From 8d5c4b20d6b3dc475ce46cb3628c3a418f14047b Mon Sep 17 00:00:00 2001 From: yiqi Date: Mon, 6 Jun 2022 13:41:16 +0800 Subject: [PATCH] Reformat and cleanup code and rename AElf.sln to AElf.All.sln --- .idea/.idea.AElf.All/.idea/encodings.xml | 4 + .idea/.idea.AElf.All/.idea/indexLayout.xml | 8 + .../.idea/projectSettingsUpdater.xml | 6 + .idea/.idea.AElf.All/.idea/vcs.xml | 6 + .idea/.idea.AElf.All/.idea/workspace.xml | 2120 +++++++ .idea/.idea.AElf.Contracts/.idea/.gitignore | 13 + .idea/.idea.AElf.Contracts/.idea/.name | 1 + .../.idea.AElf.Contracts/.idea/encodings.xml | 4 + .../.idea/indexLayout.xml | 8 + .idea/.idea.AElf.Contracts/.idea/vcs.xml | 6 + .idea/.idea.all/.idea/.name | 1 + .idea/.idea.all/.idea/encodings.xml | 4 + .idea/.idea.all/.idea/indexLayout.xml | 8 + .../.idea/projectSettingsUpdater.xml | 6 + .idea/.idea.all/.idea/vcs.xml | 6 + .idea/.idea.all/.idea/workspace.xml | 2113 ++++++ AElf.All.sln | 1256 ++++ AElf.Contracts.sln | 14 + AElf.sln | 1520 +---- AElf.sln.DotSettings | 1 + Directory.Build.props | 4 +- azure-pipelines.yml | 6 +- bench/AElf.BenchBase/AElf.BenchBase.csproj | 4 +- bench/AElf.BenchBase/Assembly.cs | 2 +- bench/AElf.BenchBase/BenchBaseAElfModule.cs | 27 +- .../PerformanceTestContract.cs | 57 +- .../PerformanceTestContractState.cs | 8 +- bench/AElf.Benchmark/AElf.Benchmark.csproj | 14 +- bench/AElf.Benchmark/BenchmarkAElfModule.cs | 77 +- bench/AElf.Benchmark/BenchmarkTestBase.cs | 246 +- bench/AElf.Benchmark/BlockAttachTests.cs | 101 +- .../BlockExecutingParallelGroupsTests.cs | 117 +- .../BlockExecutingParallelTests.cs | 113 +- bench/AElf.Benchmark/BlockExecutingTests.cs | 88 +- .../BlockchainStateMergingTests.cs | 196 +- bench/AElf.Benchmark/Fibonacci16Tests.cs | 97 +- bench/AElf.Benchmark/LoopDivAdd10MTests.cs | 103 +- bench/AElf.Benchmark/LoopExpNop1MTests.cs | 101 +- bench/AElf.Benchmark/MinerTests.cs | 100 +- bench/AElf.Benchmark/MiningTxHubBenchmark.cs | 111 +- bench/AElf.Benchmark/Program.cs | 49 +- .../TransactionVerifySignatureTests.cs | 33 +- .../TxHubHandleBestChainFoundTests.cs | 128 +- .../TxHubTransactionsReceiveTests.cs | 92 +- .../AElf.Database.Benches.csproj | 10 +- bench/AElf.Database.Benches/Assembly.cs | 2 +- .../DatabaseBenchAElfModule.cs | 11 +- bench/AElf.Database.Benches/DatabaseTests.cs | 96 +- bench/AElf.Database.Benches/DbContext.cs | 7 +- .../AElf.Database.Benches/StorageKeyTests.cs | 204 +- bench/AElf.Database.Benches/ThroughPutTest.cs | 62 +- .../AElf.Contracts.Association.csproj | 13 +- .../AElf.Contracts.Association/Association.cs | 490 +- ...ionContract_ACS1_TransactionFeeProvider.cs | 143 +- .../AssociationReferenceState.cs | 11 +- .../AssociationState.cs | 17 +- .../Association_Extensions.cs | 43 +- .../Association_Helper.cs | 289 +- .../OrganizationMemberList.cs | 27 +- .../AElf.Contracts.Configuration.csproj | 13 +- .../ConfigurationContract.cs | 61 +- ...ionContract_ACS1_TransactionFeeProvider.cs | 145 +- .../ConfigurationContract_Helper.cs | 64 +- .../ConfigurationReferenceState.cs | 11 +- .../ConfigurationState.cs | 20 +- .../AEDPoSContract.cs | 352 +- .../AEDPoSContractConstants.cs | 27 +- ...act_ACS11_CrossChainInformationProvider.cs | 139 +- ...PoSContract_ACS1_TransactionFeeProvider.cs | 150 +- ...tract_ACS4_ConsensusInformationProvider.cs | 301 +- .../AEDPoSContract_CacheFileds.cs | 21 +- ...DPoSContract_GetConsensusBlockExtraData.cs | 348 +- .../AEDPoSContract_GetConsensusCommand.cs | 153 +- .../AEDPoSContract_GetMaximumBlocksCount.cs | 225 +- .../AEDPoSContract_HelpMethods.cs | 254 +- .../AEDPoSContract_LIB.cs | 49 +- .../AEDPoSContract_MaximumMinersCount.cs | 114 +- .../AEDPoSContract_NextTerm.cs | 245 +- ...PoSContract_ProcessConsensusInformation.cs | 573 +- .../AEDPoSContract_SecretSharing.cs | 64 +- .../AEDPoSContract_SideChainDividendsPool.cs | 263 +- .../AEDPoSContract_Validation.cs | 176 +- .../AEDPoSContract_ValidationService.cs | 36 +- .../AEDPoSContract_ViewMethods.cs | 752 ++- .../AElf.Contracts.Consensus.AEDPoS.csproj | 12 +- .../AElfConsensusContractState.cs | 69 +- .../ConsensusBehaviourProviderBase.cs | 206 +- .../ConsensusCommandProvider.cs | 47 +- .../MainChainConsensusBehaviourProvider.cs | 55 +- .../MiningTimeArrangingService.cs | 32 +- .../SideChainConsensusBehaviourProvider.cs | 29 +- .../Strategies/CommandStrategyBase.cs | 110 +- .../Strategies/FirstRoundCommandStrategy.cs | 72 +- .../Strategies/ICommandStrategy.cs | 27 +- .../Strategies/NormalBlockCommandStrategy.cs | 58 +- .../TerminateRoundCommandStrategy.cs | 58 +- .../Strategies/TinyBlockCommandStrategy.cs | 97 +- .../ConsensusValidationContext.cs | 72 +- .../ContinuousBlocksValidationProvider.cs | 37 +- .../IHeaderInformationValidationProvider.cs | 9 +- .../LibInformationValidationProvider.cs | 49 +- .../MiningPermissionValidationProvider.cs | 33 +- .../NextRoundMiningOrderValidationProvider.cs | 31 +- .../RoundTerminateValidationProvider.cs | 95 +- .../TimeSlotValidationProvider.cs | 94 +- .../UpdateValueValidationProvider.cs | 89 +- .../ContractsReferences.cs | 21 +- .../AElf.Contracts.Consensus.AEDPoS/README.md | 6 +- .../Types/MinerList.cs | 86 +- .../Types/Round.cs | 433 +- .../Types/Round_ApplyNormalConsensusData.cs | 68 +- .../Types/Round_ArrangeAbnormalMiningTime.cs | 117 +- ...und_ExtractInformationToUpdateConsensus.cs | 78 +- .../Types/Round_Generation.cs | 230 +- .../Types/Round_GetLighterRound.cs | 23 +- .../Types/Round_GetLogs.cs | 109 +- .../Round_ImpliedIrreversibleBlockHeight.cs | 23 +- .../Types/Round_Recover.cs | 81 +- .../Types/Round_Simplify.cs | 127 +- .../AElf.Contracts.CrossChain.csproj | 13 +- .../CrossChainContract.cs | 540 +- .../CrossChainContractState.cs | 91 +- ...ainContract_ACS1_TransactionFeeProvider.cs | 153 +- .../CrossChainContract_Constants.cs | 25 +- .../CrossChainContract_Helper.cs | 1491 +++-- .../CrossChainContract_View.cs | 353 +- .../CrossChainReferenceState.cs | 23 +- .../AElf.Contracts.Economic.csproj | 15 +- .../EconomicContract.cs | 428 +- .../EconomicContractConstants.cs | 45 +- .../EconomicContractState.cs | 32 +- ...micContract_ACS1_TransactionFeeProvider.cs | 145 +- .../AElf.Contracts.Election.csproj | 6 +- .../ElectionContractConstants.cs | 13 +- .../ElectionContractReferenceState.cs | 29 +- .../ElectionContractState.cs | 136 +- ...ionContract_ACS1_TransactionFeeProvider.cs | 135 +- .../ElectionContract_Candidate.cs | 515 +- .../ElectionContract_Elector.cs | 1377 ++-- .../ElectionContract_Maintainence.cs | 804 ++- .../TimestampHelper.cs | 25 +- .../AElf.Contracts.Election/ViewMethods.cs | 693 +- .../AElf.Contracts.Genesis.csproj | 15 +- .../BasicContractZero.cs | 662 +- ...eroContract_ACS1_TransactionFeeProvider.cs | 115 +- .../BasicContractZeroReferenceState.cs | 11 +- .../BasicContractZeroState.cs | 42 +- .../BasicContractZero_Constants.cs | 19 +- .../BasicContractZero_Helper.cs | 375 +- .../AElf.Contracts.MultiToken.csproj | 13 +- .../TokenContractConstants.cs | 27 +- .../TokenContractReferenceState.cs | 19 +- .../TokenContractState.cs | 73 +- .../TokenContractState_ChargeFee.cs | 63 +- .../TokenContract_ACS1_MethodFeeProvider.cs | 190 +- .../TokenContract_ACS2_StatePathsProvider.cs | 133 +- .../TokenContract_Actions.cs | 999 ++- .../TokenContract_CacheFileds.cs | 9 +- ...TokenContract_Fee_Calculate_Coefficient.cs | 485 +- .../TokenContract_Fees.cs | 1112 ++-- .../TokenContract_Helper.cs | 393 +- .../TokenContract_Method_Authorization.cs | 678 +- .../TokenContract_Views.cs | 413 +- .../AElf.Contracts.NFT.csproj | 5 +- .../NFTContractConstants.cs | 19 +- .../NFTContractReferenceState.cs | 15 +- .../AElf.Contracts.NFT/NFTContractState.cs | 63 +- .../AElf.Contracts.NFT/NFTContract_ACS1.cs | 65 +- .../AElf.Contracts.NFT/NFTContract_Create.cs | 377 +- .../AElf.Contracts.NFT/NFTContract_Helpers.cs | 225 +- .../NFTContract_UseChain.cs | 820 ++- .../AElf.Contracts.NFT/NFTContract_View.cs | 169 +- .../AElf.Contracts.NFTMarket.csproj | 2 +- .../NFTMarketContract.cs | 88 +- .../NFTMarketContractConstants.cs | 17 +- .../NFTMarketContractReferenceState.cs | 11 +- .../NFTMarketContractState.cs | 75 +- .../NFTMarketContract_ACS1.cs | 41 +- .../NFTMarketContract_Buyers.cs | 1203 ++-- .../NFTMarketContract_Creators.cs | 411 +- .../NFTMarketContract_Helpers.cs | 740 +-- .../NFTMarketContract_Sellers.cs | 955 ++- .../NFTMarketContract_Views.cs | 234 +- .../AElf.Contracts.NFTMinter.csproj | 2 +- .../NFTMinterConrtract_Creator.cs | 341 +- .../NFTMinterContract.cs | 25 +- .../NFTMinterContractConstants.cs | 11 +- .../NFTMinterContractReferenceState.cs | 15 +- .../NFTMinterContractState.cs | 45 +- .../NFTMinterContract_Helpers.cs | 44 +- .../NFTMinterContract_User.cs | 214 +- .../NFTMinterContract_Views.cs | 31 +- .../AElf.Contracts.Parliament.csproj | 13 +- .../AElf.Contracts.Parliament/Parliament.cs | 531 +- ...entContract_ACS1_TransactionFeeProvider.cs | 141 +- .../ParliamentState.cs | 33 +- .../Parliament_Constants.cs | 17 +- .../Parliament_Helper.cs | 531 +- .../AElf.Contracts.Profit.csproj | 8 +- .../ContractsReferences.cs | 11 +- .../AElf.Contracts.Profit/ProfitContract.cs | 1285 ++-- .../ProfitContractConstants.cs | 17 +- .../ProfitContractState.cs | 23 +- ...fitContract_ACS1_TransactionFeeProvider.cs | 178 +- contract/AElf.Contracts.Profit/README.md | 18 +- contract/AElf.Contracts.Profit/ViewMethods.cs | 237 +- .../AElf.Contracts.Referendum.csproj | 13 +- .../ProposerWhiteListExtensions.cs | 27 +- .../AElf.Contracts.Referendum/Referendum.cs | 428 +- ...dumContract_ACS1_TransactionFeeProvider.cs | 143 +- .../ReferendumState.cs | 26 +- .../Referendum_Helper.cs | 365 +- .../AElf.Contracts.TokenConverter.csproj | 11 +- .../BancorHelper.cs | 283 +- .../InvalidValueException.cs | 9 +- .../TokenConvert_Views.cs | 173 +- .../TokenConverterContract.cs | 655 +- .../TokenConverterContractState.cs | 30 +- ...terContract_ACS1_TransactionFeeProvider.cs | 145 +- .../AElf.Contracts.TokenHolder.csproj | 7 +- .../ContractsReferences.cs | 13 +- .../TokenHolderContract.cs | 480 +- .../TokenHolderContractState.cs | 30 +- ...derContract_ACS1_TransactionFeeProvider.cs | 145 +- .../AElf.Contracts.Treasury.csproj | 13 +- .../ContractsReferences.cs | 21 +- .../TreasuryContract.cs | 1579 +++-- .../TreasuryContractConstants.cs | 13 +- .../TreasuryContractState.cs | 79 +- ...uryContract_ACS1_TransactionFeeProvider.cs | 144 +- .../AElf.Contracts.Vote.csproj | 6 +- .../ContractsReferences.cs | 11 +- contract/AElf.Contracts.Vote/README.md | 32 +- contract/AElf.Contracts.Vote/ViewMethods.cs | 95 +- contract/AElf.Contracts.Vote/VoteContract.cs | 705 +-- .../VoteContractConstants.cs | 11 +- .../AElf.Contracts.Vote/VoteContractState.cs | 59 +- ...oteContract_ACS1_TransactionFeeProvider.cs | 186 +- .../AElf.Contracts.Vote/VoteExtensions.cs | 29 +- contract/Directory.Build.props | 4 +- .../AElf.Blockchains.BasicBaseChain.csproj | 32 +- .../BasicBaseChainAElfModule.cs | 182 +- .../GenesisSmartContractDtoProviderBase.cs | 76 +- .../AElf.Blockchains.MainChain.csproj | 6 +- ...ChainContractInitializationDataProvider.cs | 17 +- .../MainChainAElfModule.cs | 51 +- ...MainChainContractDeploymentListProvider.cs | 41 +- ...ainChainGenesisSmartContractDtoProvider.cs | 37 +- ...amentContractInitializationDataProvider.cs | 14 +- ...TokenContractInitializationDataProvider.cs | 11 +- ...EDPoSContractInitializationDataProvider.cs | 57 +- .../AElf.Blockchains.SideChain.csproj | 6 +- ...ChainContractInitializationDataProvider.cs | 37 +- ...amentContractInitializationDataProvider.cs | 35 +- .../Protobuf/MinerListExtension.cs | 70 +- .../SideChainAElfModule.cs | 30 +- ...SideChainContractDeploymentListProvider.cs | 31 +- ...ideChainGenesisSmartContractDtoProvider.cs | 70 +- .../SideChainInitializationDataProvider.cs | 70 +- ...TokenContractInitializationDataProvider.cs | 59 +- .../AElf.CSharp.CodeOps.csproj | 8 +- .../CSharpCodeOpsAElfModule.cs | 33 +- .../CSharpCodeOpsOptions.cs | 9 +- .../CSharpContractAuditor.cs | 128 +- .../CSharpContractPatcher.cs | 45 +- src/AElf.CSharp.CodeOps/Constants.cs | 83 +- .../DescriptorOnlyServiceBinder.cs | 37 +- src/AElf.CSharp.CodeOps/Exceptions.cs | 59 +- .../ExecutionObserverProxy.cs | 37 +- src/AElf.CSharp.CodeOps/Extensions.cs | 254 +- .../IStateWrittenInstructionInjector.cs | 169 +- src/AElf.CSharp.CodeOps/Patchers/IPatcher.cs | 17 +- .../Module/ExecutionObserverInjector.cs | 303 +- .../Patchers/Module/MethodCallReplacer.cs | 170 +- .../Module/ResetFieldsMethodInjector.cs | 251 +- .../StateWrittenSizeLimitMethodInjector.cs | 84 +- .../Policies/DefaultPolicy.cs | 45 +- .../Validators/Assembly/AcsValidator.cs | 107 +- .../Validators/IValidator.cs | 17 +- .../Validators/Method/ArrayValidator.cs | 348 +- .../Method/DescriptorAccessValidator.cs | 65 +- .../Validators/Method/FloatOpsValidator.cs | 89 +- .../Validators/Method/GetHashCodeValidator.cs | 198 +- .../Method/MultiDimArrayValidator.cs | 59 +- .../Method/UncheckedMathValidator.cs | 71 +- .../Module/ContractStructureValidator.cs | 436 +- .../Module/InstructionInjectionValidator.cs | 100 +- .../Module/ObserverProxyValidator.cs | 246 +- .../Validators/Module/ResetFieldsValidator.cs | 284 +- .../Validators/ValidationResult.cs | 79 +- .../Whitelist/IWhitelistProvider.cs | 7 +- .../Whitelist/IWhitelistValidator.cs | 392 +- .../Validators/Whitelist/MemberRule.cs | 19 +- .../Validators/Whitelist/NamespaceRule.cs | 45 +- .../Validators/Whitelist/Permission.cs | 11 +- .../Validators/Whitelist/Trust.cs | 11 +- .../Validators/Whitelist/TypeRule.cs | 41 +- .../Validators/Whitelist/Whitelist.cs | 79 +- src/AElf.CSharp.Core/AElf.CSharp.Core.csproj | 14 +- src/AElf.CSharp.Core/ContractStubBase.cs | 11 +- .../Extension/EventExtensions.cs | 49 +- .../Extension/TimestampExtensions.cs | 149 +- src/AElf.CSharp.Core/IEvent.cs | 11 +- src/AElf.CSharp.Core/IMethodStubFactory.cs | 107 +- src/AElf.CSharp.Core/Marshaller.cs | 83 +- src/AElf.CSharp.Core/Method.cs | 226 +- src/AElf.CSharp.Core/SafeMath.cs | 416 +- src/AElf.CSharp.Core/ServerMethods.cs | 21 +- .../ServerServiceDefinition.cs | 152 +- src/AElf.CSharp.Core/ServiceBinderBase.cs | 49 +- src/AElf.CSharp.Core/Utils/EncodingHelper.cs | 23 +- src/AElf.CSharp.Core/Utils/Preconditions.cs | 47 +- src/AElf.Cluster/AElf.Cluster.csproj | 8 +- .../BlockchainNodeHostingService.cs | 47 +- src/AElf.Cluster/Application/Startup.cs | 39 +- src/AElf.Cluster/ClusterAElfModule.cs | 11 +- .../AElf.ContractDeployer.csproj | 18 +- .../ContractDeployerModule.cs | 10 +- .../ContractsDeployer.cs | 69 +- .../NoContractDllFoundInManifestException.cs | 7 +- src/AElf.ContractDeployer/Program.cs | 118 +- .../AElf.ContractTestBase.csproj | 34 +- .../ContractTestKit/ChainInitializationDto.cs | 8 +- .../ChainInitializationOptions.cs | 19 +- .../ContractTestKit/ContractTestBase.cs | 226 +- .../ContractTestKit/ContractTestConstants.cs | 9 +- .../ContractTestKit/ContractTestKit.cs | 128 +- .../ContractTestKit/ContractTestKitFactory.cs | 21 +- .../ContractTestKit/ContractTestModule.cs | 207 +- .../ContractTestKit/ContractTestService.cs | 121 +- .../ContractTestKit/IBlockTimeProvider.cs | 50 +- .../ContractTestKit/IContractTesterFactory.cs | 39 +- .../ContractTestKit/IRefBlockInfoProvider.cs | 53 +- .../IResetBlockTimeProvider.cs | 21 +- .../ITestTransactionExecutor.cs | 15 +- .../ContractTestKit/MethodStubFactory.cs | 183 +- .../ContractTestKit/SampleAccount.cs | 313 +- .../ContractTestKit/SampleAddress.cs | 43 +- .../SmartContractTestConstants.cs | 15 +- .../TestTransactionExecutor.cs | 171 +- .../UnitTestContractZeroCodeProvider.cs | 19 +- .../UnitTestSmartContractAddressService.cs | 60 +- .../GenesisSmartContractDtoProvider.cs | 71 +- .../IContractCodeProvider.cs | 17 +- ...EDPoSContractInitializationDataProvider.cs | 38 +- ...MainChainContractDeploymentListProvider.cs | 41 +- .../MainChainContractTestBase.cs | 12 +- .../MainChainContractTestModule.cs | 54 +- ...ChainContractInitializationDataProvider.cs | 16 +- ...amentContractInitializationDataProvider.cs | 12 +- ...TokenContractInitializationDataProvider.cs | 12 +- ...EDPoSContractInitializationDataProvider.cs | 55 +- ...SideChainContractDeploymentListProvider.cs | 31 +- .../SideChainContractTestBase.cs | 12 +- .../SideChainContractTestModule.cs | 61 +- ...ChainContractInitializationDataProvider.cs | 37 +- .../SideChainInitializationDataProvider.cs | 79 +- ...amentContractInitializationDataProvider.cs | 34 +- ...TokenContractInitializationDataProvider.cs | 59 +- .../AEDPoSExtensionConstants.cs | 29 +- .../AEDPoSExtensionTestBase.cs | 87 +- ...Elf.ContractTestKit.AEDPoSExtension.csproj | 14 +- .../BlockMiningException.cs | 17 +- .../BlockMiningService.cs | 751 +-- .../ConsensusFactAttribute.cs | 15 +- .../ConsensusFactDiscoverer.cs | 37 +- .../ConsensusTestCase.cs | 57 +- .../ContractTestAEDPoSExtensionModule.cs | 108 +- .../IBlockMiningService.cs | 21 +- .../IChainTypeProvider.cs | 17 +- .../ITestDataProvider.cs | 11 +- .../ITransactionListProvider.cs | 13 +- .../ITransactionTraceProvider.cs | 17 +- .../InitializationFailedException.cs | 15 +- .../MissionedECKeyPairs.cs | 47 +- ...ovideTransactionListPostExecutionPlugin.cs | 65 +- .../TestDataProvider.cs | 101 +- .../TransactionExecutedEventHandler.cs | 27 +- .../TransactionListProvider.cs | 37 +- .../TransactionTraceProvider.cs | 23 +- ...nitTestPlainTransactionExecutingService.cs | 42 +- .../AElf.ContractTestKit.csproj | 30 +- src/AElf.ContractTestKit/ContractTestBase.cs | 177 +- .../ContractTestModule.cs | 228 +- .../AllCalculateFeeCoefficientsExtensions.cs | 21 +- .../CalculateFeeCoefficientsExtensions.cs | 112 +- .../GenesisContractDtoExtensions.cs | 21 +- .../IBlockTimeProvider.cs | 50 +- .../IContractTesterFactory.cs | 39 +- .../IRefBlockInfoProvider.cs | 53 +- .../IResetBlockTimeProvider.cs | 21 +- .../ITestTransactionExecutor.cs | 15 +- src/AElf.ContractTestKit/MethodStubFactory.cs | 183 +- .../MockCalculateFunctionProvider.cs | 131 +- src/AElf.ContractTestKit/SampleAccount.cs | 313 +- src/AElf.ContractTestKit/SampleAddress.cs | 47 +- .../SmartContractTestConstants.cs | 15 +- .../TestTransactionExecutor.cs | 169 +- .../UnitTestContractZeroCodeProvider.cs | 19 +- .../UnitTestSmartContractAddressService.cs | 60 +- src/AElf.Core/AElf.Core.csproj | 10 +- .../AElfDefaultConventionalRegistrar.cs | 44 +- src/AElf.Core/CoreAElfModule.cs | 103 +- src/AElf.Core/ITaskQueue.cs | 220 +- src/AElf.Core/LoggerExtensions.cs | 12 +- src/AElf.Core/Modularity/AElfModule.cs | 19 +- .../AElf.CrossChain.Core.csproj | 5 +- .../Application/CrossChainRequestService.cs | 101 +- .../Application/CrossChainResponseService.cs | 221 +- .../Application/ICrossChainRequestService.cs | 11 +- .../Application/ICrossChainResponseService.cs | 13 +- .../Application/IBlockCacheEntityConsumer.cs | 46 +- .../Application/IBlockCacheEntityProducer.cs | 55 +- .../ICrossChainCacheEntityService.cs | 107 +- .../Cache/Infrastructure/IChainCacheEntity.cs | 127 +- .../ICrossChainCacheEntityProvider.cs | 52 +- .../Application/CrossChainClientService.cs | 88 +- .../Application/ICrossChainClientService.cs | 19 +- .../ICrossChainCommunicationPlugin.cs | 14 +- .../CrossChainClientCreationContext.cs | 17 +- .../Infrastructure/ICrossChainClient.cs | 23 +- .../ICrossChainClientProvider.cs | 19 +- .../CrossChainConfigOptions.cs | 11 +- .../CrossChainConstants.cs | 15 +- ...rossChainContractInitializationProvider.cs | 50 +- .../CrossChainCoreModule.cs | 22 +- ...ssChainSmartContractAddressNameProvider.cs | 15 +- .../Exception/CrossChainRequestException.cs | 19 +- .../CrossChainDataTypeExtensions.cs | 70 +- .../Extensions/LocalLibExtensions.cs | 47 +- .../ICrossChainBlockEntity.cs | 13 +- ...ChainContractInitializationDataProvider.cs | 29 +- ...inIndexingDataProposedLogEventProcessor.cs | 128 +- .../CrossChainIndexingDataService.cs | 633 +- ...CrossChainIndexingDataValidationService.cs | 264 +- .../ICrossChainIndexingDataService.cs | 29 +- ...CrossChainIndexingDataValidationService.cs | 11 +- .../IIrreversibleBlockStateProvider.cs | 13 +- ...nsactionInputForBlockMiningDataProvider.cs | 29 +- .../IrreversibleBlockStateProvider.cs | 57 +- ...nsactionInputForBlockMiningDataProvider.cs | 44 +- .../Protobuf/ProtobufTypes.cs | 15 +- .../AElf.CrossChain.Grpc.csproj | 9 +- .../Client/GrpcCrossChainClient.cs | 310 +- .../GrpcCrossChainClientCreationContext.cs | 7 +- .../Client/GrpcCrossChainClientNodePlugin.cs | 67 +- .../Client/GrpcCrossChainClientProvider.cs | 134 +- .../Client/GrpcCrossChainRequestException.cs | 16 +- .../Client/IGrpcCrossChainPlugin.cs | 9 +- .../GrpcCrossChainAElfModule.cs | 25 +- .../GrpcCrossChainConfigOption.cs | 25 +- .../GrpcCrossChainConnectionEventHandler.cs | 38 +- .../GrpcCrossChainConstants.cs | 9 +- .../Helper/GrpcUriHelper.cs | 53 +- .../NewChainConnectionEvent.cs | 13 +- .../Server/GrpcBasicServerBase.cs | 48 +- .../Server/GrpcCrossChainServer.cs | 89 +- .../Server/GrpcCrossChainServerNodePlugin.cs | 46 +- .../Server/GrpcParentChainServerBase.cs | 96 +- .../Server/GrpcSideChainServerBase.cs | 54 +- .../Server/IGrpcCrossChainServer.cs | 11 +- src/AElf.CrossChain/AElf.CrossChain.csproj | 2 +- .../CrossChainBlockExtraDataProvider.cs | 55 +- .../Application/CrossChainService.cs | 78 +- .../CrossChainTransactionGenerator.cs | 123 +- .../CrossChainValidationProvider.cs | 167 +- .../Application/ICrossChainService.cs | 11 +- .../ISideChainInitializationDataProvider.cs | 11 +- src/AElf.CrossChain/CrossChainAElfModule.cs | 25 +- .../CrossChainModuleEventHandler.cs | 34 +- src/AElf.CrossChain/CrossChainPlugin.cs | 68 +- .../AElf.Cryptography.csproj | 12 +- src/AElf.Cryptography/CryptoHelper.cs | 20 +- src/AElf.Cryptography/ECDSA/ECKeyPair.cs | 19 +- src/AElf.Cryptography/ECDSA/ECParameters.cs | 11 +- .../Exceptions/EcdhOperationException.cs | 9 +- .../Exceptions/InvalidKeyPairException.cs | 9 +- .../Exceptions/InvalidPasswordException.cs | 9 +- .../Exceptions/InvalidPrivateKeyException.cs | 9 +- .../Exceptions/KeyStoreNotFoundException.cs | 9 +- .../Exceptions/PublicKeyOperationException.cs | 9 +- .../Exceptions/SignatureOperationException.cs | 9 +- .../IAElfAsymmetricCipherKeyPair.cs | 11 +- .../SecretSharing/SecretSharingConsts.cs | 11 +- .../SecretSharing/SecretSharingExtensions.cs | 65 +- .../SecretSharing/SecretSharingHelper.cs | 156 +- src/AElf.Database/AElf.Database.csproj | 6 +- src/AElf.Database/DatabaseAElfModule.cs | 17 +- .../DatabaseServiceCollectionExtensions.cs | 37 +- src/AElf.Database/IKeyValueCollection.cs | 110 +- src/AElf.Database/IKeyValueDatabase.cs | 25 +- src/AElf.Database/InMemoryDatabase.cs | 126 +- src/AElf.Database/KeyValueDatabaseOptions.cs | 11 +- src/AElf.Database/KeyValueDbContext.cs | 37 +- .../KeyValueDbContextCreationOptions.cs | 27 +- ...ValueDbContextCreationOptionsExtensions.cs | 49 +- src/AElf.Database/RedisDatabase.cs | 122 +- .../RedisProtocol/PooledRedisLite.cs | 271 +- src/AElf.Database/RedisProtocol/RedisLite.cs | 1523 +++-- .../RedisProtocol/RedisLiteHelper.cs | 905 ++- src/AElf.Database/SsdbDatabase.cs | 16 +- .../AElf.EconomicSystem.csproj | 8 +- .../EconomicContractInitializationProvider.cs | 85 +- ...conomicSmartContractAddressNameProvider.cs | 15 +- .../EconomicSystemAElfModule.cs | 7 +- .../ProfitContractInitializationProvider.cs | 20 +- .../ProfitSmartContractAddressNameProvider.cs | 15 +- ...ConverterContractInitializationProvider.cs | 18 +- ...nverterSmartContractAddressNameProvider.cs | 15 +- ...kenHolderContractInitializationProvider.cs | 17 +- ...nHolderSmartContractAddressNameProvider.cs | 15 +- .../TreasuryContractInitializationProvider.cs | 36 +- ...reasurySmartContractAddressNameProvider.cs | 15 +- .../AElf.GovernmentSystem.csproj | 12 +- ...sociationContractInitializationProvider.cs | 18 +- ...ciationSmartContractAddressNameProvider.cs | 15 +- .../ElectionContractInitializationProvider.cs | 56 +- ...lectionSmartContractAddressNameProvider.cs | 15 +- .../GovernmentSystemAElfModule.cs | 7 +- ...amentContractInitializationDataProvider.cs | 27 +- ...arliamentContractInitializationProvider.cs | 48 +- ...eferendumContractInitializationProvider.cs | 17 +- ...erendumSmartContractAddressNameProvider.cs | 15 +- .../VoteContractInitializationProvider.cs | 18 +- .../VoteSmartContractAddressNameProvider.cs | 15 +- .../AElf.Kernel.ChainController.csproj | 20 +- .../Application/ChainCreationService.cs | 92 +- .../Application/IChainCreationService.cs | 15 +- .../ChainControllerAElfModule.cs | 11 +- .../AElf.Kernel.CodeCheck.csproj | 6 +- .../Application/CodeCheckService.cs | 82 +- .../CodeCheckValidationProvider.cs | 106 +- .../Application/ICheckedCodeHashProvider.cs | 96 +- .../Application/ICodeCheckService.cs | 11 +- .../CodeCheckAElfModule.cs | 19 +- src/AElf.Kernel.CodeCheck/CodeCheckOptions.cs | 9 +- .../CodeCheckRequiredLogEventProcessor.cs | 126 +- .../ContractCodeHashMap.cs | 49 +- .../ContractDeployedLogEventProcessor.cs | 76 +- .../Exception/InvalidCodeException.cs | 15 +- src/AElf.Kernel.CodeCheck/GlobalUsings.cs | 6 + .../Infrastructure/IContractAuditor.cs | 17 +- .../IContractAuditorContainer.cs | 33 +- .../Infrastructure/IRequiredAcsProvider.cs | 11 +- .../Infrastructure/RequiredAcsProvider.cs | 54 +- .../NewIrreversibleBlockFoundEventHandler.cs | 33 +- .../AElf.Kernel.Configuration.csproj | 6 +- .../ConfigurationAElfModule.cs | 13 +- ...igurationContractInitializationProvider.cs | 18 +- .../ConfigurationSetLogEventProcessor.cs | 87 +- ...urationSmartContractAddressNameProvider.cs | 15 +- .../IConfigurationProcessor.cs | 11 +- .../IConfigurationService.cs | 77 +- .../AEDPoSAElfModule.cs | 99 +- ...EDPoSContractInitializationDataProvider.cs | 37 +- .../AEDPoSContractInitializationProvider.cs | 73 +- .../AElf.Kernel.Consensus.AEDPoS.csproj | 6 +- .../Application/AEDPoSBlockTimeProvider.cs | 45 +- ...oSBroadcastPrivilegedPubkeyListProvider.cs | 91 +- .../Application/AEDPoSExtraDataExtractor.cs | 44 +- .../Application/AEDPoSInformationProvider.cs | 43 +- .../AEDPoSTriggerInformationProvider.cs | 181 +- .../ConsensusValidationFailedEventHandler.cs | 47 +- .../Application/IAEDPoSInformationProvider.cs | 11 +- .../Application/IInValueCache.cs | 47 +- .../Application/ISecretSharingService.cs | 15 +- ...IrreversibleBlockFoundLogEventProcessor.cs | 129 +- ...lockHeightUnacceptableLogEventProcessor.cs | 93 +- ...cretSharingInformationLogEventProcessor.cs | 64 +- .../Application/SecretSharingService.cs | 313 +- .../AssemblyInfo.cs | 2 +- .../ConsensusOptions.cs | 20 +- .../Extensions/ByteStringExtensions.cs | 15 +- .../Extensions/BytesValueExtensions.cs | 15 +- .../Extensions/MinerListExtensions.cs | 70 +- ...EDPoSContractInitializationDataProvider.cs | 35 +- .../AElf.Kernel.Consensus.Core.csproj | 4 +- .../ConsensusBestChainFoundEventHandler.cs | 45 +- .../Application/ConsensusExtraDataProvider.cs | 57 +- .../Application/ConsensusService.cs | 374 +- .../ConsensusTransactionGenerator.cs | 27 +- .../ConsensusValidationProvider.cs | 179 +- .../Application/IBlockTimeProvider.cs | 31 +- .../IBroadcastPrivilegedPubkeyListProvider.cs | 9 +- .../IConsensusExtraDataExtractor.cs | 9 +- .../IConsensusExtraDataProvider.cs | 7 +- .../IConsensusReaderContextService.cs | 59 +- .../Application/IConsensusScheduler.cs | 27 +- .../Application/IConsensusService.cs | 75 +- .../ITriggerInformationProvider.cs | 15 +- .../ConsensusConstants.cs | 11 +- .../ConsensusRequestMiningEventData.cs | 36 +- ...nsensusSmartContractAddressNameProvider.cs | 15 +- .../ConsensusValidationFailedEventData.cs | 11 +- .../CoreConsensusAElfModule.cs | 17 +- ...Consensus.Scheduler.FluentScheduler.csproj | 6 +- .../FluentSchedulerAElfModule.cs | 11 +- .../FluentSchedulerScheduler.cs | 59 +- ...lf.Kernel.Consensus.Scheduler.RxNet.csproj | 6 +- .../RxNetScheduler.cs | 78 +- .../RxNetSchedulerAElfModule.cs | 11 +- src/AElf.Kernel.Core/AElf.Kernel.Core.csproj | 14 +- .../Account/Application/IAccountService.cs | 88 +- .../AElfAsymmetricCipherKeyPairProvider.cs | 24 +- .../IAElfAsymmetricCipherKeyPairProvider.cs | 11 +- .../Application/BlockExtraDataService.cs | 54 +- .../Application/BlockGenerationService.cs | 56 +- .../Application/ChainBlockLinkService.cs | 73 +- .../Application/IBlockExtraDataProvider.cs | 22 +- .../Application/IBlockExtraDataService.cs | 26 +- .../Application/IBlockGenerationService.cs | 23 +- .../Application/IBlockValidationProvider.cs | 259 +- .../Application/IBlockValidationService.cs | 92 +- .../Application/IBlockchainService.cs | 662 +- .../ITransactionBlockIndexService.cs | 301 +- .../Application/ITransactionResultService.cs | 113 +- .../Blockchain/BlockExecutedSet.cs | 24 +- .../Blockchain/Domain/IBlockManager.cs | 131 +- .../Blockchain/Domain/IChainManager.cs | 849 ++- .../Domain/ITransactionBlockIndexManager.cs | 72 +- .../Blockchain/Domain/ITransactionManager.cs | 23 +- .../Domain/ITransactionResultManager.cs | 98 +- .../Blockchain/Domain/TransactionManager.cs | 99 +- .../Events/BestChainFoundEventData.cs | 11 +- .../Blockchain/Events/BlockAcceptedEvent.cs | 11 +- .../Events/NewIrreversibleBlockFoundEvent.cs | 15 +- .../ChainBlockLinkCacheProvider.cs | 61 +- .../Infrastructure/IBlockchainStore.cs | 22 +- .../IStaticChainInformationProvider.cs | 49 +- .../ITransactionBlockIndexProvider.cs | 13 +- .../TransactionBlockIndexProvider.cs | 72 +- src/AElf.Kernel.Core/ChainOptions.cs | 37 +- src/AElf.Kernel.Core/CoreKernelAElfModule.cs | 100 +- ...TransactionValidationStatusChangedEvent.cs | 13 +- .../Extensions/BlockBodyExtensions.cs | 46 +- .../Extensions/BlockExtensions.cs | 48 +- .../Extensions/BlockHeaderExtensions.cs | 26 +- .../Extensions/BlockStateSetExtension.cs | 50 +- .../Extensions/TransactionExtensions.cs | 46 +- .../Extensions/TransactionResultExtensions.cs | 17 +- .../Extensions/TransactionTraceExtensions.cs | 105 +- src/AElf.Kernel.Core/GlobalUsings.cs | 7 + .../BlockChainKeyValueDbContext.cs | 20 +- .../Infrastructure/IKeyValueStore.cs | 25 +- .../Infrastructure/KeyValueStoreBase.cs | 163 +- .../Infrastructure/StorageKeyExtensions.cs | 60 +- .../ISystemTransactionExtraDataProvider.cs | 55 +- .../ISystemTransactionGenerationService.cs | 11 +- .../ISystemTransactionGenerator.cs | 11 +- .../SystemTransactionGenerationService.cs | 42 +- .../SystemTransactionValidationProvider.cs | 42 +- .../BlockExecutedDataBaseProvider.cs | 110 +- ...BlockchainExecutedDataServiceExtensions.cs | 57 +- ...BlockchainExecutedDataServiceExtensions.cs | 23 +- ...ockExecutedDataChangeHeightEventHandler.cs | 27 +- .../Application/IBlockchainStateService.cs | 288 +- .../Domain/IBlockchainStateManager.cs | 436 +- ...nBlockExecutedDataChangeHeightEventData.cs | 9 +- .../BlockchainExecutedDataCacheProvider.cs | 91 +- .../Infrastructure/IStateStore.cs | 10 +- .../Infrastructure/StateStore.cs | 161 +- .../Events/TransactionExecutedEventData.cs | 9 +- ...ockExecutedDataChangeHeightEventHandler.cs | 16 +- .../ITransactionPackingOptionProvider.cs | 53 +- .../ITransactionValidationProvider.cs | 12 +- .../AElf.Kernel.FeatureManager.csproj | 2 +- .../FeatureActiveService.cs | 8 +- .../FeatureManagerAElfModule.cs | 5 +- .../AElf.Kernel.FeeCalculation.csproj | 14 +- .../CalculateFunctionExecutedDataService.cs | 62 +- ...ockExecutedDataChangeHeightEventHandler.cs | 17 +- .../Application/IPrimaryTokenFeeService.cs | 9 +- .../Application/IResourceTokenFeeService.cs | 11 +- .../Application/PrimaryTokenFeeService.cs | 25 +- .../Application/ResourceTokenFeeService.cs | 37 +- ...atorCoefficientUpdatedLogEventProcessor.cs | 81 +- .../AllCalculateFeeCoefficientsExtensions.cs | 15 +- .../CalculateFeeCoefficientsExtensions.cs | 106 +- .../Extensions/TransactionResultExtensions.cs | 45 +- .../FeeCalculationModule.cs | 39 +- .../Infrastructure/CalculateFunction.cs | 94 +- .../ICalculateFunctionProvider.cs | 66 +- .../Infrastructure/IFeeProvider.cs | 30 +- .../Infrastructure/ReadFeeProvider.cs | 22 +- .../Infrastructure/StorageFeeProvider.cs | 22 +- .../Infrastructure/TokenFeeProviderBase.cs | 47 +- .../Infrastructure/TrafficFeeProvider.cs | 22 +- .../Infrastructure/TxFeeProvider.cs | 20 +- .../Infrastructure/WriteFeeProvider.cs | 22 +- src/AElf.Kernel.Node/AElf.Kernel.Node.csproj | 8 +- .../IBlockchainNodeContextService.cs | 115 +- .../Domain/BlockchainNodeContext.cs | 9 +- .../Events/InitialSyncFinishedEvent.cs | 7 +- .../Infrastructure/INodePlugin.cs | 11 +- src/AElf.Kernel.Node/NodeAElfModule.cs | 11 +- .../AElf.Kernel.Proposal.csproj | 4 +- .../Application/IProposalService.cs | 13 +- .../ProposalApprovalTransactionGenerator.cs | 98 +- .../Application/ProposalService.cs | 115 +- .../Infrastructure/IProposalProvider.cs | 17 +- .../Infrastructure/ProposalProvider.cs | 43 +- .../NewIrreversibleBlockFoundEventHandler.cs | 25 +- ...liamentSmartContractAddressNameProvider.cs | 15 +- .../ProposalAElfModule.cs | 14 +- ...act.ExecutionPluginForCallThreshold.csproj | 6 +- .../CheckThresholdExecutionPlugin.cs | 142 +- .../ExecutionPluginForCallThresholdModule.cs | 11 +- ...ontract.ExecutionPluginForMethodFee.csproj | 6 +- .../ClaimFeeTransactionGenerator.cs | 98 +- .../ClaimTransactionFeesValidationProvider.cs | 145 +- ...ockExecutedDataChangeHeightEventHandler.cs | 17 +- ...nsactionFeesMapChangeHeightEventHandler.cs | 17 +- .../ExecutionPluginForMethodFeeModule.cs | 28 +- .../FeeChargePreExecutionPlugin.cs | 167 +- .../ITotalTransactionFeesMapProvider.cs | 55 +- ...lListToPayTxFeeUpdatedLogEventProcessor.cs | 94 +- .../TransactionFeeChargedLogEventProcessor.cs | 106 +- .../TransactionSizeFeeSymbolsProvider.cs | 56 +- ...tract.ExecutionPluginForResourceFee.csproj | 8 +- ...ockExecutedDataChangeHeightEventHandler.cs | 17 +- .../DonateResourceTokenValidationProvider.cs | 148 +- .../DonateResourceTransactionGenerator.cs | 106 +- .../ExecutionPluginForResourceFeeModule.cs | 21 +- .../ITotalResourceTokensMapsProvider.cs | 69 +- .../ResourceConsumptionPostExecutionPlugin.cs | 127 +- .../ResourceConsumptionPreExecutionPlugin.cs | 110 +- .../ResourceTokenChargedLogEventProcessor.cs | 134 +- .../AElf.Kernel.SmartContract.Parallel.csproj | 4 +- .../BlockParallelExecutingService.cs | 38 +- ...ockExecutedDataChangeHeightEventHandler.cs | 17 +- ...ctionsFoundInParallelGroupsEventHandler.cs | 72 +- .../IParallelTransactionExecutingService.cs | 8 +- ...ocalParallelTransactionExecutingService.cs | 415 +- ...arallelExecutionInterestedEventsHandler.cs | 60 +- ...lictingTransactionIdentificationService.cs | 118 +- ...gTransactionsFoundInParallelGroupsEvent.cs | 30 +- .../Domain/ExecutiveExtensions.cs | 78 +- ...lictingTransactionIdentificationService.cs | 14 +- .../Domain/IResourceExtractionService.cs | 24 +- .../Domain/ITransactionGrouper.cs | 25 +- .../Domain/NonparallelContractCodeProvider.cs | 65 +- .../Domain/ResourceExtractionService.cs | 402 +- .../Domain/TransactionGrouper.cs | 246 +- .../Domain/TransactionWithResourceInfo.cs | 11 +- .../TransactionWithResourceInfoExtensions.cs | 25 +- .../Domain/UnionFindNode.cs | 132 +- .../ParallelExecutionModule.cs | 19 +- .../AElf.Kernel.SmartContract.Shared.csproj | 4 +- .../ContextVariableDictionary.cs | 48 +- .../IExecutionObserver.cs | 17 +- .../ISmartContractBridgeContext.cs | 252 +- .../IStateProvider.cs | 9 +- .../AElf.Kernel.SmartContract.csproj | 10 +- .../ChainContextWithTieredStateCache.cs | 41 +- ...ockExecutedDataChangeHeightEventHandler.cs | 51 +- .../Application/ContractReaderContext.cs | 19 +- .../Application/ContractReaderFactory.cs | 34 +- .../HostSmartContractBridgeContextService.cs | 28 +- .../Application/IChainContext`.cs | 9 +- .../IContractDeploymentListProvider.cs | 9 +- .../IContractInitializationProvider.cs | 25 +- .../Application/IContractReaderFactory.cs | 11 +- .../IExecutionObserverThresholdProvider.cs | 102 +- .../IHostSmartContractBridgeContextService.cs | 9 +- .../Application/ILogEventProcessingService.cs | 9 +- .../Application/ILogEventProcessor.cs | 75 +- .../Application/IPostExecutionPlugin.cs | 12 +- .../Application/IPreExecutionPlugin.cs | 13 +- .../ISmartContractAddressProvider.cs | 58 +- .../ISmartContractAddressService.cs | 212 +- .../ISmartContractBridgeService.cs | 197 +- .../ISmartContractExecutiveService.cs | 21 +- .../Application/ISmartContractService.cs | 21 +- .../Application/IStateSizeLimitProvider.cs | 66 +- .../Application/ITransactionContextFactory.cs | 105 +- .../ITransactionExecutingService.cs | 18 +- .../ITransactionReadOnlyExecutionService.cs | 19 +- .../Application/LogEventProcessingService.cs | 123 +- .../PlainTransactionExecutingService.cs | 725 +-- .../Application/ReadOnlyMethodStubFactory.cs | 102 +- .../SmartContractExecutingException.cs | 47 +- .../SmartContractExecutionPluginBase.cs | 23 +- .../SmartContractExecutiveProvider.cs | 79 +- .../SmartContractExecutiveService.cs | 305 +- .../SmartContractFindRegistrationException.cs | 33 +- .../SmartContractRegistrationProvider.cs | 65 +- .../Application/SmartContractService.cs | 49 +- .../StateCacheFromPartialBlockStateSet.cs | 48 +- .../Application/TransactionExecutingDto.cs | 13 +- .../TransactionReadOnlyExecutionService.cs | 174 +- ...ctionReadOnlyExecutionServiceExtensions.cs | 34 +- src/AElf.Kernel.SmartContract/AssemblyInfo.cs | 2 +- .../CachedStateProvider.cs | 68 +- .../ContractOptions.cs | 11 +- .../Domain/BlockStateSetExtensions.cs | 19 +- .../Domain/ExecutionReturnSetCollection.cs | 75 +- .../Domain/TieredStateCache.cs | 108 +- .../Dto/ContractDto.cs | 19 +- .../Dto/SingleTransactionExecutingDto.cs | 23 +- .../Extensions/TaskExtensions.cs | 142 +- .../HostSmartContractBridgeContext.cs | 509 +- .../ICachedStateProvider.cs | 9 +- .../IExecutionObserverThreshold.cs | 37 +- .../IHostSmartContractBridgeContext.cs | 17 +- .../IScopedStateProvider.cs | 9 +- .../ISmartContractAddressNameProvider.cs | 13 +- .../IStateProviderFactory.cs | 10 +- .../ITransactionContext.cs | 29 +- .../IDefaultContractZeroCodeProvider.cs | 83 +- .../Infrastructure/IExecutive.cs | 37 +- .../Infrastructure/IExecutivePlugin.cs | 17 +- .../ISmartContractCategoryProvider.cs | 9 +- .../Infrastructure/ISmartContractRunner.cs | 12 +- .../ISmartContractRunnerContainer.cs | 13 +- .../SmartContractRunnerContainer.cs | 55 +- src/AElf.Kernel.SmartContract/RequiredAcs.cs | 11 +- .../ScopedStateProvider.cs | 54 +- .../SmartContractAElfModule.cs | 21 +- .../SmartContractConstants.cs | 15 +- .../StateProviderFactory.cs | 26 +- .../TransactionContext.cs | 35 +- .../ZeroSmartContractAddressNameProvider.cs | 15 +- .../AElf.Kernel.SmartContractExecution.csproj | 8 +- .../Application/BlockExecutingService.cs | 388 +- .../Application/BlockExecutionResult.cs | 20 +- .../BlockExecutionResultProcessingService.cs | 88 +- .../Application/BlockchainExecutingService.cs | 233 +- .../CodeUpdatedLogEventProcessor.cs | 89 +- .../ContractDeployedLogEventProcessor.cs | 107 +- .../Application/IBlockAttachService.cs | 100 +- .../Application/IBlockExecutingService.cs | 14 +- .../IBlockExecutionResultProcessingService.cs | 9 +- .../IBlockchainExecutingService.cs | 9 +- ...martContractRegistrationInStateProvider.cs | 57 +- .../Events/BlocksExecutionSucceededEvent.cs | 9 +- ...ObserverThresholdConfigurationProcessor.cs | 39 +- .../Extensions/BlockchainServiceExtensions.cs | 18 +- .../SmartContractExecutionAElfModule.cs | 31 +- .../StateLimitSizeConfigurationProcessor.cs | 27 +- .../AElf.Kernel.Token.csproj | 6 +- ...TokenContractInitializationDataProvider.cs | 48 +- .../TokenContractInitializationProvider.cs | 197 +- .../TokenKernelAElfModule.cs | 7 +- .../TokenSmartContractAddressNameProvider.cs | 15 +- .../AElf.Kernel.TransactionPool.csproj | 4 +- .../BlockchainServiceExtensions.cs | 33 +- .../Application/ExecutableTransactionSet.cs | 13 +- .../Application/ITransactionPoolService.cs | 93 +- .../ITransactionValidationService.cs | 33 +- .../Application/TransactionPoolStatus.cs | 11 +- .../TransactionValidationService.cs | 84 +- .../Events/TransactionAcceptedEvent.cs | 11 +- ...ansactionExecutionValidationFailedEvent.cs | 9 +- .../Events/TransactionsReceivedEvent.cs | 9 +- .../BasicTransactionValidationProvider.cs | 59 +- .../Infrastructure/ITxHub.cs | 23 +- .../TransactionExecutionValidationProvider.cs | 91 +- .../TransactionMethodValidationProvider.cs | 45 +- .../Infrastructure/TxHub.cs | 596 +- .../TransactionOptions.cs | 33 +- .../TransactionPoolAElfModule.cs | 29 +- .../TransactionPoolConsts.cs | 9 +- .../AElf.Kernel.Types.csproj | 4 +- src/AElf.Kernel.Types/Block/Block.cs | 71 +- src/AElf.Kernel.Types/Block/BlockBody.cs | 43 +- src/AElf.Kernel.Types/Block/BlockHeader.cs | 99 +- src/AElf.Kernel.Types/Block/IBlock.cs | 11 +- src/AElf.Kernel.Types/Block/IBlockBody.cs | 9 +- src/AElf.Kernel.Types/Block/IBlockHeader.cs | 15 +- src/AElf.Kernel.Types/Block/IBlockIndex.cs | 29 +- src/AElf.Kernel.Types/Bloom.cs | 171 +- src/AElf.Kernel.Types/Chain/Chain.cs | 14 +- src/AElf.Kernel.Types/Chain/ChainContext.cs | 13 +- .../Chain/DiscardedBranch.cs | 11 +- src/AElf.Kernel.Types/Chain/IChainContext.cs | 15 +- .../Extensions/LogEventExtensions.cs | 22 +- .../Helper/TimestampHelper.cs | 35 +- src/AElf.Kernel.Types/IStateCache.cs | 11 +- src/AElf.Kernel.Types/KernelConstants.cs | 31 +- src/AElf.Kernel.Types/StateValue.cs | 41 +- .../Transaction/QueuedTransaction.cs | 31 +- .../Transaction/TransactionTrace.cs | 185 +- src/AElf.Kernel/AElf.Kernel.csproj | 20 +- src/AElf.Kernel/BlockMinedEventData.cs | 9 +- .../ConsensusRequestMiningEventHandler.cs | 143 +- src/AElf.Kernel/GlobalUsings.cs | 7 + .../InitialSyncFinishedEventHandler.cs | 28 +- src/AElf.Kernel/KernelAElfModule.cs | 54 +- .../Application/BlockAcceptedEventHandler.cs | 28 +- .../Application/BlockTemplateMinerService.cs | 70 +- .../Application/BlockValidationProvider.cs | 54 +- .../BlocksExecutionSucceededEventHandler.cs | 29 +- .../Application/IBlockTemplateMinerService.cs | 18 +- .../Miner/Application/IMinerService.cs | 22 +- .../Application/IMiningRequestService.cs | 99 +- .../Miner/Application/IMiningService.cs | 22 +- .../Miner/Application/MinerService.cs | 108 +- .../Miner/Application/MiningService.cs | 229 +- .../TxPoolInterestedEventsHandler.cs | 59 +- ...kTransactionLimitConfigurationProcessor.cs | 35 +- .../Miner/BlockTransactionLimitProvider.cs | 81 +- src/AElf.Kernel/Miner/Dto/RequestMiningDto.cs | 18 +- .../NewIrreversibleBlockFoundEventHandler.cs | 142 +- src/AElf.Launcher/AElf.Launcher.csproj | 16 +- src/AElf.Launcher/Program.cs | 91 +- src/AElf.Launcher/Startup.cs | 104 +- .../appsettings.MainChain.CustomNet.json | 30 +- .../appsettings.MainChain.MainNet.json | 34 +- .../appsettings.MainChain.TestNet.json | 28 +- src/AElf.Launcher/appsettings.Production.json | 2 +- .../appsettings.SideChain.CustomNet.json | 20 +- src/AElf.Launcher/appsettings.json | 10 +- src/AElf.OS.Core/AElf.OS.Core.csproj | 6 +- src/AElf.OS.Core/AccountOptions.cs | 11 +- src/AElf.OS.Core/CoreOSAElfModule.cs | 32 +- src/AElf.OS.Core/EconomicOptions.cs | 27 +- .../Network/Application/INetworkService.cs | 44 +- .../Application/IPeerDiscoveryService.cs | 15 +- ...PeerInvalidTransactionProcessingService.cs | 9 +- .../Application/IReconnectionService.cs | 106 +- .../Network/Application/ISyncStateService.cs | 273 +- .../Network/Application/NetworkService.cs | 622 +- .../Application/PeerDiscoveryService.cs | 123 +- ...PeerInvalidTransactionProcessingService.cs | 58 +- .../Network/Application/Response.cs | 24 +- .../Network/Domain/NodeManager.cs | 105 +- .../Events/AnnoucementReceivedEventData.cs | 19 +- .../Network/Events/BlockReceivedEvent.cs | 21 +- .../Network/Events/NetworkInitializedEvent.cs | 7 +- .../Network/Events/PeerConnectedEventData.cs | 24 +- .../Extensions/AElfNetworkServerExtensions.cs | 18 +- .../BlockWithTransactionsExtensions.cs | 21 +- .../Extensions/BlockchainServiceExtensions.cs | 57 +- .../Network/Helpers/AElfPeerEndpointHelper.cs | 118 +- .../Network/Helpers/PeerInfoHelper.cs | 37 +- .../Exceptions/NetworkException.cs | 51 +- .../Infrastructure/IAElfNetworkServer.cs | 22 +- .../IBlackListedPeerProvider.cs | 94 +- .../IDiscoveredNodeCacheProvider.cs | 41 +- .../Infrastructure/INodeSyncStateProvider.cs | 37 +- .../Network/Infrastructure/IPeer.cs | 83 +- .../IPeerDiscoveryJobProcessor.cs | 236 +- .../IPeerInvalidTransactionProvider.cs | 130 +- .../Network/Infrastructure/IPeerPool.cs | 38 +- .../IPeerReconnectionStateProvider.cs | 85 +- .../Network/Infrastructure/PeerPool.cs | 260 +- .../Network/Metrics/RequestMetric.cs | 15 +- src/AElf.OS.Core/Network/NetworkConstants.cs | 67 +- src/AElf.OS.Core/Network/NetworkOptions.cs | 161 +- .../Network/Protocol/HandshakeProvider.cs | 202 +- .../Network/Protocol/IHandshakeProvider.cs | 11 +- .../Protocol/Types/BlockWithTransactions.cs | 53 +- .../Network/Protocol/Types/NodeInfo.cs | 11 +- .../Network/Protocol/Types/NodeList.cs | 11 +- .../Protocol/Types/PeerConnectionInfo.cs | 17 +- .../Network/Types/AElfPeerEndpoint.cs | 21 +- src/AElf.OS.Core/Network/Types/PeerInfo.cs | 31 +- .../Application/GenesisSmartContractDto.cs | 13 +- .../GenesisSmartContractDtoExtensions.cs | 35 +- .../IGenesisSmartContractDtoProvider.cs | 10 +- .../Application/INodeEnvironmentService.cs | 9 +- .../IOsBlockchainNodeContextService.cs | 11 +- .../Application/NodeEnvironmentService.cs | 23 +- .../OsBlockchainNodeContextService.cs | 216 +- .../OsBlockchainNodeContextStartDto.cs | 22 +- .../Node/Domain/OsBlockchainNodeContext.cs | 15 +- .../INodeEnvironmentProvider.cs | 9 +- .../Infrastructure/NodeEnvironmentProvider.cs | 33 +- .../AElf.OS.Network.Grpc.csproj | 24 +- .../BoundedExpirationCache.cs | 91 +- .../Connection/ConnectionService.cs | 549 +- .../Connection/IConnectionService.cs | 28 +- .../Connection/IPeerDialer.cs | 13 +- .../Connection/PeerDialer.cs | 415 +- .../Extensions/CallContextExtensions.cs | 38 +- .../ClientInterceptorContextExtensions.cs | 57 +- src/AElf.OS.Network.Grpc/GrpcClient.cs | 23 +- src/AElf.OS.Network.Grpc/GrpcConstants.cs | 39 +- src/AElf.OS.Network.Grpc/GrpcNetworkModule.cs | 31 +- src/AElf.OS.Network.Grpc/GrpcNetworkServer.cs | 278 +- src/AElf.OS.Network.Grpc/GrpcPeer.cs | 970 ++- src/AElf.OS.Network.Grpc/GrpcRequest.cs | 13 +- .../Helpers/GrpcEndPointHelper.cs | 23 +- src/AElf.OS.Network.Grpc/Helpers/TlsHelper.cs | 86 +- .../Interceptors/AuthInterceptor.cs | 150 +- .../Interceptors/RetryInterceptor.cs | 123 +- src/AElf.OS.Network.Grpc/QueuedHash.cs | 11 +- .../Service/GrpcServerService.cs | 586 +- src/AElf.OS.Network.Grpc/StreamJob.cs | 17 +- src/AElf.OS/AElf.OS.csproj | 10 +- .../Account/Application/AccountService.cs | 107 +- .../Account/Infrastructure/AElfKeyStore.cs | 244 +- src/AElf.OS/Account/Infrastructure/Account.cs | 20 +- .../Account/Infrastructure/AccountError.cs | 15 +- .../Account/Infrastructure/IKeyStore.cs | 15 +- .../Account/Infrastructure/Password.cs | 23 +- .../Application/BlockDownloadService.cs | 460 +- .../Application/BlockFetchService.cs | 103 +- .../Application/BlockSyncAttachService.cs | 102 +- .../Application/BlockSyncQueueService.cs | 107 +- .../BlockSync/Application/BlockSyncService.cs | 173 +- .../Application/BlockSyncValidationService.cs | 147 +- .../Application/IBlockDownloadService.cs | 15 +- .../Application/IBlockFetchService.cs | 9 +- .../Application/IBlockSyncAttachService.cs | 13 +- .../Application/IBlockSyncQueueService.cs | 11 +- .../Application/IBlockSyncService.cs | 12 +- .../IBlockSyncValidationService.cs | 15 +- src/AElf.OS/BlockSync/BlockSyncConstants.cs | 20 +- src/AElf.OS/BlockSync/BlockSyncOptions.cs | 33 +- .../Domain/BlockDownloadJobManager.cs | 41 +- .../Domain/IBlockDownloadJobManager.cs | 11 +- src/AElf.OS/BlockSync/Dto/DownloadBlockDto.cs | 19 +- .../BlockSync/Dto/SyncAnnouncementDto.cs | 17 +- src/AElf.OS/BlockSync/Dto/SyncBlockDto.cs | 17 +- .../Events/AbnormalPeerFoundEventData.cs | 13 +- .../Exceptions/BlockDownloadException.cs | 43 +- .../AnnouncementCacheProvider.cs | 101 +- .../Infrastructure/BlockSyncStateProvider.cs | 91 +- .../IAnnouncementCacheProvider.cs | 11 +- .../Infrastructure/IBlockDownloadJobStore.cs | 15 +- .../Infrastructure/IBlockSyncStateProvider.cs | 23 +- .../InMemoryBlockDownloadJobStore.cs | 70 +- .../BlockSync/Types/BlockDownloadJobInfo.cs | 27 +- .../BlockSync/Types/DownloadBlocksResult.cs | 17 +- .../BlockSync/Worker/BlockDownloadWorker.cs | 275 +- .../Handlers/AbnormalPeerEventHandler.cs | 31 +- .../Handlers/BlockAcceptedEventHandler.cs | 57 +- .../Handlers/BlockMinedEventHandler.cs | 65 +- .../AnnouncementReceivedEventHandler.cs | 80 +- .../Network/BlockReceivedEventHandler.cs | 77 +- .../Network/NetworkInitializedEventHandler.cs | 23 +- .../Network/PeerConnectedEventHandler.cs | 46 +- .../TransactionAcceptedEventHandler.cs | 17 +- .../NewIrreversibleBlockFoundEventHandler.cs | 36 +- ...onExecutionValidationFailedEventHandler.cs | 37 +- src/AElf.OS/OSConstants.cs | 13 +- src/AElf.OS/Worker/PeerDiscoveryWorker.cs | 104 +- src/AElf.OS/Worker/PeerReconnectionWorker.cs | 194 +- .../AElf.Runtime.CSharp.Core.csproj | 10 +- .../ContractCodeLoadContext.cs | 61 +- src/AElf.Runtime.CSharp.Core/Exceptions.cs | 31 +- .../ISdkStreamManager.cs | 9 +- src/AElf.Runtime.CSharp.Core/RunnerOptions.cs | 16 +- .../SdkStreamManager.cs | 54 +- ...Runtime.CSharp.ExecutiveTokenPlugin.csproj | 4 +- ...utiveTokenPluginCSharpRuntimeAElfModule.cs | 9 +- .../AElf.Runtime.CSharp.csproj | 14 +- .../CSharpRuntimeAElfModule.cs | 51 +- .../CSharpSmartContractProxy.cs | 214 +- .../CSharpSmartContractRunner.cs | 91 +- .../CSharpSmartContractRuntimeException.cs | 15 +- src/AElf.Runtime.CSharp/Executive.cs | 339 +- src/AElf.Runtime.CSharp/ServerCallHandler.cs | 97 +- src/AElf.Runtime.CSharp/ServerCalls.cs | 18 +- .../ServerServiceDefinitionExtensions.cs | 82 +- .../UnitTestCSharpSmartContractRunner.cs | 45 +- .../AElf.RuntimeSetup.csproj | 8 +- .../RuntimeSetupAElfModule.cs | 29 +- src/AElf.RuntimeSetup/log4net.config | 47 +- src/AElf.Sdk.CSharp/AElf.Sdk.CSharp.csproj | 8 +- src/AElf.Sdk.CSharp/AElfString.cs | 116 +- src/AElf.Sdk.CSharp/CSharpSmartContract.cs | 7 +- .../CSharpSmartContractAbstract.cs | 36 +- .../CSharpSmartContractContext.cs | 663 +- src/AElf.Sdk.CSharp/CSharpSmartContract`.cs | 23 +- .../CSharpSmartContract`_Internal.cs | 55 +- src/AElf.Sdk.CSharp/Exceptions.cs | 129 +- src/AElf.Sdk.CSharp/ExecutionObserver.cs | 89 +- .../Properties/InternalVisibleTo.cs | 2 +- .../SmartContractBridgeContextExtensions.cs | 446 +- src/AElf.Sdk.CSharp/SmartContractConstants.cs | 106 +- .../State/ContractReferenceState.cs | 49 +- src/AElf.Sdk.CSharp/State/ContractState.cs | 13 +- src/AElf.Sdk.CSharp/State/MappedState.cs | 408 +- src/AElf.Sdk.CSharp/State/MethodReference.cs | 73 +- .../State/MethodReferenceExtensions.cs | 16 +- src/AElf.Sdk.CSharp/State/ReadonlyState.cs | 92 +- src/AElf.Sdk.CSharp/State/SingletonState.cs | 99 +- .../State/SingletonState_Aliases.cs | 109 +- src/AElf.Sdk.CSharp/State/StateBase.cs | 68 +- src/AElf.Sdk.CSharp/State/StructuredState.cs | 156 +- src/AElf.Sdk.CSharp/ViewAttribute.cs | 9 +- src/AElf.Types/AElf.Types.csproj | 4 +- src/AElf.Types/AElfConstants.cs | 13 +- src/AElf.Types/Base58.cs | 293 +- src/AElf.Types/Extensions/ByteExtensions.cs | 195 +- .../Extensions/ByteStringExtensions.cs | 53 +- .../Extensions/HexStringExtensions.cs | 13 +- .../Extensions/IMessageExtensions.cs | 11 +- .../Extensions/MerklePathExtensions.cs | 15 +- .../Extensions/NumericExtensions.cs | 59 +- .../Extensions/StateKeyExtensions.cs | 27 +- src/AElf.Types/Extensions/StringExtensions.cs | 12 +- src/AElf.Types/Helper/AddressHelper.cs | 15 +- src/AElf.Types/Helper/BlockHelper.cs | 13 +- src/AElf.Types/Helper/ByteArrayHelper.cs | 85 +- src/AElf.Types/Helper/ByteStringHelper.cs | 34 +- src/AElf.Types/Helper/ChainHelper.cs | 71 +- src/AElf.Types/Helper/HashHelper.cs | 150 +- src/AElf.Types/Helper/SerializationHelper.cs | 192 +- src/AElf.Types/IBlockBase.cs | 9 +- src/AElf.Types/IHashProvider.cs | 9 +- src/AElf.Types/ISmartContract.cs | 7 +- .../Protobuf/FileDescriptorExtensions.cs | 16 +- src/AElf.Types/Types/Address.cs | 263 +- src/AElf.Types/Types/BigIntValue.cs | 233 +- src/AElf.Types/Types/BinaryMerkleTree.cs | 164 +- src/AElf.Types/Types/Hash.cs | 235 +- src/AElf.Types/Types/Transaction.cs | 59 +- .../AElf.WebApp.Application.Chain.csproj | 12 +- ...tionValidationStatusChangedEventHandler.cs | 41 +- .../BlockchainServiceExtensions.cs | 21 +- .../ChainApplicationWebAppAElfModule.cs | 34 +- .../Dto/BlockBodyDto.cs | 13 +- .../Dto/BlockDto.cs | 21 +- .../Dto/BlockHeaderDto.cs | 27 +- .../Dto/BlockStateDto.cs | 17 +- .../Dto/ChainStatusDto.cs | 49 +- .../Dto/CreateRawTransactionInput.cs | 129 +- .../Dto/CreateRawTransactionOutput.cs | 9 +- .../Dto/ExecuteRawTransactionDto.cs | 25 +- .../Dto/ExecuteTransactionDto.cs | 15 +- .../Dto/GetTransactionPoolStatusOutput.cs | 11 +- .../Dto/LogEventDto.cs | 21 +- .../Dto/MerklePathDto.cs | 19 +- .../Dto/MiningSequenceDto.cs | 18 +- .../Dto/SendRawTransactionInput.cs | 35 +- .../Dto/SendRawTransactionOutput.cs | 13 +- .../Dto/SendTransactionInput.cs | 15 +- .../Dto/SendTransactionOutput.cs | 9 +- .../Dto/SendTransactionsInput.cs | 15 +- .../Dto/TaskQueueStatusInfoDto.cs | 13 +- .../Dto/TransactionDto.cs | 33 +- .../Dto/TransactionResultDto.cs | 29 +- src/AElf.WebApp.Application.Chain/Error.cs | 59 +- .../ITransactionResultStatusCacheProvider.cs | 85 +- .../Profile/BlockProfile.cs | 66 +- .../Profile/BlockStateSetProfile.cs | 11 +- .../Profile/ChainProfile.cs | 29 +- .../Profile/CommonProfile.cs | 24 +- .../Profile/MerklePathProfile.cs | 13 +- .../Profile/TaskQueueInfoProfile.cs | 11 +- .../Profile/TransactionPoolStatusProfile.cs | 16 +- .../Profile/TransactionProfile.cs | 86 +- .../Services/BlockChainAppService.cs | 29 +- .../Services/ChainStatusAppService.cs | 7 +- .../ContractFileDescriptorSetAppService.cs | 10 +- .../Services/TaskQueueStatusAppService.cs | 4 +- .../Services/TransactionAppService.cs | 52 +- .../Services/TransactionResultAppService.cs | 80 +- .../Services/TransactionResultProxyService.cs | 6 +- ...ctionReadOnlyExecutionServiceExtensions.cs | 47 +- .../WebAppOptions.cs | 11 +- .../AElf.WebApp.Application.Core.csproj | 8 +- .../AElfAppService.cs | 1 - .../CoreApplicationWebAppAElfModule.cs | 2 +- .../AElf.WebApp.Application.Net.csproj | 8 +- .../Dto/AddPeerInput.cs | 15 +- .../Dto/GetNetworkInfoOutput.cs | 35 +- .../Dto/PeerDto.cs | 26 +- .../NetAppService.cs | 16 +- .../Profile/PeerInfoProfile.cs | 9 +- src/AElf.WebApp.Web/AElf.WebApp.Web.csproj | 20 +- .../AElfConventionalRouteBuilder.cs | 17 +- src/AElf.WebApp.Web/ApiOptionFilter.cs | 35 +- src/AElf.WebApp.Web/BasicAuthOptions.cs | 11 +- .../BasicAuthenticationHandler.cs | 95 +- .../ConfigureSwaggerOptions.cs | 31 +- .../WebAppAbpAspNetCoreMvcModule.cs | 19 +- .../WebAppAbpServiceConvention.cs | 1 - src/AElf.WebApp.Web/WebWebAppAElfModule.cs | 368 +- .../AElf.CSharp.CodeOps.Tests.csproj | 58 +- .../CSharpCodeOpsTestBase.cs | 97 +- .../ContractAuditorTests.cs | 671 +- .../ContractPolicyTests.cs | 178 +- .../Extensions/ExtensionTests.cs | 127 +- .../Helper/AssemblyCompiler.cs | 56 +- .../InstructionInjectionValidatorTests.cs | 47 +- .../StateWrittenInstructionInjectorTests.cs | 142 +- .../Patch/ExecutionObserverInjectorTests.cs | 81 +- .../Patch/MethodCallReplacerTests.cs | 115 +- .../Patch/ResetFieldsMethodInjectorTests.cs | 149 +- .../TestCSharpCodeOpsAElfModule.cs | 25 +- .../Validators/Method/ArrayValidatorTests.cs | 59 +- .../whitelist/WhitelistValidatorTests.cs | 94 +- .../AElf.CSharp.Core.Tests.csproj | 16 +- .../Extension/TimestampExtensionsTests.cs | 19 +- .../AElf.CSharp.Core.Tests/MarshallerTests.cs | 25 +- test/AElf.CSharp.Core.Tests/MethodTests.cs | 45 +- .../PreconditionsTests.cs | 27 +- .../TypesCSharpTestAElfModule.cs | 7 +- .../TypesCSharpTestBase.cs | 7 +- .../AElf.ContractDeployer.Tests.csproj | 16 +- .../ContractDeployerTestAElfModule.cs | 9 +- .../ContractDeployerTestBase.cs | 8 +- .../ContractsDeployerTests.cs | 135 +- .../AElf.ContractTestBase.Tests.csproj | 18 +- .../MainChainTestBase.cs | 8 +- .../MainChainTestModule.cs | 19 +- .../MainChainTests.cs | 64 +- .../SideChainTestBase.cs | 8 +- .../SideChainTestModule.cs | 19 +- .../SideChainTests.cs | 50 +- .../AEDPoSExtensionDemoModule.cs | 22 +- .../AEDPoSExtensionDemoTestBase.cs | 197 +- .../AEDPoSExtensionTests.cs | 284 +- ...ontracts.AEDPoSExtension.Demo.Tests.csproj | 20 +- .../BroadcastPrivilegedPubkeyListTest.cs | 27 +- .../MaximumMinersCountTests.cs | 136 +- .../README.md | 31 +- .../RandomNumberProviderTests.cs | 75 +- .../SideChainConsensusInformationTest.cs | 203 +- .../SideChainRentFeeModule.cs | 58 +- .../SideChainRentFeeTestBase.cs | 360 +- .../SideChainSideChainRentFeeTest.cs | 755 ++- .../AElf.Contracts.Association.Tests.csproj | 16 +- .../AssociationContractTestAElfModule.cs | 75 +- .../AssociationContractTestBase.cs | 93 +- .../AssociationContractTests.cs | 2351 +++---- .../ContractDeploymentListProvider.cs | 21 +- ...estDemoSmartContractAddressNameProvider.cs | 16 +- .../Types/MinerList.cs | 68 +- ...TestTokenContractInitializationProvider.cs | 83 +- .../AElf.Contracts.Configuration.Tests.csproj | 14 +- .../ConfigurationContractTest.cs | 734 +-- .../ConfigurationContractTestAElfModule.cs | 10 +- .../ConfigurationContractTestBase.cs | 284 +- .../AEDPoSContractConstants.cs | 13 +- .../AEDPoSContractTestAElfModule.cs | 15 +- .../AEDPoSContractTestBase.cs | 275 +- .../AEDPoSContractTestConstants.cs | 32 +- ...lf.Contracts.Consensus.AEDPoS.Tests.csproj | 30 +- .../BVT/ACS10ImplTest.cs | 80 +- .../BVT/ACS1ImplTest.cs | 108 +- .../BVT/ACS4ImplTest.cs | 650 +- .../BVT/InValueRecoveryTest.cs | 89 +- .../BVT/MinersCountTest.cs | 193 +- .../BVT/MiningProcessTest.cs | 224 +- .../BVT/SideChainDividendPoolTest.cs | 51 +- .../BVT/ViewTests.cs | 144 +- .../Extensions/BytesValueExtensions.cs | 15 +- .../ResetBlockTimeProvider.cs | 11 +- .../Types/MinerList.cs | 70 +- .../Types/Round.cs | 244 +- .../Types/Round_Generation.cs | 172 +- .../AElf.Contracts.CrossChain.Tests.csproj | 16 +- .../ContractDeploymentListProvider.cs | 23 +- .../CrossChainContractTestAElfModule.cs | 65 +- .../CrossChainContractTestBase.cs | 709 +-- .../CrossChainIndexingActionTest.cs | 2897 ++++----- .../SideChainLifeTimeManagementTest.cs | 2891 ++++----- .../UnitTestContractInitializationProvider.cs | 35 +- ...acts.Economic.AEDPoSExtension.Tests.csproj | 20 +- .../EconomicTestBase.cs | 293 +- .../EconomicTestConstants.cs | 17 +- .../EconomicTestHelpers.cs | 270 +- .../EconomicTestModule.cs | 17 +- .../EvilNodeRelatedTests.cs | 117 +- .../TreasuryCollectionTests.cs | 455 +- .../TreasuryDistributionInformation.cs | 34 +- .../TreasuryDistributionTests.cs | 750 ++- .../AElf.Contracts.Economic.TestBase.csproj | 24 +- .../AssemblyInfo.cs | 2 - .../Contracts.cs | 75 +- .../ContractsPreparation.cs | 961 ++- .../EconomicContractsTestBase.cs | 79 +- .../EconomicContractsTestConstants.cs | 51 +- .../EconomicContractsTestModule.cs | 33 +- .../EconomicTestTransactionExecutor.cs | 108 +- .../MockBlockValidationService.cs | 27 +- .../OtherContractsOperation.cs | 151 +- .../Types/MinerList.cs | 70 +- .../Types/Round.cs | 87 +- .../Types/Round_Generation.cs | 162 +- ...AElf.Contracts.EconomicSystem.Tests.csproj | 28 +- .../BVT/AETCTest.cs | 95 +- .../BVT/AdvanceResourceTokenTests.cs | 289 +- .../BVT/CalculateCoefficientFeeTests.cs | 25 +- .../BVT/ConfigurationTests.cs | 188 +- .../BVT/DonateTests.cs | 315 +- .../BVT/LockTokenTest.cs | 108 +- .../BVT/ThresholdContractTests.cs | 63 +- .../BVT/TransactionFeeProviderTests.cs | 323 +- .../BVT/TransactionFeeTests.cs | 480 +- .../BVT/TreasureViewTests.cs | 124 +- .../BVT/TreasuryBasicTests.cs | 1031 +-- .../EconomicSystemTestBase.cs | 306 +- .../EconomicSystemTestConstants.cs | 11 +- .../EconomicSystemTestModule.cs | 13 +- .../ElectionContractConstants.cs | 20 +- .../AElf.Contracts.Election.Tests.csproj | 28 +- .../BVT/ACS1ImplTest.cs | 317 +- .../BVT/ElectionTests.cs | 2189 +++---- .../BVT/ElectionViewTests.cs | 568 +- .../BVT/ReplaceCandidateTests.cs | 255 +- .../BVT/SponsorTests.cs | 89 +- .../ElectionContractConstants.cs | 13 +- .../ElectionContractTestBase.cs | 237 +- .../ElectionContractTestConstants.cs | 21 +- .../ElectionContractTestHelpers.cs | 156 +- .../ElectionContractTestModule.cs | 15 +- .../Full/MainChainMinerElection.cs | 104 +- .../Full/ReleaseProfitsFromTreasury.cs | 1103 ++-- .../GQL/ElectionTests.cs | 816 ++- .../ProfitContractConsts.cs | 11 +- .../Types/MinerList.cs | 79 +- .../Types/Round.cs | 410 +- .../Types/Round_Generation.cs | 162 +- .../VoteContractConsts.cs | 11 +- .../AElf.Contracts.Genesis.Tests.csproj | 22 +- .../GenesisContractAuthTest.cs | 2215 +++---- .../GenesisContractTest.cs | 303 +- .../GenesisContractTestAElfModule.cs | 35 +- .../GenesisContractTestBase.cs | 481 +- .../AElf.Contracts.GenesisUpdate.csproj | 6 +- .../BasicContractZero.cs | 406 +- .../BasicContractZeroState.cs | 45 +- .../AElf.Contracts.MultiToken.Tests.csproj | 18 +- .../BVT/ACS1_ImplementTest.cs | 479 +- .../BVT/ACS2_TokenResourceTests.cs | 133 +- .../BVT/TokenApplicationTests.cs | 1888 +++--- .../BVT/TokenEconomicTests.cs | 121 +- .../BVT/TokenFeeTest.cs | 368 +- .../BVT/TokenManagementTests.cs | 943 ++- ...cFunctionContractInitializationProvider.cs | 17 +- .../ContractDeploymentListProvider.cs | 42 +- .../DPoSContractConsts.cs | 15 +- .../MultiTokenContractTestAElfModule.cs | 71 +- .../MultiTokenContractTestBase.cs | 114 +- ...ContractWithCustomSystemTransactionTest.cs | 119 +- ...cFunctionContractInitializationProvider.cs | 17 +- ...amentContractInitializationDataProvider.cs | 17 +- ...TestTokenContractInitializationProvider.cs | 193 +- .../TestTokenBalanceTransactionGenerator.cs | 24 +- .../Types/MinerList.cs | 69 +- .../Types/Round.cs | 244 +- .../Types/Round_Generation.cs | 167 +- ...TestTokenContractInitializationProvider.cs | 108 +- ....MultiTokenCrossChainTransfer.Tests.csproj | 278 +- .../ContractDeploymentListProvider.cs | 51 +- .../MultiTokenContractCrossChainTest.cs | 2333 ++++--- ...tiTokenContractCrossChainTestAElfModule.cs | 181 +- .../MultiTokenContractCrossChainTestBase.cs | 585 +- .../MultiTokenContractReferenceFeeTest.cs | 1857 +++--- ...amentContractInitializationDataProvider.cs | 29 +- .../ResetBlockTimeProvider.cs | 11 +- .../SideChainInitializationDataProvider.cs | 111 +- ...TestTokenContractInitializationProvider.cs | 203 +- .../TestTokenBalanceTransactionGenerator.cs | 24 +- .../Types/MinerList.cs | 68 +- .../Types/Round.cs | 242 +- .../Types/Round_Generation.cs | 165 +- ...TestTokenContractInitializationProvider.cs | 108 +- .../AElf.Contracts.NFT.Tests.csproj | 20 +- .../NFTContractInitializationProvider.cs | 17 +- .../NFTContractTestAElfModule.cs | 23 +- .../NFTContractTestBase.cs | 291 +- .../NFTContractTests.cs | 419 +- ...NFTMarketContractInitializationProvider.cs | 16 +- .../NFTMarketContractTests.cs | 775 ++- .../NFTMarketContractTests_Auction.cs | 728 ++- .../NFTMarketContractTests_Customize.cs | 543 +- .../NFTMarketContractTests_WhiteList.cs | 794 ++- ...NFTMinterContractInitializationProvider.cs | 17 +- .../NFTMinterContractTests.cs | 212 +- .../NFTMinterContract_BlindBox.cs | 183 +- .../AElf.Contracts.Parliament.Tests.csproj | 20 +- .../ParliamentContractPrivilegeTest.cs | 367 +- .../ParliamentContractTest.cs | 2697 ++++---- .../ParliamentContractTestAElfModule.cs | 33 +- .../ParliamentContractTestBase.cs | 337 +- .../Types/MinerList.cs | 80 +- .../AElf.Contracts.Profit.Tests.csproj | 26 +- .../BVT/ProfitItemManagementTests.cs | 427 +- .../BVT/ProfitTests.cs | 240 +- .../GenesisContractDtoExtensions.cs | 21 +- .../ProfitContractTestAElfModule.cs | 15 +- .../ProfitContractTestBase.cs | 337 +- .../ProfitContractTestConstants.cs | 13 +- .../ProfitTests.cs | 2735 ++++---- .../Types/MineList.cs | 69 +- .../AElf.Contracts.Referendum.Tests.csproj | 26 +- .../GenesisContractDtoExtensions.cs | 21 +- .../ReferendumContractTest.cs | 2580 ++++---- .../ReferendumContractTestAElfModule.cs | 15 +- .../ReferendumContractTestBase.cs | 328 +- ...estDemoSmartContractAddressNameProvider.cs | 16 +- .../Types/MinerList.cs | 69 +- .../AElf.Contracts.TestBase.Tests.csproj | 18 +- .../ContractTesterTest.cs | 253 +- .../TestBaseTestAElfModule.cs | 11 +- .../AElf.Contracts.TestBase.csproj | 24 +- .../ContractTestAElfModule.cs | 83 +- .../ContractTestBase.cs | 18 +- .../AElf.Contracts.TestBase/ContractTester.cs | 1421 ++--- .../GenesisSmartContractDtoExtensions.cs | 39 +- .../SampleECKeyPairs.cs | 235 +- .../SmartContractTestConstants.cs | 31 +- .../Types/MinerList.cs | 71 +- .../AElf.Contracts.TestContract.A.csproj | 2 +- .../ContractA.cs | 158 +- .../ContractReference.cs | 11 +- .../AElf.Contracts.TestContract.B.csproj | 4 +- .../ContractB.cs | 158 +- .../ContractReference.cs | 11 +- ...ontracts.TestContract.BasicFunction.csproj | 6 +- .../BasicContractState.cs | 33 +- .../BasicContract_Action.cs | 243 +- .../BasicContract_FeeProvider.cs | 45 +- .../BasicContract_View.cs | 81 +- .../ContractReference.cs | 9 +- ...tContract.BasicFunctionWithParallel.csproj | 8 +- .../BasicFunctionWithParallelContractState.cs | 41 +- ...arallelContract_ACS1_StatePathsProvider.cs | 20 +- ...arallelContract_ACS2_StatePathsProvider.cs | 149 +- ...asicFunctionWithParallelContract_Action.cs | 733 +-- .../BasicFunctionWithParallelContract_View.cs | 99 +- .../ContractReference.cs | 9 +- ...ontracts.TestContract.BasicSecurity.csproj | 12 +- .../BasicContractState.cs | 60 +- .../BasicContract_Action.cs | 734 ++- .../BasicContract_FeeProvider.cs | 45 +- .../BasicContract_TestType.cs | 131 +- .../BasicContract_View.cs | 337 +- .../ContractReference.cs | 8 +- ....Contracts.TestContract.BasicUpdate.csproj | 8 +- .../BasicContractState.cs | 37 +- .../BasicContract_Action.cs | 150 +- .../BasicContract_FeeProvider.cs | 45 +- .../BasicContract_View.cs | 82 +- ....Contracts.TestContract.BigIntValue.csproj | 2 +- .../BigIntValueContract.cs | 61 +- .../BigIntValueContractState.cs | 9 +- .../AElf.Contracts.TestContract.C.csproj | 4 +- .../ContractC.cs | 159 +- .../ContractReference.cs | 11 +- .../AElf.Contracts.TestContract.DApp.csproj | 6 +- .../DAppConstants.cs | 15 +- .../DAppContract.cs | 403 +- .../DAppContractState.cs | 34 +- .../DAppContract_ACS9.cs | 101 +- .../DAppFeeProvider.cs | 32 +- .../AElf.Contracts.TestContract.Events.csproj | 4 +- .../ContractReference.cs | 21 +- .../EventsContract_Action.cs | 292 +- .../EventsContract_View.cs | 113 +- .../Events_Helper.cs | 99 +- ...ts.TestContract.MethodCallThreshold.csproj | 2 +- .../ContractsReferences.cs | 15 +- .../MethodCallThresholdContract.cs | 54 +- .../MethodCallThresholdContractConstants.cs | 11 +- .../MethodCallThresholdContractState.cs | 14 +- ....Contracts.TestContract.Performance.csproj | 6 +- .../PerformanceContractState.cs | 35 +- .../PerformanceContract_Action.cs | 192 +- .../PerformanceContract_FeeProvider.cs | 49 +- .../PerformanceContract_View.cs | 55 +- ...s.TestContract.RandomNumberProvider.csproj | 4 +- .../RandomNumberProviderContract.cs | 33 +- .../RandomNumberProviderContractState.cs | 8 +- ...tracts.TestContract.ResourceSpender.csproj | 2 +- .../ResourceSpenderContract.cs | 12 +- .../ResourceSpenderContractState.cs | 15 +- .../AElf.Contracts.TestContract.Tests.csproj | 22 +- .../BigIntValueTests.cs | 83 +- .../ContractBasicTests.cs | 630 +- .../ContractExternalCallTests.cs | 157 +- .../ContractMethodTests.cs | 579 +- .../ContractSecurityTests.cs | 229 +- .../PatchedContractSecurityTests.cs | 677 +- .../TestContractAElfModule.cs | 50 +- .../TestContractTestBase.cs | 819 +-- ...TestContract.TransactionFeeCharging.csproj | 2 +- .../ContractsReferences.cs | 9 +- .../TransactionFeeChargingContract.cs | 112 +- ...TransactionFeeChargingContractConstants.cs | 11 +- .../TransactionFeeChargingContractState.cs | 12 +- ...tracts.TestContract.TransactionFees.csproj | 10 +- .../Contract_Action.cs | 274 +- .../Contract_IFeeCharged.cs | 45 +- .../Contract_View.cs | 55 +- .../TransactionFeesContractState.cs | 25 +- ...racts.TokenConverter.Internal.Tests.csproj | 12 +- .../BancorHelperTest.cs | 166 +- .../ACS1_ImplementTest.cs | 332 +- ...AElf.Contracts.TokenConverter.Tests.csproj | 24 +- .../BancorHelper.cs | 314 +- .../InvalidValueException.cs | 9 +- .../TokenConvertConnectorTest.cs | 978 ++- .../TokenConverterContractTests.cs | 703 +- .../TokenConverterTestBase.cs | 220 +- .../TokenConverterTestModule.cs | 19 +- .../ACS1_ImplementTest.cs | 219 +- .../AElf.Contracts.TokenHolder.Tests.csproj | 30 +- .../DAppTests.cs | 214 +- .../DappSmartContractNameProvider.cs | 15 +- .../GenesisContractDtoExtensions.cs | 21 +- .../ResetBlockTimeProvider.cs | 11 +- .../TokenHolderContractTestAElfModule.cs | 21 +- .../TokenHolderContractTestBase.cs | 473 +- .../TokenHolderContractTestConstants.cs | 13 +- .../TokenHolderTests.cs | 883 ++- .../Types/MineList.cs | 69 +- ...ontracts.Vote.AEDPoSExtension.Tests.csproj | 16 +- .../VoteContractTestAElfModule.cs | 15 +- .../VoteContractTestBase.cs | 43 +- .../AElf.Contracts.Vote.Tests.csproj | 26 +- .../BVT/ACS1ImplTest.cs | 363 +- .../BVT/BasicTests.cs | 1065 ++-- .../BVT/SnapshotTests.cs | 161 +- .../Full/VoteForBestLanguageTests.cs | 232 +- .../GQL/BasicTests.cs | 163 +- .../GenesisContractDtoExtensions.cs | 21 +- .../ResetBlockTimeProvider.cs | 11 +- .../Types/MineList.cs | 69 +- .../VoteContractConstant.cs | 13 +- .../VoteContractTestAElfModule.cs | 17 +- .../VoteContractTestBase.cs | 331 +- .../VoteContractTestHelper.cs | 272 +- test/AElf.Core.Tests/AElf.Core.Tests.csproj | 14 +- test/AElf.Core.Tests/CoreAElfTestBase.cs | 7 +- test/AElf.Core.Tests/CoreAElfTestModule.cs | 35 +- .../Providers/ATestProvider.cs | 9 +- .../Providers/BTestProvider.cs | 9 +- .../Providers/CTestProvider.cs | 9 +- .../Providers/ITestProvider.cs | 9 +- test/AElf.Core.Tests/RegistrationTests.cs | 38 +- test/AElf.Core.Tests/ServiceContainerTests.cs | 31 +- test/AElf.Core.Tests/TaskQueueManagerTests.cs | 247 +- test/AElf.Core.Tests/TaskQueueTests.cs | 96 +- .../AElf.CrossChain.Core.Tests.csproj | 22 +- .../CrossChainRequestServiceTests.cs | 68 +- .../CrossChainResponseServiceTest.cs | 103 +- .../Cache/ChainCacheEntityProviderTest.cs | 95 +- .../Cache/CrossChainCacheEntityServiceTest.cs | 65 +- .../Cache/CrossChainDataConsumerTest.cs | 154 +- .../Cache/CrossChainDataProducerTest.cs | 114 +- .../Cache/CrossChainMemoryCacheTest.cs | 578 +- .../CrossChainClientServiceTests.cs | 115 +- .../CrossChainCommunicationTestBase.cs | 7 +- .../CrossChainCommunicationTestHelper.cs | 124 +- .../CrossChainCommunicationTestModule.cs | 321 +- ...ChainIndexingDataValidationServiceTests.cs | 675 +- .../CrossChainTestBase.cs | 56 +- .../CrossChainTestHelper.cs | 228 +- .../CrossChainTestModule.cs | 189 +- .../CrossChainIndexingDataServiceTests.cs | 1285 ++-- .../IrreversibleBlockStateProviderTest.cs | 49 +- ...ionInputForBlockMiningDataProviderTests.cs | 51 +- .../AElf.CrossChain.Grpc.Tests.csproj | 18 +- .../Client/GrpcClientTests.cs | 150 +- .../GrpcCrossChainClientNodePluginTests.cs | 82 +- .../GrpcCrossChainClientProviderTests.cs | 219 +- .../GrpcCrossChainClientServiceTests.cs | 75 +- .../Client/GrpcCrossChainClientTestBase.cs | 41 +- .../Client/GrpcCrossChainClientTestModule.cs | 140 +- .../GrpcCrossChainCommunicationTestHelper.cs | 27 +- .../GrpcCrossChainTestModule.cs | 37 +- .../LocalLibExtensionTest.cs | 130 +- .../GrpcCrossChainServerNodePluginTests.cs | 37 +- .../Server/GrpcCrossChainServerTestBase.cs | 37 +- .../Server/GrpcCrossChainServerTestModule.cs | 145 +- .../Server/GrpcServerTests.cs | 276 +- .../UriHelperTests.cs | 41 +- .../AElf.CrossChain.Tests.csproj | 20 +- .../CrossChainBlockExtraDataProviderTests.cs | 133 +- ...sChainIndexingTransactionGeneratorTests.cs | 153 +- .../CrossChainServiceTests.cs | 59 +- .../CrossChainTestBase.cs | 7 +- .../CrossChainTestHelper.cs | 102 +- .../CrossChainTestModule.cs | 148 +- .../CrossChainValidationProviderTests.cs | 305 +- .../MockTransactionPackingOptionProvider.cs | 25 +- .../AElf.Cryptography.Tests.csproj | 14 +- .../CryptoHelperTests.cs | 252 +- .../ECDSA/BlockSignatureTest.cs | 50 +- .../SecretSharingTest.cs | 143 +- .../AElf.Database.Tests.csproj | 16 +- test/AElf.Database.Tests/DatabaseTestBase.cs | 9 +- .../InMemoryDbContextTests.cs | 7 +- .../KeyValueDbContextTestBase.cs | 228 +- test/AElf.Database.Tests/MyDbContextTests.cs | 21 +- .../TestsDatabaseAElfModule.cs | 55 +- .../AElf.EconomicSystem.Tests.csproj | 16 +- .../EconomicSystemTestBase.cs | 7 +- .../EconomicSystemTestModule.cs | 24 +- .../AElf.EconomicSystem.Tests/ProviderTest.cs | 99 +- .../AElf.GovernmentSystem.Tests.csproj | 16 +- .../GovernmentSystemTestBase.cs | 7 +- .../GovernmentSystemTestModule.cs | 40 +- ...amentContractInitializationDataProvider.cs | 11 +- .../ProviderTest.cs | 99 +- .../AElf.Kernel.ChainController.Tests.csproj | 16 +- .../Application/ChainCreationServiceTests.cs | 70 +- .../ChainControllerTestAElfModule.cs | 28 +- .../ChainControllerTestBase.cs | 7 +- .../AElf.Kernel.CodeCheck.Tests.csproj | 16 +- .../Application/CodeCheckServiceTest.cs | 90 +- .../CodeCheckConstant.cs | 21 +- .../CodeCheckRequiredLogEventProcessorTest.cs | 70 +- .../CodeCheckTestAElfModule.cs | 60 +- .../CodeCheckTestBase.cs | 8 +- .../CustomizeContractAuditor.cs | 42 +- .../ContractAuditorContainerTest.cs | 59 +- .../AElf.Kernel.Configuration.Tests.csproj | 16 +- .../ConfigurationServiceTest.cs | 135 +- .../ConfigurationSetLogEventProcessorTest.cs | 151 +- .../ConfigurationTestModule.cs | 27 +- .../KernelConfigurationTestBase.cs | 80 +- .../MinerList.cs | 78 +- .../OptionalLogEventProcessingService.cs | 28 +- .../AEDPoSTestAElfModule.cs | 275 +- .../AEDPoSTestBase.cs | 9 +- .../AElf.Kernel.Consensus.AEDPoS.Tests.csproj | 18 +- .../AEDPoSExtraDataExtractorTests.cs | 67 +- .../AEDPoSTriggerInformationProviderTests.cs | 97 +- .../ConsensusExtraDataProviderTests.cs | 60 +- ...sensusValidationFailedEventHandlerTests.cs | 35 +- .../Application/InValueCacheTests.cs | 43 +- .../MockTransactionPackingOptionProvider.cs | 25 +- .../AElf.Kernel.Consensus.Tests.csproj | 24 +- .../Application/ConsensusServiceTests.cs | 139 +- .../ConsensusValidationProviderTests.cs | 141 +- .../ConsensusTestAElfModule.cs | 253 +- .../ConsensusTestBase.cs | 7 +- .../ConsensusTestHelper.cs | 17 +- .../MockConsensusScheduler.cs | 37 +- .../AElf.Kernel.Core.Tests.csproj | 16 +- .../AElfKernelTestBase.cs | 46 +- .../Application/AccountServiceTests.cs | 97 +- .../AccountTestAElfModule.cs | 17 + .../Application/BlockExtraDataServiceTests.cs | 82 +- .../BlockGenerationServiceTests.cs | 59 +- .../BlockValidationProviderTests.cs | 381 +- .../FullBlockchainServiceCreateChainTests.cs | 85 +- .../Application/FullBlockchainServiceTests.cs | 1342 ++-- .../TransactionBlockIndexServiceTests.cs | 791 +-- .../TransactionResultServiceTests.cs | 378 +- .../Blockchain/Domain/BlockManagerTests.cs | 82 +- .../Blockchain/Domain/ChainManagerTests.cs | 1925 +++--- .../Domain/TransactionManagerTests.cs | 94 +- .../StorageKeyExtensionsTests.cs | 41 +- ...TransactionBlockIndexCacheProviderTests.cs | 217 +- .../Extensions/BlockBodyExtensionsTest.cs | 52 +- .../Extensions/BlockExtensionsTests.cs | 111 +- .../Extensions/BlockHeaderExtensionsTests.cs | 37 +- .../Extensions/BlockStateSetExtensionTest.cs | 62 +- .../Extensions/LogEventExtensionsTests.cs | 57 +- .../Extensions/TransactionExtensionsTests.cs | 90 +- .../TransactionResultExtensionsTest.cs | 54 +- .../TransactionTraceExtensionsTests.cs | 338 +- test/AElf.Kernel.Core.Tests/GlobalUsings.cs | 5 + .../KernelCoreTestAElfModule.cs | 118 +- .../KernelCoreWithChainTestAElfModule.cs | 23 +- ...SystemTransactionExtraDataProviderTests.cs | 42 +- ...SystemTransactionGenerationServiceTests.cs | 36 +- ...ystemTransactionValidationProviderTests.cs | 125 +- .../BlockchainStateServiceTests.cs | 258 +- ...achedBlockchainExecutedDataServiceTests.cs | 421 +- .../BlockchainExecutedDataManagerTests.cs | 141 +- .../Domain/BlockchainStateManagerTests.cs | 641 +- ...lockchainExecutedDataCacheProviderTests.cs | 56 +- .../TransactionPackingOptionProviderTests.cs | 118 +- .../AElf.Kernel.FeatureManager.Tests.csproj | 12 +- .../FeatureActiveServiceTest.cs | 4 +- .../IMockService.cs | 13 +- .../KernelFeatureManagerTestBase.cs | 4 +- .../MinerList.cs | 78 +- .../OptionalLogEventProcessingService.cs | 7 +- .../AElf.Kernel.FeeCalculation.Tests.csproj | 16 +- ...lculateFunctionExecutedDataServiceTests.cs | 119 +- .../CalculateFunctionProviderTests.cs | 187 +- .../Infrastructure/CalculateFunctionTest.cs | 179 +- .../KernelTransactionFeeTestAElfModule.cs | 14 +- .../TransactionFeeTestBase.cs | 118 +- .../AElf.Kernel.Node.Tests.csproj | 18 +- .../BlockchainNodeContextServiceTests.cs | 144 +- .../NodeTestAElfModule.cs | 80 +- test/AElf.Kernel.Node.Tests/NodeTestBase.cs | 8 +- .../AElf.Kernel.Proposal.Tests.csproj | 18 +- ...oposalApprovalTransactionGeneratorTests.cs | 126 +- .../Application/ProposalServiceTests.cs | 243 +- .../Infrastructure/ProposalProviderTests.cs | 104 +- .../ProposalTestBase.cs | 11 +- .../ProposalTestHelper.cs | 57 +- .../ProposalTestModule.cs | 105 +- ...ForCallThreshold.Tests.TestContract.csproj | 6 +- .../Contract.cs | 67 +- .../ContractState.cs | 13 +- ...ecutionPluginForCallThreshold.Tests.csproj | 22 +- .../ExecutionPluginForCallThresholdTest.cs | 416 +- ...ExecutionPluginForCallThresholdTestBase.cs | 241 +- ...ecutionPluginForCallThresholdTestModule.cs | 22 +- ...uginForMethodFee.Tests.TestContract.csproj | 6 +- .../Contract.cs | 31 +- .../ContractState.cs | 11 +- ...EDPoSContractInitializationDataProvider.cs | 23 +- ...t.ExecutionPluginForMethodFee.Tests.csproj | 20 +- .../ExecutePluginTransactionDirectlyTest.cs | 575 +- .../ExecutionPluginForMethodFeeTest.cs | 826 ++- .../ExecutionPluginForMethodFeeTestBase.cs | 426 +- .../ExecutionPluginForMethodFeeTestModule.cs | 125 +- ...ExecutionPluginForMethodFeeWithForkTest.cs | 277 +- ...odFeeTestContractDeploymentListProvider.cs | 17 +- ...dFeeTestGenesisSmartContractDtoProvider.cs | 66 +- ...TestTokenContractInitializationProvider.cs | 65 +- .../MockTransactionGenerator.cs | 65 +- ...lainTransactionExecutingAsPluginService.cs | 178 +- ...inForResourceFee.Tests.TestContract.csproj | 6 +- .../Contract.cs | 113 +- .../ContractState.cs | 19 +- ...ExecutionPluginForResourceFee.Tests.csproj | 22 +- .../ExecutionPluginForResourceFeeTest.cs | 610 +- .../ExecutionPluginForResourceFeeTestBase.cs | 726 +-- ...ExecutionPluginForResourceFeeTestModule.cs | 26 +- ...sourceTokenPluginAndSystemGeneratorTest.cs | 466 +- ...Kernel.SmartContract.Parallel.Tests.csproj | 26 +- ...ingTransactionIdentificationServiceTest.cs | 171 +- .../InternalConstants.cs | 13 +- ...arallelTransactionExecutingServiceTests.cs | 98 +- .../MockBlockchainService.cs | 213 +- .../MockResourceExtractionService.cs | 54 +- .../MockSystemTransactionExtraDataProvider.cs | 36 +- .../NonparallelContractCodeProviderTests.cs | 109 +- .../ParallelExecutionTestBase.cs | 71 +- .../ParallelTestTransactionContextFactory.cs | 61 +- .../ParallelTransactionExecutionTests.cs | 222 +- .../ResourceExtractionServiceTest.cs | 483 +- .../SmartContractParallelTestAElfModule.cs | 14 +- .../SmartContractParallelTestModule.cs | 215 +- .../TransactionGrouperTest.cs | 355 +- ...nsactionWithResourceInfoExtensionsTests.cs | 52 +- .../UnionFindNodeTest.cs | 81 +- ...f.Kernel.SmartContract.Shared.Tests.csproj | 12 +- .../ContextVariableDictionaryTests.cs | 124 +- .../AElf.Kernel.SmartContract.Tests.csproj | 22 +- ...ExecutionObserverThresholdProviderTests.cs | 183 +- .../LogEventProcessingServiceTests.cs | 297 +- .../SmartContractAddressProviderTests.cs | 82 +- .../SmartContractAddressServiceTests.cs | 267 +- .../SmartContractBridgeServiceTests.cs | 141 +- .../SmartContractExecutiveProviderTests.cs | 59 +- .../SmartContractExecutiveServiceTests.cs | 516 +- .../SmartContractRegistrationProviderTests.cs | 92 +- .../Application/SmartContractServiceTests.cs | 162 +- ...StateCacheFromPartialBlockStateSetTests.cs | 81 +- .../StateSizeLimitProviderTests.cs | 133 +- .../Application/TestLogEventProcessor.cs | 68 +- ...ransactionReadOnlyExecutionServiceTests.cs | 349 +- .../ExecutionReturnSetCollectionTests.cs | 109 +- .../Domain/TieredStateCacheTests.cs | 146 +- .../Extension/TaskExtensionTests.cs | 186 +- .../HostSmartContractBridgeContextTests.cs | 453 +- .../SmartContractRunnerContainerTests.cs | 149 +- .../LogEventTestAElfModule.cs | 15 +- .../Sdk/CacheProviderTests.cs | 186 +- .../SmartContractHelper.cs | 181 +- .../SmartContractRunnerTestAElfModule.cs | 36 +- .../SmartContractTestAElfModule.cs | 38 +- .../SmartContractTestBase.cs | 24 +- .../TestSmartContractNameProvider.cs | 15 +- .../UnitTestContractZeroCodeProvider.cs | 30 +- .../Properties/InternalVisibleTo.cs | 2 +- .../TestContract.cs | 13 +- .../TestContractState.cs | 7 +- ...Kernel.SmartContractExecution.Tests.csproj | 18 +- .../Application/BlockAttachServiceTests.cs | 103 +- .../Application/BlockExecutingServiceTests.cs | 235 +- ...ckExecutionResultProcessingServiceTests.cs | 187 +- ...chainExecutingServiceExecuteFailedTests.cs | 79 +- .../FullBlockchainExecutingServiceTests.cs | 139 +- ...xecutingServiceValidateAfterFailedTests.cs | 89 +- .../Application/LogEventProcessorTests.cs | 309 +- ...ontractRegistrationInStateProviderTests.cs | 61 +- .../BlockchainServiceExtensionsTests.cs | 47 +- ...ontractExecutionExecutingTestAElfModule.cs | 250 +- .../SmartContractExecutionHelper.cs | 164 +- .../SmartContractExecutionTestAElfModule.cs | 29 +- .../SmartContractExecutionTestBase.cs | 31 +- test/AElf.Kernel.TestBase/KernelTestHelper.cs | 478 +- test/AElf.Kernel.TestBase/SampleAddress.cs | 47 +- .../TestBaseKernelAElfModule.cs | 21 +- .../AElf.Kernel.Tests.csproj | 24 +- .../BlockTemplateMinerServiceTests.cs | 103 +- ...ConsensusRequestMiningEventHandlerTests.cs | 157 +- .../AElf.Kernel.Tests/KernelTestAElfModule.cs | 231 +- test/AElf.Kernel.Tests/KernelTestBase.cs | 30 +- .../BlockValidationProviderTests.cs | 127 +- .../Miner/Application/MinerServiceTests.cs | 149 +- .../Application/MiningRequestServiceTests.cs | 95 +- .../Miner/Application/MiningServiceTests.cs | 171 +- ...sactionLimitConfigurationProcessorTests.cs | 108 +- .../BlockTransactionLimitProviderTests.cs | 95 +- .../TestBlockExecutingService.cs | 72 +- .../UnitTestContractZeroCodeProvider.cs | 19 +- .../UnitTestSmartContractAddressService.cs | 60 +- .../AElf.Kernel.Token.Tests.csproj | 20 +- .../KernelTokenModule.cs | 15 +- .../KernelTokenTestBase.cs | 8 +- ...TokenContractInitializationDataProvider.cs | 126 +- ...TokenContractInitializationProviderTest.cs | 113 +- .../AElf.Kernel.TransactionPool.Tests.csproj | 18 +- .../BlockchainServiceExtensionsTests.cs | 47 +- .../FakeTransaction.cs | 23 +- ...BasicTransactionValidationProviderTests.cs | 116 +- ...sactionExecutionValidationProviderTests.cs | 220 +- ...ransactionMethodValidationProviderTests.cs | 91 +- .../Infrastructure/TxHubTests.cs | 782 ++- .../TransactionMockExecutionHelper.cs | 23 +- .../TransactionPoolTestAElfModule.cs | 137 +- .../TransactionPoolTestBase.cs | 23 +- .../AElf.Kernel.Types.Tests.csproj | 16 +- .../Block/BlockTests.cs | 334 +- test/AElf.Kernel.Types.Tests/BloomTests.cs | 393 +- .../ChainHelperTests.cs | 41 +- .../SerializationTests.cs | 139 +- .../StateValueTests.cs | 42 +- .../TimestampHelperTest.cs | 55 +- .../TransactionTraceTest.cs | 99 +- .../AElf.OS.Core.Tests.csproj | 18 +- .../NodeEnvironmentServiceTests.cs | 30 +- .../Helpers/OsCoreTestHelper.cs | 55 +- .../NetworkServicePropagationTest.cs | 686 +- .../Application/NetworkServiceTests.cs | 432 +- .../Application/PeerDiscoveryServiceTests.cs | 155 +- ...nvalidTransactionProcessingServiceTests.cs | 143 +- .../PeerReconnectionServiceTests.cs | 162 +- .../Application/SyncStateServiceTests.cs | 305 +- .../Network/Domain/NodeManagerTests.cs | 185 +- .../Helpers/AElfPeerEndpointHelperTests.cs | 53 +- .../Infrastructure/BlackListProviderTests.cs | 127 +- .../DiscoveredNodeCacheProviderTests.cs | 63 +- .../PeerDiscoveryJobProcessorTests.cs | 239 +- .../PeerInvalidTransactionProviderTests.cs | 93 +- .../PeerPoolMaxPeersPerIpAddressTests.cs | 145 +- .../PeerPoolNotLimitMaxPeerTests.cs | 71 +- .../Network/Infrastructure/PeerPoolTests.cs | 406 +- .../PeerReconnectionStateProviderTests.cs | 110 +- .../Network/NetworkInfrastructureTestBase.cs | 27 +- .../NetworkInfrastructureTestModule.cs | 84 +- .../Network/NetworkServiceTestModule.cs | 253 +- .../Network/NetworkTestConstants.cs | 38 +- .../Network/OSCoreHandshakeTestModule.cs | 33 +- .../Network/OSCoreSyncFlagTestModule.cs | 37 +- .../Network/PeerDiscoveryTestModule.cs | 169 +- .../PeerInvalidTransactionTestModule.cs | 66 +- .../Protocol/BlockWithTransactionsTests.cs | 63 +- .../Protocol/HandshakeProviderTests.cs | 128 +- .../Network/TestPeerKeyProvider.cs | 9 +- .../OSCoreTestAElfModule.cs | 88 +- test/AElf.OS.Core.Tests/OSCoreTestBase.cs | 45 +- .../OSCoreWithChainTestAElfModule.cs | 111 +- .../AElf.OS.Network.Grpc.Tests.csproj | 22 +- .../BoundedExpirationCacheTests.cs | 100 +- .../ConnectionServiceBootNodeTests.cs | 41 +- .../Connection/ConnectionServiceTests.cs | 783 ++- .../PeerDialerInvalidHandshakeTests.cs | 30 +- .../Connection/PeerDialerReplyErrorTests.cs | 30 +- .../Connection/PeerDialerTests.cs | 114 +- ...ClientInterceptorContextExtensionsTests.cs | 49 +- .../GrpcNetworkBaseTestModule.cs | 19 +- ...etworkConnectionWithBootNodesTestModule.cs | 29 +- .../GrpcNetworkServerBootNodesTests.cs | 54 +- .../GrpcNetworkServerTests.cs | 210 +- .../GrpcNetworkTestBase.cs | 96 +- .../GrpcNetworkTestModule.cs | 364 +- .../GrpcNetworkWithChainAndPeerTestModule.cs | 34 +- .../GrpcNetworkWithChainTestModule.cs | 34 +- .../GrpcNetworkWithPeerTestModule.cs | 40 +- .../GrpcPeerTests.cs | 744 ++- .../Helpers/GrpcTestPeerHelper.cs | 109 +- .../Helpers/MockServiceBuilder.cs | 280 +- .../Helpers/NetworkTestHelper.cs | 67 +- .../Interceptors/AuthInterceptorTests.cs | 376 +- .../Interceptors/RetryInterceptorTest.cs | 234 +- .../PeerDialerTestModule.cs | 124 +- .../Service/GrpcServerServiceTests.cs | 1245 ++-- test/AElf.OS.TestBase/AElf.OS.TestBase.csproj | 20 +- test/AElf.OS.TestBase/MockTxHub.cs | 142 +- test/AElf.OS.TestBase/OSTestBaseAElfModule.cs | 23 +- test/AElf.OS.TestBase/OSTestHelper.cs | 784 +-- .../TestingSmartContractExecutiveService.cs | 37 +- test/AElf.OS.Tests/AElf.OS.Tests.csproj | 22 +- .../Account/AccountServiceTestAElfModule.cs | 14 +- .../Application/AccountServiceTests.cs | 142 +- .../Infrastructure/AElfKeyStoreTests.cs | 215 +- .../Account/KeyStoreTestAElfModule.cs | 37 +- .../BlockDownloadServiceAbnormalPeerTests.cs | 170 +- .../BlockDownloadServiceRetryTests.cs | 95 +- .../Application/BlockDownloadServiceTests.cs | 327 +- .../BlockFetchServiceAbnormalPeerTests.cs | 47 +- .../Application/BlockFetchServiceTests.cs | 91 +- ...BlockSyncAttachServiceAbnormalPeerTests.cs | 50 +- .../BlockSyncAttachServiceTests.cs | 84 +- .../Application/BlockSyncQueueServiceTests.cs | 141 +- .../Application/BlockSyncServiceTests.cs | 559 +- ...kSyncValidationServiceInvalidBlockTests.cs | 33 +- .../BlockSyncValidationServiceTests.cs | 272 +- .../BlockDownloadWorkerTestAElfModule.cs | 19 +- .../BlockSyncAbnormalPeerTestAElfModule.cs | 151 +- ...ncAttachBlockAbnormalPeerTestAElfModule.cs | 82 +- .../BlockSyncForkedTestAElfModule.cs | 94 +- .../BlockSync/BlockSyncRetryTestAElfModule.cs | 79 +- .../BlockSync/BlockSyncTestAElfModule.cs | 150 +- .../BlockSync/BlockSyncTestBaseAElfModule.cs | 29 +- .../Domain/BlockDownloadJobManagerTests.cs | 69 +- .../AnnouncementCacheProviderTests.cs | 125 +- .../BlockSyncStateProviderTests.cs | 91 +- .../InMemoryBlockDownloadJobStoreTests.cs | 145 +- .../Worker/BlockDownloadWorkerForkedTests.cs | 115 +- .../Worker/BlockDownloadWorkerManyJobTests.cs | 158 +- .../Worker/BlockDownloadWorkerTests.cs | 316 +- .../Handlers/AbnormalPeerEventHandlerTests.cs | 45 +- .../NetworkInitializedEventHandlerTests.cs | 31 +- .../Handlers/OSHandlerTestAElfModule.cs | 14 +- .../PeerConnectedEventHandlerTests.cs | 74 +- test/AElf.OS.Tests/OSTestAElfModule.cs | 85 +- test/AElf.OS.Tests/OSTestBase.cs | 106 +- .../Worker/PeerDiscoveryWorkerTestModule.cs | 59 +- .../Worker/PeerDiscoveryWorkerTests.cs | 229 +- .../Worker/PeerReconnectionTestAElfModule.cs | 24 +- .../Worker/PeerReconnectionWorkerTests.cs | 257 +- .../AElf.Parallel.Tests.csproj | 18 +- ...eleteDataFromStateDbPostExecutionPlugin.cs | 249 +- ...eteDataFromStateDbPreExecutionAcsPlugin.cs | 264 +- .../DeleteDataFromStateDbTest.cs | 5635 +++++++++-------- .../ParallelTestAElfModule.cs | 51 +- .../AElf.Parallel.Tests/ParallelTestHelper.cs | 377 +- .../ParallelTestWithoutFeeAElfModule.cs | 48 +- test/AElf.Parallel.Tests/ParallelTests.cs | 1065 ++-- .../AElf.Runtime.CSharp.Core.Tests.csproj | 20 +- .../CSharpRuntimeCoreTestAElfModule.cs | 10 +- .../CSharpRuntimeCoreTestBase.cs | 8 +- .../ContractCodeLoadContextTests.cs | 47 +- .../SdkStreamManagerTests.cs | 92 +- ...lf.Runtime.CSharp.Tests.BadContract.csproj | 4 +- .../BadCases.cs | 77 +- .../BadContract.cs | 295 +- .../BadContractState.cs | 24 +- .../BadReferences.cs | 64 +- .../FakeExecutionObserverProxy.cs | 31 +- ...f.Runtime.CSharp.Tests.TestContract.csproj | 2 +- .../TestContract.cs | 321 +- .../TestContractState.cs | 43 +- .../AElf.Runtime.CSharp.Tests.csproj | 56 +- .../CSharpRuntimeTestAElfModule.cs | 19 +- .../CSharpRuntimeTestBase.cs | 7 +- .../ExecutiveTests.cs | 361 +- .../ServerCallHandlerTests.cs | 195 +- .../SmartContractRunnerTests.cs | 43 +- .../TokenContractState.cs | 67 +- .../TokenContract_Actions.cs | 115 +- .../TokenContract_Helper.cs | 19 +- .../TokenContract_Views.cs | 113 +- .../AElf.Sdk.CSharp.Tests.csproj | 28 +- test/AElf.Sdk.CSharp.Tests/AElfStringTests.cs | 107 +- .../CSharpSmartContractContextTests.cs | 71 +- test/AElf.Sdk.CSharp.Tests/ContractTest.cs | 379 +- .../ExecutionObserverTests.cs | 63 +- test/AElf.Sdk.CSharp.Tests/MockStates.cs | 61 +- test/AElf.Sdk.CSharp.Tests/SafeMathTests.cs | 102 +- .../SdkCSharpTestBase.cs | 46 +- .../SerializationHelperTests.cs | 234 +- test/AElf.Sdk.CSharp.Tests/StateTest.cs | 662 +- .../TestContractTests.cs | 460 +- .../TestSdkCSharpAElfModule.cs | 41 +- test/AElf.TestBase/AElf.TestBase.csproj | 20 +- test/AElf.TestBase/AElfIntegratedTest.cs | 28 +- test/AElf.TestBase/GlobalUsings.cs | 1 + test/AElf.TestBase/IgnoreOnCIFact.cs | 21 +- test/AElf.TestBase/TestBaseAElfModule.cs | 31 +- test/AElf.Types.Tests/AElf.Types.Tests.csproj | 14 +- test/AElf.Types.Tests/AddressTest.cs | 209 +- test/AElf.Types.Tests/Base58Tests.cs | 119 +- test/AElf.Types.Tests/BinaryMerkleTestTest.cs | 749 ++- .../Extensions/ExtensionTests.cs | 451 +- test/AElf.Types.Tests/HashTests.cs | 178 +- .../Helper/BlockHelperTest.cs | 17 +- .../Helper/ByteArrayHelperTests.cs | 174 +- .../Helper/ByteStringHelperTests.cs | 55 +- .../Helper/ChainHelperTests.cs | 87 +- .../Helper/SerializationHelperTest.cs | 175 +- test/AElf.Types.Tests/ProtobufTests.cs | 47 +- ...AElf.WebApp.Application.Chain.Tests.csproj | 16 +- .../BlockChainAppServiceTest.cs | 2941 +++++---- .../FormatterAndConverterTests.cs | 302 +- .../TransactionToHubTests.cs | 203 +- .../AElf.WebApp.Application.Net.Tests.csproj | 18 +- .../NetAppServiceTest.cs | 372 +- .../AElf.WebApp.Application.TestBase.csproj | 16 +- .../WebAppErrorResponse.cs | 45 +- .../WebAppTestAElfModule.cs | 121 +- .../WebAppTestBase.cs | 6 +- .../WebAppTestStartup.cs | 38 +- 1995 files changed, 131342 insertions(+), 131997 deletions(-) create mode 100644 .idea/.idea.AElf.All/.idea/encodings.xml create mode 100644 .idea/.idea.AElf.All/.idea/indexLayout.xml create mode 100644 .idea/.idea.AElf.All/.idea/projectSettingsUpdater.xml create mode 100644 .idea/.idea.AElf.All/.idea/vcs.xml create mode 100644 .idea/.idea.AElf.All/.idea/workspace.xml create mode 100644 .idea/.idea.AElf.Contracts/.idea/.gitignore create mode 100644 .idea/.idea.AElf.Contracts/.idea/.name create mode 100644 .idea/.idea.AElf.Contracts/.idea/encodings.xml create mode 100644 .idea/.idea.AElf.Contracts/.idea/indexLayout.xml create mode 100644 .idea/.idea.AElf.Contracts/.idea/vcs.xml create mode 100644 .idea/.idea.all/.idea/.name create mode 100644 .idea/.idea.all/.idea/encodings.xml create mode 100644 .idea/.idea.all/.idea/indexLayout.xml create mode 100644 .idea/.idea.all/.idea/projectSettingsUpdater.xml create mode 100644 .idea/.idea.all/.idea/vcs.xml create mode 100644 .idea/.idea.all/.idea/workspace.xml create mode 100644 AElf.All.sln create mode 100644 AElf.Contracts.sln create mode 100644 src/AElf.Kernel.CodeCheck/GlobalUsings.cs create mode 100644 src/AElf.Kernel.Core/GlobalUsings.cs create mode 100644 src/AElf.Kernel/GlobalUsings.cs create mode 100644 test/AElf.Kernel.Core.Tests/AccountTestAElfModule.cs create mode 100644 test/AElf.Kernel.Core.Tests/GlobalUsings.cs create mode 100644 test/AElf.TestBase/GlobalUsings.cs diff --git a/.idea/.idea.AElf.All/.idea/encodings.xml b/.idea/.idea.AElf.All/.idea/encodings.xml new file mode 100644 index 0000000000..df87cf951f --- /dev/null +++ b/.idea/.idea.AElf.All/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.All/.idea/indexLayout.xml b/.idea/.idea.AElf.All/.idea/indexLayout.xml new file mode 100644 index 0000000000..7b08163ceb --- /dev/null +++ b/.idea/.idea.AElf.All/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.All/.idea/projectSettingsUpdater.xml b/.idea/.idea.AElf.All/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..4bb9f4d2a0 --- /dev/null +++ b/.idea/.idea.AElf.All/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.All/.idea/vcs.xml b/.idea/.idea.AElf.All/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/.idea.AElf.All/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.All/.idea/workspace.xml b/.idea/.idea.AElf.All/.idea/workspace.xml new file mode 100644 index 0000000000..1e8756527c --- /dev/null +++ b/.idea/.idea.AElf.All/.idea/workspace.xml @@ -0,0 +1,2120 @@ + + + + src/AElf.Launcher/AElf.Launcher.csproj + bench/AElf.Benchmark/AElf.Benchmark.csproj + src/AElf.ContractDeployer/AElf.ContractDeployer.csproj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1654486994851 + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.Contracts/.idea/.gitignore b/.idea/.idea.AElf.Contracts/.idea/.gitignore new file mode 100644 index 0000000000..91f7f7ca2e --- /dev/null +++ b/.idea/.idea.AElf.Contracts/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/.idea.AElf.Contracts.iml +/modules.xml +/contentModel.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.AElf.Contracts/.idea/.name b/.idea/.idea.AElf.Contracts/.idea/.name new file mode 100644 index 0000000000..2ee594792b --- /dev/null +++ b/.idea/.idea.AElf.Contracts/.idea/.name @@ -0,0 +1 @@ +AElf.Contracts \ No newline at end of file diff --git a/.idea/.idea.AElf.Contracts/.idea/encodings.xml b/.idea/.idea.AElf.Contracts/.idea/encodings.xml new file mode 100644 index 0000000000..df87cf951f --- /dev/null +++ b/.idea/.idea.AElf.Contracts/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.Contracts/.idea/indexLayout.xml b/.idea/.idea.AElf.Contracts/.idea/indexLayout.xml new file mode 100644 index 0000000000..7b08163ceb --- /dev/null +++ b/.idea/.idea.AElf.Contracts/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AElf.Contracts/.idea/vcs.xml b/.idea/.idea.AElf.Contracts/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/.idea.AElf.Contracts/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.all/.idea/.name b/.idea/.idea.all/.idea/.name new file mode 100644 index 0000000000..baa6044435 --- /dev/null +++ b/.idea/.idea.all/.idea/.name @@ -0,0 +1 @@ +all \ No newline at end of file diff --git a/.idea/.idea.all/.idea/encodings.xml b/.idea/.idea.all/.idea/encodings.xml new file mode 100644 index 0000000000..df87cf951f --- /dev/null +++ b/.idea/.idea.all/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.all/.idea/indexLayout.xml b/.idea/.idea.all/.idea/indexLayout.xml new file mode 100644 index 0000000000..7b08163ceb --- /dev/null +++ b/.idea/.idea.all/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.all/.idea/projectSettingsUpdater.xml b/.idea/.idea.all/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..4bb9f4d2a0 --- /dev/null +++ b/.idea/.idea.all/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.all/.idea/vcs.xml b/.idea/.idea.all/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/.idea.all/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.all/.idea/workspace.xml b/.idea/.idea.all/.idea/workspace.xml new file mode 100644 index 0000000000..47dd0ca616 --- /dev/null +++ b/.idea/.idea.all/.idea/workspace.xml @@ -0,0 +1,2113 @@ + + + + src/AElf.Launcher/AElf.Launcher.csproj + bench/AElf.Benchmark/AElf.Benchmark.csproj + src/AElf.ContractDeployer/AElf.ContractDeployer.csproj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "keyToString": { + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "WebServerToolWindowFactoryState": "false", + "nodejs_package_manager_path": "npm", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + + + + 1654264083767 + + + + + + + + + + + + + \ No newline at end of file diff --git a/AElf.All.sln b/AElf.All.sln new file mode 100644 index 0000000000..8d840b719f --- /dev/null +++ b/AElf.All.sln @@ -0,0 +1,1256 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{798BAA50-825B-4DD9-83E2-77A9EE6EBE09}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{4E54480A-D155-43ED-9736-1A5BE7957211}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core", "src\AElf.Kernel.Core\AElf.Kernel.Core.csproj", "{C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core.Tests", "test\AElf.Kernel.Core.Tests\AElf.Kernel.Core.Tests.csproj", "{43CE2CD7-AE6C-4086-8594-7BC82FC83B74}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Core", "src\AElf.OS.Core\AElf.OS.Core.csproj", "{F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Tests", "test\AElf.OS.Tests\AElf.OS.Tests.csproj", "{65480B60-CE71-4486-85F4-EBEF8BEEFD98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database", "src\AElf.Database\AElf.Database.csproj", "{B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database.Tests", "test\AElf.Database.Tests\AElf.Database.Tests.csproj", "{5A9AF758-4ECA-4962-9BBC-3B133D4F221D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cryptography", "src\AElf.Cryptography\AElf.Cryptography.csproj", "{D86E3450-B65D-4999-8C1D-4B1D4403DB51}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cryptography.Tests", "test\AElf.Cryptography.Tests\AElf.Cryptography.Tests.csproj", "{F493AA95-89E6-4F90-BA8F-129A6FE64A6D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Types", "src\AElf.Kernel.Types\AElf.Kernel.Types.csproj", "{DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Genesis.Tests", "test\AElf.Contracts.Genesis.Tests\AElf.Contracts.Genesis.Tests.csproj", "{508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution", "src\AElf.Kernel.SmartContractExecution\AElf.Kernel.SmartContractExecution.csproj", "{7ECFDC4C-4685-40AC-81D5-AB10461D299E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract", "src\AElf.Kernel.SmartContract\AElf.Kernel.SmartContract.csproj", "{05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.ChainController", "src\AElf.Kernel.ChainController\AElf.Kernel.ChainController.csproj", "{74446502-51C1-48EE-BE10-F7B3551005A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Core", "src\AElf.Core\AElf.Core.csproj", "{26287CC7-874E-4C9B-B41C-202511835B95}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp", "src\AElf.Sdk.CSharp\AElf.Sdk.CSharp.csproj", "{4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Core", "src\AElf.CrossChain.Core\AElf.CrossChain.Core.csproj", "{3B20D815-01B9-4EE4-B486-012302AB954E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp.Tests.TestContract", "test\AElf.Sdk.CSharp.Tests.TestContract\AElf.Sdk.CSharp.Tests.TestContract.csproj", "{7B4C527E-B09B-430D-9D93-9C58D78078E1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp.Tests", "test\AElf.Sdk.CSharp.Tests\AElf.Sdk.CSharp.Tests.csproj", "{F3F761B4-914A-4190-93B1-F874CEE9149E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Core", "src\AElf.Runtime.CSharp.Core\AElf.Runtime.CSharp.Core.csproj", "{DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests", "test\AElf.Runtime.CSharp.Tests\AElf.Runtime.CSharp.Tests.csproj", "{D40BEB6B-C370-4A8E-A628-47B6842C975A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TestBase", "test\AElf.TestBase\AElf.TestBase.csproj", "{7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Test.Contracts", "AElf.Test.Contracts", "{D3950CC9-808F-4ED8-946A-79A992F3F8EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestBase", "test\AElf.Contracts.TestBase\AElf.Contracts.TestBase.csproj", "{F7017767-0BD0-4882-948D-E15C6FF7C15D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.RuntimeSetup", "src\AElf.RuntimeSetup\AElf.RuntimeSetup.csproj", "{71DE375A-1037-4CDB-BC7C-6DC454B5D55D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Network.Grpc", "src\AElf.OS.Network.Grpc\AElf.OS.Network.Grpc.csproj", "{6875BAB1-307C-4BF7-A729-5C5F0BED838D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Core", "src\AElf.Kernel.Consensus.Core\AElf.Kernel.Consensus.Core.csproj", "{4F98F0BE-9C2B-4012-AA11-768303C50E46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Types", "src\AElf.Types\AElf.Types.csproj", "{602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.AEDPoS", "src\AElf.Kernel.Consensus.AEDPoS\AElf.Kernel.Consensus.AEDPoS.csproj", "{74FA5F2B-E691-483B-B19E-8DF288C1C04B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TransactionPool", "src\AElf.Kernel.TransactionPool\AElf.Kernel.TransactionPool.csproj", "{A9FD95FA-909C-4396-9DE8-954A1373B351}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel", "src\AElf.Kernel\AElf.Kernel.csproj", "{6127E436-97F1-4824-9FE3-E37A5E1CA916}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Kernel", "AElf.Kernel", "{90B310B4-C2DB-419E-B5EE-97FA096B62CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Genesis", "contract\AElf.Contracts.Genesis\AElf.Contracts.Genesis.csproj", "{B1E39853-406A-4CC7-A273-E70CFEEE3968}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Node", "src\AElf.Kernel.Node\AElf.Kernel.Node.csproj", "{9C7A5377-C2C0-4C33-9087-77FE29462C5E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.OS", "AElf.OS", "{BC510DE7-274F-4C8B-BCBB-A9E18627ED05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.CrossChain", "contract\AElf.Contracts.CrossChain\AElf.Contracts.CrossChain.csproj", "{48D20E4A-51FA-4085-A31E-096A648EB9CF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Types.Tests", "test\AElf.Kernel.Types.Tests\AElf.Kernel.Types.Tests.csproj", "{50659C6B-FDAC-4FA4-97C1-04187499F68D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Types.Tests", "test\AElf.Types.Tests\AElf.Types.Tests.csproj", "{A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution.Tests", "test\AElf.Kernel.SmartContractExecution.Tests\AElf.Kernel.SmartContractExecution.Tests.csproj", "{595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TransactionPool.Tests", "test\AElf.Kernel.TransactionPool.Tests\AElf.Kernel.TransactionPool.Tests.csproj", "{50D47C05-E2ED-459D-9415-4E1B7C024768}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Node.Tests", "test\AElf.Kernel.Node.Tests\AElf.Kernel.Node.Tests.csproj", "{7C7A6E53-F53F-4EFB-90A0-02343961386C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.ChainController.Tests", "test\AElf.Kernel.ChainController.Tests\AElf.Kernel.ChainController.Tests.csproj", "{9E848C22-3975-4898-ABA4-F1B6FEE5335E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.RxNet", "src\AElf.Kernel.Consensus.Scheduler.RxNet\AElf.Kernel.Consensus.Scheduler.RxNet.csproj", "{4BFFFB87-752F-403F-AF77-8B86E3F2D67D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Launcher", "src\AElf.Launcher\AElf.Launcher.csproj", "{2A5C7854-9B98-4798-A9AE-8DC464093B90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Core.Tests", "test\AElf.CrossChain.Core.Tests\AElf.CrossChain.Core.Tests.csproj", "{7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.FluentScheduler", "src\AElf.Kernel.Consensus.Scheduler.FluentScheduler\AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj", "{8B23312F-61B4-4330-900D-280848C2DB4B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Tests", "test\AElf.Kernel.SmartContract.Tests\AElf.Kernel.SmartContract.Tests.csproj", "{7A739BBB-E672-46FA-8AD7-C629A95FFB03}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.CrossChain", "AElf.CrossChain", "{89AC0402-38F7-405C-B244-31C5F13FD364}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestBase.Tests", "test\AElf.Contracts.TestBase.Tests\AElf.Contracts.TestBase.Tests.csproj", "{17CEAE8A-1F06-4027-9183-10901413FBA9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TestBase", "test\AElf.Kernel.TestBase\AElf.Kernel.TestBase.csproj", "{6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Shared", "src\AElf.Kernel.SmartContract.Shared\AElf.Kernel.SmartContract.Shared.csproj", "{35636A23-C51F-4B05-8F1B-AFA435332C46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Grpc", "src\AElf.CrossChain.Grpc\AElf.CrossChain.Grpc.csproj", "{A2B97AF5-E03F-4C37-B44B-3B73C489BF89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Tests", "test\AElf.Kernel.Tests\AElf.Kernel.Tests.csproj", "{DE4395E2-AFC4-415E-A51D-526E472337BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS", "src\AElf.OS\AElf.OS.csproj", "{2A37A558-8BB1-4F8F-8D16-81014B252400}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Core.Tests", "test\AElf.OS.Core.Tests\AElf.OS.Core.Tests.csproj", "{FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp", "src\AElf.Runtime.CSharp\AElf.Runtime.CSharp.csproj", "{BED61A6F-A339-4F33-ADA6-D41DA8251615}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests.TestContract", "test\AElf.Runtime.CSharp.Tests.TestContract\AElf.Runtime.CSharp.Tests.TestContract.csproj", "{9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiToken", "contract\AElf.Contracts.MultiToken\AElf.Contracts.MultiToken.csproj", "{0597D9D4-D2BB-434C-92C4-76266509D021}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.ExecutiveTokenPlugin", "src\AElf.Runtime.CSharp.ExecutiveTokenPlugin\AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj", "{E710F6D7-F087-4815-8906-AE3643E21BAE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cluster", "src\AElf.Cluster\AElf.Cluster.csproj", "{D674C1B1-2E22-416B-AEB8-CA75FA521E51}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.MainChain", "src\AElf.Blockchains.MainChain\AElf.Blockchains.MainChain.csproj", "{6D907620-FE59-4C55-86CD-8299278BC06A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.BasicBaseChain", "src\AElf.Blockchains.BasicBaseChain\AElf.Blockchains.BasicBaseChain.csproj", "{BAE34041-C603-4A7D-BE25-5DD48BD4391E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.SideChain", "src\AElf.Blockchains.SideChain\AElf.Blockchains.SideChain.csproj", "{CB758566-4212-4ECB-8210-2934FAD44941}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Blockchains", "AElf.Blockchains", "{8EF44709-4B5E-489B-A945-EDCB2D1A69C2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.TestBase", "test\AElf.OS.TestBase\AElf.OS.TestBase.csproj", "{BB775A9A-6822-439F-8D03-23F6B6FCF5DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Grpc.Tests", "test\AElf.CrossChain.Grpc.Tests\AElf.CrossChain.Grpc.Tests.csproj", "{FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Network.Grpc.Tests", "test\AElf.OS.Network.Grpc.Tests\AElf.OS.Network.Grpc.Tests.csproj", "{F3B93EF4-C324-44B1-BA33-8F4899131664}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestKit", "src\AElf.ContractTestKit\AElf.ContractTestKit.csproj", "{F4DD898D-0BE8-4873-9532-F1F26DDB3291}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiToken.Tests", "test\AElf.Contracts.MultiToken.Tests\AElf.Contracts.MultiToken.Tests.csproj", "{A526C0D6-1C3E-4570-96EB-AB784AF17835}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter", "contract\AElf.Contracts.TokenConverter\AElf.Contracts.TokenConverter.csproj", "{03EC899C-1FA1-4E98-A821-870F72B48082}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Tests", "test\AElf.Kernel.Consensus.Tests\AElf.Kernel.Consensus.Tests.csproj", "{64D9EC14-36C1-4F98-AF16-3C8A9C601B37}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Core.Tests", "test\AElf.Core.Tests\AElf.Core.Tests.csproj", "{B353DF2E-A7C1-4511-A47E-883CDF938D36}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter.Tests", "test\AElf.Contracts.TokenConverter.Tests\AElf.Contracts.TokenConverter.Tests.csproj", "{BEF12323-63DD-458D-B6E4-4209752ACA69}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.WebApp", "AElf.WebApp", "{13B37500-5DF4-4C64-BD57-2CA6A619596A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Web", "src\AElf.WebApp.Web\AElf.WebApp.Web.csproj", "{B4783569-B72C-4005-B592-F7B444364FD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Core", "src\AElf.WebApp.Application.Core\AElf.WebApp.Application.Core.csproj", "{C047419C-8A70-4533-90E4-1FAE52C141AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Chain", "src\AElf.WebApp.Application.Chain\AElf.WebApp.Application.Chain.csproj", "{139042C5-1BB4-4673-92DE-13A9584B3009}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Net", "src\AElf.WebApp.Application.Net\AElf.WebApp.Application.Net.csproj", "{623C86D3-E93D-404D-8BBD-440BC73D445B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Test.WebApp", "test\AElf.Test.WebApp", "{7190E4AA-10F9-419B-B2A2-A4A745787B3A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.TestBase", "test\AElf.WebApp.Application.TestBase\AElf.WebApp.Application.TestBase.csproj", "{89992897-D2C2-48BE-959B-6E996E82F87F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Chain.Tests", "test\AElf.WebApp.Application.Chain.Tests\AElf.WebApp.Application.Chain.Tests.csproj", "{899AC6DB-FD44-4E7B-89DB-5400891AC80A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Net.Tests", "test\AElf.WebApp.Application.Net.Tests\AElf.WebApp.Application.Net.Tests.csproj", "{BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj", "{A14864DE-5AE8-45D4-8530-BFC40489A155}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj", "{0BB1CAC9-44BB-44CC-871E-E4986A61D548}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Association", "contract\AElf.Contracts.Association\AElf.Contracts.Association.csproj", "{8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Parliament", "contract\AElf.Contracts.Parliament\AElf.Contracts.Parliament.csproj", "{E2F3E423-3593-458B-999A-4371B7B2B192}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj", "{DD0F7490-8BED-4DFD-B717-DC995F4746A0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bench", "bench", "{3099C7ED-AE0A-4670-9DF3-0CBC01D65D10}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.BenchBase", "bench\AElf.BenchBase\AElf.BenchBase.csproj", "{BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database.Benches", "bench\AElf.Database.Benches\AElf.Database.Benches.csproj", "{607F0049-E568-4EA3-9690-3C9961B4D190}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote", "contract\AElf.Contracts.Vote\AElf.Contracts.Vote.csproj", "{1634F9D4-CED2-4621-8D7C-71316642C291}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Election", "contract\AElf.Contracts.Election\AElf.Contracts.Election.csproj", "{347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Referendum", "contract\AElf.Contracts.Referendum\AElf.Contracts.Referendum.csproj", "{8CB61BE4-D787-455B-A4F7-6DCA92F379F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Benchmark", "bench\AElf.Benchmark\AElf.Benchmark.csproj", "{017DC714-0E66-40F4-830B-EB21AF09212A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.Core", "src\AElf.CSharp.Core\AElf.CSharp.Core.csproj", "{550430E8-AA02-4FEE-AC3C-34F18BAA96A4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.Core.Tests", "test\AElf.CSharp.Core.Tests\AElf.CSharp.Core.Tests.csproj", "{0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Election.Tests", "test\AElf.Contracts.Election.Tests\AElf.Contracts.Election.Tests.csproj", "{26D2AE74-DF14-414B-8023-6B3BE79FE3EE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote.Tests", "test\AElf.Contracts.Vote.Tests\AElf.Contracts.Vote.Tests.csproj", "{165D8639-ED9E-4056-BAA2-5AB53491EF25}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Association.Tests", "test\AElf.Contracts.Association.Tests\AElf.Contracts.Association.Tests.csproj", "{0D0F83C6-EB18-4DCE-9191-EF72794B7E58}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Benchmark.PerformanceTestContract", "bench\AElf.Benchmark.PerformanceTestContract\AElf.Benchmark.PerformanceTestContract.csproj", "{288C1125-6D4E-4663-B6AE-34E86386E452}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Profit", "contract\AElf.Contracts.Profit\AElf.Contracts.Profit.csproj", "{111C8C9A-28CA-4FB3-84C3-C12A2693F303}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Consensus.AEDPoS", "contract\AElf.Contracts.Consensus.AEDPoS\AElf.Contracts.Consensus.AEDPoS.csproj", "{0E09CFC2-BEE3-473E-BB88-07AA69D023A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Profit.Tests", "test\AElf.Contracts.Profit.Tests\AElf.Contracts.Profit.Tests.csproj", "{0ECB4B40-2B2B-415E-8FDD-89500A889D26}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Tests", "test\AElf.Contracts.TestContract.Tests\AElf.Contracts.TestContract.Tests.csproj", "{85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Consensus.AEDPoS.Tests", "test\AElf.Contracts.Consensus.AEDPoS.Tests\AElf.Contracts.Consensus.AEDPoS.Tests.csproj", "{5B862F43-7859-4B19-817B-6B673D85E318}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Parliament.Tests", "test\AElf.Contracts.Parliament.Tests\AElf.Contracts.Parliament.Tests.csproj", "{68B98ED7-103C-4DC6-9C89-0B90F2809284}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Referendum.Tests", "test\AElf.Contracts.Referendum.Tests\AElf.Contracts.Referendum.Tests.csproj", "{3B0D744C-AFCD-441A-B960-07273CBAA9EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Token", "src\AElf.Kernel.Token\AElf.Kernel.Token.csproj", "{8981C7F9-9A37-44F3-B4AF-C8C2C635388E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractDeployer", "src\AElf.ContractDeployer\AElf.ContractDeployer.csproj", "{567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter.Internal.Tests", "test\AElf.Contracts.TokenConverter.Internal.Tests\AElf.Contracts.TokenConverter.Internal.Tests.csproj", "{92A51B88-F801-4AA9-A4A6-1F270FF52363}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicFunction", "test\AElf.Contracts.TestContract.BasicFunction\AElf.Contracts.TestContract.BasicFunction.csproj", "{03BE179D-DF33-4909-9373-E49924DB4EA5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicSecurity", "test\AElf.Contracts.TestContract.BasicSecurity\AElf.Contracts.TestContract.BasicSecurity.csproj", "{342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicUpdate", "test\AElf.Contracts.TestContract.BasicUpdate\AElf.Contracts.TestContract.BasicUpdate.csproj", "{BF408F9E-1A91-4C66-B466-A13743E91A6E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests.BadContract", "test\AElf.Runtime.CSharp.Tests.BadContract\AElf.Runtime.CSharp.Tests.BadContract.csproj", "{E770800E-64BC-46A3-A3BA-C9910BB5771C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Parallel", "src\AElf.Kernel.SmartContract.Parallel\AElf.Kernel.SmartContract.Parallel.csproj", "{CF33B86C-3056-49D1-BF23-96E69564337C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.AEDPoS.Tests", "test\AElf.Kernel.Consensus.AEDPoS.Tests\AElf.Kernel.Consensus.AEDPoS.Tests.csproj", "{57F6A337-4B6D-420E-A0FC-62AC057F661C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Parallel.Tests", "test\AElf.Kernel.SmartContract.Parallel.Tests\AElf.Kernel.SmartContract.Parallel.Tests.csproj", "{380A3025-5888-498D-8359-0F63961E7C4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Treasury", "contract\AElf.Contracts.Treasury\AElf.Contracts.Treasury.csproj", "{FF705729-1E79-4736-A1A6-D725B8D6EFA6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.MethodCallThreshold", "test\AElf.Contracts.TestContract.MethodCallThreshold\AElf.Contracts.TestContract.MethodCallThreshold.csproj", "{8E7DE108-9D03-4DD7-A245-D12E9042915C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract", "test\AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract\AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract.csproj", "{2968AA64-9848-4932-A571-39F160166FD7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contract", "contract", "{9AA521A5-80BF-4D20-9339-31D7E86D5868}" +ProjectSection(SolutionItems) = preProject + contract\Directory.Build.props = contract\Directory.Build.props +EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold", "src\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj", "{5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj", "{E5A55EB4-23E3-4968-8D15-8E579F07DF79}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.EconomicSystem.Tests", "test\AElf.Contracts.EconomicSystem.Tests\AElf.Contracts.EconomicSystem.Tests.csproj", "{3C559DFF-17FA-4C86-816E-8CF6B09B6F05}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TransactionFeeCharging", "test\AElf.Contracts.TestContract.TransactionFeeCharging\AElf.Contracts.TestContract.TransactionFeeCharging.csproj", "{E22FFCB1-CC90-42AB-8162-EC904B555AD9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj", "{F0159BE3-115F-408B-9D4F-E296F3592C12}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Configuration", "contract\AElf.Contracts.Configuration\AElf.Contracts.Configuration.csproj", "{A9436A00-8763-4C23-BBE0-BFC6C5B49056}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Configuration.Tests", "test\AElf.Kernel.Configuration.Tests\AElf.Kernel.Configuration.Tests.csproj", "{8024E54C-51C0-48B7-BBE2-CD298F117CA0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Tests", "test\AElf.CrossChain.Tests\AElf.CrossChain.Tests.csproj", "{DFD63F70-CC2D-4971-A0A2-28A3865EBA02}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic", "contract\AElf.Contracts.Economic\AElf.Contracts.Economic.csproj", "{001B9745-C4E7-43A5-BB46-8D3646C695B0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.ResourceSpender", "test\AElf.Contracts.TestContract.ResourceSpender\AElf.Contracts.TestContract.ResourceSpender.csproj", "{778E0253-E1BA-4E72-85AA-F786B5D443C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj", "{6B07E07A-D637-45CC-B629-DE303993309C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj", "{E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj", "{4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic.TestBase", "test\AElf.Contracts.Economic.TestBase\AElf.Contracts.Economic.TestBase.csproj", "{3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestKit.AEDPoSExtension", "src\AElf.ContractTestKit.AEDPoSExtension\AElf.ContractTestKit.AEDPoSExtension.csproj", "{F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote.AEDPoSExtension.Tests", "test\AElf.Contracts.Vote.AEDPoSExtension.Tests\AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj", "{B48EE4A8-8BA9-404E-9839-A2522002FD2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.AEDPoSExtension.Demo.Tests", "test\AElf.Contracts.AEDPoSExtension.Demo.Tests\AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj", "{4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic.AEDPoSExtension.Tests", "test\AElf.Contracts.Economic.AEDPoSExtension.Tests\AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj", "{A33DF532-A418-400F-B803-89AC4C669490}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Parallel.Tests", "test\AElf.Parallel.Tests\AElf.Parallel.Tests.csproj", "{51D379F2-B146-4266-BC1A-C98EBF5C69EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicFunctionWithParallel", "test\AElf.Contracts.TestContract.BasicFunctionWithParallel\AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj", "{D62A334F-6237-4B83-B195-09ED1F25E344}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.CrossChain.Tests", "test\AElf.Contracts.CrossChain.Tests\AElf.Contracts.CrossChain.Tests.csproj", "{D6C0DFE4-0285-465C-A023-27C4493D5E74}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Performance", "test\AElf.Contracts.TestContract.Performance\AElf.Contracts.TestContract.Performance.csproj", "{215B8624-528C-47BE-BF5B-650B41098129}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Configuration.Tests", "test\AElf.Contracts.Configuration.Tests\AElf.Contracts.Configuration.Tests.csproj", "{2911782F-D3A7-42C4-ABE1-501824BC753A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.GenesisUpdate", "test\AElf.Contracts.GenesisUpdate\AElf.Contracts.GenesisUpdate.csproj", "{E208B51B-AD0E-4925-86B3-E35199BFF5C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Events", "test\AElf.Contracts.TestContract.Events\AElf.Contracts.TestContract.Events.csproj", "{10E13977-D3B0-4CA4-964A-76D2E9575936}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TransactionFees", "test\AElf.Contracts.TestContract.TransactionFees\AElf.Contracts.TestContract.TransactionFees.csproj", "{5A32215C-CE76-44B0-BD72-712CFD146852}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps", "src\AElf.CSharp.CodeOps\AElf.CSharp.CodeOps.csproj", "{BD54B7A6-E0E0-4668-9D2B-30EB3F028386}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.Tests", "test\AElf.CSharp.CodeOps.Tests\AElf.CSharp.CodeOps.Tests.csproj", "{8E054D47-BF33-4335-A7D5-084942CFD675}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenHolder", "contract\AElf.Contracts.TokenHolder\AElf.Contracts.TokenHolder.csproj", "{005575E0-4C3E-4F05-9A91-82AC7583D98C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.A", "test\AElf.Contracts.TestContract.A\AElf.Contracts.TestContract.A.csproj", "{87755332-3CAF-4305-BB2E-7470C24DA655}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.B", "test\AElf.Contracts.TestContract.B\AElf.Contracts.TestContract.B.csproj", "{496EAD56-5E85-4C76-B680-7AB268DF44C5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.C", "test\AElf.Contracts.TestContract.C\AElf.Contracts.TestContract.C.csproj", "{6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.DApp", "test\AElf.Contracts.TestContract.DApp\AElf.Contracts.TestContract.DApp.csproj", "{B40C8ADA-0B89-4023-8A16-4462C968A00E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenHolder.Tests", "test\AElf.Contracts.TokenHolder.Tests\AElf.Contracts.TokenHolder.Tests.csproj", "{A3425AC9-6CD0-4D39-B82B-5716456F1C70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.RandomNumberProvider", "test\AElf.Contracts.TestContract.RandomNumberProvider\AElf.Contracts.TestContract.RandomNumberProvider.csproj", "{1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Proposal", "src\AElf.Kernel.Proposal\AElf.Kernel.Proposal.csproj", "{151C28D4-E35D-4C50-BBCE-E664A97E1C44}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.CodeCheck", "src\AElf.Kernel.CodeCheck\AElf.Kernel.CodeCheck.csproj", "{D205205C-FB80-4657-84D2-63B10A4D0D38}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain", "src\AElf.CrossChain\AElf.CrossChain.csproj", "{07A0A8FA-1185-4856-8199-D6668FD08266}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Configuration", "src\AElf.Kernel.Configuration\AElf.Kernel.Configuration.csproj", "{836C5CB0-8BED-408C-9800-4285F539B8CA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeeCalculation", "src\AElf.Kernel.FeeCalculation\AElf.Kernel.FeeCalculation.csproj", "{47997F91-65B1-406B-9DB1-2D0BEBF7F759}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Proposal.Tests", "test\AElf.Kernel.Proposal.Tests\AElf.Kernel.Proposal.Tests.csproj", "{71C2856C-6C23-4F2B-A25B-C3819D2D83C2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeeCalculation.Tests", "test\AElf.Kernel.FeeCalculation.Tests\AElf.Kernel.FeeCalculation.Tests.csproj", "{9C88CD17-D2F3-4B07-95FC-D127497064AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.EconomicSystem", "src\AElf.EconomicSystem\AElf.EconomicSystem.csproj", "{9E9F4889-C62A-470A-A44B-51DA6E6252A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.GovernmentSystem", "src\AElf.GovernmentSystem\AElf.GovernmentSystem.csproj", "{A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestBase", "src\AElf.ContractTestBase\AElf.ContractTestBase.csproj", "{8D614C01-C059-47F1-9D6F-9068E891101D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestBase.Tests", "test\AElf.ContractTestBase.Tests\AElf.ContractTestBase.Tests.csproj", "{8750A2E5-DD57-408D-9EB8-05FD3A6376CD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Shared.Tests", "test\AElf.Kernel.SmartContract.Shared.Tests\AElf.Kernel.SmartContract.Shared.Tests.csproj", "{B1D72EE7-183B-46F8-B365-A5F0B93EC91A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiTokenCrossChainTransfer.Tests", "test\AElf.Contracts.MultiTokenCrossChainTransfer.Tests\AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj", "{850A384F-6226-433F-8777-396A3717F7E0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.EconomicSystem.Tests", "test\AElf.EconomicSystem.Tests\AElf.EconomicSystem.Tests.csproj", "{D0294ECB-E367-4964-887B-21B239F85F09}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.GovernmentSystem.Tests", "test\AElf.GovernmentSystem.Tests\AElf.GovernmentSystem.Tests.csproj", "{A61E0764-D98F-4E38-BB69-8AD4A67CAACB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Token.Tests", "test\AElf.Kernel.Token.Tests\AElf.Kernel.Token.Tests.csproj", "{11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.CodeCheck.Tests", "test\AElf.Kernel.CodeCheck.Tests\AElf.Kernel.CodeCheck.Tests.csproj", "{E9F84A8F-5761-407D-9200-BE8E3493073C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Core.Tests", "test\AElf.Runtime.CSharp.Core.Tests\AElf.Runtime.CSharp.Core.Tests.csproj", "{C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractDeployer.Tests", "test\AElf.ContractDeployer.Tests\AElf.ContractDeployer.Tests.csproj", "{B64C5954-9CC0-4A0B-9453-92324B51C23D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFT", "contract\AElf.Contracts.NFT\AElf.Contracts.NFT.csproj", "{0ECCF46E-3989-4A7E-BA31-4E73D7515578}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFTMarket", "contract\AElf.Contracts.NFTMarket\AElf.Contracts.NFTMarket.csproj", "{4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFT.Tests", "test\AElf.Contracts.NFT.Tests\AElf.Contracts.NFT.Tests.csproj", "{7E07BD13-74BF-4FD7-A294-07E664C47100}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BigIntValue", "test\AElf.Contracts.TestContract.BigIntValue\AElf.Contracts.TestContract.BigIntValue.csproj", "{F50AF512-69E2-46B5-87C6-E058CE2C2D8A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFTMinter", "contract\AElf.Contracts.NFTMinter\AElf.Contracts.NFTMinter.csproj", "{1C0833AE-18DB-4E62-BB0A-226F4555CB09}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeatureManager", "src\AElf.Kernel.FeatureManager\AElf.Kernel.FeatureManager.csproj", "{B24BC602-DAFD-4941-A913-8B0725691681}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeatureManager.Tests", "test\AElf.Kernel.FeatureManager.Tests\AElf.Kernel.FeatureManager.Tests.csproj", "{1B44277E-74EB-49B2-B8FD-05C29EE51985}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Release|Any CPU.Build.0 = Release|Any CPU + {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Release|Any CPU.Build.0 = Release|Any CPU + {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Release|Any CPU.Build.0 = Release|Any CPU + {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Release|Any CPU.Build.0 = Release|Any CPU + {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Release|Any CPU.Build.0 = Release|Any CPU + {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Release|Any CPU.Build.0 = Release|Any CPU + {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Release|Any CPU.Build.0 = Release|Any CPU + {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Release|Any CPU.Build.0 = Release|Any CPU + {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Release|Any CPU.Build.0 = Release|Any CPU + {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Release|Any CPU.Build.0 = Release|Any CPU\ + {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Release|Any CPU.Build.0 = Release|Any CPU + {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Release|Any CPU.Build.0 = Release|Any CPU + {74446502-51C1-48EE-BE10-F7B3551005A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74446502-51C1-48EE-BE10-F7B3551005A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74446502-51C1-48EE-BE10-F7B3551005A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74446502-51C1-48EE-BE10-F7B3551005A5}.Release|Any CPU.Build.0 = Release|Any CPU + {26287CC7-874E-4C9B-B41C-202511835B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26287CC7-874E-4C9B-B41C-202511835B95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26287CC7-874E-4C9B-B41C-202511835B95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26287CC7-874E-4C9B-B41C-202511835B95}.Release|Any CPU.Build.0 = Release|Any CPU + {3B20D815-01B9-4EE4-B486-012302AB954E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B20D815-01B9-4EE4-B486-012302AB954E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B20D815-01B9-4EE4-B486-012302AB954E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B20D815-01B9-4EE4-B486-012302AB954E}.Release|Any CPU.Build.0 = Release|Any CPU + {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Release|Any CPU.Build.0 = Release|Any CPU + {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Release|Any CPU.Build.0 = Release|Any CPU + {F3F761B4-914A-4190-93B1-F874CEE9149E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3F761B4-914A-4190-93B1-F874CEE9149E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3F761B4-914A-4190-93B1-F874CEE9149E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3F761B4-914A-4190-93B1-F874CEE9149E}.Release|Any CPU.Build.0 = Release|Any CPU + {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Release|Any CPU.Build.0 = Release|Any CPU + {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Release|Any CPU.Build.0 = Release|Any CPU + {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Release|Any CPU.Build.0 = Release|Any CPU + {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Release|Any CPU.Build.0 = Release|Any CPU + {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Release|Any CPU.Build.0 = Release|Any CPU + {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Release|Any CPU.Build.0 = Release|Any CPU + {A9FD95FA-909C-4396-9DE8-954A1373B351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9FD95FA-909C-4396-9DE8-954A1373B351}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9FD95FA-909C-4396-9DE8-954A1373B351}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9FD95FA-909C-4396-9DE8-954A1373B351}.Release|Any CPU.Build.0 = Release|Any CPU + {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Release|Any CPU.Build.0 = Release|Any CPU + {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Release|Any CPU.Build.0 = Release|Any CPU + {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Release|Any CPU.Build.0 = Release|Any CPU + {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Release|Any CPU.Build.0 = Release|Any CPU + {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Release|Any CPU.Build.0 = Release|Any CPU + {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Release|Any CPU.Build.0 = Release|Any CPU + {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Release|Any CPU.Build.0 = Release|Any CPU + {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Release|Any CPU.Build.0 = Release|Any CPU + {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Release|Any CPU.Build.0 = Release|Any CPU + {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Release|Any CPU.Build.0 = Release|Any CPU + {50D47C05-E2ED-459D-9415-4E1B7C024768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50D47C05-E2ED-459D-9415-4E1B7C024768}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50D47C05-E2ED-459D-9415-4E1B7C024768}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50D47C05-E2ED-459D-9415-4E1B7C024768}.Release|Any CPU.Build.0 = Release|Any CPU + {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Release|Any CPU.Build.0 = Release|Any CPU + {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Release|Any CPU.Build.0 = Release|Any CPU + {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Release|Any CPU.Build.0 = Release|Any CPU + {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Release|Any CPU.Build.0 = Release|Any CPU + {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Release|Any CPU.Build.0 = Release|Any CPU + {8B23312F-61B4-4330-900D-280848C2DB4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B23312F-61B4-4330-900D-280848C2DB4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B23312F-61B4-4330-900D-280848C2DB4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B23312F-61B4-4330-900D-280848C2DB4B}.Release|Any CPU.Build.0 = Release|Any CPU + {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Release|Any CPU.Build.0 = Release|Any CPU + {17CEAE8A-1F06-4027-9183-10901413FBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17CEAE8A-1F06-4027-9183-10901413FBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17CEAE8A-1F06-4027-9183-10901413FBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17CEAE8A-1F06-4027-9183-10901413FBA9}.Release|Any CPU.Build.0 = Release|Any CPU + {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Release|Any CPU.Build.0 = Release|Any CPU + {35636A23-C51F-4B05-8F1B-AFA435332C46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35636A23-C51F-4B05-8F1B-AFA435332C46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35636A23-C51F-4B05-8F1B-AFA435332C46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35636A23-C51F-4B05-8F1B-AFA435332C46}.Release|Any CPU.Build.0 = Release|Any CPU + {DE4395E2-AFC4-415E-A51D-526E472337BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE4395E2-AFC4-415E-A51D-526E472337BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE4395E2-AFC4-415E-A51D-526E472337BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE4395E2-AFC4-415E-A51D-526E472337BF}.Release|Any CPU.Build.0 = Release|Any CPU + {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Release|Any CPU.Build.0 = Release|Any CPU + {2A37A558-8BB1-4F8F-8D16-81014B252400}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A37A558-8BB1-4F8F-8D16-81014B252400}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A37A558-8BB1-4F8F-8D16-81014B252400}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A37A558-8BB1-4F8F-8D16-81014B252400}.Release|Any CPU.Build.0 = Release|Any CPU + {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Release|Any CPU.Build.0 = Release|Any CPU + {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Release|Any CPU.Build.0 = Release|Any CPU + {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Release|Any CPU.Build.0 = Release|Any CPU + {0597D9D4-D2BB-434C-92C4-76266509D021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0597D9D4-D2BB-434C-92C4-76266509D021}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0597D9D4-D2BB-434C-92C4-76266509D021}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0597D9D4-D2BB-434C-92C4-76266509D021}.Release|Any CPU.Build.0 = Release|Any CPU + {E710F6D7-F087-4815-8906-AE3643E21BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E710F6D7-F087-4815-8906-AE3643E21BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E710F6D7-F087-4815-8906-AE3643E21BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E710F6D7-F087-4815-8906-AE3643E21BAE}.Release|Any CPU.Build.0 = Release|Any CPU + {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Release|Any CPU.Build.0 = Release|Any CPU + {6D907620-FE59-4C55-86CD-8299278BC06A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D907620-FE59-4C55-86CD-8299278BC06A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D907620-FE59-4C55-86CD-8299278BC06A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D907620-FE59-4C55-86CD-8299278BC06A}.Release|Any CPU.Build.0 = Release|Any CPU + {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Release|Any CPU.Build.0 = Release|Any CPU + {CB758566-4212-4ECB-8210-2934FAD44941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB758566-4212-4ECB-8210-2934FAD44941}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB758566-4212-4ECB-8210-2934FAD44941}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB758566-4212-4ECB-8210-2934FAD44941}.Release|Any CPU.Build.0 = Release|Any CPU + {F3B93EF4-C324-44B1-BA33-8F4899131664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3B93EF4-C324-44B1-BA33-8F4899131664}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3B93EF4-C324-44B1-BA33-8F4899131664}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3B93EF4-C324-44B1-BA33-8F4899131664}.Release|Any CPU.Build.0 = Release|Any CPU + {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Release|Any CPU.Build.0 = Release|Any CPU + {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Release|Any CPU.Build.0 = Release|Any CPU + {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Release|Any CPU.Build.0 = Release|Any CPU + {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Release|Any CPU.Build.0 = Release|Any CPU + {03EC899C-1FA1-4E98-A821-870F72B48082}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03EC899C-1FA1-4E98-A821-870F72B48082}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03EC899C-1FA1-4E98-A821-870F72B48082}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03EC899C-1FA1-4E98-A821-870F72B48082}.Release|Any CPU.Build.0 = Release|Any CPU + {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Release|Any CPU.Build.0 = Release|Any CPU + {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Release|Any CPU.Build.0 = Release|Any CPU + {BEF12323-63DD-458D-B6E4-4209752ACA69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BEF12323-63DD-458D-B6E4-4209752ACA69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BEF12323-63DD-458D-B6E4-4209752ACA69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BEF12323-63DD-458D-B6E4-4209752ACA69}.Release|Any CPU.Build.0 = Release|Any CPU + {B4783569-B72C-4005-B592-F7B444364FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4783569-B72C-4005-B592-F7B444364FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4783569-B72C-4005-B592-F7B444364FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4783569-B72C-4005-B592-F7B444364FD2}.Release|Any CPU.Build.0 = Release|Any CPU + {C047419C-8A70-4533-90E4-1FAE52C141AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C047419C-8A70-4533-90E4-1FAE52C141AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C047419C-8A70-4533-90E4-1FAE52C141AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C047419C-8A70-4533-90E4-1FAE52C141AD}.Release|Any CPU.Build.0 = Release|Any CPU + {139042C5-1BB4-4673-92DE-13A9584B3009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {139042C5-1BB4-4673-92DE-13A9584B3009}.Debug|Any CPU.Build.0 = Debug|Any CPU + {139042C5-1BB4-4673-92DE-13A9584B3009}.Release|Any CPU.ActiveCfg = Release|Any CPU + {139042C5-1BB4-4673-92DE-13A9584B3009}.Release|Any CPU.Build.0 = Release|Any CPU + {623C86D3-E93D-404D-8BBD-440BC73D445B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {623C86D3-E93D-404D-8BBD-440BC73D445B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {623C86D3-E93D-404D-8BBD-440BC73D445B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {623C86D3-E93D-404D-8BBD-440BC73D445B}.Release|Any CPU.Build.0 = Release|Any CPU + {89992897-D2C2-48BE-959B-6E996E82F87F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89992897-D2C2-48BE-959B-6E996E82F87F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89992897-D2C2-48BE-959B-6E996E82F87F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89992897-D2C2-48BE-959B-6E996E82F87F}.Release|Any CPU.Build.0 = Release|Any CPU + {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Release|Any CPU.Build.0 = Release|Any CPU + {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Release|Any CPU.Build.0 = Release|Any CPU + {E2F3E423-3593-458B-999A-4371B7B2B192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2F3E423-3593-458B-999A-4371B7B2B192}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2F3E423-3593-458B-999A-4371B7B2B192}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2F3E423-3593-458B-999A-4371B7B2B192}.Release|Any CPU.Build.0 = Release|Any CPU + {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Release|Any CPU.Build.0 = Release|Any CPU + {A14864DE-5AE8-45D4-8530-BFC40489A155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A14864DE-5AE8-45D4-8530-BFC40489A155}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A14864DE-5AE8-45D4-8530-BFC40489A155}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A14864DE-5AE8-45D4-8530-BFC40489A155}.Release|Any CPU.Build.0 = Release|Any CPU + {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Release|Any CPU.Build.0 = Release|Any CPU + {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Release|Any CPU.Build.0 = Release|Any CPU + {1634F9D4-CED2-4621-8D7C-71316642C291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1634F9D4-CED2-4621-8D7C-71316642C291}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1634F9D4-CED2-4621-8D7C-71316642C291}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1634F9D4-CED2-4621-8D7C-71316642C291}.Release|Any CPU.Build.0 = Release|Any CPU + {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Release|Any CPU.Build.0 = Release|Any CPU + {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Release|Any CPU.Build.0 = Release|Any CPU + {607F0049-E568-4EA3-9690-3C9961B4D190}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {607F0049-E568-4EA3-9690-3C9961B4D190}.Debug|Any CPU.Build.0 = Debug|Any CPU + {607F0049-E568-4EA3-9690-3C9961B4D190}.Release|Any CPU.ActiveCfg = Release|Any CPU + {607F0049-E568-4EA3-9690-3C9961B4D190}.Release|Any CPU.Build.0 = Release|Any CPU + {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Release|Any CPU.Build.0 = Release|Any CPU + {017DC714-0E66-40F4-830B-EB21AF09212A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {017DC714-0E66-40F4-830B-EB21AF09212A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {017DC714-0E66-40F4-830B-EB21AF09212A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {017DC714-0E66-40F4-830B-EB21AF09212A}.Release|Any CPU.Build.0 = Release|Any CPU + {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Release|Any CPU.Build.0 = Release|Any CPU + {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Release|Any CPU.Build.0 = Release|Any CPU + {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Release|Any CPU.Build.0 = Release|Any CPU + {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Release|Any CPU.Build.0 = Release|Any CPU + {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Release|Any CPU.Build.0 = Release|Any CPU + {288C1125-6D4E-4663-B6AE-34E86386E452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {288C1125-6D4E-4663-B6AE-34E86386E452}.Debug|Any CPU.Build.0 = Debug|Any CPU + {288C1125-6D4E-4663-B6AE-34E86386E452}.Release|Any CPU.ActiveCfg = Release|Any CPU + {288C1125-6D4E-4663-B6AE-34E86386E452}.Release|Any CPU.Build.0 = Release|Any CPU + {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Debug|Any CPU.Build.0 = Debug|Any CPU + {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Release|Any CPU.ActiveCfg = Release|Any CPU + {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Release|Any CPU.Build.0 = Release|Any CPU + {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Release|Any CPU.Build.0 = Release|Any CPU + {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Release|Any CPU.Build.0 = Release|Any CPU + {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Release|Any CPU.Build.0 = Release|Any CPU + {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Debug|Any CPU.Build.0 = Debug|Any CPU + {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Release|Any CPU.ActiveCfg = Release|Any CPU + {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Release|Any CPU.Build.0 = Release|Any CPU + {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Release|Any CPU.Build.0 = Release|Any CPU + {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Release|Any CPU.Build.0 = Release|Any CPU + {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Release|Any CPU.Build.0 = Release|Any CPU + {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Release|Any CPU.Build.0 = Release|Any CPU + {03BE179D-DF33-4909-9373-E49924DB4EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03BE179D-DF33-4909-9373-E49924DB4EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03BE179D-DF33-4909-9373-E49924DB4EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03BE179D-DF33-4909-9373-E49924DB4EA5}.Release|Any CPU.Build.0 = Release|Any CPU + {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Release|Any CPU.Build.0 = Release|Any CPU + {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Release|Any CPU.Build.0 = Release|Any CPU + {5B862F43-7859-4B19-817B-6B673D85E318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B862F43-7859-4B19-817B-6B673D85E318}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B862F43-7859-4B19-817B-6B673D85E318}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B862F43-7859-4B19-817B-6B673D85E318}.Release|Any CPU.Build.0 = Release|Any CPU + {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Release|Any CPU.Build.0 = Release|Any CPU + {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Release|Any CPU.Build.0 = Release|Any CPU + {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Release|Any CPU.Build.0 = Release|Any CPU + {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Release|Any CPU.Build.0 = Release|Any CPU + {2968AA64-9848-4932-A571-39F160166FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2968AA64-9848-4932-A571-39F160166FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2968AA64-9848-4932-A571-39F160166FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2968AA64-9848-4932-A571-39F160166FD7}.Release|Any CPU.Build.0 = Release|Any CPU + {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Release|Any CPU.Build.0 = Release|Any CPU + {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Release|Any CPU.Build.0 = Release|Any CPU + {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Release|Any CPU.Build.0 = Release|Any CPU + {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Release|Any CPU.Build.0 = Release|Any CPU + {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Release|Any CPU.Build.0 = Release|Any CPU + {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Release|Any CPU.Build.0 = Release|Any CPU + {F0159BE3-115F-408B-9D4F-E296F3592C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0159BE3-115F-408B-9D4F-E296F3592C12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0159BE3-115F-408B-9D4F-E296F3592C12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0159BE3-115F-408B-9D4F-E296F3592C12}.Release|Any CPU.Build.0 = Release|Any CPU + {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Release|Any CPU.Build.0 = Release|Any CPU + {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Release|Any CPU.Build.0 = Release|Any CPU + {6B07E07A-D637-45CC-B629-DE303993309C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B07E07A-D637-45CC-B629-DE303993309C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B07E07A-D637-45CC-B629-DE303993309C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B07E07A-D637-45CC-B629-DE303993309C}.Release|Any CPU.Build.0 = Release|Any CPU + {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Release|Any CPU.Build.0 = Release|Any CPU + {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Release|Any CPU.Build.0 = Release|Any CPU + {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Release|Any CPU.Build.0 = Release|Any CPU + {CF33B86C-3056-49D1-BF23-96E69564337C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF33B86C-3056-49D1-BF23-96E69564337C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF33B86C-3056-49D1-BF23-96E69564337C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF33B86C-3056-49D1-BF23-96E69564337C}.Release|Any CPU.Build.0 = Release|Any CPU + {380A3025-5888-498D-8359-0F63961E7C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {380A3025-5888-498D-8359-0F63961E7C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {380A3025-5888-498D-8359-0F63961E7C4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {380A3025-5888-498D-8359-0F63961E7C4C}.Release|Any CPU.Build.0 = Release|Any CPU + {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Release|Any CPU.Build.0 = Release|Any CPU + {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Release|Any CPU.Build.0 = Release|Any CPU + {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Release|Any CPU.Build.0 = Release|Any CPU + {A33DF532-A418-400F-B803-89AC4C669490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A33DF532-A418-400F-B803-89AC4C669490}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A33DF532-A418-400F-B803-89AC4C669490}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A33DF532-A418-400F-B803-89AC4C669490}.Release|Any CPU.Build.0 = Release|Any CPU + {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Release|Any CPU.Build.0 = Release|Any CPU + {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Release|Any CPU.Build.0 = Release|Any CPU + {D62A334F-6237-4B83-B195-09ED1F25E344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D62A334F-6237-4B83-B195-09ED1F25E344}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D62A334F-6237-4B83-B195-09ED1F25E344}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D62A334F-6237-4B83-B195-09ED1F25E344}.Release|Any CPU.Build.0 = Release|Any CPU + {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Release|Any CPU.Build.0 = Release|Any CPU + {215B8624-528C-47BE-BF5B-650B41098129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {215B8624-528C-47BE-BF5B-650B41098129}.Debug|Any CPU.Build.0 = Debug|Any CPU + {215B8624-528C-47BE-BF5B-650B41098129}.Release|Any CPU.ActiveCfg = Release|Any CPU + {215B8624-528C-47BE-BF5B-650B41098129}.Release|Any CPU.Build.0 = Release|Any CPU + {2911782F-D3A7-42C4-ABE1-501824BC753A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2911782F-D3A7-42C4-ABE1-501824BC753A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2911782F-D3A7-42C4-ABE1-501824BC753A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2911782F-D3A7-42C4-ABE1-501824BC753A}.Release|Any CPU.Build.0 = Release|Any CPU + {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Release|Any CPU.Build.0 = Release|Any CPU + {10E13977-D3B0-4CA4-964A-76D2E9575936}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10E13977-D3B0-4CA4-964A-76D2E9575936}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10E13977-D3B0-4CA4-964A-76D2E9575936}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10E13977-D3B0-4CA4-964A-76D2E9575936}.Release|Any CPU.Build.0 = Release|Any CPU + {5A32215C-CE76-44B0-BD72-712CFD146852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A32215C-CE76-44B0-BD72-712CFD146852}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A32215C-CE76-44B0-BD72-712CFD146852}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A32215C-CE76-44B0-BD72-712CFD146852}.Release|Any CPU.Build.0 = Release|Any CPU + {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Release|Any CPU.Build.0 = Release|Any CPU + {8E054D47-BF33-4335-A7D5-084942CFD675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E054D47-BF33-4335-A7D5-084942CFD675}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E054D47-BF33-4335-A7D5-084942CFD675}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E054D47-BF33-4335-A7D5-084942CFD675}.Release|Any CPU.Build.0 = Release|Any CPU + {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Release|Any CPU.Build.0 = Release|Any CPU + {87755332-3CAF-4305-BB2E-7470C24DA655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87755332-3CAF-4305-BB2E-7470C24DA655}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87755332-3CAF-4305-BB2E-7470C24DA655}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87755332-3CAF-4305-BB2E-7470C24DA655}.Release|Any CPU.Build.0 = Release|Any CPU + {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Release|Any CPU.Build.0 = Release|Any CPU + {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Release|Any CPU.Build.0 = Release|Any CPU + {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Release|Any CPU.Build.0 = Release|Any CPU + {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Release|Any CPU.Build.0 = Release|Any CPU + {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Release|Any CPU.Build.0 = Release|Any CPU + {07A0A8FA-1185-4856-8199-D6668FD08266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07A0A8FA-1185-4856-8199-D6668FD08266}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07A0A8FA-1185-4856-8199-D6668FD08266}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07A0A8FA-1185-4856-8199-D6668FD08266}.Release|Any CPU.Build.0 = Release|Any CPU + {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Debug|Any CPU.Build.0 = Debug|Any CPU + {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Release|Any CPU.ActiveCfg = Release|Any CPU + {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Release|Any CPU.Build.0 = Release|Any CPU + {D205205C-FB80-4657-84D2-63B10A4D0D38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D205205C-FB80-4657-84D2-63B10A4D0D38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D205205C-FB80-4657-84D2-63B10A4D0D38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D205205C-FB80-4657-84D2-63B10A4D0D38}.Release|Any CPU.Build.0 = Release|Any CPU + {836C5CB0-8BED-408C-9800-4285F539B8CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {836C5CB0-8BED-408C-9800-4285F539B8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {836C5CB0-8BED-408C-9800-4285F539B8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {836C5CB0-8BED-408C-9800-4285F539B8CA}.Release|Any CPU.Build.0 = Release|Any CPU + {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Release|Any CPU.Build.0 = Release|Any CPU + {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Release|Any CPU.Build.0 = Release|Any CPU + {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Release|Any CPU.Build.0 = Release|Any CPU + {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Release|Any CPU.Build.0 = Release|Any CPU + {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Release|Any CPU.Build.0 = Release|Any CPU + {8D614C01-C059-47F1-9D6F-9068E891101D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D614C01-C059-47F1-9D6F-9068E891101D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D614C01-C059-47F1-9D6F-9068E891101D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D614C01-C059-47F1-9D6F-9068E891101D}.Release|Any CPU.Build.0 = Release|Any CPU + {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Release|Any CPU.Build.0 = Release|Any CPU + {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Release|Any CPU.Build.0 = Release|Any CPU + {850A384F-6226-433F-8777-396A3717F7E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {850A384F-6226-433F-8777-396A3717F7E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {850A384F-6226-433F-8777-396A3717F7E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {850A384F-6226-433F-8777-396A3717F7E0}.Release|Any CPU.Build.0 = Release|Any CPU + {D0294ECB-E367-4964-887B-21B239F85F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0294ECB-E367-4964-887B-21B239F85F09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0294ECB-E367-4964-887B-21B239F85F09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0294ECB-E367-4964-887B-21B239F85F09}.Release|Any CPU.Build.0 = Release|Any CPU + {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Release|Any CPU.Build.0 = Release|Any CPU + {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Release|Any CPU.Build.0 = Release|Any CPU + {E9F84A8F-5761-407D-9200-BE8E3493073C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9F84A8F-5761-407D-9200-BE8E3493073C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9F84A8F-5761-407D-9200-BE8E3493073C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9F84A8F-5761-407D-9200-BE8E3493073C}.Release|Any CPU.Build.0 = Release|Any CPU + {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Release|Any CPU.Build.0 = Release|Any CPU + {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Release|Any CPU.Build.0 = Release|Any CPU + {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Release|Any CPU.Build.0 = Release|Any CPU + {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Release|Any CPU.Build.0 = Release|Any CPU + {7E07BD13-74BF-4FD7-A294-07E664C47100}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E07BD13-74BF-4FD7-A294-07E664C47100}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E07BD13-74BF-4FD7-A294-07E664C47100}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E07BD13-74BF-4FD7-A294-07E664C47100}.Release|Any CPU.Build.0 = Release|Any CPU + {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Release|Any CPU.Build.0 = Release|Any CPU + {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Release|Any CPU.Build.0 = Release|Any CPU + {B24BC602-DAFD-4941-A913-8B0725691681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B24BC602-DAFD-4941-A913-8B0725691681}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B24BC602-DAFD-4941-A913-8B0725691681}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B24BC602-DAFD-4941-A913-8B0725691681}.Release|Any CPU.Build.0 = Release|Any CPU + {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F7C06F6A-D4FE-4202-B8B8-A593F80AB861} + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F493AA95-89E6-4F90-BA8F-129A6FE64A6D} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {5A9AF758-4ECA-4962-9BBC-3B133D4F221D} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {43CE2CD7-AE6C-4086-8594-7BC82FC83B74} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {65480B60-CE71-4486-85F4-EBEF8BEEFD98} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {7B4C527E-B09B-430D-9D93-9C58D78078E1} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {F3F761B4-914A-4190-93B1-F874CEE9149E} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {D40BEB6B-C370-4A8E-A628-47B6842C975A} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {D3950CC9-808F-4ED8-946A-79A992F3F8EF} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {F7017767-0BD0-4882-948D-E15C6FF7C15D} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {6127E436-97F1-4824-9FE3-E37A5E1CA916} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {74446502-51C1-48EE-BE10-F7B3551005A5} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {7ECFDC4C-4685-40AC-81D5-AB10461D299E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {A9FD95FA-909C-4396-9DE8-954A1373B351} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {B1E39853-406A-4CC7-A273-E70CFEEE3968} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {48D20E4A-51FA-4085-A31E-096A648EB9CF} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {4F98F0BE-9C2B-4012-AA11-768303C50E46} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {74FA5F2B-E691-483B-B19E-8DF288C1C04B} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} + {6875BAB1-307C-4BF7-A729-5C5F0BED838D} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} + {9C7A5377-C2C0-4C33-9087-77FE29462C5E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {50659C6B-FDAC-4FA4-97C1-04187499F68D} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {50D47C05-E2ED-459D-9415-4E1B7C024768} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {7C7A6E53-F53F-4EFB-90A0-02343961386C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {9E848C22-3975-4898-ABA4-F1B6FEE5335E} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {4BFFFB87-752F-403F-AF77-8B86E3F2D67D} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {3B20D815-01B9-4EE4-B486-012302AB954E} = {89AC0402-38F7-405C-B244-31C5F13FD364} + {8B23312F-61B4-4330-900D-280848C2DB4B} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {7A739BBB-E672-46FA-8AD7-C629A95FFB03} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {35636A23-C51F-4B05-8F1B-AFA435332C46} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {DE4395E2-AFC4-415E-A51D-526E472337BF} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {A2B97AF5-E03F-4C37-B44B-3B73C489BF89} = {89AC0402-38F7-405C-B244-31C5F13FD364} + {2A37A558-8BB1-4F8F-8D16-81014B252400} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} + {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {0597D9D4-D2BB-434C-92C4-76266509D021} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {BAE34041-C603-4A7D-BE25-5DD48BD4391E} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} + {6D907620-FE59-4C55-86CD-8299278BC06A} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} + {CB758566-4212-4ECB-8210-2934FAD44941} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} + {F3B93EF4-C324-44B1-BA33-8F4899131664} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {BB775A9A-6822-439F-8D03-23F6B6FCF5DA} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {A526C0D6-1C3E-4570-96EB-AB784AF17835} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {03EC899C-1FA1-4E98-A821-870F72B48082} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {64D9EC14-36C1-4F98-AF16-3C8A9C601B37} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {B353DF2E-A7C1-4511-A47E-883CDF938D36} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {BEF12323-63DD-458D-B6E4-4209752ACA69} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {B4783569-B72C-4005-B592-F7B444364FD2} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} + {C047419C-8A70-4533-90E4-1FAE52C141AD} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} + {139042C5-1BB4-4673-92DE-13A9584B3009} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} + {623C86D3-E93D-404D-8BBD-440BC73D445B} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} + {7190E4AA-10F9-419B-B2A2-A4A745787B3A} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {89992897-D2C2-48BE-959B-6E996E82F87F} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} + {899AC6DB-FD44-4E7B-89DB-5400891AC80A} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} + {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {E2F3E423-3593-458B-999A-4371B7B2B192} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} + {A14864DE-5AE8-45D4-8530-BFC40489A155} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {0BB1CAC9-44BB-44CC-871E-E4986A61D548} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {DD0F7490-8BED-4DFD-B717-DC995F4746A0} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {1634F9D4-CED2-4621-8D7C-71316642C291} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {D674C1B1-2E22-416B-AEB8-CA75FA521E51} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {26287CC7-874E-4C9B-B41C-202511835B95} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {D86E3450-B65D-4999-8C1D-4B1D4403DB51} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {2A5C7854-9B98-4798-A9AE-8DC464093B90} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {BED61A6F-A339-4F33-ADA6-D41DA8251615} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {E710F6D7-F087-4815-8906-AE3643E21BAE} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {71DE375A-1037-4CDB-BC7C-6DC454B5D55D} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {89AC0402-38F7-405C-B244-31C5F13FD364} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {90B310B4-C2DB-419E-B5EE-97FA096B62CC} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {13B37500-5DF4-4C64-BD57-2CA6A619596A} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} + {607F0049-E568-4EA3-9690-3C9961B4D190} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} + {8CB61BE4-D787-455B-A4F7-6DCA92F379F1} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {017DC714-0E66-40F4-830B-EB21AF09212A} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} + {F4DD898D-0BE8-4873-9532-F1F26DDB3291} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {550430E8-AA02-4FEE-AC3C-34F18BAA96A4} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {17CEAE8A-1F06-4027-9183-10901413FBA9} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {26D2AE74-DF14-414B-8023-6B3BE79FE3EE} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {165D8639-ED9E-4056-BAA2-5AB53491EF25} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {0D0F83C6-EB18-4DCE-9191-EF72794B7E58} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {288C1125-6D4E-4663-B6AE-34E86386E452} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} + {111C8C9A-28CA-4FB3-84C3-C12A2693F303} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {0E09CFC2-BEE3-473E-BB88-07AA69D023A8} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {0ECB4B40-2B2B-415E-8FDD-89500A889D26} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {68B98ED7-103C-4DC6-9C89-0B90F2809284} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {3B0D744C-AFCD-441A-B960-07273CBAA9EA} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {5B862F43-7859-4B19-817B-6B673D85E318} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {8981C7F9-9A37-44F3-B4AF-C8C2C635388E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {92A51B88-F801-4AA9-A4A6-1F270FF52363} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {03BE179D-DF33-4909-9373-E49924DB4EA5} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {BF408F9E-1A91-4C66-B466-A13743E91A6E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {E770800E-64BC-46A3-A3BA-C9910BB5771C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {57F6A337-4B6D-420E-A0FC-62AC057F661C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {8E7DE108-9D03-4DD7-A245-D12E9042915C} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {2968AA64-9848-4932-A571-39F160166FD7} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {A9436A00-8763-4C23-BBE0-BFC6C5B49056} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {8024E54C-51C0-48B7-BBE2-CD298F117CA0} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {FF705729-1E79-4736-A1A6-D725B8D6EFA6} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {E5A55EB4-23E3-4968-8D15-8E579F07DF79} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {3C559DFF-17FA-4C86-816E-8CF6B09B6F05} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {E22FFCB1-CC90-42AB-8162-EC904B555AD9} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {F0159BE3-115F-408B-9D4F-E296F3592C12} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {001B9745-C4E7-43A5-BB46-8D3646C695B0} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {778E0253-E1BA-4E72-85AA-F786B5D443C6} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {6B07E07A-D637-45CC-B629-DE303993309C} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {CF33B86C-3056-49D1-BF23-96E69564337C} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {380A3025-5888-498D-8359-0F63961E7C4C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {B48EE4A8-8BA9-404E-9839-A2522002FD2E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {A33DF532-A418-400F-B803-89AC4C669490} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {DFD63F70-CC2D-4971-A0A2-28A3865EBA02} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {51D379F2-B146-4266-BC1A-C98EBF5C69EC} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {D62A334F-6237-4B83-B195-09ED1F25E344} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {D6C0DFE4-0285-465C-A023-27C4493D5E74} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {2911782F-D3A7-42C4-ABE1-501824BC753A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {215B8624-528C-47BE-BF5B-650B41098129} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {E208B51B-AD0E-4925-86B3-E35199BFF5C1} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {10E13977-D3B0-4CA4-964A-76D2E9575936} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {5A32215C-CE76-44B0-BD72-712CFD146852} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {BD54B7A6-E0E0-4668-9D2B-30EB3F028386} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {8E054D47-BF33-4335-A7D5-084942CFD675} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {005575E0-4C3E-4F05-9A91-82AC7583D98C} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {87755332-3CAF-4305-BB2E-7470C24DA655} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {496EAD56-5E85-4C76-B680-7AB268DF44C5} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {B40C8ADA-0B89-4023-8A16-4462C968A00E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {A3425AC9-6CD0-4D39-B82B-5716456F1C70} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {07A0A8FA-1185-4856-8199-D6668FD08266} = {89AC0402-38F7-405C-B244-31C5F13FD364} + {151C28D4-E35D-4C50-BBCE-E664A97E1C44} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {D205205C-FB80-4657-84D2-63B10A4D0D38} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {836C5CB0-8BED-408C-9800-4285F539B8CA} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {47997F91-65B1-406B-9DB1-2D0BEBF7F759} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {71C2856C-6C23-4F2B-A25B-C3819D2D83C2} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {9C88CD17-D2F3-4B07-95FC-D127497064AA} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {9E9F4889-C62A-470A-A44B-51DA6E6252A5} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {8D614C01-C059-47F1-9D6F-9068E891101D} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} + {8750A2E5-DD57-408D-9EB8-05FD3A6376CD} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {B1D72EE7-183B-46F8-B365-A5F0B93EC91A} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {850A384F-6226-433F-8777-396A3717F7E0} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {D0294ECB-E367-4964-887B-21B239F85F09} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {A61E0764-D98F-4E38-BB69-8AD4A67CAACB} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {E9F84A8F-5761-407D-9200-BE8E3493073C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {B64C5954-9CC0-4A0B-9453-92324B51C23D} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {0ECCF46E-3989-4A7E-BA31-4E73D7515578} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {7E07BD13-74BF-4FD7-A294-07E664C47100} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {F50AF512-69E2-46B5-87C6-E058CE2C2D8A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} + {1C0833AE-18DB-4E62-BB0A-226F4555CB09} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} + {B24BC602-DAFD-4941-A913-8B0725691681} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} + {1B44277E-74EB-49B2-B8FD-05C29EE51985} = {4E54480A-D155-43ED-9736-1A5BE7957211} + EndGlobalSection +EndGlobal diff --git a/AElf.Contracts.sln b/AElf.Contracts.sln new file mode 100644 index 0000000000..ac50a9f51e --- /dev/null +++ b/AElf.Contracts.sln @@ -0,0 +1,14 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contract", "contract", "{651F0F6E-86CF-42D2-9110-5F3EAE5704F0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{26990847-E0A2-4FCC-8C71-267CA77557CD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{51CE1A9E-63A0-49C6-B820-C8519C94F389}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/AElf.sln b/AElf.sln index 8d840b719f..05a3fd5aaa 100644 --- a/AElf.sln +++ b/AElf.sln @@ -1,1256 +1,404 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{798BAA50-825B-4DD9-83E2-77A9EE6EBE09}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FAF67841-474B-4087-8C1A-A1F9E2EAD066}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{4E54480A-D155-43ED-9736-1A5BE7957211}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B7751FC6-0B5D-4AD1-93FB-77FF50954BC5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core", "src\AElf.Kernel.Core\AElf.Kernel.Core.csproj", "{C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Blockchains", "AElf.Blockchains", "{398463C0-5870-4F95-B5E9-1F48E30D35C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core.Tests", "test\AElf.Kernel.Core.Tests\AElf.Kernel.Core.Tests.csproj", "{43CE2CD7-AE6C-4086-8594-7BC82FC83B74}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.CrossChain", "AElf.CrossChain", "{4F4757BD-571E-453D-8447-CCBD53FABA9A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Core", "src\AElf.OS.Core\AElf.OS.Core.csproj", "{F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Kernel", "AElf.Kernel", "{50504D10-798D-478E-BE01-EBB979416A11}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Tests", "test\AElf.OS.Tests\AElf.OS.Tests.csproj", "{65480B60-CE71-4486-85F4-EBEF8BEEFD98}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.OS", "AElf.OS", "{8855E0A7-8C0D-4ECC-AB97-D9FCBC30B9C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database", "src\AElf.Database\AElf.Database.csproj", "{B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.WebApp", "AElf.WebApp", "{62C7FEA0-5588-4AD7-A0FC-110544EAE285}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database.Tests", "test\AElf.Database.Tests\AElf.Database.Tests.csproj", "{5A9AF758-4ECA-4962-9BBC-3B133D4F221D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Test.WebApp", "AElf.Test.WebApp", "{56AE29B6-6233-4B1F-848B-079B6CC0A3B0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cryptography", "src\AElf.Cryptography\AElf.Cryptography.csproj", "{D86E3450-B65D-4999-8C1D-4B1D4403DB51}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core", "src\AElf.Kernel.Core\AElf.Kernel.Core.csproj", "{D80FD698-7A0E-4DF2-BD0C-624E924A5D4E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cryptography.Tests", "test\AElf.Cryptography.Tests\AElf.Cryptography.Tests.csproj", "{F493AA95-89E6-4F90-BA8F-129A6FE64A6D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Core.Tests", "test\AElf.Kernel.Core.Tests\AElf.Kernel.Core.Tests.csproj", "{9A5B0538-886A-4DBC-A8BE-A9521D23BD5C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Types", "src\AElf.Kernel.Types\AElf.Kernel.Types.csproj", "{DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TestBase", "test\AElf.TestBase\AElf.TestBase.csproj", "{DB854ADC-6E0D-48F6-B594-2BBD32DC92B9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Genesis.Tests", "test\AElf.Contracts.Genesis.Tests\AElf.Contracts.Genesis.Tests.csproj", "{508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel", "src\AElf.Kernel\AElf.Kernel.csproj", "{10E20EF3-FFC9-45B3-BDBB-749A23297BCC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution", "src\AElf.Kernel.SmartContractExecution\AElf.Kernel.SmartContractExecution.csproj", "{7ECFDC4C-4685-40AC-81D5-AB10461D299E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.ChainController", "src\AElf.Kernel.ChainController\AElf.Kernel.ChainController.csproj", "{09D01D94-3318-482D-A99E-C22BF62A94D5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract", "src\AElf.Kernel.SmartContract\AElf.Kernel.SmartContract.csproj", "{05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.CodeCheck", "src\AElf.Kernel.CodeCheck\AElf.Kernel.CodeCheck.csproj", "{CB4827A7-E3CC-4604-82AC-3E5D18DFD57F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.ChainController", "src\AElf.Kernel.ChainController\AElf.Kernel.ChainController.csproj", "{74446502-51C1-48EE-BE10-F7B3551005A5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Configuration", "src\AElf.Kernel.Configuration\AElf.Kernel.Configuration.csproj", "{0E02293C-8544-4C43-81CE-2E8A416E38BF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Core", "src\AElf.Core\AElf.Core.csproj", "{26287CC7-874E-4C9B-B41C-202511835B95}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.AEDPoS", "src\AElf.Kernel.Consensus.AEDPoS\AElf.Kernel.Consensus.AEDPoS.csproj", "{4E956F38-77A7-445A-B067-BFB123995C4C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp", "src\AElf.Sdk.CSharp\AElf.Sdk.CSharp.csproj", "{4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Core", "src\AElf.Kernel.Consensus.Core\AElf.Kernel.Consensus.Core.csproj", "{5DAB0F25-2DF9-49FA-9966-84CECFE403CA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Core", "src\AElf.CrossChain.Core\AElf.CrossChain.Core.csproj", "{3B20D815-01B9-4EE4-B486-012302AB954E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.FluentScheduler", "src\AElf.Kernel.Consensus.Scheduler.FluentScheduler\AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj", "{B998C279-C62E-4949-92C5-52D4455B4B6F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp.Tests.TestContract", "test\AElf.Sdk.CSharp.Tests.TestContract\AElf.Sdk.CSharp.Tests.TestContract.csproj", "{7B4C527E-B09B-430D-9D93-9C58D78078E1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.RxNet", "src\AElf.Kernel.Consensus.Scheduler.RxNet\AElf.Kernel.Consensus.Scheduler.RxNet.csproj", "{0396B229-C6D6-4CCC-BCD2-0158A93193D3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp.Tests", "test\AElf.Sdk.CSharp.Tests\AElf.Sdk.CSharp.Tests.csproj", "{F3F761B4-914A-4190-93B1-F874CEE9149E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeatureManager", "src\AElf.Kernel.FeatureManager\AElf.Kernel.FeatureManager.csproj", "{CFDA6378-7EA0-4DAB-BE1F-CE10E0072718}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Core", "src\AElf.Runtime.CSharp.Core\AElf.Runtime.CSharp.Core.csproj", "{DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeeCalculation", "src\AElf.Kernel.FeeCalculation\AElf.Kernel.FeeCalculation.csproj", "{7308E633-AA3E-4CB9-87BE-E4345562C45C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests", "test\AElf.Runtime.CSharp.Tests\AElf.Runtime.CSharp.Tests.csproj", "{D40BEB6B-C370-4A8E-A628-47B6842C975A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Node", "src\AElf.Kernel.Node\AElf.Kernel.Node.csproj", "{C0557028-6FC0-4AF4-B362-2F0813C91942}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.TestBase", "test\AElf.TestBase\AElf.TestBase.csproj", "{7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Proposal", "src\AElf.Kernel.Proposal\AElf.Kernel.Proposal.csproj", "{D0899A52-03D7-47AA-BD7F-090586F0776D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Test.Contracts", "AElf.Test.Contracts", "{D3950CC9-808F-4ED8-946A-79A992F3F8EF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract", "src\AElf.Kernel.SmartContract\AElf.Kernel.SmartContract.csproj", "{D95441CB-A6F0-480A-8CAB-4E5A64D66FB9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestBase", "test\AElf.Contracts.TestBase\AElf.Contracts.TestBase.csproj", "{F7017767-0BD0-4882-948D-E15C6FF7C15D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold", "src\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj", "{ABF5DEF1-2613-4465-9A3B-6B2EE4200B87}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.RuntimeSetup", "src\AElf.RuntimeSetup\AElf.RuntimeSetup.csproj", "{71DE375A-1037-4CDB-BC7C-6DC454B5D55D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj", "{2BCA926A-1254-45C8-AD2A-72EAB5523F41}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Network.Grpc", "src\AElf.OS.Network.Grpc\AElf.OS.Network.Grpc.csproj", "{6875BAB1-307C-4BF7-A729-5C5F0BED838D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Parallel", "src\AElf.Kernel.SmartContract.Parallel\AElf.Kernel.SmartContract.Parallel.csproj", "{093E68B5-EC42-4351-8BE2-5A47CA2AB8EC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Core", "src\AElf.Kernel.Consensus.Core\AElf.Kernel.Consensus.Core.csproj", "{4F98F0BE-9C2B-4012-AA11-768303C50E46}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj", "{7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Types", "src\AElf.Types\AElf.Types.csproj", "{602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Shared", "src\AElf.Kernel.SmartContract.Shared\AElf.Kernel.SmartContract.Shared.csproj", "{71663388-D915-4A4E-83DB-AE2140D08D51}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.AEDPoS", "src\AElf.Kernel.Consensus.AEDPoS\AElf.Kernel.Consensus.AEDPoS.csproj", "{74FA5F2B-E691-483B-B19E-8DF288C1C04B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution", "src\AElf.Kernel.SmartContractExecution\AElf.Kernel.SmartContractExecution.csproj", "{AB8997F4-8457-4D9F-91E7-5AFE381A2174}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TransactionPool", "src\AElf.Kernel.TransactionPool\AElf.Kernel.TransactionPool.csproj", "{A9FD95FA-909C-4396-9DE8-954A1373B351}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Token", "src\AElf.Kernel.Token\AElf.Kernel.Token.csproj", "{3210AAC2-FC6A-4CEC-A50E-4119BDE314B6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel", "src\AElf.Kernel\AElf.Kernel.csproj", "{6127E436-97F1-4824-9FE3-E37A5E1CA916}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TransactionPool", "src\AElf.Kernel.TransactionPool\AElf.Kernel.TransactionPool.csproj", "{D165126B-E07E-4082-BA44-DF6496308587}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Kernel", "AElf.Kernel", "{90B310B4-C2DB-419E-B5EE-97FA096B62CC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Types", "src\AElf.Kernel.Types\AElf.Kernel.Types.csproj", "{280453F1-3C62-4CD7-9B6F-1FFE088F312B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Genesis", "contract\AElf.Contracts.Genesis\AElf.Contracts.Genesis.csproj", "{B1E39853-406A-4CC7-A273-E70CFEEE3968}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain", "src\AElf.CrossChain\AElf.CrossChain.csproj", "{2C0712A8-D2F2-4E50-B602-22F86154F6C0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Node", "src\AElf.Kernel.Node\AElf.Kernel.Node.csproj", "{9C7A5377-C2C0-4C33-9087-77FE29462C5E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Core", "src\AElf.CrossChain.Core\AElf.CrossChain.Core.csproj", "{9349308B-EF29-4AA0-9EF9-C3E8D764C2BD}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.OS", "AElf.OS", "{BC510DE7-274F-4C8B-BCBB-A9E18627ED05}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Grpc", "src\AElf.CrossChain.Grpc\AElf.CrossChain.Grpc.csproj", "{4D87024C-330B-44C8-AD91-F0E682A9C4E5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.CrossChain", "contract\AElf.Contracts.CrossChain\AElf.Contracts.CrossChain.csproj", "{48D20E4A-51FA-4085-A31E-096A648EB9CF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.BasicBaseChain", "src\AElf.Blockchains.BasicBaseChain\AElf.Blockchains.BasicBaseChain.csproj", "{2C3D5076-88F5-4912-B8EF-4C049ACED839}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Types.Tests", "test\AElf.Kernel.Types.Tests\AElf.Kernel.Types.Tests.csproj", "{50659C6B-FDAC-4FA4-97C1-04187499F68D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.MainChain", "src\AElf.Blockchains.MainChain\AElf.Blockchains.MainChain.csproj", "{235ACAD6-900E-46FD-8AAF-A711C1F3C9EA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Types.Tests", "test\AElf.Types.Tests\AElf.Types.Tests.csproj", "{A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.SideChain", "src\AElf.Blockchains.SideChain\AElf.Blockchains.SideChain.csproj", "{59DB24D0-1E43-44DA-A7FB-58C320095F33}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution.Tests", "test\AElf.Kernel.SmartContractExecution.Tests\AElf.Kernel.SmartContractExecution.Tests.csproj", "{595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS", "src\AElf.OS\AElf.OS.csproj", "{96743545-B779-4C8D-B5F1-88DE4F21E9FE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TransactionPool.Tests", "test\AElf.Kernel.TransactionPool.Tests\AElf.Kernel.TransactionPool.Tests.csproj", "{50D47C05-E2ED-459D-9415-4E1B7C024768}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Core", "src\AElf.OS.Core\AElf.OS.Core.csproj", "{21F6E2E7-D343-4F2D-A659-00CA82364DB9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Node.Tests", "test\AElf.Kernel.Node.Tests\AElf.Kernel.Node.Tests.csproj", "{7C7A6E53-F53F-4EFB-90A0-02343961386C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Network.Grpc", "src\AElf.OS.Network.Grpc\AElf.OS.Network.Grpc.csproj", "{EED60DD2-4FEC-4EC7-A32A-AE92E441C628}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.ChainController.Tests", "test\AElf.Kernel.ChainController.Tests\AElf.Kernel.ChainController.Tests.csproj", "{9E848C22-3975-4898-ABA4-F1B6FEE5335E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Chain", "src\AElf.WebApp.Application.Chain\AElf.WebApp.Application.Chain.csproj", "{D850E2C3-860C-435C-892E-A7BAD0A12F62}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.RxNet", "src\AElf.Kernel.Consensus.Scheduler.RxNet\AElf.Kernel.Consensus.Scheduler.RxNet.csproj", "{4BFFFB87-752F-403F-AF77-8B86E3F2D67D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Core", "src\AElf.WebApp.Application.Core\AElf.WebApp.Application.Core.csproj", "{E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Launcher", "src\AElf.Launcher\AElf.Launcher.csproj", "{2A5C7854-9B98-4798-A9AE-8DC464093B90}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Net", "src\AElf.WebApp.Application.Net\AElf.WebApp.Application.Net.csproj", "{101756E8-279C-4BE8-8FFF-EBB01729F068}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Core.Tests", "test\AElf.CrossChain.Core.Tests\AElf.CrossChain.Core.Tests.csproj", "{7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Web", "src\AElf.WebApp.Web\AElf.WebApp.Web.csproj", "{158E84D9-7B67-4708-B3C1-A4DC3638053F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Scheduler.FluentScheduler", "src\AElf.Kernel.Consensus.Scheduler.FluentScheduler\AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj", "{8B23312F-61B4-4330-900D-280848C2DB4B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractDeployer", "src\AElf.ContractDeployer\AElf.ContractDeployer.csproj", "{3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Tests", "test\AElf.Kernel.SmartContract.Tests\AElf.Kernel.SmartContract.Tests.csproj", "{7A739BBB-E672-46FA-8AD7-C629A95FFB03}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Core", "src\AElf.Core\AElf.Core.csproj", "{8C2AF2E7-2B40-4C12-B59E-60DEAB029836}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.CrossChain", "AElf.CrossChain", "{89AC0402-38F7-405C-B244-31C5F13FD364}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cryptography", "src\AElf.Cryptography\AElf.Cryptography.csproj", "{081B2111-7CF2-40CB-A89B-31EC77BF1174}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestBase.Tests", "test\AElf.Contracts.TestBase.Tests\AElf.Contracts.TestBase.Tests.csproj", "{17CEAE8A-1F06-4027-9183-10901413FBA9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps", "src\AElf.CSharp.CodeOps\AElf.CSharp.CodeOps.csproj", "{5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.TestBase", "test\AElf.Kernel.TestBase\AElf.Kernel.TestBase.csproj", "{6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.Core", "src\AElf.CSharp.Core\AElf.CSharp.Core.csproj", "{A0267C0D-0713-4C10-A608-CB0009230C43}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Shared", "src\AElf.Kernel.SmartContract.Shared\AElf.Kernel.SmartContract.Shared.csproj", "{35636A23-C51F-4B05-8F1B-AFA435332C46}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database", "src\AElf.Database\AElf.Database.csproj", "{B7E38978-CFAC-4137-8784-2202212CFB81}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Grpc", "src\AElf.CrossChain.Grpc\AElf.CrossChain.Grpc.csproj", "{A2B97AF5-E03F-4C37-B44B-3B73C489BF89}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.EconomicSystem", "src\AElf.EconomicSystem\AElf.EconomicSystem.csproj", "{03349D2D-98EA-421E-A87C-8F5C5C6B9CDD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Tests", "test\AElf.Kernel.Tests\AElf.Kernel.Tests.csproj", "{DE4395E2-AFC4-415E-A51D-526E472337BF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.GovernmentSystem", "src\AElf.GovernmentSystem\AElf.GovernmentSystem.csproj", "{8A28360D-19CE-40A2-9AA1-E187C8328E19}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS", "src\AElf.OS\AElf.OS.csproj", "{2A37A558-8BB1-4F8F-8D16-81014B252400}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Launcher", "src\AElf.Launcher\AElf.Launcher.csproj", "{B47584E3-02B8-4AF4-BC86-1CC92E2A1188}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Core.Tests", "test\AElf.OS.Core.Tests\AElf.OS.Core.Tests.csproj", "{FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp", "src\AElf.Runtime.CSharp\AElf.Runtime.CSharp.csproj", "{050F25D1-A52A-4AB4-9F59-96BCA2C2D354}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp", "src\AElf.Runtime.CSharp\AElf.Runtime.CSharp.csproj", "{BED61A6F-A339-4F33-ADA6-D41DA8251615}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Core", "src\AElf.Runtime.CSharp.Core\AElf.Runtime.CSharp.Core.csproj", "{4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests.TestContract", "test\AElf.Runtime.CSharp.Tests.TestContract\AElf.Runtime.CSharp.Tests.TestContract.csproj", "{9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.ExecutiveTokenPlugin", "src\AElf.Runtime.CSharp.ExecutiveTokenPlugin\AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj", "{1BABD106-C70F-4533-B306-1C13A12083F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiToken", "contract\AElf.Contracts.MultiToken\AElf.Contracts.MultiToken.csproj", "{0597D9D4-D2BB-434C-92C4-76266509D021}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.RuntimeSetup", "src\AElf.RuntimeSetup\AElf.RuntimeSetup.csproj", "{FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.ExecutiveTokenPlugin", "src\AElf.Runtime.CSharp.ExecutiveTokenPlugin\AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj", "{E710F6D7-F087-4815-8906-AE3643E21BAE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Sdk.CSharp", "src\AElf.Sdk.CSharp\AElf.Sdk.CSharp.csproj", "{F45BC4EA-069C-4BA7-9949-C4187737C46A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Cluster", "src\AElf.Cluster\AElf.Cluster.csproj", "{D674C1B1-2E22-416B-AEB8-CA75FA521E51}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.MainChain", "src\AElf.Blockchains.MainChain\AElf.Blockchains.MainChain.csproj", "{6D907620-FE59-4C55-86CD-8299278BC06A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.BasicBaseChain", "src\AElf.Blockchains.BasicBaseChain\AElf.Blockchains.BasicBaseChain.csproj", "{BAE34041-C603-4A7D-BE25-5DD48BD4391E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Blockchains.SideChain", "src\AElf.Blockchains.SideChain\AElf.Blockchains.SideChain.csproj", "{CB758566-4212-4ECB-8210-2934FAD44941}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Blockchains", "AElf.Blockchains", "{8EF44709-4B5E-489B-A945-EDCB2D1A69C2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.TestBase", "test\AElf.OS.TestBase\AElf.OS.TestBase.csproj", "{BB775A9A-6822-439F-8D03-23F6B6FCF5DA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Grpc.Tests", "test\AElf.CrossChain.Grpc.Tests\AElf.CrossChain.Grpc.Tests.csproj", "{FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.OS.Network.Grpc.Tests", "test\AElf.OS.Network.Grpc.Tests\AElf.OS.Network.Grpc.Tests.csproj", "{F3B93EF4-C324-44B1-BA33-8F4899131664}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestKit", "src\AElf.ContractTestKit\AElf.ContractTestKit.csproj", "{F4DD898D-0BE8-4873-9532-F1F26DDB3291}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiToken.Tests", "test\AElf.Contracts.MultiToken.Tests\AElf.Contracts.MultiToken.Tests.csproj", "{A526C0D6-1C3E-4570-96EB-AB784AF17835}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter", "contract\AElf.Contracts.TokenConverter\AElf.Contracts.TokenConverter.csproj", "{03EC899C-1FA1-4E98-A821-870F72B48082}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.Tests", "test\AElf.Kernel.Consensus.Tests\AElf.Kernel.Consensus.Tests.csproj", "{64D9EC14-36C1-4F98-AF16-3C8A9C601B37}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Core.Tests", "test\AElf.Core.Tests\AElf.Core.Tests.csproj", "{B353DF2E-A7C1-4511-A47E-883CDF938D36}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter.Tests", "test\AElf.Contracts.TokenConverter.Tests\AElf.Contracts.TokenConverter.Tests.csproj", "{BEF12323-63DD-458D-B6E4-4209752ACA69}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.WebApp", "AElf.WebApp", "{13B37500-5DF4-4C64-BD57-2CA6A619596A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Web", "src\AElf.WebApp.Web\AElf.WebApp.Web.csproj", "{B4783569-B72C-4005-B592-F7B444364FD2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Core", "src\AElf.WebApp.Application.Core\AElf.WebApp.Application.Core.csproj", "{C047419C-8A70-4533-90E4-1FAE52C141AD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Chain", "src\AElf.WebApp.Application.Chain\AElf.WebApp.Application.Chain.csproj", "{139042C5-1BB4-4673-92DE-13A9584B3009}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Net", "src\AElf.WebApp.Application.Net\AElf.WebApp.Application.Net.csproj", "{623C86D3-E93D-404D-8BBD-440BC73D445B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AElf.Test.WebApp", "test\AElf.Test.WebApp", "{7190E4AA-10F9-419B-B2A2-A4A745787B3A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.TestBase", "test\AElf.WebApp.Application.TestBase\AElf.WebApp.Application.TestBase.csproj", "{89992897-D2C2-48BE-959B-6E996E82F87F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Chain.Tests", "test\AElf.WebApp.Application.Chain.Tests\AElf.WebApp.Application.Chain.Tests.csproj", "{899AC6DB-FD44-4E7B-89DB-5400891AC80A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.WebApp.Application.Net.Tests", "test\AElf.WebApp.Application.Net.Tests\AElf.WebApp.Application.Net.Tests.csproj", "{BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj", "{A14864DE-5AE8-45D4-8530-BFC40489A155}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj", "{0BB1CAC9-44BB-44CC-871E-E4986A61D548}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Association", "contract\AElf.Contracts.Association\AElf.Contracts.Association.csproj", "{8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Parliament", "contract\AElf.Contracts.Parliament\AElf.Contracts.Parliament.csproj", "{E2F3E423-3593-458B-999A-4371B7B2B192}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj", "{DD0F7490-8BED-4DFD-B717-DC995F4746A0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "bench", "bench", "{3099C7ED-AE0A-4670-9DF3-0CBC01D65D10}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.BenchBase", "bench\AElf.BenchBase\AElf.BenchBase.csproj", "{BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Database.Benches", "bench\AElf.Database.Benches\AElf.Database.Benches.csproj", "{607F0049-E568-4EA3-9690-3C9961B4D190}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote", "contract\AElf.Contracts.Vote\AElf.Contracts.Vote.csproj", "{1634F9D4-CED2-4621-8D7C-71316642C291}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Election", "contract\AElf.Contracts.Election\AElf.Contracts.Election.csproj", "{347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Referendum", "contract\AElf.Contracts.Referendum\AElf.Contracts.Referendum.csproj", "{8CB61BE4-D787-455B-A4F7-6DCA92F379F1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Benchmark", "bench\AElf.Benchmark\AElf.Benchmark.csproj", "{017DC714-0E66-40F4-830B-EB21AF09212A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.Core", "src\AElf.CSharp.Core\AElf.CSharp.Core.csproj", "{550430E8-AA02-4FEE-AC3C-34F18BAA96A4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.Core.Tests", "test\AElf.CSharp.Core.Tests\AElf.CSharp.Core.Tests.csproj", "{0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Election.Tests", "test\AElf.Contracts.Election.Tests\AElf.Contracts.Election.Tests.csproj", "{26D2AE74-DF14-414B-8023-6B3BE79FE3EE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote.Tests", "test\AElf.Contracts.Vote.Tests\AElf.Contracts.Vote.Tests.csproj", "{165D8639-ED9E-4056-BAA2-5AB53491EF25}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Association.Tests", "test\AElf.Contracts.Association.Tests\AElf.Contracts.Association.Tests.csproj", "{0D0F83C6-EB18-4DCE-9191-EF72794B7E58}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Benchmark.PerformanceTestContract", "bench\AElf.Benchmark.PerformanceTestContract\AElf.Benchmark.PerformanceTestContract.csproj", "{288C1125-6D4E-4663-B6AE-34E86386E452}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Profit", "contract\AElf.Contracts.Profit\AElf.Contracts.Profit.csproj", "{111C8C9A-28CA-4FB3-84C3-C12A2693F303}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Consensus.AEDPoS", "contract\AElf.Contracts.Consensus.AEDPoS\AElf.Contracts.Consensus.AEDPoS.csproj", "{0E09CFC2-BEE3-473E-BB88-07AA69D023A8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Profit.Tests", "test\AElf.Contracts.Profit.Tests\AElf.Contracts.Profit.Tests.csproj", "{0ECB4B40-2B2B-415E-8FDD-89500A889D26}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Tests", "test\AElf.Contracts.TestContract.Tests\AElf.Contracts.TestContract.Tests.csproj", "{85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Consensus.AEDPoS.Tests", "test\AElf.Contracts.Consensus.AEDPoS.Tests\AElf.Contracts.Consensus.AEDPoS.Tests.csproj", "{5B862F43-7859-4B19-817B-6B673D85E318}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Parliament.Tests", "test\AElf.Contracts.Parliament.Tests\AElf.Contracts.Parliament.Tests.csproj", "{68B98ED7-103C-4DC6-9C89-0B90F2809284}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Referendum.Tests", "test\AElf.Contracts.Referendum.Tests\AElf.Contracts.Referendum.Tests.csproj", "{3B0D744C-AFCD-441A-B960-07273CBAA9EA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Token", "src\AElf.Kernel.Token\AElf.Kernel.Token.csproj", "{8981C7F9-9A37-44F3-B4AF-C8C2C635388E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractDeployer", "src\AElf.ContractDeployer\AElf.ContractDeployer.csproj", "{567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenConverter.Internal.Tests", "test\AElf.Contracts.TokenConverter.Internal.Tests\AElf.Contracts.TokenConverter.Internal.Tests.csproj", "{92A51B88-F801-4AA9-A4A6-1F270FF52363}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicFunction", "test\AElf.Contracts.TestContract.BasicFunction\AElf.Contracts.TestContract.BasicFunction.csproj", "{03BE179D-DF33-4909-9373-E49924DB4EA5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicSecurity", "test\AElf.Contracts.TestContract.BasicSecurity\AElf.Contracts.TestContract.BasicSecurity.csproj", "{342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicUpdate", "test\AElf.Contracts.TestContract.BasicUpdate\AElf.Contracts.TestContract.BasicUpdate.csproj", "{BF408F9E-1A91-4C66-B466-A13743E91A6E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Tests.BadContract", "test\AElf.Runtime.CSharp.Tests.BadContract\AElf.Runtime.CSharp.Tests.BadContract.csproj", "{E770800E-64BC-46A3-A3BA-C9910BB5771C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Parallel", "src\AElf.Kernel.SmartContract.Parallel\AElf.Kernel.SmartContract.Parallel.csproj", "{CF33B86C-3056-49D1-BF23-96E69564337C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Consensus.AEDPoS.Tests", "test\AElf.Kernel.Consensus.AEDPoS.Tests\AElf.Kernel.Consensus.AEDPoS.Tests.csproj", "{57F6A337-4B6D-420E-A0FC-62AC057F661C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Parallel.Tests", "test\AElf.Kernel.SmartContract.Parallel.Tests\AElf.Kernel.SmartContract.Parallel.Tests.csproj", "{380A3025-5888-498D-8359-0F63961E7C4C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Treasury", "contract\AElf.Contracts.Treasury\AElf.Contracts.Treasury.csproj", "{FF705729-1E79-4736-A1A6-D725B8D6EFA6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.MethodCallThreshold", "test\AElf.Contracts.TestContract.MethodCallThreshold\AElf.Contracts.TestContract.MethodCallThreshold.csproj", "{8E7DE108-9D03-4DD7-A245-D12E9042915C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract", "test\AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract\AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract.csproj", "{2968AA64-9848-4932-A571-39F160166FD7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contract", "contract", "{9AA521A5-80BF-4D20-9339-31D7E86D5868}" -ProjectSection(SolutionItems) = preProject - contract\Directory.Build.props = contract\Directory.Build.props -EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold", "src\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj", "{5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj", "{E5A55EB4-23E3-4968-8D15-8E579F07DF79}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.EconomicSystem.Tests", "test\AElf.Contracts.EconomicSystem.Tests\AElf.Contracts.EconomicSystem.Tests.csproj", "{3C559DFF-17FA-4C86-816E-8CF6B09B6F05}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TransactionFeeCharging", "test\AElf.Contracts.TestContract.TransactionFeeCharging\AElf.Contracts.TestContract.TransactionFeeCharging.csproj", "{E22FFCB1-CC90-42AB-8162-EC904B555AD9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests\AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj", "{F0159BE3-115F-408B-9D4F-E296F3592C12}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Configuration", "contract\AElf.Contracts.Configuration\AElf.Contracts.Configuration.csproj", "{A9436A00-8763-4C23-BBE0-BFC6C5B49056}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Configuration.Tests", "test\AElf.Kernel.Configuration.Tests\AElf.Kernel.Configuration.Tests.csproj", "{8024E54C-51C0-48B7-BBE2-CD298F117CA0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain.Tests", "test\AElf.CrossChain.Tests\AElf.CrossChain.Tests.csproj", "{DFD63F70-CC2D-4971-A0A2-28A3865EBA02}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic", "contract\AElf.Contracts.Economic\AElf.Contracts.Economic.csproj", "{001B9745-C4E7-43A5-BB46-8D3646C695B0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.ResourceSpender", "test\AElf.Contracts.TestContract.ResourceSpender\AElf.Contracts.TestContract.ResourceSpender.csproj", "{778E0253-E1BA-4E72-85AA-F786B5D443C6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee", "src\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj", "{6B07E07A-D637-45CC-B629-DE303993309C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj", "{E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests", "test\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests\AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj", "{4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic.TestBase", "test\AElf.Contracts.Economic.TestBase\AElf.Contracts.Economic.TestBase.csproj", "{3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestKit.AEDPoSExtension", "src\AElf.ContractTestKit.AEDPoSExtension\AElf.ContractTestKit.AEDPoSExtension.csproj", "{F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Vote.AEDPoSExtension.Tests", "test\AElf.Contracts.Vote.AEDPoSExtension.Tests\AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj", "{B48EE4A8-8BA9-404E-9839-A2522002FD2E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.AEDPoSExtension.Demo.Tests", "test\AElf.Contracts.AEDPoSExtension.Demo.Tests\AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj", "{4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Economic.AEDPoSExtension.Tests", "test\AElf.Contracts.Economic.AEDPoSExtension.Tests\AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj", "{A33DF532-A418-400F-B803-89AC4C669490}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Parallel.Tests", "test\AElf.Parallel.Tests\AElf.Parallel.Tests.csproj", "{51D379F2-B146-4266-BC1A-C98EBF5C69EC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BasicFunctionWithParallel", "test\AElf.Contracts.TestContract.BasicFunctionWithParallel\AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj", "{D62A334F-6237-4B83-B195-09ED1F25E344}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.CrossChain.Tests", "test\AElf.Contracts.CrossChain.Tests\AElf.Contracts.CrossChain.Tests.csproj", "{D6C0DFE4-0285-465C-A023-27C4493D5E74}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Performance", "test\AElf.Contracts.TestContract.Performance\AElf.Contracts.TestContract.Performance.csproj", "{215B8624-528C-47BE-BF5B-650B41098129}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.Configuration.Tests", "test\AElf.Contracts.Configuration.Tests\AElf.Contracts.Configuration.Tests.csproj", "{2911782F-D3A7-42C4-ABE1-501824BC753A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.GenesisUpdate", "test\AElf.Contracts.GenesisUpdate\AElf.Contracts.GenesisUpdate.csproj", "{E208B51B-AD0E-4925-86B3-E35199BFF5C1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Events", "test\AElf.Contracts.TestContract.Events\AElf.Contracts.TestContract.Events.csproj", "{10E13977-D3B0-4CA4-964A-76D2E9575936}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TransactionFees", "test\AElf.Contracts.TestContract.TransactionFees\AElf.Contracts.TestContract.TransactionFees.csproj", "{5A32215C-CE76-44B0-BD72-712CFD146852}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps", "src\AElf.CSharp.CodeOps\AElf.CSharp.CodeOps.csproj", "{BD54B7A6-E0E0-4668-9D2B-30EB3F028386}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.Tests", "test\AElf.CSharp.CodeOps.Tests\AElf.CSharp.CodeOps.Tests.csproj", "{8E054D47-BF33-4335-A7D5-084942CFD675}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenHolder", "contract\AElf.Contracts.TokenHolder\AElf.Contracts.TokenHolder.csproj", "{005575E0-4C3E-4F05-9A91-82AC7583D98C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.A", "test\AElf.Contracts.TestContract.A\AElf.Contracts.TestContract.A.csproj", "{87755332-3CAF-4305-BB2E-7470C24DA655}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.B", "test\AElf.Contracts.TestContract.B\AElf.Contracts.TestContract.B.csproj", "{496EAD56-5E85-4C76-B680-7AB268DF44C5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.C", "test\AElf.Contracts.TestContract.C\AElf.Contracts.TestContract.C.csproj", "{6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.DApp", "test\AElf.Contracts.TestContract.DApp\AElf.Contracts.TestContract.DApp.csproj", "{B40C8ADA-0B89-4023-8A16-4462C968A00E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TokenHolder.Tests", "test\AElf.Contracts.TokenHolder.Tests\AElf.Contracts.TokenHolder.Tests.csproj", "{A3425AC9-6CD0-4D39-B82B-5716456F1C70}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.RandomNumberProvider", "test\AElf.Contracts.TestContract.RandomNumberProvider\AElf.Contracts.TestContract.RandomNumberProvider.csproj", "{1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Proposal", "src\AElf.Kernel.Proposal\AElf.Kernel.Proposal.csproj", "{151C28D4-E35D-4C50-BBCE-E664A97E1C44}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.CodeCheck", "src\AElf.Kernel.CodeCheck\AElf.Kernel.CodeCheck.csproj", "{D205205C-FB80-4657-84D2-63B10A4D0D38}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CrossChain", "src\AElf.CrossChain\AElf.CrossChain.csproj", "{07A0A8FA-1185-4856-8199-D6668FD08266}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Configuration", "src\AElf.Kernel.Configuration\AElf.Kernel.Configuration.csproj", "{836C5CB0-8BED-408C-9800-4285F539B8CA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeeCalculation", "src\AElf.Kernel.FeeCalculation\AElf.Kernel.FeeCalculation.csproj", "{47997F91-65B1-406B-9DB1-2D0BEBF7F759}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Proposal.Tests", "test\AElf.Kernel.Proposal.Tests\AElf.Kernel.Proposal.Tests.csproj", "{71C2856C-6C23-4F2B-A25B-C3819D2D83C2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeeCalculation.Tests", "test\AElf.Kernel.FeeCalculation.Tests\AElf.Kernel.FeeCalculation.Tests.csproj", "{9C88CD17-D2F3-4B07-95FC-D127497064AA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.EconomicSystem", "src\AElf.EconomicSystem\AElf.EconomicSystem.csproj", "{9E9F4889-C62A-470A-A44B-51DA6E6252A5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.GovernmentSystem", "src\AElf.GovernmentSystem\AElf.GovernmentSystem.csproj", "{A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestBase", "src\AElf.ContractTestBase\AElf.ContractTestBase.csproj", "{8D614C01-C059-47F1-9D6F-9068E891101D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractTestBase.Tests", "test\AElf.ContractTestBase.Tests\AElf.ContractTestBase.Tests.csproj", "{8750A2E5-DD57-408D-9EB8-05FD3A6376CD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.Shared.Tests", "test\AElf.Kernel.SmartContract.Shared.Tests\AElf.Kernel.SmartContract.Shared.Tests.csproj", "{B1D72EE7-183B-46F8-B365-A5F0B93EC91A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.MultiTokenCrossChainTransfer.Tests", "test\AElf.Contracts.MultiTokenCrossChainTransfer.Tests\AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj", "{850A384F-6226-433F-8777-396A3717F7E0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.EconomicSystem.Tests", "test\AElf.EconomicSystem.Tests\AElf.EconomicSystem.Tests.csproj", "{D0294ECB-E367-4964-887B-21B239F85F09}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.GovernmentSystem.Tests", "test\AElf.GovernmentSystem.Tests\AElf.GovernmentSystem.Tests.csproj", "{A61E0764-D98F-4E38-BB69-8AD4A67CAACB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.Token.Tests", "test\AElf.Kernel.Token.Tests\AElf.Kernel.Token.Tests.csproj", "{11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.CodeCheck.Tests", "test\AElf.Kernel.CodeCheck.Tests\AElf.Kernel.CodeCheck.Tests.csproj", "{E9F84A8F-5761-407D-9200-BE8E3493073C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Runtime.CSharp.Core.Tests", "test\AElf.Runtime.CSharp.Core.Tests\AElf.Runtime.CSharp.Core.Tests.csproj", "{C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.ContractDeployer.Tests", "test\AElf.ContractDeployer.Tests\AElf.ContractDeployer.Tests.csproj", "{B64C5954-9CC0-4A0B-9453-92324B51C23D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFT", "contract\AElf.Contracts.NFT\AElf.Contracts.NFT.csproj", "{0ECCF46E-3989-4A7E-BA31-4E73D7515578}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFTMarket", "contract\AElf.Contracts.NFTMarket\AElf.Contracts.NFTMarket.csproj", "{4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFT.Tests", "test\AElf.Contracts.NFT.Tests\AElf.Contracts.NFT.Tests.csproj", "{7E07BD13-74BF-4FD7-A294-07E664C47100}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.BigIntValue", "test\AElf.Contracts.TestContract.BigIntValue\AElf.Contracts.TestContract.BigIntValue.csproj", "{F50AF512-69E2-46B5-87C6-E058CE2C2D8A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.NFTMinter", "contract\AElf.Contracts.NFTMinter\AElf.Contracts.NFTMinter.csproj", "{1C0833AE-18DB-4E62-BB0A-226F4555CB09}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeatureManager", "src\AElf.Kernel.FeatureManager\AElf.Kernel.FeatureManager.csproj", "{B24BC602-DAFD-4941-A913-8B0725691681}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.FeatureManager.Tests", "test\AElf.Kernel.FeatureManager.Tests\AElf.Kernel.FeatureManager.Tests.csproj", "{1B44277E-74EB-49B2-B8FD-05C29EE51985}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Types", "src\AElf.Types\AElf.Types.csproj", "{2F811176-5E40-4F94-ABF9-590C6BADE118}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79}.Release|Any CPU.Build.0 = Release|Any CPU - {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43CE2CD7-AE6C-4086-8594-7BC82FC83B74}.Release|Any CPU.Build.0 = Release|Any CPU - {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C}.Release|Any CPU.Build.0 = Release|Any CPU - {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {65480B60-CE71-4486-85F4-EBEF8BEEFD98}.Release|Any CPU.Build.0 = Release|Any CPU - {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507}.Release|Any CPU.Build.0 = Release|Any CPU - {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5A9AF758-4ECA-4962-9BBC-3B133D4F221D}.Release|Any CPU.Build.0 = Release|Any CPU - {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D86E3450-B65D-4999-8C1D-4B1D4403DB51}.Release|Any CPU.Build.0 = Release|Any CPU - {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F493AA95-89E6-4F90-BA8F-129A6FE64A6D}.Release|Any CPU.Build.0 = Release|Any CPU - {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5}.Release|Any CPU.Build.0 = Release|Any CPU - {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7}.Release|Any CPU.Build.0 = Release|Any CPU\ - {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7ECFDC4C-4685-40AC-81D5-AB10461D299E}.Release|Any CPU.Build.0 = Release|Any CPU - {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A}.Release|Any CPU.Build.0 = Release|Any CPU - {74446502-51C1-48EE-BE10-F7B3551005A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74446502-51C1-48EE-BE10-F7B3551005A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74446502-51C1-48EE-BE10-F7B3551005A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74446502-51C1-48EE-BE10-F7B3551005A5}.Release|Any CPU.Build.0 = Release|Any CPU - {26287CC7-874E-4C9B-B41C-202511835B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26287CC7-874E-4C9B-B41C-202511835B95}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26287CC7-874E-4C9B-B41C-202511835B95}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26287CC7-874E-4C9B-B41C-202511835B95}.Release|Any CPU.Build.0 = Release|Any CPU - {3B20D815-01B9-4EE4-B486-012302AB954E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B20D815-01B9-4EE4-B486-012302AB954E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B20D815-01B9-4EE4-B486-012302AB954E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B20D815-01B9-4EE4-B486-012302AB954E}.Release|Any CPU.Build.0 = Release|Any CPU - {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98}.Release|Any CPU.Build.0 = Release|Any CPU - {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B4C527E-B09B-430D-9D93-9C58D78078E1}.Release|Any CPU.Build.0 = Release|Any CPU - {F3F761B4-914A-4190-93B1-F874CEE9149E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F3F761B4-914A-4190-93B1-F874CEE9149E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F3F761B4-914A-4190-93B1-F874CEE9149E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F3F761B4-914A-4190-93B1-F874CEE9149E}.Release|Any CPU.Build.0 = Release|Any CPU - {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7}.Release|Any CPU.Build.0 = Release|Any CPU - {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D40BEB6B-C370-4A8E-A628-47B6842C975A}.Release|Any CPU.Build.0 = Release|Any CPU - {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5}.Release|Any CPU.Build.0 = Release|Any CPU - {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7017767-0BD0-4882-948D-E15C6FF7C15D}.Release|Any CPU.Build.0 = Release|Any CPU - {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71DE375A-1037-4CDB-BC7C-6DC454B5D55D}.Release|Any CPU.Build.0 = Release|Any CPU - {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3}.Release|Any CPU.Build.0 = Release|Any CPU - {A9FD95FA-909C-4396-9DE8-954A1373B351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9FD95FA-909C-4396-9DE8-954A1373B351}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9FD95FA-909C-4396-9DE8-954A1373B351}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9FD95FA-909C-4396-9DE8-954A1373B351}.Release|Any CPU.Build.0 = Release|Any CPU - {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6875BAB1-307C-4BF7-A729-5C5F0BED838D}.Release|Any CPU.Build.0 = Release|Any CPU - {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6127E436-97F1-4824-9FE3-E37A5E1CA916}.Release|Any CPU.Build.0 = Release|Any CPU - {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1E39853-406A-4CC7-A273-E70CFEEE3968}.Release|Any CPU.Build.0 = Release|Any CPU - {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F98F0BE-9C2B-4012-AA11-768303C50E46}.Release|Any CPU.Build.0 = Release|Any CPU - {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74FA5F2B-E691-483B-B19E-8DF288C1C04B}.Release|Any CPU.Build.0 = Release|Any CPU - {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48D20E4A-51FA-4085-A31E-096A648EB9CF}.Release|Any CPU.Build.0 = Release|Any CPU - {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C7A5377-C2C0-4C33-9087-77FE29462C5E}.Release|Any CPU.Build.0 = Release|Any CPU - {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50659C6B-FDAC-4FA4-97C1-04187499F68D}.Release|Any CPU.Build.0 = Release|Any CPU - {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B}.Release|Any CPU.Build.0 = Release|Any CPU - {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5}.Release|Any CPU.Build.0 = Release|Any CPU - {50D47C05-E2ED-459D-9415-4E1B7C024768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50D47C05-E2ED-459D-9415-4E1B7C024768}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50D47C05-E2ED-459D-9415-4E1B7C024768}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50D47C05-E2ED-459D-9415-4E1B7C024768}.Release|Any CPU.Build.0 = Release|Any CPU - {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C7A6E53-F53F-4EFB-90A0-02343961386C}.Release|Any CPU.Build.0 = Release|Any CPU - {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E848C22-3975-4898-ABA4-F1B6FEE5335E}.Release|Any CPU.Build.0 = Release|Any CPU - {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A5C7854-9B98-4798-A9AE-8DC464093B90}.Release|Any CPU.Build.0 = Release|Any CPU - {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B}.Release|Any CPU.Build.0 = Release|Any CPU - {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4BFFFB87-752F-403F-AF77-8B86E3F2D67D}.Release|Any CPU.Build.0 = Release|Any CPU - {8B23312F-61B4-4330-900D-280848C2DB4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8B23312F-61B4-4330-900D-280848C2DB4B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8B23312F-61B4-4330-900D-280848C2DB4B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8B23312F-61B4-4330-900D-280848C2DB4B}.Release|Any CPU.Build.0 = Release|Any CPU - {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A739BBB-E672-46FA-8AD7-C629A95FFB03}.Release|Any CPU.Build.0 = Release|Any CPU - {17CEAE8A-1F06-4027-9183-10901413FBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {17CEAE8A-1F06-4027-9183-10901413FBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {17CEAE8A-1F06-4027-9183-10901413FBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {17CEAE8A-1F06-4027-9183-10901413FBA9}.Release|Any CPU.Build.0 = Release|Any CPU - {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC}.Release|Any CPU.Build.0 = Release|Any CPU - {35636A23-C51F-4B05-8F1B-AFA435332C46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {35636A23-C51F-4B05-8F1B-AFA435332C46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35636A23-C51F-4B05-8F1B-AFA435332C46}.Release|Any CPU.ActiveCfg = Release|Any CPU - {35636A23-C51F-4B05-8F1B-AFA435332C46}.Release|Any CPU.Build.0 = Release|Any CPU - {DE4395E2-AFC4-415E-A51D-526E472337BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DE4395E2-AFC4-415E-A51D-526E472337BF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DE4395E2-AFC4-415E-A51D-526E472337BF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DE4395E2-AFC4-415E-A51D-526E472337BF}.Release|Any CPU.Build.0 = Release|Any CPU - {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2B97AF5-E03F-4C37-B44B-3B73C489BF89}.Release|Any CPU.Build.0 = Release|Any CPU - {2A37A558-8BB1-4F8F-8D16-81014B252400}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A37A558-8BB1-4F8F-8D16-81014B252400}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A37A558-8BB1-4F8F-8D16-81014B252400}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A37A558-8BB1-4F8F-8D16-81014B252400}.Release|Any CPU.Build.0 = Release|Any CPU - {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F}.Release|Any CPU.Build.0 = Release|Any CPU - {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BED61A6F-A339-4F33-ADA6-D41DA8251615}.Release|Any CPU.Build.0 = Release|Any CPU - {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D}.Release|Any CPU.Build.0 = Release|Any CPU - {0597D9D4-D2BB-434C-92C4-76266509D021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0597D9D4-D2BB-434C-92C4-76266509D021}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0597D9D4-D2BB-434C-92C4-76266509D021}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0597D9D4-D2BB-434C-92C4-76266509D021}.Release|Any CPU.Build.0 = Release|Any CPU - {E710F6D7-F087-4815-8906-AE3643E21BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E710F6D7-F087-4815-8906-AE3643E21BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E710F6D7-F087-4815-8906-AE3643E21BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E710F6D7-F087-4815-8906-AE3643E21BAE}.Release|Any CPU.Build.0 = Release|Any CPU - {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D674C1B1-2E22-416B-AEB8-CA75FA521E51}.Release|Any CPU.Build.0 = Release|Any CPU - {6D907620-FE59-4C55-86CD-8299278BC06A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6D907620-FE59-4C55-86CD-8299278BC06A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D907620-FE59-4C55-86CD-8299278BC06A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6D907620-FE59-4C55-86CD-8299278BC06A}.Release|Any CPU.Build.0 = Release|Any CPU - {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BAE34041-C603-4A7D-BE25-5DD48BD4391E}.Release|Any CPU.Build.0 = Release|Any CPU - {CB758566-4212-4ECB-8210-2934FAD44941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB758566-4212-4ECB-8210-2934FAD44941}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB758566-4212-4ECB-8210-2934FAD44941}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB758566-4212-4ECB-8210-2934FAD44941}.Release|Any CPU.Build.0 = Release|Any CPU - {F3B93EF4-C324-44B1-BA33-8F4899131664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F3B93EF4-C324-44B1-BA33-8F4899131664}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F3B93EF4-C324-44B1-BA33-8F4899131664}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F3B93EF4-C324-44B1-BA33-8F4899131664}.Release|Any CPU.Build.0 = Release|Any CPU - {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB775A9A-6822-439F-8D03-23F6B6FCF5DA}.Release|Any CPU.Build.0 = Release|Any CPU - {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5}.Release|Any CPU.Build.0 = Release|Any CPU - {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F4DD898D-0BE8-4873-9532-F1F26DDB3291}.Release|Any CPU.Build.0 = Release|Any CPU - {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A526C0D6-1C3E-4570-96EB-AB784AF17835}.Release|Any CPU.Build.0 = Release|Any CPU - {03EC899C-1FA1-4E98-A821-870F72B48082}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03EC899C-1FA1-4E98-A821-870F72B48082}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03EC899C-1FA1-4E98-A821-870F72B48082}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03EC899C-1FA1-4E98-A821-870F72B48082}.Release|Any CPU.Build.0 = Release|Any CPU - {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Debug|Any CPU.Build.0 = Debug|Any CPU - {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Release|Any CPU.ActiveCfg = Release|Any CPU - {64D9EC14-36C1-4F98-AF16-3C8A9C601B37}.Release|Any CPU.Build.0 = Release|Any CPU - {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B353DF2E-A7C1-4511-A47E-883CDF938D36}.Release|Any CPU.Build.0 = Release|Any CPU - {BEF12323-63DD-458D-B6E4-4209752ACA69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BEF12323-63DD-458D-B6E4-4209752ACA69}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BEF12323-63DD-458D-B6E4-4209752ACA69}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BEF12323-63DD-458D-B6E4-4209752ACA69}.Release|Any CPU.Build.0 = Release|Any CPU - {B4783569-B72C-4005-B592-F7B444364FD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B4783569-B72C-4005-B592-F7B444364FD2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B4783569-B72C-4005-B592-F7B444364FD2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B4783569-B72C-4005-B592-F7B444364FD2}.Release|Any CPU.Build.0 = Release|Any CPU - {C047419C-8A70-4533-90E4-1FAE52C141AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C047419C-8A70-4533-90E4-1FAE52C141AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C047419C-8A70-4533-90E4-1FAE52C141AD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C047419C-8A70-4533-90E4-1FAE52C141AD}.Release|Any CPU.Build.0 = Release|Any CPU - {139042C5-1BB4-4673-92DE-13A9584B3009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {139042C5-1BB4-4673-92DE-13A9584B3009}.Debug|Any CPU.Build.0 = Debug|Any CPU - {139042C5-1BB4-4673-92DE-13A9584B3009}.Release|Any CPU.ActiveCfg = Release|Any CPU - {139042C5-1BB4-4673-92DE-13A9584B3009}.Release|Any CPU.Build.0 = Release|Any CPU - {623C86D3-E93D-404D-8BBD-440BC73D445B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {623C86D3-E93D-404D-8BBD-440BC73D445B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {623C86D3-E93D-404D-8BBD-440BC73D445B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {623C86D3-E93D-404D-8BBD-440BC73D445B}.Release|Any CPU.Build.0 = Release|Any CPU - {89992897-D2C2-48BE-959B-6E996E82F87F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89992897-D2C2-48BE-959B-6E996E82F87F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89992897-D2C2-48BE-959B-6E996E82F87F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89992897-D2C2-48BE-959B-6E996E82F87F}.Release|Any CPU.Build.0 = Release|Any CPU - {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {899AC6DB-FD44-4E7B-89DB-5400891AC80A}.Release|Any CPU.Build.0 = Release|Any CPU - {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9}.Release|Any CPU.Build.0 = Release|Any CPU - {E2F3E423-3593-458B-999A-4371B7B2B192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E2F3E423-3593-458B-999A-4371B7B2B192}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E2F3E423-3593-458B-999A-4371B7B2B192}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E2F3E423-3593-458B-999A-4371B7B2B192}.Release|Any CPU.Build.0 = Release|Any CPU - {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1}.Release|Any CPU.Build.0 = Release|Any CPU - {A14864DE-5AE8-45D4-8530-BFC40489A155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A14864DE-5AE8-45D4-8530-BFC40489A155}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A14864DE-5AE8-45D4-8530-BFC40489A155}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A14864DE-5AE8-45D4-8530-BFC40489A155}.Release|Any CPU.Build.0 = Release|Any CPU - {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BB1CAC9-44BB-44CC-871E-E4986A61D548}.Release|Any CPU.Build.0 = Release|Any CPU - {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DD0F7490-8BED-4DFD-B717-DC995F4746A0}.Release|Any CPU.Build.0 = Release|Any CPU - {1634F9D4-CED2-4621-8D7C-71316642C291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1634F9D4-CED2-4621-8D7C-71316642C291}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1634F9D4-CED2-4621-8D7C-71316642C291}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1634F9D4-CED2-4621-8D7C-71316642C291}.Release|Any CPU.Build.0 = Release|Any CPU - {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2}.Release|Any CPU.Build.0 = Release|Any CPU - {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3}.Release|Any CPU.Build.0 = Release|Any CPU - {607F0049-E568-4EA3-9690-3C9961B4D190}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {607F0049-E568-4EA3-9690-3C9961B4D190}.Debug|Any CPU.Build.0 = Debug|Any CPU - {607F0049-E568-4EA3-9690-3C9961B4D190}.Release|Any CPU.ActiveCfg = Release|Any CPU - {607F0049-E568-4EA3-9690-3C9961B4D190}.Release|Any CPU.Build.0 = Release|Any CPU - {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8CB61BE4-D787-455B-A4F7-6DCA92F379F1}.Release|Any CPU.Build.0 = Release|Any CPU - {017DC714-0E66-40F4-830B-EB21AF09212A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {017DC714-0E66-40F4-830B-EB21AF09212A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {017DC714-0E66-40F4-830B-EB21AF09212A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {017DC714-0E66-40F4-830B-EB21AF09212A}.Release|Any CPU.Build.0 = Release|Any CPU - {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {550430E8-AA02-4FEE-AC3C-34F18BAA96A4}.Release|Any CPU.Build.0 = Release|Any CPU - {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE}.Release|Any CPU.Build.0 = Release|Any CPU - {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26D2AE74-DF14-414B-8023-6B3BE79FE3EE}.Release|Any CPU.Build.0 = Release|Any CPU - {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Release|Any CPU.ActiveCfg = Release|Any CPU - {165D8639-ED9E-4056-BAA2-5AB53491EF25}.Release|Any CPU.Build.0 = Release|Any CPU - {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0D0F83C6-EB18-4DCE-9191-EF72794B7E58}.Release|Any CPU.Build.0 = Release|Any CPU - {288C1125-6D4E-4663-B6AE-34E86386E452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {288C1125-6D4E-4663-B6AE-34E86386E452}.Debug|Any CPU.Build.0 = Debug|Any CPU - {288C1125-6D4E-4663-B6AE-34E86386E452}.Release|Any CPU.ActiveCfg = Release|Any CPU - {288C1125-6D4E-4663-B6AE-34E86386E452}.Release|Any CPU.Build.0 = Release|Any CPU - {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Debug|Any CPU.Build.0 = Debug|Any CPU - {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Release|Any CPU.ActiveCfg = Release|Any CPU - {111C8C9A-28CA-4FB3-84C3-C12A2693F303}.Release|Any CPU.Build.0 = Release|Any CPU - {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E09CFC2-BEE3-473E-BB88-07AA69D023A8}.Release|Any CPU.Build.0 = Release|Any CPU - {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0ECB4B40-2B2B-415E-8FDD-89500A889D26}.Release|Any CPU.Build.0 = Release|Any CPU - {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8}.Release|Any CPU.Build.0 = Release|Any CPU - {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Debug|Any CPU.Build.0 = Debug|Any CPU - {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Release|Any CPU.ActiveCfg = Release|Any CPU - {68B98ED7-103C-4DC6-9C89-0B90F2809284}.Release|Any CPU.Build.0 = Release|Any CPU - {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3B0D744C-AFCD-441A-B960-07273CBAA9EA}.Release|Any CPU.Build.0 = Release|Any CPU - {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8981C7F9-9A37-44F3-B4AF-C8C2C635388E}.Release|Any CPU.Build.0 = Release|Any CPU - {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C}.Release|Any CPU.Build.0 = Release|Any CPU - {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Debug|Any CPU.Build.0 = Debug|Any CPU - {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Release|Any CPU.ActiveCfg = Release|Any CPU - {92A51B88-F801-4AA9-A4A6-1F270FF52363}.Release|Any CPU.Build.0 = Release|Any CPU - {03BE179D-DF33-4909-9373-E49924DB4EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {03BE179D-DF33-4909-9373-E49924DB4EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {03BE179D-DF33-4909-9373-E49924DB4EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {03BE179D-DF33-4909-9373-E49924DB4EA5}.Release|Any CPU.Build.0 = Release|Any CPU - {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Debug|Any CPU.Build.0 = Debug|Any CPU - {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Release|Any CPU.ActiveCfg = Release|Any CPU - {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85}.Release|Any CPU.Build.0 = Release|Any CPU - {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF408F9E-1A91-4C66-B466-A13743E91A6E}.Release|Any CPU.Build.0 = Release|Any CPU - {5B862F43-7859-4B19-817B-6B673D85E318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B862F43-7859-4B19-817B-6B673D85E318}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B862F43-7859-4B19-817B-6B673D85E318}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B862F43-7859-4B19-817B-6B673D85E318}.Release|Any CPU.Build.0 = Release|Any CPU - {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E770800E-64BC-46A3-A3BA-C9910BB5771C}.Release|Any CPU.Build.0 = Release|Any CPU - {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {57F6A337-4B6D-420E-A0FC-62AC057F661C}.Release|Any CPU.Build.0 = Release|Any CPU - {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF705729-1E79-4736-A1A6-D725B8D6EFA6}.Release|Any CPU.Build.0 = Release|Any CPU - {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8E7DE108-9D03-4DD7-A245-D12E9042915C}.Release|Any CPU.Build.0 = Release|Any CPU - {2968AA64-9848-4932-A571-39F160166FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2968AA64-9848-4932-A571-39F160166FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2968AA64-9848-4932-A571-39F160166FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2968AA64-9848-4932-A571-39F160166FD7}.Release|Any CPU.Build.0 = Release|Any CPU - {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9436A00-8763-4C23-BBE0-BFC6C5B49056}.Release|Any CPU.Build.0 = Release|Any CPU - {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8024E54C-51C0-48B7-BBE2-CD298F117CA0}.Release|Any CPU.Build.0 = Release|Any CPU - {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD}.Release|Any CPU.Build.0 = Release|Any CPU - {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5A55EB4-23E3-4968-8D15-8E579F07DF79}.Release|Any CPU.Build.0 = Release|Any CPU - {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C559DFF-17FA-4C86-816E-8CF6B09B6F05}.Release|Any CPU.Build.0 = Release|Any CPU - {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E22FFCB1-CC90-42AB-8162-EC904B555AD9}.Release|Any CPU.Build.0 = Release|Any CPU - {F0159BE3-115F-408B-9D4F-E296F3592C12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0159BE3-115F-408B-9D4F-E296F3592C12}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0159BE3-115F-408B-9D4F-E296F3592C12}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0159BE3-115F-408B-9D4F-E296F3592C12}.Release|Any CPU.Build.0 = Release|Any CPU - {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {001B9745-C4E7-43A5-BB46-8D3646C695B0}.Release|Any CPU.Build.0 = Release|Any CPU - {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {778E0253-E1BA-4E72-85AA-F786B5D443C6}.Release|Any CPU.Build.0 = Release|Any CPU - {6B07E07A-D637-45CC-B629-DE303993309C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B07E07A-D637-45CC-B629-DE303993309C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B07E07A-D637-45CC-B629-DE303993309C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B07E07A-D637-45CC-B629-DE303993309C}.Release|Any CPU.Build.0 = Release|Any CPU - {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD}.Release|Any CPU.Build.0 = Release|Any CPU - {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3}.Release|Any CPU.Build.0 = Release|Any CPU - {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3}.Release|Any CPU.Build.0 = Release|Any CPU - {CF33B86C-3056-49D1-BF23-96E69564337C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF33B86C-3056-49D1-BF23-96E69564337C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF33B86C-3056-49D1-BF23-96E69564337C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF33B86C-3056-49D1-BF23-96E69564337C}.Release|Any CPU.Build.0 = Release|Any CPU - {380A3025-5888-498D-8359-0F63961E7C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {380A3025-5888-498D-8359-0F63961E7C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {380A3025-5888-498D-8359-0F63961E7C4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {380A3025-5888-498D-8359-0F63961E7C4C}.Release|Any CPU.Build.0 = Release|Any CPU - {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2}.Release|Any CPU.Build.0 = Release|Any CPU - {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B48EE4A8-8BA9-404E-9839-A2522002FD2E}.Release|Any CPU.Build.0 = Release|Any CPU - {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A}.Release|Any CPU.Build.0 = Release|Any CPU - {A33DF532-A418-400F-B803-89AC4C669490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A33DF532-A418-400F-B803-89AC4C669490}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A33DF532-A418-400F-B803-89AC4C669490}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A33DF532-A418-400F-B803-89AC4C669490}.Release|Any CPU.Build.0 = Release|Any CPU - {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFD63F70-CC2D-4971-A0A2-28A3865EBA02}.Release|Any CPU.Build.0 = Release|Any CPU - {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {51D379F2-B146-4266-BC1A-C98EBF5C69EC}.Release|Any CPU.Build.0 = Release|Any CPU - {D62A334F-6237-4B83-B195-09ED1F25E344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D62A334F-6237-4B83-B195-09ED1F25E344}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D62A334F-6237-4B83-B195-09ED1F25E344}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D62A334F-6237-4B83-B195-09ED1F25E344}.Release|Any CPU.Build.0 = Release|Any CPU - {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6C0DFE4-0285-465C-A023-27C4493D5E74}.Release|Any CPU.Build.0 = Release|Any CPU - {215B8624-528C-47BE-BF5B-650B41098129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {215B8624-528C-47BE-BF5B-650B41098129}.Debug|Any CPU.Build.0 = Debug|Any CPU - {215B8624-528C-47BE-BF5B-650B41098129}.Release|Any CPU.ActiveCfg = Release|Any CPU - {215B8624-528C-47BE-BF5B-650B41098129}.Release|Any CPU.Build.0 = Release|Any CPU - {2911782F-D3A7-42C4-ABE1-501824BC753A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2911782F-D3A7-42C4-ABE1-501824BC753A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2911782F-D3A7-42C4-ABE1-501824BC753A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2911782F-D3A7-42C4-ABE1-501824BC753A}.Release|Any CPU.Build.0 = Release|Any CPU - {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E208B51B-AD0E-4925-86B3-E35199BFF5C1}.Release|Any CPU.Build.0 = Release|Any CPU - {10E13977-D3B0-4CA4-964A-76D2E9575936}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10E13977-D3B0-4CA4-964A-76D2E9575936}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10E13977-D3B0-4CA4-964A-76D2E9575936}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10E13977-D3B0-4CA4-964A-76D2E9575936}.Release|Any CPU.Build.0 = Release|Any CPU - {5A32215C-CE76-44B0-BD72-712CFD146852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5A32215C-CE76-44B0-BD72-712CFD146852}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5A32215C-CE76-44B0-BD72-712CFD146852}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5A32215C-CE76-44B0-BD72-712CFD146852}.Release|Any CPU.Build.0 = Release|Any CPU - {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD54B7A6-E0E0-4668-9D2B-30EB3F028386}.Release|Any CPU.Build.0 = Release|Any CPU - {8E054D47-BF33-4335-A7D5-084942CFD675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8E054D47-BF33-4335-A7D5-084942CFD675}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8E054D47-BF33-4335-A7D5-084942CFD675}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8E054D47-BF33-4335-A7D5-084942CFD675}.Release|Any CPU.Build.0 = Release|Any CPU - {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {005575E0-4C3E-4F05-9A91-82AC7583D98C}.Release|Any CPU.Build.0 = Release|Any CPU - {87755332-3CAF-4305-BB2E-7470C24DA655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {87755332-3CAF-4305-BB2E-7470C24DA655}.Debug|Any CPU.Build.0 = Debug|Any CPU - {87755332-3CAF-4305-BB2E-7470C24DA655}.Release|Any CPU.ActiveCfg = Release|Any CPU - {87755332-3CAF-4305-BB2E-7470C24DA655}.Release|Any CPU.Build.0 = Release|Any CPU - {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {496EAD56-5E85-4C76-B680-7AB268DF44C5}.Release|Any CPU.Build.0 = Release|Any CPU - {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3}.Release|Any CPU.Build.0 = Release|Any CPU - {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA}.Release|Any CPU.Build.0 = Release|Any CPU - {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B40C8ADA-0B89-4023-8A16-4462C968A00E}.Release|Any CPU.Build.0 = Release|Any CPU - {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3425AC9-6CD0-4D39-B82B-5716456F1C70}.Release|Any CPU.Build.0 = Release|Any CPU - {07A0A8FA-1185-4856-8199-D6668FD08266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07A0A8FA-1185-4856-8199-D6668FD08266}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07A0A8FA-1185-4856-8199-D6668FD08266}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07A0A8FA-1185-4856-8199-D6668FD08266}.Release|Any CPU.Build.0 = Release|Any CPU - {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Debug|Any CPU.Build.0 = Debug|Any CPU - {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Release|Any CPU.ActiveCfg = Release|Any CPU - {151C28D4-E35D-4C50-BBCE-E664A97E1C44}.Release|Any CPU.Build.0 = Release|Any CPU - {D205205C-FB80-4657-84D2-63B10A4D0D38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D205205C-FB80-4657-84D2-63B10A4D0D38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D205205C-FB80-4657-84D2-63B10A4D0D38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D205205C-FB80-4657-84D2-63B10A4D0D38}.Release|Any CPU.Build.0 = Release|Any CPU - {836C5CB0-8BED-408C-9800-4285F539B8CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {836C5CB0-8BED-408C-9800-4285F539B8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {836C5CB0-8BED-408C-9800-4285F539B8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {836C5CB0-8BED-408C-9800-4285F539B8CA}.Release|Any CPU.Build.0 = Release|Any CPU - {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47997F91-65B1-406B-9DB1-2D0BEBF7F759}.Release|Any CPU.Build.0 = Release|Any CPU - {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71C2856C-6C23-4F2B-A25B-C3819D2D83C2}.Release|Any CPU.Build.0 = Release|Any CPU - {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C88CD17-D2F3-4B07-95FC-D127497064AA}.Release|Any CPU.Build.0 = Release|Any CPU - {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E9F4889-C62A-470A-A44B-51DA6E6252A5}.Release|Any CPU.Build.0 = Release|Any CPU - {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9}.Release|Any CPU.Build.0 = Release|Any CPU - {8D614C01-C059-47F1-9D6F-9068E891101D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D614C01-C059-47F1-9D6F-9068E891101D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D614C01-C059-47F1-9D6F-9068E891101D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D614C01-C059-47F1-9D6F-9068E891101D}.Release|Any CPU.Build.0 = Release|Any CPU - {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8750A2E5-DD57-408D-9EB8-05FD3A6376CD}.Release|Any CPU.Build.0 = Release|Any CPU - {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B1D72EE7-183B-46F8-B365-A5F0B93EC91A}.Release|Any CPU.Build.0 = Release|Any CPU - {850A384F-6226-433F-8777-396A3717F7E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {850A384F-6226-433F-8777-396A3717F7E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {850A384F-6226-433F-8777-396A3717F7E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {850A384F-6226-433F-8777-396A3717F7E0}.Release|Any CPU.Build.0 = Release|Any CPU - {D0294ECB-E367-4964-887B-21B239F85F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D0294ECB-E367-4964-887B-21B239F85F09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0294ECB-E367-4964-887B-21B239F85F09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D0294ECB-E367-4964-887B-21B239F85F09}.Release|Any CPU.Build.0 = Release|Any CPU - {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A61E0764-D98F-4E38-BB69-8AD4A67CAACB}.Release|Any CPU.Build.0 = Release|Any CPU - {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7}.Release|Any CPU.Build.0 = Release|Any CPU - {E9F84A8F-5761-407D-9200-BE8E3493073C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9F84A8F-5761-407D-9200-BE8E3493073C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E9F84A8F-5761-407D-9200-BE8E3493073C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E9F84A8F-5761-407D-9200-BE8E3493073C}.Release|Any CPU.Build.0 = Release|Any CPU - {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47}.Release|Any CPU.Build.0 = Release|Any CPU - {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B64C5954-9CC0-4A0B-9453-92324B51C23D}.Release|Any CPU.Build.0 = Release|Any CPU - {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0ECCF46E-3989-4A7E-BA31-4E73D7515578}.Release|Any CPU.Build.0 = Release|Any CPU - {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B}.Release|Any CPU.Build.0 = Release|Any CPU - {7E07BD13-74BF-4FD7-A294-07E664C47100}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E07BD13-74BF-4FD7-A294-07E664C47100}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E07BD13-74BF-4FD7-A294-07E664C47100}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E07BD13-74BF-4FD7-A294-07E664C47100}.Release|Any CPU.Build.0 = Release|Any CPU - {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F50AF512-69E2-46B5-87C6-E058CE2C2D8A}.Release|Any CPU.Build.0 = Release|Any CPU - {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1C0833AE-18DB-4E62-BB0A-226F4555CB09}.Release|Any CPU.Build.0 = Release|Any CPU - {B24BC602-DAFD-4941-A913-8B0725691681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B24BC602-DAFD-4941-A913-8B0725691681}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B24BC602-DAFD-4941-A913-8B0725691681}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B24BC602-DAFD-4941-A913-8B0725691681}.Release|Any CPU.Build.0 = Release|Any CPU - {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B44277E-74EB-49B2-B8FD-05C29EE51985}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F7C06F6A-D4FE-4202-B8B8-A593F80AB861} - EndGlobalSection GlobalSection(NestedProjects) = preSolution - {F493AA95-89E6-4F90-BA8F-129A6FE64A6D} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {5A9AF758-4ECA-4962-9BBC-3B133D4F221D} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {43CE2CD7-AE6C-4086-8594-7BC82FC83B74} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {65480B60-CE71-4486-85F4-EBEF8BEEFD98} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {7B4C527E-B09B-430D-9D93-9C58D78078E1} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {F3F761B4-914A-4190-93B1-F874CEE9149E} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {D40BEB6B-C370-4A8E-A628-47B6842C975A} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {7FEA756D-FA6F-48AF-A1F9-E6CD65F6DEF5} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {D3950CC9-808F-4ED8-946A-79A992F3F8EF} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {508FD4EB-9EA0-43B1-B1AD-30ED7D0545F7} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {F7017767-0BD0-4882-948D-E15C6FF7C15D} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {6127E436-97F1-4824-9FE3-E37A5E1CA916} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {74446502-51C1-48EE-BE10-F7B3551005A5} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {C7A26DA1-70D3-4D73-B5DB-A83241AB6F79} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {05996EDC-D17E-4DC4-82C0-EDD4408E5F8A} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {7ECFDC4C-4685-40AC-81D5-AB10461D299E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {A9FD95FA-909C-4396-9DE8-954A1373B351} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {DAEEB200-1D20-4A56-8C21-CA2ADE976AD5} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {B1E39853-406A-4CC7-A273-E70CFEEE3968} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {48D20E4A-51FA-4085-A31E-096A648EB9CF} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {4F98F0BE-9C2B-4012-AA11-768303C50E46} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {74FA5F2B-E691-483B-B19E-8DF288C1C04B} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {F1B2B70C-7E8D-4F73-80C2-455CAF21C09C} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} - {6875BAB1-307C-4BF7-A729-5C5F0BED838D} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} - {9C7A5377-C2C0-4C33-9087-77FE29462C5E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {50659C6B-FDAC-4FA4-97C1-04187499F68D} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {A4ED0D4F-73A1-46F3-9046-D3AA2A05B98B} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {595D1AC6-F8C2-418E-A8C7-9BDB5A0650E5} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {50D47C05-E2ED-459D-9415-4E1B7C024768} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {7C7A6E53-F53F-4EFB-90A0-02343961386C} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {9E848C22-3975-4898-ABA4-F1B6FEE5335E} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {4BFFFB87-752F-403F-AF77-8B86E3F2D67D} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {7231A984-223A-4BD9-A4A6-EAC30DE3AA4B} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {3B20D815-01B9-4EE4-B486-012302AB954E} = {89AC0402-38F7-405C-B244-31C5F13FD364} - {8B23312F-61B4-4330-900D-280848C2DB4B} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {7A739BBB-E672-46FA-8AD7-C629A95FFB03} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {6B97F71E-83AE-4FA9-B41D-06FFAC81EDCC} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {35636A23-C51F-4B05-8F1B-AFA435332C46} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {DE4395E2-AFC4-415E-A51D-526E472337BF} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {A2B97AF5-E03F-4C37-B44B-3B73C489BF89} = {89AC0402-38F7-405C-B244-31C5F13FD364} - {2A37A558-8BB1-4F8F-8D16-81014B252400} = {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} - {FC6DA3E4-5333-4D2B-9DB1-01870435AB9F} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {9EA920C4-2FA4-41CC-BCDC-D5FBF0EA4B3D} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {0597D9D4-D2BB-434C-92C4-76266509D021} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {BAE34041-C603-4A7D-BE25-5DD48BD4391E} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} - {6D907620-FE59-4C55-86CD-8299278BC06A} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} - {CB758566-4212-4ECB-8210-2934FAD44941} = {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} - {F3B93EF4-C324-44B1-BA33-8F4899131664} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {BB775A9A-6822-439F-8D03-23F6B6FCF5DA} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {FB8D7DC0-3F5E-466B-95B4-D2420F7F7BF5} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {A526C0D6-1C3E-4570-96EB-AB784AF17835} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {03EC899C-1FA1-4E98-A821-870F72B48082} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {64D9EC14-36C1-4F98-AF16-3C8A9C601B37} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {B353DF2E-A7C1-4511-A47E-883CDF938D36} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {BEF12323-63DD-458D-B6E4-4209752ACA69} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {B4783569-B72C-4005-B592-F7B444364FD2} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} - {C047419C-8A70-4533-90E4-1FAE52C141AD} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} - {139042C5-1BB4-4673-92DE-13A9584B3009} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} - {623C86D3-E93D-404D-8BBD-440BC73D445B} = {13B37500-5DF4-4C64-BD57-2CA6A619596A} - {7190E4AA-10F9-419B-B2A2-A4A745787B3A} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {89992897-D2C2-48BE-959B-6E996E82F87F} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} - {899AC6DB-FD44-4E7B-89DB-5400891AC80A} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} - {8F64B1AB-51AD-4BCC-AE60-27E7FD3E56D9} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {E2F3E423-3593-458B-999A-4371B7B2B192} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {BECDF1B9-E3FD-4ABD-BB78-41F8200821D1} = {7190E4AA-10F9-419B-B2A2-A4A745787B3A} - {A14864DE-5AE8-45D4-8530-BFC40489A155} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {0BB1CAC9-44BB-44CC-871E-E4986A61D548} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {DD0F7490-8BED-4DFD-B717-DC995F4746A0} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {1634F9D4-CED2-4621-8D7C-71316642C291} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {347CD12D-E1AA-4FC4-B33E-0E3EFED6B1A2} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {D674C1B1-2E22-416B-AEB8-CA75FA521E51} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {26287CC7-874E-4C9B-B41C-202511835B95} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {D86E3450-B65D-4999-8C1D-4B1D4403DB51} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {B0AD7E8F-E1BB-470A-A38A-4E0B920E0507} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {2A5C7854-9B98-4798-A9AE-8DC464093B90} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {BED61A6F-A339-4F33-ADA6-D41DA8251615} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {DB1E5EA5-4EC2-4C95-A942-DA09D68783E7} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {E710F6D7-F087-4815-8906-AE3643E21BAE} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {71DE375A-1037-4CDB-BC7C-6DC454B5D55D} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {4895B014-DCC4-4F5B-9DDE-FA1B43E37B98} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {602B14ED-409E-4EFD-AF5C-DE0AFE706AF3} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {8EF44709-4B5E-489B-A945-EDCB2D1A69C2} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {89AC0402-38F7-405C-B244-31C5F13FD364} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {90B310B4-C2DB-419E-B5EE-97FA096B62CC} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {BC510DE7-274F-4C8B-BCBB-A9E18627ED05} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {13B37500-5DF4-4C64-BD57-2CA6A619596A} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {BC5F86D6-8E7A-474F-94F0-85DA60E8EFC3} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} - {607F0049-E568-4EA3-9690-3C9961B4D190} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} - {8CB61BE4-D787-455B-A4F7-6DCA92F379F1} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {017DC714-0E66-40F4-830B-EB21AF09212A} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} - {F4DD898D-0BE8-4873-9532-F1F26DDB3291} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {550430E8-AA02-4FEE-AC3C-34F18BAA96A4} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {0C2B9A2C-AB0B-46D5-8EA3-800565C596DE} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {17CEAE8A-1F06-4027-9183-10901413FBA9} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {26D2AE74-DF14-414B-8023-6B3BE79FE3EE} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {165D8639-ED9E-4056-BAA2-5AB53491EF25} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {0D0F83C6-EB18-4DCE-9191-EF72794B7E58} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {288C1125-6D4E-4663-B6AE-34E86386E452} = {3099C7ED-AE0A-4670-9DF3-0CBC01D65D10} - {111C8C9A-28CA-4FB3-84C3-C12A2693F303} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {0E09CFC2-BEE3-473E-BB88-07AA69D023A8} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {0ECB4B40-2B2B-415E-8FDD-89500A889D26} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {85A88294-A9B6-476C-AFB8-CF69DC1C1ED8} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {68B98ED7-103C-4DC6-9C89-0B90F2809284} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {3B0D744C-AFCD-441A-B960-07273CBAA9EA} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {5B862F43-7859-4B19-817B-6B673D85E318} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {8981C7F9-9A37-44F3-B4AF-C8C2C635388E} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {567AB0C7-3B13-4FD3-9881-6CB6A6A03E7C} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {92A51B88-F801-4AA9-A4A6-1F270FF52363} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {03BE179D-DF33-4909-9373-E49924DB4EA5} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {342CCE8D-0715-42BC-A7C8-5FA3AAC40C85} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {BF408F9E-1A91-4C66-B466-A13743E91A6E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {E770800E-64BC-46A3-A3BA-C9910BB5771C} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {57F6A337-4B6D-420E-A0FC-62AC057F661C} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {8E7DE108-9D03-4DD7-A245-D12E9042915C} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {2968AA64-9848-4932-A571-39F160166FD7} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {A9436A00-8763-4C23-BBE0-BFC6C5B49056} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {8024E54C-51C0-48B7-BBE2-CD298F117CA0} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {FF705729-1E79-4736-A1A6-D725B8D6EFA6} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {5C8F7663-0E7C-41F9-B6E1-1A3E23B153AD} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {E5A55EB4-23E3-4968-8D15-8E579F07DF79} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {3C559DFF-17FA-4C86-816E-8CF6B09B6F05} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {E22FFCB1-CC90-42AB-8162-EC904B555AD9} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {F0159BE3-115F-408B-9D4F-E296F3592C12} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {001B9745-C4E7-43A5-BB46-8D3646C695B0} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {778E0253-E1BA-4E72-85AA-F786B5D443C6} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {6B07E07A-D637-45CC-B629-DE303993309C} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {E12D7110-BAD3-4CDC-8C6E-E7378EE194FD} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {4EAA2F01-747B-4E67-A17F-8FB7AB6075C3} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {3ACBD44B-6C90-472E-B49E-A8E07B1F60F3} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {CF33B86C-3056-49D1-BF23-96E69564337C} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {380A3025-5888-498D-8359-0F63961E7C4C} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {F0F4CD3F-A2E6-451C-B66E-D1C2C416AFD2} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {B48EE4A8-8BA9-404E-9839-A2522002FD2E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {4DD0A6AA-2F9A-49BA-88D3-2285F927CA4A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {A33DF532-A418-400F-B803-89AC4C669490} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {DFD63F70-CC2D-4971-A0A2-28A3865EBA02} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {51D379F2-B146-4266-BC1A-C98EBF5C69EC} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {D62A334F-6237-4B83-B195-09ED1F25E344} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {D6C0DFE4-0285-465C-A023-27C4493D5E74} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {2911782F-D3A7-42C4-ABE1-501824BC753A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {215B8624-528C-47BE-BF5B-650B41098129} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {E208B51B-AD0E-4925-86B3-E35199BFF5C1} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {10E13977-D3B0-4CA4-964A-76D2E9575936} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {5A32215C-CE76-44B0-BD72-712CFD146852} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {BD54B7A6-E0E0-4668-9D2B-30EB3F028386} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {8E054D47-BF33-4335-A7D5-084942CFD675} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {005575E0-4C3E-4F05-9A91-82AC7583D98C} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {87755332-3CAF-4305-BB2E-7470C24DA655} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {496EAD56-5E85-4C76-B680-7AB268DF44C5} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {6CB1C14C-6C41-468C-9E01-69A1B3FB53E3} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {B40C8ADA-0B89-4023-8A16-4462C968A00E} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {A3425AC9-6CD0-4D39-B82B-5716456F1C70} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {1DD7CB96-0349-4CC1-B66A-6A3FA88874BA} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {07A0A8FA-1185-4856-8199-D6668FD08266} = {89AC0402-38F7-405C-B244-31C5F13FD364} - {151C28D4-E35D-4C50-BBCE-E664A97E1C44} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {D205205C-FB80-4657-84D2-63B10A4D0D38} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {836C5CB0-8BED-408C-9800-4285F539B8CA} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {47997F91-65B1-406B-9DB1-2D0BEBF7F759} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {71C2856C-6C23-4F2B-A25B-C3819D2D83C2} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {9C88CD17-D2F3-4B07-95FC-D127497064AA} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {9E9F4889-C62A-470A-A44B-51DA6E6252A5} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {A22F4A7C-1610-4595-B5F7-4EF8348FE3A9} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {8D614C01-C059-47F1-9D6F-9068E891101D} = {798BAA50-825B-4DD9-83E2-77A9EE6EBE09} - {8750A2E5-DD57-408D-9EB8-05FD3A6376CD} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {B1D72EE7-183B-46F8-B365-A5F0B93EC91A} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {850A384F-6226-433F-8777-396A3717F7E0} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {D0294ECB-E367-4964-887B-21B239F85F09} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {A61E0764-D98F-4E38-BB69-8AD4A67CAACB} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {11EBFA91-4457-4C5B-A57C-4AD69C82F2B7} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {E9F84A8F-5761-407D-9200-BE8E3493073C} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {C3EEC9D9-F818-4058-B6F3-B71C1C0B8D47} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {B64C5954-9CC0-4A0B-9453-92324B51C23D} = {4E54480A-D155-43ED-9736-1A5BE7957211} - {0ECCF46E-3989-4A7E-BA31-4E73D7515578} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {4F0FEB76-5EB6-4AFC-9222-21DD22884A3B} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {7E07BD13-74BF-4FD7-A294-07E664C47100} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {F50AF512-69E2-46B5-87C6-E058CE2C2D8A} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} - {1C0833AE-18DB-4E62-BB0A-226F4555CB09} = {9AA521A5-80BF-4D20-9339-31D7E86D5868} - {B24BC602-DAFD-4941-A913-8B0725691681} = {90B310B4-C2DB-419E-B5EE-97FA096B62CC} - {1B44277E-74EB-49B2-B8FD-05C29EE51985} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {398463C0-5870-4F95-B5E9-1F48E30D35C8} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {4F4757BD-571E-453D-8447-CCBD53FABA9A} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {50504D10-798D-478E-BE01-EBB979416A11} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {8855E0A7-8C0D-4ECC-AB97-D9FCBC30B9C8} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {62C7FEA0-5588-4AD7-A0FC-110544EAE285} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {56AE29B6-6233-4B1F-848B-079B6CC0A3B0} = {B7751FC6-0B5D-4AD1-93FB-77FF50954BC5} + {D80FD698-7A0E-4DF2-BD0C-624E924A5D4E} = {50504D10-798D-478E-BE01-EBB979416A11} + {9A5B0538-886A-4DBC-A8BE-A9521D23BD5C} = {B7751FC6-0B5D-4AD1-93FB-77FF50954BC5} + {DB854ADC-6E0D-48F6-B594-2BBD32DC92B9} = {B7751FC6-0B5D-4AD1-93FB-77FF50954BC5} + {10E20EF3-FFC9-45B3-BDBB-749A23297BCC} = {50504D10-798D-478E-BE01-EBB979416A11} + {09D01D94-3318-482D-A99E-C22BF62A94D5} = {50504D10-798D-478E-BE01-EBB979416A11} + {CB4827A7-E3CC-4604-82AC-3E5D18DFD57F} = {50504D10-798D-478E-BE01-EBB979416A11} + {0E02293C-8544-4C43-81CE-2E8A416E38BF} = {50504D10-798D-478E-BE01-EBB979416A11} + {4E956F38-77A7-445A-B067-BFB123995C4C} = {50504D10-798D-478E-BE01-EBB979416A11} + {5DAB0F25-2DF9-49FA-9966-84CECFE403CA} = {50504D10-798D-478E-BE01-EBB979416A11} + {B998C279-C62E-4949-92C5-52D4455B4B6F} = {50504D10-798D-478E-BE01-EBB979416A11} + {0396B229-C6D6-4CCC-BCD2-0158A93193D3} = {50504D10-798D-478E-BE01-EBB979416A11} + {CFDA6378-7EA0-4DAB-BE1F-CE10E0072718} = {50504D10-798D-478E-BE01-EBB979416A11} + {7308E633-AA3E-4CB9-87BE-E4345562C45C} = {50504D10-798D-478E-BE01-EBB979416A11} + {C0557028-6FC0-4AF4-B362-2F0813C91942} = {50504D10-798D-478E-BE01-EBB979416A11} + {D0899A52-03D7-47AA-BD7F-090586F0776D} = {50504D10-798D-478E-BE01-EBB979416A11} + {D95441CB-A6F0-480A-8CAB-4E5A64D66FB9} = {50504D10-798D-478E-BE01-EBB979416A11} + {ABF5DEF1-2613-4465-9A3B-6B2EE4200B87} = {50504D10-798D-478E-BE01-EBB979416A11} + {2BCA926A-1254-45C8-AD2A-72EAB5523F41} = {50504D10-798D-478E-BE01-EBB979416A11} + {093E68B5-EC42-4351-8BE2-5A47CA2AB8EC} = {50504D10-798D-478E-BE01-EBB979416A11} + {7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02} = {50504D10-798D-478E-BE01-EBB979416A11} + {71663388-D915-4A4E-83DB-AE2140D08D51} = {50504D10-798D-478E-BE01-EBB979416A11} + {AB8997F4-8457-4D9F-91E7-5AFE381A2174} = {50504D10-798D-478E-BE01-EBB979416A11} + {3210AAC2-FC6A-4CEC-A50E-4119BDE314B6} = {50504D10-798D-478E-BE01-EBB979416A11} + {D165126B-E07E-4082-BA44-DF6496308587} = {50504D10-798D-478E-BE01-EBB979416A11} + {280453F1-3C62-4CD7-9B6F-1FFE088F312B} = {50504D10-798D-478E-BE01-EBB979416A11} + {2C0712A8-D2F2-4E50-B602-22F86154F6C0} = {4F4757BD-571E-453D-8447-CCBD53FABA9A} + {9349308B-EF29-4AA0-9EF9-C3E8D764C2BD} = {4F4757BD-571E-453D-8447-CCBD53FABA9A} + {4D87024C-330B-44C8-AD91-F0E682A9C4E5} = {4F4757BD-571E-453D-8447-CCBD53FABA9A} + {2C3D5076-88F5-4912-B8EF-4C049ACED839} = {398463C0-5870-4F95-B5E9-1F48E30D35C8} + {235ACAD6-900E-46FD-8AAF-A711C1F3C9EA} = {398463C0-5870-4F95-B5E9-1F48E30D35C8} + {59DB24D0-1E43-44DA-A7FB-58C320095F33} = {398463C0-5870-4F95-B5E9-1F48E30D35C8} + {96743545-B779-4C8D-B5F1-88DE4F21E9FE} = {8855E0A7-8C0D-4ECC-AB97-D9FCBC30B9C8} + {21F6E2E7-D343-4F2D-A659-00CA82364DB9} = {8855E0A7-8C0D-4ECC-AB97-D9FCBC30B9C8} + {EED60DD2-4FEC-4EC7-A32A-AE92E441C628} = {8855E0A7-8C0D-4ECC-AB97-D9FCBC30B9C8} + {D850E2C3-860C-435C-892E-A7BAD0A12F62} = {62C7FEA0-5588-4AD7-A0FC-110544EAE285} + {E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6} = {62C7FEA0-5588-4AD7-A0FC-110544EAE285} + {101756E8-279C-4BE8-8FFF-EBB01729F068} = {62C7FEA0-5588-4AD7-A0FC-110544EAE285} + {158E84D9-7B67-4708-B3C1-A4DC3638053F} = {62C7FEA0-5588-4AD7-A0FC-110544EAE285} + {3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {8C2AF2E7-2B40-4C12-B59E-60DEAB029836} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {081B2111-7CF2-40CB-A89B-31EC77BF1174} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {A0267C0D-0713-4C10-A608-CB0009230C43} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {B7E38978-CFAC-4137-8784-2202212CFB81} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {03349D2D-98EA-421E-A87C-8F5C5C6B9CDD} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {8A28360D-19CE-40A2-9AA1-E187C8328E19} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {B47584E3-02B8-4AF4-BC86-1CC92E2A1188} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {050F25D1-A52A-4AB4-9F59-96BCA2C2D354} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {1BABD106-C70F-4533-B306-1C13A12083F3} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {F45BC4EA-069C-4BA7-9949-C4187737C46A} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + {2F811176-5E40-4F94-ABF9-590C6BADE118} = {FAF67841-474B-4087-8C1A-A1F9E2EAD066} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D80FD698-7A0E-4DF2-BD0C-624E924A5D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D80FD698-7A0E-4DF2-BD0C-624E924A5D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D80FD698-7A0E-4DF2-BD0C-624E924A5D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D80FD698-7A0E-4DF2-BD0C-624E924A5D4E}.Release|Any CPU.Build.0 = Release|Any CPU + {9A5B0538-886A-4DBC-A8BE-A9521D23BD5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A5B0538-886A-4DBC-A8BE-A9521D23BD5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A5B0538-886A-4DBC-A8BE-A9521D23BD5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A5B0538-886A-4DBC-A8BE-A9521D23BD5C}.Release|Any CPU.Build.0 = Release|Any CPU + {DB854ADC-6E0D-48F6-B594-2BBD32DC92B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DB854ADC-6E0D-48F6-B594-2BBD32DC92B9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DB854ADC-6E0D-48F6-B594-2BBD32DC92B9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DB854ADC-6E0D-48F6-B594-2BBD32DC92B9}.Release|Any CPU.Build.0 = Release|Any CPU + {10E20EF3-FFC9-45B3-BDBB-749A23297BCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10E20EF3-FFC9-45B3-BDBB-749A23297BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10E20EF3-FFC9-45B3-BDBB-749A23297BCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10E20EF3-FFC9-45B3-BDBB-749A23297BCC}.Release|Any CPU.Build.0 = Release|Any CPU + {09D01D94-3318-482D-A99E-C22BF62A94D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09D01D94-3318-482D-A99E-C22BF62A94D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09D01D94-3318-482D-A99E-C22BF62A94D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09D01D94-3318-482D-A99E-C22BF62A94D5}.Release|Any CPU.Build.0 = Release|Any CPU + {CB4827A7-E3CC-4604-82AC-3E5D18DFD57F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB4827A7-E3CC-4604-82AC-3E5D18DFD57F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB4827A7-E3CC-4604-82AC-3E5D18DFD57F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB4827A7-E3CC-4604-82AC-3E5D18DFD57F}.Release|Any CPU.Build.0 = Release|Any CPU + {0E02293C-8544-4C43-81CE-2E8A416E38BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E02293C-8544-4C43-81CE-2E8A416E38BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E02293C-8544-4C43-81CE-2E8A416E38BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E02293C-8544-4C43-81CE-2E8A416E38BF}.Release|Any CPU.Build.0 = Release|Any CPU + {4E956F38-77A7-445A-B067-BFB123995C4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E956F38-77A7-445A-B067-BFB123995C4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E956F38-77A7-445A-B067-BFB123995C4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E956F38-77A7-445A-B067-BFB123995C4C}.Release|Any CPU.Build.0 = Release|Any CPU + {5DAB0F25-2DF9-49FA-9966-84CECFE403CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DAB0F25-2DF9-49FA-9966-84CECFE403CA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DAB0F25-2DF9-49FA-9966-84CECFE403CA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DAB0F25-2DF9-49FA-9966-84CECFE403CA}.Release|Any CPU.Build.0 = Release|Any CPU + {B998C279-C62E-4949-92C5-52D4455B4B6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B998C279-C62E-4949-92C5-52D4455B4B6F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B998C279-C62E-4949-92C5-52D4455B4B6F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B998C279-C62E-4949-92C5-52D4455B4B6F}.Release|Any CPU.Build.0 = Release|Any CPU + {0396B229-C6D6-4CCC-BCD2-0158A93193D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0396B229-C6D6-4CCC-BCD2-0158A93193D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0396B229-C6D6-4CCC-BCD2-0158A93193D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0396B229-C6D6-4CCC-BCD2-0158A93193D3}.Release|Any CPU.Build.0 = Release|Any CPU + {CFDA6378-7EA0-4DAB-BE1F-CE10E0072718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CFDA6378-7EA0-4DAB-BE1F-CE10E0072718}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CFDA6378-7EA0-4DAB-BE1F-CE10E0072718}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CFDA6378-7EA0-4DAB-BE1F-CE10E0072718}.Release|Any CPU.Build.0 = Release|Any CPU + {7308E633-AA3E-4CB9-87BE-E4345562C45C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7308E633-AA3E-4CB9-87BE-E4345562C45C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7308E633-AA3E-4CB9-87BE-E4345562C45C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7308E633-AA3E-4CB9-87BE-E4345562C45C}.Release|Any CPU.Build.0 = Release|Any CPU + {C0557028-6FC0-4AF4-B362-2F0813C91942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0557028-6FC0-4AF4-B362-2F0813C91942}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0557028-6FC0-4AF4-B362-2F0813C91942}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0557028-6FC0-4AF4-B362-2F0813C91942}.Release|Any CPU.Build.0 = Release|Any CPU + {D0899A52-03D7-47AA-BD7F-090586F0776D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0899A52-03D7-47AA-BD7F-090586F0776D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0899A52-03D7-47AA-BD7F-090586F0776D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0899A52-03D7-47AA-BD7F-090586F0776D}.Release|Any CPU.Build.0 = Release|Any CPU + {D95441CB-A6F0-480A-8CAB-4E5A64D66FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D95441CB-A6F0-480A-8CAB-4E5A64D66FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D95441CB-A6F0-480A-8CAB-4E5A64D66FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D95441CB-A6F0-480A-8CAB-4E5A64D66FB9}.Release|Any CPU.Build.0 = Release|Any CPU + {ABF5DEF1-2613-4465-9A3B-6B2EE4200B87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABF5DEF1-2613-4465-9A3B-6B2EE4200B87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABF5DEF1-2613-4465-9A3B-6B2EE4200B87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABF5DEF1-2613-4465-9A3B-6B2EE4200B87}.Release|Any CPU.Build.0 = Release|Any CPU + {2BCA926A-1254-45C8-AD2A-72EAB5523F41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BCA926A-1254-45C8-AD2A-72EAB5523F41}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BCA926A-1254-45C8-AD2A-72EAB5523F41}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BCA926A-1254-45C8-AD2A-72EAB5523F41}.Release|Any CPU.Build.0 = Release|Any CPU + {093E68B5-EC42-4351-8BE2-5A47CA2AB8EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {093E68B5-EC42-4351-8BE2-5A47CA2AB8EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {093E68B5-EC42-4351-8BE2-5A47CA2AB8EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {093E68B5-EC42-4351-8BE2-5A47CA2AB8EC}.Release|Any CPU.Build.0 = Release|Any CPU + {7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CB6B6F2-1184-4F0F-B2C3-1B8C4099CA02}.Release|Any CPU.Build.0 = Release|Any CPU + {71663388-D915-4A4E-83DB-AE2140D08D51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71663388-D915-4A4E-83DB-AE2140D08D51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71663388-D915-4A4E-83DB-AE2140D08D51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71663388-D915-4A4E-83DB-AE2140D08D51}.Release|Any CPU.Build.0 = Release|Any CPU + {AB8997F4-8457-4D9F-91E7-5AFE381A2174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB8997F4-8457-4D9F-91E7-5AFE381A2174}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB8997F4-8457-4D9F-91E7-5AFE381A2174}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB8997F4-8457-4D9F-91E7-5AFE381A2174}.Release|Any CPU.Build.0 = Release|Any CPU + {3210AAC2-FC6A-4CEC-A50E-4119BDE314B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3210AAC2-FC6A-4CEC-A50E-4119BDE314B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3210AAC2-FC6A-4CEC-A50E-4119BDE314B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3210AAC2-FC6A-4CEC-A50E-4119BDE314B6}.Release|Any CPU.Build.0 = Release|Any CPU + {D165126B-E07E-4082-BA44-DF6496308587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D165126B-E07E-4082-BA44-DF6496308587}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D165126B-E07E-4082-BA44-DF6496308587}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D165126B-E07E-4082-BA44-DF6496308587}.Release|Any CPU.Build.0 = Release|Any CPU + {280453F1-3C62-4CD7-9B6F-1FFE088F312B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {280453F1-3C62-4CD7-9B6F-1FFE088F312B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {280453F1-3C62-4CD7-9B6F-1FFE088F312B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {280453F1-3C62-4CD7-9B6F-1FFE088F312B}.Release|Any CPU.Build.0 = Release|Any CPU + {2C0712A8-D2F2-4E50-B602-22F86154F6C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C0712A8-D2F2-4E50-B602-22F86154F6C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C0712A8-D2F2-4E50-B602-22F86154F6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C0712A8-D2F2-4E50-B602-22F86154F6C0}.Release|Any CPU.Build.0 = Release|Any CPU + {9349308B-EF29-4AA0-9EF9-C3E8D764C2BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9349308B-EF29-4AA0-9EF9-C3E8D764C2BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9349308B-EF29-4AA0-9EF9-C3E8D764C2BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9349308B-EF29-4AA0-9EF9-C3E8D764C2BD}.Release|Any CPU.Build.0 = Release|Any CPU + {4D87024C-330B-44C8-AD91-F0E682A9C4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D87024C-330B-44C8-AD91-F0E682A9C4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D87024C-330B-44C8-AD91-F0E682A9C4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D87024C-330B-44C8-AD91-F0E682A9C4E5}.Release|Any CPU.Build.0 = Release|Any CPU + {2C3D5076-88F5-4912-B8EF-4C049ACED839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C3D5076-88F5-4912-B8EF-4C049ACED839}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C3D5076-88F5-4912-B8EF-4C049ACED839}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C3D5076-88F5-4912-B8EF-4C049ACED839}.Release|Any CPU.Build.0 = Release|Any CPU + {235ACAD6-900E-46FD-8AAF-A711C1F3C9EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {235ACAD6-900E-46FD-8AAF-A711C1F3C9EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {235ACAD6-900E-46FD-8AAF-A711C1F3C9EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {235ACAD6-900E-46FD-8AAF-A711C1F3C9EA}.Release|Any CPU.Build.0 = Release|Any CPU + {59DB24D0-1E43-44DA-A7FB-58C320095F33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59DB24D0-1E43-44DA-A7FB-58C320095F33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59DB24D0-1E43-44DA-A7FB-58C320095F33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59DB24D0-1E43-44DA-A7FB-58C320095F33}.Release|Any CPU.Build.0 = Release|Any CPU + {96743545-B779-4C8D-B5F1-88DE4F21E9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96743545-B779-4C8D-B5F1-88DE4F21E9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96743545-B779-4C8D-B5F1-88DE4F21E9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96743545-B779-4C8D-B5F1-88DE4F21E9FE}.Release|Any CPU.Build.0 = Release|Any CPU + {21F6E2E7-D343-4F2D-A659-00CA82364DB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21F6E2E7-D343-4F2D-A659-00CA82364DB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21F6E2E7-D343-4F2D-A659-00CA82364DB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21F6E2E7-D343-4F2D-A659-00CA82364DB9}.Release|Any CPU.Build.0 = Release|Any CPU + {EED60DD2-4FEC-4EC7-A32A-AE92E441C628}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EED60DD2-4FEC-4EC7-A32A-AE92E441C628}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EED60DD2-4FEC-4EC7-A32A-AE92E441C628}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EED60DD2-4FEC-4EC7-A32A-AE92E441C628}.Release|Any CPU.Build.0 = Release|Any CPU + {D850E2C3-860C-435C-892E-A7BAD0A12F62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D850E2C3-860C-435C-892E-A7BAD0A12F62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D850E2C3-860C-435C-892E-A7BAD0A12F62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D850E2C3-860C-435C-892E-A7BAD0A12F62}.Release|Any CPU.Build.0 = Release|Any CPU + {E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E29E8B05-3006-4FD6-9CAF-C5EC970DFEC6}.Release|Any CPU.Build.0 = Release|Any CPU + {101756E8-279C-4BE8-8FFF-EBB01729F068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {101756E8-279C-4BE8-8FFF-EBB01729F068}.Debug|Any CPU.Build.0 = Debug|Any CPU + {101756E8-279C-4BE8-8FFF-EBB01729F068}.Release|Any CPU.ActiveCfg = Release|Any CPU + {101756E8-279C-4BE8-8FFF-EBB01729F068}.Release|Any CPU.Build.0 = Release|Any CPU + {158E84D9-7B67-4708-B3C1-A4DC3638053F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {158E84D9-7B67-4708-B3C1-A4DC3638053F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {158E84D9-7B67-4708-B3C1-A4DC3638053F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {158E84D9-7B67-4708-B3C1-A4DC3638053F}.Release|Any CPU.Build.0 = Release|Any CPU + {3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CBB0E9C-E7FB-41F4-A3EB-68FF64E5EAEB}.Release|Any CPU.Build.0 = Release|Any CPU + {8C2AF2E7-2B40-4C12-B59E-60DEAB029836}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C2AF2E7-2B40-4C12-B59E-60DEAB029836}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C2AF2E7-2B40-4C12-B59E-60DEAB029836}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C2AF2E7-2B40-4C12-B59E-60DEAB029836}.Release|Any CPU.Build.0 = Release|Any CPU + {081B2111-7CF2-40CB-A89B-31EC77BF1174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {081B2111-7CF2-40CB-A89B-31EC77BF1174}.Debug|Any CPU.Build.0 = Debug|Any CPU + {081B2111-7CF2-40CB-A89B-31EC77BF1174}.Release|Any CPU.ActiveCfg = Release|Any CPU + {081B2111-7CF2-40CB-A89B-31EC77BF1174}.Release|Any CPU.Build.0 = Release|Any CPU + {5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BDE10B0-8AB7-4093-BFB1-409A9E0A23FC}.Release|Any CPU.Build.0 = Release|Any CPU + {A0267C0D-0713-4C10-A608-CB0009230C43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0267C0D-0713-4C10-A608-CB0009230C43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0267C0D-0713-4C10-A608-CB0009230C43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0267C0D-0713-4C10-A608-CB0009230C43}.Release|Any CPU.Build.0 = Release|Any CPU + {B7E38978-CFAC-4137-8784-2202212CFB81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7E38978-CFAC-4137-8784-2202212CFB81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7E38978-CFAC-4137-8784-2202212CFB81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7E38978-CFAC-4137-8784-2202212CFB81}.Release|Any CPU.Build.0 = Release|Any CPU + {03349D2D-98EA-421E-A87C-8F5C5C6B9CDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03349D2D-98EA-421E-A87C-8F5C5C6B9CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03349D2D-98EA-421E-A87C-8F5C5C6B9CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03349D2D-98EA-421E-A87C-8F5C5C6B9CDD}.Release|Any CPU.Build.0 = Release|Any CPU + {8A28360D-19CE-40A2-9AA1-E187C8328E19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A28360D-19CE-40A2-9AA1-E187C8328E19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A28360D-19CE-40A2-9AA1-E187C8328E19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A28360D-19CE-40A2-9AA1-E187C8328E19}.Release|Any CPU.Build.0 = Release|Any CPU + {B47584E3-02B8-4AF4-BC86-1CC92E2A1188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B47584E3-02B8-4AF4-BC86-1CC92E2A1188}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B47584E3-02B8-4AF4-BC86-1CC92E2A1188}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B47584E3-02B8-4AF4-BC86-1CC92E2A1188}.Release|Any CPU.Build.0 = Release|Any CPU + {050F25D1-A52A-4AB4-9F59-96BCA2C2D354}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {050F25D1-A52A-4AB4-9F59-96BCA2C2D354}.Debug|Any CPU.Build.0 = Debug|Any CPU + {050F25D1-A52A-4AB4-9F59-96BCA2C2D354}.Release|Any CPU.ActiveCfg = Release|Any CPU + {050F25D1-A52A-4AB4-9F59-96BCA2C2D354}.Release|Any CPU.Build.0 = Release|Any CPU + {4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4586C7F3-F4F5-4CF6-89E5-F89FE7DDEE6E}.Release|Any CPU.Build.0 = Release|Any CPU + {1BABD106-C70F-4533-B306-1C13A12083F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BABD106-C70F-4533-B306-1C13A12083F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BABD106-C70F-4533-B306-1C13A12083F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BABD106-C70F-4533-B306-1C13A12083F3}.Release|Any CPU.Build.0 = Release|Any CPU + {FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD3630A4-1FDF-4C58-93A1-ABA1F7C27A97}.Release|Any CPU.Build.0 = Release|Any CPU + {F45BC4EA-069C-4BA7-9949-C4187737C46A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F45BC4EA-069C-4BA7-9949-C4187737C46A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F45BC4EA-069C-4BA7-9949-C4187737C46A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F45BC4EA-069C-4BA7-9949-C4187737C46A}.Release|Any CPU.Build.0 = Release|Any CPU + {2F811176-5E40-4F94-ABF9-590C6BADE118}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F811176-5E40-4F94-ABF9-590C6BADE118}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F811176-5E40-4F94-ABF9-590C6BADE118}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F811176-5E40-4F94-ABF9-590C6BADE118}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/AElf.sln.DotSettings b/AElf.sln.DotSettings index 902d53db0b..04a90e14d0 100644 --- a/AElf.sln.DotSettings +++ b/AElf.sln.DotSettings @@ -1,4 +1,5 @@  + False JS True True diff --git a/Directory.Build.props b/Directory.Build.props index 06c51a392c..72fe490962 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 65edbcc406..503f13886b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -11,7 +11,7 @@ jobs: - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: - version: 6.0.5 + version: 6.0.x - script: choco install protoc --version=3.19.4 -y displayName: 'Install protobuf' - script: choco install unzip @@ -47,7 +47,7 @@ jobs: - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: - version: 6.0.5 + version: 6.0.x - script: bash scripts/install_protobuf.sh - script: bash scripts/download_binary.sh - script: bash build.sh -target=Test-with-Codecov-N --parts=3 --n=2 @@ -80,7 +80,7 @@ jobs: - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: - version: 6.0.5 + version: 6.0.x - script: bash scripts/install_protobuf.sh - script: bash scripts/download_binary.sh - script: bash build.sh -target=Test-with-Codecov-N --parts=3 --n=3 diff --git a/bench/AElf.BenchBase/AElf.BenchBase.csproj b/bench/AElf.BenchBase/AElf.BenchBase.csproj index 3eb29dc87c..64d89d764d 100644 --- a/bench/AElf.BenchBase/AElf.BenchBase.csproj +++ b/bench/AElf.BenchBase/AElf.BenchBase.csproj @@ -6,11 +6,11 @@ - + - + diff --git a/bench/AElf.BenchBase/Assembly.cs b/bench/AElf.BenchBase/Assembly.cs index 217120083b..41a898e37e 100644 --- a/bench/AElf.BenchBase/Assembly.cs +++ b/bench/AElf.BenchBase/Assembly.cs @@ -1,3 +1,3 @@ using Xunit; -[assembly: CollectionBehavior(DisableTestParallelization = true)] +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/bench/AElf.BenchBase/BenchBaseAElfModule.cs b/bench/AElf.BenchBase/BenchBaseAElfModule.cs index 2495bd796f..fc31de7847 100644 --- a/bench/AElf.BenchBase/BenchBaseAElfModule.cs +++ b/bench/AElf.BenchBase/BenchBaseAElfModule.cs @@ -2,21 +2,18 @@ using AElf.TestBase; using Volo.Abp.Modularity; -namespace AElf.BenchBase +namespace AElf.BenchBase; + +[DependsOn(typeof(TestBaseAElfModule))] +public class BenchBaseAElfModule : AElfModule +{ +} + +public class BenchBaseTest : AElfIntegratedTest + where TModule : IAbpModule { - [DependsOn(typeof(TestBaseAElfModule))] - public class BenchBaseAElfModule : AElfModule - { - - } - - public class BenchBaseTest : AElfIntegratedTest - where TModule: IAbpModule - { - } +} - public class BenchBaseTest : AElfIntegratedTest - { - - } +public class BenchBaseTest : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContract.cs b/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContract.cs index c6404b5061..0cf3b17b87 100644 --- a/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContract.cs +++ b/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContract.cs @@ -1,43 +1,40 @@ -using System; using Google.Protobuf.WellKnownTypes; -namespace AElf.Benchmark.PerformanceTestContract +namespace AElf.Benchmark.PerformanceTestContract; + +public class PerformanceTestContract : PerformanceTestContractContainer.PerformanceTestContractBase { - public class PerformanceTestContract : PerformanceTestContractContainer.PerformanceTestContractBase + public override UInt64Value Fibonacci(UInt64Value input) { - public override UInt64Value Fibonacci(UInt64Value input) - { - var result = CalculateFibonacci(input.Value); - return new UInt64Value {Value = result}; - } + var result = CalculateFibonacci(input.Value); + return new UInt64Value { Value = result }; + } - private ulong CalculateFibonacci(ulong n) - { - if (n == 0 || n == 1) - return n; - return CalculateFibonacci(n - 1) + CalculateFibonacci(n - 2); - } + private ulong CalculateFibonacci(ulong n) + { + if (n == 0 || n == 1) + return n; + return CalculateFibonacci(n - 1) + CalculateFibonacci(n - 2); + } - public override Int32Value LoopExpNop(PerformanceTesteInput input) + public override Int32Value LoopExpNop(PerformanceTesteInput input) + { + for (uint i = 0; i < input.N; i++) { - for (uint i = 0; i < input.N; i++) - { - - } - - return new Int32Value {Value = input.Seed}; } - public override DoubleValue LoopDivAdd(DivAddTestInput input) - { - var r = input.X; - for (uint i = 0; i < input.N; i++) - { - r /= input.Y; - r += input.K; - } + return new Int32Value { Value = input.Seed }; + } - return new DoubleValue {Value = r}; + public override DoubleValue LoopDivAdd(DivAddTestInput input) + { + var r = input.X; + for (uint i = 0; i < input.N; i++) + { + r /= input.Y; + r += input.K; } + + return new DoubleValue { Value = r }; } } \ No newline at end of file diff --git a/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContractState.cs b/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContractState.cs index d8d1c9dd57..68517364f1 100644 --- a/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContractState.cs +++ b/bench/AElf.Benchmark.PerformanceTestContract/PerformanceTestContractState.cs @@ -1,9 +1,7 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Benchmark.PerformanceTestContract +namespace AElf.Benchmark.PerformanceTestContract; + +public class PerformanceTestContractState : ContractState { - public class PerformanceTestContractState: ContractState - { - - } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/AElf.Benchmark.csproj b/bench/AElf.Benchmark/AElf.Benchmark.csproj index f2bf573bc3..d6775812dd 100644 --- a/bench/AElf.Benchmark/AElf.Benchmark.csproj +++ b/bench/AElf.Benchmark/AElf.Benchmark.csproj @@ -3,22 +3,22 @@ net6.0 false - + Exe - - + + - - - + + + - + false Contract diff --git a/bench/AElf.Benchmark/BenchmarkAElfModule.cs b/bench/AElf.Benchmark/BenchmarkAElfModule.cs index eaa6cc3fbb..7a6894fed1 100644 --- a/bench/AElf.Benchmark/BenchmarkAElfModule.cs +++ b/bench/AElf.Benchmark/BenchmarkAElfModule.cs @@ -4,9 +4,9 @@ using AElf.Kernel.Account.Infrastructure; using AElf.Kernel.Consensus.Application; using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Parallel; using AElf.Modularity; using AElf.OS; -using AElf.Kernel.SmartContract.Parallel; using AElf.OS.Network.Infrastructure; using AElf.Runtime.CSharp; using Microsoft.Extensions.DependencyInjection; @@ -14,53 +14,52 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[DependsOn( + typeof(OSCoreWithChainTestAElfModule) +)] +public class BenchmarkAElfModule : AElfModule { - [DependsOn( - typeof(OSCoreWithChainTestAElfModule) - )] - public class BenchmarkAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } +} - [DependsOn( - typeof(CoreOSAElfModule), - typeof(KernelAElfModule), - typeof(CSharpRuntimeAElfModule), - typeof(TestBaseKernelAElfModule) - )] - public class MiningBenchmarkAElfModule : AElfModule +[DependsOn( + typeof(CoreOSAElfModule), + typeof(KernelAElfModule), + typeof(CSharpRuntimeAElfModule), + typeof(TestBaseKernelAElfModule) +)] +public class MiningBenchmarkAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(o => Mock.Of()); + context.Services.AddTransient(); + context.Services.AddTransient(o => Mock.Of()); + // Configure(options => options.EnableTransactionExecutionValidation = false); + Configure(options => { - context.Services.AddSingleton(o => Mock.Of()); - context.Services.AddTransient(); - context.Services.AddTransient(o => Mock.Of()); - // Configure(options => options.EnableTransactionExecutionValidation = false); - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - }); - } + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + }); + } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var keyPairProvider = context.ServiceProvider.GetRequiredService(); - keyPairProvider.SetKeyPair(CryptoHelper.GenerateKeyPair()); - } + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var keyPairProvider = context.ServiceProvider.GetRequiredService(); + keyPairProvider.SetKeyPair(CryptoHelper.GenerateKeyPair()); } +} - [DependsOn( - typeof(OSCoreWithChainTestAElfModule), - typeof(ParallelExecutionModule) - )] - public class BenchmarkParallelAElfModule : AElfModule +[DependsOn( + typeof(OSCoreWithChainTestAElfModule), + typeof(ParallelExecutionModule) +)] +public class BenchmarkParallelAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BenchmarkTestBase.cs b/bench/AElf.Benchmark/BenchmarkTestBase.cs index b91846ce1b..3d26c9301a 100644 --- a/bench/AElf.Benchmark/BenchmarkTestBase.cs +++ b/bench/AElf.Benchmark/BenchmarkTestBase.cs @@ -1,16 +1,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; -using AElf.ContractTestKit; using AElf.Cryptography; using AElf.Kernel; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Application; @@ -22,150 +19,149 @@ using Google.Protobuf; using Volo.Abp.Modularity; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +public class BenchmarkTestBase : BenchmarkTestBase +{ +} + +public class BenchmarkTestBase : AElfIntegratedTest + where TModule : IAbpModule { - public class BenchmarkTestBase : BenchmarkTestBase + protected readonly IBlockchainStore TransactionResultStore; + + public BenchmarkTestBase() { + TransactionResultStore = GetRequiredService>(); } - public class BenchmarkTestBase : AElfIntegratedTest - where TModule : IAbpModule + protected async Task RemoveTransactionResultsAsync(IEnumerable transactionIds, Hash disambiguationHash) { - protected readonly IBlockchainStore TransactionResultStore; + await TransactionResultStore.RemoveAllAsync(transactionIds + .Select(t => HashHelper.XorAndCompute(t, disambiguationHash).ToStorageKey()).ToList()); + } +} - public BenchmarkTestBase() - { - TransactionResultStore = GetRequiredService>(); - } +public class MiningWithTransactionsBenchmarkBase : BenchmarkTestBase +{ + private readonly IAccountService _accountService; + private readonly string _nativeSymbol = "ELF"; + private readonly IOsBlockchainNodeContextService _osBlockchainNodeContextService; + private readonly ISmartContractAddressService _smartContractAddressService; + protected readonly IBlockchainService BlockchainService; - protected async Task RemoveTransactionResultsAsync(IEnumerable transactionIds, Hash disambiguationHash) - { - await TransactionResultStore.RemoveAllAsync(transactionIds - .Select(t => HashHelper.XorAndCompute(t, disambiguationHash).ToStorageKey()).ToList()); - } + public readonly long TokenTotalSupply = 100_000_000_000_000_000L; + protected readonly ITransactionPoolService TransactionPoolService; + + private IReadOnlyDictionary _codes; + + public MiningWithTransactionsBenchmarkBase() + { + TransactionPoolService = GetRequiredService(); + _osBlockchainNodeContextService = GetRequiredService(); + _accountService = GetRequiredService(); + BlockchainService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); } - public class MiningWithTransactionsBenchmarkBase : BenchmarkTestBase + public IReadOnlyDictionary Codes => + _codes ??= ContractsDeployer.GetContractCodes(); + + public async Task InitializeChainAsync() { - private readonly IOsBlockchainNodeContextService _osBlockchainNodeContextService; - private readonly IAccountService _accountService; - protected readonly IBlockchainService BlockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - protected readonly ITransactionPoolService TransactionPoolService; + await StartNodeAsync(); + var chain = await BlockchainService.GetChainAsync(); - public MiningWithTransactionsBenchmarkBase() + if (chain.BestChainHeight == 1) { - TransactionPoolService = GetRequiredService(); - _osBlockchainNodeContextService = GetRequiredService(); - _accountService = GetRequiredService(); - BlockchainService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); + var genesisBlock = await BlockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); + chain = await BlockchainService.GetChainAsync(); + await BlockchainService.SetIrreversibleBlockAsync(chain, genesisBlock.Height, genesisBlock.GetHash()); } - private IReadOnlyDictionary _codes; - - public IReadOnlyDictionary Codes => - _codes ??= ContractsDeployer.GetContractCodes(); + await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, + chain.BestChainHeight); + } - public async Task InitializeChainAsync() + private async Task StartNodeAsync() + { + var ownAddress = await _accountService.GetAccountAsync(); + var callList = new List(); + callList.Add(nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput { - await StartNodeAsync(); - var chain = await BlockchainService.GetChainAsync(); - - if (chain.BestChainHeight == 1) - { - var genesisBlock = await BlockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); - chain = await BlockchainService.GetChainAsync(); - await BlockchainService.SetIrreversibleBlockAsync(chain, genesisBlock.Height, genesisBlock.GetHash()); - } + Symbol = _nativeSymbol, + TokenName = "ELF_Token", + TotalSupply = TokenTotalSupply, + Decimals = 8, + Issuer = ownAddress, + IsBurnable = true + }); + callList.Add(nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), + new SetPrimaryTokenSymbolInput { Symbol = _nativeSymbol }); + callList.Add(nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput + { + Symbol = _nativeSymbol, + Amount = TokenTotalSupply, + To = ownAddress, + Memo = "Issue" + }); + + var tokenContractCode = Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("MultiToken")).Value; + var dto = new OsBlockchainNodeContextStartDto + { + ZeroSmartContract = typeof(BasicContractZero), + ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + SmartContractRunnerCategory = KernelConstants.CodeCoverageRunnerCategory + }; + var genesisSmartContractDto = new GenesisSmartContractDto + { + Code = tokenContractCode, + SystemSmartContractName = TokenSmartContractAddressNameProvider.Name + }; + genesisSmartContractDto.AddGenesisTransactionMethodCall(callList.ToArray()); + dto.InitializationSmartContracts.Add(genesisSmartContractDto); - await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, - chain.BestChainHeight); - } + await _osBlockchainNodeContextService.StartAsync(dto); + } - public readonly long TokenTotalSupply = 100_000_000_000_000_000L; - private readonly string _nativeSymbol = "ELF"; + public async Task> GenerateTransferTransactionsAsync(int txCount) + { + var txList = new List(); + while (txCount-- > 0) + txList.Add(await GenerateTransferTransactionAsync()); + return txList; + } - private async Task StartNodeAsync() - { - var ownAddress = await _accountService.GetAccountAsync(); - var callList = new List(); - callList.Add(nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput - { - Symbol = _nativeSymbol, - TokenName = "ELF_Token", - TotalSupply = TokenTotalSupply, - Decimals = 8, - Issuer = ownAddress, - IsBurnable = true - }); - callList.Add(nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - new SetPrimaryTokenSymbolInput {Symbol = _nativeSymbol}); - callList.Add(nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput - { - Symbol = _nativeSymbol, - Amount = TokenTotalSupply, - To = ownAddress, - Memo = "Issue" - }); - - var tokenContractCode = Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("MultiToken")).Value; - var dto = new OsBlockchainNodeContextStartDto - { - ZeroSmartContract = typeof(BasicContractZero), - ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - SmartContractRunnerCategory = KernelConstants.CodeCoverageRunnerCategory, - }; - var genesisSmartContractDto = new GenesisSmartContractDto + public async Task GenerateTransferTransactionAsync() + { + var chain = await BlockchainService.GetChainAsync(); + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext { - Code = tokenContractCode, - SystemSmartContractName = TokenSmartContractAddressNameProvider.Name, - }; - genesisSmartContractDto.AddGenesisTransactionMethodCall(callList.ToArray()); - dto.InitializationSmartContracts.Add(genesisSmartContractDto); - - await _osBlockchainNodeContextService.StartAsync(dto); - } - - public async Task> GenerateTransferTransactionsAsync(int txCount) + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, TokenSmartContractAddressNameProvider.StringName); + var getBalanceInput = new GetBalanceInput { - var txList = new List(); - while (txCount-- > 0) - txList.Add(await GenerateTransferTransactionAsync()); - return txList; - } - - public async Task GenerateTransferTransactionAsync() + Owner = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey), + Symbol = _nativeSymbol + }; + var transaction = new Transaction { - var chain = await BlockchainService.GetChainAsync(); - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, TokenSmartContractAddressNameProvider.StringName); - var getBalanceInput = new GetBalanceInput - { - Owner = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey), - Symbol = _nativeSymbol - }; - var transaction = new Transaction - { - From = await _accountService.GetAccountAsync(), - To = tokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.GetBalance), - Params = getBalanceInput.ToByteString(), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) - }; - var sig = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(sig); - - return transaction; - } + From = await _accountService.GetAccountAsync(), + To = tokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.GetBalance), + Params = getBalanceInput.ToByteString(), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + var sig = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(sig); + + return transaction; } +} - public class BenchmarkParallelTestBase : BenchmarkTestBase - { - } +public class BenchmarkParallelTestBase : BenchmarkTestBase +{ } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BlockAttachTests.cs b/bench/AElf.Benchmark/BlockAttachTests.cs index abcedc4005..97665b9d40 100644 --- a/bench/AElf.Benchmark/BlockAttachTests.cs +++ b/bench/AElf.Benchmark/BlockAttachTests.cs @@ -9,65 +9,64 @@ using AElf.OS; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class BlockAttachTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class BlockAttachTests : BenchmarkTestBase - { - private IBlockchainStore _chains; - private INotModifiedCachedStateStore _blockStateSets; - private IBlockManager _blockManager; - private IChainManager _chainManager; - private IBlockchainService _blockchainService; - private IBlockAttachService _blockAttachService; - private ITransactionManager _transactionManager; - private OSTestHelper _osTestHelper; + private Block _block; + private IBlockAttachService _blockAttachService; + private IBlockchainService _blockchainService; + private IBlockManager _blockManager; + private INotModifiedCachedStateStore _blockStateSets; - private Chain _chain; - private Block _block; + private Chain _chain; + private IChainManager _chainManager; + private IBlockchainStore _chains; + private OSTestHelper _osTestHelper; + private ITransactionManager _transactionManager; - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - [GlobalSetup] - public async Task GlobalSetup() - { - _chains = GetRequiredService>(); - _blockStateSets = GetRequiredService>(); - _chainManager = GetRequiredService(); - _blockManager = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockAttachService = GetRequiredService(); - _transactionManager = GetRequiredService(); - _osTestHelper = GetRequiredService(); + [GlobalSetup] + public async Task GlobalSetup() + { + _chains = GetRequiredService>(); + _blockStateSets = GetRequiredService>(); + _chainManager = GetRequiredService(); + _blockManager = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockAttachService = GetRequiredService(); + _transactionManager = GetRequiredService(); + _osTestHelper = GetRequiredService(); - _chain = await _blockchainService.GetChainAsync(); - } + _chain = await _blockchainService.GetChainAsync(); + } - [IterationSetup] - public async Task IterationSetup() - { - var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - await _blockchainService.AddTransactionsAsync(transactions); - _block = _osTestHelper.GenerateBlock(_chain.BestChainHash, _chain.BestChainHeight, transactions); + [IterationSetup] + public async Task IterationSetup() + { + var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + await _blockchainService.AddTransactionsAsync(transactions); + _block = _osTestHelper.GenerateBlock(_chain.BestChainHash, _chain.BestChainHeight, transactions); - await _blockchainService.AddBlockAsync(_block); - } + await _blockchainService.AddBlockAsync(_block); + } - [Benchmark] - public async Task AttachBlockTest() - { - await _blockAttachService.AttachBlockAsync(_block); - } + [Benchmark] + public async Task AttachBlockTest() + { + await _blockAttachService.AttachBlockAsync(_block); + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); - await _transactionManager.RemoveTransactionsAsync(_block.Body.TransactionIds); - await RemoveTransactionResultsAsync(_block.Body.TransactionIds, _block.GetHash()); - await _chainManager.RemoveChainBlockLinkAsync(_block.GetHash()); - await _blockManager.RemoveBlockAsync(_block.GetHash()); - await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); - } + [IterationCleanup] + public async Task IterationCleanup() + { + await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); + await _transactionManager.RemoveTransactionsAsync(_block.Body.TransactionIds); + await RemoveTransactionResultsAsync(_block.Body.TransactionIds, _block.GetHash()); + await _chainManager.RemoveChainBlockLinkAsync(_block.GetHash()); + await _blockManager.RemoveBlockAsync(_block.GetHash()); + await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BlockExecutingParallelGroupsTests.cs b/bench/AElf.Benchmark/BlockExecutingParallelGroupsTests.cs index b22e9b80f4..67c87fe386 100644 --- a/bench/AElf.Benchmark/BlockExecutingParallelGroupsTests.cs +++ b/bench/AElf.Benchmark/BlockExecutingParallelGroupsTests.cs @@ -13,74 +13,73 @@ using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class BlockExecutingParalleGroupslTests : BenchmarkParallelTestBase { - [MarkdownExporterAttribute.GitHub] - public class BlockExecutingParalleGroupslTests : BenchmarkParallelTestBase - { - private IBlockExecutingService _blockExecutingService; - private IBlockchainService _blockchainService; - private IMinerService _minerService; - private INotModifiedCachedStateStore _blockStateSets; - private OSTestHelper _osTestHelper; + private Block _block; + private IBlockchainService _blockchainService; + private IBlockExecutingService _blockExecutingService; + private INotModifiedCachedStateStore _blockStateSets; + private List _cancellableTransactions; + private List _keyPairs; + private IMinerService _minerService; + private OSTestHelper _osTestHelper; + private List _prepareTransactions; - private List _systemTransactions; - private List _prepareTransactions; - private List _cancellableTransactions; - private List _keyPairs; - private Block _block; + private List _systemTransactions; - [Params(1, 2, 5, 10, 50, 100)] public int GroupCount; + [Params(1, 2, 5, 10, 50, 100)] public int GroupCount; - public int TransactionCount = 200; + public int TransactionCount = 200; - [GlobalSetup] - public void GlobalSetup() - { - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _minerService = GetRequiredService(); - _blockStateSets = GetRequiredService>(); - _osTestHelper = GetRequiredService(); + [GlobalSetup] + public void GlobalSetup() + { + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _minerService = GetRequiredService(); + _blockStateSets = GetRequiredService>(); + _osTestHelper = GetRequiredService(); - _prepareTransactions = new List(); - _systemTransactions = new List(); - _cancellableTransactions = new List(); - _keyPairs = new List(); - } + _prepareTransactions = new List(); + _systemTransactions = new List(); + _cancellableTransactions = new List(); + _keyPairs = new List(); + } - [IterationSetup] - public async Task IterationSetup() - { - var chain = await _blockchainService.GetChainAsync(); - var tokenAmount = TransactionCount / GroupCount; - (_prepareTransactions, _keyPairs) = await _osTestHelper.PrepareTokenForParallel(GroupCount, tokenAmount); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _prepareTransactions); - await _blockExecutingService.ExecuteBlockAsync(_block.Header, _prepareTransactions); - await _osTestHelper.BroadcastTransactions(_prepareTransactions); - _block = (await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; + [IterationSetup] + public async Task IterationSetup() + { + var chain = await _blockchainService.GetChainAsync(); + var tokenAmount = TransactionCount / GroupCount; + (_prepareTransactions, _keyPairs) = await _osTestHelper.PrepareTokenForParallel(GroupCount, tokenAmount); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _prepareTransactions); + await _blockExecutingService.ExecuteBlockAsync(_block.Header, _prepareTransactions); + await _osTestHelper.BroadcastTransactions(_prepareTransactions); + _block = (await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; - _systemTransactions = await _osTestHelper.GenerateTransferTransactions(1); - _cancellableTransactions = await _osTestHelper.GenerateTransactionsWithoutConflictAsync(_keyPairs, tokenAmount); - chain = await _blockchainService.GetChainAsync(); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - _systemTransactions.Concat(_cancellableTransactions)); - } + _systemTransactions = await _osTestHelper.GenerateTransferTransactions(1); + _cancellableTransactions = await _osTestHelper.GenerateTransactionsWithoutConflictAsync(_keyPairs, tokenAmount); + chain = await _blockchainService.GetChainAsync(); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + _systemTransactions.Concat(_cancellableTransactions)); + } - [Benchmark] - public async Task ExecuteBlock() - { - _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, - _systemTransactions, _cancellableTransactions, CancellationToken.None)).Block; - } + [Benchmark] + public async Task ExecuteBlock() + { + _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, + _systemTransactions, _cancellableTransactions, CancellationToken.None)).Block; + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); - var transactionIds = _systemTransactions.Concat(_cancellableTransactions).Select(t => t.GetHash()).ToList(); - await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); - } + [IterationCleanup] + public async Task IterationCleanup() + { + await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); + var transactionIds = _systemTransactions.Concat(_cancellableTransactions).Select(t => t.GetHash()).ToList(); + await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BlockExecutingParallelTests.cs b/bench/AElf.Benchmark/BlockExecutingParallelTests.cs index a9ca992aea..7ceb192016 100644 --- a/bench/AElf.Benchmark/BlockExecutingParallelTests.cs +++ b/bench/AElf.Benchmark/BlockExecutingParallelTests.cs @@ -13,73 +13,72 @@ using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class BlockExecutingParallelTests : BenchmarkParallelTestBase { - [MarkdownExporterAttribute.GitHub] - public class BlockExecutingParallelTests : BenchmarkParallelTestBase - { - private IBlockExecutingService _blockExecutingService; - private IBlockchainService _blockchainService; - private IMinerService _minerService; - private INotModifiedCachedStateStore _blockStateSets; - private OSTestHelper _osTestHelper; + private Block _block; + private IBlockchainService _blockchainService; + private IBlockExecutingService _blockExecutingService; + private INotModifiedCachedStateStore _blockStateSets; + private List _cancellableTransactions; + private List _keyPairs; + private IMinerService _minerService; + private OSTestHelper _osTestHelper; + private List _prepareTransactions; - private List _systemTransactions; - private List _prepareTransactions; - private List _cancellableTransactions; - private List _keyPairs; - private Block _block; + private List _systemTransactions; - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - [GlobalSetup] - public void GlobalSetup() - { - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _minerService = GetRequiredService(); - _blockStateSets = GetRequiredService>(); - _osTestHelper = GetRequiredService(); + [GlobalSetup] + public void GlobalSetup() + { + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _minerService = GetRequiredService(); + _blockStateSets = GetRequiredService>(); + _osTestHelper = GetRequiredService(); - _prepareTransactions = new List(); - _systemTransactions = new List(); - _cancellableTransactions = new List(); - _keyPairs = new List(); - } + _prepareTransactions = new List(); + _systemTransactions = new List(); + _cancellableTransactions = new List(); + _keyPairs = new List(); + } - [IterationSetup] - public async Task IterationSetup() - { - var chain = await _blockchainService.GetChainAsync(); + [IterationSetup] + public async Task IterationSetup() + { + var chain = await _blockchainService.GetChainAsync(); - (_prepareTransactions, _keyPairs) = await _osTestHelper.PrepareTokenForParallel(TransactionCount); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _prepareTransactions); - await _blockExecutingService.ExecuteBlockAsync(_block.Header, _prepareTransactions); - await _osTestHelper.BroadcastTransactions(_prepareTransactions); - _block = (await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; + (_prepareTransactions, _keyPairs) = await _osTestHelper.PrepareTokenForParallel(TransactionCount); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _prepareTransactions); + await _blockExecutingService.ExecuteBlockAsync(_block.Header, _prepareTransactions); + await _osTestHelper.BroadcastTransactions(_prepareTransactions); + _block = (await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; - _systemTransactions = await _osTestHelper.GenerateTransferTransactions(1); - _cancellableTransactions = await _osTestHelper.GenerateTransactionsWithoutConflictAsync(_keyPairs); - chain = await _blockchainService.GetChainAsync(); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - _systemTransactions.Concat(_cancellableTransactions)); - } + _systemTransactions = await _osTestHelper.GenerateTransferTransactions(1); + _cancellableTransactions = await _osTestHelper.GenerateTransactionsWithoutConflictAsync(_keyPairs); + chain = await _blockchainService.GetChainAsync(); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + _systemTransactions.Concat(_cancellableTransactions)); + } - [Benchmark] - public async Task ExecuteBlock() - { - _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, - _systemTransactions, _cancellableTransactions, CancellationToken.None)).Block; - } + [Benchmark] + public async Task ExecuteBlock() + { + _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, + _systemTransactions, _cancellableTransactions, CancellationToken.None)).Block; + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); + [IterationCleanup] + public async Task IterationCleanup() + { + await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); - var transactionIds = _systemTransactions.Concat(_cancellableTransactions).Select(t => t.GetHash()).ToList(); - await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); - } + var transactionIds = _systemTransactions.Concat(_cancellableTransactions).Select(t => t.GetHash()).ToList(); + await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BlockExecutingTests.cs b/bench/AElf.Benchmark/BlockExecutingTests.cs index 2845dfc5ac..a0d375eb7f 100644 --- a/bench/AElf.Benchmark/BlockExecutingTests.cs +++ b/bench/AElf.Benchmark/BlockExecutingTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -11,51 +10,50 @@ using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class BlockExecutingTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class BlockExecutingTests : BenchmarkTestBase + private Block _block; + private IBlockchainService _blockchainService; + private IBlockExecutingService _blockExecutingService; + private INotModifiedCachedStateStore _blockStateSets; + private OSTestHelper _osTestHelper; + + private List _transactions; + + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + + [GlobalSetup] + public void GlobalSetup() + { + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _blockStateSets = GetRequiredService>(); + _osTestHelper = GetRequiredService(); + } + + [IterationSetup] + public async Task IterationSetup() + { + var chain = await _blockchainService.GetChainAsync(); + + _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _transactions); + } + + [Benchmark] + public async Task ExecuteBlock() + { + _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, _transactions)).Block; + } + + [IterationCleanup] + public async Task IterationCleanup() { - private IBlockExecutingService _blockExecutingService; - private IBlockchainService _blockchainService; - private INotModifiedCachedStateStore _blockStateSets; - private OSTestHelper _osTestHelper; - - private List _transactions; - private Block _block; - - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - - [GlobalSetup] - public void GlobalSetup() - { - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _blockStateSets = GetRequiredService>(); - _osTestHelper = GetRequiredService(); - } - - [IterationSetup] - public async Task IterationSetup() - { - var chain = await _blockchainService.GetChainAsync(); - - _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, _transactions); - } - - [Benchmark] - public async Task ExecuteBlock() - { - _block = (await _blockExecutingService.ExecuteBlockAsync(_block.Header, _transactions)).Block; - } - - [IterationCleanup] - public async Task IterationCleanup() - { - await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); - var transactionIds = _transactions.Select(t => t.GetHash()).ToList(); - await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); - } + await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); + var transactionIds = _transactions.Select(t => t.GetHash()).ToList(); + await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/BlockchainStateMergingTests.cs b/bench/AElf.Benchmark/BlockchainStateMergingTests.cs index 8eb92cbc50..1453da1f44 100644 --- a/bench/AElf.Benchmark/BlockchainStateMergingTests.cs +++ b/bench/AElf.Benchmark/BlockchainStateMergingTests.cs @@ -1,11 +1,8 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel; -using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Application; @@ -15,118 +12,111 @@ using AElf.OS; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class BlockchainStateMergingTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class BlockchainStateMergingTests : BenchmarkTestBase + private IBlockchainService _blockchainService; + private IBlockchainStateService _blockchainStateService; + private IBlockManager _blockManager; + private List _blocks; + private IBlockStateSetManger _blockStateSetManger; + private List _blockStateSets; + + private Chain _chain; + private IChainManager _chainManager; + private IBlockchainStore _chains; + private ChainStateInfo _chainStateInfo; + private IStateStore _chainStateInfoCollection; + private OSTestHelper _osTestHelper; + private ITransactionManager _transactionManager; + private ITransactionPoolService _transactionPoolService; + + [Params(1, 10, 50)] public int BlockCount; + + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + + [GlobalSetup] + public async Task GlobalSetup() { - private IStateStore _chainStateInfoCollection; - private IBlockchainStore _chains; - private IBlockManager _blockManager; - private ITransactionManager _transactionManager; - private IBlockchainStateService _blockchainStateService; - private IBlockStateSetManger _blockStateSetManger; - private IBlockchainService _blockchainService; - private IChainManager _chainManager; - private ITransactionPoolService _transactionPoolService; - private OSTestHelper _osTestHelper; - - private Chain _chain; - private ChainStateInfo _chainStateInfo; - private List _blockStateSets; - private List _blocks; - - [Params(1, 10, 50)] public int BlockCount; - - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - - [GlobalSetup] - public async Task GlobalSetup() - { - _chains = GetRequiredService>(); - _chainStateInfoCollection = GetRequiredService>(); - _blockchainStateService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _blockchainService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _chainManager = GetRequiredService(); - _blockManager = GetRequiredService(); - _transactionManager = GetRequiredService(); - _transactionPoolService = GetRequiredService(); - - - _blockStateSets = new List(); - _blocks = new List(); - - _chain = await _blockchainService.GetChainAsync(); - - var blockHash = _chain.BestChainHash; - while (true) - { - var blockState = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); - _blockStateSets.Add(blockState); - - var blockHeader = await _blockchainService.GetBlockHeaderByHashAsync(blockHash); - blockHash = blockHeader.PreviousBlockHash; - if (blockHash == _chain.LastIrreversibleBlockHash) - { - break; - } - } - - await _blockchainStateService.MergeBlockStateAsync(_chain.BestChainHeight, _chain.BestChainHash); - - for (var i = 0; i < BlockCount; i++) - { - var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - await _osTestHelper.BroadcastTransactions(transactions); - var block = await _osTestHelper.MinedOneBlock(); - _blocks.Add(block); - - var blockState = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - _blockStateSets.Add(blockState); - } - - var chain = await _blockchainService.GetChainAsync(); - await _chainManager.SetIrreversibleBlockAsync(chain, chain.BestChainHash); - - _chainStateInfo = await _chainStateInfoCollection.GetAsync(chain.Id.ToStorageKey()); - } + _chains = GetRequiredService>(); + _chainStateInfoCollection = GetRequiredService>(); + _blockchainStateService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _blockchainService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _chainManager = GetRequiredService(); + _blockManager = GetRequiredService(); + _transactionManager = GetRequiredService(); + _transactionPoolService = GetRequiredService(); + + + _blockStateSets = new List(); + _blocks = new List(); + + _chain = await _blockchainService.GetChainAsync(); - [Benchmark] - public async Task MergeBlockStateTest() + var blockHash = _chain.BestChainHash; + while (true) { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + var blockState = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); + _blockStateSets.Add(blockState); + + var blockHeader = await _blockchainService.GetBlockHeaderByHashAsync(blockHash); + blockHash = blockHeader.PreviousBlockHash; + if (blockHash == _chain.LastIrreversibleBlockHash) break; } - [IterationCleanup] - public async Task IterationCleanup() + await _blockchainStateService.MergeBlockStateAsync(_chain.BestChainHeight, _chain.BestChainHash); + + for (var i = 0; i < BlockCount; i++) { - await _chainStateInfoCollection.SetAsync(_chain.Id.ToStorageKey(), _chainStateInfo); - foreach (var blockStateSet in _blockStateSets) - { - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - } + var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + await _osTestHelper.BroadcastTransactions(transactions); + var block = await _osTestHelper.MinedOneBlock(); + _blocks.Add(block); + + var blockState = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + _blockStateSets.Add(blockState); } - [GlobalCleanup] - public async Task GlobalCleanup() - { - foreach (var block in _blocks) - { - await _transactionPoolService.CleanByTransactionIdsAsync(block.TransactionIds); + var chain = await _blockchainService.GetChainAsync(); + await _chainManager.SetIrreversibleBlockAsync(chain, chain.BestChainHash); - await _transactionManager.RemoveTransactionsAsync(block.Body.TransactionIds); - await RemoveTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); - await _chainManager.RemoveChainBlockLinkAsync(block.GetHash()); - await _blockManager.RemoveBlockAsync(block.GetHash()); - } + _chainStateInfo = await _chainStateInfoCollection.GetAsync(chain.Id.ToStorageKey()); + } - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, - _chain.BestChainHeight); + [Benchmark] + public async Task MergeBlockStateTest() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + } + + [IterationCleanup] + public async Task IterationCleanup() + { + await _chainStateInfoCollection.SetAsync(_chain.Id.ToStorageKey(), _chainStateInfo); + foreach (var blockStateSet in _blockStateSets) await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + } - await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); + [GlobalCleanup] + public async Task GlobalCleanup() + { + foreach (var block in _blocks) + { + await _transactionPoolService.CleanByTransactionIdsAsync(block.TransactionIds); + + await _transactionManager.RemoveTransactionsAsync(block.Body.TransactionIds); + await RemoveTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); + await _chainManager.RemoveChainBlockLinkAsync(block.GetHash()); + await _blockManager.RemoveBlockAsync(block.GetHash()); } + + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, + _chain.BestChainHeight); + + await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/Fibonacci16Tests.cs b/bench/AElf.Benchmark/Fibonacci16Tests.cs index 5ae0283eee..b325e30008 100644 --- a/bench/AElf.Benchmark/Fibonacci16Tests.cs +++ b/bench/AElf.Benchmark/Fibonacci16Tests.cs @@ -8,63 +8,58 @@ using BenchmarkDotNet.Attributes; using Google.Protobuf.WellKnownTypes; -namespace AElf.Benchmark -{ - [MarkdownExporterAttribute.GitHub] - public class Fibonacci16Tests : BenchmarkTestBase - { - private IBlockchainService _blockchainService; - private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private OSTestHelper _osTestHelper; +namespace AElf.Benchmark; - private Transaction _transaction; - private Address _contractAddress; - private Chain _chain; - private TransactionTrace _transactionTrace; - - private const ulong Fibonacci16Result = 987; +[MarkdownExporterAttribute.GitHub] +public class Fibonacci16Tests : BenchmarkTestBase +{ + private const ulong Fibonacci16Result = 987; + private IBlockchainService _blockchainService; + private Chain _chain; + private Address _contractAddress; + private OSTestHelper _osTestHelper; - [GlobalSetup] - public async Task GlobalSetup() - { - _blockchainService = GetRequiredService(); - _transactionReadOnlyExecutionService = GetRequiredService(); - _osTestHelper = GetRequiredService(); + private Transaction _transaction; + private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + private TransactionTrace _transactionTrace; - _contractAddress = await _osTestHelper.DeployContract(); - _chain = await _blockchainService.GetChainAsync(); - } + [GlobalSetup] + public async Task GlobalSetup() + { + _blockchainService = GetRequiredService(); + _transactionReadOnlyExecutionService = GetRequiredService(); + _osTestHelper = GetRequiredService(); - [IterationSetup] - public void IterationSetup() - { - _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, - nameof(PerformanceTestContract.PerformanceTestContract.Fibonacci), new UInt64Value - { - Value = 16 - }); - } + _contractAddress = await _osTestHelper.DeployContract(); + _chain = await _blockchainService.GetChainAsync(); + } - [Benchmark] - public async Task Fibonacci16() - { - _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = _chain.BestChainHash, - BlockHeight = _chain.BestChainHeight - }, - _transaction, - TimestampHelper.GetUtcNow()); - } + [IterationSetup] + public void IterationSetup() + { + _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, + nameof(PerformanceTestContract.PerformanceTestContract.Fibonacci), new UInt64Value + { + Value = 16 + }); + } - [IterationCleanup] - public void IterationCleanup() - { - var calResult = UInt64Value.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; - if (calResult != Fibonacci16Result) + [Benchmark] + public async Task Fibonacci16() + { + _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext { - throw new Exception("execute fail"); - } - } + BlockHash = _chain.BestChainHash, + BlockHeight = _chain.BestChainHeight + }, + _transaction, + TimestampHelper.GetUtcNow()); + } + + [IterationCleanup] + public void IterationCleanup() + { + var calResult = UInt64Value.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; + if (calResult != Fibonacci16Result) throw new Exception("execute fail"); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/LoopDivAdd10MTests.cs b/bench/AElf.Benchmark/LoopDivAdd10MTests.cs index 82e04e7d24..e625617e31 100644 --- a/bench/AElf.Benchmark/LoopDivAdd10MTests.cs +++ b/bench/AElf.Benchmark/LoopDivAdd10MTests.cs @@ -9,66 +9,61 @@ using BenchmarkDotNet.Attributes; using Google.Protobuf.WellKnownTypes; -namespace AElf.Benchmark -{ - [MarkdownExporterAttribute.GitHub] - public class LoopDivAdd10MTests : BenchmarkTestBase - { - private IBlockchainService _blockchainService; - private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private OSTestHelper _osTestHelper; +namespace AElf.Benchmark; - private Transaction _transaction; - private Address _contractAddress; - private Chain _chain; - private TransactionTrace _transactionTrace; - - private const double ExecuteResult = 501.67224080267556; +[MarkdownExporterAttribute.GitHub] +public class LoopDivAdd10MTests : BenchmarkTestBase +{ + private const double ExecuteResult = 501.67224080267556; + private IBlockchainService _blockchainService; + private Chain _chain; + private Address _contractAddress; + private OSTestHelper _osTestHelper; - [GlobalSetup] - public async Task GlobalSetup() - { - _blockchainService = GetRequiredService(); - _transactionReadOnlyExecutionService = GetRequiredService(); - _osTestHelper = GetRequiredService(); + private Transaction _transaction; + private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + private TransactionTrace _transactionTrace; - _contractAddress = await _osTestHelper.DeployContract(); - _chain = await _blockchainService.GetChainAsync(); - } + [GlobalSetup] + public async Task GlobalSetup() + { + _blockchainService = GetRequiredService(); + _transactionReadOnlyExecutionService = GetRequiredService(); + _osTestHelper = GetRequiredService(); - [IterationSetup] - public void IterationSetup() - { - _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, - nameof(PerformanceTestContract.PerformanceTestContract.LoopDivAdd), new DivAddTestInput() - { - X = 100, - Y = 300, - K = 500, - N = 10000000 - }); - } + _contractAddress = await _osTestHelper.DeployContract(); + _chain = await _blockchainService.GetChainAsync(); + } - [Benchmark] - public async Task LoopDivAdd10M() - { - _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = _chain.BestChainHash, - BlockHeight = _chain.BestChainHeight - }, - _transaction, - TimestampHelper.GetUtcNow()); - } + [IterationSetup] + public void IterationSetup() + { + _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, + nameof(PerformanceTestContract.PerformanceTestContract.LoopDivAdd), new DivAddTestInput + { + X = 100, + Y = 300, + K = 500, + N = 10000000 + }); + } - [IterationCleanup] - public void IterationCleanup() - { - var calResult = DoubleValue.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; - if (calResult != ExecuteResult) + [Benchmark] + public async Task LoopDivAdd10M() + { + _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext { - throw new Exception("execute fail"); - } - } + BlockHash = _chain.BestChainHash, + BlockHeight = _chain.BestChainHeight + }, + _transaction, + TimestampHelper.GetUtcNow()); + } + + [IterationCleanup] + public void IterationCleanup() + { + var calResult = DoubleValue.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; + if (calResult != ExecuteResult) throw new Exception("execute fail"); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/LoopExpNop1MTests.cs b/bench/AElf.Benchmark/LoopExpNop1MTests.cs index 03be535b8c..5dc5651ec3 100644 --- a/bench/AElf.Benchmark/LoopExpNop1MTests.cs +++ b/bench/AElf.Benchmark/LoopExpNop1MTests.cs @@ -9,65 +9,60 @@ using BenchmarkDotNet.Attributes; using Google.Protobuf.WellKnownTypes; -namespace AElf.Benchmark -{ - [MarkdownExporterAttribute.GitHub] - public class LoopExpNop1MTests : BenchmarkTestBase - { - private IBlockchainService _blockchainService; - private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private OSTestHelper _osTestHelper; +namespace AElf.Benchmark; - private Transaction _transaction; - private Address _contractAddress; - private Chain _chain; - private TransactionTrace _transactionTrace; - - private const int ExecuteResult = 15; +[MarkdownExporterAttribute.GitHub] +public class LoopExpNop1MTests : BenchmarkTestBase +{ + private const int ExecuteResult = 15; + private IBlockchainService _blockchainService; + private Chain _chain; + private Address _contractAddress; + private OSTestHelper _osTestHelper; - [GlobalSetup] - public async Task GlobalSetup() - { - _blockchainService = GetRequiredService(); - _transactionReadOnlyExecutionService = GetRequiredService(); - _osTestHelper = GetRequiredService(); + private Transaction _transaction; + private ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + private TransactionTrace _transactionTrace; - _contractAddress = await _osTestHelper.DeployContract(); - _chain = await _blockchainService.GetChainAsync(); - } + [GlobalSetup] + public async Task GlobalSetup() + { + _blockchainService = GetRequiredService(); + _transactionReadOnlyExecutionService = GetRequiredService(); + _osTestHelper = GetRequiredService(); - [IterationSetup] - public void IterationSetup() - { - _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, - nameof(PerformanceTestContract.PerformanceTestContract.LoopExpNop), new PerformanceTesteInput() - { - Exponent = 0, - Seed = ExecuteResult, - N = 1000000 - }); - } + _contractAddress = await _osTestHelper.DeployContract(); + _chain = await _blockchainService.GetChainAsync(); + } - [Benchmark] - public async Task LoopExpNop1M() - { - _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = _chain.BestChainHash, - BlockHeight = _chain.BestChainHeight - }, - _transaction, - TimestampHelper.GetUtcNow()); - } + [IterationSetup] + public void IterationSetup() + { + _transaction = _osTestHelper.GenerateTransaction(SampleAddress.AddressList[0], _contractAddress, + nameof(PerformanceTestContract.PerformanceTestContract.LoopExpNop), new PerformanceTesteInput + { + Exponent = 0, + Seed = ExecuteResult, + N = 1000000 + }); + } - [IterationCleanup] - public void IterationCleanup() - { - var calResult = UInt64Value.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; - if (calResult != ExecuteResult) + [Benchmark] + public async Task LoopExpNop1M() + { + _transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext { - throw new Exception("execute fail"); - } - } + BlockHash = _chain.BestChainHash, + BlockHeight = _chain.BestChainHeight + }, + _transaction, + TimestampHelper.GetUtcNow()); + } + + [IterationCleanup] + public void IterationCleanup() + { + var calResult = UInt64Value.Parser.ParseFrom(_transactionTrace.ReturnValue).Value; + if (calResult != ExecuteResult) throw new Exception("execute fail"); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/MinerTests.cs b/bench/AElf.Benchmark/MinerTests.cs index 345753577b..d05cf12922 100644 --- a/bench/AElf.Benchmark/MinerTests.cs +++ b/bench/AElf.Benchmark/MinerTests.cs @@ -1,77 +1,73 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Infrastructure; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.TransactionPool.Application; using AElf.OS; using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class MinerTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class MinerTests : BenchmarkTestBase - { - private IBlockchainService _blockchainService; - private IMinerService _minerService; - private INotModifiedCachedStateStore _blockStateSets; - private ITransactionPoolService _transactionPoolService; - private ITransactionManager _transactionManager; - private OSTestHelper _osTestHelper; + private Block _block; + private IBlockchainService _blockchainService; + private INotModifiedCachedStateStore _blockStateSets; - private Chain _chain; - private Block _block; - private List _transactions; + private Chain _chain; + private IMinerService _minerService; + private OSTestHelper _osTestHelper; + private ITransactionManager _transactionManager; + private ITransactionPoolService _transactionPoolService; + private List _transactions; - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - [GlobalSetup] - public async Task GlobalSetup() - { - _blockchainService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _minerService = GetRequiredService(); - _blockStateSets = GetRequiredService>(); - _transactionManager = GetRequiredService(); - _transactionPoolService = GetRequiredService(); + [GlobalSetup] + public async Task GlobalSetup() + { + _blockchainService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _minerService = GetRequiredService(); + _blockStateSets = GetRequiredService>(); + _transactionManager = GetRequiredService(); + _transactionPoolService = GetRequiredService(); - _transactions = new List(); - _chain = await _blockchainService.GetChainAsync(); - } + _transactions = new List(); + _chain = await _blockchainService.GetChainAsync(); + } - [IterationSetup] - public async Task IterationSetup() - { - _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - await _osTestHelper.BroadcastTransactions(_transactions); - } + [IterationSetup] + public async Task IterationSetup() + { + _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + await _osTestHelper.BroadcastTransactions(_transactions); + } - [Benchmark] - public async Task MineBlockTest() - { - _block = (await _minerService.MineAsync(_chain.BestChainHash, _chain.BestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; - } + [Benchmark] + public async Task MineBlockTest() + { + _block = (await _minerService.MineAsync(_chain.BestChainHash, _chain.BestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); - var transactionIds = _transactions.Select(t => t.GetHash()).ToList(); - await _transactionManager.RemoveTransactionsAsync(transactionIds); - await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); + [IterationCleanup] + public async Task IterationCleanup() + { + await _blockStateSets.RemoveAsync(_block.GetHash().ToStorageKey()); + var transactionIds = _transactions.Select(t => t.GetHash()).ToList(); + await _transactionManager.RemoveTransactionsAsync(transactionIds); + await RemoveTransactionResultsAsync(transactionIds, _block.GetHash()); - await _transactionPoolService.CleanByTransactionIdsAsync(_transactions.Select(t => t.GetHash()).ToList()); - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, - _chain.BestChainHeight); - } + await _transactionPoolService.CleanByTransactionIdsAsync(_transactions.Select(t => t.GetHash()).ToList()); + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, + _chain.BestChainHeight); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/MiningTxHubBenchmark.cs b/bench/AElf.Benchmark/MiningTxHubBenchmark.cs index b1b5749822..9203d89423 100644 --- a/bench/AElf.Benchmark/MiningTxHubBenchmark.cs +++ b/bench/AElf.Benchmark/MiningTxHubBenchmark.cs @@ -3,79 +3,76 @@ using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Miner.Application; -using AElf.Kernel.TransactionPool; using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class MiningTxHubBenchmark : MiningWithTransactionsBenchmarkBase { - [MarkdownExporterAttribute.GitHub] - public class MiningTxHubBenchmark : MiningWithTransactionsBenchmarkBase - { - private readonly IMinerService _minerService; - private readonly ITransactionManager _transactionManager; + private readonly IMinerService _minerService; + private readonly List _transactionIdList = new(); + private readonly ITransactionManager _transactionManager; - public MiningTxHubBenchmark() - { - _minerService = GetRequiredService(); - _transactionManager = GetRequiredService(); - } + private Chain _chain; - private Chain _chain; - private readonly List _transactionIdList = new List(); + [Params(1000, 3000)] public int TransactionCount; - [Params(1000, 3000)] public int TransactionCount; + public MiningTxHubBenchmark() + { + _minerService = GetRequiredService(); + _transactionManager = GetRequiredService(); + } - [GlobalSetup] - public async Task GlobalSetup() - { - await InitializeChainAsync(); - _chain = await BlockchainService.GetChainAsync(); - } + [GlobalSetup] + public async Task GlobalSetup() + { + await InitializeChainAsync(); + _chain = await BlockchainService.GetChainAsync(); + } - [IterationSetup] - public async Task IterationSetup() - { - await AddTransactionsToTxHub(TransactionCount); - } + [IterationSetup] + public async Task IterationSetup() + { + await AddTransactionsToTxHub(TransactionCount); + } - [Benchmark] - public async Task MineWithTxHubAsync() - { - var txCount = 0; - var preBlockHash = _chain.BestChainHash; - var preBlockHeight = _chain.BestChainHeight; + [Benchmark] + public async Task MineWithTxHubAsync() + { + var txCount = 0; + var preBlockHash = _chain.BestChainHash; + var preBlockHeight = _chain.BestChainHeight; - while (txCount < TransactionCount) - { - var blockExecutedSet = await _minerService.MineAsync(preBlockHash, preBlockHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000)); - txCount += blockExecutedSet.TransactionIds.Count(); - _transactionIdList.AddRange(blockExecutedSet.TransactionIds.ToList()); - await BlockchainService.SetBestChainAsync(_chain, preBlockHeight, preBlockHash); - await TransactionPoolService.CleanByTransactionIdsAsync(blockExecutedSet.TransactionIds); - await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(preBlockHash, preBlockHeight); - } + while (txCount < TransactionCount) + { + var blockExecutedSet = await _minerService.MineAsync(preBlockHash, preBlockHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000)); + txCount += blockExecutedSet.TransactionIds.Count(); + _transactionIdList.AddRange(blockExecutedSet.TransactionIds.ToList()); + await BlockchainService.SetBestChainAsync(_chain, preBlockHeight, preBlockHash); + await TransactionPoolService.CleanByTransactionIdsAsync(blockExecutedSet.TransactionIds); + await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(preBlockHash, preBlockHeight); } + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _transactionManager.RemoveTransactionsAsync(_transactionIdList); - await TransactionPoolService.CleanByTransactionIdsAsync(_transactionIdList); + [IterationCleanup] + public async Task IterationCleanup() + { + await _transactionManager.RemoveTransactionsAsync(_transactionIdList); + await TransactionPoolService.CleanByTransactionIdsAsync(_transactionIdList); - await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, - _chain.BestChainHeight); - _transactionIdList.Clear(); - } + await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, + _chain.BestChainHeight); + _transactionIdList.Clear(); + } - private async Task AddTransactionsToTxHub(int txCount) - { - var txList = await GenerateTransferTransactionsAsync(txCount); - await TransactionPoolService.AddTransactionsAsync(txList); - } + private async Task AddTransactionsToTxHub(int txCount) + { + var txList = await GenerateTransferTransactionsAsync(txCount); + await TransactionPoolService.AddTransactionsAsync(txList); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/Program.cs b/bench/AElf.Benchmark/Program.cs index a3c0b2da41..bc0d10d859 100644 --- a/bench/AElf.Benchmark/Program.cs +++ b/bench/AElf.Benchmark/Program.cs @@ -5,37 +5,36 @@ using BenchmarkDotNet.Running; using Volo.Abp; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +internal class Program { - class Program + private static void Main(string[] args) { - static void Main(string[] args) + RegisterAssemblyResolveEvent(); + using (var application = AbpApplicationFactory.Create(options => + { + options.UseAutofac(); + })) { - RegisterAssemblyResolveEvent(); - using (var application = AbpApplicationFactory.Create(options => - { - options.UseAutofac(); - })) - { - application.Initialize(); - BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new DebugInProcessConfig()); - } + application.Initialize(); + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new DebugInProcessConfig()); } + } - private static void RegisterAssemblyResolveEvent() - { - AppDomain currentDomain = AppDomain.CurrentDomain; + private static void RegisterAssemblyResolveEvent() + { + var currentDomain = AppDomain.CurrentDomain; - currentDomain.AssemblyResolve += OnAssemblyResolve; - } + currentDomain.AssemblyResolve += OnAssemblyResolve; + } - private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) - { - string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); - if (!File.Exists(assemblyPath)) return null; - Assembly assembly = Assembly.LoadFrom(assemblyPath); - return assembly; - } + private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + { + var folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); + if (!File.Exists(assemblyPath)) return null; + var assembly = Assembly.LoadFrom(assemblyPath); + return assembly; } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/TransactionVerifySignatureTests.cs b/bench/AElf.Benchmark/TransactionVerifySignatureTests.cs index 5b99bb30ae..e66d975bb4 100644 --- a/bench/AElf.Benchmark/TransactionVerifySignatureTests.cs +++ b/bench/AElf.Benchmark/TransactionVerifySignatureTests.cs @@ -4,27 +4,26 @@ using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class TransactionVerifySignatureTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class TransactionVerifySignatureTests : BenchmarkTestBase - { - private OSTestHelper _osTestHelper; + private OSTestHelper _osTestHelper; - private Transaction _transaction; + private Transaction _transaction; - [GlobalSetup] - public async Task GlobalSetup() - { - _osTestHelper = GetRequiredService(); + [GlobalSetup] + public async Task GlobalSetup() + { + _osTestHelper = GetRequiredService(); - _transaction = await _osTestHelper.GenerateTransferTransaction(); - } + _transaction = await _osTestHelper.GenerateTransferTransaction(); + } - [Benchmark] - public void VerifySignatureTest() - { - _transaction.VerifySignature(); - } + [Benchmark] + public void VerifySignatureTest() + { + _transaction.VerifySignature(); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/TxHubHandleBestChainFoundTests.cs b/bench/AElf.Benchmark/TxHubHandleBestChainFoundTests.cs index c060f2cace..af464ee92e 100644 --- a/bench/AElf.Benchmark/TxHubHandleBestChainFoundTests.cs +++ b/bench/AElf.Benchmark/TxHubHandleBestChainFoundTests.cs @@ -1,87 +1,83 @@ using System.Threading.Tasks; using AElf.Kernel; -using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Kernel.TransactionPool; using AElf.Kernel.TransactionPool.Application; using AElf.OS; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class TxHubHandleBestChainFoundTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class TxHubHandleBestChainFoundTests : BenchmarkTestBase - { - private IBlockchainStore _chains; - private IBlockchainStore _chainBlockLinks; - private IChainManager _chainManager; - private IBlockManager _blockManager; - private ITransactionManager _transactionManager; - private ITransactionPoolService _transactionPoolService; - private IBlockchainService _blockchainService; - private OSTestHelper _osTestHelper; + private Block _block; + private IBlockchainService _blockchainService; + private IBlockManager _blockManager; - private Chain _chain; - private Block _block; + private Chain _chain; + private IBlockchainStore _chainBlockLinks; + private IChainManager _chainManager; + private IBlockchainStore _chains; + private OSTestHelper _osTestHelper; + private ITransactionManager _transactionManager; + private ITransactionPoolService _transactionPoolService; - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - [GlobalSetup] - public async Task GlobalSetup() - { - _chains = GetRequiredService>(); - _chainBlockLinks = GetRequiredService>(); - _chainManager = GetRequiredService(); - _blockManager = GetRequiredService(); - _transactionManager = GetRequiredService(); - _transactionPoolService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _osTestHelper = GetRequiredService(); + [GlobalSetup] + public async Task GlobalSetup() + { + _chains = GetRequiredService>(); + _chainBlockLinks = GetRequiredService>(); + _chainManager = GetRequiredService(); + _blockManager = GetRequiredService(); + _transactionManager = GetRequiredService(); + _transactionPoolService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _osTestHelper = GetRequiredService(); - _chain = await _blockchainService.GetChainAsync(); - } + _chain = await _blockchainService.GetChainAsync(); + } - [IterationSetup] - public async Task IterationSetup() - { - var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - await _transactionPoolService.AddTransactionsAsync(transactions); - var chain = await _blockchainService.GetChainAsync(); - _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - await _blockchainService.AddBlockAsync(_block); - await _chainBlockLinks.SetAsync( - chain.Id.ToStorageKey() + KernelConstants.StorageKeySeparator + _block.GetHash().ToStorageKey(), - new ChainBlockLink() - { - BlockHash = _block.GetHash(), - Height = _block.Height, - PreviousBlockHash = _block.Header.PreviousBlockHash, - IsLinked = true - }); - await _blockchainService.SetBestChainAsync(chain, _block.Height, _block.GetHash()); - } + [IterationSetup] + public async Task IterationSetup() + { + var transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + await _transactionPoolService.AddTransactionsAsync(transactions); + var chain = await _blockchainService.GetChainAsync(); + _block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + await _blockchainService.AddBlockAsync(_block); + await _chainBlockLinks.SetAsync( + chain.Id.ToStorageKey() + KernelConstants.StorageKeySeparator + _block.GetHash().ToStorageKey(), + new ChainBlockLink + { + BlockHash = _block.GetHash(), + Height = _block.Height, + PreviousBlockHash = _block.Header.PreviousBlockHash, + IsLinked = true + }); + await _blockchainService.SetBestChainAsync(chain, _block.Height, _block.GetHash()); + } - [Benchmark] - public async Task HandleBestChainFoundTest() - { - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_block.GetHash(), _block.Height); - } + [Benchmark] + public async Task HandleBestChainFoundTest() + { + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_block.GetHash(), _block.Height); + } - [IterationCleanup] - public async Task IterationCleanup() - { - await _transactionPoolService.CleanByTransactionIdsAsync(_block.TransactionIds); - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, - _chain.BestChainHeight); + [IterationCleanup] + public async Task IterationCleanup() + { + await _transactionPoolService.CleanByTransactionIdsAsync(_block.TransactionIds); + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, + _chain.BestChainHeight); - await _transactionManager.RemoveTransactionsAsync(_block.Body.TransactionIds); - await _chainManager.RemoveChainBlockLinkAsync(_block.GetHash()); - await _blockManager.RemoveBlockAsync(_block.GetHash()); - await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); - } + await _transactionManager.RemoveTransactionsAsync(_block.Body.TransactionIds); + await _chainManager.RemoveChainBlockLinkAsync(_block.GetHash()); + await _blockManager.RemoveBlockAsync(_block.GetHash()); + await _chains.SetAsync(_chain.Id.ToStorageKey(), _chain); } } \ No newline at end of file diff --git a/bench/AElf.Benchmark/TxHubTransactionsReceiveTests.cs b/bench/AElf.Benchmark/TxHubTransactionsReceiveTests.cs index db82e00c07..85fa68fb47 100644 --- a/bench/AElf.Benchmark/TxHubTransactionsReceiveTests.cs +++ b/bench/AElf.Benchmark/TxHubTransactionsReceiveTests.cs @@ -4,60 +4,56 @@ using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; -using AElf.Kernel.SmartContractExecution.Application; -using AElf.Kernel.TransactionPool; using AElf.Kernel.TransactionPool.Application; using AElf.OS; using AElf.Types; using BenchmarkDotNet.Attributes; -namespace AElf.Benchmark +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class TxHubTransactionsReceiveTests : BenchmarkTestBase { - [MarkdownExporterAttribute.GitHub] - public class TxHubTransactionsReceiveTests : BenchmarkTestBase + private IBlockchainService _blockchainService; + + private Chain _chain; + private OSTestHelper _osTestHelper; + private ITransactionManager _transactionManager; + private ITransactionPoolService _transactionPoolService; + private List _transactions; + + [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; + + [GlobalSetup] + public async Task GlobalSetup() + { + _blockchainService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _transactionManager = GetRequiredService(); + _transactionPoolService = GetRequiredService(); + + _chain = await _blockchainService.GetChainAsync(); + } + + [IterationSetup] + public async Task IterationSetup() { - private IBlockchainService _blockchainService; - private ITransactionPoolService _transactionPoolService; - private ITransactionManager _transactionManager; - private OSTestHelper _osTestHelper; - - private Chain _chain; - private List _transactions; - - [Params(1, 10, 100, 1000, 3000, 5000)] public int TransactionCount; - - [GlobalSetup] - public async Task GlobalSetup() - { - _blockchainService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _transactionManager = GetRequiredService(); - _transactionPoolService = GetRequiredService(); - - _chain = await _blockchainService.GetChainAsync(); - } - - [IterationSetup] - public async Task IterationSetup() - { - _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); - } - - [Benchmark] - public async Task HandleTransactionsReceivedTest() - { - await _transactionPoolService.AddTransactionsAsync(_transactions); - } - - [IterationCleanup] - public async Task IterationCleanup() - { - await _transactionPoolService.CleanByTransactionIdsAsync(_transactions.Select(t => t.GetHash()).ToList()); - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, - _chain.BestChainHeight); - - await _transactionManager.RemoveTransactionsAsync(_transactions.Select(t => t.GetHash()).ToList()); - } + _transactions = await _osTestHelper.GenerateTransferTransactions(TransactionCount); + } + + [Benchmark] + public async Task HandleTransactionsReceivedTest() + { + await _transactionPoolService.AddTransactionsAsync(_transactions); + } + + [IterationCleanup] + public async Task IterationCleanup() + { + await _transactionPoolService.CleanByTransactionIdsAsync(_transactions.Select(t => t.GetHash()).ToList()); + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(_chain.BestChainHash, + _chain.BestChainHeight); + + await _transactionManager.RemoveTransactionsAsync(_transactions.Select(t => t.GetHash()).ToList()); } } \ No newline at end of file diff --git a/bench/AElf.Database.Benches/AElf.Database.Benches.csproj b/bench/AElf.Database.Benches/AElf.Database.Benches.csproj index 6b7bde0461..c4374730fd 100644 --- a/bench/AElf.Database.Benches/AElf.Database.Benches.csproj +++ b/bench/AElf.Database.Benches/AElf.Database.Benches.csproj @@ -7,14 +7,14 @@ - - - + + + - - + + diff --git a/bench/AElf.Database.Benches/Assembly.cs b/bench/AElf.Database.Benches/Assembly.cs index 217120083b..41a898e37e 100644 --- a/bench/AElf.Database.Benches/Assembly.cs +++ b/bench/AElf.Database.Benches/Assembly.cs @@ -1,3 +1,3 @@ using Xunit; -[assembly: CollectionBehavior(DisableTestParallelization = true)] +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/bench/AElf.Database.Benches/DatabaseBenchAElfModule.cs b/bench/AElf.Database.Benches/DatabaseBenchAElfModule.cs index 3347f24507..4c3418d3d3 100644 --- a/bench/AElf.Database.Benches/DatabaseBenchAElfModule.cs +++ b/bench/AElf.Database.Benches/DatabaseBenchAElfModule.cs @@ -1,13 +1,12 @@ using AElf.BenchBase; using Volo.Abp.Modularity; -namespace AElf.Database.Benches +namespace AElf.Database.Benches; + +public class DatabaseBenchAElfModule : BenchBaseAElfModule { - public class DatabaseBenchAElfModule : BenchBaseAElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - } + context.Services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); } } \ No newline at end of file diff --git a/bench/AElf.Database.Benches/DatabaseTests.cs b/bench/AElf.Database.Benches/DatabaseTests.cs index d91e34114d..459560eb56 100644 --- a/bench/AElf.Database.Benches/DatabaseTests.cs +++ b/bench/AElf.Database.Benches/DatabaseTests.cs @@ -6,66 +6,62 @@ using Volo.Abp.Threading; using Xunit.Abstractions; -namespace AElf.Database.Benches +namespace AElf.Database.Benches; + +public class DatabaseTests : BenchBaseTest { - public class DatabaseTests : BenchBaseTest - { - public DatabaseTests(ITestOutputHelper output) - { - Trace.Listeners.Clear(); - Trace.Listeners.Add(new XunitTraceListener(output)); - - SetTestOutputHelper(output); - - GetService>().LogWarning("Hello"); - } - + private Counter _counter; + private DbContext _dbContext; - private Counter _counter; + private IKeyValueDatabase _memoryDatabase; - private IKeyValueDatabase _memoryDatabase; - private DbContext _dbContext; + private readonly byte[] _testBytes = "BenchmarkContextBenchmarkContextBenchmarkContextBenchmarkContext".GetBytes(); - private byte[] _testBytes = "BenchmarkContextBenchmarkContextBenchmarkContextBenchmarkContext".GetBytes(); + public DatabaseTests(ITestOutputHelper output) + { + Trace.Listeners.Clear(); + Trace.Listeners.Add(new XunitTraceListener(output)); - [PerfSetup] - public void Setup(BenchmarkContext context) - { - _counter = context.GetCounter("TestCounter"); + SetTestOutputHelper(output); - _dbContext = this.GetService(); + GetService>().LogWarning("Hello"); + } - _memoryDatabase = _dbContext.Database; - _memoryDatabase.SetAsync("hello", _testBytes); - - - } + [PerfSetup] + public void Setup(BenchmarkContext context) + { + _counter = context.GetCounter("TestCounter"); - [NBenchFact] - [PerfBenchmark(NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 5000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 0d)] - public void Set() - { - AsyncHelper.RunSync(() => _memoryDatabase.SetAsync("hello", _testBytes)); - _counter.Increment(); - } + _dbContext = GetService(); - [NBenchFact] - [PerfBenchmark(NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 5000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 0d)] - public void Get() - { - AsyncHelper.RunSync(() => _memoryDatabase.GetAsync("hello")); + _memoryDatabase = _dbContext.Database; + _memoryDatabase.SetAsync("hello", _testBytes); + } - _counter.Increment(); - } + [NBenchFact] + [PerfBenchmark(NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 5000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 0d)] + public void Set() + { + AsyncHelper.RunSync(() => _memoryDatabase.SetAsync("hello", _testBytes)); + _counter.Increment(); + } + + [NBenchFact] + [PerfBenchmark(NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 5000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 0d)] + public void Get() + { + AsyncHelper.RunSync(() => _memoryDatabase.GetAsync("hello")); - [PerfCleanup] - public void Cleanup() - { - // does nothing - } + _counter.Increment(); + } + + [PerfCleanup] + public void Cleanup() + { + // does nothing } } \ No newline at end of file diff --git a/bench/AElf.Database.Benches/DbContext.cs b/bench/AElf.Database.Benches/DbContext.cs index 48f03184c4..1b60eb1f6f 100644 --- a/bench/AElf.Database.Benches/DbContext.cs +++ b/bench/AElf.Database.Benches/DbContext.cs @@ -1,6 +1,5 @@ -namespace AElf.Database.Benches +namespace AElf.Database.Benches; + +internal class DbContext : KeyValueDbContext { - class DbContext : KeyValueDbContext - { - } } \ No newline at end of file diff --git a/bench/AElf.Database.Benches/StorageKeyTests.cs b/bench/AElf.Database.Benches/StorageKeyTests.cs index 8b6d1f8c57..b582749447 100644 --- a/bench/AElf.Database.Benches/StorageKeyTests.cs +++ b/bench/AElf.Database.Benches/StorageKeyTests.cs @@ -5,115 +5,113 @@ using Pro.NBench.xUnit.XunitExtensions; using Xunit.Abstractions; -namespace AElf.Database.Benches +namespace AElf.Database.Benches; + +public class StorageKeyTests { - public class StorageKeyTests + private Counter _counter; + private Hash _hash; + + private string _hashBase64; + private byte[] _hashBytes; + + public StorageKeyTests(ITestOutputHelper output) { - public StorageKeyTests(ITestOutputHelper output) - { - Trace.Listeners.Clear(); - Trace.Listeners.Add(new XunitTraceListener(output)); - } + Trace.Listeners.Clear(); + Trace.Listeners.Add(new XunitTraceListener(output)); + } - - private Counter _counter; - private Hash _hash; - private string _hashBase64; - private byte[] _hashBytes; - + [PerfSetup] + public void Setup(BenchmarkContext context) + { + _counter = context.GetCounter("TestCounter"); + _hash = HashHelper.ComputeFrom("FromStringFromStringFromStringFromString"); + _hashBytes = _hash.Value.ToByteArray(); + _hashBase64 = _hash.Value.ToBase64(); + } - [PerfSetup] - public void Setup(BenchmarkContext context) - { - _counter = context.GetCounter("TestCounter"); - _hash = HashHelper.ComputeFrom("FromStringFromStringFromStringFromString"); - _hashBytes = _hash.Value.ToByteArray(); - _hashBase64 = _hash.Value.ToBase64(); - } + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void HashToStorageKey() + { + _hash.ToHex(); + _counter.Increment(); + } - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void HashToStorageKey() - { - _hash.ToHex(); - _counter.Increment(); - } - - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void HashToUtf8() - { - _hash.Value.ToStringUtf8(); - _counter.Increment(); - } - - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void HashToBase64() - { - _hash.Value.ToBase64(); - _counter.Increment(); - } - - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void HashToBytes() - { - _hash.Value.ToByteArray(); - _counter.Increment(); - } - - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void CombineBytes() - { - - var arr = _hashBytes.Concat(_hashBytes).ToArray(); - _counter.Increment(); - } - - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] - //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void CombineBase64() - { - var srt = _hashBase64 + _hashBase64; - _counter.Increment(); - } + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void HashToUtf8() + { + _hash.Value.ToStringUtf8(); + _counter.Increment(); + } - [PerfCleanup] - public void Cleanup(){ - // does nothing - } + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void HashToBase64() + { + _hash.Value.ToBase64(); + _counter.Increment(); + } + + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void HashToBytes() + { + _hash.Value.ToByteArray(); + _counter.Increment(); + } + + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void CombineBytes() + { + var arr = _hashBytes.Concat(_hashBytes).ToArray(); + _counter.Increment(); + } + + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, .0d)] + //[MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void CombineBase64() + { + var srt = _hashBase64 + _hashBase64; + _counter.Increment(); + } + + [PerfCleanup] + public void Cleanup() + { + // does nothing } } \ No newline at end of file diff --git a/bench/AElf.Database.Benches/ThroughPutTest.cs b/bench/AElf.Database.Benches/ThroughPutTest.cs index 54e41e7c4b..d7bdd6ebf2 100644 --- a/bench/AElf.Database.Benches/ThroughPutTest.cs +++ b/bench/AElf.Database.Benches/ThroughPutTest.cs @@ -1,43 +1,41 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; using NBench; using Pro.NBench.xUnit.XunitExtensions; using Xunit.Abstractions; -namespace AElf.Database.Benches +namespace AElf.Database.Benches; + +public class ThroughPutTest { - public class ThroughPutTest - { - public ThroughPutTest(ITestOutputHelper output) - { - Trace.Listeners.Clear(); - Trace.Listeners.Add(new XunitTraceListener(output)); - } + private Counter _counter; - - private Counter _counter; + public ThroughPutTest(ITestOutputHelper output) + { + Trace.Listeners.Clear(); + Trace.Listeners.Add(new XunitTraceListener(output)); + } - [PerfSetup] - public void Setup(BenchmarkContext context) - { - _counter = context.GetCounter("TestCounter"); - } + [PerfSetup] + public void Setup(BenchmarkContext context) + { + _counter = context.GetCounter("TestCounter"); + } - [NBenchFact] - [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", - NumberOfIterations = 3, RunMode = RunMode.Throughput, - RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] - [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 10000000.0d)] - [MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] - [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] - public void Benchmark() - { - _counter.Increment(); - } + [NBenchFact] + [PerfBenchmark(Description = "Test to ensure that a minimal throughput test can be rapidly executed.", + NumberOfIterations = 3, RunMode = RunMode.Throughput, + RunTimeMilliseconds = 1000, TestMode = TestMode.Test)] + [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 10000000.0d)] + [MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThanOrEqualTo, ByteConstants.ThirtyTwoKb)] + [GcTotalAssertion(GcMetric.TotalCollections, GcGeneration.Gen2, MustBe.ExactlyEqualTo, 0.0d)] + public void Benchmark() + { + _counter.Increment(); + } - [PerfCleanup] - public void Cleanup(){ - // does nothing - } + [PerfCleanup] + public void Cleanup() + { + // does nothing } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/AElf.Contracts.Association.csproj b/contract/AElf.Contracts.Association/AElf.Contracts.Association.csproj index d5be4e2769..0d2c24b45d 100644 --- a/contract/AElf.Contracts.Association/AElf.Contracts.Association.csproj +++ b/contract/AElf.Contracts.Association/AElf.Contracts.Association.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Association true - Association is a contract that enables the creation of organizations and approvals. - The created proposals can be voted for and eventually released. + Association is a contract that enables the creation of organizations and approvals. + The created proposals can be voted for and eventually released. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs0.proto diff --git a/contract/AElf.Contracts.Association/Association.cs b/contract/AElf.Contracts.Association/Association.cs index 8011fc85a9..db9a2d81dd 100644 --- a/contract/AElf.Contracts.Association/Association.cs +++ b/contract/AElf.Contracts.Association/Association.cs @@ -1,296 +1,290 @@ using System.Linq; -using AElf.Standards.ACS3; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; -using CreateProposalInput = AElf.Standards.ACS3.CreateProposalInput; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public partial class AssociationContract : AssociationContractImplContainer.AssociationContractImplBase { - public partial class AssociationContract : AssociationContractImplContainer.AssociationContractImplBase + #region View + + public override Organization GetOrganization(Address address) { - #region View + return State.Organizations[address] ?? new Organization(); + } - public override Organization GetOrganization(Address address) - { - return State.Organizations[address] ?? new Organization(); - } + public override ProposalOutput GetProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + if (proposal == null) return new ProposalOutput(); + + var organization = State.Organizations[proposal.OrganizationAddress]; + var readyToRelease = IsReleaseThresholdReached(proposal, organization); - public override ProposalOutput GetProposal(Hash proposalId) + return new ProposalOutput { - var proposal = State.Proposals[proposalId]; - if (proposal == null) - { - return new ProposalOutput(); - } + ProposalId = proposalId, + ContractMethodName = proposal.ContractMethodName, + ExpiredTime = proposal.ExpiredTime, + OrganizationAddress = proposal.OrganizationAddress, + Params = proposal.Params, + Proposer = proposal.Proposer, + ToAddress = proposal.ToAddress, + ToBeReleased = readyToRelease, + ApprovalCount = proposal.Approvals.Count, + RejectionCount = proposal.Rejections.Count, + AbstentionCount = proposal.Abstentions.Count + }; + } - var organization = State.Organizations[proposal.OrganizationAddress]; - var readyToRelease = IsReleaseThresholdReached(proposal, organization); + public override Address CalculateOrganizationAddress(CreateOrganizationInput input) + { + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + return organizationAddress; + } - return new ProposalOutput - { - ProposalId = proposalId, - ContractMethodName = proposal.ContractMethodName, - ExpiredTime = proposal.ExpiredTime, - OrganizationAddress = proposal.OrganizationAddress, - Params = proposal.Params, - Proposer = proposal.Proposer, - ToAddress = proposal.ToAddress, - ToBeReleased = readyToRelease, - ApprovalCount = proposal.Approvals.Count, - RejectionCount = proposal.Rejections.Count, - AbstentionCount = proposal.Abstentions.Count - }; - } + public override BoolValue ValidateOrganizationExist(Address input) + { + return new BoolValue { Value = State.Organizations[input] != null }; + } - public override Address CalculateOrganizationAddress(CreateOrganizationInput input) + public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) + { + var organization = State.Organizations[input.OrganizationAddress]; + return new BoolValue { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - return organizationAddress; - } + Value = organization.ProposerWhiteList.Contains(input.Proposer) + }; + } - public override BoolValue ValidateOrganizationExist(Address input) - { - return new BoolValue {Value = State.Organizations[input] != null}; - } + #endregion view + + #region Actions - public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) + public override Address CreateOrganization(CreateOrganizationInput input) + { + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + var organizationHash = organizationHashAddressPair.OrganizationHash; + var organization = new Organization { - var organization = State.Organizations[input.OrganizationAddress]; - return new BoolValue + ProposalReleaseThreshold = input.ProposalReleaseThreshold, + OrganizationAddress = organizationAddress, + ProposerWhiteList = input.ProposerWhiteList, + OrganizationMemberList = input.OrganizationMemberList, + OrganizationHash = organizationHash, + CreationToken = input.CreationToken + }; + Assert(Validate(organization), "Invalid organization."); + if (State.Organizations[organizationAddress] == null) + { + State.Organizations[organizationAddress] = organization; + Context.Fire(new OrganizationCreated { - Value = organization.ProposerWhiteList.Contains(input.Proposer) - }; + OrganizationAddress = organizationAddress + }); } - #endregion view + return organizationAddress; + } - #region Actions + public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Unauthorized to create organization."); + var organizationAddress = CreateOrganization(input.OrganizationCreationInput); + if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) + Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - public override Address CreateOrganization(CreateOrganizationInput input) - { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - var organizationHash = organizationHashAddressPair.OrganizationHash; - var organization = new Organization - { - ProposalReleaseThreshold = input.ProposalReleaseThreshold, - OrganizationAddress = organizationAddress, - ProposerWhiteList = input.ProposerWhiteList, - OrganizationMemberList = input.OrganizationMemberList, - OrganizationHash = organizationHash, - CreationToken = input.CreationToken - }; - Assert(Validate(organization), "Invalid organization."); - if (State.Organizations[organizationAddress] == null) - { - State.Organizations[organizationAddress] = organization; - Context.Fire(new OrganizationCreated - { - OrganizationAddress = organizationAddress - }); - } - - return organizationAddress; - } + return organizationAddress; + } - public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) - { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Unauthorized to create organization."); - var organizationAddress = CreateOrganization(input.OrganizationCreationInput); - if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) - { - Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - } + public override Hash CreateProposal(CreateProposalInput input) + { + AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); + var proposalId = CreateNewProposal(input); + return proposalId; + } - return organizationAddress; - } + public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Not authorized to propose."); + AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); + var proposalId = CreateNewProposal(input.ProposalInput); + return proposalId; + } - public override Hash CreateProposal(CreateProposalInput input) - { - AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); - var proposalId = CreateNewProposal(input); - return proposalId; - } + public override Empty Approve(Hash input) + { + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedBySender(proposal, Context.Sender); + var organization = GetOrganization(proposal.OrganizationAddress); + AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) + proposal.Approvals.Add(Context.Sender); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Not authorized to propose."); - AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); - var proposalId = CreateNewProposal(input.ProposalInput); - return proposalId; - } + Address = Context.Sender, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Approve), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - public override Empty Approve(Hash input) - { - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedBySender(proposal, Context.Sender); - var organization = GetOrganization(proposal.OrganizationAddress); - AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - - proposal.Approvals.Add(Context.Sender); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated - { - Address = Context.Sender, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Approve), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + public override Empty Reject(Hash input) + { + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedBySender(proposal, Context.Sender); + var organization = GetOrganization(proposal.OrganizationAddress); + AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - public override Empty Reject(Hash input) + proposal.Rejections.Add(Context.Sender); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedBySender(proposal, Context.Sender); - var organization = GetOrganization(proposal.OrganizationAddress); - AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - - proposal.Rejections.Add(Context.Sender); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated - { - Address = Context.Sender, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Reject), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + Address = Context.Sender, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Reject), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - public override Empty Abstain(Hash input) - { - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedBySender(proposal, Context.Sender); - var organization = GetOrganization(proposal.OrganizationAddress); - AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - - proposal.Abstentions.Add(Context.Sender); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated - { - Address = Context.Sender, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Abstain), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + public override Empty Abstain(Hash input) + { + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedBySender(proposal, Context.Sender); + var organization = GetOrganization(proposal.OrganizationAddress); + AssertIsAuthorizedOrganizationMember(organization, Context.Sender); - public override Empty Release(Hash input) + proposal.Abstentions.Add(Context.Sender); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - var proposalInfo = GetValidProposal(input); - Assert(Context.Sender == proposalInfo.Proposer, "No permission."); - var organization = State.Organizations[proposalInfo.OrganizationAddress]; - Assert(IsReleaseThresholdReached(proposalInfo, organization), "Not approved."); - Context.SendVirtualInlineBySystemContract(CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposalInfo.ToAddress, - proposalInfo.ContractMethodName, proposalInfo.Params); - - Context.Fire(new ProposalReleased - { - ProposalId = input, - OrganizationAddress = proposalInfo.OrganizationAddress - }); - State.Proposals.Remove(input); + Address = Context.Sender, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Abstain), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - return new Empty(); - } + public override Empty Release(Hash input) + { + var proposalInfo = GetValidProposal(input); + Assert(Context.Sender == proposalInfo.Proposer, "No permission."); + var organization = State.Organizations[proposalInfo.OrganizationAddress]; + Assert(IsReleaseThresholdReached(proposalInfo, organization), "Not approved."); + Context.SendVirtualInlineBySystemContract( + CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposalInfo.ToAddress, + proposalInfo.ContractMethodName, proposalInfo.Params); - public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) + Context.Fire(new ProposalReleased { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.ProposalReleaseThreshold = input; - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new OrganizationThresholdChanged - { - OrganizationAddress = Context.Sender, - ProposerReleaseThreshold = input - }); - return new Empty(); - } - - public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) + ProposalId = input, + OrganizationAddress = proposalInfo.OrganizationAddress + }); + State.Proposals.Remove(input); + + return new Empty(); + } + + public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.ProposalReleaseThreshold = input; + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new OrganizationThresholdChanged { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.ProposerWhiteList = input; - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new OrganizationWhiteListChanged() - { - OrganizationAddress = Context.Sender, - ProposerWhiteList = input - }); - return new Empty(); - } + OrganizationAddress = Context.Sender, + ProposerReleaseThreshold = input + }); + return new Empty(); + } - public override Empty AddMember(Address input) + public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.ProposerWhiteList = input; + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new OrganizationWhiteListChanged { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.OrganizationMemberList.OrganizationMembers.Add(input); - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new MemberAdded() - { - OrganizationAddress = Context.Sender, - Member = input - }); - return new Empty(); - } + OrganizationAddress = Context.Sender, + ProposerWhiteList = input + }); + return new Empty(); + } - public override Empty ChangeMember(ChangeMemberInput input) + public override Empty AddMember(Address input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.OrganizationMemberList.OrganizationMembers.Add(input); + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new MemberAdded { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - var removeResult = organization.OrganizationMemberList.OrganizationMembers.Remove(input.OldMember); - Assert(removeResult, "Remove member failed."); - organization.OrganizationMemberList.OrganizationMembers.Add(input.NewMember); - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new MemberChanged - { - OrganizationAddress = Context.Sender, - OldMember = input.OldMember, - NewMember = input.NewMember - }); - return new Empty(); - } + OrganizationAddress = Context.Sender, + Member = input + }); + return new Empty(); + } - public override Empty RemoveMember(Address input) + public override Empty ChangeMember(ChangeMemberInput input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + var removeResult = organization.OrganizationMemberList.OrganizationMembers.Remove(input.OldMember); + Assert(removeResult, "Remove member failed."); + organization.OrganizationMemberList.OrganizationMembers.Add(input.NewMember); + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new MemberChanged { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - var removeResult = organization.OrganizationMemberList.OrganizationMembers.Remove(input); - Assert(removeResult, "Remove member failed."); - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new MemberRemoved - { - OrganizationAddress = Context.Sender, - Member = input - }); - return new Empty(); - } + OrganizationAddress = Context.Sender, + OldMember = input.OldMember, + NewMember = input.NewMember + }); + return new Empty(); + } - public override Empty ClearProposal(Hash input) + public override Empty RemoveMember(Address input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + var removeResult = organization.OrganizationMemberList.OrganizationMembers.Remove(input); + Assert(removeResult, "Remove member failed."); + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new MemberRemoved { - // anyone can clear proposal if it is expired - var proposal = State.Proposals[input]; - Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); - State.Proposals.Remove(input); - return new Empty(); - } + OrganizationAddress = Context.Sender, + Member = input + }); + return new Empty(); + } - #endregion + public override Empty ClearProposal(Hash input) + { + // anyone can clear proposal if it is expired + var proposal = State.Proposals[input]; + Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); + State.Proposals.Remove(input); + return new Empty(); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/AssociationContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Association/AssociationContract_ACS1_TransactionFeeProvider.cs index ff520436f7..2cc10f7c85 100644 --- a/contract/AElf.Contracts.Association/AssociationContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Association/AssociationContract_ACS1_TransactionFeeProvider.cs @@ -1,97 +1,88 @@ -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public partial class AssociationContract { - public partial class AssociationContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/AssociationReferenceState.cs b/contract/AElf.Contracts.Association/AssociationReferenceState.cs index 7a0037bbb7..bf19f5a917 100644 --- a/contract/AElf.Contracts.Association/AssociationReferenceState.cs +++ b/contract/AElf.Contracts.Association/AssociationReferenceState.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public partial class AssociationState { - public partial class AssociationState - { - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/AssociationState.cs b/contract/AElf.Contracts.Association/AssociationState.cs index a35408b341..ede523611e 100644 --- a/contract/AElf.Contracts.Association/AssociationState.cs +++ b/contract/AElf.Contracts.Association/AssociationState.cs @@ -1,14 +1,13 @@ using AElf.Sdk.CSharp.State; -using AElf.Types; using AElf.Standards.ACS1; +using AElf.Types; + +namespace AElf.Contracts.Association; -namespace AElf.Contracts.Association +public partial class AssociationState : ContractState { - public partial class AssociationState : ContractState - { - public MappedState Organizations { get; set; } - public MappedState Proposals { get; set; } - public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public MappedState Organizations { get; set; } + public MappedState Proposals { get; set; } + public MappedState TransactionFees { get; set; } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/Association_Extensions.cs b/contract/AElf.Contracts.Association/Association_Extensions.cs index 29b5062abe..9169f11a49 100644 --- a/contract/AElf.Contracts.Association/Association_Extensions.cs +++ b/contract/AElf.Contracts.Association/Association_Extensions.cs @@ -2,33 +2,32 @@ using AElf.Standards.ACS3; using AElf.Types; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public static class AssociationExtensions { - public static class AssociationExtensions + public static int Count(this ProposerWhiteList proposerWhiteList) { - public static int Count(this ProposerWhiteList proposerWhiteList) - { - return proposerWhiteList.Proposers.Count; - } + return proposerWhiteList.Proposers.Count; + } - public static bool Empty(this ProposerWhiteList proposerWhiteList) - { - return proposerWhiteList.Count() == 0; - } + public static bool Empty(this ProposerWhiteList proposerWhiteList) + { + return proposerWhiteList.Count() == 0; + } - public static bool AnyDuplicate(this ProposerWhiteList proposerWhiteList) - { - return proposerWhiteList.Proposers.GroupBy(p => p).Any(g => g.Count() > 1); - } + public static bool AnyDuplicate(this ProposerWhiteList proposerWhiteList) + { + return proposerWhiteList.Proposers.GroupBy(p => p).Any(g => g.Count() > 1); + } - public static bool AnyDuplicate(this OrganizationMemberList organizationMemberList) - { - return organizationMemberList.OrganizationMembers.GroupBy(m => m).Any(g => g.Count() > 1); - } + public static bool AnyDuplicate(this OrganizationMemberList organizationMemberList) + { + return organizationMemberList.OrganizationMembers.GroupBy(m => m).Any(g => g.Count() > 1); + } - public static bool Contains(this ProposerWhiteList proposerWhiteList, Address address) - { - return proposerWhiteList.Proposers.Contains(address); - } + public static bool Contains(this ProposerWhiteList proposerWhiteList, Address address) + { + return proposerWhiteList.Proposers.Contains(address); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/Association_Helper.cs b/contract/AElf.Contracts.Association/Association_Helper.cs index a806ea17bc..c246df26ee 100644 --- a/contract/AElf.Contracts.Association/Association_Helper.cs +++ b/contract/AElf.Contracts.Association/Association_Helper.cs @@ -1,172 +1,169 @@ using System; using System.Linq; -using AElf.Standards.ACS3; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public partial class AssociationContract { - public partial class AssociationContract + private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) { - private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) - { - var organization = State.Organizations[organizationAddress]; - Assert(organization != null, "No registered organization."); - Assert(organization.ProposerWhiteList.Contains(proposer), "Unauthorized to propose."); - } + var organization = State.Organizations[organizationAddress]; + Assert(organization != null, "No registered organization."); + Assert(organization.ProposerWhiteList.Contains(proposer), "Unauthorized to propose."); + } - private void AssertIsAuthorizedOrganizationMember(Organization organization, Address member) - { - Assert(organization.OrganizationMemberList.Contains(member), - "Unauthorized member."); - } + private void AssertIsAuthorizedOrganizationMember(Organization organization, Address member) + { + Assert(organization.OrganizationMemberList.Contains(member), + "Unauthorized member."); + } - private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) - { - var isRejected = IsProposalRejected(proposal, organization); - if (isRejected) - return false; + private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) + { + var isRejected = IsProposalRejected(proposal, organization); + if (isRejected) + return false; - var isAbstained = IsProposalAbstained(proposal, organization); - return !isAbstained && CheckEnoughVoteAndApprovals(proposal, organization); - } + var isAbstained = IsProposalAbstained(proposal, organization); + return !isAbstained && CheckEnoughVoteAndApprovals(proposal, organization); + } - private bool IsProposalRejected(ProposalInfo proposal, Organization organization) - { - var rejectionMemberCount = - proposal.Rejections.Count(organization.OrganizationMemberList.Contains); - return rejectionMemberCount > organization.ProposalReleaseThreshold.MaximalRejectionThreshold; - } + private bool IsProposalRejected(ProposalInfo proposal, Organization organization) + { + var rejectionMemberCount = + proposal.Rejections.Count(organization.OrganizationMemberList.Contains); + return rejectionMemberCount > organization.ProposalReleaseThreshold.MaximalRejectionThreshold; + } - private bool IsProposalAbstained(ProposalInfo proposal, Organization organization) - { - var abstentionMemberCount = proposal.Abstentions.Count(organization.OrganizationMemberList.Contains); - return abstentionMemberCount > organization.ProposalReleaseThreshold.MaximalAbstentionThreshold; - } + private bool IsProposalAbstained(ProposalInfo proposal, Organization organization) + { + var abstentionMemberCount = proposal.Abstentions.Count(organization.OrganizationMemberList.Contains); + return abstentionMemberCount > organization.ProposalReleaseThreshold.MaximalAbstentionThreshold; + } - private bool CheckEnoughVoteAndApprovals(ProposalInfo proposal, Organization organization) - { - var approvedMemberCount = proposal.Approvals.Count(organization.OrganizationMemberList.Contains); - var isApprovalEnough = - approvedMemberCount >= organization.ProposalReleaseThreshold.MinimalApprovalThreshold; - if (!isApprovalEnough) - return false; - - var isVoteThresholdReached = - proposal.Abstentions.Concat(proposal.Approvals).Concat(proposal.Rejections).Count() >= - organization.ProposalReleaseThreshold.MinimalVoteThreshold; - return isVoteThresholdReached; - } - - private bool Validate(Organization organization) - { - if (organization.ProposerWhiteList.Empty() || - organization.ProposerWhiteList.AnyDuplicate() || - organization.OrganizationMemberList.Empty() || - organization.OrganizationMemberList.AnyDuplicate()) - return false; - if (organization.OrganizationAddress == null || organization.OrganizationHash == null) - return false; - var proposalReleaseThreshold = organization.ProposalReleaseThreshold; - var organizationMemberCount = organization.OrganizationMemberList.Count(); - return proposalReleaseThreshold.MinimalVoteThreshold <= organizationMemberCount && - proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && - proposalReleaseThreshold.MinimalApprovalThreshold > 0 && - proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && - proposalReleaseThreshold.MaximalRejectionThreshold >= 0 && - proposalReleaseThreshold.MaximalAbstentionThreshold + - proposalReleaseThreshold.MinimalApprovalThreshold <= organizationMemberCount && - proposalReleaseThreshold.MaximalRejectionThreshold + - proposalReleaseThreshold.MinimalApprovalThreshold <= organizationMemberCount; - } - - private bool Validate(ProposalInfo proposal) - { - if (proposal.ToAddress == null || string.IsNullOrWhiteSpace(proposal.ContractMethodName) || - !ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl)) - { - return false; - } + private bool CheckEnoughVoteAndApprovals(ProposalInfo proposal, Organization organization) + { + var approvedMemberCount = proposal.Approvals.Count(organization.OrganizationMemberList.Contains); + var isApprovalEnough = + approvedMemberCount >= organization.ProposalReleaseThreshold.MinimalApprovalThreshold; + if (!isApprovalEnough) + return false; + + var isVoteThresholdReached = + proposal.Abstentions.Concat(proposal.Approvals).Concat(proposal.Rejections).Count() >= + organization.ProposalReleaseThreshold.MinimalVoteThreshold; + return isVoteThresholdReached; + } + + private bool Validate(Organization organization) + { + if (organization.ProposerWhiteList.Empty() || + organization.ProposerWhiteList.AnyDuplicate() || + organization.OrganizationMemberList.Empty() || + organization.OrganizationMemberList.AnyDuplicate()) + return false; + if (organization.OrganizationAddress == null || organization.OrganizationHash == null) + return false; + var proposalReleaseThreshold = organization.ProposalReleaseThreshold; + var organizationMemberCount = organization.OrganizationMemberList.Count(); + return proposalReleaseThreshold.MinimalVoteThreshold <= organizationMemberCount && + proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && + proposalReleaseThreshold.MinimalApprovalThreshold > 0 && + proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && + proposalReleaseThreshold.MaximalRejectionThreshold >= 0 && + proposalReleaseThreshold.MaximalAbstentionThreshold + + proposalReleaseThreshold.MinimalApprovalThreshold <= organizationMemberCount && + proposalReleaseThreshold.MaximalRejectionThreshold + + proposalReleaseThreshold.MinimalApprovalThreshold <= organizationMemberCount; + } - return proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; - } + private bool Validate(ProposalInfo proposal) + { + if (proposal.ToAddress == null || string.IsNullOrWhiteSpace(proposal.ContractMethodName) || + !ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl)) + return false; - private bool ValidateDescriptionUrlScheme(string uriString) - { - if (string.IsNullOrEmpty(uriString)) - return true; - bool result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - return result; - } - - private ProposalInfo GetValidProposal(Hash proposalId) - { - var proposal = State.Proposals[proposalId]; - Assert(proposal != null, "Invalid proposal id."); - Assert(Validate(proposal), "Invalid proposal."); - return proposal; - } - - private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( - CreateOrganizationInput createOrganizationInput) - { - var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); + return proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; + } - var organizationAddress = - Context.ConvertVirtualAddressToContractAddressWithContractHashName( - CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); + private bool ValidateDescriptionUrlScheme(string uriString) + { + if (string.IsNullOrEmpty(uriString)) + return true; + var result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + return result; + } - return new OrganizationHashAddressPair - { - OrganizationAddress = organizationAddress, - OrganizationHash = organizationHash - }; - } + private ProposalInfo GetValidProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + Assert(proposal != null, "Invalid proposal id."); + Assert(Validate(proposal), "Invalid proposal."); + return proposal; + } - private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) - { - return creationToken == null - ? organizationHash - : HashHelper.ConcatAndCompute(organizationHash, creationToken); - } + private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( + CreateOrganizationInput createOrganizationInput) + { + var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); - private void AssertProposalNotYetVotedBySender(ProposalInfo proposal, Address sender) + var organizationAddress = + Context.ConvertVirtualAddressToContractAddressWithContractHashName( + CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); + + return new OrganizationHashAddressPair { - var isAlreadyVoted = proposal.Approvals.Contains(sender) || proposal.Rejections.Contains(sender) || - proposal.Abstentions.Contains(sender); + OrganizationAddress = organizationAddress, + OrganizationHash = organizationHash + }; + } + + private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) + { + return creationToken == null + ? organizationHash + : HashHelper.ConcatAndCompute(organizationHash, creationToken); + } + + private void AssertProposalNotYetVotedBySender(ProposalInfo proposal, Address sender) + { + var isAlreadyVoted = proposal.Approvals.Contains(sender) || proposal.Rejections.Contains(sender) || + proposal.Abstentions.Contains(sender); + + Assert(!isAlreadyVoted, "Sender already voted."); + } - Assert(!isAlreadyVoted, "Sender already voted."); - } + private Hash GenerateProposalId(CreateProposalInput input) + { + return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); + } - private Hash GenerateProposalId(CreateProposalInput input) + private Hash CreateNewProposal(CreateProposalInput input) + { + var proposalId = GenerateProposalId(input); + var proposal = new ProposalInfo { - return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); - } - - private Hash CreateNewProposal(CreateProposalInput input) + ContractMethodName = input.ContractMethodName, + ExpiredTime = input.ExpiredTime, + Params = input.Params, + ToAddress = input.ToAddress, + OrganizationAddress = input.OrganizationAddress, + ProposalId = proposalId, + Proposer = Context.Sender, + ProposalDescriptionUrl = input.ProposalDescriptionUrl + }; + Assert(Validate(proposal), "Invalid proposal."); + Assert(State.Proposals[proposalId] == null, "Proposal already exists."); + State.Proposals[proposalId] = proposal; + Context.Fire(new ProposalCreated { - Hash proposalId = GenerateProposalId(input); - var proposal = new ProposalInfo - { - ContractMethodName = input.ContractMethodName, - ExpiredTime = input.ExpiredTime, - Params = input.Params, - ToAddress = input.ToAddress, - OrganizationAddress = input.OrganizationAddress, - ProposalId = proposalId, - Proposer = Context.Sender, - ProposalDescriptionUrl = input.ProposalDescriptionUrl - }; - Assert(Validate(proposal), "Invalid proposal."); - Assert(State.Proposals[proposalId] == null, "Proposal already exists."); - State.Proposals[proposalId] = proposal; - Context.Fire(new ProposalCreated - { - ProposalId = proposalId, - OrganizationAddress = input.OrganizationAddress - }); - return proposalId; - } + ProposalId = proposalId, + OrganizationAddress = input.OrganizationAddress + }); + return proposalId; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Association/OrganizationMemberList.cs b/contract/AElf.Contracts.Association/OrganizationMemberList.cs index 9faf6ece09..bf386699ba 100644 --- a/contract/AElf.Contracts.Association/OrganizationMemberList.cs +++ b/contract/AElf.Contracts.Association/OrganizationMemberList.cs @@ -1,22 +1,21 @@ using AElf.Types; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public partial class OrganizationMemberList { - public partial class OrganizationMemberList + public int Count() { - public int Count() - { - return organizationMembers_.Count; - } + return organizationMembers_.Count; + } - public bool Empty() - { - return Count() == 0; - } + public bool Empty() + { + return Count() == 0; + } - public bool Contains(Address address) - { - return organizationMembers_.Contains(address); - } + public bool Contains(Address address) + { + return organizationMembers_.Contains(address); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Configuration/AElf.Contracts.Configuration.csproj b/contract/AElf.Contracts.Configuration/AElf.Contracts.Configuration.csproj index bd47723238..414dc60419 100644 --- a/contract/AElf.Contracts.Configuration/AElf.Contracts.Configuration.csproj +++ b/contract/AElf.Contracts.Configuration/AElf.Contracts.Configuration.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Configuration true - Configuration is a contract used for changing configurable aspects of the chain, like for example - the maximum amount of packable transactions. + Configuration is a contract used for changing configurable aspects of the chain, like for example + the maximum amount of packable transactions. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs3.proto diff --git a/contract/AElf.Contracts.Configuration/ConfigurationContract.cs b/contract/AElf.Contracts.Configuration/ConfigurationContract.cs index 6719f447e7..fa2ca64c50 100644 --- a/contract/AElf.Contracts.Configuration/ConfigurationContract.cs +++ b/contract/AElf.Contracts.Configuration/ConfigurationContract.cs @@ -1,45 +1,42 @@ using System.Linq; -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; -using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Configuration +namespace AElf.Contracts.Configuration; + +public partial class ConfigurationContract : ConfigurationImplContainer.ConfigurationImplBase { - public partial class ConfigurationContract : ConfigurationImplContainer.ConfigurationImplBase + public override Empty SetConfiguration(SetConfigurationInput input) { - public override Empty SetConfiguration(SetConfigurationInput input) + AssertPerformedByConfigurationControllerOrZeroContract(); + Assert(input.Key.Any() && input.Value != ByteString.Empty, "Invalid set config input."); + State.Configurations[input.Key] = new BytesValue { Value = input.Value }; + Context.Fire(new ConfigurationSet { - AssertPerformedByConfigurationControllerOrZeroContract(); - Assert(input.Key.Any() && input.Value != ByteString.Empty, "Invalid set config input."); - State.Configurations[input.Key] = new BytesValue {Value = input.Value}; - Context.Fire(new ConfigurationSet - { - Key = input.Key, - Value = input.Value - }); - return new Empty(); - } + Key = input.Key, + Value = input.Value + }); + return new Empty(); + } - public override BytesValue GetConfiguration(StringValue input) - { - var value = State.Configurations[input.Value]; - return value ?? new BytesValue(); - } + public override BytesValue GetConfiguration(StringValue input) + { + var value = State.Configurations[input.Value]; + return value ?? new BytesValue(); + } - public override Empty ChangeConfigurationController(AuthorityInfo input) - { - AssertPerformedByConfigurationController(); - Assert(input != null, "invalid input"); - Assert(CheckOrganizationExist(input),"Invalid authority input."); - State.ConfigurationController.Value = input; - return new Empty(); - } + public override Empty ChangeConfigurationController(AuthorityInfo input) + { + AssertPerformedByConfigurationController(); + Assert(input != null, "invalid input"); + Assert(CheckOrganizationExist(input), "Invalid authority input."); + State.ConfigurationController.Value = input; + return new Empty(); + } - public override AuthorityInfo GetConfigurationController(Empty input) - { - return State.ConfigurationController.Value ?? GetDefaultConfigurationController(); - } + public override AuthorityInfo GetConfigurationController(Empty input) + { + return State.ConfigurationController.Value ?? GetDefaultConfigurationController(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Configuration/ConfigurationContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Configuration/ConfigurationContract_ACS1_TransactionFeeProvider.cs index d3265e8ad2..ba17121688 100644 --- a/contract/AElf.Contracts.Configuration/ConfigurationContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Configuration/ConfigurationContract_ACS1_TransactionFeeProvider.cs @@ -1,100 +1,91 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Configuration +namespace AElf.Contracts.Configuration; + +public partial class ConfigurationContract { - public partial class ConfigurationContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + RequiredMethodFeeControllerSet(); - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - #endregion + return new Empty(); + } - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Configuration/ConfigurationContract_Helper.cs b/contract/AElf.Contracts.Configuration/ConfigurationContract_Helper.cs index 2429be7a90..11c552dcc3 100644 --- a/contract/AElf.Contracts.Configuration/ConfigurationContract_Helper.cs +++ b/contract/AElf.Contracts.Configuration/ConfigurationContract_Helper.cs @@ -1,48 +1,44 @@ using AElf.Sdk.CSharp; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Configuration +namespace AElf.Contracts.Configuration; + +public partial class ConfigurationContract { - public partial class ConfigurationContract + private AuthorityInfo GetDefaultConfigurationController() { - private AuthorityInfo GetDefaultConfigurationController() - { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - return new AuthorityInfo - { - ContractAddress = State.ParliamentContract.Value, - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) - }; - } + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private void AssertPerformedByConfigurationController() + return new AuthorityInfo { - if (State.ConfigurationController.Value == null) - { - var defaultConfigurationController = GetDefaultConfigurationController(); - State.ConfigurationController.Value = defaultConfigurationController; - } + ContractAddress = State.ParliamentContract.Value, + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) + }; + } - Assert(Context.Sender == State.ConfigurationController.Value.OwnerAddress, "No permission."); + private void AssertPerformedByConfigurationController() + { + if (State.ConfigurationController.Value == null) + { + var defaultConfigurationController = GetDefaultConfigurationController(); + State.ConfigurationController.Value = defaultConfigurationController; } - private void AssertPerformedByConfigurationControllerOrZeroContract() - { - if (State.ConfigurationController.Value == null) - { - var defaultConfigurationController = GetDefaultConfigurationController(); - State.ConfigurationController.Value = defaultConfigurationController; - } + Assert(Context.Sender == State.ConfigurationController.Value.OwnerAddress, "No permission."); + } - Assert( - State.ConfigurationController.Value.OwnerAddress == Context.Sender || - Context.GetZeroSmartContractAddress() == Context.Sender, "No permission."); + private void AssertPerformedByConfigurationControllerOrZeroContract() + { + if (State.ConfigurationController.Value == null) + { + var defaultConfigurationController = GetDefaultConfigurationController(); + State.ConfigurationController.Value = defaultConfigurationController; } + + Assert( + State.ConfigurationController.Value.OwnerAddress == Context.Sender || + Context.GetZeroSmartContractAddress() == Context.Sender, "No permission."); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Configuration/ConfigurationReferenceState.cs b/contract/AElf.Contracts.Configuration/ConfigurationReferenceState.cs index 93b317b9b5..3396fb63ed 100644 --- a/contract/AElf.Contracts.Configuration/ConfigurationReferenceState.cs +++ b/contract/AElf.Contracts.Configuration/ConfigurationReferenceState.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -namespace AElf.Contracts.Configuration +namespace AElf.Contracts.Configuration; + +public partial class ConfigurationState { - public partial class ConfigurationState - { - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Configuration/ConfigurationState.cs b/contract/AElf.Contracts.Configuration/ConfigurationState.cs index 1b0e747907..0e339eddf1 100644 --- a/contract/AElf.Contracts.Configuration/ConfigurationState.cs +++ b/contract/AElf.Contracts.Configuration/ConfigurationState.cs @@ -1,15 +1,13 @@ -using AElf.Standards.ACS1; -using AElf.Sdk.CSharp.State; -using AElf.Types; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Configuration +namespace AElf.Contracts.Configuration; + +public partial class ConfigurationState : ContractState { - public partial class ConfigurationState : ContractState - { - public SingletonState ConfigurationController { get; set; } - public SingletonState MethodFeeController { get; set; } - public MappedState TransactionFees { get; set; } - public MappedState Configurations { get; set; } - } + public SingletonState ConfigurationController { get; set; } + public SingletonState MethodFeeController { get; set; } + public MappedState TransactionFees { get; set; } + public MappedState Configurations { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs index 4642f00a7b..9517ca71b1 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs @@ -5,230 +5,220 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract : AEDPoSContractImplContainer.AEDPoSContractImplBase { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract : AEDPoSContractImplContainer.AEDPoSContractImplBase + #region Initial + + /// + /// The transaction with this method will generate on every node + /// and executed with the same result. + /// Otherwise, the block hash of the genesis block won't be equal. + /// + /// + /// + public override Empty InitialAElfConsensusContract(InitialAElfConsensusContractInput input) { - #region Initial - - /// - /// The transaction with this method will generate on every node - /// and executed with the same result. - /// Otherwise, the block hash of the genesis block won't be equal. - /// - /// - /// - public override Empty InitialAElfConsensusContract(InitialAElfConsensusContractInput input) - { - Assert(State.CurrentRoundNumber.Value == 0 && !State.Initialized.Value, "Already initialized."); - State.Initialized.Value = true; - - State.PeriodSeconds.Value = input.IsTermStayOne - ? int.MaxValue - : input.PeriodSeconds; - - State.MinerIncreaseInterval.Value = input.MinerIncreaseInterval; - - Context.LogDebug(() => $"There are {State.PeriodSeconds.Value} seconds per period."); - - if (input.IsSideChain) - { - InitialProfitSchemeForSideChain(input.PeriodSeconds); - } - - if (input.IsTermStayOne || input.IsSideChain) - { - State.IsMainChain.Value = false; - return new Empty(); - } + Assert(State.CurrentRoundNumber.Value == 0 && !State.Initialized.Value, "Already initialized."); + State.Initialized.Value = true; - State.IsMainChain.Value = true; + State.PeriodSeconds.Value = input.IsTermStayOne + ? int.MaxValue + : input.PeriodSeconds; - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - State.TreasuryContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.MinerIncreaseInterval.Value = input.MinerIncreaseInterval; - State.MaximumMinersCount.Value = int.MaxValue; + Context.LogDebug(() => $"There are {State.PeriodSeconds.Value} seconds per period."); - if (State.TreasuryContract.Value != null) - { - State.TreasuryContract.UpdateMiningReward.Send(new Int64Value - { - Value = AEDPoSContractConstants.InitialMiningRewardPerBlock - }); - } + if (input.IsSideChain) InitialProfitSchemeForSideChain(input.PeriodSeconds); + if (input.IsTermStayOne || input.IsSideChain) + { + State.IsMainChain.Value = false; return new Empty(); } - #endregion + State.IsMainChain.Value = true; - #region FirstRound + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + State.TreasuryContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - /// - /// The transaction with this method will generate on every node - /// and executed with the same result. - /// Otherwise, the block hash of the genesis block won't be equal. - /// - /// - /// - public override Empty FirstRound(Round input) - { - /* Basic checks. */ - Assert(State.CurrentRoundNumber.Value == 0, "Already initialized."); + State.MaximumMinersCount.Value = int.MaxValue; - /* Initial settings. */ - State.CurrentTermNumber.Value = 1; - State.CurrentRoundNumber.Value = 1; - State.FirstRoundNumberOfEachTerm[1] = 1; - State.MiningInterval.Value = input.GetMiningInterval(); - SetMinerList(input.GetMinerList(), 1); + if (State.TreasuryContract.Value != null) + State.TreasuryContract.UpdateMiningReward.Send(new Int64Value + { + Value = AEDPoSContractConstants.InitialMiningRewardPerBlock + }); - AddRoundInformation(input); + return new Empty(); + } - Context.LogDebug(() => - $"Initial Miners: {input.RealTimeMinersInformation.Keys.Aggregate("\n", (key1, key2) => key1 + "\n" + key2)}"); + #endregion - return new Empty(); - } + #region FirstRound - #endregion + /// + /// The transaction with this method will generate on every node + /// and executed with the same result. + /// Otherwise, the block hash of the genesis block won't be equal. + /// + /// + /// + public override Empty FirstRound(Round input) + { + /* Basic checks. */ + Assert(State.CurrentRoundNumber.Value == 0, "Already initialized."); - #region UpdateValue + /* Initial settings. */ + State.CurrentTermNumber.Value = 1; + State.CurrentRoundNumber.Value = 1; + State.FirstRoundNumberOfEachTerm[1] = 1; + State.MiningInterval.Value = input.GetMiningInterval(); + SetMinerList(input.GetMinerList(), 1); - public override Empty UpdateValue(UpdateValueInput input) - { - ProcessConsensusInformation(input); - return new Empty(); - } + AddRoundInformation(input); - #endregion + Context.LogDebug(() => + $"Initial Miners: {input.RealTimeMinersInformation.Keys.Aggregate("\n", (key1, key2) => key1 + "\n" + key2)}"); - #region UpdateTinyBlockInformation + return new Empty(); + } - public override Empty UpdateTinyBlockInformation(TinyBlockInput input) - { - ProcessConsensusInformation(input); - return new Empty(); - } + #endregion - #endregion + #region UpdateValue - #region NextRound + public override Empty UpdateValue(UpdateValueInput input) + { + ProcessConsensusInformation(input); + return new Empty(); + } - public override Empty NextRound(Round input) - { - SupplyCurrentRoundInformation(); - ProcessConsensusInformation(input); - return new Empty(); - } + #endregion - /// - /// To fill up with InValue and Signature if some miners didn't mined during current round. - /// - private void SupplyCurrentRoundInformation() - { - var currentRound = GetCurrentRoundInformation(new Empty()); - Context.LogDebug(() => $"Before supply:\n{currentRound.ToString(Context.RecoverPublicKey().ToHex())}"); - var notMinedMiners = currentRound.RealTimeMinersInformation.Values.Where(m => m.OutValue == null).ToList(); - if (!notMinedMiners.Any()) return; - TryToGetPreviousRoundInformation(out var previousRound); - foreach (var miner in notMinedMiners) - { - Context.LogDebug(() => $"Miner pubkey {miner.Pubkey}"); + #region UpdateTinyBlockInformation - Hash previousInValue = null; - Hash signature = null; + public override Empty UpdateTinyBlockInformation(TinyBlockInput input) + { + ProcessConsensusInformation(input); + return new Empty(); + } - // Normal situation: previous round information exists and contains this miner. - if (previousRound != null && previousRound.RealTimeMinersInformation.ContainsKey(miner.Pubkey)) - { - // Check this miner's: - // 1. PreviousInValue in current round; (means previous in value recovered by other miners) - // 2. InValue in previous round; (means this miner hasn't produce blocks for a while) - previousInValue = currentRound.RealTimeMinersInformation[miner.Pubkey].PreviousInValue; - if (previousInValue == null) - { - previousInValue = previousRound.RealTimeMinersInformation[miner.Pubkey].InValue; - } - - // If previousInValue is still null, treat this as abnormal situation. - if (previousInValue != null) - { - Context.LogDebug(() => $"Previous round: {previousRound.ToString(miner.Pubkey)}"); - signature = previousRound.CalculateSignature(previousInValue); - } - } + #endregion - if (previousInValue == null) - { - // Handle abnormal situation. + // Keep this for compatibility. + public override Hash GetRandomHash(Int64Value input) + { + Assert(input.Value > 1, "Invalid block height."); + Assert(Context.CurrentHeight >= input.Value, "Block height not reached."); + return State.RandomHashes[input.Value] ?? Hash.Empty; + } - // The fake in value shall only use once during one term. - previousInValue = HashHelper.ComputeFrom(miner); - signature = previousInValue; - } + public override BytesValue GetRandomBytes(BytesValue input) + { + var height = new Int64Value(); + height.MergeFrom(input.Value); + return GetRandomHash(height).ToBytesValue(); + } - // Fill this two fields at last. - miner.InValue = previousInValue; - miner.Signature = signature; + public override Empty RecordCandidateReplacement(RecordCandidateReplacementInput input) + { + Assert(Context.Sender == State.ElectionContract.Value, + "Only Election Contract can record candidate replacement information."); + + if (!TryToGetCurrentRoundInformation(out var currentRound) || + !currentRound.RealTimeMinersInformation.ContainsKey(input.OldPubkey)) return new Empty(); + + // If this candidate is current miner, need to modify current round information. + var realTimeMinerInformation = currentRound.RealTimeMinersInformation[input.OldPubkey]; + realTimeMinerInformation.Pubkey = input.NewPubkey; + currentRound.RealTimeMinersInformation.Remove(input.OldPubkey); + currentRound.RealTimeMinersInformation.Add(input.NewPubkey, realTimeMinerInformation); + if (currentRound.ExtraBlockProducerOfPreviousRound == input.OldPubkey) + currentRound.ExtraBlockProducerOfPreviousRound = input.NewPubkey; + State.Rounds[State.CurrentRoundNumber.Value] = currentRound; + + // Notify Treasury Contract to update replacement information. (Update from old record.) + State.TreasuryContract.RecordMinerReplacement.Send(new RecordMinerReplacementInput + { + OldPubkey = input.OldPubkey, + NewPubkey = input.NewPubkey, + CurrentTermNumber = State.CurrentTermNumber.Value + }); - currentRound.RealTimeMinersInformation[miner.Pubkey] = miner; - } + return new Empty(); + } - TryToUpdateRoundInformation(currentRound); - Context.LogDebug(() => $"After supply:\n{currentRound.ToString(Context.RecoverPublicKey().ToHex())}"); - } + #region NextRound - #endregion + public override Empty NextRound(Round input) + { + SupplyCurrentRoundInformation(); + ProcessConsensusInformation(input); + return new Empty(); + } - // Keep this for compatibility. - public override Hash GetRandomHash(Int64Value input) + /// + /// To fill up with InValue and Signature if some miners didn't mined during current round. + /// + private void SupplyCurrentRoundInformation() + { + var currentRound = GetCurrentRoundInformation(new Empty()); + Context.LogDebug(() => $"Before supply:\n{currentRound.ToString(Context.RecoverPublicKey().ToHex())}"); + var notMinedMiners = currentRound.RealTimeMinersInformation.Values.Where(m => m.OutValue == null).ToList(); + if (!notMinedMiners.Any()) return; + TryToGetPreviousRoundInformation(out var previousRound); + foreach (var miner in notMinedMiners) { - Assert(input.Value > 1, "Invalid block height."); - Assert(Context.CurrentHeight >= input.Value, "Block height not reached."); - return State.RandomHashes[input.Value] ?? Hash.Empty; - } + Context.LogDebug(() => $"Miner pubkey {miner.Pubkey}"); - public override BytesValue GetRandomBytes(BytesValue input) - { - var height = new Int64Value(); - height.MergeFrom(input.Value); - return GetRandomHash(height).ToBytesValue(); - } + Hash previousInValue = null; + Hash signature = null; - public override Empty RecordCandidateReplacement(RecordCandidateReplacementInput input) - { - Assert(Context.Sender == State.ElectionContract.Value, - "Only Election Contract can record candidate replacement information."); - - if (!TryToGetCurrentRoundInformation(out var currentRound) || - !currentRound.RealTimeMinersInformation.ContainsKey(input.OldPubkey)) return new Empty(); - - // If this candidate is current miner, need to modify current round information. - var realTimeMinerInformation = currentRound.RealTimeMinersInformation[input.OldPubkey]; - realTimeMinerInformation.Pubkey = input.NewPubkey; - currentRound.RealTimeMinersInformation.Remove(input.OldPubkey); - currentRound.RealTimeMinersInformation.Add(input.NewPubkey, realTimeMinerInformation); - if (currentRound.ExtraBlockProducerOfPreviousRound == input.OldPubkey) + // Normal situation: previous round information exists and contains this miner. + if (previousRound != null && previousRound.RealTimeMinersInformation.ContainsKey(miner.Pubkey)) { - currentRound.ExtraBlockProducerOfPreviousRound = input.NewPubkey; + // Check this miner's: + // 1. PreviousInValue in current round; (means previous in value recovered by other miners) + // 2. InValue in previous round; (means this miner hasn't produce blocks for a while) + previousInValue = currentRound.RealTimeMinersInformation[miner.Pubkey].PreviousInValue; + if (previousInValue == null) + previousInValue = previousRound.RealTimeMinersInformation[miner.Pubkey].InValue; + + // If previousInValue is still null, treat this as abnormal situation. + if (previousInValue != null) + { + Context.LogDebug(() => $"Previous round: {previousRound.ToString(miner.Pubkey)}"); + signature = previousRound.CalculateSignature(previousInValue); + } } - State.Rounds[State.CurrentRoundNumber.Value] = currentRound; - // Notify Treasury Contract to update replacement information. (Update from old record.) - State.TreasuryContract.RecordMinerReplacement.Send(new RecordMinerReplacementInput + if (previousInValue == null) { - OldPubkey = input.OldPubkey, - NewPubkey = input.NewPubkey, - CurrentTermNumber = State.CurrentTermNumber.Value - }); + // Handle abnormal situation. - return new Empty(); + // The fake in value shall only use once during one term. + previousInValue = HashHelper.ComputeFrom(miner); + signature = previousInValue; + } + + // Fill this two fields at last. + miner.InValue = previousInValue; + miner.Signature = signature; + + currentRound.RealTimeMinersInformation[miner.Pubkey] = miner; } + + TryToUpdateRoundInformation(currentRound); + Context.LogDebug(() => $"After supply:\n{currentRound.ToString(Context.RecoverPublicKey().ToHex())}"); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContractConstants.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContractConstants.cs index 7ae75fa9ca..9c4f4c1599 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContractConstants.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContractConstants.cs @@ -1,16 +1,15 @@ -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public static class AEDPoSContractConstants { - // ReSharper disable once InconsistentNaming - public static class AEDPoSContractConstants - { - public const int MaximumTinyBlocksCount = 8; - public const long InitialMiningRewardPerBlock = 12500000; - public const long TimeToReduceMiningRewardByHalf = 126144000; // 60 * 60 * 24 * 365 * 4 - public const int SupposedMinersCount = 17; - public const int KeepRounds = 40960; - public const long TolerableMissedTimeSlotsCount = 60 * 24 * 3; // one time slot per minute and last 3 days. - public const string SideChainShareProfitsTokenSymbol = "SHARE"; - public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; - public const string PayRentalSymbolListName = "SymbolListToPayRental"; - } + public const int MaximumTinyBlocksCount = 8; + public const long InitialMiningRewardPerBlock = 12500000; + public const long TimeToReduceMiningRewardByHalf = 126144000; // 60 * 60 * 24 * 365 * 4 + public const int SupposedMinersCount = 17; + public const int KeepRounds = 40960; + public const long TolerableMissedTimeSlotsCount = 60 * 24 * 3; // one time slot per minute and last 3 days. + public const string SideChainShareProfitsTokenSymbol = "SHARE"; + public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; + public const string PayRentalSymbolListName = "SymbolListToPayRental"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS11_CrossChainInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS11_CrossChainInformationProvider.cs index ae55efb3a2..0b7fd8af6b 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS11_CrossChainInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS11_CrossChainInformationProvider.cs @@ -6,97 +6,94 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSContract { - public partial class AEDPoSContract + public override BytesValue GetChainInitializationInformation(BytesValue input) { - #region UpdateConsensusInformation - - public override Empty UpdateInformationFromCrossChain(BytesValue input) + return new BytesValue { - Assert( - Context.Sender == Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName), - "Only Cross Chain Contract can call this method."); + Value = new MinerListWithRoundNumber + { + MinerList = GetCurrentMinerList(new Empty()), + RoundNumber = State.CurrentRoundNumber.Value + }.ToByteString() + }; + } - Assert(!State.IsMainChain.Value, "Only side chain can update consensus information."); + public override BoolValue CheckCrossChainIndexingPermission(Address input) + { + return IsCurrentMiner(input); + } - // For now we just extract the miner list from main chain consensus information, then update miners list. - if (input == null || input.Value.IsEmpty) return new Empty(); + #region UpdateConsensusInformation - var consensusInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(input.Value); + public override Empty UpdateInformationFromCrossChain(BytesValue input) + { + Assert( + Context.Sender == Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName), + "Only Cross Chain Contract can call this method."); - // check round number of shared consensus, not term number - if (consensusInformation.Round.RoundNumber <= State.MainChainRoundNumber.Value) - return new Empty(); + Assert(!State.IsMainChain.Value, "Only side chain can update consensus information."); - Context.LogDebug(() => - $"Shared miner list of round {consensusInformation.Round.RoundNumber}:" + - $"{consensusInformation.Round.ToString("M")}"); + // For now we just extract the miner list from main chain consensus information, then update miners list. + if (input == null || input.Value.IsEmpty) return new Empty(); - DistributeResourceTokensToPreviousMiners(); + var consensusInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(input.Value); - State.MainChainRoundNumber.Value = consensusInformation.Round.RoundNumber; + // check round number of shared consensus, not term number + if (consensusInformation.Round.RoundNumber <= State.MainChainRoundNumber.Value) + return new Empty(); - var minersKeys = consensusInformation.Round.RealTimeMinersInformation.Keys; - State.MainChainCurrentMinerList.Value = new MinerList - { - Pubkeys = {minersKeys.Select(ByteStringHelper.FromHexString)} - }; + Context.LogDebug(() => + $"Shared miner list of round {consensusInformation.Round.RoundNumber}:" + + $"{consensusInformation.Round.ToString("M")}"); - return new Empty(); - } + DistributeResourceTokensToPreviousMiners(); + + State.MainChainRoundNumber.Value = consensusInformation.Round.RoundNumber; - private void DistributeResourceTokensToPreviousMiners() + var minersKeys = consensusInformation.Round.RealTimeMinersInformation.Keys; + State.MainChainCurrentMinerList.Value = new MinerList { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + Pubkeys = { minersKeys.Select(ByteStringHelper.FromHexString) } + }; - var minerList = State.MainChainCurrentMinerList.Value.Pubkeys; - foreach (var symbol in Context.Variables.GetStringArray(AEDPoSContractConstants.PayTxFeeSymbolListName) - .Union(Context.Variables.GetStringArray(AEDPoSContractConstants.PayRentalSymbolListName))) - { - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = Context.Self, - Symbol = symbol - }).Balance; - var amount = balance.Div(minerList.Count); - Context.LogDebug(() => $"Consensus Contract {symbol} balance: {balance}. Every miner can get {amount}"); - if (amount <= 0) continue; - foreach (var pubkey in minerList) - { - var address = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(pubkey.ToHex())); - Context.LogDebug(() => $"Will send {amount} {symbol}s to {pubkey}"); - State.TokenContract.Transfer.Send(new TransferInput - { - To = address, - Amount = amount, - Symbol = symbol - }); - } - } - } + return new Empty(); + } - #endregion + private void DistributeResourceTokensToPreviousMiners() + { + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - public override BytesValue GetChainInitializationInformation(BytesValue input) + var minerList = State.MainChainCurrentMinerList.Value.Pubkeys; + foreach (var symbol in Context.Variables.GetStringArray(AEDPoSContractConstants.PayTxFeeSymbolListName) + .Union(Context.Variables.GetStringArray(AEDPoSContractConstants.PayRentalSymbolListName))) { - return new BytesValue + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput { - Value = new MinerListWithRoundNumber + Owner = Context.Self, + Symbol = symbol + }).Balance; + var amount = balance.Div(minerList.Count); + Context.LogDebug(() => $"Consensus Contract {symbol} balance: {balance}. Every miner can get {amount}"); + if (amount <= 0) continue; + foreach (var pubkey in minerList) + { + var address = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(pubkey.ToHex())); + Context.LogDebug(() => $"Will send {amount} {symbol}s to {pubkey}"); + State.TokenContract.Transfer.Send(new TransferInput { - MinerList = GetCurrentMinerList(new Empty()), - RoundNumber = State.CurrentRoundNumber.Value - }.ToByteString() - }; - } - - public override BoolValue CheckCrossChainIndexingPermission(Address input) - { - return IsCurrentMiner(input); + To = address, + Amount = amount, + Symbol = symbol + }); + } } } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS1_TransactionFeeProvider.cs index 72d42b72b1..c606c0324f 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS1_TransactionFeeProvider.cs @@ -1,105 +1,99 @@ using System.Collections.Generic; +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - public override MethodFees GetMethodFee(StringValue input) - { - if (new List - { - nameof(InitialAElfConsensusContract), nameof(FirstRound), nameof(UpdateValue), - nameof(UpdateTinyBlockInformation), nameof(NextRound), nameof(NextTerm) - }.Contains(input.Value)) - { - return new MethodFees - { - MethodName = input.Value, - IsSizeFeeFree = true - }; - } + RequiredMethodFeeControllerSet(); - return State.TransactionFees[input.Value]; - } - - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - #endregion - - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } + return new Empty(); + } - RequiredMethodFeeControllerSet(); + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + State.MethodFeeController.Value = input; + return new Empty(); + } - return new Empty(); - } + #region Views - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override MethodFees GetMethodFee(StringValue input) + { + if (new List + { + nameof(InitialAElfConsensusContract), nameof(FirstRound), nameof(UpdateValue), + nameof(UpdateTinyBlockInformation), nameof(NextRound), nameof(NextTerm) + }.Contains(input.Value)) + return new MethodFees + { + MethodName = input.Value, + IsSizeFeeFree = true + }; - State.MethodFeeController.Value = input; - return new Empty(); - } + return State.TransactionFees[input.Value]; + } - #region private methods + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - EnsureParliamentContractAddressSet(); + #endregion - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; + #region private methods - State.MethodFeeController.Value = defaultAuthority; - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + EnsureParliamentContractAddressSet(); - private void AssertSenderAddressWith(Address address) + var defaultAuthority = new AuthorityInfo { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + State.MethodFeeController.Value = defaultAuthority; + } - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - EnsureTokenContractAddressSet(); - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - #endregion + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + EnsureTokenContractAddressSet(); + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs index 1a4c7d1a55..4bbf853a65 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs @@ -1,188 +1,181 @@ -using System.Collections.Generic; using System.Linq; using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// In this method, `Context.CurrentBlockTime` is the time one miner start request his next consensus command. + /// + /// + /// + public override ConsensusCommand GetConsensusCommand(BytesValue input) { - /// - /// In this method, `Context.CurrentBlockTime` is the time one miner start request his next consensus command. - /// - /// - /// - public override ConsensusCommand GetConsensusCommand(BytesValue input) - { - _processingBlockMinerPubkey = input.Value.ToHex(); + _processingBlockMinerPubkey = input.Value.ToHex(); - if (Context.CurrentHeight < 2) return ConsensusCommandProvider.InvalidConsensusCommand; + if (Context.CurrentHeight < 2) return ConsensusCommandProvider.InvalidConsensusCommand; - if (!TryToGetCurrentRoundInformation(out var currentRound)) - return ConsensusCommandProvider.InvalidConsensusCommand; + if (!TryToGetCurrentRoundInformation(out var currentRound)) + return ConsensusCommandProvider.InvalidConsensusCommand; - if (!currentRound.IsInMinerList(_processingBlockMinerPubkey)) - return ConsensusCommandProvider.InvalidConsensusCommand; + if (!currentRound.IsInMinerList(_processingBlockMinerPubkey)) + return ConsensusCommandProvider.InvalidConsensusCommand; - if (currentRound.RealTimeMinersInformation.Count != 1 && - currentRound.RoundNumber > 2 && - State.LatestPubkeyToTinyBlocksCount.Value != null && - State.LatestPubkeyToTinyBlocksCount.Value.Pubkey == _processingBlockMinerPubkey && - State.LatestPubkeyToTinyBlocksCount.Value.BlocksCount < 0) - return GetConsensusCommand(AElfConsensusBehaviour.NextRound, currentRound, _processingBlockMinerPubkey, - Context.CurrentBlockTime); + if (currentRound.RealTimeMinersInformation.Count != 1 && + currentRound.RoundNumber > 2 && + State.LatestPubkeyToTinyBlocksCount.Value != null && + State.LatestPubkeyToTinyBlocksCount.Value.Pubkey == _processingBlockMinerPubkey && + State.LatestPubkeyToTinyBlocksCount.Value.BlocksCount < 0) + return GetConsensusCommand(AElfConsensusBehaviour.NextRound, currentRound, _processingBlockMinerPubkey, + Context.CurrentBlockTime); - var blockchainStartTimestamp = GetBlockchainStartTimestamp(); + var blockchainStartTimestamp = GetBlockchainStartTimestamp(); - var behaviour = IsMainChain - ? new MainChainConsensusBehaviourProvider(currentRound, _processingBlockMinerPubkey, - GetMaximumBlocksCount(), - Context.CurrentBlockTime, blockchainStartTimestamp, State.PeriodSeconds.Value) - .GetConsensusBehaviour() - : new SideChainConsensusBehaviourProvider(currentRound, _processingBlockMinerPubkey, + var behaviour = IsMainChain + ? new MainChainConsensusBehaviourProvider(currentRound, _processingBlockMinerPubkey, GetMaximumBlocksCount(), - Context.CurrentBlockTime).GetConsensusBehaviour(); - - Context.LogDebug(() => - $"{currentRound.ToString(_processingBlockMinerPubkey)}\nArranged behaviour: {behaviour.ToString()}"); - - return behaviour == AElfConsensusBehaviour.Nothing - ? ConsensusCommandProvider.InvalidConsensusCommand - : GetConsensusCommand(behaviour, currentRound, _processingBlockMinerPubkey, Context.CurrentBlockTime); - } + Context.CurrentBlockTime, blockchainStartTimestamp, State.PeriodSeconds.Value) + .GetConsensusBehaviour() + : new SideChainConsensusBehaviourProvider(currentRound, _processingBlockMinerPubkey, + GetMaximumBlocksCount(), + Context.CurrentBlockTime).GetConsensusBehaviour(); + + Context.LogDebug(() => + $"{currentRound.ToString(_processingBlockMinerPubkey)}\nArranged behaviour: {behaviour.ToString()}"); + + return behaviour == AElfConsensusBehaviour.Nothing + ? ConsensusCommandProvider.InvalidConsensusCommand + : GetConsensusCommand(behaviour, currentRound, _processingBlockMinerPubkey, Context.CurrentBlockTime); + } - public override BytesValue GetConsensusExtraData(BytesValue input) - { - return GetConsensusBlockExtraData(input); - } + public override BytesValue GetConsensusExtraData(BytesValue input) + { + return GetConsensusBlockExtraData(input); + } - public override TransactionList GenerateConsensusTransactions(BytesValue input) - { - var triggerInformation = new AElfConsensusTriggerInformation(); - triggerInformation.MergeFrom(input.Value); - // Some basic checks. - Assert(triggerInformation.Pubkey.Any(), - "Data to request consensus information should contain pubkey."); - - var pubkey = triggerInformation.Pubkey; - var consensusInformation = new AElfConsensusHeaderInformation(); - consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value); - var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey); - return transactionList; - } + public override TransactionList GenerateConsensusTransactions(BytesValue input) + { + var triggerInformation = new AElfConsensusTriggerInformation(); + triggerInformation.MergeFrom(input.Value); + // Some basic checks. + Assert(triggerInformation.Pubkey.Any(), + "Data to request consensus information should contain pubkey."); + + var pubkey = triggerInformation.Pubkey; + var consensusInformation = new AElfConsensusHeaderInformation(); + consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value); + var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey); + return transactionList; + } - public override ValidationResult ValidateConsensusBeforeExecution(BytesValue input) - { - var extraData = AElfConsensusHeaderInformation.Parser.ParseFrom(input.Value.ToByteArray()); - return ValidateBeforeExecution(extraData); - } + public override ValidationResult ValidateConsensusBeforeExecution(BytesValue input) + { + var extraData = AElfConsensusHeaderInformation.Parser.ParseFrom(input.Value.ToByteArray()); + return ValidateBeforeExecution(extraData); + } - public override ValidationResult ValidateConsensusAfterExecution(BytesValue input) + public override ValidationResult ValidateConsensusAfterExecution(BytesValue input) + { + var headerInformation = new AElfConsensusHeaderInformation(); + headerInformation.MergeFrom(input.Value); + if (TryToGetCurrentRoundInformation(out var currentRound)) { - var headerInformation = new AElfConsensusHeaderInformation(); - headerInformation.MergeFrom(input.Value); - if (TryToGetCurrentRoundInformation(out var currentRound)) + if (headerInformation.Behaviour == AElfConsensusBehaviour.UpdateValue) + headerInformation.Round = + currentRound.RecoverFromUpdateValue(headerInformation.Round, + headerInformation.SenderPubkey.ToHex()); + + if (headerInformation.Behaviour == AElfConsensusBehaviour.TinyBlock) + headerInformation.Round = + currentRound.RecoverFromTinyBlock(headerInformation.Round, + headerInformation.SenderPubkey.ToHex()); + + var isContainPreviousInValue = !currentRound.IsMinerListJustChanged; + if (headerInformation.Round.GetHash(isContainPreviousInValue) != + currentRound.GetHash(isContainPreviousInValue)) { - if (headerInformation.Behaviour == AElfConsensusBehaviour.UpdateValue) - { - headerInformation.Round = - currentRound.RecoverFromUpdateValue(headerInformation.Round, - headerInformation.SenderPubkey.ToHex()); - } - - if (headerInformation.Behaviour == AElfConsensusBehaviour.TinyBlock) - { - headerInformation.Round = - currentRound.RecoverFromTinyBlock(headerInformation.Round, - headerInformation.SenderPubkey.ToHex()); - } - - var isContainPreviousInValue = !currentRound.IsMinerListJustChanged; - if (headerInformation.Round.GetHash(isContainPreviousInValue) != - currentRound.GetHash(isContainPreviousInValue)) - { - var headerMiners = headerInformation.Round.RealTimeMinersInformation.Keys; - var stateMiners = currentRound.RealTimeMinersInformation.Keys; - var replacedMiners = headerMiners.Except(stateMiners).ToList(); - if (!replacedMiners.Any()) + var headerMiners = headerInformation.Round.RealTimeMinersInformation.Keys; + var stateMiners = currentRound.RealTimeMinersInformation.Keys; + var replacedMiners = headerMiners.Except(stateMiners).ToList(); + if (!replacedMiners.Any()) + return new ValidationResult { - return new ValidationResult - { - Success = false, Message = - "Current round information is different with consensus extra data.\n" + - $"New block header consensus information:\n{headerInformation.Round}" + - $"Stated block header consensus information:\n{currentRound}" - }; - } + Success = false, Message = + "Current round information is different with consensus extra data.\n" + + $"New block header consensus information:\n{headerInformation.Round}" + + $"Stated block header consensus information:\n{currentRound}" + }; - var newMiners = stateMiners.Except(headerMiners).ToList(); - var officialNewestMiners = replacedMiners.Select(miner => - State.ElectionContract.GetNewestPubkey.Call(new StringValue {Value = miner}).Value) - .ToList(); + var newMiners = stateMiners.Except(headerMiners).ToList(); + var officialNewestMiners = replacedMiners.Select(miner => + State.ElectionContract.GetNewestPubkey.Call(new StringValue { Value = miner }).Value) + .ToList(); - Assert( - newMiners.Count == officialNewestMiners.Count && - newMiners.Union(officialNewestMiners).Count() == newMiners.Count, - "Incorrect replacement information."); - } + Assert( + newMiners.Count == officialNewestMiners.Count && + newMiners.Union(officialNewestMiners).Count() == newMiners.Count, + "Incorrect replacement information."); } - - return new ValidationResult {Success = true}; } - private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderInformation consensusInformation, - ByteString pubkey) + return new ValidationResult { Success = true }; + } + + private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderInformation consensusInformation, + ByteString pubkey) + { + var round = consensusInformation.Round; + var behaviour = consensusInformation.Behaviour; + switch (behaviour) { - var round = consensusInformation.Round; - var behaviour = consensusInformation.Behaviour; - switch (behaviour) - { - case AElfConsensusBehaviour.UpdateValue: - Context.LogDebug(() => $"Previous in value in extra data:{round.RealTimeMinersInformation[pubkey.ToHex()].PreviousInValue}"); - return new TransactionList + case AElfConsensusBehaviour.UpdateValue: + Context.LogDebug(() => + $"Previous in value in extra data:{round.RealTimeMinersInformation[pubkey.ToHex()].PreviousInValue}"); + return new TransactionList + { + Transactions = { - Transactions = - { - GenerateTransaction(nameof(UpdateValue), - round.ExtractInformationToUpdateConsensus(pubkey.ToHex())) - } - }; - case AElfConsensusBehaviour.TinyBlock: - var minerInRound = round.RealTimeMinersInformation[pubkey.ToHex()]; - return new TransactionList + GenerateTransaction(nameof(UpdateValue), + round.ExtractInformationToUpdateConsensus(pubkey.ToHex())) + } + }; + case AElfConsensusBehaviour.TinyBlock: + var minerInRound = round.RealTimeMinersInformation[pubkey.ToHex()]; + return new TransactionList + { + Transactions = { - Transactions = - { - GenerateTransaction(nameof(UpdateTinyBlockInformation), - new TinyBlockInput - { - ActualMiningTime = minerInRound.ActualMiningTimes.Last(), - ProducedBlocks = minerInRound.ProducedBlocks, - RoundId = round.RoundIdForValidation - }) - } - }; - case AElfConsensusBehaviour.NextRound: - return new TransactionList + GenerateTransaction(nameof(UpdateTinyBlockInformation), + new TinyBlockInput + { + ActualMiningTime = minerInRound.ActualMiningTimes.Last(), + ProducedBlocks = minerInRound.ProducedBlocks, + RoundId = round.RoundIdForValidation + }) + } + }; + case AElfConsensusBehaviour.NextRound: + return new TransactionList + { + Transactions = { - Transactions = - { - GenerateTransaction(nameof(NextRound), round) - } - }; - case AElfConsensusBehaviour.NextTerm: - return new TransactionList + GenerateTransaction(nameof(NextRound), round) + } + }; + case AElfConsensusBehaviour.NextTerm: + return new TransactionList + { + Transactions = { - Transactions = - { - GenerateTransaction(nameof(NextTerm), round) - } - }; - default: - return new TransactionList(); - } + GenerateTransaction(nameof(NextTerm), round) + } + }; + default: + return new TransactionList(); } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_CacheFileds.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_CacheFileds.cs index db17ded5df..4433b1fca8 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_CacheFileds.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_CacheFileds.cs @@ -1,13 +1,12 @@ -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +/// +/// DO NOT forget to clear after executing one transaction, +/// otherwise these cached states will be saved to `executive` instance unexpectedly. +/// +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - /// - /// DO NOT forget to clear after executing one transaction, - /// otherwise these cached states will be saved to `executive` instance unexpectedly. - /// - public partial class AEDPoSContract - { - private string _processingBlockMinerPubkey; - private bool? _isMainChain; - } + private bool? _isMainChain; + private string _processingBlockMinerPubkey; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusBlockExtraData.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusBlockExtraData.cs index 40f0f2dfde..bbbce356a4 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusBlockExtraData.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusBlockExtraData.cs @@ -5,227 +5,213 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private BytesValue GetConsensusBlockExtraData(BytesValue input, bool isGeneratingTransactions = false) { - private BytesValue GetConsensusBlockExtraData(BytesValue input, bool isGeneratingTransactions = false) - { - var triggerInformation = new AElfConsensusTriggerInformation(); - triggerInformation.MergeFrom(input.Value); + var triggerInformation = new AElfConsensusTriggerInformation(); + triggerInformation.MergeFrom(input.Value); - Assert(triggerInformation.Pubkey.Any(), "Invalid pubkey."); + Assert(triggerInformation.Pubkey.Any(), "Invalid pubkey."); - TryToGetCurrentRoundInformation(out var currentRound); + TryToGetCurrentRoundInformation(out var currentRound); - var publicKeyBytes = triggerInformation.Pubkey; - var pubkey = publicKeyBytes.ToHex(); + var publicKeyBytes = triggerInformation.Pubkey; + var pubkey = publicKeyBytes.ToHex(); - var information = new AElfConsensusHeaderInformation(); - switch (triggerInformation.Behaviour) - { - case AElfConsensusBehaviour.UpdateValue: - information = GetConsensusExtraDataToPublishOutValue(currentRound, pubkey, - triggerInformation); - if (!isGeneratingTransactions) - { - information.Round = information.Round.GetUpdateValueRound(pubkey); - } - - break; - - case AElfConsensusBehaviour.TinyBlock: - information = GetConsensusExtraDataForTinyBlock(currentRound, pubkey, - triggerInformation); - break; - - case AElfConsensusBehaviour.NextRound: - information = GetConsensusExtraDataForNextRound(currentRound, pubkey, - triggerInformation); - break; - - case AElfConsensusBehaviour.NextTerm: - information = GetConsensusExtraDataForNextTerm(pubkey, triggerInformation); - break; - } + var information = new AElfConsensusHeaderInformation(); + switch (triggerInformation.Behaviour) + { + case AElfConsensusBehaviour.UpdateValue: + information = GetConsensusExtraDataToPublishOutValue(currentRound, pubkey, + triggerInformation); + if (!isGeneratingTransactions) information.Round = information.Round.GetUpdateValueRound(pubkey); + + break; + + case AElfConsensusBehaviour.TinyBlock: + information = GetConsensusExtraDataForTinyBlock(currentRound, pubkey, + triggerInformation); + break; + + case AElfConsensusBehaviour.NextRound: + information = GetConsensusExtraDataForNextRound(currentRound, pubkey, + triggerInformation); + break; + + case AElfConsensusBehaviour.NextTerm: + information = GetConsensusExtraDataForNextTerm(pubkey, triggerInformation); + break; + } - if (!isGeneratingTransactions) - { - information.Round.DeleteSecretSharingInformation(); - } + if (!isGeneratingTransactions) information.Round.DeleteSecretSharingInformation(); - return information.ToBytesValue(); - } + return information.ToBytesValue(); + } - private AElfConsensusHeaderInformation GetConsensusExtraDataToPublishOutValue(Round currentRound, - string pubkey, AElfConsensusTriggerInformation triggerInformation) - { - currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound - .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); - currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = - currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); - currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes - .Add(Context.CurrentBlockTime); + private AElfConsensusHeaderInformation GetConsensusExtraDataToPublishOutValue(Round currentRound, + string pubkey, AElfConsensusTriggerInformation triggerInformation) + { + currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound + .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); + currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = + currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); + currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes + .Add(Context.CurrentBlockTime); - Assert(triggerInformation.InValue != null, "In value should not be null."); + Assert(triggerInformation.InValue != null, "In value should not be null."); - var outValue = HashHelper.ComputeFrom(triggerInformation.InValue); - var signature = - HashHelper.ConcatAndCompute(outValue, triggerInformation.InValue); // Just initial signature value. - var previousInValue = Hash.Empty; // Just initial previous in value. + var outValue = HashHelper.ComputeFrom(triggerInformation.InValue); + var signature = + HashHelper.ConcatAndCompute(outValue, triggerInformation.InValue); // Just initial signature value. + var previousInValue = Hash.Empty; // Just initial previous in value. - if (TryToGetPreviousRoundInformation(out var previousRound) && !IsFirstRoundOfCurrentTerm(out _)) + if (TryToGetPreviousRoundInformation(out var previousRound) && !IsFirstRoundOfCurrentTerm(out _)) + { + if (triggerInformation.PreviousInValue != null && + triggerInformation.PreviousInValue != Hash.Empty) { - if (triggerInformation.PreviousInValue != null && - triggerInformation.PreviousInValue != Hash.Empty) + Context.LogDebug( + () => $"Previous in value in trigger information: {triggerInformation.PreviousInValue}"); + // Self check. + if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && + HashHelper.ComputeFrom(triggerInformation.PreviousInValue) != + previousRound.RealTimeMinersInformation[pubkey].OutValue) { - Context.LogDebug( - () => $"Previous in value in trigger information: {triggerInformation.PreviousInValue}"); - // Self check. - if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && - HashHelper.ComputeFrom(triggerInformation.PreviousInValue) != - previousRound.RealTimeMinersInformation[pubkey].OutValue) - { - Context.LogDebug(() => "Failed to produce block at previous round?"); - previousInValue = Hash.Empty; - } - else - { - previousInValue = triggerInformation.PreviousInValue; - } - signature = previousRound.CalculateSignature(triggerInformation.PreviousInValue); + Context.LogDebug(() => "Failed to produce block at previous round?"); + previousInValue = Hash.Empty; } else { - var fakePreviousInValue = HashHelper.ComputeFrom(pubkey.Append(Context.CurrentHeight.ToString())); - if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && previousRound.RoundNumber != 1) - { - var appointedPreviousInValue = previousRound.RealTimeMinersInformation[pubkey].InValue; - if (appointedPreviousInValue != null) - { - fakePreviousInValue = appointedPreviousInValue; - } - signature = previousRound.CalculateSignature(fakePreviousInValue); - } - else - { - // This miner appears first time in current round, like as a replacement of evil miner. - signature = previousRound.CalculateSignature(fakePreviousInValue); - } + previousInValue = triggerInformation.PreviousInValue; } - } - - var updatedRound = currentRound.ApplyNormalConsensusData(pubkey, previousInValue, - outValue, signature); - - Context.LogDebug( - () => $"Previous in value after ApplyNormalConsensusData: " + - $"{updatedRound.RealTimeMinersInformation[pubkey].PreviousInValue}"); - - updatedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight = Context.CurrentHeight; - // Update secret pieces of latest in value. - UpdateLatestSecretPieces(updatedRound, pubkey, triggerInformation); - - // To publish Out Value. - return new AElfConsensusHeaderInformation - { - SenderPubkey = ByteStringHelper.FromHexString(pubkey), - Round = updatedRound, - Behaviour = triggerInformation.Behaviour - }; - } - - private void UpdateLatestSecretPieces(Round updatedRound, string pubkey, AElfConsensusTriggerInformation triggerInformation) - { - foreach (var encryptedPiece in triggerInformation.EncryptedPieces) + signature = previousRound.CalculateSignature(triggerInformation.PreviousInValue); + } + else { - updatedRound.RealTimeMinersInformation[pubkey].EncryptedPieces - .Add(encryptedPiece.Key, encryptedPiece.Value); + var fakePreviousInValue = HashHelper.ComputeFrom(pubkey.Append(Context.CurrentHeight.ToString())); + if (previousRound.RealTimeMinersInformation.ContainsKey(pubkey) && previousRound.RoundNumber != 1) + { + var appointedPreviousInValue = previousRound.RealTimeMinersInformation[pubkey].InValue; + if (appointedPreviousInValue != null) fakePreviousInValue = appointedPreviousInValue; + signature = previousRound.CalculateSignature(fakePreviousInValue); + } + else + { + // This miner appears first time in current round, like as a replacement of evil miner. + signature = previousRound.CalculateSignature(fakePreviousInValue); + } } + } - foreach (var decryptedPiece in triggerInformation.DecryptedPieces) - if (updatedRound.RealTimeMinersInformation.ContainsKey(decryptedPiece.Key)) - updatedRound.RealTimeMinersInformation[decryptedPiece.Key].DecryptedPieces[pubkey] = - decryptedPiece.Value; + var updatedRound = currentRound.ApplyNormalConsensusData(pubkey, previousInValue, + outValue, signature); - foreach (var revealedInValue in triggerInformation.RevealedInValues) - if (updatedRound.RealTimeMinersInformation.ContainsKey(revealedInValue.Key) && - (updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == Hash.Empty || - updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == null)) - updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue = revealedInValue.Value; - } + Context.LogDebug( + () => "Previous in value after ApplyNormalConsensusData: " + + $"{updatedRound.RealTimeMinersInformation[pubkey].PreviousInValue}"); - private AElfConsensusHeaderInformation GetConsensusExtraDataForTinyBlock(Round currentRound, - string pubkey, AElfConsensusTriggerInformation triggerInformation) - { - currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound - .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); - currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = - currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); - currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes - .Add(Context.CurrentBlockTime); + updatedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight = Context.CurrentHeight; - return new AElfConsensusHeaderInformation - { - SenderPubkey = ByteStringHelper.FromHexString(pubkey), - Round = currentRound.GetTinyBlockRound(pubkey), - Behaviour = triggerInformation.Behaviour - }; - } + // Update secret pieces of latest in value. + UpdateLatestSecretPieces(updatedRound, pubkey, triggerInformation); - private AElfConsensusHeaderInformation GetConsensusExtraDataForNextRound(Round currentRound, - string pubkey, AElfConsensusTriggerInformation triggerInformation) + // To publish Out Value. + return new AElfConsensusHeaderInformation { - GenerateNextRoundInformation(currentRound, Context.CurrentBlockTime, out var nextRound); + SenderPubkey = ByteStringHelper.FromHexString(pubkey), + Round = updatedRound, + Behaviour = triggerInformation.Behaviour + }; + } - nextRound.ExtraBlockProducerOfPreviousRound = pubkey; + private void UpdateLatestSecretPieces(Round updatedRound, string pubkey, + AElfConsensusTriggerInformation triggerInformation) + { + foreach (var encryptedPiece in triggerInformation.EncryptedPieces) + updatedRound.RealTimeMinersInformation[pubkey].EncryptedPieces + .Add(encryptedPiece.Key, encryptedPiece.Value); + + foreach (var decryptedPiece in triggerInformation.DecryptedPieces) + if (updatedRound.RealTimeMinersInformation.ContainsKey(decryptedPiece.Key)) + updatedRound.RealTimeMinersInformation[decryptedPiece.Key].DecryptedPieces[pubkey] = + decryptedPiece.Value; + + foreach (var revealedInValue in triggerInformation.RevealedInValues) + if (updatedRound.RealTimeMinersInformation.ContainsKey(revealedInValue.Key) && + (updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == Hash.Empty || + updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue == null)) + updatedRound.RealTimeMinersInformation[revealedInValue.Key].PreviousInValue = revealedInValue.Value; + } - if (!nextRound.RealTimeMinersInformation.Keys.Contains(pubkey)) - { - // This miner was replaced by another miner in next round. - return new AElfConsensusHeaderInformation - { - SenderPubkey = ByteStringHelper.FromHexString(pubkey), - Round = nextRound, - Behaviour = triggerInformation.Behaviour - }; - } + private AElfConsensusHeaderInformation GetConsensusExtraDataForTinyBlock(Round currentRound, + string pubkey, AElfConsensusTriggerInformation triggerInformation) + { + currentRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = currentRound + .RealTimeMinersInformation[pubkey].ProducedTinyBlocks.Add(1); + currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks = + currentRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); + currentRound.RealTimeMinersInformation[pubkey].ActualMiningTimes + .Add(Context.CurrentBlockTime); + + return new AElfConsensusHeaderInformation + { + SenderPubkey = ByteStringHelper.FromHexString(pubkey), + Round = currentRound.GetTinyBlockRound(pubkey), + Behaviour = triggerInformation.Behaviour + }; + } - RevealSharedInValues(currentRound, pubkey); + private AElfConsensusHeaderInformation GetConsensusExtraDataForNextRound(Round currentRound, + string pubkey, AElfConsensusTriggerInformation triggerInformation) + { + GenerateNextRoundInformation(currentRound, Context.CurrentBlockTime, out var nextRound); - nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks = - nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); - Context.LogDebug(() => $"Mined blocks: {nextRound.GetMinedBlocks()}"); - nextRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; - nextRound.RealTimeMinersInformation[pubkey].ActualMiningTimes - .Add(Context.CurrentBlockTime); + nextRound.ExtraBlockProducerOfPreviousRound = pubkey; + if (!nextRound.RealTimeMinersInformation.Keys.Contains(pubkey)) + // This miner was replaced by another miner in next round. return new AElfConsensusHeaderInformation { SenderPubkey = ByteStringHelper.FromHexString(pubkey), Round = nextRound, Behaviour = triggerInformation.Behaviour }; - } - private AElfConsensusHeaderInformation GetConsensusExtraDataForNextTerm(string pubkey, - AElfConsensusTriggerInformation triggerInformation) + RevealSharedInValues(currentRound, pubkey); + + nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks = + nextRound.RealTimeMinersInformation[pubkey].ProducedBlocks.Add(1); + Context.LogDebug(() => $"Mined blocks: {nextRound.GetMinedBlocks()}"); + nextRound.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; + nextRound.RealTimeMinersInformation[pubkey].ActualMiningTimes + .Add(Context.CurrentBlockTime); + + return new AElfConsensusHeaderInformation { - var firstRoundOfNextTerm = GenerateFirstRoundOfNextTerm(pubkey, State.MiningInterval.Value); - Assert(firstRoundOfNextTerm.RoundId != 0, "Failed to generate new round information."); - if (firstRoundOfNextTerm.RealTimeMinersInformation.ContainsKey(pubkey)) - { - firstRoundOfNextTerm.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; - } + SenderPubkey = ByteStringHelper.FromHexString(pubkey), + Round = nextRound, + Behaviour = triggerInformation.Behaviour + }; + } - return new AElfConsensusHeaderInformation - { - SenderPubkey = ByteStringHelper.FromHexString(pubkey), - Round = firstRoundOfNextTerm, - Behaviour = triggerInformation.Behaviour - }; - } + private AElfConsensusHeaderInformation GetConsensusExtraDataForNextTerm(string pubkey, + AElfConsensusTriggerInformation triggerInformation) + { + var firstRoundOfNextTerm = GenerateFirstRoundOfNextTerm(pubkey, State.MiningInterval.Value); + Assert(firstRoundOfNextTerm.RoundId != 0, "Failed to generate new round information."); + if (firstRoundOfNextTerm.RealTimeMinersInformation.ContainsKey(pubkey)) + firstRoundOfNextTerm.RealTimeMinersInformation[pubkey].ProducedTinyBlocks = 1; + + return new AElfConsensusHeaderInformation + { + SenderPubkey = ByteStringHelper.FromHexString(pubkey), + Round = firstRoundOfNextTerm, + Behaviour = triggerInformation.Behaviour + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusCommand.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusCommand.cs index 67b47173fb..160a2cdf01 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusCommand.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetConsensusCommand.cs @@ -1,100 +1,97 @@ using System.Linq; -using AElf.Standards.ACS4; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -using Google.Protobuf; +using AElf.Standards.ACS4; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// AElf Consensus Behaviour is changeable in this method when + /// this miner should skip his time slot more precisely. + /// + /// + /// + /// + /// + /// + private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, Round currentRound, + string pubkey, Timestamp currentBlockTime = null) { - /// - /// AElf Consensus Behaviour is changeable in this method when - /// this miner should skip his time slot more precisely. - /// - /// - /// - /// - /// - /// - private ConsensusCommand GetConsensusCommand(AElfConsensusBehaviour behaviour, Round currentRound, - string pubkey, Timestamp currentBlockTime = null) - { - if (SolitaryMinerDetection(currentRound, pubkey)) - return ConsensusCommandProvider.InvalidConsensusCommand; + if (SolitaryMinerDetection(currentRound, pubkey)) + return ConsensusCommandProvider.InvalidConsensusCommand; - Context.LogDebug(() => $"Params to get command: {behaviour}, {pubkey}, {currentBlockTime}"); + Context.LogDebug(() => $"Params to get command: {behaviour}, {pubkey}, {currentBlockTime}"); - if (currentRound.RoundNumber == 1 && behaviour == AElfConsensusBehaviour.UpdateValue) - return new ConsensusCommandProvider(new FirstRoundCommandStrategy(currentRound, pubkey, - currentBlockTime, behaviour)).GetConsensusCommand(); + if (currentRound.RoundNumber == 1 && behaviour == AElfConsensusBehaviour.UpdateValue) + return new ConsensusCommandProvider(new FirstRoundCommandStrategy(currentRound, pubkey, + currentBlockTime, behaviour)).GetConsensusCommand(); - switch (behaviour) - { - case AElfConsensusBehaviour.UpdateValue: - TryToGetPreviousRoundInformation(out var previousRound); - return new ConsensusCommandProvider(new NormalBlockCommandStrategy(currentRound, pubkey, - currentBlockTime, previousRound.RoundId)).GetConsensusCommand(); - - case AElfConsensusBehaviour.NextRound: - case AElfConsensusBehaviour.NextTerm: - return new ConsensusCommandProvider( - new TerminateRoundCommandStrategy(currentRound, pubkey, currentBlockTime, - behaviour == AElfConsensusBehaviour.NextTerm)) - .GetConsensusCommand(); + switch (behaviour) + { + case AElfConsensusBehaviour.UpdateValue: + TryToGetPreviousRoundInformation(out var previousRound); + return new ConsensusCommandProvider(new NormalBlockCommandStrategy(currentRound, pubkey, + currentBlockTime, previousRound.RoundId)).GetConsensusCommand(); - case AElfConsensusBehaviour.TinyBlock: - { - var consensusCommand = - new ConsensusCommandProvider(new TinyBlockCommandStrategy(currentRound, pubkey, - currentBlockTime, GetMaximumBlocksCount())).GetConsensusCommand(); - return consensusCommand; - } + case AElfConsensusBehaviour.NextRound: + case AElfConsensusBehaviour.NextTerm: + return new ConsensusCommandProvider( + new TerminateRoundCommandStrategy(currentRound, pubkey, currentBlockTime, + behaviour == AElfConsensusBehaviour.NextTerm)) + .GetConsensusCommand(); - default: - return ConsensusCommandProvider.InvalidConsensusCommand; + case AElfConsensusBehaviour.TinyBlock: + { + var consensusCommand = + new ConsensusCommandProvider(new TinyBlockCommandStrategy(currentRound, pubkey, + currentBlockTime, GetMaximumBlocksCount())).GetConsensusCommand(); + return consensusCommand; } + + default: + return ConsensusCommandProvider.InvalidConsensusCommand; } + } - /// - /// If current miner mined blocks only himself for 2 rounds, - /// just stop and waiting to execute other miners' blocks. - /// - /// - /// - /// - private bool SolitaryMinerDetection(Round currentRound, string pubkey) + /// + /// If current miner mined blocks only himself for 2 rounds, + /// just stop and waiting to execute other miners' blocks. + /// + /// + /// + /// + private bool SolitaryMinerDetection(Round currentRound, string pubkey) + { + var isAlone = false; + // Skip this detection until 4th round. + if (currentRound.RoundNumber > 3 && currentRound.RealTimeMinersInformation.Count > 2) { - var isAlone = false; - // Skip this detection until 4th round. - if (currentRound.RoundNumber > 3 && currentRound.RealTimeMinersInformation.Count > 2) - { - // Not single node. - - var minedMinersOfCurrentRound = currentRound.GetMinedMiners(); - isAlone = minedMinersOfCurrentRound.Count == 0; + // Not single node. - // If only this node mined during previous round, stop mining. - if (TryToGetPreviousRoundInformation(out var previousRound) && isAlone) - { - var minedMiners = previousRound.GetMinedMiners(); - isAlone = minedMiners.Count == 1 && - minedMiners.Select(m => m.Pubkey).Contains(pubkey); - } + var minedMinersOfCurrentRound = currentRound.GetMinedMiners(); + isAlone = minedMinersOfCurrentRound.Count == 0; - // check one further round. - if (isAlone && TryToGetRoundInformation(previousRound.RoundNumber.Sub(1), - out var previousPreviousRound)) - { - var minedMiners = previousPreviousRound.GetMinedMiners(); - isAlone = minedMiners.Count == 1 && - minedMiners.Select(m => m.Pubkey).Contains(pubkey); - } + // If only this node mined during previous round, stop mining. + if (TryToGetPreviousRoundInformation(out var previousRound) && isAlone) + { + var minedMiners = previousRound.GetMinedMiners(); + isAlone = minedMiners.Count == 1 && + minedMiners.Select(m => m.Pubkey).Contains(pubkey); } - return isAlone; + // check one further round. + if (isAlone && TryToGetRoundInformation(previousRound.RoundNumber.Sub(1), + out var previousPreviousRound)) + { + var minedMiners = previousPreviousRound.GetMinedMiners(); + isAlone = minedMiners.Count == 1 && + minedMiners.Select(m => m.Pubkey).Contains(pubkey); + } } + + return isAlone; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetMaximumBlocksCount.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetMaximumBlocksCount.cs index 2c4fba1952..4a353065c3 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetMaximumBlocksCount.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_GetMaximumBlocksCount.cs @@ -2,146 +2,137 @@ using System.Linq; using AElf.CSharp.Core; using AElf.Sdk.CSharp; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public override Int32Value GetMaximumBlocksCount(Empty input) { - public override Int32Value GetMaximumBlocksCount(Empty input) - { - return new Int32Value {Value = GetMaximumBlocksCount()}; - } + return new Int32Value { Value = GetMaximumBlocksCount() }; + } - /// - /// Implemented GitHub PR #1952. - /// Adjust (mainly reduce) the count of tiny blocks produced by a miner each time to avoid too many forks. - /// - /// - private int GetMaximumBlocksCount() - { - TryToGetCurrentRoundInformation(out var currentRound); - var libRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; - var libBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; - var currentHeight = Context.CurrentHeight; - var currentRoundNumber = currentRound.RoundNumber; + /// + /// Implemented GitHub PR #1952. + /// Adjust (mainly reduce) the count of tiny blocks produced by a miner each time to avoid too many forks. + /// + /// + private int GetMaximumBlocksCount() + { + TryToGetCurrentRoundInformation(out var currentRound); + var libRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; + var libBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; + var currentHeight = Context.CurrentHeight; + var currentRoundNumber = currentRound.RoundNumber; - Context.LogDebug(() => - $"Calculating max blocks count based on:\nR_LIB: {libRoundNumber}\nH_LIB:{libBlockHeight}\nR:{currentRoundNumber}\nH:{currentHeight}"); + Context.LogDebug(() => + $"Calculating max blocks count based on:\nR_LIB: {libRoundNumber}\nH_LIB:{libBlockHeight}\nR:{currentRoundNumber}\nH:{currentHeight}"); - if (libRoundNumber == 0) - { - return AEDPoSContractConstants.MaximumTinyBlocksCount; - } + if (libRoundNumber == 0) return AEDPoSContractConstants.MaximumTinyBlocksCount; - var blockchainMiningStatusEvaluator = new BlockchainMiningStatusEvaluator(libRoundNumber, - currentRoundNumber, AEDPoSContractConstants.MaximumTinyBlocksCount); - blockchainMiningStatusEvaluator.Deconstruct(out var blockchainMiningStatus); + var blockchainMiningStatusEvaluator = new BlockchainMiningStatusEvaluator(libRoundNumber, + currentRoundNumber, AEDPoSContractConstants.MaximumTinyBlocksCount); + blockchainMiningStatusEvaluator.Deconstruct(out var blockchainMiningStatus); - Context.LogDebug(() => $"Current blockchain mining status: {blockchainMiningStatus.ToString()}"); + Context.LogDebug(() => $"Current blockchain mining status: {blockchainMiningStatus.ToString()}"); - // If R_LIB + 2 < R < R_LIB + CB1, CB goes to Min(T(L2 * (CB1 - (R - R_LIB)) / A), CB0), while CT stays same as before. - if (blockchainMiningStatus == BlockchainMiningStatus.Abnormal) - { - var previousRoundMinedMinerList = State.MinedMinerListMap[currentRoundNumber.Sub(1)].Pubkeys; - var previousPreviousRoundMinedMinerList = State.MinedMinerListMap[currentRoundNumber.Sub(2)].Pubkeys; - var minersOfLastTwoRounds = previousRoundMinedMinerList - .Intersect(previousPreviousRoundMinedMinerList).Count(); - var factor = minersOfLastTwoRounds.Mul( - blockchainMiningStatusEvaluator.SevereStatusRoundsThreshold.Sub( - (int) currentRoundNumber.Sub(libRoundNumber))); - var count = Math.Min(AEDPoSContractConstants.MaximumTinyBlocksCount, - Ceiling(factor, currentRound.RealTimeMinersInformation.Count)); - Context.LogDebug(() => $"Maximum blocks count tune to {count}"); - return count; - } - - //If R >= R_LIB + CB1, CB goes to 1, and CT goes to 0 - if (blockchainMiningStatus == BlockchainMiningStatus.Severe) - { - // Fire an event to notify miner not package normal transaction. - Context.Fire(new IrreversibleBlockHeightUnacceptable - { - DistanceToIrreversibleBlockHeight = currentHeight.Sub(libBlockHeight) - }); - State.IsPreviousBlockInSevereStatus.Value = true; - return 1; - } - - if (!State.IsPreviousBlockInSevereStatus.Value) - return AEDPoSContractConstants.MaximumTinyBlocksCount; + // If R_LIB + 2 < R < R_LIB + CB1, CB goes to Min(T(L2 * (CB1 - (R - R_LIB)) / A), CB0), while CT stays same as before. + if (blockchainMiningStatus == BlockchainMiningStatus.Abnormal) + { + var previousRoundMinedMinerList = State.MinedMinerListMap[currentRoundNumber.Sub(1)].Pubkeys; + var previousPreviousRoundMinedMinerList = State.MinedMinerListMap[currentRoundNumber.Sub(2)].Pubkeys; + var minersOfLastTwoRounds = previousRoundMinedMinerList + .Intersect(previousPreviousRoundMinedMinerList).Count(); + var factor = minersOfLastTwoRounds.Mul( + blockchainMiningStatusEvaluator.SevereStatusRoundsThreshold.Sub( + (int)currentRoundNumber.Sub(libRoundNumber))); + var count = Math.Min(AEDPoSContractConstants.MaximumTinyBlocksCount, + Ceiling(factor, currentRound.RealTimeMinersInformation.Count)); + Context.LogDebug(() => $"Maximum blocks count tune to {count}"); + return count; + } + //If R >= R_LIB + CB1, CB goes to 1, and CT goes to 0 + if (blockchainMiningStatus == BlockchainMiningStatus.Severe) + { + // Fire an event to notify miner not package normal transaction. Context.Fire(new IrreversibleBlockHeightUnacceptable { - DistanceToIrreversibleBlockHeight = 0 + DistanceToIrreversibleBlockHeight = currentHeight.Sub(libBlockHeight) }); - State.IsPreviousBlockInSevereStatus.Value = false; + State.IsPreviousBlockInSevereStatus.Value = true; + return 1; + } + if (!State.IsPreviousBlockInSevereStatus.Value) return AEDPoSContractConstants.MaximumTinyBlocksCount; - } - private static int Ceiling(int num1, int num2) + Context.Fire(new IrreversibleBlockHeightUnacceptable { - var flag = num1 % num2; - return flag == 0 ? num1.Div(num2) : num1.Div(num2).Add(1); - } + DistanceToIrreversibleBlockHeight = 0 + }); + State.IsPreviousBlockInSevereStatus.Value = false; - private class BlockchainMiningStatusEvaluator - { - private const int AbnormalThresholdRoundsCount = 2; - - /// - /// Stands for R_LIB - /// - private readonly long _libRoundNumber; - - /// - /// Stands for R - /// - private readonly long _currentRoundNumber; - - /// - /// Stands for CB0 - /// - private readonly int _maximumTinyBlocksCount; - - /// - /// Stands for CB1 - /// - public int SevereStatusRoundsThreshold => Math.Max(8, _maximumTinyBlocksCount); - - public BlockchainMiningStatusEvaluator(long currentConfirmedIrreversibleBlockRoundNumber, - long currentRoundNumber, int maximumTinyBlocksCount) - { - _libRoundNumber = currentConfirmedIrreversibleBlockRoundNumber; - _currentRoundNumber = currentRoundNumber; - _maximumTinyBlocksCount = maximumTinyBlocksCount; - } + return AEDPoSContractConstants.MaximumTinyBlocksCount; + } - public void Deconstruct(out BlockchainMiningStatus status) - { - status = BlockchainMiningStatus.Normal; - - if (_libRoundNumber.Add(AbnormalThresholdRoundsCount) < _currentRoundNumber && - _currentRoundNumber < _libRoundNumber.Add(SevereStatusRoundsThreshold)) - { - status = BlockchainMiningStatus.Abnormal; - } - - if (_currentRoundNumber >= _libRoundNumber.Add(SevereStatusRoundsThreshold)) - { - status = BlockchainMiningStatus.Severe; - } - } + private static int Ceiling(int num1, int num2) + { + var flag = num1 % num2; + return flag == 0 ? num1.Div(num2) : num1.Div(num2).Add(1); + } + + private class BlockchainMiningStatusEvaluator + { + private const int AbnormalThresholdRoundsCount = 2; + + /// + /// Stands for R + /// + private readonly long _currentRoundNumber; + + /// + /// Stands for R_LIB + /// + private readonly long _libRoundNumber; + + /// + /// Stands for CB0 + /// + private readonly int _maximumTinyBlocksCount; + + public BlockchainMiningStatusEvaluator(long currentConfirmedIrreversibleBlockRoundNumber, + long currentRoundNumber, int maximumTinyBlocksCount) + { + _libRoundNumber = currentConfirmedIrreversibleBlockRoundNumber; + _currentRoundNumber = currentRoundNumber; + _maximumTinyBlocksCount = maximumTinyBlocksCount; } - private enum BlockchainMiningStatus + /// + /// Stands for CB1 + /// + public int SevereStatusRoundsThreshold => Math.Max(8, _maximumTinyBlocksCount); + + public void Deconstruct(out BlockchainMiningStatus status) { - Normal, - Abnormal, - Severe + status = BlockchainMiningStatus.Normal; + + if (_libRoundNumber.Add(AbnormalThresholdRoundsCount) < _currentRoundNumber && + _currentRoundNumber < _libRoundNumber.Add(SevereStatusRoundsThreshold)) + status = BlockchainMiningStatus.Abnormal; + + if (_currentRoundNumber >= _libRoundNumber.Add(SevereStatusRoundsThreshold)) + status = BlockchainMiningStatus.Severe; } } + + private enum BlockchainMiningStatus + { + Normal, + Abnormal, + Severe + } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_HelpMethods.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_HelpMethods.cs index 6b42f61893..39b05ac4a1 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_HelpMethods.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_HelpMethods.cs @@ -1,77 +1,77 @@ -using System.Collections.Generic; -using System.Linq; using AElf.CSharp.Core; using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private bool IsMainChain { - private bool IsMainChain + get { - get - { - if (_isMainChain != null) return (bool) _isMainChain; - _isMainChain = State.IsMainChain.Value; - return (bool) _isMainChain; - } + if (_isMainChain != null) return (bool)_isMainChain; + _isMainChain = State.IsMainChain.Value; + return (bool)_isMainChain; } + } - private Timestamp GetBlockchainStartTimestamp() - { - return State.BlockchainStartTimestamp.Value ?? new Timestamp(); - } + private Timestamp GetBlockchainStartTimestamp() + { + return State.BlockchainStartTimestamp.Value ?? new Timestamp(); + } - private bool IsFirstRoundOfCurrentTerm(out long termNumber) - { - termNumber = 1; - return TryToGetTermNumber(out termNumber) && - TryToGetPreviousRoundInformation(out var previousRound) && - previousRound.TermNumber != termNumber || - TryToGetRoundNumber(out var roundNumber) && roundNumber == 1; - } + private bool IsFirstRoundOfCurrentTerm(out long termNumber) + { + termNumber = 1; + return (TryToGetTermNumber(out termNumber) && + TryToGetPreviousRoundInformation(out var previousRound) && + previousRound.TermNumber != termNumber) || + (TryToGetRoundNumber(out var roundNumber) && roundNumber == 1); + } - private bool TryToGetTermNumber(out long termNumber) - { - termNumber = State.CurrentTermNumber.Value; - return termNumber != 0; - } + private bool TryToGetTermNumber(out long termNumber) + { + termNumber = State.CurrentTermNumber.Value; + return termNumber != 0; + } - private bool TryToGetRoundNumber(out long roundNumber) - { - roundNumber = State.CurrentRoundNumber.Value; - return roundNumber != 0; - } + private bool TryToGetRoundNumber(out long roundNumber) + { + roundNumber = State.CurrentRoundNumber.Value; + return roundNumber != 0; + } - private bool TryToGetCurrentRoundInformation(out Round round) - { - round = null; - if (!TryToGetRoundNumber(out var roundNumber)) return false; - round = State.Rounds[roundNumber]; - return !round.IsEmpty; - } + private bool TryToGetCurrentRoundInformation(out Round round) + { + round = null; + if (!TryToGetRoundNumber(out var roundNumber)) return false; + round = State.Rounds[roundNumber]; + return !round.IsEmpty; + } - private bool TryToGetPreviousRoundInformation(out Round previousRound) - { - previousRound = new Round(); - if (!TryToGetRoundNumber(out var roundNumber)) return false; - if (roundNumber < 2) return false; - var targetRoundNumber = roundNumber.Sub(1); - previousRound = State.Rounds[targetRoundNumber]; - return !previousRound.IsEmpty; - } + private bool TryToGetPreviousRoundInformation(out Round previousRound) + { + previousRound = new Round(); + if (!TryToGetRoundNumber(out var roundNumber)) return false; + if (roundNumber < 2) return false; + var targetRoundNumber = roundNumber.Sub(1); + previousRound = State.Rounds[targetRoundNumber]; + return !previousRound.IsEmpty; + } - private bool TryToGetRoundInformation(long roundNumber, out Round round) - { - round = State.Rounds[roundNumber]; - return !round.IsEmpty; - } + private bool TryToGetRoundInformation(long roundNumber, out Round round) + { + round = State.Rounds[roundNumber]; + return !round.IsEmpty; + } - private Transaction GenerateTransaction(string methodName, IMessage parameter) => new Transaction + private Transaction GenerateTransaction(string methodName, IMessage parameter) + { + return new() { From = Context.Sender, To = Context.Self, @@ -80,91 +80,81 @@ private bool TryToGetRoundInformation(long roundNumber, out Round round) RefBlockNumber = Context.CurrentHeight, RefBlockPrefix = BlockHelper.GetRefBlockPrefix(Context.PreviousBlockHash) }; + } - private void SetBlockchainStartTimestamp(Timestamp timestamp) - { - Context.LogDebug(() => $"Set start timestamp to {timestamp}"); - State.BlockchainStartTimestamp.Value = timestamp; - } + private void SetBlockchainStartTimestamp(Timestamp timestamp) + { + Context.LogDebug(() => $"Set start timestamp to {timestamp}"); + State.BlockchainStartTimestamp.Value = timestamp; + } - private bool TryToUpdateRoundNumber(long roundNumber) - { - var oldRoundNumber = State.CurrentRoundNumber.Value; - if (roundNumber != 1 && oldRoundNumber + 1 != roundNumber) return false; - State.CurrentRoundNumber.Value = roundNumber; - return true; - } + private bool TryToUpdateRoundNumber(long roundNumber) + { + var oldRoundNumber = State.CurrentRoundNumber.Value; + if (roundNumber != 1 && oldRoundNumber + 1 != roundNumber) return false; + State.CurrentRoundNumber.Value = roundNumber; + return true; + } - /// - /// Will force to generate a `Change` to tx executing result. - /// - /// - private void AddRoundInformation(Round round) - { - State.Rounds.Set(round.RoundNumber, round); + /// + /// Will force to generate a `Change` to tx executing result. + /// + /// + private void AddRoundInformation(Round round) + { + State.Rounds.Set(round.RoundNumber, round); - if (round.RoundNumber > 1 && !round.IsMinerListJustChanged) - { - // No need to share secret pieces if miner list just changed. - - Context.Fire(new SecretSharingInformation - { - CurrentRoundId = round.RoundId, - PreviousRound = State.Rounds[round.RoundNumber.Sub(1)], - PreviousRoundId = State.Rounds[round.RoundNumber.Sub(1)].RoundId - }); - } - - // Only clear old round information when the mining status is Normal. - var roundNumberToRemove = round.RoundNumber.Sub(AEDPoSContractConstants.KeepRounds); - if ( - roundNumberToRemove > - 1 && // Which means we won't remove the information of the first round of first term. - GetMaximumBlocksCount() == AEDPoSContractConstants.MaximumTinyBlocksCount) + if (round.RoundNumber > 1 && !round.IsMinerListJustChanged) + // No need to share secret pieces if miner list just changed. + + Context.Fire(new SecretSharingInformation { - State.Rounds.Remove(roundNumberToRemove); - } - } + CurrentRoundId = round.RoundId, + PreviousRound = State.Rounds[round.RoundNumber.Sub(1)], + PreviousRoundId = State.Rounds[round.RoundNumber.Sub(1)].RoundId + }); + + // Only clear old round information when the mining status is Normal. + var roundNumberToRemove = round.RoundNumber.Sub(AEDPoSContractConstants.KeepRounds); + if ( + roundNumberToRemove > + 1 && // Which means we won't remove the information of the first round of first term. + GetMaximumBlocksCount() == AEDPoSContractConstants.MaximumTinyBlocksCount) + State.Rounds.Remove(roundNumberToRemove); + } - private bool TryToUpdateRoundInformation(Round round) - { - var ri = State.Rounds[round.RoundNumber]; - if (ri == null) return false; - State.Rounds[round.RoundNumber] = round; - return true; - } + private bool TryToUpdateRoundInformation(Round round) + { + var ri = State.Rounds[round.RoundNumber]; + if (ri == null) return false; + State.Rounds[round.RoundNumber] = round; + return true; + } - private void EnsureTransactionOnlyExecutedOnceInOneBlock() - { - Assert(State.LatestExecutedHeight.Value != Context.CurrentHeight, "Cannot execute this tx."); - State.LatestExecutedHeight.Value = Context.CurrentHeight; - } + private void EnsureTransactionOnlyExecutedOnceInOneBlock() + { + Assert(State.LatestExecutedHeight.Value != Context.CurrentHeight, "Cannot execute this tx."); + State.LatestExecutedHeight.Value = Context.CurrentHeight; + } - private void EnsureTokenContractAddressSet() - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - } + private void EnsureTokenContractAddressSet() + { + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + } - private void EnsureElectionContractAddressSet() - { - if (State.ElectionContract.Value == null) - { - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - } - } + private void EnsureElectionContractAddressSet() + { + if (State.ElectionContract.Value == null) + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + } - private void EnsureParliamentContractAddressSet() - { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - } + private void EnsureParliamentContractAddressSet() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_LIB.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_LIB.cs index f43ed63cfe..2de3e15e2a 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_LIB.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_LIB.cs @@ -1,40 +1,35 @@ using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private class LastIrreversibleBlockHeightCalculator { - private class LastIrreversibleBlockHeightCalculator + private readonly Round _currentRound; + private readonly Round _previousRound; + + public LastIrreversibleBlockHeightCalculator(Round currentRound, Round previousRound) { - private readonly Round _currentRound; - private readonly Round _previousRound; + _currentRound = currentRound; + _previousRound = previousRound; + } - public LastIrreversibleBlockHeightCalculator(Round currentRound, Round previousRound) - { - _currentRound = currentRound; - _previousRound = previousRound; - } + public void Deconstruct(out long libHeight) + { + if (_currentRound.IsEmpty || _previousRound.IsEmpty) libHeight = 0; - public void Deconstruct(out long libHeight) + var minedMiners = _currentRound.GetMinedMiners().Select(m => m.Pubkey).ToList(); + var impliedIrreversibleHeights = _previousRound.GetSortedImpliedIrreversibleBlockHeights(minedMiners); + if (impliedIrreversibleHeights.Count < _currentRound.MinersCountOfConsent) { - if (_currentRound.IsEmpty || _previousRound.IsEmpty) - { - libHeight = 0; - } - - var minedMiners = _currentRound.GetMinedMiners().Select(m => m.Pubkey).ToList(); - var impliedIrreversibleHeights = _previousRound.GetSortedImpliedIrreversibleBlockHeights(minedMiners); - if (impliedIrreversibleHeights.Count < _currentRound.MinersCountOfConsent) - { - libHeight = 0; - return; - } - - libHeight = impliedIrreversibleHeights[impliedIrreversibleHeights.Count.Sub(1).Div(3)]; + libHeight = 0; + return; } + + libHeight = impliedIrreversibleHeights[impliedIrreversibleHeights.Count.Sub(1).Div(3)]; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_MaximumMinersCount.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_MaximumMinersCount.cs index 170677cfe8..b4c02f13cd 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_MaximumMinersCount.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_MaximumMinersCount.cs @@ -1,84 +1,78 @@ using System; -using AElf.Standards.ACS1; using AElf.Contracts.Election; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSContract { - public partial class AEDPoSContract + public override Empty SetMaximumMinersCount(Int32Value input) { - public override Empty SetMaximumMinersCount(Int32Value input) - { - EnsureElectionContractAddressSet(); + EnsureElectionContractAddressSet(); - Assert(input.Value > 0, "Invalid max miners count."); + Assert(input.Value > 0, "Invalid max miners count."); - RequiredMaximumMinersCountControllerSet(); - Assert(Context.Sender == State.MaximumMinersCountController.Value.OwnerAddress, - "No permission to set max miners count."); + RequiredMaximumMinersCountControllerSet(); + Assert(Context.Sender == State.MaximumMinersCountController.Value.OwnerAddress, + "No permission to set max miners count."); - TryToGetCurrentRoundInformation(out Round round); + TryToGetCurrentRoundInformation(out var round); - State.MaximumMinersCount.Value = input.Value; - State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput - { - MinersCount = GetMinersCount(round) - }); + State.MaximumMinersCount.Value = input.Value; + State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput + { + MinersCount = GetMinersCount(round) + }); - return new Empty(); - } + return new Empty(); + } - private void RequiredMaximumMinersCountControllerSet() + private void RequiredMaximumMinersCountControllerSet() + { + if (State.MaximumMinersCountController.Value != null) return; + EnsureParliamentContractAddressSet(); + + var defaultAuthority = new AuthorityInfo { - if (State.MaximumMinersCountController.Value != null) return; - EnsureParliamentContractAddressSet(); + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; + State.MaximumMinersCountController.Value = defaultAuthority; + } - State.MaximumMinersCountController.Value = defaultAuthority; - } + public override Empty ChangeMaximumMinersCountController(AuthorityInfo input) + { + RequiredMaximumMinersCountControllerSet(); + AssertSenderAddressWith(State.MaximumMinersCountController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty ChangeMaximumMinersCountController(AuthorityInfo input) - { - RequiredMaximumMinersCountControllerSet(); - AssertSenderAddressWith(State.MaximumMinersCountController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + State.MaximumMinersCountController.Value = input; + return new Empty(); + } - State.MaximumMinersCountController.Value = input; - return new Empty(); - } + public override AuthorityInfo GetMaximumMinersCountController(Empty input) + { + RequiredMaximumMinersCountControllerSet(); + return State.MaximumMinersCountController.Value; + } - public override AuthorityInfo GetMaximumMinersCountController(Empty input) + public override Int32Value GetMaximumMinersCount(Empty input) + { + return new Int32Value { - RequiredMaximumMinersCountControllerSet(); - return State.MaximumMinersCountController.Value; - } + Value = Math.Min(GetAutoIncreasedMinersCount(), State.MaximumMinersCount.Value) + }; + } - public override Int32Value GetMaximumMinersCount(Empty input) - { - return new Int32Value - { - Value = Math.Min(GetAutoIncreasedMinersCount(), State.MaximumMinersCount.Value) - }; - } + private int GetAutoIncreasedMinersCount() + { + if (State.BlockchainStartTimestamp.Value == null) return AEDPoSContractConstants.SupposedMinersCount; - private int GetAutoIncreasedMinersCount() - { - if (State.BlockchainStartTimestamp.Value == null) - { - return AEDPoSContractConstants.SupposedMinersCount; - } - - return AEDPoSContractConstants.SupposedMinersCount.Add( - (int) (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds - .Div(State.MinerIncreaseInterval.Value).Mul(2)); - } + return AEDPoSContractConstants.SupposedMinersCount.Add( + (int)(Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds + .Div(State.MinerIncreaseInterval.Value).Mul(2)); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs index 3561e5aee4..fbe886f8a4 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs @@ -1,169 +1,152 @@ using System.Linq; using AElf.Contracts.Election; -using AElf.Standards.ACS10; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS10; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public override Empty NextTerm(Round input) { - public override Empty NextTerm(Round input) - { - SupplyCurrentRoundInformation(); - ProcessConsensusInformation(input); - return new Empty(); - } - - private void UpdateProducedBlocksNumberOfSender(Round input) - { - var senderPubkey = Context.RecoverPublicKey().ToHex(); + SupplyCurrentRoundInformation(); + ProcessConsensusInformation(input); + return new Empty(); + } - // Update produced block number of transaction sender. - if (input.RealTimeMinersInformation.ContainsKey(senderPubkey)) + private void UpdateProducedBlocksNumberOfSender(Round input) + { + var senderPubkey = Context.RecoverPublicKey().ToHex(); + + // Update produced block number of transaction sender. + if (input.RealTimeMinersInformation.ContainsKey(senderPubkey)) + input.RealTimeMinersInformation[senderPubkey].ProducedBlocks = + input.RealTimeMinersInformation[senderPubkey].ProducedBlocks.Add(1); + else + // If the sender isn't in miner list of next term. + State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput { - input.RealTimeMinersInformation[senderPubkey].ProducedBlocks = - input.RealTimeMinersInformation[senderPubkey].ProducedBlocks.Add(1); - } - else + Pubkey = senderPubkey, + RecentlyProducedBlocks = 1 + }); + } + + private void UpdateCurrentMinerInformationToElectionContract(Round previousRound) + { + State.ElectionContract.UpdateMultipleCandidateInformation.Send(new UpdateMultipleCandidateInformationInput + { + Value = { - // If the sender isn't in miner list of next term. - State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput + previousRound.RealTimeMinersInformation.Select(i => new UpdateCandidateInformationInput { - Pubkey = senderPubkey, - RecentlyProducedBlocks = 1 - }); + Pubkey = i.Key, + RecentlyProducedBlocks = i.Value.ProducedBlocks, + RecentlyMissedTimeSlots = i.Value.MissedTimeSlots + }) } - } + }); + } - private void UpdateCurrentMinerInformationToElectionContract(Round previousRound) - { - State.ElectionContract.UpdateMultipleCandidateInformation.Send(new UpdateMultipleCandidateInformationInput + private void UpdateMinersCountToElectionContract(Round input) + { + var minersCount = GetMinersCount(input); + if (minersCount != 0 && State.ElectionContract.Value != null) + State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput { - Value = - { - previousRound.RealTimeMinersInformation.Select(i => new UpdateCandidateInformationInput - { - Pubkey = i.Key, - RecentlyProducedBlocks = i.Value.ProducedBlocks, - RecentlyMissedTimeSlots = i.Value.MissedTimeSlots - }) - } + MinersCount = minersCount }); - } + } - private void UpdateMinersCountToElectionContract(Round input) + /// + /// Only Main Chain can perform this action. + /// + /// + /// + /// + /// + private bool SetMinerList(MinerList minerList, long termNumber, bool gonnaReplaceSomeone = false) + { + // Miners for one specific term should only update once. + var minerListFromState = State.MinerListMap[termNumber]; + if (gonnaReplaceSomeone || minerListFromState == null) { - var minersCount = GetMinersCount(input); - if (minersCount != 0 && State.ElectionContract.Value != null) - { - State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput - { - MinersCount = minersCount - }); - } + State.MainChainCurrentMinerList.Value = minerList; + State.MinerListMap[termNumber] = minerList; + return true; } - /// - /// Only Main Chain can perform this action. - /// - /// - /// - /// - /// - private bool SetMinerList(MinerList minerList, long termNumber, bool gonnaReplaceSomeone = false) - { - // Miners for one specific term should only update once. - var minerListFromState = State.MinerListMap[termNumber]; - if (gonnaReplaceSomeone || minerListFromState == null) - { - State.MainChainCurrentMinerList.Value = minerList; - State.MinerListMap[termNumber] = minerList; - return true; - } + return false; + } - return false; - } + /// + /// Normally this process contained in NextRound method. + /// + private void CountMissedTimeSlots() + { + if (!TryToGetCurrentRoundInformation(out var currentRound)) return; - /// - /// Normally this process contained in NextRound method. - /// - private void CountMissedTimeSlots() - { - if (!TryToGetCurrentRoundInformation(out var currentRound)) return; + foreach (var minerInRound in currentRound.RealTimeMinersInformation) + if (minerInRound.Value.OutValue == null) + minerInRound.Value.MissedTimeSlots = minerInRound.Value.MissedTimeSlots.Add(1); - foreach (var minerInRound in currentRound.RealTimeMinersInformation) - { - if (minerInRound.Value.OutValue == null) - { - minerInRound.Value.MissedTimeSlots = minerInRound.Value.MissedTimeSlots.Add(1); - } - } + TryToUpdateRoundInformation(currentRound); + } - TryToUpdateRoundInformation(currentRound); - } + private bool TryToUpdateTermNumber(long termNumber) + { + var oldTermNumber = State.CurrentTermNumber.Value; + if (termNumber != 1 && oldTermNumber + 1 != termNumber) return false; - private bool TryToUpdateTermNumber(long termNumber) - { - var oldTermNumber = State.CurrentTermNumber.Value; - if (termNumber != 1 && oldTermNumber + 1 != termNumber) - { - return false; - } + State.CurrentTermNumber.Value = termNumber; + return true; + } - State.CurrentTermNumber.Value = termNumber; - return true; + private bool DonateMiningReward(Round previousRound) + { + if (State.TreasuryContract.Value == null) + { + var treasuryContractAddress = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + // Return false if Treasury Contract didn't deployed. + if (treasuryContractAddress == null) return false; + State.TreasuryContract.Value = treasuryContractAddress; } - private bool DonateMiningReward(Round previousRound) + var miningRewardPerBlock = GetMiningRewardPerBlock(); + var minedBlocks = previousRound.GetMinedBlocks(); + var amount = minedBlocks.Mul(miningRewardPerBlock); + State.TreasuryContract.UpdateMiningReward.Send(new Int64Value { Value = miningRewardPerBlock }); + + if (amount > 0) { - if (State.TreasuryContract.Value == null) + State.TreasuryContract.Donate.Send(new DonateInput { - var treasuryContractAddress = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - // Return false if Treasury Contract didn't deployed. - if (treasuryContractAddress == null) return false; - State.TreasuryContract.Value = treasuryContractAddress; - } - - var miningRewardPerBlock = GetMiningRewardPerBlock(); - var minedBlocks = previousRound.GetMinedBlocks(); - var amount = minedBlocks.Mul(miningRewardPerBlock); - State.TreasuryContract.UpdateMiningReward.Send(new Int64Value {Value = miningRewardPerBlock}); + Symbol = Context.Variables.NativeSymbol, + Amount = amount + }); - if (amount > 0) + Context.Fire(new MiningRewardGenerated { - State.TreasuryContract.Donate.Send(new DonateInput - { - Symbol = Context.Variables.NativeSymbol, - Amount = amount - }); - - Context.Fire(new MiningRewardGenerated - { - TermNumber = previousRound.TermNumber, - Amount = amount - }); - } + TermNumber = previousRound.TermNumber, + Amount = amount + }); + } - Context.LogDebug(() => $"Released {amount} mining rewards."); + Context.LogDebug(() => $"Released {amount} mining rewards."); - return true; - } + return true; + } - private long GetMiningRewardPerBlock() - { - var miningReward = AEDPoSContractConstants.InitialMiningRewardPerBlock; - var blockAge = GetBlockchainAge(); - var denominator = blockAge.Div(AEDPoSContractConstants.TimeToReduceMiningRewardByHalf); - for (var i = 0; i < denominator; i++) - { - miningReward = miningReward.Div(2); - } + private long GetMiningRewardPerBlock() + { + var miningReward = AEDPoSContractConstants.InitialMiningRewardPerBlock; + var blockAge = GetBlockchainAge(); + var denominator = blockAge.Div(AEDPoSContractConstants.TimeToReduceMiningRewardByHalf); + for (var i = 0; i < denominator; i++) miningReward = miningReward.Div(2); - return miningReward; - } + return miningReward; } } \ 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 53d8f26f94..4e37a46580 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -1,389 +1,352 @@ using System.Linq; using System.Runtime.CompilerServices; -using AElf.Standards.ACS10; using AElf.Contracts.Election; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// Same process for every behaviour. + /// + /// + /// + private void ProcessConsensusInformation(dynamic input, [CallerMemberName] string callerMethodName = null) { - /// - /// Same process for every behaviour. - /// - /// - /// - private void ProcessConsensusInformation(dynamic input, [CallerMemberName] string callerMethodName = null) - { - EnsureTransactionOnlyExecutedOnceInOneBlock(); + EnsureTransactionOnlyExecutedOnceInOneBlock(); - Context.LogDebug(() => $"Processing {callerMethodName}"); + Context.LogDebug(() => $"Processing {callerMethodName}"); - /* Privilege check. */ - if (!PreCheck()) - { - Assert(false, "No permission."); - } + /* Privilege check. */ + if (!PreCheck()) Assert(false, "No permission."); - State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty()); + State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty()); - // The only difference. - switch (input) - { - case Round round when callerMethodName == nameof(NextRound): - ProcessNextRound(round); - break; - case Round round when callerMethodName == nameof(NextTerm): - ProcessNextTerm(round); - break; - case UpdateValueInput updateValueInput: - ProcessUpdateValue(updateValueInput); - break; - case TinyBlockInput tinyBlockInput: - ProcessTinyBlock(tinyBlockInput); - break; - } - - var miningInformationUpdated = new MiningInformationUpdated - { - // _processingBlockMinerPubkey is set during PreCheck. - Pubkey = _processingBlockMinerPubkey, - Behaviour = callerMethodName, - MiningTime = Context.CurrentBlockTime, - BlockHeight = Context.CurrentHeight, - PreviousBlockHash = Context.PreviousBlockHash - }; - Context.Fire(miningInformationUpdated); - Context.LogDebug(() => $"Synced mining information: {miningInformationUpdated}"); - - // Make sure the method GetMaximumBlocksCount executed no matter what consensus behaviour is. - var minersCountInTheory = GetMaximumBlocksCount(); - ResetLatestProviderToTinyBlocksCount(minersCountInTheory); - - if (TryToGetCurrentRoundInformation(out var currentRound)) - { - Context.LogDebug(() => - $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); - } - - var latestSignature = GetLatestSignature(currentRound); - var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)]; - var randomHash = previousRandomHash == null - ? latestSignature - : HashHelper.XorAndCompute(previousRandomHash, latestSignature); - - State.RandomHashes[Context.CurrentHeight] = randomHash; - - Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); - - if (!State.IsMainChain.Value && currentRound.RoundNumber > 1) - { - Release(); - } - - // Clear cache. - _processingBlockMinerPubkey = null; + // The only difference. + switch (input) + { + case Round round when callerMethodName == nameof(NextRound): + ProcessNextRound(round); + break; + case Round round when callerMethodName == nameof(NextTerm): + ProcessNextTerm(round); + break; + case UpdateValueInput updateValueInput: + ProcessUpdateValue(updateValueInput); + break; + case TinyBlockInput tinyBlockInput: + ProcessTinyBlock(tinyBlockInput); + break; } - /// - /// Get latest updated signature. - /// A signature is for generating a random hash. - /// - /// - /// - private Hash GetLatestSignature(Round currentRound) + var miningInformationUpdated = new MiningInformationUpdated { - var latestSignature = currentRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .LastOrDefault(m => m.Signature != null)?.Signature; - if (latestSignature != null) return latestSignature; - if (TryToGetPreviousRoundInformation(out var previousRound)) - { - latestSignature = previousRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .LastOrDefault(m => m.Signature != null) - ?.Signature; - } + // _processingBlockMinerPubkey is set during PreCheck. + Pubkey = _processingBlockMinerPubkey, + Behaviour = callerMethodName, + MiningTime = Context.CurrentBlockTime, + BlockHeight = Context.CurrentHeight, + PreviousBlockHash = Context.PreviousBlockHash + }; + Context.Fire(miningInformationUpdated); + Context.LogDebug(() => $"Synced mining information: {miningInformationUpdated}"); + + // Make sure the method GetMaximumBlocksCount executed no matter what consensus behaviour is. + var minersCountInTheory = GetMaximumBlocksCount(); + ResetLatestProviderToTinyBlocksCount(minersCountInTheory); + + if (TryToGetCurrentRoundInformation(out var currentRound)) + Context.LogDebug(() => + $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); + + var latestSignature = GetLatestSignature(currentRound); + var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)]; + var randomHash = previousRandomHash == null + ? latestSignature + : HashHelper.XorAndCompute(previousRandomHash, latestSignature); + + State.RandomHashes[Context.CurrentHeight] = randomHash; + + Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); + + if (!State.IsMainChain.Value && currentRound.RoundNumber > 1) Release(); + + // Clear cache. + _processingBlockMinerPubkey = null; + } - return latestSignature; - } + /// + /// Get latest updated signature. + /// A signature is for generating a random hash. + /// + /// + /// + private Hash GetLatestSignature(Round currentRound) + { + var latestSignature = currentRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .LastOrDefault(m => m.Signature != null)?.Signature; + if (latestSignature != null) return latestSignature; + if (TryToGetPreviousRoundInformation(out var previousRound)) + latestSignature = previousRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .LastOrDefault(m => m.Signature != null) + ?.Signature; + + return latestSignature; + } - private void ProcessNextRound(Round nextRound) - { - RecordMinedMinerListOfCurrentRound(); + private void ProcessNextRound(Round nextRound) + { + RecordMinedMinerListOfCurrentRound(); - TryToGetCurrentRoundInformation(out var currentRound); + TryToGetCurrentRoundInformation(out var currentRound); - // Do some other stuff during the first time to change round. - if (currentRound.RoundNumber == 1) + // Do some other stuff during the first time to change round. + if (currentRound.RoundNumber == 1) + { + // Set blockchain start timestamp. + var actualBlockchainStartTimestamp = + currentRound.FirstActualMiner()?.ActualMiningTimes.FirstOrDefault() ?? + Context.CurrentBlockTime; + SetBlockchainStartTimestamp(actualBlockchainStartTimestamp); + + // Initialize current miners' information in Election Contract. + if (State.IsMainChain.Value) { - // Set blockchain start timestamp. - var actualBlockchainStartTimestamp = - currentRound.FirstActualMiner()?.ActualMiningTimes.FirstOrDefault() ?? - Context.CurrentBlockTime; - SetBlockchainStartTimestamp(actualBlockchainStartTimestamp); - - // Initialize current miners' information in Election Contract. - if (State.IsMainChain.Value) - { - var minersCount = GetMinersCount(nextRound); - if (minersCount != 0 && State.ElectionContract.Value != null) + var minersCount = GetMinersCount(nextRound); + if (minersCount != 0 && State.ElectionContract.Value != null) + State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput { - State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput - { - MinersCount = minersCount - }); - } - } + MinersCount = minersCount + }); } + } - if (State.IsMainChain.Value && // Only detect evil miners in Main Chain. - currentRound.TryToDetectEvilMiners(out var evilMiners)) + if (State.IsMainChain.Value && // Only detect evil miners in Main Chain. + currentRound.TryToDetectEvilMiners(out var evilMiners)) + { + Context.LogDebug(() => "Evil miners detected."); + foreach (var evilMiner in evilMiners) { - Context.LogDebug(() => "Evil miners detected."); - foreach (var evilMiner in evilMiners) + Context.LogDebug(() => + $"Evil miner {evilMiner}, missed time slots: {currentRound.RealTimeMinersInformation[evilMiner].MissedTimeSlots}."); + // Mark these evil miners. + State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput { - Context.LogDebug(() => - $"Evil miner {evilMiner}, missed time slots: {currentRound.RealTimeMinersInformation[evilMiner].MissedTimeSlots}."); - // Mark these evil miners. - State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput - { - Pubkey = evilMiner, - IsEvilNode = true - }); - } + Pubkey = evilMiner, + IsEvilNode = true + }); } - - AddRoundInformation(nextRound); - - Assert(TryToUpdateRoundNumber(nextRound.RoundNumber), "Failed to update round number."); } - private void ProcessNextTerm(Round nextRound) - { - RecordMinedMinerListOfCurrentRound(); + AddRoundInformation(nextRound); - // Count missed time slot of current round. - CountMissedTimeSlots(); + Assert(TryToUpdateRoundNumber(nextRound.RoundNumber), "Failed to update round number."); + } - Assert(TryToGetTermNumber(out var termNumber), "Term number not found."); + private void ProcessNextTerm(Round nextRound) + { + RecordMinedMinerListOfCurrentRound(); - // Update current term number and current round number. - Assert(TryToUpdateTermNumber(nextRound.TermNumber), "Failed to update term number."); - Assert(TryToUpdateRoundNumber(nextRound.RoundNumber), "Failed to update round number."); + // Count missed time slot of current round. + CountMissedTimeSlots(); - UpdateMinersCountToElectionContract(nextRound); + Assert(TryToGetTermNumber(out var termNumber), "Term number not found."); - // Reset some fields of first two rounds of next term. - foreach (var minerInRound in nextRound.RealTimeMinersInformation.Values) - { - minerInRound.MissedTimeSlots = 0; - minerInRound.ProducedBlocks = 0; - } + // Update current term number and current round number. + Assert(TryToUpdateTermNumber(nextRound.TermNumber), "Failed to update term number."); + Assert(TryToUpdateRoundNumber(nextRound.RoundNumber), "Failed to update round number."); - UpdateProducedBlocksNumberOfSender(nextRound); + UpdateMinersCountToElectionContract(nextRound); - // Update miners list. - var miners = new MinerList(); - miners.Pubkeys.AddRange(nextRound.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString)); - if (!SetMinerList(miners, nextRound.TermNumber)) - { - Assert(false, "Failed to update miner list."); - } + // Reset some fields of first two rounds of next term. + foreach (var minerInRound in nextRound.RealTimeMinersInformation.Values) + { + minerInRound.MissedTimeSlots = 0; + minerInRound.ProducedBlocks = 0; + } - // Update term number lookup. (Using term number to get first round number of related term.) - State.FirstRoundNumberOfEachTerm[nextRound.TermNumber] = nextRound.RoundNumber; + UpdateProducedBlocksNumberOfSender(nextRound); - // Update rounds information of next two rounds. - AddRoundInformation(nextRound); + // Update miners list. + var miners = new MinerList(); + miners.Pubkeys.AddRange(nextRound.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString)); + if (!SetMinerList(miners, nextRound.TermNumber)) Assert(false, "Failed to update miner list."); - if (!TryToGetPreviousRoundInformation(out var previousRound)) - { - Assert(false, "Failed to get previous round information."); - } + // Update term number lookup. (Using term number to get first round number of related term.) + State.FirstRoundNumberOfEachTerm[nextRound.TermNumber] = nextRound.RoundNumber; - UpdateCurrentMinerInformationToElectionContract(previousRound); + // Update rounds information of next two rounds. + AddRoundInformation(nextRound); - if (DonateMiningReward(previousRound)) - { - State.TreasuryContract.Release.Send(new ReleaseInput - { - PeriodNumber = termNumber - }); + if (!TryToGetPreviousRoundInformation(out var previousRound)) + Assert(false, "Failed to get previous round information."); - Context.LogDebug(() => $"Released treasury profit for term {termNumber}"); - } + UpdateCurrentMinerInformationToElectionContract(previousRound); - State.ElectionContract.TakeSnapshot.Send(new TakeElectionSnapshotInput + if (DonateMiningReward(previousRound)) + { + State.TreasuryContract.Release.Send(new ReleaseInput { - MinedBlocks = previousRound.GetMinedBlocks(), - TermNumber = termNumber, - RoundNumber = previousRound.RoundNumber + PeriodNumber = termNumber }); - Context.LogDebug(() => $"Changing term number to {nextRound.TermNumber}"); + Context.LogDebug(() => $"Released treasury profit for term {termNumber}"); } - private void RecordMinedMinerListOfCurrentRound() + State.ElectionContract.TakeSnapshot.Send(new TakeElectionSnapshotInput { - TryToGetCurrentRoundInformation(out var currentRound); + MinedBlocks = previousRound.GetMinedBlocks(), + TermNumber = termNumber, + RoundNumber = previousRound.RoundNumber + }); - State.MinedMinerListMap.Set(currentRound.RoundNumber, new MinerList - { - Pubkeys = {currentRound.GetMinedMiners().Select(m => ByteStringHelper.FromHexString(m.Pubkey))} - }); + Context.LogDebug(() => $"Changing term number to {nextRound.TermNumber}"); + } - // Remove information out of date. - var removeTargetRoundNumber = currentRound.RoundNumber.Sub(3); - if (removeTargetRoundNumber > 0 && State.MinedMinerListMap[removeTargetRoundNumber] != null) - { - State.MinedMinerListMap.Remove(removeTargetRoundNumber); - } - } + private void RecordMinedMinerListOfCurrentRound() + { + TryToGetCurrentRoundInformation(out var currentRound); - private void ProcessUpdateValue(UpdateValueInput updateValueInput) + State.MinedMinerListMap.Set(currentRound.RoundNumber, new MinerList { - TryToGetCurrentRoundInformation(out var currentRound); + Pubkeys = { currentRound.GetMinedMiners().Select(m => ByteStringHelper.FromHexString(m.Pubkey)) } + }); - var minerInRound = currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey]; - minerInRound.ActualMiningTimes.Add(updateValueInput.ActualMiningTime); - minerInRound.Signature = updateValueInput.Signature; - minerInRound.OutValue = updateValueInput.OutValue; - minerInRound.SupposedOrderOfNextRound = updateValueInput.SupposedOrderOfNextRound; - minerInRound.FinalOrderOfNextRound = updateValueInput.SupposedOrderOfNextRound; - minerInRound.ImpliedIrreversibleBlockHeight = updateValueInput.ImpliedIrreversibleBlockHeight; + // Remove information out of date. + var removeTargetRoundNumber = currentRound.RoundNumber.Sub(3); + if (removeTargetRoundNumber > 0 && State.MinedMinerListMap[removeTargetRoundNumber] != null) + State.MinedMinerListMap.Remove(removeTargetRoundNumber); + } - // Just add 1 based on previous data, do not use provided values. - minerInRound.ProducedBlocks = minerInRound.ProducedBlocks.Add(1); - minerInRound.ProducedTinyBlocks = minerInRound.ProducedTinyBlocks.Add(1); + private void ProcessUpdateValue(UpdateValueInput updateValueInput) + { + TryToGetCurrentRoundInformation(out var currentRound); - PerformSecretSharing(updateValueInput, minerInRound, currentRound, _processingBlockMinerPubkey); + var minerInRound = currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey]; + minerInRound.ActualMiningTimes.Add(updateValueInput.ActualMiningTime); + minerInRound.Signature = updateValueInput.Signature; + minerInRound.OutValue = updateValueInput.OutValue; + minerInRound.SupposedOrderOfNextRound = updateValueInput.SupposedOrderOfNextRound; + minerInRound.FinalOrderOfNextRound = updateValueInput.SupposedOrderOfNextRound; + minerInRound.ImpliedIrreversibleBlockHeight = updateValueInput.ImpliedIrreversibleBlockHeight; - foreach (var tuneOrder in updateValueInput.TuneOrderInformation) - { - currentRound.RealTimeMinersInformation[tuneOrder.Key].FinalOrderOfNextRound = tuneOrder.Value; - } + // Just add 1 based on previous data, do not use provided values. + minerInRound.ProducedBlocks = minerInRound.ProducedBlocks.Add(1); + minerInRound.ProducedTinyBlocks = minerInRound.ProducedTinyBlocks.Add(1); - // It is permissible for miners not publish their in values. - if (updateValueInput.PreviousInValue != Hash.Empty) - { - minerInRound.PreviousInValue = updateValueInput.PreviousInValue; - } + PerformSecretSharing(updateValueInput, minerInRound, currentRound, _processingBlockMinerPubkey); - if (TryToGetPreviousRoundInformation(out var previousRound)) - { - new LastIrreversibleBlockHeightCalculator(currentRound, previousRound).Deconstruct( - out var libHeight); - Context.LogDebug(() => $"Finished calculation of lib height: {libHeight}"); - // LIB height can't be available if it is lower than last time. - if (currentRound.ConfirmedIrreversibleBlockHeight < libHeight) - { - Context.LogDebug(() => $"New lib height: {libHeight}"); - Context.Fire(new IrreversibleBlockFound - { - IrreversibleBlockHeight = libHeight - }); - currentRound.ConfirmedIrreversibleBlockHeight = libHeight; - currentRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.RoundNumber.Sub(1); - } - } + foreach (var tuneOrder in updateValueInput.TuneOrderInformation) + currentRound.RealTimeMinersInformation[tuneOrder.Key].FinalOrderOfNextRound = tuneOrder.Value; - if (!TryToUpdateRoundInformation(currentRound)) - { - Assert(false, "Failed to update round information."); - } - } + // It is permissible for miners not publish their in values. + if (updateValueInput.PreviousInValue != Hash.Empty) + minerInRound.PreviousInValue = updateValueInput.PreviousInValue; - private static void PerformSecretSharing(UpdateValueInput input, MinerInRound minerInRound, Round round, - string publicKey) + if (TryToGetPreviousRoundInformation(out var previousRound)) { - minerInRound.EncryptedPieces.Add(input.EncryptedPieces); - foreach (var decryptedPreviousInValue in input.DecryptedPieces) - { - round.RealTimeMinersInformation[decryptedPreviousInValue.Key].DecryptedPieces - .Add(publicKey, decryptedPreviousInValue.Value); - } - - foreach (var previousInValue in input.MinersPreviousInValues) + new LastIrreversibleBlockHeightCalculator(currentRound, previousRound).Deconstruct( + out var libHeight); + Context.LogDebug(() => $"Finished calculation of lib height: {libHeight}"); + // LIB height can't be available if it is lower than last time. + if (currentRound.ConfirmedIrreversibleBlockHeight < libHeight) { - round.RealTimeMinersInformation[previousInValue.Key].PreviousInValue = previousInValue.Value; + Context.LogDebug(() => $"New lib height: {libHeight}"); + Context.Fire(new IrreversibleBlockFound + { + IrreversibleBlockHeight = libHeight + }); + currentRound.ConfirmedIrreversibleBlockHeight = libHeight; + currentRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.RoundNumber.Sub(1); } } - private void ProcessTinyBlock(TinyBlockInput tinyBlockInput) - { - TryToGetCurrentRoundInformation(out var currentRound); + if (!TryToUpdateRoundInformation(currentRound)) Assert(false, "Failed to update round information."); + } - var minerInRound = currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey]; - minerInRound.ActualMiningTimes.Add(tinyBlockInput.ActualMiningTime); - minerInRound.ProducedBlocks = minerInRound.ProducedBlocks.Add(1); - minerInRound.ProducedTinyBlocks = minerInRound.ProducedTinyBlocks.Add(1); + private static void PerformSecretSharing(UpdateValueInput input, MinerInRound minerInRound, Round round, + string publicKey) + { + minerInRound.EncryptedPieces.Add(input.EncryptedPieces); + foreach (var decryptedPreviousInValue in input.DecryptedPieces) + round.RealTimeMinersInformation[decryptedPreviousInValue.Key].DecryptedPieces + .Add(publicKey, decryptedPreviousInValue.Value); - Assert(TryToUpdateRoundInformation(currentRound), "Failed to update round information."); - } + foreach (var previousInValue in input.MinersPreviousInValues) + round.RealTimeMinersInformation[previousInValue.Key].PreviousInValue = previousInValue.Value; + } - /// - /// The transaction can still executed successfully if the pre-check failed, - /// though doing nothing about updating state. - /// - /// - private bool PreCheck() - { - TryToGetCurrentRoundInformation(out var currentRound); - TryToGetPreviousRoundInformation(out var previousRound); + private void ProcessTinyBlock(TinyBlockInput tinyBlockInput) + { + TryToGetCurrentRoundInformation(out var currentRound); - _processingBlockMinerPubkey = Context.RecoverPublicKey().ToHex(); + var minerInRound = currentRound.RealTimeMinersInformation[_processingBlockMinerPubkey]; + minerInRound.ActualMiningTimes.Add(tinyBlockInput.ActualMiningTime); + minerInRound.ProducedBlocks = minerInRound.ProducedBlocks.Add(1); + minerInRound.ProducedTinyBlocks = minerInRound.ProducedTinyBlocks.Add(1); - // Though we've already prevented related transactions from inserting to the transaction pool - // via ConstrainedAEDPoSTransactionValidationProvider, - // this kind of permission check is still useful. - if (!currentRound.IsInMinerList(_processingBlockMinerPubkey) && - !previousRound.IsInMinerList(_processingBlockMinerPubkey)) // Case a failed miner performing NextTerm - { - return false; - } + Assert(TryToUpdateRoundInformation(currentRound), "Failed to update round information."); + } - return true; - } + /// + /// The transaction can still executed successfully if the pre-check failed, + /// though doing nothing about updating state. + /// + /// + private bool PreCheck() + { + TryToGetCurrentRoundInformation(out var currentRound); + TryToGetPreviousRoundInformation(out var previousRound); + + _processingBlockMinerPubkey = Context.RecoverPublicKey().ToHex(); + + // Though we've already prevented related transactions from inserting to the transaction pool + // via ConstrainedAEDPoSTransactionValidationProvider, + // this kind of permission check is still useful. + if (!currentRound.IsInMinerList(_processingBlockMinerPubkey) && + !previousRound.IsInMinerList(_processingBlockMinerPubkey)) // Case a failed miner performing NextTerm + return false; + + return true; + } - /// - /// To prevent one miner produced too many continuous blocks. - /// - /// - private void ResetLatestProviderToTinyBlocksCount(int minersCountInTheory) + /// + /// To prevent one miner produced too many continuous blocks. + /// + /// + private void ResetLatestProviderToTinyBlocksCount(int minersCountInTheory) + { + LatestPubkeyToTinyBlocksCount currentValue; + if (State.LatestPubkeyToTinyBlocksCount.Value == null) { - LatestPubkeyToTinyBlocksCount currentValue; - if (State.LatestPubkeyToTinyBlocksCount.Value == null) + currentValue = new LatestPubkeyToTinyBlocksCount { - currentValue = new LatestPubkeyToTinyBlocksCount + Pubkey = _processingBlockMinerPubkey, + BlocksCount = AEDPoSContractConstants.MaximumTinyBlocksCount.Sub(1) + }; + State.LatestPubkeyToTinyBlocksCount.Value = currentValue; + } + else + { + currentValue = State.LatestPubkeyToTinyBlocksCount.Value; + if (currentValue.Pubkey == _processingBlockMinerPubkey) + State.LatestPubkeyToTinyBlocksCount.Value = new LatestPubkeyToTinyBlocksCount { Pubkey = _processingBlockMinerPubkey, - BlocksCount = AEDPoSContractConstants.MaximumTinyBlocksCount.Sub(1) + BlocksCount = currentValue.BlocksCount.Sub(1) }; - State.LatestPubkeyToTinyBlocksCount.Value = currentValue; - } else - { - currentValue = State.LatestPubkeyToTinyBlocksCount.Value; - if (currentValue.Pubkey == _processingBlockMinerPubkey) - { - State.LatestPubkeyToTinyBlocksCount.Value = new LatestPubkeyToTinyBlocksCount - { - Pubkey = _processingBlockMinerPubkey, - BlocksCount = currentValue.BlocksCount.Sub(1) - }; - } - else + State.LatestPubkeyToTinyBlocksCount.Value = new LatestPubkeyToTinyBlocksCount { - State.LatestPubkeyToTinyBlocksCount.Value = new LatestPubkeyToTinyBlocksCount - { - Pubkey = _processingBlockMinerPubkey, - BlocksCount = minersCountInTheory.Sub(1) - }; - } - } + Pubkey = _processingBlockMinerPubkey, + BlocksCount = minersCountInTheory.Sub(1) + }; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SecretSharing.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SecretSharing.cs index 81cce0fba7..57f132e0de 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SecretSharing.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SecretSharing.cs @@ -1,54 +1,52 @@ using System.Linq; using AElf.Cryptography.SecretSharing; using AElf.CSharp.Core; -using AElf.Types; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private void RevealSharedInValues(Round currentRound, string publicKey) { - private void RevealSharedInValues(Round currentRound, string publicKey) - { - Context.LogDebug(() => "About to reveal shared in values."); + Context.LogDebug(() => "About to reveal shared in values."); - if (!currentRound.RealTimeMinersInformation.ContainsKey(publicKey)) return; + if (!currentRound.RealTimeMinersInformation.ContainsKey(publicKey)) return; - if (!TryToGetPreviousRoundInformation(out var previousRound)) return; + if (!TryToGetPreviousRoundInformation(out var previousRound)) return; - var minersCount = currentRound.RealTimeMinersInformation.Count; - var minimumCount = minersCount.Mul(2).Div(3); - minimumCount = minimumCount == 0 ? 1 : minimumCount; + var minersCount = currentRound.RealTimeMinersInformation.Count; + var minimumCount = minersCount.Mul(2).Div(3); + minimumCount = minimumCount == 0 ? 1 : minimumCount; - foreach (var pair in previousRound.RealTimeMinersInformation.OrderBy(m => m.Value.Order)) - { - // Skip himself. - if (pair.Key == publicKey) continue; + foreach (var pair in previousRound.RealTimeMinersInformation.OrderBy(m => m.Value.Order)) + { + // Skip himself. + if (pair.Key == publicKey) continue; - if (!currentRound.RealTimeMinersInformation.Keys.Contains(pair.Key)) continue; + if (!currentRound.RealTimeMinersInformation.Keys.Contains(pair.Key)) continue; - var publicKeyOfAnotherMiner = pair.Key; - var anotherMinerInPreviousRound = pair.Value; + var publicKeyOfAnotherMiner = pair.Key; + var anotherMinerInPreviousRound = pair.Value; - if (anotherMinerInPreviousRound.EncryptedPieces.Count < minimumCount) continue; - if (anotherMinerInPreviousRound.DecryptedPieces.Count < minersCount) continue; + if (anotherMinerInPreviousRound.EncryptedPieces.Count < minimumCount) continue; + if (anotherMinerInPreviousRound.DecryptedPieces.Count < minersCount) continue; - // Reveal another miner's in value for target round: + // Reveal another miner's in value for target round: - var orders = anotherMinerInPreviousRound.DecryptedPieces.Select((t, i) => - previousRound.RealTimeMinersInformation.Values - .First(m => m.Pubkey == - anotherMinerInPreviousRound.DecryptedPieces.Keys.ToList()[i]).Order) - .ToList(); + var orders = anotherMinerInPreviousRound.DecryptedPieces.Select((t, i) => + previousRound.RealTimeMinersInformation.Values + .First(m => m.Pubkey == + anotherMinerInPreviousRound.DecryptedPieces.Keys.ToList()[i]).Order) + .ToList(); - var sharedParts = anotherMinerInPreviousRound.DecryptedPieces.Values.ToList() - .Select(s => s.ToByteArray()).ToList(); + var sharedParts = anotherMinerInPreviousRound.DecryptedPieces.Values.ToList() + .Select(s => s.ToByteArray()).ToList(); - var revealedInValue = - HashHelper.ComputeFrom(SecretSharingHelper.DecodeSecret(sharedParts, orders, minimumCount)); + var revealedInValue = + HashHelper.ComputeFrom(SecretSharingHelper.DecodeSecret(sharedParts, orders, minimumCount)); - currentRound.RealTimeMinersInformation[publicKeyOfAnotherMiner].PreviousInValue = revealedInValue; - } + currentRound.RealTimeMinersInformation[publicKeyOfAnotherMiner].PreviousInValue = revealedInValue; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SideChainDividendsPool.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SideChainDividendsPool.cs index 531e680dc0..4bfa29371b 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SideChainDividendsPool.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_SideChainDividendsPool.cs @@ -1,183 +1,176 @@ using System.Linq; -using AElf.Standards.ACS10; using AElf.Contracts.MultiToken; using AElf.Contracts.Profit; using AElf.Contracts.TokenHolder; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS10; using Google.Protobuf.WellKnownTypes; using ContributeProfitsInput = AElf.Contracts.TokenHolder.ContributeProfitsInput; using DistributeProfitsInput = AElf.Contracts.TokenHolder.DistributeProfitsInput; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSContract { - public partial class AEDPoSContract + private void InitialProfitSchemeForSideChain(long periodSeconds) { - private void InitialProfitSchemeForSideChain(long periodSeconds) + var tokenHolderContractAddress = + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); + // No need to continue if Token Holder Contract didn't deployed. + if (tokenHolderContractAddress == null) { - var tokenHolderContractAddress = - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); - // No need to continue if Token Holder Contract didn't deployed. - if (tokenHolderContractAddress == null) - { - Context.LogDebug(() => "Token Holder Contract not found, so won't initial side chain dividends pool."); - return; - } - - State.TokenHolderContract.Value = tokenHolderContractAddress; - State.TokenHolderContract.CreateScheme.Send(new CreateTokenHolderProfitSchemeInput - { - Symbol = AEDPoSContractConstants.SideChainShareProfitsTokenSymbol, - MinimumLockMinutes = periodSeconds.Div(60) - }); - - Context.LogDebug(() => "Side chain dividends pool created."); + Context.LogDebug(() => "Token Holder Contract not found, so won't initial side chain dividends pool."); + return; } - public override Empty Donate(DonateInput input) + State.TokenHolderContract.Value = tokenHolderContractAddress; + State.TokenHolderContract.CreateScheme.Send(new CreateTokenHolderProfitSchemeInput { - EnsureTokenContractAddressSet(); + Symbol = AEDPoSContractConstants.SideChainShareProfitsTokenSymbol, + MinimumLockMinutes = periodSeconds.Div(60) + }); - if (!State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = input.Symbol}).Value) - { - return new Empty(); - } + Context.LogDebug(() => "Side chain dividends pool created."); + } - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount, - To = Context.Self - }); + public override Empty Donate(DonateInput input) + { + EnsureTokenContractAddressSet(); - State.TokenContract.Approve.Send(new ApproveInput - { - Symbol = input.Symbol, - Amount = input.Amount, - Spender = State.TokenHolderContract.Value - }); + if (!State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = input.Symbol }).Value) + return new Empty(); - State.TokenHolderContract.ContributeProfits.Send(new ContributeProfitsInput - { - SchemeManager = Context.Self, - Symbol = input.Symbol, - Amount = input.Amount - }); + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount, + To = Context.Self + }); - Context.Fire(new DonationReceived - { - From = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount, - PoolContract = Context.Self - }); + State.TokenContract.Approve.Send(new ApproveInput + { + Symbol = input.Symbol, + Amount = input.Amount, + Spender = State.TokenHolderContract.Value + }); - var currentReceivedDividends = State.SideChainReceivedDividends[Context.CurrentHeight]; - if (currentReceivedDividends != null && currentReceivedDividends.Value.ContainsKey(input.Symbol)) - { - currentReceivedDividends.Value[input.Symbol] = - currentReceivedDividends.Value[input.Symbol].Add(input.Amount); - } - else + State.TokenHolderContract.ContributeProfits.Send(new ContributeProfitsInput + { + SchemeManager = Context.Self, + Symbol = input.Symbol, + Amount = input.Amount + }); + + Context.Fire(new DonationReceived + { + From = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount, + PoolContract = Context.Self + }); + + var currentReceivedDividends = State.SideChainReceivedDividends[Context.CurrentHeight]; + if (currentReceivedDividends != null && currentReceivedDividends.Value.ContainsKey(input.Symbol)) + currentReceivedDividends.Value[input.Symbol] = + currentReceivedDividends.Value[input.Symbol].Add(input.Amount); + else + currentReceivedDividends = new Dividends { - currentReceivedDividends = new Dividends + Value = { - Value = { - { - input.Symbol, input.Amount - } + input.Symbol, input.Amount } - }; - } + } + }; - State.SideChainReceivedDividends[Context.CurrentHeight] = currentReceivedDividends; + State.SideChainReceivedDividends[Context.CurrentHeight] = currentReceivedDividends; - Context.LogDebug(() => $"Contributed {input.Amount} {input.Symbol}s to side chain dividends pool."); + Context.LogDebug(() => $"Contributed {input.Amount} {input.Symbol}s to side chain dividends pool."); - return new Empty(); - } + return new Empty(); + } - public override Empty Release(ReleaseInput input) - { - Assert(false, "Side chain dividend pool can only release automatically."); - return new Empty(); - } + public override Empty Release(ReleaseInput input) + { + Assert(false, "Side chain dividend pool can only release automatically."); + return new Empty(); + } - public void Release() + public void Release() + { + if (State.TokenHolderContract.Value == null) return; + var scheme = State.TokenHolderContract.GetScheme.Call(Context.Self); + var isTimeToRelease = + (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds + .Div(State.PeriodSeconds.Value) > scheme.Period - 1; + Context.LogDebug(() => "ReleaseSideChainDividendsPool Information:\n" + + $"CurrentBlockTime: {Context.CurrentBlockTime}\n" + + $"BlockChainStartTime: {State.BlockchainStartTimestamp.Value}\n" + + $"PeriodSeconds: {State.PeriodSeconds.Value}\n" + + $"Scheme Period: {scheme.Period}"); + if (isTimeToRelease) { - if (State.TokenHolderContract.Value == null) return; - var scheme = State.TokenHolderContract.GetScheme.Call(Context.Self); - var isTimeToRelease = - (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds - .Div(State.PeriodSeconds.Value) > scheme.Period - 1; - Context.LogDebug(() => "ReleaseSideChainDividendsPool Information:\n" + - $"CurrentBlockTime: {Context.CurrentBlockTime}\n" + - $"BlockChainStartTime: {State.BlockchainStartTimestamp.Value}\n" + - $"PeriodSeconds: {State.PeriodSeconds.Value}\n" + - $"Scheme Period: {scheme.Period}"); - if (isTimeToRelease) + Context.LogDebug(() => "Ready to release side chain dividends pool."); + State.TokenHolderContract.DistributeProfits.Send(new DistributeProfitsInput { - Context.LogDebug(() => "Ready to release side chain dividends pool."); - State.TokenHolderContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeManager = Context.Self - }); - } + SchemeManager = Context.Self + }); } + } - public override Empty SetSymbolList(SymbolList input) - { - Assert(false, "Side chain dividend pool not support setting symbol list."); - return new Empty(); - } + public override Empty SetSymbolList(SymbolList input) + { + Assert(false, "Side chain dividend pool not support setting symbol list."); + return new Empty(); + } - public override Dividends GetDividends(Int64Value input) - { - Assert(Context.CurrentHeight > input.Value, "Cannot query dividends of a future block."); - return State.SideChainReceivedDividends[input.Value]; - } + public override Dividends GetDividends(Int64Value input) + { + Assert(Context.CurrentHeight > input.Value, "Cannot query dividends of a future block."); + return State.SideChainReceivedDividends[input.Value]; + } - public override SymbolList GetSymbolList(Empty input) + public override SymbolList GetSymbolList(Empty input) + { + return new SymbolList { - return new SymbolList + Value = { - Value = - { - GetSideChainDividendPoolScheme().ReceivedTokenSymbols - } - }; - } + GetSideChainDividendPoolScheme().ReceivedTokenSymbols + } + }; + } - public override Dividends GetUndistributedDividends(Empty input) + public override Dividends GetUndistributedDividends(Empty input) + { + var scheme = GetSideChainDividendPoolScheme(); + return new Dividends { - var scheme = GetSideChainDividendPoolScheme(); - return new Dividends + Value = { - Value = + scheme.ReceivedTokenSymbols.Select(s => State.TokenContract.GetBalance.Call(new GetBalanceInput { - scheme.ReceivedTokenSymbols.Select(s => State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = scheme.VirtualAddress, - Symbol = s - })).ToDictionary(b => b.Symbol, b => b.Balance) - } - }; - } - - private Scheme GetSideChainDividendPoolScheme() - { - if (State.SideChainDividendPoolSchemeId.Value == null) - { - var tokenHolderScheme = State.TokenHolderContract.GetScheme.Call(Context.Self); - State.SideChainDividendPoolSchemeId.Value = tokenHolderScheme.SchemeId; + Owner = scheme.VirtualAddress, + Symbol = s + })).ToDictionary(b => b.Symbol, b => b.Balance) } + }; + } - return Context.Call( - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName), - nameof(ProfitContractContainer.ProfitContractReferenceState.GetScheme), - State.SideChainDividendPoolSchemeId.Value); + private Scheme GetSideChainDividendPoolScheme() + { + if (State.SideChainDividendPoolSchemeId.Value == null) + { + var tokenHolderScheme = State.TokenHolderContract.GetScheme.Call(Context.Self); + State.SideChainDividendPoolSchemeId.Value = tokenHolderScheme.SchemeId; } + + return Context.Call( + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName), + nameof(ProfitContractContainer.ProfitContractReferenceState.GetScheme), + State.SideChainDividendPoolSchemeId.Value); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_Validation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_Validation.cs index 878afa461a..8ca95cfb6b 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_Validation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_Validation.cs @@ -1,121 +1,105 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS4; using AElf.CSharp.Core; +using AElf.Standards.ACS4; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// This method will be executed before executing a block. + /// + /// + /// + private ValidationResult ValidateBeforeExecution(AElfConsensusHeaderInformation extraData) { - /// - /// This method will be executed before executing a block. - /// - /// - /// - private ValidationResult ValidateBeforeExecution(AElfConsensusHeaderInformation extraData) - { - // According to current round information: - if (!TryToGetCurrentRoundInformation(out var baseRound)) - { - return new ValidationResult {Success = false, Message = "Failed to get current round information."}; - } + // According to current round information: + if (!TryToGetCurrentRoundInformation(out var baseRound)) + return new ValidationResult { Success = false, Message = "Failed to get current round information." }; - // Skip the certain initial miner during first several rounds. (When other nodes haven't produce blocks yet.) - if (baseRound.RealTimeMinersInformation.Count != 1 && - Context.CurrentHeight < AEDPoSContractConstants.MaximumTinyBlocksCount.Mul(3)) + // Skip the certain initial miner during first several rounds. (When other nodes haven't produce blocks yet.) + if (baseRound.RealTimeMinersInformation.Count != 1 && + Context.CurrentHeight < AEDPoSContractConstants.MaximumTinyBlocksCount.Mul(3)) + { + string producedMiner = null; + var result = true; + for (var i = baseRound.RoundNumber; i > 0; i--) { - string producedMiner = null; - var result = true; - for (var i = baseRound.RoundNumber; i > 0; i--) + var producedMiners = State.Rounds[i].RealTimeMinersInformation.Values + .Where(m => m.ActualMiningTimes.Any()).ToList(); + if (producedMiners.Count != 1) { - var producedMiners = State.Rounds[i].RealTimeMinersInformation.Values - .Where(m => m.ActualMiningTimes.Any()).ToList(); - if (producedMiners.Count != 1) - { - result = false; - break; - } - if (producedMiner == null) - { - producedMiner = producedMiners.Single().Pubkey; - } - else if (producedMiner != producedMiners.Single().Pubkey) - { - result = false; - } + result = false; + break; } - if (result) - { - return new ValidationResult {Success = true}; - } + if (producedMiner == null) + producedMiner = producedMiners.Single().Pubkey; + else if (producedMiner != producedMiners.Single().Pubkey) result = false; } - if (extraData.Behaviour == AElfConsensusBehaviour.UpdateValue) - { - baseRound.RecoverFromUpdateValue(extraData.Round, extraData.SenderPubkey.ToHex()); - } + if (result) return new ValidationResult { Success = true }; + } - if (extraData.Behaviour == AElfConsensusBehaviour.TinyBlock) - { - baseRound.RecoverFromTinyBlock(extraData.Round, extraData.SenderPubkey.ToHex()); - } + if (extraData.Behaviour == AElfConsensusBehaviour.UpdateValue) + baseRound.RecoverFromUpdateValue(extraData.Round, extraData.SenderPubkey.ToHex()); - var validationContext = new ConsensusValidationContext - { - BaseRound = baseRound, - CurrentTermNumber = State.CurrentTermNumber.Value, - CurrentRoundNumber = State.CurrentRoundNumber.Value, - PreviousRound = TryToGetPreviousRoundInformation(out var previousRound) ? previousRound : new Round(), - LatestPubkeyToTinyBlocksCount = State.LatestPubkeyToTinyBlocksCount.Value, - ExtraData = extraData - }; - - /* Ask several questions: */ - - // Add basic providers at first. - var validationProviders = new List - { - // Is sender in miner list (of base round)? - new MiningPermissionValidationProvider(), + if (extraData.Behaviour == AElfConsensusBehaviour.TinyBlock) + baseRound.RecoverFromTinyBlock(extraData.Round, extraData.SenderPubkey.ToHex()); - // Is this block produced in proper time? - new TimeSlotValidationProvider(), + var validationContext = new ConsensusValidationContext + { + BaseRound = baseRound, + CurrentTermNumber = State.CurrentTermNumber.Value, + CurrentRoundNumber = State.CurrentRoundNumber.Value, + PreviousRound = TryToGetPreviousRoundInformation(out var previousRound) ? previousRound : new Round(), + LatestPubkeyToTinyBlocksCount = State.LatestPubkeyToTinyBlocksCount.Value, + ExtraData = extraData + }; + + /* Ask several questions: */ + + // Add basic providers at first. + var validationProviders = new List + { + // Is sender in miner list (of base round)? + new MiningPermissionValidationProvider(), - // Is sender produced too many blocks at one time? - new ContinuousBlocksValidationProvider() - }; + // Is this block produced in proper time? + new TimeSlotValidationProvider(), - switch (extraData.Behaviour) - { - case AElfConsensusBehaviour.UpdateValue: - validationProviders.Add(new UpdateValueValidationProvider()); - // Is confirmed lib height and lib round number went down? (Which should not happens.) - validationProviders.Add(new LibInformationValidationProvider()); - break; - case AElfConsensusBehaviour.NextRound: - // Is sender's order of next round correct? - validationProviders.Add(new NextRoundMiningOrderValidationProvider()); - validationProviders.Add(new RoundTerminateValidationProvider()); - break; - case AElfConsensusBehaviour.NextTerm: - validationProviders.Add(new RoundTerminateValidationProvider()); - break; - } + // Is sender produced too many blocks at one time? + new ContinuousBlocksValidationProvider() + }; - var service = new HeaderInformationValidationService(validationProviders); + switch (extraData.Behaviour) + { + case AElfConsensusBehaviour.UpdateValue: + validationProviders.Add(new UpdateValueValidationProvider()); + // Is confirmed lib height and lib round number went down? (Which should not happens.) + validationProviders.Add(new LibInformationValidationProvider()); + break; + case AElfConsensusBehaviour.NextRound: + // Is sender's order of next round correct? + validationProviders.Add(new NextRoundMiningOrderValidationProvider()); + validationProviders.Add(new RoundTerminateValidationProvider()); + break; + case AElfConsensusBehaviour.NextTerm: + validationProviders.Add(new RoundTerminateValidationProvider()); + break; + } - Context.LogDebug(() => $"Validating behaviour: {extraData.Behaviour.ToString()}"); + var service = new HeaderInformationValidationService(validationProviders); - var validationResult = service.ValidateInformation(validationContext); + Context.LogDebug(() => $"Validating behaviour: {extraData.Behaviour.ToString()}"); - if (validationResult.Success == false) - { - Context.LogDebug(() => $"Consensus Validation before execution failed : {validationResult.Message}"); - } + var validationResult = service.ValidateInformation(validationContext); - return validationResult; - } + if (validationResult.Success == false) + Context.LogDebug(() => $"Consensus Validation before execution failed : {validationResult.Message}"); + + return validationResult; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ValidationService.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ValidationService.cs index 7ecb0360bf..fd4dbaaded 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ValidationService.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ValidationService.cs @@ -1,31 +1,27 @@ using System.Collections.Generic; using AElf.Standards.ACS4; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class HeaderInformationValidationService { - public class HeaderInformationValidationService + private readonly IEnumerable _headerInformationValidationProviders; + + public HeaderInformationValidationService( + IEnumerable headerInformationValidationProviders) { - private readonly IEnumerable _headerInformationValidationProviders; + _headerInformationValidationProviders = headerInformationValidationProviders; + } - public HeaderInformationValidationService( - IEnumerable headerInformationValidationProviders) + public ValidationResult ValidateInformation(ConsensusValidationContext validationContext) + { + foreach (var headerInformationValidationProvider in _headerInformationValidationProviders) { - _headerInformationValidationProviders = headerInformationValidationProviders; + var result = + headerInformationValidationProvider.ValidateHeaderInformation(validationContext); + if (!result.Success) return result; } - public ValidationResult ValidateInformation(ConsensusValidationContext validationContext) - { - foreach (var headerInformationValidationProvider in _headerInformationValidationProviders) - { - var result = - headerInformationValidationProvider.ValidateHeaderInformation(validationContext); - if (!result.Success) - { - return result; - } - } - - return new ValidationResult {Success = true}; - } + return new ValidationResult { Success = true }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ViewMethods.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ViewMethods.cs index ab1fd440ed..02fcd80818 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ViewMethods.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ViewMethods.cs @@ -8,477 +8,467 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public override Int64Value GetCurrentRoundNumber(Empty input) { - public override Int64Value GetCurrentRoundNumber(Empty input) => - new Int64Value {Value = State.CurrentRoundNumber.Value}; + return new() { Value = State.CurrentRoundNumber.Value }; + } - public override Round GetCurrentRoundInformation(Empty input) => - TryToGetCurrentRoundInformation(out var currentRound) ? currentRound : new Round(); + public override Round GetCurrentRoundInformation(Empty input) + { + return TryToGetCurrentRoundInformation(out var currentRound) ? currentRound : new Round(); + } - public override Round GetRoundInformation(Int64Value input) => - TryToGetRoundInformation(input.Value, out var round) ? round : new Round(); + public override Round GetRoundInformation(Int64Value input) + { + return TryToGetRoundInformation(input.Value, out var round) ? round : new Round(); + } - public override MinerList GetCurrentMinerList(Empty input) => - TryToGetCurrentRoundInformation(out var round) - ? new MinerList + public override MinerList GetCurrentMinerList(Empty input) + { + return TryToGetCurrentRoundInformation(out var round) + ? new MinerList + { + Pubkeys = { - Pubkeys = - { - round.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString) - } + round.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString) } - : new MinerList(); + } + : new MinerList(); + } - public override PubkeyList GetCurrentMinerPubkeyList(Empty input) => new PubkeyList + public override PubkeyList GetCurrentMinerPubkeyList(Empty input) + { + return new() { - Pubkeys = {GetCurrentMinerList(input).Pubkeys.Select(p => p.ToHex())} + Pubkeys = { GetCurrentMinerList(input).Pubkeys.Select(p => p.ToHex()) } }; + } - public override MinerListWithRoundNumber GetCurrentMinerListWithRoundNumber(Empty input) => - new MinerListWithRoundNumber - { - MinerList = GetCurrentMinerList(new Empty()), - RoundNumber = State.CurrentRoundNumber.Value - }; + public override MinerListWithRoundNumber GetCurrentMinerListWithRoundNumber(Empty input) + { + return new() + { + MinerList = GetCurrentMinerList(new Empty()), + RoundNumber = State.CurrentRoundNumber.Value + }; + } - public override Round GetPreviousRoundInformation(Empty input) => - TryToGetPreviousRoundInformation(out var previousRound) ? previousRound : new Round(); + public override Round GetPreviousRoundInformation(Empty input) + { + return TryToGetPreviousRoundInformation(out var previousRound) ? previousRound : new Round(); + } - public override MinerList GetMinerList(GetMinerListInput input) => - State.MinerListMap[input.TermNumber] ?? new MinerList(); + public override MinerList GetMinerList(GetMinerListInput input) + { + return State.MinerListMap[input.TermNumber] ?? new MinerList(); + } - public override Int64Value GetMinedBlocksOfPreviousTerm(Empty input) + public override Int64Value GetMinedBlocksOfPreviousTerm(Empty input) + { + if (TryToGetTermNumber(out var termNumber)) { - if (TryToGetTermNumber(out var termNumber)) - { - var targetRound = State.FirstRoundNumberOfEachTerm[termNumber].Sub(1); - if (TryToGetRoundInformation(targetRound, out var round)) - { - return new Int64Value {Value = round.GetMinedBlocks()}; - } - } - - return new Int64Value(); + var targetRound = State.FirstRoundNumberOfEachTerm[termNumber].Sub(1); + if (TryToGetRoundInformation(targetRound, out var round)) + return new Int64Value { Value = round.GetMinedBlocks() }; } - public override MinerList GetPreviousMinerList(Empty input) - { - if (TryToGetTermNumber(out var termNumber) && termNumber > 1) - { - return State.MinerListMap[termNumber.Sub(1)] ?? new MinerList(); - } - - return new MinerList(); - } + return new Int64Value(); + } - public override StringValue GetNextMinerPubkey(Empty input) - { - if (TryToGetCurrentRoundInformation(out var round)) - { - return new StringValue - { - Value = round.RealTimeMinersInformation.Values - .FirstOrDefault(m => m.ExpectedMiningTime > Context.CurrentBlockTime)?.Pubkey ?? - round.RealTimeMinersInformation.Values.First(m => m.IsExtraBlockProducer).Pubkey - }; - } + public override MinerList GetPreviousMinerList(Empty input) + { + if (TryToGetTermNumber(out var termNumber) && termNumber > 1) + return State.MinerListMap[termNumber.Sub(1)] ?? new MinerList(); - return new StringValue(); - } + return new MinerList(); + } - /// - /// Current implementation can be incorrect if all nodes recovering from - /// a strike more than the time of one round, because it's impossible to - /// infer a time slot in this situation. - /// - /// - /// - public override BoolValue IsCurrentMiner(Address input) - { - var pubkey = ConvertAddressToPubkey(input); - return new BoolValue + public override StringValue GetNextMinerPubkey(Empty input) + { + if (TryToGetCurrentRoundInformation(out var round)) + return new StringValue { - Value = IsCurrentMiner(pubkey) + Value = round.RealTimeMinersInformation.Values + .FirstOrDefault(m => m.ExpectedMiningTime > Context.CurrentBlockTime)?.Pubkey ?? + round.RealTimeMinersInformation.Values.First(m => m.IsExtraBlockProducer).Pubkey }; - } - /// - /// The address must in miner list. - /// - /// - /// - private string ConvertAddressToPubkey(Address address) + return new StringValue(); + } + + /// + /// Current implementation can be incorrect if all nodes recovering from + /// a strike more than the time of one round, because it's impossible to + /// infer a time slot in this situation. + /// + /// + /// + public override BoolValue IsCurrentMiner(Address input) + { + var pubkey = ConvertAddressToPubkey(input); + return new BoolValue { - if (!TryToGetCurrentRoundInformation(out var currentRound)) return null; - var possibleKeys = currentRound.RealTimeMinersInformation.Keys.ToList(); - if (TryToGetPreviousRoundInformation(out var previousRound)) - { - possibleKeys.AddRange(previousRound.RealTimeMinersInformation.Keys); - } + Value = IsCurrentMiner(pubkey) + }; + } - return possibleKeys.FirstOrDefault(k => - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(k)) == address); - } + /// + /// The address must in miner list. + /// + /// + /// + private string ConvertAddressToPubkey(Address address) + { + if (!TryToGetCurrentRoundInformation(out var currentRound)) return null; + var possibleKeys = currentRound.RealTimeMinersInformation.Keys.ToList(); + if (TryToGetPreviousRoundInformation(out var previousRound)) + possibleKeys.AddRange(previousRound.RealTimeMinersInformation.Keys); - private bool IsCurrentMiner(string pubkey) - { - if (pubkey == null) return false; + return possibleKeys.FirstOrDefault(k => + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(k)) == address); + } - if (!TryToGetCurrentRoundInformation(out var currentRound)) return false; + private bool IsCurrentMiner(string pubkey) + { + if (pubkey == null) return false; - if (!currentRound.IsMinerListJustChanged) - { - if (!currentRound.RealTimeMinersInformation.ContainsKey(pubkey)) return false; - } + if (!TryToGetCurrentRoundInformation(out var currentRound)) return false; - Context.LogDebug(() => - $"Extra block producer of previous round: {currentRound.ExtraBlockProducerOfPreviousRound}"); + if (!currentRound.IsMinerListJustChanged) + if (!currentRound.RealTimeMinersInformation.ContainsKey(pubkey)) + return false; - // Check confirmed extra block producer of previous round. - if (Context.CurrentBlockTime <= currentRound.GetRoundStartTime() && - currentRound.ExtraBlockProducerOfPreviousRound == pubkey) - { - Context.LogDebug(() => "[CURRENT MINER]PREVIOUS"); - return true; - } + Context.LogDebug(() => + $"Extra block producer of previous round: {currentRound.ExtraBlockProducerOfPreviousRound}"); - var miningInterval = currentRound.GetMiningInterval(); - var minerInRound = currentRound.RealTimeMinersInformation[pubkey]; - var timeSlotStartTime = minerInRound.ExpectedMiningTime; + // Check confirmed extra block producer of previous round. + if (Context.CurrentBlockTime <= currentRound.GetRoundStartTime() && + currentRound.ExtraBlockProducerOfPreviousRound == pubkey) + { + Context.LogDebug(() => "[CURRENT MINER]PREVIOUS"); + return true; + } - // Check normal time slot. - if (timeSlotStartTime <= Context.CurrentBlockTime && Context.CurrentBlockTime <= - timeSlotStartTime.AddMilliseconds(miningInterval)) - { - Context.LogDebug(() => "[CURRENT MINER]NORMAL"); - return true; - } + var miningInterval = currentRound.GetMiningInterval(); + var minerInRound = currentRound.RealTimeMinersInformation[pubkey]; + var timeSlotStartTime = minerInRound.ExpectedMiningTime; - var supposedExtraBlockProducer = - currentRound.RealTimeMinersInformation.Single(m => m.Value.IsExtraBlockProducer).Key; + // Check normal time slot. + if (timeSlotStartTime <= Context.CurrentBlockTime && Context.CurrentBlockTime <= + timeSlotStartTime.AddMilliseconds(miningInterval)) + { + Context.LogDebug(() => "[CURRENT MINER]NORMAL"); + return true; + } - // Check extra block time slot. - if (Context.CurrentBlockTime >= currentRound.GetExtraBlockMiningTime() && - supposedExtraBlockProducer == pubkey) - { - Context.LogDebug(() => "[CURRENT MINER]EXTRA"); - return true; - } + var supposedExtraBlockProducer = + currentRound.RealTimeMinersInformation.Single(m => m.Value.IsExtraBlockProducer).Key; - // Check saving extra block time slot. - var nextArrangeMiningTime = - currentRound.ArrangeAbnormalMiningTime(pubkey, Context.CurrentBlockTime, true); - var actualArrangedMiningTime = nextArrangeMiningTime.AddMilliseconds(-currentRound.TotalMilliseconds()); - if (actualArrangedMiningTime <= Context.CurrentBlockTime && - Context.CurrentBlockTime <= actualArrangedMiningTime.AddMilliseconds(miningInterval)) - { - Context.LogDebug(() => "[CURRENT MINER]SAVING"); - return true; - } + // Check extra block time slot. + if (Context.CurrentBlockTime >= currentRound.GetExtraBlockMiningTime() && + supposedExtraBlockProducer == pubkey) + { + Context.LogDebug(() => "[CURRENT MINER]EXTRA"); + return true; + } - // If current round is the first round of current term. - if (currentRound.RoundNumber == 1) - { - Context.LogDebug(() => "First round"); + // Check saving extra block time slot. + var nextArrangeMiningTime = + currentRound.ArrangeAbnormalMiningTime(pubkey, Context.CurrentBlockTime, true); + var actualArrangedMiningTime = nextArrangeMiningTime.AddMilliseconds(-currentRound.TotalMilliseconds()); + if (actualArrangedMiningTime <= Context.CurrentBlockTime && + Context.CurrentBlockTime <= actualArrangedMiningTime.AddMilliseconds(miningInterval)) + { + Context.LogDebug(() => "[CURRENT MINER]SAVING"); + return true; + } - var latestMinedInfo = - currentRound.RealTimeMinersInformation.Values.OrderByDescending(i => i.Order) - .FirstOrDefault(i => i.ActualMiningTimes.Any() && i.Pubkey != pubkey); - if (latestMinedInfo != null) + // If current round is the first round of current term. + if (currentRound.RoundNumber == 1) + { + Context.LogDebug(() => "First round"); + + var latestMinedInfo = + currentRound.RealTimeMinersInformation.Values.OrderByDescending(i => i.Order) + .FirstOrDefault(i => i.ActualMiningTimes.Any() && i.Pubkey != pubkey); + if (latestMinedInfo != null) + { + var minersCount = currentRound.RealTimeMinersInformation.Count; + var latestMinedSlotLastActualMiningTime = latestMinedInfo.ActualMiningTimes.Last(); + var latestMinedOrder = latestMinedInfo.Order; + var currentMinerOrder = + currentRound.RealTimeMinersInformation.Single(i => i.Key == pubkey).Value.Order; + var passedSlotsCount = + (Context.CurrentBlockTime - latestMinedSlotLastActualMiningTime).Milliseconds() + .Div(miningInterval); + if (passedSlotsCount == currentMinerOrder.Sub(latestMinedOrder).Add(1).Add(minersCount) || + passedSlotsCount == currentMinerOrder.Sub(latestMinedOrder).Add(minersCount)) { - var minersCount = currentRound.RealTimeMinersInformation.Count; - var latestMinedSlotLastActualMiningTime = latestMinedInfo.ActualMiningTimes.Last(); - var latestMinedOrder = latestMinedInfo.Order; - var currentMinerOrder = - currentRound.RealTimeMinersInformation.Single(i => i.Key == pubkey).Value.Order; - var passedSlotsCount = - (Context.CurrentBlockTime - latestMinedSlotLastActualMiningTime).Milliseconds() - .Div(miningInterval); - if (passedSlotsCount == currentMinerOrder.Sub(latestMinedOrder).Add(1).Add(minersCount) || - passedSlotsCount == currentMinerOrder.Sub(latestMinedOrder).Add(minersCount)) - { - Context.LogDebug(() => "[CURRENT MINER]FIRST ROUND"); - return true; - } + Context.LogDebug(() => "[CURRENT MINER]FIRST ROUND"); + return true; } } + } - Context.LogDebug(() => "[CURRENT MINER]NOT MINER"); + Context.LogDebug(() => "[CURRENT MINER]NOT MINER"); - return false; - } + return false; + } + + private Round GenerateFirstRoundOfNextTerm(string senderPubkey, int miningInterval) + { + Round newRound; + TryToGetCurrentRoundInformation(out var currentRound); - private Round GenerateFirstRoundOfNextTerm(string senderPubkey, int miningInterval) + if (TryToGetVictories(out var victories)) + { + Context.LogDebug(() => "Got victories successfully."); + newRound = victories.GenerateFirstRoundOfNewTerm(miningInterval, Context.CurrentBlockTime, + currentRound); + } + else { - Round newRound; - TryToGetCurrentRoundInformation(out var currentRound); + // Miners of new round are same with current round. + var miners = new MinerList(); + miners.Pubkeys.AddRange( + currentRound.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString)); + newRound = miners.GenerateFirstRoundOfNewTerm(currentRound.GetMiningInterval(), + Context.CurrentBlockTime, currentRound); + } - if (TryToGetVictories(out var victories)) - { - Context.LogDebug(() => "Got victories successfully."); - newRound = victories.GenerateFirstRoundOfNewTerm(miningInterval, Context.CurrentBlockTime, - currentRound); - } - else - { - // Miners of new round are same with current round. - var miners = new MinerList(); - miners.Pubkeys.AddRange( - currentRound.RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString)); - newRound = miners.GenerateFirstRoundOfNewTerm(currentRound.GetMiningInterval(), - Context.CurrentBlockTime, currentRound); - } + newRound.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; + newRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; - newRound.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; - newRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; + newRound.BlockchainAge = GetBlockchainAge(); - newRound.BlockchainAge = GetBlockchainAge(); + if (newRound.RealTimeMinersInformation.ContainsKey(senderPubkey)) + newRound.RealTimeMinersInformation[senderPubkey].ProducedBlocks = 1; + else + UpdateCandidateInformation(senderPubkey, 1, 0); - if (newRound.RealTimeMinersInformation.ContainsKey(senderPubkey)) - { - newRound.RealTimeMinersInformation[senderPubkey].ProducedBlocks = 1; - } - else - { - UpdateCandidateInformation(senderPubkey, 1, 0); - } + newRound.ExtraBlockProducerOfPreviousRound = senderPubkey; - newRound.ExtraBlockProducerOfPreviousRound = senderPubkey; + return newRound; + } - return newRound; - } + private long GetBlockchainAge() + { + return State.BlockchainStartTimestamp.Value == null + ? 0 + : (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds; + } - private long GetBlockchainAge() + private bool TryToGetVictories(out MinerList victories) + { + if (!State.IsMainChain.Value) { - return State.BlockchainStartTimestamp.Value == null - ? 0 - : (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds; + victories = null; + return false; } - private bool TryToGetVictories(out MinerList victories) + var victoriesPublicKeys = State.ElectionContract.GetVictories.Call(new Empty()); + Context.LogDebug(() => + "Got victories from Election Contract:\n" + + $"{string.Join("\n", victoriesPublicKeys.Value.Select(s => s.ToHex().Substring(0, 20)))}"); + victories = new MinerList { - if (!State.IsMainChain.Value) - { - victories = null; - return false; - } + Pubkeys = { victoriesPublicKeys.Value } + }; + return victories.Pubkeys.Any(); + } - var victoriesPublicKeys = State.ElectionContract.GetVictories.Call(new Empty()); - Context.LogDebug(() => - "Got victories from Election Contract:\n" + - $"{string.Join("\n", victoriesPublicKeys.Value.Select(s => s.ToHex().Substring(0, 20)))}"); - victories = new MinerList - { - Pubkeys = {victoriesPublicKeys.Value}, - }; - return victories.Pubkeys.Any(); + private void GenerateNextRoundInformation(Round currentRound, Timestamp currentBlockTime, out Round nextRound) + { + TryToGetPreviousRoundInformation(out var previousRound); + if (!IsMainChain && IsMainChainMinerListChanged(currentRound)) + { + nextRound = State.MainChainCurrentMinerList.Value.GenerateFirstRoundOfNewTerm( + currentRound.GetMiningInterval(), currentBlockTime, currentRound.RoundNumber); + nextRound.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; + nextRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; + return; } - private void GenerateNextRoundInformation(Round currentRound, Timestamp currentBlockTime, out Round nextRound) + var blockchainStartTimestamp = GetBlockchainStartTimestamp(); + var isMinerListChanged = false; + if (IsMainChain && previousRound.TermNumber == currentRound.TermNumber) // In same term. { - TryToGetPreviousRoundInformation(out var previousRound); - if (!IsMainChain && IsMainChainMinerListChanged(currentRound)) - { - nextRound = State.MainChainCurrentMinerList.Value.GenerateFirstRoundOfNewTerm( - currentRound.GetMiningInterval(), currentBlockTime, currentRound.RoundNumber); - nextRound.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; - nextRound.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; - return; - } + var minerReplacementInformation = State.ElectionContract.GetMinerReplacementInformation.Call( + new GetMinerReplacementInformationInput + { + CurrentMinerList = { currentRound.RealTimeMinersInformation.Keys } + }); + + Context.LogDebug(() => $"Got miner replacement information:\n{minerReplacementInformation}"); - var blockchainStartTimestamp = GetBlockchainStartTimestamp(); - var isMinerListChanged = false; - if (IsMainChain && previousRound.TermNumber == currentRound.TermNumber) // In same term. + if (minerReplacementInformation.AlternativeCandidatePubkeys.Count > 0) { - var minerReplacementInformation = State.ElectionContract.GetMinerReplacementInformation.Call( - new GetMinerReplacementInformationInput + for (var i = 0; i < minerReplacementInformation.AlternativeCandidatePubkeys.Count; i++) + { + var alternativeCandidatePubkey = minerReplacementInformation.AlternativeCandidatePubkeys[i]; + var evilMinerPubkey = minerReplacementInformation.EvilMinerPubkeys[i]; + + // Update history information of evil node. + UpdateCandidateInformation(evilMinerPubkey, + currentRound.RealTimeMinersInformation[evilMinerPubkey].ProducedBlocks, + currentRound.RealTimeMinersInformation[evilMinerPubkey].MissedTimeSlots, true); + + Context.Fire(new MinerReplaced { - CurrentMinerList = {currentRound.RealTimeMinersInformation.Keys} + NewMinerPubkey = alternativeCandidatePubkey }); - Context.LogDebug(() => $"Got miner replacement information:\n{minerReplacementInformation}"); - - if (minerReplacementInformation.AlternativeCandidatePubkeys.Count > 0) - { - for (var i = 0; i < minerReplacementInformation.AlternativeCandidatePubkeys.Count; i++) + // Transfer evil node's consensus information to the chosen backup. + var evilMinerInformation = currentRound.RealTimeMinersInformation[evilMinerPubkey]; + var minerInRound = new MinerInRound { - var alternativeCandidatePubkey = minerReplacementInformation.AlternativeCandidatePubkeys[i]; - var evilMinerPubkey = minerReplacementInformation.EvilMinerPubkeys[i]; - - // Update history information of evil node. - UpdateCandidateInformation(evilMinerPubkey, - currentRound.RealTimeMinersInformation[evilMinerPubkey].ProducedBlocks, - currentRound.RealTimeMinersInformation[evilMinerPubkey].MissedTimeSlots, true); - - Context.Fire(new MinerReplaced - { - NewMinerPubkey = alternativeCandidatePubkey - }); - - // Transfer evil node's consensus information to the chosen backup. - var evilMinerInformation = currentRound.RealTimeMinersInformation[evilMinerPubkey]; - var minerInRound = new MinerInRound - { - Pubkey = alternativeCandidatePubkey, - ExpectedMiningTime = evilMinerInformation.ExpectedMiningTime, - Order = evilMinerInformation.Order, - PreviousInValue = Hash.Empty, - IsExtraBlockProducer = evilMinerInformation.IsExtraBlockProducer - }; - - currentRound.RealTimeMinersInformation.Remove(evilMinerPubkey); - currentRound.RealTimeMinersInformation.Add(alternativeCandidatePubkey, minerInRound); - } - - isMinerListChanged = true; + Pubkey = alternativeCandidatePubkey, + ExpectedMiningTime = evilMinerInformation.ExpectedMiningTime, + Order = evilMinerInformation.Order, + PreviousInValue = Hash.Empty, + IsExtraBlockProducer = evilMinerInformation.IsExtraBlockProducer + }; + + currentRound.RealTimeMinersInformation.Remove(evilMinerPubkey); + currentRound.RealTimeMinersInformation.Add(alternativeCandidatePubkey, minerInRound); } - } - currentRound.GenerateNextRoundInformation(currentBlockTime, blockchainStartTimestamp, out nextRound, - isMinerListChanged); + isMinerListChanged = true; + } } - private bool IsMainChainMinerListChanged(Round currentRound) - { - return State.MainChainCurrentMinerList.Value.Pubkeys.Any() && - GetMinerListHash(currentRound.RealTimeMinersInformation.Keys) != - GetMinerListHash(State.MainChainCurrentMinerList.Value.Pubkeys.Select(p => p.ToHex())); - } + currentRound.GenerateNextRoundInformation(currentBlockTime, blockchainStartTimestamp, out nextRound, + isMinerListChanged); + } - private static Hash GetMinerListHash(IEnumerable minerList) - { - return HashHelper.ComputeFrom( - minerList.OrderBy(p => p).Aggregate("", (current, publicKey) => current + publicKey)); - } + private bool IsMainChainMinerListChanged(Round currentRound) + { + return State.MainChainCurrentMinerList.Value.Pubkeys.Any() && + GetMinerListHash(currentRound.RealTimeMinersInformation.Keys) != + GetMinerListHash(State.MainChainCurrentMinerList.Value.Pubkeys.Select(p => p.ToHex())); + } - public override Int64Value GetCurrentTermNumber(Empty input) - { - return new Int64Value {Value = State.CurrentTermNumber.Value}; - } + private static Hash GetMinerListHash(IEnumerable minerList) + { + return HashHelper.ComputeFrom( + minerList.OrderBy(p => p).Aggregate("", (current, publicKey) => current + publicKey)); + } - private void UpdateCandidateInformation(string candidatePublicKey, long recentlyProducedBlocks, - long recentlyMissedTimeSlots, bool isEvilNode = false) - { - if (!State.IsMainChain.Value) - { - return; - } + public override Int64Value GetCurrentTermNumber(Empty input) + { + return new Int64Value { Value = State.CurrentTermNumber.Value }; + } - State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput - { - Pubkey = candidatePublicKey, - RecentlyProducedBlocks = recentlyProducedBlocks, - RecentlyMissedTimeSlots = recentlyMissedTimeSlots, - IsEvilNode = isEvilNode - }); - } + private void UpdateCandidateInformation(string candidatePublicKey, long recentlyProducedBlocks, + long recentlyMissedTimeSlots, bool isEvilNode = false) + { + if (!State.IsMainChain.Value) return; - private int GetMinersCount(Round input) + State.ElectionContract.UpdateCandidateInformation.Send(new UpdateCandidateInformationInput { - if (State.BlockchainStartTimestamp.Value == null) - { - return AEDPoSContractConstants.SupposedMinersCount; - } + Pubkey = candidatePublicKey, + RecentlyProducedBlocks = recentlyProducedBlocks, + RecentlyMissedTimeSlots = recentlyMissedTimeSlots, + IsEvilNode = isEvilNode + }); + } - if (!TryToGetRoundInformation(1, out _)) return 0; - return Math.Min(input.RealTimeMinersInformation.Count < AEDPoSContractConstants.SupposedMinersCount - ? AEDPoSContractConstants.SupposedMinersCount - : AEDPoSContractConstants.SupposedMinersCount.Add( - (int) (Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds - .Div(State.MinerIncreaseInterval.Value).Mul(2)), State.MaximumMinersCount.Value); - } + private int GetMinersCount(Round input) + { + if (State.BlockchainStartTimestamp.Value == null) return AEDPoSContractConstants.SupposedMinersCount; + + if (!TryToGetRoundInformation(1, out _)) return 0; + return Math.Min(input.RealTimeMinersInformation.Count < AEDPoSContractConstants.SupposedMinersCount + ? AEDPoSContractConstants.SupposedMinersCount + : AEDPoSContractConstants.SupposedMinersCount.Add( + (int)(Context.CurrentBlockTime - State.BlockchainStartTimestamp.Value).Seconds + .Div(State.MinerIncreaseInterval.Value).Mul(2)), State.MaximumMinersCount.Value); + } - public override Int64Value GetCurrentTermMiningReward(Empty input) - { - if (TryToGetCurrentRoundInformation(out var currentRound)) - { - return new Int64Value - {Value = currentRound.GetMinedBlocks().Mul(GetMiningRewardPerBlock())}; - } + public override Int64Value GetCurrentTermMiningReward(Empty input) + { + if (TryToGetCurrentRoundInformation(out var currentRound)) + return new Int64Value + { Value = currentRound.GetMinedBlocks().Mul(GetMiningRewardPerBlock()) }; - return new Int64Value {Value = 0}; - } + return new Int64Value { Value = 0 }; + } + + public override Int64Value GetCurrentMiningRewardPerBlock(Empty input) + { + return new Int64Value { Value = GetMiningRewardPerBlock() }; + } - public override Int64Value GetCurrentMiningRewardPerBlock(Empty input) + /// + /// Get left seconds to next election takes effects. + /// Return 0 for side chain and single node. + /// + /// + /// + public override Int64Value GetNextElectCountDown(Empty input) + { + if (!State.IsMainChain.Value) return new Int64Value(); + + var currentTermNumber = State.CurrentTermNumber.Value; + Timestamp currentTermStartTime; + if (currentTermNumber == 1) { - return new Int64Value {Value = GetMiningRewardPerBlock()}; + currentTermStartTime = State.BlockchainStartTimestamp.Value; + if (TryToGetRoundInformation(1, out var firstRound) && + firstRound.RealTimeMinersInformation.Count == 1) + return new Int64Value(); // Return 0 for single node. } - - /// - /// Get left seconds to next election takes effects. - /// Return 0 for side chain and single node. - /// - /// - /// - public override Int64Value GetNextElectCountDown(Empty input) + else { - if (!State.IsMainChain.Value) - { - return new Int64Value(); - } - - var currentTermNumber = State.CurrentTermNumber.Value; - Timestamp currentTermStartTime; - if (currentTermNumber == 1) - { - currentTermStartTime = State.BlockchainStartTimestamp.Value; - if (TryToGetRoundInformation(1, out var firstRound) && - firstRound.RealTimeMinersInformation.Count == 1) - return new Int64Value(); // Return 0 for single node. - } - else - { - var firstRoundNumberOfCurrentTerm = State.FirstRoundNumberOfEachTerm[currentTermNumber]; - if (!TryToGetRoundInformation(firstRoundNumberOfCurrentTerm, out var firstRoundOfCurrentTerm)) - return new Int64Value(); // Unlikely. - if (firstRoundOfCurrentTerm.RealTimeMinersInformation.Count == 1) - return new Int64Value(); // Return 0 for single node. - currentTermStartTime = firstRoundOfCurrentTerm.GetRoundStartTime(); - } - - var currentTermEndTime = currentTermStartTime.AddSeconds(State.PeriodSeconds.Value); - return new Int64Value {Value = (currentTermEndTime - Context.CurrentBlockTime).Seconds}; + var firstRoundNumberOfCurrentTerm = State.FirstRoundNumberOfEachTerm[currentTermNumber]; + if (!TryToGetRoundInformation(firstRoundNumberOfCurrentTerm, out var firstRoundOfCurrentTerm)) + return new Int64Value(); // Unlikely. + if (firstRoundOfCurrentTerm.RealTimeMinersInformation.Count == 1) + return new Int64Value(); // Return 0 for single node. + currentTermStartTime = firstRoundOfCurrentTerm.GetRoundStartTime(); } - public override Round GetPreviousTermInformation(Int64Value input) + var currentTermEndTime = currentTermStartTime.AddSeconds(State.PeriodSeconds.Value); + return new Int64Value { Value = (currentTermEndTime - Context.CurrentBlockTime).Seconds }; + } + + public override Round GetPreviousTermInformation(Int64Value input) + { + var lastRoundNumber = State.FirstRoundNumberOfEachTerm[input.Value.Add(1)].Sub(1); + var round = State.Rounds[lastRoundNumber]; + if (round == null || round.RoundId == 0) return new Round(); + var result = new Round { - var lastRoundNumber = State.FirstRoundNumberOfEachTerm[input.Value.Add(1)].Sub(1); - var round = State.Rounds[lastRoundNumber]; - if (round == null || round.RoundId == 0) return new Round(); - var result = new Round + TermNumber = input.Value + }; + foreach (var minerInRound in round.RealTimeMinersInformation) + result.RealTimeMinersInformation[minerInRound.Key] = new MinerInRound { - TermNumber = input.Value + Pubkey = minerInRound.Value.Pubkey, + ProducedBlocks = minerInRound.Value.ProducedBlocks }; - foreach (var minerInRound in round.RealTimeMinersInformation) - { - result.RealTimeMinersInformation[minerInRound.Key] = new MinerInRound - { - Pubkey = minerInRound.Value.Pubkey, - ProducedBlocks = minerInRound.Value.ProducedBlocks - }; - } - return result; - } + return result; + } - public override MinerList GetMainChainCurrentMinerList(Empty input) - { - return State.MainChainCurrentMinerList.Value; - } + public override MinerList GetMainChainCurrentMinerList(Empty input) + { + return State.MainChainCurrentMinerList.Value; + } - public override PubkeyList GetPreviousTermMinerPubkeyList(Empty input) + public override PubkeyList GetPreviousTermMinerPubkeyList(Empty input) + { + var lastRoundNumber = State.FirstRoundNumberOfEachTerm[State.CurrentTermNumber.Value].Sub(1); + var lastRound = State.Rounds[lastRoundNumber]; + if (lastRound == null || lastRound.RoundId == 0) return new PubkeyList(); + return new PubkeyList { - var lastRoundNumber = State.FirstRoundNumberOfEachTerm[State.CurrentTermNumber.Value].Sub(1); - var lastRound = State.Rounds[lastRoundNumber]; - if (lastRound == null || lastRound.RoundId == 0) return new PubkeyList(); - return new PubkeyList - { - Pubkeys = {lastRound.RealTimeMinersInformation.Keys} - }; - } + Pubkeys = { lastRound.RealTimeMinersInformation.Keys } + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj b/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj index 3e12ab30ff..13ae50e26c 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,19 +9,19 @@ - true + true - true + true - + Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\election_contract.proto @@ -69,7 +69,7 @@ Protobuf\Proto\aedpos_contract.proto - + Protobuf\Proto\aedpos_contract_impl.proto diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs index 21d8c49807..55bed98cc7 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs @@ -1,63 +1,62 @@ +using AElf.Sdk.CSharp.State; using AElf.Standards.ACS1; using AElf.Standards.ACS10; -using AElf.Sdk.CSharp.State; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +// ReSharper disable UnusedAutoPropertyAccessor.Global +public partial class AEDPoSContractState : ContractState { - // ReSharper disable once InconsistentNaming - // ReSharper disable UnusedAutoPropertyAccessor.Global - public partial class AEDPoSContractState : ContractState - { - public BoolState Initialized { get; set; } + public BoolState Initialized { get; set; } - /// - /// Seconds. - /// - public ReadonlyState PeriodSeconds { get; set; } + /// + /// Seconds. + /// + public ReadonlyState PeriodSeconds { get; set; } - public Int64State CurrentRoundNumber { get; set; } + public Int64State CurrentRoundNumber { get; set; } - public Int64State CurrentTermNumber { get; set; } + public Int64State CurrentTermNumber { get; set; } - public ReadonlyState BlockchainStartTimestamp { get; set; } + public ReadonlyState BlockchainStartTimestamp { get; set; } - public MappedState Rounds { get; set; } + public MappedState Rounds { get; set; } - public ReadonlyState MiningInterval { get; set; } + public ReadonlyState MiningInterval { get; set; } - public MappedState FirstRoundNumberOfEachTerm { get; set; } + public MappedState FirstRoundNumberOfEachTerm { get; set; } - public MappedState MinerListMap { get; set; } + public MappedState MinerListMap { get; set; } - public Int64State MainChainRoundNumber { get; set; } + public Int64State MainChainRoundNumber { get; set; } - public SingletonState MainChainCurrentMinerList { get; set; } + public SingletonState MainChainCurrentMinerList { get; set; } - public BoolState IsMainChain { get; set; } + public BoolState IsMainChain { get; set; } - public ReadonlyState MinerIncreaseInterval { get; set; } + public ReadonlyState MinerIncreaseInterval { get; set; } - public Int32State MaximumMinersCount { get; set; } + public Int32State MaximumMinersCount { get; set; } - public SingletonState LatestPubkeyToTinyBlocksCount { get; set; } + public SingletonState LatestPubkeyToTinyBlocksCount { get; set; } - public MappedState MinedMinerListMap { get; set; } - public MappedState TransactionFees { get; set; } + public MappedState MinedMinerListMap { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState RoundBeforeLatestExecution { get; set; } - public SingletonState MethodFeeController { get; set; } - public SingletonState MaximumMinersCountController { get; set; } + public SingletonState RoundBeforeLatestExecution { get; set; } + public SingletonState MethodFeeController { get; set; } + public SingletonState MaximumMinersCountController { get; set; } - public MappedState RandomHashes { get; set; } + public MappedState RandomHashes { get; set; } - public SingletonState LatestExecutedHeight { get; set; } + public SingletonState LatestExecutedHeight { get; set; } - public MappedState SideChainReceivedDividends { get; set; } + public MappedState SideChainReceivedDividends { get; set; } - public SingletonState SideChainDividendPoolSchemeId { get; set; } + public SingletonState SideChainDividendPoolSchemeId { get; set; } - public BoolState IsPreviousBlockInSevereStatus { get; set; } - } + public BoolState IsPreviousBlockInSevereStatus { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusBehaviourProviderBase.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusBehaviourProviderBase.cs index 609eb0530b..fbf71a2fbd 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusBehaviourProviderBase.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusBehaviourProviderBase.cs @@ -1,136 +1,124 @@ using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// First step of getting consensus command for any pubkey: + /// to get expected consensus behaviour. + /// + private abstract class ConsensusBehaviourProviderBase { - /// - /// First step of getting consensus command for any pubkey: - /// to get expected consensus behaviour. - /// - private abstract class ConsensusBehaviourProviderBase - { - protected readonly Round CurrentRound; + private readonly Timestamp _currentBlockTime; - private readonly string _pubkey; - private readonly int _maximumBlocksCount; - private readonly Timestamp _currentBlockTime; + private readonly bool _isTimeSlotPassed; + private readonly int _maximumBlocksCount; + private readonly MinerInRound _minerInRound; - private readonly bool _isTimeSlotPassed; - private readonly MinerInRound _minerInRound; + private readonly string _pubkey; + protected readonly Round CurrentRound; - protected ConsensusBehaviourProviderBase(Round currentRound, string pubkey, int maximumBlocksCount, - Timestamp currentBlockTime) - { - CurrentRound = currentRound; + protected ConsensusBehaviourProviderBase(Round currentRound, string pubkey, int maximumBlocksCount, + Timestamp currentBlockTime) + { + CurrentRound = currentRound; - _pubkey = pubkey; - _maximumBlocksCount = maximumBlocksCount; - _currentBlockTime = currentBlockTime; + _pubkey = pubkey; + _maximumBlocksCount = maximumBlocksCount; + _currentBlockTime = currentBlockTime; - _isTimeSlotPassed = CurrentRound.IsTimeSlotPassed(_pubkey, _currentBlockTime); - _minerInRound = CurrentRound.RealTimeMinersInformation[_pubkey]; - } + _isTimeSlotPassed = CurrentRound.IsTimeSlotPassed(_pubkey, _currentBlockTime); + _minerInRound = CurrentRound.RealTimeMinersInformation[_pubkey]; + } - public AElfConsensusBehaviour GetConsensusBehaviour() - { - // The most simple situation: provided pubkey isn't a miner. - // Already checked in GetConsensusCommand. + public AElfConsensusBehaviour GetConsensusBehaviour() + { + // The most simple situation: provided pubkey isn't a miner. + // Already checked in GetConsensusCommand. // if (!CurrentRound.IsInMinerList(_pubkey)) // { // return AElfConsensusBehaviour.Nothing; // } - // If out value is null, it means provided pubkey hasn't mine any block during current round period. - if (_minerInRound.OutValue == null) - { - var behaviour = HandleMinerInNewRound(); - - // It's possible HandleMinerInNewRound can't handle all the situations, if this method returns Nothing, - // just go ahead. Otherwise, return it's result. - if (behaviour != AElfConsensusBehaviour.Nothing) - { - return behaviour; - } - } - else if (!_isTimeSlotPassed - ) // Provided pubkey mined blocks during current round, and current block time is still in his time slot. - { - if (_minerInRound.ActualMiningTimes.Count < _maximumBlocksCount) - { - // Provided pubkey can keep producing tiny blocks. - return AElfConsensusBehaviour.TinyBlock; - } - - var blocksBeforeCurrentRound = - _minerInRound.ActualMiningTimes.Count(t => t <= CurrentRound.GetRoundStartTime()); - - // If provided pubkey is the one who terminated previous round, he can mine - // (_maximumBlocksCount + blocksBeforeCurrentRound) blocks - // because he has two time slots recorded in current round. - - if (CurrentRound.ExtraBlockProducerOfPreviousRound == - _pubkey && // Provided pubkey terminated previous round - !CurrentRound.IsMinerListJustChanged && // & Current round isn't the first round of current term - _minerInRound.ActualMiningTimes.Count.Add(1) < - _maximumBlocksCount.Add( - blocksBeforeCurrentRound) // & Provided pubkey hasn't mine enough blocks for current round. - ) - { - // Then provided pubkey can keep producing tiny blocks. - return AElfConsensusBehaviour.TinyBlock; - } - } - - return GetConsensusBehaviourToTerminateCurrentRound(); - } + // If out value is null, it means provided pubkey hasn't mine any block during current round period. + if (_minerInRound.OutValue == null) + { + var behaviour = HandleMinerInNewRound(); - /// - /// If this miner come to a new round, normally, there are three possible behaviour: - /// UPDATE_VALUE (most common) - /// TINY_BLOCK (happens if this miner is mining blocks for extra block time slot of previous round) - /// NEXT_ROUND (only happens in first round) - /// - /// - private AElfConsensusBehaviour HandleMinerInNewRound() + // It's possible HandleMinerInNewRound can't handle all the situations, if this method returns Nothing, + // just go ahead. Otherwise, return it's result. + if (behaviour != AElfConsensusBehaviour.Nothing) return behaviour; + } + else if (!_isTimeSlotPassed + ) // Provided pubkey mined blocks during current round, and current block time is still in his time slot. { - if ( - // For first round, the expected mining time is incorrect (due to configuration), - CurrentRound.RoundNumber == 1 && - // so we'd better prevent miners' ain't first order (meanwhile he isn't boot miner) from mining fork blocks - _minerInRound.Order != 1 && - // by postpone their mining time - CurrentRound.FirstMiner().OutValue == null - ) - { - return AElfConsensusBehaviour.NextRound; - } - - if ( - // If this miner is extra block producer of previous round, - CurrentRound.ExtraBlockProducerOfPreviousRound == _pubkey && - // and currently the time is ahead of current round, - _currentBlockTime < CurrentRound.GetRoundStartTime() && - // make this miner produce some tiny blocks. - _minerInRound.ActualMiningTimes.Count < _maximumBlocksCount - ) - { + if (_minerInRound.ActualMiningTimes.Count < _maximumBlocksCount) + // Provided pubkey can keep producing tiny blocks. return AElfConsensusBehaviour.TinyBlock; - } - return !_isTimeSlotPassed ? AElfConsensusBehaviour.UpdateValue : AElfConsensusBehaviour.Nothing; + var blocksBeforeCurrentRound = + _minerInRound.ActualMiningTimes.Count(t => t <= CurrentRound.GetRoundStartTime()); + + // If provided pubkey is the one who terminated previous round, he can mine + // (_maximumBlocksCount + blocksBeforeCurrentRound) blocks + // because he has two time slots recorded in current round. + + if (CurrentRound.ExtraBlockProducerOfPreviousRound == + _pubkey && // Provided pubkey terminated previous round + !CurrentRound.IsMinerListJustChanged && // & Current round isn't the first round of current term + _minerInRound.ActualMiningTimes.Count.Add(1) < + _maximumBlocksCount.Add( + blocksBeforeCurrentRound) // & Provided pubkey hasn't mine enough blocks for current round. + ) + // Then provided pubkey can keep producing tiny blocks. + return AElfConsensusBehaviour.TinyBlock; } - /// - /// Main Chain & Side Chains are different (because side chains have no election mechanism thus no NEXT_TERM behaviour). - /// - /// - protected abstract AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound(); + return GetConsensusBehaviourToTerminateCurrentRound(); } + + /// + /// If this miner come to a new round, normally, there are three possible behaviour: + /// UPDATE_VALUE (most common) + /// TINY_BLOCK (happens if this miner is mining blocks for extra block time slot of previous round) + /// NEXT_ROUND (only happens in first round) + /// + /// + private AElfConsensusBehaviour HandleMinerInNewRound() + { + if ( + // For first round, the expected mining time is incorrect (due to configuration), + CurrentRound.RoundNumber == 1 && + // so we'd better prevent miners' ain't first order (meanwhile he isn't boot miner) from mining fork blocks + _minerInRound.Order != 1 && + // by postpone their mining time + CurrentRound.FirstMiner().OutValue == null + ) + return AElfConsensusBehaviour.NextRound; + + if ( + // If this miner is extra block producer of previous round, + CurrentRound.ExtraBlockProducerOfPreviousRound == _pubkey && + // and currently the time is ahead of current round, + _currentBlockTime < CurrentRound.GetRoundStartTime() && + // make this miner produce some tiny blocks. + _minerInRound.ActualMiningTimes.Count < _maximumBlocksCount + ) + return AElfConsensusBehaviour.TinyBlock; + + return !_isTimeSlotPassed ? AElfConsensusBehaviour.UpdateValue : AElfConsensusBehaviour.Nothing; + } + + /// + /// Main Chain & Side Chains are different (because side chains have no election mechanism thus no NEXT_TERM + /// behaviour). + /// + /// + protected abstract AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusCommandProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusCommandProvider.cs index e49c4125f6..98eb489c9e 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusCommandProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/ConsensusCommandProvider.cs @@ -3,36 +3,35 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private class ConsensusCommandProvider { - private class ConsensusCommandProvider - { - private readonly ICommandStrategy _commandStrategy; + private readonly ICommandStrategy _commandStrategy; - /// - /// No, you can't mine blocks. - /// - public static ConsensusCommand InvalidConsensusCommand => new ConsensusCommand - { - ArrangedMiningTime = new Timestamp {Seconds = int.MaxValue}, - Hint = ByteString.CopyFrom(new AElfConsensusHint - { - Behaviour = AElfConsensusBehaviour.Nothing - }.ToByteArray()) - }; + public ConsensusCommandProvider(ICommandStrategy commandStrategy) + { + _commandStrategy = commandStrategy; + } - public ConsensusCommandProvider(ICommandStrategy commandStrategy) + /// + /// No, you can't mine blocks. + /// + public static ConsensusCommand InvalidConsensusCommand => new() + { + ArrangedMiningTime = new Timestamp { Seconds = int.MaxValue }, + Hint = ByteString.CopyFrom(new AElfConsensusHint { - _commandStrategy = commandStrategy; - } + Behaviour = AElfConsensusBehaviour.Nothing + }.ToByteArray()) + }; - public ConsensusCommand GetConsensusCommand() - { - return _commandStrategy.GetConsensusCommand(); - } + public ConsensusCommand GetConsensusCommand() + { + return _commandStrategy.GetConsensusCommand(); } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MainChainConsensusBehaviourProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MainChainConsensusBehaviourProvider.cs index 706b5880b4..084d45f240 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MainChainConsensusBehaviourProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MainChainConsensusBehaviourProvider.cs @@ -1,37 +1,38 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private class MainChainConsensusBehaviourProvider : ConsensusBehaviourProviderBase { - private class MainChainConsensusBehaviourProvider : ConsensusBehaviourProviderBase - { - private readonly Timestamp _blockchainStartTimestamp; - private readonly long _periodSeconds; + private readonly Timestamp _blockchainStartTimestamp; + private readonly long _periodSeconds; - public MainChainConsensusBehaviourProvider(Round currentRound, string pubkey, int maximumBlocksCount, - Timestamp currentBlockTime, Timestamp blockchainStartTimestamp, long periodSeconds) : base(currentRound, - pubkey, maximumBlocksCount, currentBlockTime) - { - _blockchainStartTimestamp = blockchainStartTimestamp; - _periodSeconds = periodSeconds; - } + public MainChainConsensusBehaviourProvider(Round currentRound, string pubkey, int maximumBlocksCount, + Timestamp currentBlockTime, Timestamp blockchainStartTimestamp, long periodSeconds) : base(currentRound, + pubkey, maximumBlocksCount, currentBlockTime) + { + _blockchainStartTimestamp = blockchainStartTimestamp; + _periodSeconds = periodSeconds; + } - /// - /// The blockchain start timestamp is incorrect during the first round, - /// don't worry, we can return NextRound without hesitation. - /// Besides, return only NextRound for single node running. - /// - /// - protected override AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound() => - CurrentRound.RoundNumber == 1 || // Return NEXT_ROUND in first round. - !CurrentRound.NeedToChangeTerm(_blockchainStartTimestamp, - CurrentRound.TermNumber, _periodSeconds) || - CurrentRound.RealTimeMinersInformation.Keys.Count == 1 // Return NEXT_ROUND for single node. - ? AElfConsensusBehaviour.NextRound - : AElfConsensusBehaviour.NextTerm; + /// + /// The blockchain start timestamp is incorrect during the first round, + /// don't worry, we can return NextRound without hesitation. + /// Besides, return only NextRound for single node running. + /// + /// + protected override AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound() + { + return CurrentRound.RoundNumber == 1 || // Return NEXT_ROUND in first round. + !CurrentRound.NeedToChangeTerm(_blockchainStartTimestamp, + CurrentRound.TermNumber, _periodSeconds) || + CurrentRound.RealTimeMinersInformation.Keys.Count == 1 // Return NEXT_ROUND for single node. + ? AElfConsensusBehaviour.NextRound + : AElfConsensusBehaviour.NextTerm; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MiningTimeArrangingService.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MiningTimeArrangingService.cs index 0236826b08..68eb91b4fd 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MiningTimeArrangingService.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/MiningTimeArrangingService.cs @@ -1,29 +1,27 @@ using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private static class MiningTimeArrangingService { - private static class MiningTimeArrangingService + public static Timestamp ArrangeMiningTimeWithOffset(Timestamp currentBlockTime, int offset) { - public static Timestamp ArrangeMiningTimeWithOffset(Timestamp currentBlockTime, int offset) - { - return currentBlockTime.AddMilliseconds(offset); - } + return currentBlockTime.AddMilliseconds(offset); + } - public static Timestamp ArrangeNormalBlockMiningTime(Round round, string pubkey, Timestamp currentBlockTime) - { - return TimestampExtensions.Max(round.GetExpectedMiningTime(pubkey), currentBlockTime); - } + public static Timestamp ArrangeNormalBlockMiningTime(Round round, string pubkey, Timestamp currentBlockTime) + { + return TimestampExtensions.Max(round.GetExpectedMiningTime(pubkey), currentBlockTime); + } - public static Timestamp ArrangeExtraBlockMiningTime(Round round, string pubkey, Timestamp currentBlockTime) - { - return round.ArrangeAbnormalMiningTime(pubkey, currentBlockTime); - } + public static Timestamp ArrangeExtraBlockMiningTime(Round round, string pubkey, Timestamp currentBlockTime) + { + return round.ArrangeAbnormalMiningTime(pubkey, currentBlockTime); } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/SideChainConsensusBehaviourProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/SideChainConsensusBehaviourProvider.cs index c7ad9c0d51..b7ca40d70f 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/SideChainConsensusBehaviourProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/SideChainConsensusBehaviourProvider.cs @@ -1,24 +1,25 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private class SideChainConsensusBehaviourProvider : ConsensusBehaviourProviderBase { - private class SideChainConsensusBehaviourProvider : ConsensusBehaviourProviderBase + public SideChainConsensusBehaviourProvider(Round currentRound, string pubkey, int maximumBlocksCount, + Timestamp currentBlockTime) : base(currentRound, pubkey, maximumBlocksCount, currentBlockTime) { - public SideChainConsensusBehaviourProvider(Round currentRound, string pubkey, int maximumBlocksCount, - Timestamp currentBlockTime) : base(currentRound, pubkey, maximumBlocksCount, currentBlockTime) - { - } + } - /// - /// Simply return NEXT_ROUND for side chain. - /// - /// - protected override AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound() => - AElfConsensusBehaviour.NextRound; + /// + /// Simply return NEXT_ROUND for side chain. + /// + /// + protected override AElfConsensusBehaviour GetConsensusBehaviourToTerminateCurrentRound() + { + return AElfConsensusBehaviour.NextRound; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/CommandStrategyBase.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/CommandStrategyBase.cs index b88f97aa6c..0bc6ab961a 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/CommandStrategyBase.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/CommandStrategyBase.cs @@ -1,69 +1,73 @@ -using AElf.Standards.ACS4; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSContract { - public partial class AEDPoSContract + /// + /// Basically provides some useful fields for other strategies. + /// + public abstract class CommandStrategyBase : ICommandStrategy { /// - /// Basically provides some useful fields for other strategies. + /// In AElf Main Chain, miner will produce 8 blocks (as fast as possible) during every time slot by default. + /// + private const int TinyBlocksCount = 8; + + /// + /// The minimum interval between two blocks of same time slot. /// - public abstract class CommandStrategyBase : ICommandStrategy + protected const int TinyBlockMinimumInterval = 50; + + protected readonly Timestamp CurrentBlockTime; + protected readonly Round CurrentRound; + protected readonly string Pubkey; + + protected CommandStrategyBase(Round currentRound, string pubkey, Timestamp currentBlockTime) { - protected readonly Round CurrentRound; - protected readonly string Pubkey; - protected readonly Timestamp CurrentBlockTime; + CurrentRound = currentRound; + Pubkey = pubkey; + CurrentBlockTime = currentBlockTime; + } - /// - /// In AElf Main Chain, miner will produce 8 blocks (as fast as possible) during every time slot by default. - /// - private const int TinyBlocksCount = 8; - /// - /// The minimum interval between two blocks of same time slot. - /// - protected const int TinyBlockMinimumInterval = 50; + protected MinerInRound MinerInRound => CurrentRound.RealTimeMinersInformation[Pubkey]; + protected int Order => CurrentRound.GetMiningOrder(Pubkey); + protected int MiningInterval => CurrentRound.GetMiningInterval(); - protected MinerInRound MinerInRound => CurrentRound.RealTimeMinersInformation[Pubkey]; - protected int Order => CurrentRound.GetMiningOrder(Pubkey); - protected int MiningInterval => CurrentRound.GetMiningInterval(); - /// - /// Producing time of every (tiny) block at most. - /// - private int TinyBlockSlotInterval => MiningInterval.Div(TinyBlocksCount); - protected int MinersCount => CurrentRound.RealTimeMinersInformation.Count; - /// - /// Give 3/5 of producing time for mining by default. - /// - protected int DefaultBlockMiningLimit => TinyBlockSlotInterval.Mul(3).Div(5); - /// - /// If this tiny block is the last one of current time slot, give half of producing time for mining. - /// - protected int LastTinyBlockMiningLimit => TinyBlockSlotInterval.Div(2); - /// - /// If this block is of consensus behaviour NEXT_TERM, the producing time is MiningInterval, - /// so the limitation of mining is 8 times than DefaultBlockMiningLimit. - /// - protected int LastBlockOfCurrentTermMiningLimit => MiningInterval.Mul(3).Div(5); + /// + /// Producing time of every (tiny) block at most. + /// + private int TinyBlockSlotInterval => MiningInterval.Div(TinyBlocksCount); - protected CommandStrategyBase(Round currentRound, string pubkey, Timestamp currentBlockTime) - { - CurrentRound = currentRound; - Pubkey = pubkey; - CurrentBlockTime = currentBlockTime; - } + protected int MinersCount => CurrentRound.RealTimeMinersInformation.Count; - public ConsensusCommand GetConsensusCommand() - { - return GetAEDPoSConsensusCommand(); - } + /// + /// Give 3/5 of producing time for mining by default. + /// + protected int DefaultBlockMiningLimit => TinyBlockSlotInterval.Mul(3).Div(5); + + /// + /// If this tiny block is the last one of current time slot, give half of producing time for mining. + /// + protected int LastTinyBlockMiningLimit => TinyBlockSlotInterval.Div(2); - // ReSharper disable once InconsistentNaming - public virtual ConsensusCommand GetAEDPoSConsensusCommand() - { - return ConsensusCommandProvider.InvalidConsensusCommand; - } + /// + /// If this block is of consensus behaviour NEXT_TERM, the producing time is MiningInterval, + /// so the limitation of mining is 8 times than DefaultBlockMiningLimit. + /// + protected int LastBlockOfCurrentTermMiningLimit => MiningInterval.Mul(3).Div(5); + + public ConsensusCommand GetConsensusCommand() + { + return GetAEDPoSConsensusCommand(); + } + + // ReSharper disable once InconsistentNaming + public virtual ConsensusCommand GetAEDPoSConsensusCommand() + { + return ConsensusCommandProvider.InvalidConsensusCommand; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/FirstRoundCommandStrategy.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/FirstRoundCommandStrategy.cs index 01220c4eba..0764c44d66 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/FirstRoundCommandStrategy.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/FirstRoundCommandStrategy.cs @@ -1,51 +1,49 @@ -using AElf.Standards.ACS4; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// Why implement a strategy only for first round? + /// Because during the first round, the ExpectedMiningTimes of every miner + /// depends on the StartTimestamp configured before starting current blockchain, + /// (which AElf Main Chain use new Timestamp {Seconds = 0},) + /// thus we can't really give mining scheduler these data. + /// The ActualMiningTimes will based on Orders of these miners. + /// + private class FirstRoundCommandStrategy : CommandStrategyBase { - /// - /// Why implement a strategy only for first round? - /// Because during the first round, the ExpectedMiningTimes of every miner - /// depends on the StartTimestamp configured before starting current blockchain, - /// (which AElf Main Chain use new Timestamp {Seconds = 0},) - /// thus we can't really give mining scheduler these data. - /// The ActualMiningTimes will based on Orders of these miners. - /// - private class FirstRoundCommandStrategy : CommandStrategyBase - { - private readonly AElfConsensusBehaviour _consensusBehaviour; + private readonly AElfConsensusBehaviour _consensusBehaviour; - public FirstRoundCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, - AElfConsensusBehaviour consensusBehaviour) : base(currentRound, pubkey, currentBlockTime) - { - _consensusBehaviour = consensusBehaviour; - } + public FirstRoundCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, + AElfConsensusBehaviour consensusBehaviour) : base(currentRound, pubkey, currentBlockTime) + { + _consensusBehaviour = consensusBehaviour; + } - public override ConsensusCommand GetAEDPoSConsensusCommand() + public override ConsensusCommand GetAEDPoSConsensusCommand() + { + var miningInterval = MiningInterval; + var offset = + _consensusBehaviour == AElfConsensusBehaviour.UpdateValue && Order == 1 + ? miningInterval + : Order.Add(MinersCount).Sub(1).Mul(miningInterval); + var arrangedMiningTime = + MiningTimeArrangingService.ArrangeMiningTimeWithOffset(CurrentBlockTime, offset); + return new ConsensusCommand { - var miningInterval = MiningInterval; - var offset = - _consensusBehaviour == AElfConsensusBehaviour.UpdateValue && Order == 1 - ? miningInterval - : Order.Add(MinersCount).Sub(1).Mul(miningInterval); - var arrangedMiningTime = - MiningTimeArrangingService.ArrangeMiningTimeWithOffset(CurrentBlockTime, offset); - return new ConsensusCommand - { - Hint = new AElfConsensusHint {Behaviour = _consensusBehaviour}.ToByteString(), - ArrangedMiningTime = arrangedMiningTime, - MiningDueTime = arrangedMiningTime.AddMilliseconds(miningInterval), - LimitMillisecondsOfMiningBlock = DefaultBlockMiningLimit - }; - } + Hint = new AElfConsensusHint { Behaviour = _consensusBehaviour }.ToByteString(), + ArrangedMiningTime = arrangedMiningTime, + MiningDueTime = arrangedMiningTime.AddMilliseconds(miningInterval), + LimitMillisecondsOfMiningBlock = DefaultBlockMiningLimit + }; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/ICommandStrategy.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/ICommandStrategy.cs index 3c4a32ab6e..86627bf185 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/ICommandStrategy.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/ICommandStrategy.cs @@ -1,21 +1,20 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + /// + /// To provide consensus command for different consensus behaviours, like + /// consensus command of blocks in first round, + /// consensus command of normal block (miner will publish out value and previous in value), + /// consensus command of tiny block (miner just update his latest mining time) + /// consensus command of terminating current round. + /// + protected interface ICommandStrategy { - /// - /// To provide consensus command for different consensus behaviours, like - /// consensus command of blocks in first round, - /// consensus command of normal block (miner will publish out value and previous in value), - /// consensus command of tiny block (miner just update his latest mining time) - /// consensus command of terminating current round. - /// - protected interface ICommandStrategy - { - ConsensusCommand GetConsensusCommand(); - } + ConsensusCommand GetConsensusCommand(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/NormalBlockCommandStrategy.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/NormalBlockCommandStrategy.cs index c803896a73..c44b829337 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/NormalBlockCommandStrategy.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/NormalBlockCommandStrategy.cs @@ -1,45 +1,43 @@ -using AElf.Standards.ACS4; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public class NormalBlockCommandStrategy : CommandStrategyBase { - public class NormalBlockCommandStrategy : CommandStrategyBase + private readonly long _previousRoundId; + + public NormalBlockCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, + long previousRoundId) : base( + currentRound, pubkey, currentBlockTime) { - private readonly long _previousRoundId; + _previousRoundId = previousRoundId; + } - public NormalBlockCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, - long previousRoundId) : base( - currentRound, pubkey, currentBlockTime) - { - _previousRoundId = previousRoundId; - } + public override ConsensusCommand GetAEDPoSConsensusCommand() + { + var arrangedMiningTime = + MiningTimeArrangingService.ArrangeNormalBlockMiningTime(CurrentRound, Pubkey, CurrentBlockTime); - public override ConsensusCommand GetAEDPoSConsensusCommand() + return new ConsensusCommand { - var arrangedMiningTime = - MiningTimeArrangingService.ArrangeNormalBlockMiningTime(CurrentRound, Pubkey, CurrentBlockTime); - - return new ConsensusCommand + Hint = new AElfConsensusHint { - Hint = new AElfConsensusHint - { - Behaviour = AElfConsensusBehaviour.UpdateValue, - RoundId = CurrentRound.RoundId, - PreviousRoundId = _previousRoundId - }.ToByteString(), - ArrangedMiningTime = arrangedMiningTime, - // Cancel mining after time slot of current miner because of the task queue. - MiningDueTime = CurrentRound.GetExpectedMiningTime(Pubkey).AddMilliseconds(MiningInterval), - LimitMillisecondsOfMiningBlock = DefaultBlockMiningLimit - }; - } + Behaviour = AElfConsensusBehaviour.UpdateValue, + RoundId = CurrentRound.RoundId, + PreviousRoundId = _previousRoundId + }.ToByteString(), + ArrangedMiningTime = arrangedMiningTime, + // Cancel mining after time slot of current miner because of the task queue. + MiningDueTime = CurrentRound.GetExpectedMiningTime(Pubkey).AddMilliseconds(MiningInterval), + LimitMillisecondsOfMiningBlock = DefaultBlockMiningLimit + }; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TerminateRoundCommandStrategy.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TerminateRoundCommandStrategy.cs index eda926b178..7d9d9bd838 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TerminateRoundCommandStrategy.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TerminateRoundCommandStrategy.cs @@ -1,43 +1,41 @@ -using AElf.Standards.ACS4; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + public class TerminateRoundCommandStrategy : CommandStrategyBase { - public class TerminateRoundCommandStrategy : CommandStrategyBase - { - private readonly bool _isNewTerm; + private readonly bool _isNewTerm; - public TerminateRoundCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, - bool isNewTerm) : base( - currentRound, pubkey, currentBlockTime) - { - _isNewTerm = isNewTerm; - } + public TerminateRoundCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, + bool isNewTerm) : base( + currentRound, pubkey, currentBlockTime) + { + _isNewTerm = isNewTerm; + } - public override ConsensusCommand GetAEDPoSConsensusCommand() + public override ConsensusCommand GetAEDPoSConsensusCommand() + { + var arrangedMiningTime = + MiningTimeArrangingService.ArrangeExtraBlockMiningTime(CurrentRound, Pubkey, CurrentBlockTime); + return new ConsensusCommand { - var arrangedMiningTime = - MiningTimeArrangingService.ArrangeExtraBlockMiningTime(CurrentRound, Pubkey, CurrentBlockTime); - return new ConsensusCommand - { - Hint = new AElfConsensusHint - { - Behaviour = _isNewTerm ? AElfConsensusBehaviour.NextTerm : AElfConsensusBehaviour.NextRound - } - .ToByteString(), - ArrangedMiningTime = arrangedMiningTime, - MiningDueTime = arrangedMiningTime.AddMilliseconds(MiningInterval), - LimitMillisecondsOfMiningBlock = - _isNewTerm ? LastBlockOfCurrentTermMiningLimit : DefaultBlockMiningLimit - }; - } + Hint = new AElfConsensusHint + { + Behaviour = _isNewTerm ? AElfConsensusBehaviour.NextTerm : AElfConsensusBehaviour.NextRound + } + .ToByteString(), + ArrangedMiningTime = arrangedMiningTime, + MiningDueTime = arrangedMiningTime.AddMilliseconds(MiningInterval), + LimitMillisecondsOfMiningBlock = + _isNewTerm ? LastBlockOfCurrentTermMiningLimit : DefaultBlockMiningLimit + }; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TinyBlockCommandStrategy.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TinyBlockCommandStrategy.cs index ab2d32a5f0..8ce8f252bf 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TinyBlockCommandStrategy.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusCommandGeneration/Strategies/TinyBlockCommandStrategy.cs @@ -1,70 +1,65 @@ using System.Linq; -using AElf.Standards.ACS4; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public partial class AEDPoSContract { - // ReSharper disable once InconsistentNaming - public partial class AEDPoSContract + private class TinyBlockCommandStrategy : CommandStrategyBase { - private class TinyBlockCommandStrategy : CommandStrategyBase - { - private readonly int _maximumBlocksCount; + private readonly int _maximumBlocksCount; - public TinyBlockCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, - int maximumBlocksCount) : base( - currentRound, pubkey, currentBlockTime) - { - _maximumBlocksCount = maximumBlocksCount; - } + public TinyBlockCommandStrategy(Round currentRound, string pubkey, Timestamp currentBlockTime, + int maximumBlocksCount) : base( + currentRound, pubkey, currentBlockTime) + { + _maximumBlocksCount = maximumBlocksCount; + } - public override ConsensusCommand GetAEDPoSConsensusCommand() - { - // Provided pubkey can mine a block after TinyBlockMinimumInterval ms. - var arrangedMiningTime = - MiningTimeArrangingService.ArrangeMiningTimeWithOffset(CurrentBlockTime, - TinyBlockMinimumInterval); + public override ConsensusCommand GetAEDPoSConsensusCommand() + { + // Provided pubkey can mine a block after TinyBlockMinimumInterval ms. + var arrangedMiningTime = + MiningTimeArrangingService.ArrangeMiningTimeWithOffset(CurrentBlockTime, + TinyBlockMinimumInterval); - var roundStartTime = CurrentRound.GetRoundStartTime(); - var currentTimeSlotStartTime = CurrentBlockTime < roundStartTime - ? roundStartTime.AddMilliseconds(-MiningInterval) - : CurrentRound.RoundNumber == 1 - ? MinerInRound.ActualMiningTimes.First() - : MinerInRound.ExpectedMiningTime; - var currentTimeSlotEndTime = currentTimeSlotStartTime.AddMilliseconds(MiningInterval); + var roundStartTime = CurrentRound.GetRoundStartTime(); + var currentTimeSlotStartTime = CurrentBlockTime < roundStartTime + ? roundStartTime.AddMilliseconds(-MiningInterval) + : CurrentRound.RoundNumber == 1 + ? MinerInRound.ActualMiningTimes.First() + : MinerInRound.ExpectedMiningTime; + var currentTimeSlotEndTime = currentTimeSlotStartTime.AddMilliseconds(MiningInterval); - return arrangedMiningTime > currentTimeSlotEndTime - ? new TerminateRoundCommandStrategy(CurrentRound, Pubkey, CurrentBlockTime, false) - .GetAEDPoSConsensusCommand() // The arranged mining time already beyond the time slot. - : new ConsensusCommand - { - Hint = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.TinyBlock}.ToByteString(), - ArrangedMiningTime = arrangedMiningTime, - MiningDueTime = currentTimeSlotEndTime, - LimitMillisecondsOfMiningBlock = IsLastTinyBlockOfCurrentSlot() - ? LastTinyBlockMiningLimit - : DefaultBlockMiningLimit - }; - } + return arrangedMiningTime > currentTimeSlotEndTime + ? new TerminateRoundCommandStrategy(CurrentRound, Pubkey, CurrentBlockTime, false) + .GetAEDPoSConsensusCommand() // The arranged mining time already beyond the time slot. + : new ConsensusCommand + { + Hint = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.TinyBlock }.ToByteString(), + ArrangedMiningTime = arrangedMiningTime, + MiningDueTime = currentTimeSlotEndTime, + LimitMillisecondsOfMiningBlock = IsLastTinyBlockOfCurrentSlot() + ? LastTinyBlockMiningLimit + : DefaultBlockMiningLimit + }; + } - private bool IsLastTinyBlockOfCurrentSlot() - { - var producedBlocksOfCurrentRound = MinerInRound.ProducedTinyBlocks; - var roundStartTime = CurrentRound.GetRoundStartTime(); + private bool IsLastTinyBlockOfCurrentSlot() + { + var producedBlocksOfCurrentRound = MinerInRound.ProducedTinyBlocks; + var roundStartTime = CurrentRound.GetRoundStartTime(); - if (CurrentBlockTime < roundStartTime) - { - return producedBlocksOfCurrentRound == _maximumBlocksCount; - } + if (CurrentBlockTime < roundStartTime) return producedBlocksOfCurrentRound == _maximumBlocksCount; - var blocksBeforeCurrentRound = MinerInRound.ActualMiningTimes.Count(t => t < roundStartTime); - return producedBlocksOfCurrentRound == blocksBeforeCurrentRound.Add(_maximumBlocksCount); - } + var blocksBeforeCurrentRound = MinerInRound.ActualMiningTimes.Count(t => t < roundStartTime); + return producedBlocksOfCurrentRound == blocksBeforeCurrentRound.Add(_maximumBlocksCount); } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ConsensusValidationContext.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ConsensusValidationContext.cs index 0c3c935b05..19de3bef60 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ConsensusValidationContext.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ConsensusValidationContext.cs @@ -1,41 +1,41 @@ // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS + +namespace AElf.Contracts.Consensus.AEDPoS; + +/// +/// Useful data for validating consensus header information. +/// +public class ConsensusValidationContext { + public long CurrentTermNumber { get; set; } + public long CurrentRoundNumber { get; set; } + + /// + /// We can trust this because we already validated the pubkey + /// during `AEDPoSExtraDataExtractor.ExtractConsensusExtraData` + /// + public string SenderPubkey => ExtraData.SenderPubkey.ToHex(); + + /// + /// Round information fetch from StateDb. + /// + public Round BaseRound { get; set; } + + /// + /// Round information included in the consensus header extra data. + /// + public Round ProvidedRound => ExtraData.Round; + /// - /// Useful data for validating consensus header information. + /// Previous round information fetch from StateDb. /// - public class ConsensusValidationContext - { - public long CurrentTermNumber { get; set; } - public long CurrentRoundNumber { get; set; } - - /// - /// We can trust this because we already validated the pubkey - /// during `AEDPoSExtraDataExtractor.ExtractConsensusExtraData` - /// - public string SenderPubkey => ExtraData.SenderPubkey.ToHex(); - - /// - /// Round information fetch from StateDb. - /// - public Round BaseRound { get; set; } - - /// - /// Round information included in the consensus header extra data. - /// - public Round ProvidedRound => ExtraData.Round; - - /// - /// Previous round information fetch from StateDb. - /// - public Round PreviousRound { get; set; } - - /// - /// This filed is to prevent one miner produces too many continues blocks - /// (which may cause problems to other parts). - /// - public LatestPubkeyToTinyBlocksCount LatestPubkeyToTinyBlocksCount { get; set; } - - public AElfConsensusHeaderInformation ExtraData { get; set; } - } + public Round PreviousRound { get; set; } + + /// + /// This filed is to prevent one miner produces too many continues blocks + /// (which may cause problems to other parts). + /// + public LatestPubkeyToTinyBlocksCount LatestPubkeyToTinyBlocksCount { get; set; } + + public AElfConsensusHeaderInformation ExtraData { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ContinuousBlocksValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ContinuousBlocksValidationProvider.cs index e62b8c4c04..a4ab442b6e 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ContinuousBlocksValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/ContinuousBlocksValidationProvider.cs @@ -1,30 +1,29 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class ContinuousBlocksValidationProvider : IHeaderInformationValidationProvider { - public class ContinuousBlocksValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) - { - // Is sender produce too many continuous blocks? - var validationResult = new ValidationResult(); + // Is sender produce too many continuous blocks? + var validationResult = new ValidationResult(); - if (validationContext.ProvidedRound.RoundNumber > 2 && // Skip first two rounds. - validationContext.BaseRound.RealTimeMinersInformation.Count != 1) + if (validationContext.ProvidedRound.RoundNumber > 2 && // Skip first two rounds. + validationContext.BaseRound.RealTimeMinersInformation.Count != 1) + { + var latestPubkeyToTinyBlocksCount = validationContext.LatestPubkeyToTinyBlocksCount; + if (latestPubkeyToTinyBlocksCount != null && + latestPubkeyToTinyBlocksCount.Pubkey == validationContext.SenderPubkey && + latestPubkeyToTinyBlocksCount.BlocksCount < 0) { - var latestPubkeyToTinyBlocksCount = validationContext.LatestPubkeyToTinyBlocksCount; - if (latestPubkeyToTinyBlocksCount != null && - latestPubkeyToTinyBlocksCount.Pubkey == validationContext.SenderPubkey && - latestPubkeyToTinyBlocksCount.BlocksCount < 0) - { - validationResult.Message = "Sender produced too many continuous blocks."; - return validationResult; - } + validationResult.Message = "Sender produced too many continuous blocks."; + return validationResult; } - - validationResult.Success = true; - return validationResult; } + + validationResult.Success = true; + return validationResult; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/IHeaderInformationValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/IHeaderInformationValidationProvider.cs index 47264a4e43..1f17159952 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/IHeaderInformationValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/IHeaderInformationValidationProvider.cs @@ -1,10 +1,9 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public interface IHeaderInformationValidationProvider { - public interface IHeaderInformationValidationProvider - { - ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext); - } + ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext); } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/LibInformationValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/LibInformationValidationProvider.cs index a567b87f23..0423a3652f 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/LibInformationValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/LibInformationValidationProvider.cs @@ -1,36 +1,35 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class LibInformationValidationProvider : IHeaderInformationValidationProvider { - public class LibInformationValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) + var validationResult = new ValidationResult(); + var baseRound = validationContext.BaseRound; + var providedRound = validationContext.ProvidedRound; + var pubkey = validationContext.SenderPubkey; + if (providedRound.ConfirmedIrreversibleBlockHeight != 0 && + providedRound.ConfirmedIrreversibleBlockRoundNumber != 0 && + (baseRound.ConfirmedIrreversibleBlockHeight > providedRound.ConfirmedIrreversibleBlockHeight || + baseRound.ConfirmedIrreversibleBlockRoundNumber > providedRound.ConfirmedIrreversibleBlockRoundNumber)) { - var validationResult = new ValidationResult(); - var baseRound = validationContext.BaseRound; - var providedRound = validationContext.ProvidedRound; - var pubkey = validationContext.SenderPubkey; - if (providedRound.ConfirmedIrreversibleBlockHeight != 0 && - providedRound.ConfirmedIrreversibleBlockRoundNumber != 0 && - (baseRound.ConfirmedIrreversibleBlockHeight > providedRound.ConfirmedIrreversibleBlockHeight || - baseRound.ConfirmedIrreversibleBlockRoundNumber > providedRound.ConfirmedIrreversibleBlockRoundNumber)) - { - validationResult.Message = "Incorrect lib information."; - return validationResult; - } - - if (providedRound.RealTimeMinersInformation.ContainsKey(pubkey) && - providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight != 0 && - baseRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight > - providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight) - { - validationResult.Message = "Incorrect implied lib height."; - return validationResult; - } + validationResult.Message = "Incorrect lib information."; + return validationResult; + } - validationResult.Success = true; + if (providedRound.RealTimeMinersInformation.ContainsKey(pubkey) && + providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight != 0 && + baseRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight > + providedRound.RealTimeMinersInformation[pubkey].ImpliedIrreversibleBlockHeight) + { + validationResult.Message = "Incorrect implied lib height."; return validationResult; } + + validationResult.Success = true; + return validationResult; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/MiningPermissionValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/MiningPermissionValidationProvider.cs index c81c5390b0..61c5249ce7 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/MiningPermissionValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/MiningPermissionValidationProvider.cs @@ -1,27 +1,26 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class MiningPermissionValidationProvider : IHeaderInformationValidationProvider { - public class MiningPermissionValidationProvider : IHeaderInformationValidationProvider + /// + /// This validation will based on current round information stored in StateDb. + /// Simply check keys of RealTimeMinersInformation should be enough. + /// + /// + /// + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - /// - /// This validation will based on current round information stored in StateDb. - /// Simply check keys of RealTimeMinersInformation should be enough. - /// - /// - /// - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) + var validationResult = new ValidationResult(); + if (!validationContext.BaseRound.RealTimeMinersInformation.Keys.Contains(validationContext.SenderPubkey)) { - var validationResult = new ValidationResult(); - if (!validationContext.BaseRound.RealTimeMinersInformation.Keys.Contains(validationContext.SenderPubkey)) - { - validationResult.Message = $"Sender {validationContext.SenderPubkey} is not a miner."; - return validationResult; - } - - validationResult.Success = true; + validationResult.Message = $"Sender {validationContext.SenderPubkey} is not a miner."; return validationResult; } + + validationResult.Success = true; + return validationResult; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/NextRoundMiningOrderValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/NextRoundMiningOrderValidationProvider.cs index c8de718af6..c8dfcf1590 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/NextRoundMiningOrderValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/NextRoundMiningOrderValidationProvider.cs @@ -2,26 +2,25 @@ using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class NextRoundMiningOrderValidationProvider : IHeaderInformationValidationProvider { - public class NextRoundMiningOrderValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) + // Miners that have determined the order of the next round should be equal to + // miners that mined blocks during current round. + var validationResult = new ValidationResult(); + var providedRound = validationContext.ProvidedRound; + var distinctCount = providedRound.RealTimeMinersInformation.Values.Where(m => m.FinalOrderOfNextRound > 0) + .Distinct().Count(); + if (distinctCount != providedRound.RealTimeMinersInformation.Values.Count(m => m.OutValue != null)) { - // Miners that have determined the order of the next round should be equal to - // miners that mined blocks during current round. - var validationResult = new ValidationResult(); - var providedRound = validationContext.ProvidedRound; - var distinctCount = providedRound.RealTimeMinersInformation.Values.Where(m => m.FinalOrderOfNextRound > 0) - .Distinct().Count(); - if (distinctCount != providedRound.RealTimeMinersInformation.Values.Count(m => m.OutValue != null)) - { - validationResult.Message = "Invalid FinalOrderOfNextRound."; - return validationResult; - } - - validationResult.Success = true; + validationResult.Message = "Invalid FinalOrderOfNextRound."; return validationResult; } + + validationResult.Success = true; + return validationResult; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/RoundTerminateValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/RoundTerminateValidationProvider.cs index 77c6ef08b9..fb5be90bda 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/RoundTerminateValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/RoundTerminateValidationProvider.cs @@ -1,63 +1,48 @@ -using AElf.Standards.ACS4; -using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; -using AElf.Types; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class RoundTerminateValidationProvider : IHeaderInformationValidationProvider { - public class RoundTerminateValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) - { - var validationResult = new ValidationResult(); - var extraData = validationContext.ExtraData; - if (extraData.Behaviour == AElfConsensusBehaviour.NextRound) - { - return ValidationForNextRound(validationContext); - } - - if (extraData.Behaviour == AElfConsensusBehaviour.NextTerm) - { - return ValidationForNextTerm(validationContext); - } - - validationResult.Success = true; - return validationResult; - } - - private ValidationResult ValidationForNextRound(ConsensusValidationContext validationContext) - { - // Is next round information correct? - // Currently two aspects: - // Round Number - // In Values Should Be Null - var extraData = validationContext.ExtraData; - if (validationContext.BaseRound.RoundNumber.Add(1) != extraData.Round.RoundNumber) - { - return new ValidationResult {Message = "Incorrect round number for next round."}; - } - - return extraData.Round.RealTimeMinersInformation.Values.Any(m => m.InValue != null) - ? new ValidationResult {Message = "Incorrect next round information."} - : new ValidationResult {Success = true}; - } - - private ValidationResult ValidationForNextTerm(ConsensusValidationContext validationContext) - { - var extraData = validationContext.ExtraData; - var validationResult = ValidationForNextRound(validationContext); - if (!validationResult.Success) - { - return validationResult; - } - - // Is next term number correct? - return validationContext.BaseRound.TermNumber.Add(1) != extraData.Round.TermNumber - ? new ValidationResult {Message = "Incorrect term number for next round."} - : new ValidationResult {Success = true}; - } + var validationResult = new ValidationResult(); + var extraData = validationContext.ExtraData; + if (extraData.Behaviour == AElfConsensusBehaviour.NextRound) return ValidationForNextRound(validationContext); + + if (extraData.Behaviour == AElfConsensusBehaviour.NextTerm) return ValidationForNextTerm(validationContext); + + validationResult.Success = true; + return validationResult; + } + + private ValidationResult ValidationForNextRound(ConsensusValidationContext validationContext) + { + // Is next round information correct? + // Currently two aspects: + // Round Number + // In Values Should Be Null + var extraData = validationContext.ExtraData; + if (validationContext.BaseRound.RoundNumber.Add(1) != extraData.Round.RoundNumber) + return new ValidationResult { Message = "Incorrect round number for next round." }; + + return extraData.Round.RealTimeMinersInformation.Values.Any(m => m.InValue != null) + ? new ValidationResult { Message = "Incorrect next round information." } + : new ValidationResult { Success = true }; + } + + private ValidationResult ValidationForNextTerm(ConsensusValidationContext validationContext) + { + var extraData = validationContext.ExtraData; + var validationResult = ValidationForNextRound(validationContext); + if (!validationResult.Success) return validationResult; + + // Is next term number correct? + return validationContext.BaseRound.TermNumber.Add(1) != extraData.Round.TermNumber + ? new ValidationResult { Message = "Incorrect term number for next round." } + : new ValidationResult { Success = true }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/TimeSlotValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/TimeSlotValidationProvider.cs index df97acc808..c5e4e723c7 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/TimeSlotValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/TimeSlotValidationProvider.cs @@ -1,65 +1,59 @@ using System.Linq; -using AElf.Standards.ACS4; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class TimeSlotValidationProvider : IHeaderInformationValidationProvider { - public class TimeSlotValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) + var validationResult = new ValidationResult(); + // If provided round is a new round + if (validationContext.ProvidedRound.RoundId != validationContext.BaseRound.RoundId) { - var validationResult = new ValidationResult(); - // If provided round is a new round - if (validationContext.ProvidedRound.RoundId != validationContext.BaseRound.RoundId) - { - // Is new round information fits time slot rule? - validationResult = validationContext.ProvidedRound.CheckRoundTimeSlots(); - if (!validationResult.Success) - { - return validationResult; - } - } - else - { - // Is sender respect his time slot? - // It is maybe failing due to using too much time producing previous tiny blocks. - if (!CheckMinerTimeSlot(validationContext)) - { - validationResult.Message = $"Time slot already passed before execution.{validationContext.SenderPubkey}"; - validationResult.IsReTrigger = true; - return validationResult; - } - } - - validationResult.Success = true; - return validationResult; + // Is new round information fits time slot rule? + validationResult = validationContext.ProvidedRound.CheckRoundTimeSlots(); + if (!validationResult.Success) return validationResult; } - - private bool CheckMinerTimeSlot(ConsensusValidationContext validationContext) + else { - if (IsFirstRoundOfCurrentTerm(out _, validationContext)) return true; - var minerInRound = validationContext.BaseRound.RealTimeMinersInformation[validationContext.SenderPubkey]; - var latestActualMiningTime = minerInRound.ActualMiningTimes.OrderBy(t => t).LastOrDefault(); - if (latestActualMiningTime == null) return true; - var expectedMiningTime = minerInRound.ExpectedMiningTime; - var endOfExpectedTimeSlot = - expectedMiningTime.AddMilliseconds(validationContext.BaseRound.GetMiningInterval()); - if (latestActualMiningTime < expectedMiningTime) + // Is sender respect his time slot? + // It is maybe failing due to using too much time producing previous tiny blocks. + if (!CheckMinerTimeSlot(validationContext)) { - // Which means this miner is producing tiny blocks for previous extra block slot. - return latestActualMiningTime < validationContext.BaseRound.GetRoundStartTime(); + validationResult.Message = + $"Time slot already passed before execution.{validationContext.SenderPubkey}"; + validationResult.IsReTrigger = true; + return validationResult; } - - return latestActualMiningTime < endOfExpectedTimeSlot; } - private bool IsFirstRoundOfCurrentTerm(out long termNumber, ConsensusValidationContext validationContext) - { - termNumber = validationContext.CurrentTermNumber; - return validationContext.PreviousRound.TermNumber != termNumber || - validationContext.CurrentRoundNumber == 1; - } + validationResult.Success = true; + return validationResult; + } + + private bool CheckMinerTimeSlot(ConsensusValidationContext validationContext) + { + if (IsFirstRoundOfCurrentTerm(out _, validationContext)) return true; + var minerInRound = validationContext.BaseRound.RealTimeMinersInformation[validationContext.SenderPubkey]; + var latestActualMiningTime = minerInRound.ActualMiningTimes.OrderBy(t => t).LastOrDefault(); + if (latestActualMiningTime == null) return true; + var expectedMiningTime = minerInRound.ExpectedMiningTime; + var endOfExpectedTimeSlot = + expectedMiningTime.AddMilliseconds(validationContext.BaseRound.GetMiningInterval()); + if (latestActualMiningTime < expectedMiningTime) + // Which means this miner is producing tiny blocks for previous extra block slot. + return latestActualMiningTime < validationContext.BaseRound.GetRoundStartTime(); + + return latestActualMiningTime < endOfExpectedTimeSlot; + } + + private bool IsFirstRoundOfCurrentTerm(out long termNumber, ConsensusValidationContext validationContext) + { + termNumber = validationContext.CurrentTermNumber; + return validationContext.PreviousRound.TermNumber != termNumber || + validationContext.CurrentRoundNumber == 1; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/UpdateValueValidationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/UpdateValueValidationProvider.cs index 842e5cadd0..15fb76dcda 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/UpdateValueValidationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ConsensusHeaderInfoValidationProviders/UpdateValueValidationProvider.cs @@ -1,57 +1,50 @@ -using System.Collections.Generic; using System.Linq; using AElf.Standards.ACS4; -using AElf.Sdk.CSharp; using AElf.Types; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class UpdateValueValidationProvider : IHeaderInformationValidationProvider { - public class UpdateValueValidationProvider : IHeaderInformationValidationProvider + public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) { - public ValidationResult ValidateHeaderInformation(ConsensusValidationContext validationContext) - { - // Only one Out Value should be filled. - if (!NewConsensusInformationFilled(validationContext)) - { - return new ValidationResult {Message = "Incorrect new Out Value."}; - } - - if (!ValidatePreviousInValue(validationContext)) - { - return new ValidationResult {Message = "Incorrect previous in value."}; - } - - return new ValidationResult {Success = true}; - } - - /// - /// Check only one Out Value was filled during this updating. - /// - /// - /// - private bool NewConsensusInformationFilled(ConsensusValidationContext validationContext) - { - var minerInRound = - validationContext.ProvidedRound.RealTimeMinersInformation[validationContext.SenderPubkey]; - return minerInRound.OutValue != null && minerInRound.Signature != null && - minerInRound.OutValue.Value.Any() && minerInRound.Signature.Value.Any(); - } - - private bool ValidatePreviousInValue(ConsensusValidationContext validationContext) - { - var extraData = validationContext.ExtraData; - var publicKey = validationContext.SenderPubkey; - - if (!validationContext.PreviousRound.RealTimeMinersInformation.ContainsKey(publicKey)) return true; - - if (extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue == null) return true; - - var previousOutValue = validationContext.PreviousRound.RealTimeMinersInformation[publicKey].OutValue; - var previousInValue = extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue; - if (previousInValue == Hash.Empty) return true; - - return HashHelper.ComputeFrom(previousInValue) == previousOutValue; - } + // Only one Out Value should be filled. + if (!NewConsensusInformationFilled(validationContext)) + return new ValidationResult { Message = "Incorrect new Out Value." }; + + if (!ValidatePreviousInValue(validationContext)) + return new ValidationResult { Message = "Incorrect previous in value." }; + + return new ValidationResult { Success = true }; + } + + /// + /// Check only one Out Value was filled during this updating. + /// + /// + /// + private bool NewConsensusInformationFilled(ConsensusValidationContext validationContext) + { + var minerInRound = + validationContext.ProvidedRound.RealTimeMinersInformation[validationContext.SenderPubkey]; + return minerInRound.OutValue != null && minerInRound.Signature != null && + minerInRound.OutValue.Value.Any() && minerInRound.Signature.Value.Any(); + } + + private bool ValidatePreviousInValue(ConsensusValidationContext validationContext) + { + var extraData = validationContext.ExtraData; + var publicKey = validationContext.SenderPubkey; + + if (!validationContext.PreviousRound.RealTimeMinersInformation.ContainsKey(publicKey)) return true; + + if (extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue == null) return true; + + var previousOutValue = validationContext.PreviousRound.RealTimeMinersInformation[publicKey].OutValue; + var previousInValue = extraData.Round.RealTimeMinersInformation[publicKey].PreviousInValue; + if (previousInValue == Hash.Empty) return true; + + return HashHelper.ComputeFrom(previousInValue) == previousOutValue; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/ContractsReferences.cs b/contract/AElf.Contracts.Consensus.AEDPoS/ContractsReferences.cs index 37ab6c445c..48852984c8 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/ContractsReferences.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/ContractsReferences.cs @@ -4,16 +4,15 @@ using AElf.Contracts.TokenHolder; using AElf.Contracts.Treasury; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +// ReSharper disable UnusedAutoPropertyAccessor.Global +public partial class AEDPoSContractState { - // ReSharper disable once InconsistentNaming - // ReSharper disable UnusedAutoPropertyAccessor.Global - public partial class AEDPoSContractState - { - internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } - internal TreasuryContractImplContainer.TreasuryContractImplReferenceState TreasuryContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal TokenHolderContractContainer.TokenHolderContractReferenceState TokenHolderContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } + internal TreasuryContractImplContainer.TreasuryContractImplReferenceState TreasuryContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal TokenHolderContractContainer.TokenHolderContractReferenceState TokenHolderContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/README.md b/contract/AElf.Contracts.Consensus.AEDPoS/README.md index 2f948ae1f9..bc8ca90077 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/README.md +++ b/contract/AElf.Contracts.Consensus.AEDPoS/README.md @@ -16,7 +16,8 @@ Basically initial miners list are hard coded to `Genesis Block`. Initial miners will be replaced as soon as we have enough voted miners. -Miners will be changed according to the amount of votes they obtained every time our Main Chain turn to next term, like every 7 days. +Miners will be changed according to the amount of votes they obtained every time our Main Chain turn to next term, like +every 7 days. Miners count will be changed every year. @@ -26,4 +27,5 @@ Send a transaction of `AnnounceElection` to `Election Contract`, this will lock ### Vote to candidates -Voters can send a transaction of `Vote` to `Election Contract` voting for any registered candidate, this will lock a certain amount a ELF tokens of this voter, and transfer `VOTE` token to him from `Election Contract`. +Voters can send a transaction of `Vote` to `Election Contract` voting for any registered candidate, this will lock a +certain amount a ELF tokens of this voter, and transfer `VOTE` token to him from `Election Contract`. diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/MinerList.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/MinerList.cs index d3a09efb7f..63cec72d06 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/MinerList.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/MinerList.cs @@ -5,55 +5,51 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class MinerList { - public partial class MinerList + internal Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - internal Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds(i.Mul(miningInterval).Add(miningInterval)); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber.Add(1); - round.TermNumber = currentTermNumber.Add(1); - round.IsMinerListJustChanged = true; - - return round; - } + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - internal Round GenerateFirstRoundOfNewTerm(int miningInterval, Timestamp currentBlockTime, Round currentRound) + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var round = GenerateFirstRoundOfNewTerm(miningInterval, currentBlockTime, currentRound.RoundNumber, - currentRound.TermNumber); - round.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; - round.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i.Mul(miningInterval).Add(miningInterval)); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber.Add(1); + round.TermNumber = currentTermNumber.Add(1); + round.IsMinerListJustChanged = true; + + return round; + } + + internal Round GenerateFirstRoundOfNewTerm(int miningInterval, Timestamp currentBlockTime, Round currentRound) + { + var round = GenerateFirstRoundOfNewTerm(miningInterval, currentBlockTime, currentRound.RoundNumber, + currentRound.TermNumber); + round.ConfirmedIrreversibleBlockHeight = currentRound.ConfirmedIrreversibleBlockHeight; + round.ConfirmedIrreversibleBlockRoundNumber = currentRound.ConfirmedIrreversibleBlockRoundNumber; + return round; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round.cs index dd3494ceb3..b062d408e9 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round.cs @@ -1,270 +1,249 @@ using System; using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS4; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Standards.ACS4; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + public long RoundId { - public long RoundId + get { - get - { - if (RealTimeMinersInformation.Values.All(bpInfo => bpInfo.ExpectedMiningTime != null)) - { - return RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); - } - - return RoundIdForValidation; - } + if (RealTimeMinersInformation.Values.All(bpInfo => bpInfo.ExpectedMiningTime != null)) + return RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + + return RoundIdForValidation; } + } - public bool IsEmpty => RoundId == 0; + public bool IsEmpty => RoundId == 0; - /// - /// Check the equality of time slots of miners. - /// Also, the mining interval shouldn't be 0. - /// - /// - public ValidationResult CheckRoundTimeSlots() - { - var miners = RealTimeMinersInformation.Values.OrderBy(m => m.Order).ToList(); - if (miners.Count == 1) - { - // No need to check single node. - return new ValidationResult {Success = true}; - } - - if (miners.Any(m => m.ExpectedMiningTime == null)) - { - return new ValidationResult {Message = $"Incorrect expected mining time.\n{this}"}; - } - - var baseMiningInterval = - (miners[1].ExpectedMiningTime - miners[0].ExpectedMiningTime).Milliseconds(); - - if (baseMiningInterval <= 0) - { - return new ValidationResult {Message = $"Mining interval must greater than 0.\n{this}"}; - } - - for (var i = 1; i < miners.Count - 1; i++) - { - var miningInterval = - (miners[i + 1].ExpectedMiningTime - miners[i].ExpectedMiningTime).Milliseconds(); - if (Math.Abs(miningInterval - baseMiningInterval) > baseMiningInterval) - { - return new ValidationResult {Message = "Time slots are so different."}; - } - } - - return new ValidationResult {Success = true}; - } + /// + /// Check the equality of time slots of miners. + /// Also, the mining interval shouldn't be 0. + /// + /// + public ValidationResult CheckRoundTimeSlots() + { + var miners = RealTimeMinersInformation.Values.OrderBy(m => m.Order).ToList(); + if (miners.Count == 1) + // No need to check single node. + return new ValidationResult { Success = true }; + + if (miners.Any(m => m.ExpectedMiningTime == null)) + return new ValidationResult { Message = $"Incorrect expected mining time.\n{this}" }; + + var baseMiningInterval = + (miners[1].ExpectedMiningTime - miners[0].ExpectedMiningTime).Milliseconds(); + + if (baseMiningInterval <= 0) + return new ValidationResult { Message = $"Mining interval must greater than 0.\n{this}" }; - public Hash GetHash(bool isContainPreviousInValue = true) + for (var i = 1; i < miners.Count - 1; i++) { - return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); + var miningInterval = + (miners[i + 1].ExpectedMiningTime - miners[i].ExpectedMiningTime).Milliseconds(); + if (Math.Abs(miningInterval - baseMiningInterval) > baseMiningInterval) + return new ValidationResult { Message = "Time slots are so different." }; } - /// - /// For multiple miners, return the length every mining time slot (which should be equal). - /// For single miner, return 4000 ms. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } + return new ValidationResult { Success = true }; + } - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); + public Hash GetHash(bool isContainPreviousInValue = true) + { + return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); + } - return Math.Abs((int) (firstTwoMiners[1].ExpectedMiningTime - firstTwoMiners[0].ExpectedMiningTime) - .Milliseconds()); - } + /// + /// For multiple miners, return the length every mining time slot (which should be equal). + /// For single miner, return 4000 ms. + /// + /// + public int GetMiningInterval() + { + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; - public bool IsTimeSlotPassed(string publicKey, Timestamp currentBlockTime) - { - var miningInterval = GetMiningInterval(); - if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; - var minerInRound = RealTimeMinersInformation[publicKey]; - if (RoundNumber != 1) - { - return minerInRound.ExpectedMiningTime + new Duration {Seconds = miningInterval.Div(1000)} < - currentBlockTime; - } - - var actualStartTimes = FirstMiner().ActualMiningTimes; - if (actualStartTimes.Count == 0) - { - return false; - } - - var actualStartTime = actualStartTimes.First(); - var runningTime = currentBlockTime - actualStartTime; - var expectedOrder = runningTime.Seconds.Div(miningInterval.Div(1000)).Add(1); - return minerInRound.Order < expectedOrder; - } + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); - /// - /// Actually the expected mining time of the miner whose order is 1. - /// - /// - public Timestamp GetRoundStartTime() - { - return FirstMiner().ExpectedMiningTime; - } + return Math.Abs((int)(firstTwoMiners[1].ExpectedMiningTime - firstTwoMiners[0].ExpectedMiningTime) + .Milliseconds()); + } - public Hash CalculateSignature(Hash inValue) - { - return HashHelper.XorAndCompute(inValue, - RealTimeMinersInformation.Values.Aggregate(Hash.Empty, - (current, minerInRound) => HashHelper.XorAndCompute(current, minerInRound.Signature))); - } + public bool IsTimeSlotPassed(string publicKey, Timestamp currentBlockTime) + { + var miningInterval = GetMiningInterval(); + if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; + var minerInRound = RealTimeMinersInformation[publicKey]; + if (RoundNumber != 1) + return minerInRound.ExpectedMiningTime + new Duration { Seconds = miningInterval.Div(1000) } < + currentBlockTime; + + var actualStartTimes = FirstMiner().ActualMiningTimes; + if (actualStartTimes.Count == 0) return false; + + var actualStartTime = actualStartTimes.First(); + var runningTime = currentBlockTime - actualStartTime; + var expectedOrder = runningTime.Seconds.Div(miningInterval.Div(1000)).Add(1); + return minerInRound.Order < expectedOrder; + } - public Timestamp GetExtraBlockMiningTime() - { - return RealTimeMinersInformation.OrderBy(m => m.Value.Order).Last().Value - .ExpectedMiningTime - .AddMilliseconds(GetMiningInterval()); - } + /// + /// Actually the expected mining time of the miner whose order is 1. + /// + /// + public Timestamp GetRoundStartTime() + { + return FirstMiner().ExpectedMiningTime; + } - public long GetMinedBlocks() - { - return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); - } + public Hash CalculateSignature(Hash inValue) + { + return HashHelper.XorAndCompute(inValue, + RealTimeMinersInformation.Values.Aggregate(Hash.Empty, + (current, minerInRound) => HashHelper.XorAndCompute(current, minerInRound.Signature))); + } - public MinerList GetMinerList() - { - return new MinerList - { - Pubkeys = {RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString)} - }; - } + public Timestamp GetExtraBlockMiningTime() + { + return RealTimeMinersInformation.OrderBy(m => m.Value.Order).Last().Value + .ExpectedMiningTime + .AddMilliseconds(GetMiningInterval()); + } - public bool IsInMinerList(string pubkey) - { - return RealTimeMinersInformation.Keys.Contains(pubkey); - } + public long GetMinedBlocks() + { + return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); + } - public MinerInRound FirstMiner() + public MinerList GetMinerList() + { + return new MinerList { - return RealTimeMinersInformation.Count > 0 - ? RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == 1) - // Unlikely. - : new MinerInRound(); - } + Pubkeys = { RealTimeMinersInformation.Keys.Select(ByteStringHelper.FromHexString) } + }; + } - public MinerInRound FirstActualMiner() - { - return RealTimeMinersInformation.Count > 0 - ? RealTimeMinersInformation.Values.FirstOrDefault(m => m.OutValue != null) - : null; - } + public bool IsInMinerList(string pubkey) + { + return RealTimeMinersInformation.Keys.Contains(pubkey); + } - public Timestamp GetExpectedMiningTime(string publicKey) - { - return RealTimeMinersInformation.ContainsKey(publicKey) - ? RealTimeMinersInformation[publicKey].ExpectedMiningTime - : new Timestamp {Seconds = long.MaxValue}; - } + public MinerInRound FirstMiner() + { + return RealTimeMinersInformation.Count > 0 + ? RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == 1) + // Unlikely. + : new MinerInRound(); + } - /// - /// Get miner's order of provided round information. - /// If provided round doesn't contain this pubkey, return int.MaxValue. - /// - /// - /// - public int GetMiningOrder(string pubkey) - { - return RealTimeMinersInformation.ContainsKey(pubkey) - ? RealTimeMinersInformation[pubkey].Order - : int.MaxValue; - } + public MinerInRound FirstActualMiner() + { + return RealTimeMinersInformation.Count > 0 + ? RealTimeMinersInformation.Values.FirstOrDefault(m => m.OutValue != null) + : null; + } - public bool TryToDetectEvilMiners(out List evilMiners) - { - evilMiners = RealTimeMinersInformation.Values - .Where(m => m.MissedTimeSlots >= AEDPoSContractConstants.TolerableMissedTimeSlotsCount) - .Select(m => m.Pubkey).ToList(); - return evilMiners.Count > 0; - } + public Timestamp GetExpectedMiningTime(string publicKey) + { + return RealTimeMinersInformation.ContainsKey(publicKey) + ? RealTimeMinersInformation[publicKey].ExpectedMiningTime + : new Timestamp { Seconds = long.MaxValue }; + } - private byte[] GetCheckableRound(bool isContainPreviousInValue = true) - { - var minersInformation = new Dictionary(); - foreach (var minerInRound in RealTimeMinersInformation.Clone()) - { - var checkableMinerInRound = minerInRound.Value.Clone(); - checkableMinerInRound.EncryptedPieces.Clear(); - checkableMinerInRound.DecryptedPieces.Clear(); - checkableMinerInRound.ActualMiningTimes.Clear(); - if (!isContainPreviousInValue) - { - checkableMinerInRound.PreviousInValue = Hash.Empty; - } - - minersInformation.Add(minerInRound.Key, checkableMinerInRound); - } - - var checkableRound = new Round - { - RoundNumber = RoundNumber, - TermNumber = TermNumber, - RealTimeMinersInformation = {minersInformation}, - BlockchainAge = BlockchainAge - }; - return checkableRound.ToByteArray(); - } + /// + /// Get miner's order of provided round information. + /// If provided round doesn't contain this pubkey, return int.MaxValue. + /// + /// + /// + public int GetMiningOrder(string pubkey) + { + return RealTimeMinersInformation.ContainsKey(pubkey) + ? RealTimeMinersInformation[pubkey].Order + : int.MaxValue; + } - /// - /// Change term if two thirds of miners latest ActualMiningTime meets threshold of changing term. - /// - /// - /// - /// - /// - public bool NeedToChangeTerm(Timestamp blockchainStartTimestamp, long currentTermNumber, long periodSeconds) - { - return RealTimeMinersInformation.Values - .Where(m => m.ActualMiningTimes.Any()) - .Select(m => m.ActualMiningTimes.Last()) - .Count(t => IsTimeToChangeTerm(blockchainStartTimestamp, - t, currentTermNumber, periodSeconds)) - >= MinersCountOfConsent; - } + public bool TryToDetectEvilMiners(out List evilMiners) + { + evilMiners = RealTimeMinersInformation.Values + .Where(m => m.MissedTimeSlots >= AEDPoSContractConstants.TolerableMissedTimeSlotsCount) + .Select(m => m.Pubkey).ToList(); + return evilMiners.Count > 0; + } - /// - /// If periodSeconds == 7: - /// 1, 1, 1 => 0 != 1 - 1 => false - /// 1, 2, 1 => 0 != 1 - 1 => false - /// 1, 8, 1 => 1 != 1 - 1 => true => term number will be 2 - /// 1, 9, 2 => 1 != 2 - 1 => false - /// 1, 15, 2 => 2 != 2 - 1 => true => term number will be 3. - /// - /// - /// - /// - /// - /// - private static bool IsTimeToChangeTerm(Timestamp blockchainStartTimestamp, Timestamp blockProducedTimestamp, - long termNumber, long periodSeconds) + private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + { + var minersInformation = new Dictionary(); + foreach (var minerInRound in RealTimeMinersInformation.Clone()) { - return (blockProducedTimestamp - blockchainStartTimestamp).Seconds.Div(periodSeconds) != termNumber - 1; + var checkableMinerInRound = minerInRound.Value.Clone(); + checkableMinerInRound.EncryptedPieces.Clear(); + checkableMinerInRound.DecryptedPieces.Clear(); + checkableMinerInRound.ActualMiningTimes.Clear(); + if (!isContainPreviousInValue) checkableMinerInRound.PreviousInValue = Hash.Empty; + + minersInformation.Add(minerInRound.Key, checkableMinerInRound); } - private static int GetAbsModulus(long longValue, int intValue) + var checkableRound = new Round { - return (int) Math.Abs(longValue % intValue); - } + RoundNumber = RoundNumber, + TermNumber = TermNumber, + RealTimeMinersInformation = { minersInformation }, + BlockchainAge = BlockchainAge + }; + return checkableRound.ToByteArray(); + } + + /// + /// Change term if two thirds of miners latest ActualMiningTime meets threshold of changing term. + /// + /// + /// + /// + /// + public bool NeedToChangeTerm(Timestamp blockchainStartTimestamp, long currentTermNumber, long periodSeconds) + { + return RealTimeMinersInformation.Values + .Where(m => m.ActualMiningTimes.Any()) + .Select(m => m.ActualMiningTimes.Last()) + .Count(t => IsTimeToChangeTerm(blockchainStartTimestamp, + t, currentTermNumber, periodSeconds)) + >= MinersCountOfConsent; + } + + /// + /// If periodSeconds == 7: + /// 1, 1, 1 => 0 != 1 - 1 => false + /// 1, 2, 1 => 0 != 1 - 1 => false + /// 1, 8, 1 => 1 != 1 - 1 => true => term number will be 2 + /// 1, 9, 2 => 1 != 2 - 1 => false + /// 1, 15, 2 => 2 != 2 - 1 => true => term number will be 3. + /// + /// + /// + /// + /// + /// + private static bool IsTimeToChangeTerm(Timestamp blockchainStartTimestamp, Timestamp blockProducedTimestamp, + long termNumber, long periodSeconds) + { + return (blockProducedTimestamp - blockchainStartTimestamp).Seconds.Div(periodSeconds) != termNumber - 1; + } + + private static int GetAbsModulus(long longValue, int intValue) + { + return (int)Math.Abs(longValue % intValue); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ApplyNormalConsensusData.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ApplyNormalConsensusData.cs index 0c049bec89..332e5b04b0 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ApplyNormalConsensusData.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ApplyNormalConsensusData.cs @@ -1,56 +1,48 @@ using System.Linq; using AElf.Types; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + public Round ApplyNormalConsensusData(string pubkey, Hash previousInValue, Hash outValue, Hash signature) { - public Round ApplyNormalConsensusData(string pubkey, Hash previousInValue, Hash outValue, Hash signature) - { - if (!RealTimeMinersInformation.ContainsKey(pubkey)) - { - return this; - } + if (!RealTimeMinersInformation.ContainsKey(pubkey)) return this; - RealTimeMinersInformation[pubkey].OutValue = outValue; - RealTimeMinersInformation[pubkey].Signature = signature; - if (RealTimeMinersInformation[pubkey].PreviousInValue == Hash.Empty || - RealTimeMinersInformation[pubkey].PreviousInValue == null) - { - RealTimeMinersInformation[pubkey].PreviousInValue = previousInValue; - } + RealTimeMinersInformation[pubkey].OutValue = outValue; + RealTimeMinersInformation[pubkey].Signature = signature; + if (RealTimeMinersInformation[pubkey].PreviousInValue == Hash.Empty || + RealTimeMinersInformation[pubkey].PreviousInValue == null) + RealTimeMinersInformation[pubkey].PreviousInValue = previousInValue; - var minersCount = RealTimeMinersInformation.Count; - var sigNum = signature.ToInt64(); + var minersCount = RealTimeMinersInformation.Count; + var sigNum = signature.ToInt64(); - var supposedOrderOfNextRound = GetAbsModulus(sigNum, minersCount) + 1; + var supposedOrderOfNextRound = GetAbsModulus(sigNum, minersCount) + 1; - // Check the existence of conflicts about OrderOfNextRound. - // If so, modify others'. - var conflicts = RealTimeMinersInformation.Values - .Where(i => i.FinalOrderOfNextRound == supposedOrderOfNextRound).ToList(); + // Check the existence of conflicts about OrderOfNextRound. + // If so, modify others'. + var conflicts = RealTimeMinersInformation.Values + .Where(i => i.FinalOrderOfNextRound == supposedOrderOfNextRound).ToList(); - foreach (var orderConflictedMiner in conflicts) - { - // Multiple conflicts is unlikely. + foreach (var orderConflictedMiner in conflicts) + // Multiple conflicts is unlikely. - for (var i = supposedOrderOfNextRound + 1; i < minersCount * 2; i++) + for (var i = supposedOrderOfNextRound + 1; i < minersCount * 2; i++) + { + var maybeNewOrder = i > minersCount ? i % minersCount : i; + if (RealTimeMinersInformation.Values.All(m => m.FinalOrderOfNextRound != maybeNewOrder)) { - var maybeNewOrder = i > minersCount ? i % minersCount : i; - if (RealTimeMinersInformation.Values.All(m => m.FinalOrderOfNextRound != maybeNewOrder)) - { - RealTimeMinersInformation[orderConflictedMiner.Pubkey].FinalOrderOfNextRound = - maybeNewOrder; - break; - } + RealTimeMinersInformation[orderConflictedMiner.Pubkey].FinalOrderOfNextRound = + maybeNewOrder; + break; } } - RealTimeMinersInformation[pubkey].SupposedOrderOfNextRound = supposedOrderOfNextRound; - // Initialize FinalOrderOfNextRound as the value of SupposedOrderOfNextRound - RealTimeMinersInformation[pubkey].FinalOrderOfNextRound = supposedOrderOfNextRound; + RealTimeMinersInformation[pubkey].SupposedOrderOfNextRound = supposedOrderOfNextRound; + // Initialize FinalOrderOfNextRound as the value of SupposedOrderOfNextRound + RealTimeMinersInformation[pubkey].FinalOrderOfNextRound = supposedOrderOfNextRound; - return this; - } + return this; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ArrangeAbnormalMiningTime.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ArrangeAbnormalMiningTime.cs index f1d87a4e82..a186cd1a8a 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ArrangeAbnormalMiningTime.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ArrangeAbnormalMiningTime.cs @@ -4,76 +4,71 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + /// + /// If one node produced block this round or missed his time slot, + /// whatever how long he missed, we can give him a consensus command with new time slot + /// to produce a block (for terminating current round and start new round). + /// The schedule generated by this command will be cancelled + /// if this node executed blocks from other nodes. + /// + /// + public Timestamp ArrangeAbnormalMiningTime(string pubkey, Timestamp currentBlockTime, + bool mustExceededCurrentRound = false) { - /// - /// If one node produced block this round or missed his time slot, - /// whatever how long he missed, we can give him a consensus command with new time slot - /// to produce a block (for terminating current round and start new round). - /// The schedule generated by this command will be cancelled - /// if this node executed blocks from other nodes. - /// - /// - public Timestamp ArrangeAbnormalMiningTime(string pubkey, Timestamp currentBlockTime, bool mustExceededCurrentRound = false) - { - var miningInterval = GetMiningInterval(); - - var minerInRound = RealTimeMinersInformation[pubkey]; + var miningInterval = GetMiningInterval(); - if (GetExtraBlockProducerInformation().Pubkey == pubkey && !mustExceededCurrentRound) - { - var distance = (GetExtraBlockMiningTime().AddMilliseconds(miningInterval) - currentBlockTime).Milliseconds(); - if (distance > 0) - { - return GetExtraBlockMiningTime(); - } - } - - var distanceToRoundStartTime = (currentBlockTime - GetRoundStartTime()).Milliseconds(); - var missedRoundsCount = distanceToRoundStartTime.Div(TotalMilliseconds(miningInterval)); - var futureRoundStartTime = CalculateFutureRoundStartTime(missedRoundsCount, miningInterval); - return futureRoundStartTime.AddMilliseconds(minerInRound.Order.Mul(miningInterval)); - } + var minerInRound = RealTimeMinersInformation[pubkey]; - private MinerInRound GetExtraBlockProducerInformation() + if (GetExtraBlockProducerInformation().Pubkey == pubkey && !mustExceededCurrentRound) { - return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; + var distance = (GetExtraBlockMiningTime().AddMilliseconds(miningInterval) - currentBlockTime) + .Milliseconds(); + if (distance > 0) return GetExtraBlockMiningTime(); } - /// - /// This method for now is able to handle the situation of a miner keeping offline so many rounds, - /// by using missedRoundsCount. - /// - /// - /// - /// - private Timestamp CalculateFutureRoundStartTime(long missedRoundsCount = 0, int miningInterval = 0) - { - if (miningInterval == 0) - miningInterval = GetMiningInterval(); + var distanceToRoundStartTime = (currentBlockTime - GetRoundStartTime()).Milliseconds(); + var missedRoundsCount = distanceToRoundStartTime.Div(TotalMilliseconds(miningInterval)); + var futureRoundStartTime = CalculateFutureRoundStartTime(missedRoundsCount, miningInterval); + return futureRoundStartTime.AddMilliseconds(minerInRound.Order.Mul(miningInterval)); + } - var totalMilliseconds = TotalMilliseconds(miningInterval); - return GetRoundStartTime().AddMilliseconds(missedRoundsCount.Add(1).Mul(totalMilliseconds)); - } + private MinerInRound GetExtraBlockProducerInformation() + { + return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; + } - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + /// + /// This method for now is able to handle the situation of a miner keeping offline so many rounds, + /// by using missedRoundsCount. + /// + /// + /// + /// + private Timestamp CalculateFutureRoundStartTime(long missedRoundsCount = 0, int miningInterval = 0) + { + if (miningInterval == 0) + miningInterval = GetMiningInterval(); - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } + var totalMilliseconds = TotalMilliseconds(miningInterval); + return GetRoundStartTime().AddMilliseconds(missedRoundsCount.Add(1).Mul(totalMilliseconds)); + } + + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); + + return RealTimeMinersInformation.Count * miningInterval + miningInterval; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs index eeb102d2c0..786eef5ca0 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs @@ -1,53 +1,49 @@ using System.Linq; using AElf.Types; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + /// + /// Maybe tune other miners' supposed order of next round, + /// will record this purpose to their FinalOrderOfNextRound field. + /// + /// + /// + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) { - /// - /// Maybe tune other miners' supposed order of next round, - /// will record this purpose to their FinalOrderOfNextRound field. - /// - /// - /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) - { - if (!RealTimeMinersInformation.ContainsKey(pubkey)) - { - return null; - } + if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; - var minerInRound = RealTimeMinersInformation[pubkey]; + var minerInRound = RealTimeMinersInformation[pubkey]; - var tuneOrderInformation = RealTimeMinersInformation.Values - .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) - .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); + var tuneOrderInformation = RealTimeMinersInformation.Values + .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) + .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); - var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => - v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) - .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); + var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => + v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) + .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); - var minersPreviousInValues = - RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( - info => info.Pubkey, - info => info.PreviousInValue); + var minersPreviousInValues = + RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( + info => info.Pubkey, + info => info.PreviousInValue); - return new UpdateValueInput - { - OutValue = minerInRound.OutValue, - Signature = minerInRound.Signature, - PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, - RoundId = RoundIdForValidation, - ProducedBlocks = minerInRound.ProducedBlocks, - ActualMiningTime = minerInRound.ActualMiningTimes.Last(), - SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, - TuneOrderInformation = {tuneOrderInformation}, - EncryptedPieces = {minerInRound.EncryptedPieces}, - DecryptedPieces = {decryptedPreviousInValues}, - MinersPreviousInValues = {minersPreviousInValues}, - ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight - }; - } + return new UpdateValueInput + { + OutValue = minerInRound.OutValue, + Signature = minerInRound.Signature, + PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, + RoundId = RoundIdForValidation, + ProducedBlocks = minerInRound.ProducedBlocks, + ActualMiningTime = minerInRound.ActualMiningTimes.Last(), + SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, + TuneOrderInformation = { tuneOrderInformation }, + EncryptedPieces = { minerInRound.EncryptedPieces }, + DecryptedPieces = { decryptedPreviousInValues }, + MinersPreviousInValues = { minersPreviousInValues }, + ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Generation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Generation.cs index e17b956387..c0dd65c505 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Generation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Generation.cs @@ -4,143 +4,133 @@ using AElf.CSharp.Core.Extension; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + public void GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound, bool isMinerListChanged = false) { - public void GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound, bool isMinerListChanged = false) - { - nextRound = new Round {IsMinerListJustChanged = isMinerListChanged}; - - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; - - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; + nextRound = new Round { IsMinerListJustChanged = isMinerListChanged }; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) - { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp.AddMilliseconds(miningInterval.Mul(order)), - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } - - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) - { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp - .AddMilliseconds(miningInterval.Mul(order)), - ProducedBlocks = minerInRound.ProducedBlocks, - // Update missed time slots count of one miner. - MissedTimeSlots = minerInRound.MissedTimeSlots.Add(1) - }; - } - - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - BreakContinuousMining(ref nextRound); + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - nextRound.ConfirmedIrreversibleBlockHeight = ConfirmedIrreversibleBlockHeight; - nextRound.ConfirmedIrreversibleBlockRoundNumber = ConfirmedIrreversibleBlockRoundNumber; - } - - private void BreakContinuousMining(ref Round nextRound) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) { - var minersCount = RealTimeMinersInformation.Count; - if (minersCount <= 1) return; - - // First miner of next round != Extra block producer of current round - var firstMinerOfNextRound = nextRound.RealTimeMinersInformation.Values.First(i => i.Order == 1); - var extraBlockProducerOfCurrentRound = GetExtraBlockProducerInformation(); - if (firstMinerOfNextRound.Pubkey == extraBlockProducerOfCurrentRound.Pubkey) - { - var secondMinerOfNextRound = - nextRound.RealTimeMinersInformation.Values.First(i => i.Order == 2); - secondMinerOfNextRound.Order = 1; - firstMinerOfNextRound.Order = 2; - var tempTimestamp = secondMinerOfNextRound.ExpectedMiningTime; - secondMinerOfNextRound.ExpectedMiningTime = firstMinerOfNextRound.ExpectedMiningTime; - firstMinerOfNextRound.ExpectedMiningTime = tempTimestamp; - } - - // Last miner of next round != Extra block producer of next round - var lastMinerOfNextRound = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(i => i.Order == minersCount); - if (lastMinerOfNextRound == null) + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - return; - } - - var extraBlockProducerOfNextRound = nextRound.GetExtraBlockProducerInformation(); - if (lastMinerOfNextRound.Pubkey == extraBlockProducerOfNextRound.Pubkey) - { - var lastButOneMinerOfNextRound = - nextRound.RealTimeMinersInformation.Values.First(i => i.Order == minersCount.Sub(1)); - lastButOneMinerOfNextRound.Order = minersCount; - lastMinerOfNextRound.Order = minersCount.Sub(1); - var tempTimestamp = lastButOneMinerOfNextRound.ExpectedMiningTime; - lastButOneMinerOfNextRound.ExpectedMiningTime = lastMinerOfNextRound.ExpectedMiningTime; - lastMinerOfNextRound.ExpectedMiningTime = tempTimestamp; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp.AddMilliseconds(miningInterval.Mul(order)), + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; } - private int CalculateNextExtraBlockProducerOrder() + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } - - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToInt64(); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + .AddMilliseconds(miningInterval.Mul(order)), + ProducedBlocks = minerInRound.ProducedBlocks, + // Update missed time slots count of one miner. + MissedTimeSlots = minerInRound.MissedTimeSlots.Add(1) + }; } - public List GetMinedMiners() + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; + + BreakContinuousMining(ref nextRound); + + nextRound.ConfirmedIrreversibleBlockHeight = ConfirmedIrreversibleBlockHeight; + nextRound.ConfirmedIrreversibleBlockRoundNumber = ConfirmedIrreversibleBlockRoundNumber; + } + + private void BreakContinuousMining(ref Round nextRound) + { + var minersCount = RealTimeMinersInformation.Count; + if (minersCount <= 1) return; + + // First miner of next round != Extra block producer of current round + var firstMinerOfNextRound = nextRound.RealTimeMinersInformation.Values.First(i => i.Order == 1); + var extraBlockProducerOfCurrentRound = GetExtraBlockProducerInformation(); + if (firstMinerOfNextRound.Pubkey == extraBlockProducerOfCurrentRound.Pubkey) { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + var secondMinerOfNextRound = + nextRound.RealTimeMinersInformation.Values.First(i => i.Order == 2); + secondMinerOfNextRound.Order = 1; + firstMinerOfNextRound.Order = 2; + var tempTimestamp = secondMinerOfNextRound.ExpectedMiningTime; + secondMinerOfNextRound.ExpectedMiningTime = firstMinerOfNextRound.ExpectedMiningTime; + firstMinerOfNextRound.ExpectedMiningTime = tempTimestamp; } - private List GetNotMinedMiners() + // Last miner of next round != Extra block producer of next round + var lastMinerOfNextRound = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(i => i.Order == minersCount); + if (lastMinerOfNextRound == null) return; + + var extraBlockProducerOfNextRound = nextRound.GetExtraBlockProducerInformation(); + if (lastMinerOfNextRound.Pubkey == extraBlockProducerOfNextRound.Pubkey) { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); + var lastButOneMinerOfNextRound = + nextRound.RealTimeMinersInformation.Values.First(i => i.Order == minersCount.Sub(1)); + lastButOneMinerOfNextRound.Order = minersCount; + lastMinerOfNextRound.Order = minersCount.Sub(1); + var tempTimestamp = lastButOneMinerOfNextRound.ExpectedMiningTime; + lastButOneMinerOfNextRound.ExpectedMiningTime = lastMinerOfNextRound.ExpectedMiningTime; + lastMinerOfNextRound.ExpectedMiningTime = tempTimestamp; } } + + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; + + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToInt64(); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } + + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } + + private List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); + } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLighterRound.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLighterRound.cs index 4d1c437227..2b9fa1af62 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLighterRound.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLighterRound.cs @@ -1,22 +1,15 @@ using System.Linq; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round + public void DeleteSecretSharingInformation() { - public void DeleteSecretSharingInformation() - { - var encryptedPieces = RealTimeMinersInformation.Values.Select(i => i.EncryptedPieces); - foreach (var encryptedPiece in encryptedPieces) - { - encryptedPiece.Clear(); - } + var encryptedPieces = RealTimeMinersInformation.Values.Select(i => i.EncryptedPieces); + foreach (var encryptedPiece in encryptedPieces) encryptedPiece.Clear(); - var decryptedPieces = RealTimeMinersInformation.Values.Select(i => i.DecryptedPieces); - foreach (var decryptedPiece in decryptedPieces) - { - decryptedPiece.Clear(); - } - } + var decryptedPieces = RealTimeMinersInformation.Values.Select(i => i.DecryptedPieces); + foreach (var decryptedPiece in decryptedPieces) decryptedPiece.Clear(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLogs.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLogs.cs index ccdfbdf587..a773d15ea8 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLogs.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_GetLogs.cs @@ -2,71 +2,66 @@ using System.Linq; using AElf.Sdk.CSharp; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round : IFormattable { - public partial class Round : IFormattable + public string ToString(string format, IFormatProvider formatProvider = null) { - private string GetLogs(string publicKey) - { - var logs = $"\n[Round {RoundNumber}](Round Id: {RoundId})[Term {TermNumber}]"; - foreach (var minerInRound in RealTimeMinersInformation.Values.OrderBy(m => m.Order)) - { - var minerInformation = "\n"; - minerInformation = minerInformation.Append($"[{minerInRound.Pubkey.Substring(0, 10)}]"); - minerInformation = minerInformation.Append(minerInRound.IsExtraBlockProducer ? "(Current EBP)" : ""); - minerInformation = minerInformation.AppendLine(minerInRound.Pubkey == publicKey - ? "(This Node)" - : ""); - minerInformation = minerInformation.AppendLine($"Order:\t {minerInRound.Order}"); - minerInformation = minerInformation.AppendLine( - $"Expect:\t {minerInRound.ExpectedMiningTime?.ToDateTime().ToUniversalTime():yyyy-MM-dd HH.mm.ss,ffffff}"); - var roundStartTime = GetRoundStartTime(); - var actualMiningTimes = minerInRound.ActualMiningTimes.OrderBy(t => t).Select(t => - { - if (t < roundStartTime) - { - return - $"{t.ToDateTime().ToUniversalTime():yyyy-MM-dd HH.mm.ss,ffffff} (For Extra Block Slot Of Previous Round)"; - } - - return t.ToDateTime().ToUniversalTime().ToString("yyyy-MM-dd HH.mm.ss,ffffff"); - }); - var actualMiningTimesStr = - minerInRound.ActualMiningTimes.Any() ? string.Join("\n\t ", actualMiningTimes) : ""; - minerInformation = minerInformation.AppendLine($"Actual:\t {actualMiningTimesStr}"); - minerInformation = minerInformation.AppendLine($"Out:\t {minerInRound.OutValue?.ToHex()}"); - if (RoundNumber != 1) - { - minerInformation = minerInformation.AppendLine($"PreIn:\t {minerInRound.PreviousInValue?.ToHex()}"); - } + if (string.IsNullOrEmpty(format)) format = "G"; - minerInformation = minerInformation.AppendLine($"In:\t {minerInRound.InValue?.ToHex()}"); - minerInformation = minerInformation.AppendLine($"Sig:\t {minerInRound.Signature?.ToHex()}"); - minerInformation = minerInformation.AppendLine($"Mine:\t {minerInRound.ProducedBlocks}"); - minerInformation = minerInformation.AppendLine($"Miss:\t {minerInRound.MissedTimeSlots}"); - minerInformation = minerInformation.AppendLine($"Tiny:\t {minerInRound.ActualMiningTimes.Count}"); - minerInformation = minerInformation.AppendLine($"NOrder:\t {minerInRound.FinalOrderOfNextRound}"); - minerInformation = minerInformation.AppendLine($"Lib:\t {minerInRound.ImpliedIrreversibleBlockHeight}"); - - logs = logs.Append(minerInformation); - } - - return logs; + switch (format) + { + case "G": return ToString(); + case "M": + // Return formatted miner list. + return RealTimeMinersInformation.Keys.Aggregate("\n", (key1, key2) => key1 + "\n" + key2); } - public string ToString(string format, IFormatProvider formatProvider = null) - { - if (string.IsNullOrEmpty(format)) format = "G"; + return GetLogs(format); + } - switch (format) + private string GetLogs(string publicKey) + { + var logs = $"\n[Round {RoundNumber}](Round Id: {RoundId})[Term {TermNumber}]"; + foreach (var minerInRound in RealTimeMinersInformation.Values.OrderBy(m => m.Order)) + { + var minerInformation = "\n"; + minerInformation = minerInformation.Append($"[{minerInRound.Pubkey.Substring(0, 10)}]"); + minerInformation = minerInformation.Append(minerInRound.IsExtraBlockProducer ? "(Current EBP)" : ""); + minerInformation = minerInformation.AppendLine(minerInRound.Pubkey == publicKey + ? "(This Node)" + : ""); + minerInformation = minerInformation.AppendLine($"Order:\t {minerInRound.Order}"); + minerInformation = minerInformation.AppendLine( + $"Expect:\t {minerInRound.ExpectedMiningTime?.ToDateTime().ToUniversalTime():yyyy-MM-dd HH.mm.ss,ffffff}"); + var roundStartTime = GetRoundStartTime(); + var actualMiningTimes = minerInRound.ActualMiningTimes.OrderBy(t => t).Select(t => { - case "G": return ToString(); - case "M": - // Return formatted miner list. - return RealTimeMinersInformation.Keys.Aggregate("\n", (key1, key2) => key1 + "\n" + key2); - } + if (t < roundStartTime) + return + $"{t.ToDateTime().ToUniversalTime():yyyy-MM-dd HH.mm.ss,ffffff} (For Extra Block Slot Of Previous Round)"; - return GetLogs(format); + return t.ToDateTime().ToUniversalTime().ToString("yyyy-MM-dd HH.mm.ss,ffffff"); + }); + var actualMiningTimesStr = + minerInRound.ActualMiningTimes.Any() ? string.Join("\n\t ", actualMiningTimes) : ""; + minerInformation = minerInformation.AppendLine($"Actual:\t {actualMiningTimesStr}"); + minerInformation = minerInformation.AppendLine($"Out:\t {minerInRound.OutValue?.ToHex()}"); + if (RoundNumber != 1) + minerInformation = minerInformation.AppendLine($"PreIn:\t {minerInRound.PreviousInValue?.ToHex()}"); + + minerInformation = minerInformation.AppendLine($"In:\t {minerInRound.InValue?.ToHex()}"); + minerInformation = minerInformation.AppendLine($"Sig:\t {minerInRound.Signature?.ToHex()}"); + minerInformation = minerInformation.AppendLine($"Mine:\t {minerInRound.ProducedBlocks}"); + minerInformation = minerInformation.AppendLine($"Miss:\t {minerInRound.MissedTimeSlots}"); + minerInformation = minerInformation.AppendLine($"Tiny:\t {minerInRound.ActualMiningTimes.Count}"); + minerInformation = minerInformation.AppendLine($"NOrder:\t {minerInRound.FinalOrderOfNextRound}"); + minerInformation = minerInformation.AppendLine($"Lib:\t {minerInRound.ImpliedIrreversibleBlockHeight}"); + + logs = logs.Append(minerInformation); } + + return logs; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ImpliedIrreversibleBlockHeight.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ImpliedIrreversibleBlockHeight.cs index 1bbf6331bd..383503b0ab 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ImpliedIrreversibleBlockHeight.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ImpliedIrreversibleBlockHeight.cs @@ -3,19 +3,18 @@ using AElf.CSharp.Core; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class Round { - public partial class Round - { - public List GetSortedImpliedIrreversibleBlockHeights(List specificPublicKeys) - { - var heights = RealTimeMinersInformation.Values.Where(i => specificPublicKeys.Contains(i.Pubkey)) - .Where(i => i.ImpliedIrreversibleBlockHeight > 0) - .Select(i => i.ImpliedIrreversibleBlockHeight).ToList(); - heights.Sort(); - return heights; - } + public int MinersCountOfConsent => RealTimeMinersInformation.Count.Mul(2).Div(3).Add(1); - public int MinersCountOfConsent => RealTimeMinersInformation.Count.Mul(2).Div(3).Add(1); + public List GetSortedImpliedIrreversibleBlockHeights(List specificPublicKeys) + { + var heights = RealTimeMinersInformation.Values.Where(i => specificPublicKeys.Contains(i.Pubkey)) + .Where(i => i.ImpliedIrreversibleBlockHeight > 0) + .Select(i => i.ImpliedIrreversibleBlockHeight).ToList(); + heights.Sort(); + return heights; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Recover.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Recover.cs index 742b9eebc5..94e6955d75 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Recover.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Recover.cs @@ -1,53 +1,48 @@ -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +/// +/// Mirror of Round_Simplify +/// +public partial class Round { - /// - /// Mirror of Round_Simplify - /// - public partial class Round + public Round RecoverFromUpdateValue(Round providedRound, string pubkey) { - public Round RecoverFromUpdateValue(Round providedRound, string pubkey) - { - if (!RealTimeMinersInformation.ContainsKey(pubkey) || - !providedRound.RealTimeMinersInformation.ContainsKey(pubkey)) - { - return this; - } - - var minerInRound = RealTimeMinersInformation[pubkey]; - var providedInformation = providedRound.RealTimeMinersInformation[pubkey]; - minerInRound.OutValue = providedInformation.OutValue; - minerInRound.Signature = providedInformation.Signature; - minerInRound.PreviousInValue = providedInformation.PreviousInValue; - minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight; - minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes); - - foreach (var information in providedRound.RealTimeMinersInformation) - { - RealTimeMinersInformation[information.Key].SupposedOrderOfNextRound = - information.Value.SupposedOrderOfNextRound; - RealTimeMinersInformation[information.Key].FinalOrderOfNextRound = - information.Value.FinalOrderOfNextRound; - RealTimeMinersInformation[information.Key].PreviousInValue = - information.Value.PreviousInValue; - } - + if (!RealTimeMinersInformation.ContainsKey(pubkey) || + !providedRound.RealTimeMinersInformation.ContainsKey(pubkey)) return this; - } - public Round RecoverFromTinyBlock(Round providedRound, string pubkey) + var minerInRound = RealTimeMinersInformation[pubkey]; + var providedInformation = providedRound.RealTimeMinersInformation[pubkey]; + minerInRound.OutValue = providedInformation.OutValue; + minerInRound.Signature = providedInformation.Signature; + minerInRound.PreviousInValue = providedInformation.PreviousInValue; + minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight; + minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes); + + foreach (var information in providedRound.RealTimeMinersInformation) { - if (!RealTimeMinersInformation.ContainsKey(pubkey) || - !providedRound.RealTimeMinersInformation.ContainsKey(pubkey)) - { - return this; - } + RealTimeMinersInformation[information.Key].SupposedOrderOfNextRound = + information.Value.SupposedOrderOfNextRound; + RealTimeMinersInformation[information.Key].FinalOrderOfNextRound = + information.Value.FinalOrderOfNextRound; + RealTimeMinersInformation[information.Key].PreviousInValue = + information.Value.PreviousInValue; + } - var minerInRound = RealTimeMinersInformation[pubkey]; - var providedInformation = providedRound.RealTimeMinersInformation[pubkey]; - minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight; - minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes); + return this; + } + public Round RecoverFromTinyBlock(Round providedRound, string pubkey) + { + if (!RealTimeMinersInformation.ContainsKey(pubkey) || + !providedRound.RealTimeMinersInformation.ContainsKey(pubkey)) return this; - } + + var minerInRound = RealTimeMinersInformation[pubkey]; + var providedInformation = providedRound.RealTimeMinersInformation[pubkey]; + minerInRound.ImpliedIrreversibleBlockHeight = providedInformation.ImpliedIrreversibleBlockHeight; + minerInRound.ActualMiningTimes.Add(providedInformation.ActualMiningTimes); + + return this; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Simplify.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Simplify.cs index 5878f93964..3be23bedba 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Simplify.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_Simplify.cs @@ -1,88 +1,83 @@ using System.Collections.Generic; using System.Linq; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +/// +/// Mirror of Round_Recover +/// +public partial class Round { - /// - /// Mirror of Round_Recover - /// - public partial class Round + public Round GetUpdateValueRound(string pubkey) { - public Round GetUpdateValueRound(string pubkey) + var minerInRound = RealTimeMinersInformation[pubkey]; + var round = new Round { - var minerInRound = RealTimeMinersInformation[pubkey]; - var round = new Round + RoundNumber = RoundNumber, + RoundIdForValidation = RoundId, + RealTimeMinersInformation = { - RoundNumber = RoundNumber, - RoundIdForValidation = RoundId, - RealTimeMinersInformation = + [pubkey] = new MinerInRound { - [pubkey] = new MinerInRound - { - Pubkey = pubkey, - OutValue = minerInRound.OutValue, - Signature = minerInRound.Signature, - ProducedBlocks = minerInRound.ProducedBlocks, - ProducedTinyBlocks = minerInRound.ProducedTinyBlocks, - PreviousInValue = minerInRound.PreviousInValue, - ActualMiningTimes = {minerInRound.ActualMiningTimes}, - ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight, - Order = minerInRound.Order, - IsExtraBlockProducer = minerInRound.IsExtraBlockProducer - } + Pubkey = pubkey, + OutValue = minerInRound.OutValue, + Signature = minerInRound.Signature, + ProducedBlocks = minerInRound.ProducedBlocks, + ProducedTinyBlocks = minerInRound.ProducedTinyBlocks, + PreviousInValue = minerInRound.PreviousInValue, + ActualMiningTimes = { minerInRound.ActualMiningTimes }, + ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight, + Order = minerInRound.Order, + IsExtraBlockProducer = minerInRound.IsExtraBlockProducer } - }; - foreach (var information in RealTimeMinersInformation) + } + }; + foreach (var information in RealTimeMinersInformation) + if (information.Key == pubkey) { - if (information.Key == pubkey) - { - round.RealTimeMinersInformation[pubkey].SupposedOrderOfNextRound = - minerInRound.SupposedOrderOfNextRound; - round.RealTimeMinersInformation[pubkey].FinalOrderOfNextRound = minerInRound.FinalOrderOfNextRound; - } - else + round.RealTimeMinersInformation[pubkey].SupposedOrderOfNextRound = + minerInRound.SupposedOrderOfNextRound; + round.RealTimeMinersInformation[pubkey].FinalOrderOfNextRound = minerInRound.FinalOrderOfNextRound; + } + else + { + round.RealTimeMinersInformation.Add(information.Key, new MinerInRound { - round.RealTimeMinersInformation.Add(information.Key, new MinerInRound - { - Pubkey = information.Value.Pubkey, - SupposedOrderOfNextRound = information.Value.SupposedOrderOfNextRound, - FinalOrderOfNextRound = information.Value.FinalOrderOfNextRound, - Order = information.Value.Order, - IsExtraBlockProducer = information.Value.IsExtraBlockProducer, - PreviousInValue = information.Value.PreviousInValue - }); - } + Pubkey = information.Value.Pubkey, + SupposedOrderOfNextRound = information.Value.SupposedOrderOfNextRound, + FinalOrderOfNextRound = information.Value.FinalOrderOfNextRound, + Order = information.Value.Order, + IsExtraBlockProducer = information.Value.IsExtraBlockProducer, + PreviousInValue = information.Value.PreviousInValue + }); } - return round; - } + return round; + } - public Round GetTinyBlockRound(string pubkey) + public Round GetTinyBlockRound(string pubkey) + { + var minerInRound = RealTimeMinersInformation[pubkey]; + var round = new Round { - var minerInRound = RealTimeMinersInformation[pubkey]; - var round = new Round + RoundNumber = RoundNumber, + RoundIdForValidation = RoundId, + RealTimeMinersInformation = { - RoundNumber = RoundNumber, - RoundIdForValidation = RoundId, - RealTimeMinersInformation = + [pubkey] = new MinerInRound { - [pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - ActualMiningTimes = {minerInRound.ActualMiningTimes}, - ProducedBlocks = minerInRound.ProducedBlocks, - ProducedTinyBlocks = minerInRound.ProducedTinyBlocks, - ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight - } + Pubkey = minerInRound.Pubkey, + ActualMiningTimes = { minerInRound.ActualMiningTimes }, + ProducedBlocks = minerInRound.ProducedBlocks, + ProducedTinyBlocks = minerInRound.ProducedTinyBlocks, + ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight } - }; - - foreach (var otherPubkey in RealTimeMinersInformation.Keys.Except(new List {pubkey})) - { - round.RealTimeMinersInformation.Add(otherPubkey, new MinerInRound()); } + }; + + foreach (var otherPubkey in RealTimeMinersInformation.Keys.Except(new List { pubkey })) + round.RealTimeMinersInformation.Add(otherPubkey, new MinerInRound()); - return round; - } + return round; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/AElf.Contracts.CrossChain.csproj b/contract/AElf.Contracts.CrossChain/AElf.Contracts.CrossChain.csproj index 011b426801..e4a88d7962 100644 --- a/contract/AElf.Contracts.CrossChain/AElf.Contracts.CrossChain.csproj +++ b/contract/AElf.Contracts.CrossChain/AElf.Contracts.CrossChain.csproj @@ -1,17 +1,18 @@ - + net6.0 AElf.Contracts.CrossChain true - CrossChain is a contract that implements cross-chain related features, especially - indexing. + CrossChain is a contract that implements cross-chain related features, especially + indexing. + - true + true - true + true @@ -19,7 +20,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs3.proto diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract.cs index 51141a5377..4124de3a00 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract.cs @@ -1,315 +1,313 @@ -using System.Linq; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.MultiToken; +using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; -using AElf.CSharp.Core; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.CrossChain +namespace AElf.Contracts.CrossChain; + +public partial class CrossChainContract : CrossChainContractImplContainer.CrossChainContractImplBase { - public partial class CrossChainContract : CrossChainContractImplContainer.CrossChainContractImplBase + public override Empty Initialize(InitializeInput input) { - public override Empty Initialize(InitializeInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); - State.ParentChainId.Value = input.ParentChainId; - State.CurrentParentChainHeight.Value = input.CreationHeightOnParentChain - 1; - State.IndexingPendingProposal.Value = new ProposedCrossChainIndexing(); - - CreateInitialOrganizationForInitialControllerAddress(); - State.Initialized.Value = true; + Assert(!State.Initialized.Value, "Already initialized."); + State.ParentChainId.Value = input.ParentChainId; + State.CurrentParentChainHeight.Value = input.CreationHeightOnParentChain - 1; + State.IndexingPendingProposal.Value = new ProposedCrossChainIndexing(); - if (Context.CurrentHeight != AElfConstants.GenesisBlockHeight) - return new Empty(); + CreateInitialOrganizationForInitialControllerAddress(); + State.Initialized.Value = true; - State.GenesisContract.Value = Context.GetZeroSmartContractAddress(); - State.GenesisContract.SetContractProposerRequiredState.Send( - new BoolValue {Value = input.IsPrivilegePreserved}); + if (Context.CurrentHeight != AElfConstants.GenesisBlockHeight) return new Empty(); - } - public override Empty SetInitialSideChainLifetimeControllerAddress(Address input) - { - Assert(State.SideChainLifetimeController.Value == null, "Already initialized."); - var parliamentContractAddress = State.ParliamentContract.Value; - Assert(parliamentContractAddress == Context.Sender, "No permission."); - var initialAuthorityInfo = new AuthorityInfo - { - OwnerAddress = input, - ContractAddress = parliamentContractAddress - }; - State.SideChainLifetimeController.Value = initialAuthorityInfo; - return new Empty(); - } - - public override Empty SetInitialIndexingControllerAddress(Address input) - { - Assert(State.CrossChainIndexingController.Value == null, "Already initialized."); - var parliamentContractAddress = State.ParliamentContract.Value; - Assert(parliamentContractAddress == Context.Sender, "No permission."); - var initialAuthorityInfo = new AuthorityInfo - { - OwnerAddress = input, - ContractAddress = parliamentContractAddress - }; - State.CrossChainIndexingController.Value = initialAuthorityInfo; - return new Empty(); - } + State.GenesisContract.Value = Context.GetZeroSmartContractAddress(); + State.GenesisContract.SetContractProposerRequiredState.Send( + new BoolValue { Value = input.IsPrivilegePreserved }); + return new Empty(); + } - #region Side chain lifetime actions + public override Empty SetInitialSideChainLifetimeControllerAddress(Address input) + { + Assert(State.SideChainLifetimeController.Value == null, "Already initialized."); + var parliamentContractAddress = State.ParliamentContract.Value; + Assert(parliamentContractAddress == Context.Sender, "No permission."); + var initialAuthorityInfo = new AuthorityInfo + { + OwnerAddress = input, + ContractAddress = parliamentContractAddress + }; + State.SideChainLifetimeController.Value = initialAuthorityInfo; + return new Empty(); + } - public override Empty RequestSideChainCreation(SideChainCreationRequest input) + public override Empty SetInitialIndexingControllerAddress(Address input) + { + Assert(State.CrossChainIndexingController.Value == null, "Already initialized."); + var parliamentContractAddress = State.ParliamentContract.Value; + Assert(parliamentContractAddress == Context.Sender, "No permission."); + var initialAuthorityInfo = new AuthorityInfo { - AssertValidSideChainCreationRequest(input, Context.Sender); - var sideChainCreationRequestState = ProposeNewSideChain(input, Context.Sender); - State.ProposedSideChainCreationRequestState[Context.Sender] = sideChainCreationRequestState; - return new Empty(); - } + OwnerAddress = input, + ContractAddress = parliamentContractAddress + }; + State.CrossChainIndexingController.Value = initialAuthorityInfo; + return new Empty(); + } - public override Empty ReleaseSideChainCreation(ReleaseSideChainCreationInput input) + public override Empty ChangeCrossChainIndexingController(AuthorityInfo input) + { + AssertCrossChainIndexingControllerAuthority(Context.Sender); + SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); + Assert( + input.ContractAddress == State.ParliamentContract.Value && + ValidateParliamentOrganization(input.OwnerAddress), "Invalid authority input."); + State.CrossChainIndexingController.Value = input; + Context.Fire(new CrossChainIndexingControllerChanged { - var sideChainCreationRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; - Assert(sideChainCreationRequest != null, "Release side chain creation failed."); - if (!TryClearExpiredSideChainCreationRequestProposal(input.ProposalId, Context.Sender)) - { - var serialNumber = State.SideChainSerialNumber.Value.Add(1); - var chainId = GetChainId(serialNumber); - CreateSideChainToken(sideChainCreationRequest.SideChainCreationRequest, chainId, sideChainCreationRequest.Proposer); - Context.SendInline(State.SideChainLifetimeController.Value.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), - input.ProposalId); - } - - return new Empty(); - } + AuthorityInfo = input + }); + return new Empty(); + } - /// - /// Create side chain. It is a proposal result from system address. - /// - /// - /// - public override Int32Value CreateSideChain(CreateSideChainInput input) + public override Empty ChangeSideChainLifetimeController(AuthorityInfo input) + { + AssertSideChainLifetimeControllerAuthority(Context.Sender); + Assert(ValidateAuthorityInfoExists(input), "Invalid authority input."); + State.SideChainLifetimeController.Value = input; + Context.Fire(new SideChainLifetimeControllerChanged { - // side chain creation should be triggered by organization address. - AssertSideChainLifetimeControllerAuthority(Context.Sender); - - var proposedSideChainCreationRequestState = State.ProposedSideChainCreationRequestState[input.Proposer]; - State.ProposedSideChainCreationRequestState.Remove(input.Proposer); - var sideChainCreationRequest = input.SideChainCreationRequest; - Assert( - proposedSideChainCreationRequestState != null && - proposedSideChainCreationRequestState.SideChainCreationRequest.Equals(sideChainCreationRequest), - "Side chain creation failed without proposed data."); - AssertValidSideChainCreationRequest(sideChainCreationRequest, input.Proposer); - - State.SideChainSerialNumber.Value = State.SideChainSerialNumber.Value.Add(1); - var serialNumber = State.SideChainSerialNumber.Value; - var chainId = GetChainId(serialNumber); - State.AcceptedSideChainCreationRequest[chainId] = sideChainCreationRequest; + AuthorityInfo = input + }); + return new Empty(); + } - // lock token - ChargeSideChainIndexingFee(input.Proposer, sideChainCreationRequest.LockedTokenAmount, chainId); + #region Side chain lifetime actions - var sideChainInfo = new SideChainInfo - { - Proposer = input.Proposer, - SideChainId = chainId, - SideChainStatus = SideChainStatus.Active, - IndexingPrice = sideChainCreationRequest.IndexingPrice, - IsPrivilegePreserved = sideChainCreationRequest.IsPrivilegePreserved, - CreationTimestamp = Context.CurrentBlockTime, - CreationHeightOnParentChain = Context.CurrentHeight, - IndexingFeeController = CreateDefaultOrganizationForIndexingFeePriceManagement(input.Proposer) - }; - State.SideChainInfo[chainId] = sideChainInfo; - State.CurrentSideChainHeight[chainId] = 0; - - var chainInitializationData = - GetChainInitializationData(sideChainInfo, sideChainCreationRequest); - State.SideChainInitializationData[sideChainInfo.SideChainId] = chainInitializationData; - - Context.Fire(new SideChainCreatedEvent - { - ChainId = chainId, - Creator = input.Proposer - }); - return new Int32Value {Value = chainId}; + public override Empty RequestSideChainCreation(SideChainCreationRequest input) + { + AssertValidSideChainCreationRequest(input, Context.Sender); + var sideChainCreationRequestState = ProposeNewSideChain(input, Context.Sender); + State.ProposedSideChainCreationRequestState[Context.Sender] = sideChainCreationRequestState; + return new Empty(); + } + + public override Empty ReleaseSideChainCreation(ReleaseSideChainCreationInput input) + { + var sideChainCreationRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; + Assert(sideChainCreationRequest != null, "Release side chain creation failed."); + if (!TryClearExpiredSideChainCreationRequestProposal(input.ProposalId, Context.Sender)) + { + var serialNumber = State.SideChainSerialNumber.Value.Add(1); + var chainId = GetChainId(serialNumber); + CreateSideChainToken(sideChainCreationRequest.SideChainCreationRequest, chainId, + sideChainCreationRequest.Proposer); + Context.SendInline(State.SideChainLifetimeController.Value.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), + input.ProposalId); } - /// - /// Recharge for side chain. - /// - /// - /// - public override Empty Recharge(RechargeInput input) + return new Empty(); + } + + /// + /// Create side chain. It is a proposal result from system address. + /// + /// + /// + public override Int32Value CreateSideChain(CreateSideChainInput input) + { + // side chain creation should be triggered by organization address. + AssertSideChainLifetimeControllerAuthority(Context.Sender); + + var proposedSideChainCreationRequestState = State.ProposedSideChainCreationRequestState[input.Proposer]; + State.ProposedSideChainCreationRequestState.Remove(input.Proposer); + var sideChainCreationRequest = input.SideChainCreationRequest; + Assert( + proposedSideChainCreationRequestState != null && + proposedSideChainCreationRequestState.SideChainCreationRequest.Equals(sideChainCreationRequest), + "Side chain creation failed without proposed data."); + AssertValidSideChainCreationRequest(sideChainCreationRequest, input.Proposer); + + State.SideChainSerialNumber.Value = State.SideChainSerialNumber.Value.Add(1); + var serialNumber = State.SideChainSerialNumber.Value; + var chainId = GetChainId(serialNumber); + State.AcceptedSideChainCreationRequest[chainId] = sideChainCreationRequest; + + // lock token + ChargeSideChainIndexingFee(input.Proposer, sideChainCreationRequest.LockedTokenAmount, chainId); + + var sideChainInfo = new SideChainInfo + { + Proposer = input.Proposer, + SideChainId = chainId, + SideChainStatus = SideChainStatus.Active, + IndexingPrice = sideChainCreationRequest.IndexingPrice, + IsPrivilegePreserved = sideChainCreationRequest.IsPrivilegePreserved, + CreationTimestamp = Context.CurrentBlockTime, + CreationHeightOnParentChain = Context.CurrentHeight, + IndexingFeeController = CreateDefaultOrganizationForIndexingFeePriceManagement(input.Proposer) + }; + State.SideChainInfo[chainId] = sideChainInfo; + State.CurrentSideChainHeight[chainId] = 0; + + var chainInitializationData = + GetChainInitializationData(sideChainInfo, sideChainCreationRequest); + State.SideChainInitializationData[sideChainInfo.SideChainId] = chainInitializationData; + + Context.Fire(new SideChainCreatedEvent { - var chainId = input.ChainId; - var sideChainInfo = State.SideChainInfo[chainId]; - Assert(sideChainInfo != null && sideChainInfo.SideChainStatus != SideChainStatus.Terminated, - "Side chain not found or incorrect side chain status."); + ChainId = chainId, + Creator = input.Proposer + }); + return new Int32Value { Value = chainId }; + } - TransferFrom(new TransferFromInput - { - From = Context.Sender, - To = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), - Symbol = Context.Variables.NativeSymbol, - Amount = input.Amount, - Memo = "Indexing fee recharging." - }); - - long arrearsAmount = 0; - if (sideChainInfo.SideChainStatus == SideChainStatus.IndexingFeeDebt) + /// + /// Recharge for side chain. + /// + /// + /// + public override Empty Recharge(RechargeInput input) + { + var chainId = input.ChainId; + var sideChainInfo = State.SideChainInfo[chainId]; + Assert(sideChainInfo != null && sideChainInfo.SideChainStatus != SideChainStatus.Terminated, + "Side chain not found or incorrect side chain status."); + + TransferFrom(new TransferFromInput + { + From = Context.Sender, + To = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), + Symbol = Context.Variables.NativeSymbol, + Amount = input.Amount, + Memo = "Indexing fee recharging." + }); + + long arrearsAmount = 0; + if (sideChainInfo.SideChainStatus == SideChainStatus.IndexingFeeDebt) + { + // arrears + foreach (var arrears in sideChainInfo.ArrearsInfo) { - // arrears - foreach (var arrears in sideChainInfo.ArrearsInfo) + arrearsAmount += arrears.Value; + TransferDepositToken(new TransferInput { - arrearsAmount += arrears.Value; - TransferDepositToken(new TransferInput - { - To = Address.Parser.ParseFrom(ByteString.FromBase64(arrears.Key)), - Symbol = Context.Variables.NativeSymbol, - Amount = arrears.Value, - Memo = "Indexing fee recharging." - }, chainId); - } - - var originBalance = GetSideChainIndexingFeeDeposit(chainId); - Assert(input.Amount + originBalance >= arrearsAmount + sideChainInfo.IndexingPrice, - "Indexing fee recharging not enough."); + To = Address.Parser.ParseFrom(ByteString.FromBase64(arrears.Key)), + Symbol = Context.Variables.NativeSymbol, + Amount = arrears.Value, + Memo = "Indexing fee recharging." + }, chainId); } - sideChainInfo.ArrearsInfo.Clear(); - sideChainInfo.SideChainStatus = SideChainStatus.Active; - State.SideChainInfo[chainId] = sideChainInfo; - return new Empty(); - } - - /// - /// Dispose side chain. It is a proposal result from system address. - /// - /// - /// - public override Int32Value DisposeSideChain(Int32Value input) - { - AssertSideChainLifetimeControllerAuthority(Context.Sender); - - var chainId = input.Value; - var info = State.SideChainInfo[chainId]; - Assert(info != null, "Side chain not found."); - Assert(info.SideChainStatus != SideChainStatus.Terminated, "Incorrect chain status."); - - if (TryGetIndexingProposal(chainId, out _)) - ResetChainIndexingProposal(chainId); - - UnlockTokenAndResource(info); - info.SideChainStatus = SideChainStatus.Terminated; - State.SideChainInfo[chainId] = info; - Context.Fire(new Disposed - { - ChainId = chainId - }); - return new Int32Value {Value = chainId}; + var originBalance = GetSideChainIndexingFeeDeposit(chainId); + Assert(input.Amount + originBalance >= arrearsAmount + sideChainInfo.IndexingPrice, + "Indexing fee recharging not enough."); } - public override Empty AdjustIndexingFeePrice(AdjustIndexingFeeInput input) - { - var info = State.SideChainInfo[input.SideChainId]; - Assert(info != null && info.SideChainStatus != SideChainStatus.Terminated, - "Side chain not found or incorrect side chain status."); - Assert(input.IndexingFee >= 0, "Invalid side chain fee price."); - var expectedOrganizationAddress = info.IndexingFeeController.OwnerAddress; - Assert(expectedOrganizationAddress == Context.Sender, "No permission."); - info.IndexingPrice = input.IndexingFee; - State.SideChainInfo[input.SideChainId] = info; - return new Empty(); - } + sideChainInfo.ArrearsInfo.Clear(); + sideChainInfo.SideChainStatus = SideChainStatus.Active; + State.SideChainInfo[chainId] = sideChainInfo; + return new Empty(); + } - public override Empty ChangeSideChainIndexingFeeController(ChangeSideChainIndexingFeeControllerInput input) - { - var sideChainInfo = State.SideChainInfo[input.ChainId]; - var authorityInfo = sideChainInfo.IndexingFeeController; - Assert(authorityInfo.OwnerAddress == Context.Sender, "No permission."); - Assert(ValidateAuthorityInfoExists(input.AuthorityInfo), "Invalid authority input."); - sideChainInfo.IndexingFeeController = input.AuthorityInfo; - State.SideChainInfo[input.ChainId] = sideChainInfo; - Context.Fire(new SideChainIndexingFeeControllerChanged - { - ChainId = input.ChainId, - AuthorityInfo = input.AuthorityInfo - }); - return new Empty(); - } + /// + /// Dispose side chain. It is a proposal result from system address. + /// + /// + /// + public override Int32Value DisposeSideChain(Int32Value input) + { + AssertSideChainLifetimeControllerAuthority(Context.Sender); - #endregion Side chain lifetime actions + var chainId = input.Value; + var info = State.SideChainInfo[chainId]; + Assert(info != null, "Side chain not found."); + Assert(info.SideChainStatus != SideChainStatus.Terminated, "Incorrect chain status."); - #region Cross chain indexing actions + if (TryGetIndexingProposal(chainId, out _)) + ResetChainIndexingProposal(chainId); - /// - /// Propose cross chain block data to be indexed and create a proposal. - /// - /// - /// - public override Empty ProposeCrossChainIndexing(CrossChainBlockData input) + UnlockTokenAndResource(info); + info.SideChainStatus = SideChainStatus.Terminated; + State.SideChainInfo[chainId] = info; + Context.Fire(new Disposed { - Context.LogDebug(() => "Proposing cross chain data.."); - EnsureTransactionOnlyExecutedOnceInOneBlock(); - AssertAddressIsCurrentMiner(Context.Sender); - ClearCrossChainIndexingProposalIfExpired(); - var crossChainDataDto = ValidateCrossChainDataBeforeIndexing(input); - ProposeCrossChainBlockData(crossChainDataDto, Context.Sender); - return new Empty(); - } + ChainId = chainId + }); + return new Int32Value { Value = chainId }; + } - public override Empty ReleaseCrossChainIndexingProposal(ReleaseCrossChainIndexingProposalInput input) - { - Context.LogDebug(() => "Releasing cross chain data.."); - EnsureTransactionOnlyExecutedOnceInOneBlock(); - AssertAddressIsCurrentMiner(Context.Sender); - Assert(input.ChainIdList.Count > 0, "Empty input not allowed."); - ReleaseIndexingProposal(input.ChainIdList); - RecordCrossChainData(input.ChainIdList); - return new Empty(); - } + public override Empty AdjustIndexingFeePrice(AdjustIndexingFeeInput input) + { + var info = State.SideChainInfo[input.SideChainId]; + Assert(info != null && info.SideChainStatus != SideChainStatus.Terminated, + "Side chain not found or incorrect side chain status."); + Assert(input.IndexingFee >= 0, "Invalid side chain fee price."); + var expectedOrganizationAddress = info.IndexingFeeController.OwnerAddress; + Assert(expectedOrganizationAddress == Context.Sender, "No permission."); + info.IndexingPrice = input.IndexingFee; + State.SideChainInfo[input.SideChainId] = info; + return new Empty(); + } - public override Empty AcceptCrossChainIndexingProposal(AcceptCrossChainIndexingProposalInput input) + public override Empty ChangeSideChainIndexingFeeController(ChangeSideChainIndexingFeeControllerInput input) + { + var sideChainInfo = State.SideChainInfo[input.ChainId]; + var authorityInfo = sideChainInfo.IndexingFeeController; + Assert(authorityInfo.OwnerAddress == Context.Sender, "No permission."); + Assert(ValidateAuthorityInfoExists(input.AuthorityInfo), "Invalid authority input."); + sideChainInfo.IndexingFeeController = input.AuthorityInfo; + State.SideChainInfo[input.ChainId] = sideChainInfo; + Context.Fire(new SideChainIndexingFeeControllerChanged { - AssertCrossChainIndexingControllerAuthority(Context.Sender); - AssertIsCrossChainBlockDataAccepted(input.ChainId); - ResetChainIndexingProposal(input.ChainId); - return new Empty(); - } + ChainId = input.ChainId, + AuthorityInfo = input.AuthorityInfo + }); + return new Empty(); + } - #endregion Cross chain actions + #endregion Side chain lifetime actions - public override Empty ChangeCrossChainIndexingController(AuthorityInfo input) - { - AssertCrossChainIndexingControllerAuthority(Context.Sender); - SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - Assert( - input.ContractAddress == State.ParliamentContract.Value && - ValidateParliamentOrganization(input.OwnerAddress), "Invalid authority input."); - State.CrossChainIndexingController.Value = input; - Context.Fire(new CrossChainIndexingControllerChanged - { - AuthorityInfo = input - }); - return new Empty(); - } + #region Cross chain indexing actions - public override Empty ChangeSideChainLifetimeController(AuthorityInfo input) - { - AssertSideChainLifetimeControllerAuthority(Context.Sender); - Assert(ValidateAuthorityInfoExists(input), "Invalid authority input."); - State.SideChainLifetimeController.Value = input; - Context.Fire(new SideChainLifetimeControllerChanged() - { - AuthorityInfo = input - }); - return new Empty(); - } + /// + /// Propose cross chain block data to be indexed and create a proposal. + /// + /// + /// + public override Empty ProposeCrossChainIndexing(CrossChainBlockData input) + { + Context.LogDebug(() => "Proposing cross chain data.."); + EnsureTransactionOnlyExecutedOnceInOneBlock(); + AssertAddressIsCurrentMiner(Context.Sender); + ClearCrossChainIndexingProposalIfExpired(); + var crossChainDataDto = ValidateCrossChainDataBeforeIndexing(input); + ProposeCrossChainBlockData(crossChainDataDto, Context.Sender); + return new Empty(); } + + public override Empty ReleaseCrossChainIndexingProposal(ReleaseCrossChainIndexingProposalInput input) + { + Context.LogDebug(() => "Releasing cross chain data.."); + EnsureTransactionOnlyExecutedOnceInOneBlock(); + AssertAddressIsCurrentMiner(Context.Sender); + Assert(input.ChainIdList.Count > 0, "Empty input not allowed."); + ReleaseIndexingProposal(input.ChainIdList); + RecordCrossChainData(input.ChainIdList); + return new Empty(); + } + + public override Empty AcceptCrossChainIndexingProposal(AcceptCrossChainIndexingProposalInput input) + { + AssertCrossChainIndexingControllerAuthority(Context.Sender); + AssertIsCrossChainBlockDataAccepted(input.ChainId); + ResetChainIndexingProposal(input.ChainId); + return new Empty(); + } + + #endregion Cross chain actions } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContractState.cs b/contract/AElf.Contracts.CrossChain/CrossChainContractState.cs index 47903e68d5..1579939b38 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContractState.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContractState.cs @@ -1,52 +1,51 @@ +using AElf.Sdk.CSharp.State; using AElf.Standards.ACS1; using AElf.Standards.ACS7; -using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.CrossChain +namespace AElf.Contracts.CrossChain; + +public partial class CrossChainContractState : ContractState { - public partial class CrossChainContractState : ContractState - { - public BoolState Initialized { get; set; } - public Int64State SideChainSerialNumber { get; set; } - - public SingletonState CrossChainIndexingController { get; set; } - - public SingletonState SideChainLifetimeController { get; set; } - - public MappedState TransactionFees { get; set; } - - public SingletonState IndexingPendingProposal { get; set; } - - public MappedState ProposedSideChainCreationRequestState { get; set; } - - public MappedState AcceptedSideChainCreationRequest { get; set; } - - - public SingletonState MethodFeeController { get; set; } - - #region side chain - - public MappedState SideChainInfo { get; set; } - public MappedState CurrentSideChainHeight { get; set; } - - internal MappedState SideChainInitializationData { get; set; } - - public MappedState IndexedSideChainBlockData { get; set; } - - #endregion - - #region parent chain - - public MappedState TransactionMerkleTreeRootRecordedInParentChain { get; set; } - public MappedState ChildHeightToParentChainHeight { get; set; } - public MappedState TxRootMerklePathInParentChain { get; set; } - public Int64State CurrentParentChainHeight { get; set; } - public Int32State ParentChainId { get; set; } - public MappedState ParentChainTransactionStatusMerkleTreeRoot { get; set; } - - #endregion - - public SingletonState LatestExecutedHeight { get; set; } - } + public BoolState Initialized { get; set; } + public Int64State SideChainSerialNumber { get; set; } + + public SingletonState CrossChainIndexingController { get; set; } + + public SingletonState SideChainLifetimeController { get; set; } + + public MappedState TransactionFees { get; set; } + + public SingletonState IndexingPendingProposal { get; set; } + + public MappedState ProposedSideChainCreationRequestState { get; set; } + + public MappedState AcceptedSideChainCreationRequest { get; set; } + + + public SingletonState MethodFeeController { get; set; } + + public SingletonState LatestExecutedHeight { get; set; } + + #region side chain + + public MappedState SideChainInfo { get; set; } + public MappedState CurrentSideChainHeight { get; set; } + + internal MappedState SideChainInitializationData { get; set; } + + public MappedState IndexedSideChainBlockData { get; set; } + + #endregion + + #region parent chain + + public MappedState TransactionMerkleTreeRootRecordedInParentChain { get; set; } + public MappedState ChildHeightToParentChainHeight { get; set; } + public MappedState TxRootMerklePathInParentChain { get; set; } + public Int64State CurrentParentChainHeight { get; set; } + public Int32State ParentChainId { get; set; } + public MappedState ParentChainTransactionStatusMerkleTreeRoot { get; set; } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract_ACS1_TransactionFeeProvider.cs index 4ec8c54639..684e410592 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract_ACS1_TransactionFeeProvider.cs @@ -1,108 +1,99 @@ using System.Collections.Generic; +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.CrossChain +namespace AElf.Contracts.CrossChain; + +public partial class CrossChainContract { - public partial class CrossChainContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - public override MethodFees GetMethodFee(StringValue input) - { - if (new List - { - nameof(ProposeCrossChainIndexing), nameof(ReleaseCrossChainIndexingProposal) - }.Contains(input.Value)) - { - return new MethodFees - { - MethodName = input.Value, - IsSizeFeeFree = true - }; - } - return State.TransactionFees[input.Value]; - } - - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + RequiredMethodFeeControllerSet(); - #endregion + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - - RequiredMethodFeeControllerSet(); + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - return new Empty(); - } + State.MethodFeeController.Value = input; + return new Empty(); + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #region Views - State.MethodFeeController.Value = input; - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + if (new List + { + nameof(ProposeCrossChainIndexing), nameof(ReleaseCrossChainIndexingProposal) + }.Contains(input.Value)) + return new MethodFees + { + MethodName = input.Value, + IsSizeFeeFree = true + }; + return State.TransactionFees[input.Value]; + } - #region private methods + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); + #endregion - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; + #region private methods - State.MethodFeeController.Value = defaultAuthority; - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - private void AssertSenderAddressWith(Address address) + var defaultAuthority = new AuthorityInfo { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + State.MethodFeeController.Value = defaultAuthority; + } - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - #endregion + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract_Constants.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract_Constants.cs index 30d357d175..3a52cc8e4e 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract_Constants.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract_Constants.cs @@ -1,15 +1,14 @@ -namespace AElf.Contracts.CrossChain +namespace AElf.Contracts.CrossChain; + +public partial class CrossChainContract { - public partial class CrossChainContract - { - private const int CrossChainIndexingProposalExpirationTimePeriod = 120; - private const long CrossChainIndexingBannedBlockHeightInterval = 256; - private const int SideChainCreationProposalExpirationTimePeriod = 86400; // 60 * 60 * 24 - private const int DefaultMinimalApprovalThreshold = 6667; - private const int DefaultMaximalAbstentionThreshold = 1000; - private const int DefaultMaximalRejectionThreshold = 1000; - private const int DefaultMinimalVoteThresholdThreshold = 6667; - - private const string PayRentalSymbolListName = "SymbolListToPayRental"; - } + private const int CrossChainIndexingProposalExpirationTimePeriod = 120; + private const long CrossChainIndexingBannedBlockHeightInterval = 256; + private const int SideChainCreationProposalExpirationTimePeriod = 86400; // 60 * 60 * 24 + private const int DefaultMinimalApprovalThreshold = 6667; + private const int DefaultMaximalAbstentionThreshold = 1000; + private const int DefaultMaximalRejectionThreshold = 1000; + private const int DefaultMinimalVoteThresholdThreshold = 6667; + + private const string PayRentalSymbolListName = "SymbolListToPayRental"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs index e2778eac02..7161618577 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs @@ -1,920 +1,911 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.Association; using AElf.Contracts.MultiToken; using AElf.CSharp.Core.Extension; using AElf.CSharp.Core.Utils; using AElf.Sdk.CSharp; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; +using CreateOrganizationBySystemContractInput = AElf.Contracts.Parliament.CreateOrganizationBySystemContractInput; + +namespace AElf.Contracts.CrossChain; -namespace AElf.Contracts.CrossChain +public partial class CrossChainContract { - public partial class CrossChainContract + private const string ConsensusExtraDataName = "Consensus"; + + /// + /// Bind parent chain height together with self height. + /// + /// + /// + private void BindParentChainHeight(long childHeight, long parentHeight) { - private const string ConsensusExtraDataName = "Consensus"; + Assert(State.ChildHeightToParentChainHeight[childHeight] == 0, + $"Already bound at height {childHeight} with parent chain"); + State.ChildHeightToParentChainHeight[childHeight] = parentHeight; + } - /// - /// Bind parent chain height together with self height. - /// - /// - /// - private void BindParentChainHeight(long childHeight, long parentHeight) - { - Assert(State.ChildHeightToParentChainHeight[childHeight] == 0, - $"Already bound at height {childHeight} with parent chain"); - State.ChildHeightToParentChainHeight[childHeight] = parentHeight; - } + private Hash ComputeRootWithTransactionStatusMerklePath(Hash txId, MerklePath path) + { + var txResultStatusRawBytes = + EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString()); + var hash = HashHelper.ComputeFrom(ByteArrayHelper.ConcatArrays(txId.ToByteArray(), txResultStatusRawBytes)); + return path.ComputeRootWithLeafNode(hash); + } - private Hash ComputeRootWithTransactionStatusMerklePath(Hash txId, MerklePath path) - { - var txResultStatusRawBytes = - EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString()); - var hash = HashHelper.ComputeFrom(ByteArrayHelper.ConcatArrays(txId.ToByteArray(), txResultStatusRawBytes)); - return path.ComputeRootWithLeafNode(hash); - } + private Hash ComputeRootWithMultiHash(IEnumerable nodes) + { + return BinaryMerkleTree.FromLeafNodes(nodes).Root; + } - private Hash ComputeRootWithMultiHash(IEnumerable nodes) - { - return BinaryMerkleTree.FromLeafNodes(nodes).Root; - } + /// + /// Record merkle path of self chain block, which is from parent chain. + /// + /// + /// + private void AddIndexedTxRootMerklePathInParentChain(long height, MerklePath path) + { + var existing = State.TxRootMerklePathInParentChain[height]; + Assert(existing == null, + $"Merkle path already bound at height {height}."); + State.TxRootMerklePathInParentChain[height] = path; + } - /// - /// Record merkle path of self chain block, which is from parent chain. - /// - /// - /// - private void AddIndexedTxRootMerklePathInParentChain(long height, MerklePath path) - { - var existing = State.TxRootMerklePathInParentChain[height]; - Assert(existing == null, - $"Merkle path already bound at height {height}."); - State.TxRootMerklePathInParentChain[height] = path; - } + private void ChargeSideChainIndexingFee(Address lockAddress, long amount, int chainId) + { + if (amount <= 0) + return; + TransferFrom(new TransferFromInput + { + From = lockAddress, + To = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), + Amount = amount, + Symbol = Context.Variables.NativeSymbol + }); + } - private void ChargeSideChainIndexingFee(Address lockAddress, long amount, int chainId) - { - if (amount <= 0) - return; - TransferFrom(new TransferFromInput - { - From = lockAddress, - To = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), - Amount = amount, - Symbol = Context.Variables.NativeSymbol - }); - } + private void UnlockTokenAndResource(SideChainInfo sideChainInfo) + { + // unlock token + var chainId = sideChainInfo.SideChainId; + var balance = GetSideChainIndexingFeeDeposit(chainId); + if (balance <= 0) + return; + TransferDepositToken(new TransferInput + { + To = sideChainInfo.Proposer, + Amount = balance, + Symbol = Context.Variables.NativeSymbol + }, chainId); + } - private void UnlockTokenAndResource(SideChainInfo sideChainInfo) + private long GetSideChainIndexingFeeDeposit(int chainId) + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + var balanceOutput = State.TokenContract.GetBalance.Call(new GetBalanceInput { - // unlock token - var chainId = sideChainInfo.SideChainId; - var balance = GetSideChainIndexingFeeDeposit(chainId); - if (balance <= 0) - return; - TransferDepositToken(new TransferInput - { - To = sideChainInfo.Proposer, - Amount = balance, - Symbol = Context.Variables.NativeSymbol - }, chainId); - } + Owner = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), + Symbol = Context.Variables.NativeSymbol + }); - private long GetSideChainIndexingFeeDeposit(int chainId) - { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - var balanceOutput = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = Context.ConvertVirtualAddressToContractAddress(ConvertChainIdToHash(chainId)), - Symbol = Context.Variables.NativeSymbol - }); + return balanceOutput.Balance; + } - return balanceOutput.Balance; - } + private void AssertValidSideChainCreationRequest(SideChainCreationRequest sideChainCreationRequest, + Address proposer) + { + var proposedRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; + Assert(proposedRequest == null || Context.CurrentBlockTime >= proposedRequest.ExpiredTime, + "Request side chain creation failed."); - private void AssertValidSideChainCreationRequest(SideChainCreationRequest sideChainCreationRequest, - Address proposer) + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput { - var proposedRequest = State.ProposedSideChainCreationRequestState[Context.Sender]; - Assert(proposedRequest == null || Context.CurrentBlockTime >= proposedRequest.ExpiredTime, - "Request side chain creation failed."); + Owner = proposer, + Spender = Context.Self, + Symbol = Context.Variables.NativeSymbol + }).Allowance; - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput - { - Owner = proposer, - Spender = Context.Self, - Symbol = Context.Variables.NativeSymbol - }).Allowance; - - Assert( - allowance >= sideChainCreationRequest.LockedTokenAmount, - "Allowance not enough."); + Assert( + allowance >= sideChainCreationRequest.LockedTokenAmount, + "Allowance not enough."); - Assert( - sideChainCreationRequest.IndexingPrice >= 0 && - sideChainCreationRequest.LockedTokenAmount >= sideChainCreationRequest.IndexingPrice, - "Invalid chain creation request."); + Assert( + sideChainCreationRequest.IndexingPrice >= 0 && + sideChainCreationRequest.LockedTokenAmount >= sideChainCreationRequest.IndexingPrice, + "Invalid chain creation request."); - if (!sideChainCreationRequest.IsPrivilegePreserved) - return; // there is no restriction for non-exclusive side chain creation + if (!sideChainCreationRequest.IsPrivilegePreserved) + return; // there is no restriction for non-exclusive side chain creation - AssertValidResourceTokenAmount(sideChainCreationRequest); + AssertValidResourceTokenAmount(sideChainCreationRequest); - if (!IsPrimaryTokenNeeded(sideChainCreationRequest)) - return; + if (!IsPrimaryTokenNeeded(sideChainCreationRequest)) + return; - // assert primary token to create - AssertValidSideChainTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest); - Assert(sideChainCreationRequest.SideChainTokenInitialIssueList.Count > 0 && - sideChainCreationRequest.SideChainTokenInitialIssueList.All(issue => issue.Amount > 0), - "Invalid side chain token initial issue list."); - } - - private void AssertValidResourceTokenAmount(SideChainCreationRequest sideChainCreationRequest) - { - var resourceTokenMap = sideChainCreationRequest.InitialResourceAmount; - foreach (var resourceTokenSymbol in Context.Variables.GetStringArray(PayRentalSymbolListName)) - { - Assert(resourceTokenMap.ContainsKey(resourceTokenSymbol) && resourceTokenMap[resourceTokenSymbol] > 0, - "Invalid side chain resource token request."); - } - } + // assert primary token to create + AssertValidSideChainTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest); + Assert(sideChainCreationRequest.SideChainTokenInitialIssueList.Count > 0 && + sideChainCreationRequest.SideChainTokenInitialIssueList.All(issue => issue.Amount > 0), + "Invalid side chain token initial issue list."); + } - private void AssertValidSideChainTokenInfo(SideChainTokenCreationRequest sideChainTokenCreationRequest) - { - Assert( - !string.IsNullOrEmpty(sideChainTokenCreationRequest.SideChainTokenSymbol) && - !string.IsNullOrEmpty(sideChainTokenCreationRequest.SideChainTokenName), - "Invalid side chain token name."); - Assert(sideChainTokenCreationRequest.SideChainTokenTotalSupply > 0, "Invalid side chain token supply."); - } + private void AssertValidResourceTokenAmount(SideChainCreationRequest sideChainCreationRequest) + { + var resourceTokenMap = sideChainCreationRequest.InitialResourceAmount; + foreach (var resourceTokenSymbol in Context.Variables.GetStringArray(PayRentalSymbolListName)) + Assert(resourceTokenMap.ContainsKey(resourceTokenSymbol) && resourceTokenMap[resourceTokenSymbol] > 0, + "Invalid side chain resource token request."); + } - private void SetContractStateRequired(ContractReferenceState state, string contractSystemName) - { - if (state.Value != null) - return; - state.Value = Context.GetContractAddressByName(contractSystemName); - } + private void AssertValidSideChainTokenInfo(SideChainTokenCreationRequest sideChainTokenCreationRequest) + { + Assert( + !string.IsNullOrEmpty(sideChainTokenCreationRequest.SideChainTokenSymbol) && + !string.IsNullOrEmpty(sideChainTokenCreationRequest.SideChainTokenName), + "Invalid side chain token name."); + Assert(sideChainTokenCreationRequest.SideChainTokenTotalSupply > 0, "Invalid side chain token supply."); + } - private void TransferDepositToken(TransferInput input, int chainId) - { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - Context.SendVirtualInline(ConvertChainIdToHash(chainId), State.TokenContract.Value, - nameof(State.TokenContract.Transfer), input); - } + private void SetContractStateRequired(ContractReferenceState state, string contractSystemName) + { + if (state.Value != null) + return; + state.Value = Context.GetContractAddressByName(contractSystemName); + } - private void TransferFrom(TransferFromInput input) - { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - State.TokenContract.TransferFrom.Send(input); - } + private void TransferDepositToken(TransferInput input, int chainId) + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + Context.SendVirtualInline(ConvertChainIdToHash(chainId), State.TokenContract.Value, + nameof(State.TokenContract.Transfer), input); + } - private void CreateSideChainToken(SideChainCreationRequest sideChainCreationRequest, int chainId, - Address creator) - { - if (!IsPrimaryTokenNeeded(sideChainCreationRequest)) - return; + private void TransferFrom(TransferFromInput input) + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + State.TokenContract.TransferFrom.Send(input); + } - // new token needed only for exclusive side chain - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - State.TokenContract.Create.Send(new CreateInput - { - TokenName = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenName, - Decimals = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenDecimals, - IsBurnable = true, - Issuer = creator, - IssueChainId = chainId, - Symbol = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol, - TotalSupply = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenTotalSupply - }); - } + private void CreateSideChainToken(SideChainCreationRequest sideChainCreationRequest, int chainId, + Address creator) + { + if (!IsPrimaryTokenNeeded(sideChainCreationRequest)) + return; + + // new token needed only for exclusive side chain + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + State.TokenContract.Create.Send(new CreateInput + { + TokenName = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenName, + Decimals = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenDecimals, + IsBurnable = true, + Issuer = creator, + IssueChainId = chainId, + Symbol = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol, + TotalSupply = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenTotalSupply + }); + } - private TokenInfo GetNativeTokenInfo() - { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - return State.TokenContract.GetNativeTokenInfo.Call(new Empty()); - } + private TokenInfo GetNativeTokenInfo() + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + return State.TokenContract.GetNativeTokenInfo.Call(new Empty()); + } - private TokenInfo GetTokenInfo(string symbol) + private TokenInfo GetTokenInfo(string symbol) + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + return State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - return State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput - { - Symbol = symbol - }); - } + Symbol = symbol + }); + } - private TokenInfoList GetResourceTokenInfo() - { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - return State.TokenContract.GetResourceTokenInfo.Call(new Empty()); - } + private TokenInfoList GetResourceTokenInfo() + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + return State.TokenContract.GetResourceTokenInfo.Call(new Empty()); + } - private ByteString GetInitialConsensusInformation() - { - SetContractStateRequired(State.CrossChainInteractionContract, - SmartContractConstants.ConsensusContractSystemName); - var miners = State.CrossChainInteractionContract.GetChainInitializationInformation.Call(new BytesValue()); - return miners.Value; - } + private ByteString GetInitialConsensusInformation() + { + SetContractStateRequired(State.CrossChainInteractionContract, + SmartContractConstants.ConsensusContractSystemName); + var miners = State.CrossChainInteractionContract.GetChainInitializationInformation.Call(new BytesValue()); + return miners.Value; + } - // only for side chain - private void UpdateConsensusInformation(ByteString bytes) - { - SetContractStateRequired(State.CrossChainInteractionContract, - SmartContractConstants.ConsensusContractSystemName); - Context.SendInline(State.CrossChainInteractionContract.Value, - nameof(State.CrossChainInteractionContract.UpdateInformationFromCrossChain), - new BytesValue {Value = bytes}); - } + // only for side chain + private void UpdateConsensusInformation(ByteString bytes) + { + SetContractStateRequired(State.CrossChainInteractionContract, + SmartContractConstants.ConsensusContractSystemName); + Context.SendInline(State.CrossChainInteractionContract.Value, + nameof(State.CrossChainInteractionContract.UpdateInformationFromCrossChain), + new BytesValue { Value = bytes }); + } - private Hash GetParentChainMerkleTreeRoot(long parentChainHeight) - { - return State.ParentChainTransactionStatusMerkleTreeRoot[parentChainHeight]; - } + private Hash GetParentChainMerkleTreeRoot(long parentChainHeight) + { + return State.ParentChainTransactionStatusMerkleTreeRoot[parentChainHeight]; + } - private Hash GetSideChainMerkleTreeRoot(long parentChainHeight) - { - var indexedSideChainData = State.IndexedSideChainBlockData[parentChainHeight]; - return ComputeRootWithMultiHash( - indexedSideChainData.SideChainBlockDataList.Select(d => d.TransactionStatusMerkleTreeRoot)); - } + private Hash GetSideChainMerkleTreeRoot(long parentChainHeight) + { + var indexedSideChainData = State.IndexedSideChainBlockData[parentChainHeight]; + return ComputeRootWithMultiHash( + indexedSideChainData.SideChainBlockDataList.Select(d => d.TransactionStatusMerkleTreeRoot)); + } - private Hash GetCousinChainMerkleTreeRoot(long parentChainHeight) - { - return State.TransactionMerkleTreeRootRecordedInParentChain[parentChainHeight]; - } + private Hash GetCousinChainMerkleTreeRoot(long parentChainHeight) + { + return State.TransactionMerkleTreeRootRecordedInParentChain[parentChainHeight]; + } - private Hash GetMerkleTreeRoot(int chainId, long parentChainHeight) - { - if (chainId == State.ParentChainId.Value) - { - // it is parent chain - return GetParentChainMerkleTreeRoot(parentChainHeight); - } + private Hash GetMerkleTreeRoot(int chainId, long parentChainHeight) + { + if (chainId == State.ParentChainId.Value) + // it is parent chain + return GetParentChainMerkleTreeRoot(parentChainHeight); - if (State.SideChainInfo[chainId] != null) - { - // it is child chain - return GetSideChainMerkleTreeRoot(parentChainHeight); - } + if (State.SideChainInfo[chainId] != null) + // it is child chain + return GetSideChainMerkleTreeRoot(parentChainHeight); - return GetCousinChainMerkleTreeRoot(parentChainHeight); - } + return GetCousinChainMerkleTreeRoot(parentChainHeight); + } - private AuthorityInfo GetCrossChainIndexingController() - { - return State.CrossChainIndexingController.Value; - } + private AuthorityInfo GetCrossChainIndexingController() + { + return State.CrossChainIndexingController.Value; + } - private AuthorityInfo GetSideChainLifetimeController() - { - return State.SideChainLifetimeController.Value; - } + private AuthorityInfo GetSideChainLifetimeController() + { + return State.SideChainLifetimeController.Value; + } - private void AssertCrossChainIndexingControllerAuthority(Address address) - { - var crossChainIndexingController = GetCrossChainIndexingController(); - Assert(crossChainIndexingController.OwnerAddress == address, "Unauthorized behavior."); - } + private void AssertCrossChainIndexingControllerAuthority(Address address) + { + var crossChainIndexingController = GetCrossChainIndexingController(); + Assert(crossChainIndexingController.OwnerAddress == address, "Unauthorized behavior."); + } - private void AssertSideChainLifetimeControllerAuthority(Address address) - { - var sideChainLifetimeController = GetSideChainLifetimeController(); - Assert(sideChainLifetimeController.OwnerAddress == address, "Unauthorized behavior."); - } + private void AssertSideChainLifetimeControllerAuthority(Address address) + { + var sideChainLifetimeController = GetSideChainLifetimeController(); + Assert(sideChainLifetimeController.OwnerAddress == address, "Unauthorized behavior."); + } - private void AssertAddressIsCurrentMiner(Address address) - { - SetContractStateRequired(State.CrossChainInteractionContract, - SmartContractConstants.ConsensusContractSystemName); - var isCurrentMiner = State.CrossChainInteractionContract.CheckCrossChainIndexingPermission.Call(address) - .Value; - Assert(isCurrentMiner, "No permission."); - } + private void AssertAddressIsCurrentMiner(Address address) + { + SetContractStateRequired(State.CrossChainInteractionContract, + SmartContractConstants.ConsensusContractSystemName); + var isCurrentMiner = State.CrossChainInteractionContract.CheckCrossChainIndexingPermission.Call(address) + .Value; + Assert(isCurrentMiner, "No permission."); + } - private void ReleaseIndexingProposal(IEnumerable chainIdList) + private void ReleaseIndexingProposal(IEnumerable chainIdList) + { + foreach (var chainId in chainIdList) { - foreach (var chainId in chainIdList) - { - var pendingProposalExists = TryGetIndexingProposalWithStatus(chainId, - CrossChainIndexingProposalStatus.Pending, - out var pendingCrossChainIndexingProposal); - Assert(pendingProposalExists, "Chain indexing not proposed."); - HandleIndexingProposal(pendingCrossChainIndexingProposal.ProposalId); - } + var pendingProposalExists = TryGetIndexingProposalWithStatus(chainId, + CrossChainIndexingProposalStatus.Pending, + out var pendingCrossChainIndexingProposal); + Assert(pendingProposalExists, "Chain indexing not proposed."); + HandleIndexingProposal(pendingCrossChainIndexingProposal.ProposalId); } + } - private void RecordCrossChainData(IEnumerable chainIdList) + private void RecordCrossChainData(IEnumerable chainIdList) + { + var indexedSideChainBlockData = new IndexedSideChainBlockData(); + foreach (var chainId in chainIdList) { - var indexedSideChainBlockData = new IndexedSideChainBlockData(); - foreach (var chainId in chainIdList) - { - var pendingProposalExists = TryGetIndexingProposalWithStatus(chainId, - CrossChainIndexingProposalStatus.Pending, - out var pendingCrossChainIndexingProposal); - Assert(pendingProposalExists, "Chain indexing not proposed."); - - if (chainId == State.ParentChainId.Value) - IndexParentChainBlockData(pendingCrossChainIndexingProposal.ProposedCrossChainBlockData - .ParentChainBlockDataList); - else - indexedSideChainBlockData.SideChainBlockDataList.Add(IndexSideChainBlockData( - pendingCrossChainIndexingProposal.ProposedCrossChainBlockData.SideChainBlockDataList, - pendingCrossChainIndexingProposal.Proposer, chainId)); + var pendingProposalExists = TryGetIndexingProposalWithStatus(chainId, + CrossChainIndexingProposalStatus.Pending, + out var pendingCrossChainIndexingProposal); + Assert(pendingProposalExists, "Chain indexing not proposed."); - SetCrossChainIndexingProposalStatus(pendingCrossChainIndexingProposal, - CrossChainIndexingProposalStatus.Accepted); - } + if (chainId == State.ParentChainId.Value) + IndexParentChainBlockData(pendingCrossChainIndexingProposal.ProposedCrossChainBlockData + .ParentChainBlockDataList); + else + indexedSideChainBlockData.SideChainBlockDataList.Add(IndexSideChainBlockData( + pendingCrossChainIndexingProposal.ProposedCrossChainBlockData.SideChainBlockDataList, + pendingCrossChainIndexingProposal.Proposer, chainId)); - if (indexedSideChainBlockData.SideChainBlockDataList.Count > 0) - { - State.IndexedSideChainBlockData.Set(Context.CurrentHeight, indexedSideChainBlockData); - Context.Fire(new SideChainBlockDataIndexed()); - } + SetCrossChainIndexingProposalStatus(pendingCrossChainIndexingProposal, + CrossChainIndexingProposalStatus.Accepted); } - private void AssertParentChainBlock(int parentChainId, long currentRecordedHeight, - ParentChainBlockData parentChainBlockData) + if (indexedSideChainBlockData.SideChainBlockDataList.Count > 0) { - Assert(parentChainId == parentChainBlockData.ChainId, "Wrong parent chain id."); - Assert(currentRecordedHeight + 1 == parentChainBlockData.Height, - $"Parent chain block info at height {currentRecordedHeight + 1} is needed, not {parentChainBlockData.Height}"); - Assert(parentChainBlockData.TransactionStatusMerkleTreeRoot != null, - "Parent chain transaction status merkle tree root needed."); + State.IndexedSideChainBlockData.Set(Context.CurrentHeight, indexedSideChainBlockData); + Context.Fire(new SideChainBlockDataIndexed()); } + } - private void AssertIsCrossChainBlockDataAccepted(int chainId) - { - var pendingProposalExists = - TryGetIndexingProposalWithStatus(chainId, CrossChainIndexingProposalStatus.Accepted, out _); - Assert(pendingProposalExists, "Incorrect cross chain indexing proposal status."); - } + private void AssertParentChainBlock(int parentChainId, long currentRecordedHeight, + ParentChainBlockData parentChainBlockData) + { + Assert(parentChainId == parentChainBlockData.ChainId, "Wrong parent chain id."); + Assert(currentRecordedHeight + 1 == parentChainBlockData.Height, + $"Parent chain block info at height {currentRecordedHeight + 1} is needed, not {parentChainBlockData.Height}"); + Assert(parentChainBlockData.TransactionStatusMerkleTreeRoot != null, + "Parent chain transaction status merkle tree root needed."); + } + + private void AssertIsCrossChainBlockDataAccepted(int chainId) + { + var pendingProposalExists = + TryGetIndexingProposalWithStatus(chainId, CrossChainIndexingProposalStatus.Accepted, out _); + Assert(pendingProposalExists, "Incorrect cross chain indexing proposal status."); + } - private int GetChainId(long serialNumber) + private int GetChainId(long serialNumber) + { + return ChainHelper.GetChainId(serialNumber + Context.ChainId); + } + + private SideChainCreationRequestState ProposeNewSideChain(SideChainCreationRequest request, Address proposer) + { + var sideChainLifeTimeController = GetSideChainLifetimeController(); + var proposalCreationInput = new CreateProposalBySystemContractInput { - return ChainHelper.GetChainId(serialNumber + Context.ChainId); - } + ProposalInput = + new CreateProposalInput + { + ContractMethodName = nameof(CreateSideChain), + ToAddress = Context.Self, + ExpiredTime = + Context.CurrentBlockTime.AddSeconds(SideChainCreationProposalExpirationTimePeriod), + Params = new CreateSideChainInput { SideChainCreationRequest = request, Proposer = proposer } + .ToByteString(), + OrganizationAddress = sideChainLifeTimeController.OwnerAddress + }, + OriginProposer = Context.Sender + }; + Context.SendInline(sideChainLifeTimeController.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState + .CreateProposalBySystemContract), proposalCreationInput); + var sideChainCreationRequest = new SideChainCreationRequestState + { + SideChainCreationRequest = request, + ExpiredTime = proposalCreationInput.ProposalInput.ExpiredTime, + Proposer = proposer + }; + return sideChainCreationRequest; + } - private SideChainCreationRequestState ProposeNewSideChain(SideChainCreationRequest request, Address proposer) + private void ProposeCrossChainBlockData(CrossChainDataDto crossChainDataDto, Address proposer) + { + var crossChainIndexingController = GetCrossChainIndexingController(); + foreach (var chainId in crossChainDataDto.GetChainIdList()) { - var sideChainLifeTimeController = GetSideChainLifetimeController(); + Assert(!TryGetIndexingProposal(chainId, out _), "Chain indexing already proposed."); + var proposalToken = + HashHelper.ConcatAndCompute(Context.PreviousBlockHash, ConvertChainIdToHash(chainId)); var proposalCreationInput = new CreateProposalBySystemContractInput { - ProposalInput = - new CreateProposalInput + ProposalInput = new CreateProposalInput + { + Params = new AcceptCrossChainIndexingProposalInput { - ContractMethodName = nameof(CreateSideChain), - ToAddress = Context.Self, - ExpiredTime = - Context.CurrentBlockTime.AddSeconds(SideChainCreationProposalExpirationTimePeriod), - Params = new CreateSideChainInput {SideChainCreationRequest = request, Proposer = proposer} - .ToByteString(), - OrganizationAddress = sideChainLifeTimeController.OwnerAddress - }, + ChainId = chainId + }.ToByteString(), + ContractMethodName = nameof(AcceptCrossChainIndexingProposal), + ExpiredTime = + Context.CurrentBlockTime.AddSeconds(CrossChainIndexingProposalExpirationTimePeriod), + OrganizationAddress = crossChainIndexingController.OwnerAddress, + ToAddress = Context.Self, + Token = proposalToken + }, OriginProposer = Context.Sender }; - Context.SendInline(sideChainLifeTimeController.ContractAddress, + + Context.SendInline(crossChainIndexingController.ContractAddress, nameof(AuthorizationContractContainer.AuthorizationContractReferenceState .CreateProposalBySystemContract), proposalCreationInput); - var sideChainCreationRequest = new SideChainCreationRequestState() + + var proposedCrossChainBlockData = new CrossChainBlockData(); + if (crossChainDataDto.ParentChainToBeIndexedData.TryGetValue(chainId, + out var parentChainToBeIndexedData)) + proposedCrossChainBlockData.ParentChainBlockDataList.Add(parentChainToBeIndexedData); + else if (crossChainDataDto.SideChainToBeIndexedData.TryGetValue(chainId, + out var sideChainToBeIndexedData)) + proposedCrossChainBlockData.SideChainBlockDataList.Add(sideChainToBeIndexedData); + + var crossChainIndexingProposal = new ChainIndexingProposal { - SideChainCreationRequest = request, - ExpiredTime = proposalCreationInput.ProposalInput.ExpiredTime, - Proposer = proposer + ChainId = chainId, + Proposer = proposer, + ProposedCrossChainBlockData = proposedCrossChainBlockData }; - return sideChainCreationRequest; + var proposalId = Context.GenerateId(crossChainIndexingController.ContractAddress, proposalToken); + crossChainIndexingProposal.ProposalId = proposalId; + SetCrossChainIndexingProposalStatus(crossChainIndexingProposal, + CrossChainIndexingProposalStatus.Pending); + Context.Fire(new CrossChainIndexingDataProposedEvent + { + ProposedCrossChainData = proposedCrossChainBlockData, + ProposalId = proposalId + }); + + Context.LogDebug(() => + $"Proposed cross chain data for chain {ChainHelper.ConvertChainIdToBase58(chainId)}"); } + } - private void ProposeCrossChainBlockData(CrossChainDataDto crossChainDataDto, Address proposer) - { - var crossChainIndexingController = GetCrossChainIndexingController(); - foreach (var chainId in crossChainDataDto.GetChainIdList()) - { - Assert(!TryGetIndexingProposal(chainId, out _), "Chain indexing already proposed."); - var proposalToken = - HashHelper.ConcatAndCompute(Context.PreviousBlockHash, ConvertChainIdToHash(chainId)); - var proposalCreationInput = new CreateProposalBySystemContractInput - { - ProposalInput = new CreateProposalInput - { - Params = new AcceptCrossChainIndexingProposalInput - { - ChainId = chainId - }.ToByteString(), - ContractMethodName = nameof(AcceptCrossChainIndexingProposal), - ExpiredTime = - Context.CurrentBlockTime.AddSeconds(CrossChainIndexingProposalExpirationTimePeriod), - OrganizationAddress = crossChainIndexingController.OwnerAddress, - ToAddress = Context.Self, - Token = proposalToken - }, - OriginProposer = Context.Sender - }; - - Context.SendInline(crossChainIndexingController.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState - .CreateProposalBySystemContract), proposalCreationInput); - - var proposedCrossChainBlockData = new CrossChainBlockData(); - if (crossChainDataDto.ParentChainToBeIndexedData.TryGetValue(chainId, - out var parentChainToBeIndexedData)) - proposedCrossChainBlockData.ParentChainBlockDataList.Add(parentChainToBeIndexedData); - else if (crossChainDataDto.SideChainToBeIndexedData.TryGetValue(chainId, - out var sideChainToBeIndexedData)) - proposedCrossChainBlockData.SideChainBlockDataList.Add(sideChainToBeIndexedData); + private ProposalOutput GetCrossChainProposal(AuthorityInfo authorityInfo, Hash proposalId) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.GetProposal), proposalId); + } - var crossChainIndexingProposal = new ChainIndexingProposal - { - ChainId = chainId, - Proposer = proposer, - ProposedCrossChainBlockData = proposedCrossChainBlockData - }; - var proposalId = Context.GenerateId(crossChainIndexingController.ContractAddress, proposalToken); - crossChainIndexingProposal.ProposalId = proposalId; - SetCrossChainIndexingProposalStatus(crossChainIndexingProposal, - CrossChainIndexingProposalStatus.Pending); - Context.Fire(new CrossChainIndexingDataProposedEvent - { - ProposedCrossChainData = proposedCrossChainBlockData, - ProposalId = proposalId - }); + private void HandleIndexingProposal(Hash proposalId) + { + var crossChainIndexingController = GetCrossChainIndexingController(); + var proposal = GetCrossChainProposal(crossChainIndexingController, proposalId); + Assert(proposal.ToBeReleased, "Not approved cross chain indexing proposal."); + Context.SendInline(crossChainIndexingController.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), + proposal.ProposalId); // release if ready + } - Context.LogDebug(() => - $"Proposed cross chain data for chain {ChainHelper.ConvertChainIdToBase58(chainId)}"); - } - } + private CrossChainDataDto ValidateCrossChainDataBeforeIndexing(CrossChainBlockData crossChainBlockData) + { + Assert( + crossChainBlockData.ParentChainBlockDataList.Count > 0 || + crossChainBlockData.SideChainBlockDataList.Count > 0, + "Empty cross chain data proposed."); + var validatedParentChainBlockData = new Dictionary>(); + var validationResult = ValidateSideChainBlockData(crossChainBlockData.SideChainBlockDataList, + out var validatedSideChainBlockData) && + ValidateParentChainBlockData(crossChainBlockData.ParentChainBlockDataList, + out validatedParentChainBlockData); + Assert(validationResult, "Invalid cross chain data to be indexed."); + var crossChainDataDto = new CrossChainDataDto(validatedSideChainBlockData, validatedParentChainBlockData); + + Assert(crossChainDataDto.GetChainIdList().Count > 0, "Empty cross chain data not allowed."); + return crossChainDataDto; + } - private ProposalOutput GetCrossChainProposal(AuthorityInfo authorityInfo, Hash proposalId) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.GetProposal), proposalId); - } + private bool TryGetIndexingProposal(int chainId, out ChainIndexingProposal proposal) + { + var proposedIndexingProposal = State.IndexingPendingProposal.Value; + return proposedIndexingProposal.ChainIndexingProposalCollections.TryGetValue(chainId, out proposal); + } - private void HandleIndexingProposal(Hash proposalId) - { - var crossChainIndexingController = GetCrossChainIndexingController(); - var proposal = GetCrossChainProposal(crossChainIndexingController, proposalId); - Assert(proposal.ToBeReleased, "Not approved cross chain indexing proposal."); - Context.SendInline(crossChainIndexingController.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), - proposal.ProposalId); // release if ready - } + private bool TryGetIndexingProposalWithStatus(int chainId, CrossChainIndexingProposalStatus status, + out ChainIndexingProposal proposal) + { + var proposedIndexingProposal = State.IndexingPendingProposal.Value; + if (!proposedIndexingProposal.ChainIndexingProposalCollections.TryGetValue(chainId, out proposal)) + return false; + return proposal.Status == status; + } - private CrossChainDataDto ValidateCrossChainDataBeforeIndexing(CrossChainBlockData crossChainBlockData) - { - Assert( - crossChainBlockData.ParentChainBlockDataList.Count > 0 || - crossChainBlockData.SideChainBlockDataList.Count > 0, - "Empty cross chain data proposed."); - var validatedParentChainBlockData = new Dictionary>(); - var validationResult = ValidateSideChainBlockData(crossChainBlockData.SideChainBlockDataList, - out var validatedSideChainBlockData) && - ValidateParentChainBlockData(crossChainBlockData.ParentChainBlockDataList, - out validatedParentChainBlockData); - Assert(validationResult, "Invalid cross chain data to be indexed."); - var crossChainDataDto = new CrossChainDataDto(validatedSideChainBlockData, validatedParentChainBlockData); - - Assert(crossChainDataDto.GetChainIdList().Count > 0, "Empty cross chain data not allowed."); - return crossChainDataDto; - } + private void ResetChainIndexingProposal(int chainId) + { + // clear pending proposal + var proposedIndexingProposal = State.IndexingPendingProposal.Value; + proposedIndexingProposal.ChainIndexingProposalCollections.Remove(chainId); + State.IndexingPendingProposal.Value = proposedIndexingProposal; + } - private bool TryGetIndexingProposal(int chainId, out ChainIndexingProposal proposal) - { - var proposedIndexingProposal = State.IndexingPendingProposal.Value; - return proposedIndexingProposal.ChainIndexingProposalCollections.TryGetValue(chainId, out proposal); - } + private void SetCrossChainIndexingProposalStatus(ChainIndexingProposal crossChainIndexingProposal, + CrossChainIndexingProposalStatus status) + { + crossChainIndexingProposal.Status = status; + var proposedIndexingProposal = State.IndexingPendingProposal.Value; + proposedIndexingProposal.ChainIndexingProposalCollections[crossChainIndexingProposal.ChainId] = + crossChainIndexingProposal; + State.IndexingPendingProposal.Value = proposedIndexingProposal; + } - private bool TryGetIndexingProposalWithStatus(int chainId, CrossChainIndexingProposalStatus status, - out ChainIndexingProposal proposal) + private ChainInitializationData GetChainInitializationData(SideChainInfo sideChainInfo, + SideChainCreationRequest sideChainCreationRequest) + { + SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); + var res = new ChainInitializationData { - var proposedIndexingProposal = State.IndexingPendingProposal.Value; - if (!proposedIndexingProposal.ChainIndexingProposalCollections.TryGetValue(chainId, out proposal)) - return false; - return proposal.Status == status; - } + CreationHeightOnParentChain = sideChainInfo.CreationHeightOnParentChain, + ChainId = sideChainInfo.SideChainId, + Creator = sideChainInfo.Proposer, + CreationTimestamp = sideChainInfo.CreationTimestamp, + ChainCreatorPrivilegePreserved = sideChainInfo.IsPrivilegePreserved, + ParentChainTokenContractAddress = State.TokenContract.Value + }; - private void ResetChainIndexingProposal(int chainId) - { - // clear pending proposal - var proposedIndexingProposal = State.IndexingPendingProposal.Value; - proposedIndexingProposal.ChainIndexingProposalCollections.Remove(chainId); - State.IndexingPendingProposal.Value = proposedIndexingProposal; - } + var initialConsensusInfo = GetInitialConsensusInformation(); + res.ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo + { InitialConsensusData = initialConsensusInfo }; - private void SetCrossChainIndexingProposalStatus(ChainIndexingProposal crossChainIndexingProposal, - CrossChainIndexingProposalStatus status) - { - crossChainIndexingProposal.Status = status; - var proposedIndexingProposal = State.IndexingPendingProposal.Value; - proposedIndexingProposal.ChainIndexingProposalCollections[crossChainIndexingProposal.ChainId] = - crossChainIndexingProposal; - State.IndexingPendingProposal.Value = proposedIndexingProposal; - } + var nativeTokenInformation = GetNativeTokenInfo().ToByteString(); + res.NativeTokenInfoData = nativeTokenInformation; - private ChainInitializationData GetChainInitializationData(SideChainInfo sideChainInfo, - SideChainCreationRequest sideChainCreationRequest) + var resourceTokenInformation = GetResourceTokenInfo().ToByteString(); + res.ResourceTokenInfo = new ResourceTokenInfo { - SetContractStateRequired(State.TokenContract, SmartContractConstants.TokenContractSystemName); - var res = new ChainInitializationData - { - CreationHeightOnParentChain = sideChainInfo.CreationHeightOnParentChain, - ChainId = sideChainInfo.SideChainId, - Creator = sideChainInfo.Proposer, - CreationTimestamp = sideChainInfo.CreationTimestamp, - ChainCreatorPrivilegePreserved = sideChainInfo.IsPrivilegePreserved, - ParentChainTokenContractAddress = State.TokenContract.Value - }; - - var initialConsensusInfo = GetInitialConsensusInformation(); - res.ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo - {InitialConsensusData = initialConsensusInfo}; + ResourceTokenListData = resourceTokenInformation, + InitialResourceAmount = { sideChainCreationRequest.InitialResourceAmount } + }; - ByteString nativeTokenInformation = GetNativeTokenInfo().ToByteString(); - res.NativeTokenInfoData = nativeTokenInformation; - - ByteString resourceTokenInformation = GetResourceTokenInfo().ToByteString(); - res.ResourceTokenInfo = new ResourceTokenInfo + if (IsPrimaryTokenNeeded(sideChainCreationRequest)) + { + var sideChainTokenInformation = + GetTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol) + .ToByteString(); + res.ChainPrimaryTokenInfo = new ChainPrimaryTokenInfo { - ResourceTokenListData = resourceTokenInformation, - InitialResourceAmount = {sideChainCreationRequest.InitialResourceAmount} + ChainPrimaryTokenData = sideChainTokenInformation, + SideChainTokenInitialIssueList = { sideChainCreationRequest.SideChainTokenInitialIssueList } }; - - if (IsPrimaryTokenNeeded(sideChainCreationRequest)) - { - ByteString sideChainTokenInformation = - GetTokenInfo(sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol).ToByteString(); - res.ChainPrimaryTokenInfo = new ChainPrimaryTokenInfo - { - ChainPrimaryTokenData = sideChainTokenInformation, - SideChainTokenInitialIssueList = {sideChainCreationRequest.SideChainTokenInitialIssueList}, - }; - } - - return res; } - private void ClearCrossChainIndexingProposalIfExpired() - { - var crossChainIndexingProposal = State.IndexingPendingProposal.Value; - if (crossChainIndexingProposal == null) - { - State.IndexingPendingProposal.Value = new ProposedCrossChainIndexing(); - return; - } + return res; + } - foreach (var chainId in crossChainIndexingProposal.ChainIndexingProposalCollections.Keys.ToList()) - { - var indexingProposal = crossChainIndexingProposal.ChainIndexingProposalCollections[chainId]; - var isExpired = CheckProposalExpired(GetCrossChainIndexingController(), indexingProposal.ProposalId); - if (isExpired) - ResetChainIndexingProposal(chainId); - } + private void ClearCrossChainIndexingProposalIfExpired() + { + var crossChainIndexingProposal = State.IndexingPendingProposal.Value; + if (crossChainIndexingProposal == null) + { + State.IndexingPendingProposal.Value = new ProposedCrossChainIndexing(); + return; } - private bool TryClearExpiredSideChainCreationRequestProposal(Hash proposalId, Address proposer) + foreach (var chainId in crossChainIndexingProposal.ChainIndexingProposalCollections.Keys.ToList()) { - var isExpired = CheckProposalExpired(GetSideChainLifetimeController(), proposalId); + var indexingProposal = crossChainIndexingProposal.ChainIndexingProposalCollections[chainId]; + var isExpired = CheckProposalExpired(GetCrossChainIndexingController(), indexingProposal.ProposalId); if (isExpired) - State.ProposedSideChainCreationRequestState.Remove(proposer); - return isExpired; + ResetChainIndexingProposal(chainId); } + } - private bool CheckProposalExpired(AuthorityInfo authorityInfo, Hash proposalId) - { - var proposalInfo = GetCrossChainProposal(authorityInfo, proposalId); - return proposalInfo.ExpiredTime <= Context.CurrentBlockTime; - } + private bool TryClearExpiredSideChainCreationRequestProposal(Hash proposalId, Address proposer) + { + var isExpired = CheckProposalExpired(GetSideChainLifetimeController(), proposalId); + if (isExpired) + State.ProposedSideChainCreationRequestState.Remove(proposer); + return isExpired; + } - private void CreateInitialOrganizationForInitialControllerAddress() - { - SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - var proposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = DefaultMinimalApprovalThreshold, - MinimalVoteThreshold = DefaultMinimalVoteThresholdThreshold, - MaximalAbstentionThreshold = DefaultMaximalAbstentionThreshold, - MaximalRejectionThreshold = DefaultMaximalRejectionThreshold - }; - State.ParliamentContract.CreateOrganizationBySystemContract.Send( - new Parliament.CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = new Parliament.CreateOrganizationInput - { - ProposalReleaseThreshold = proposalReleaseThreshold, - ProposerAuthorityRequired = false, - ParliamentMemberProposingAllowed = true - }, - OrganizationAddressFeedbackMethod = nameof(SetInitialSideChainLifetimeControllerAddress) - }); - - State.ParliamentContract.CreateOrganizationBySystemContract.Send( - new Parliament.CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = new Parliament.CreateOrganizationInput - { - ProposalReleaseThreshold = proposalReleaseThreshold, - ProposerAuthorityRequired = true, - ParliamentMemberProposingAllowed = true - }, - OrganizationAddressFeedbackMethod = nameof(SetInitialIndexingControllerAddress) - }); - } + private bool CheckProposalExpired(AuthorityInfo authorityInfo, Hash proposalId) + { + var proposalInfo = GetCrossChainProposal(authorityInfo, proposalId); + return proposalInfo.ExpiredTime <= Context.CurrentBlockTime; + } - private CreateOrganizationInput GenerateOrganizationInputForIndexingFeePrice( - IList
organizationMembers) - { - var createOrganizationInput = new CreateOrganizationInput + private void CreateInitialOrganizationForInitialControllerAddress() + { + SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); + var proposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = DefaultMinimalApprovalThreshold, + MinimalVoteThreshold = DefaultMinimalVoteThresholdThreshold, + MaximalAbstentionThreshold = DefaultMaximalAbstentionThreshold, + MaximalRejectionThreshold = DefaultMaximalRejectionThreshold + }; + State.ParliamentContract.CreateOrganizationBySystemContract.Send( + new CreateOrganizationBySystemContractInput { - ProposerWhiteList = new ProposerWhiteList + OrganizationCreationInput = new Parliament.CreateOrganizationInput { - Proposers = {organizationMembers} + ProposalReleaseThreshold = proposalReleaseThreshold, + ProposerAuthorityRequired = false, + ParliamentMemberProposingAllowed = true }, - OrganizationMemberList = new OrganizationMemberList + OrganizationAddressFeedbackMethod = nameof(SetInitialSideChainLifetimeControllerAddress) + }); + + State.ParliamentContract.CreateOrganizationBySystemContract.Send( + new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = new Parliament.CreateOrganizationInput { - OrganizationMembers = {organizationMembers} + ProposalReleaseThreshold = proposalReleaseThreshold, + ProposerAuthorityRequired = true, + ParliamentMemberProposingAllowed = true }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = organizationMembers.ToList().Count, - MinimalVoteThreshold = organizationMembers.ToList().Count, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - } - }; - return createOrganizationInput; - } + OrganizationAddressFeedbackMethod = nameof(SetInitialIndexingControllerAddress) + }); + } - private Address CalculateSideChainIndexingFeeControllerOrganizationAddress(CreateOrganizationInput input) + private CreateOrganizationInput GenerateOrganizationInputForIndexingFeePrice( + IList
organizationMembers) + { + var createOrganizationInput = new CreateOrganizationInput { - SetContractStateRequired(State.AssociationContract, SmartContractConstants.AssociationContractSystemName); - var address = State.AssociationContract.CalculateOrganizationAddress.Call(input); - return address; - } + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { organizationMembers } + }, + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { organizationMembers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = organizationMembers.ToList().Count, + MinimalVoteThreshold = organizationMembers.ToList().Count, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + } + }; + return createOrganizationInput; + } - private AuthorityInfo CreateDefaultOrganizationForIndexingFeePriceManagement(Address sideChainCreator) - { - var createOrganizationInput = - GenerateOrganizationInputForIndexingFeePrice(new List
- { - sideChainCreator, - GetCrossChainIndexingController().OwnerAddress - }); - SetContractStateRequired(State.AssociationContract, SmartContractConstants.AssociationContractSystemName); - State.AssociationContract.CreateOrganization.Send(createOrganizationInput); - - var controllerAddress = CalculateSideChainIndexingFeeControllerOrganizationAddress(createOrganizationInput); - return new AuthorityInfo + private Address CalculateSideChainIndexingFeeControllerOrganizationAddress(CreateOrganizationInput input) + { + SetContractStateRequired(State.AssociationContract, SmartContractConstants.AssociationContractSystemName); + var address = State.AssociationContract.CalculateOrganizationAddress.Call(input); + return address; + } + + private AuthorityInfo CreateDefaultOrganizationForIndexingFeePriceManagement(Address sideChainCreator) + { + var createOrganizationInput = + GenerateOrganizationInputForIndexingFeePrice(new List
{ - ContractAddress = State.AssociationContract.Value, - OwnerAddress = controllerAddress - }; - } + sideChainCreator, + GetCrossChainIndexingController().OwnerAddress + }); + SetContractStateRequired(State.AssociationContract, SmartContractConstants.AssociationContractSystemName); + State.AssociationContract.CreateOrganization.Send(createOrganizationInput); - private bool ValidateAuthorityInfoExists(AuthorityInfo authorityInfo) + var controllerAddress = CalculateSideChainIndexingFeeControllerOrganizationAddress(createOrganizationInput); + return new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + ContractAddress = State.AssociationContract.Value, + OwnerAddress = controllerAddress + }; + } - private bool ValidateParliamentOrganization(Address organizationAddress) - { - SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - var organization = State.ParliamentContract.GetOrganization.Call(organizationAddress); - return organization != null && organization.ParliamentMemberProposingAllowed; - } + private bool ValidateAuthorityInfoExists(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } + + private bool ValidateParliamentOrganization(Address organizationAddress) + { + SetContractStateRequired(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); + var organization = State.ParliamentContract.GetOrganization.Call(organizationAddress); + return organization != null && organization.ParliamentMemberProposingAllowed; + } + + private bool ValidateSideChainBlockData(IEnumerable sideChainBlockData, + out Dictionary> validatedSideChainBlockData) + { + var groupResult = sideChainBlockData.GroupBy(data => data.ChainId, data => data); - private bool ValidateSideChainBlockData(IEnumerable sideChainBlockData, - out Dictionary> validatedSideChainBlockData) + validatedSideChainBlockData = new Dictionary>(); + foreach (var group in groupResult) { - var groupResult = sideChainBlockData.GroupBy(data => data.ChainId, data => data); + var chainId = group.Key; + validatedSideChainBlockData[chainId] = group.ToList(); + var info = State.SideChainInfo[chainId]; + if (info == null || info.SideChainStatus == SideChainStatus.Terminated) + return false; + var currentSideChainHeight = State.CurrentSideChainHeight[chainId]; + var target = currentSideChainHeight != 0 + ? currentSideChainHeight + 1 + : AElfConstants.GenesisBlockHeight; - validatedSideChainBlockData = new Dictionary>(); - foreach (var group in groupResult) + foreach (var blockData in group) { - var chainId = group.Key; - validatedSideChainBlockData[chainId] = group.ToList(); - var info = State.SideChainInfo[chainId]; - if (info == null || info.SideChainStatus == SideChainStatus.Terminated) + var sideChainHeight = blockData.Height; + if (target != sideChainHeight) return false; - var currentSideChainHeight = State.CurrentSideChainHeight[chainId]; - var target = currentSideChainHeight != 0 - ? currentSideChainHeight + 1 - : AElfConstants.GenesisBlockHeight; - - foreach (var blockData in group) - { - var sideChainHeight = blockData.Height; - if (target != sideChainHeight) - return false; - target++; - } + target++; } - - return true; } - private bool ValidateParentChainBlockData(IList parentChainBlockData, - out Dictionary> validatedParentChainBlockData) + return true; + } + + private bool ValidateParentChainBlockData(IList parentChainBlockData, + out Dictionary> validatedParentChainBlockData) + { + var parentChainId = State.ParentChainId.Value; + var currentHeight = State.CurrentParentChainHeight.Value; + validatedParentChainBlockData = new Dictionary>(); + foreach (var blockData in parentChainBlockData) { - var parentChainId = State.ParentChainId.Value; - var currentHeight = State.CurrentParentChainHeight.Value; - validatedParentChainBlockData = new Dictionary>(); - foreach (var blockData in parentChainBlockData) - { - if (parentChainId != blockData.ChainId || currentHeight + 1 != blockData.Height || - blockData.TransactionStatusMerkleTreeRoot == null) - return false; - if (blockData.IndexedMerklePath.Any(indexedBlockInfo => + if (parentChainId != blockData.ChainId || currentHeight + 1 != blockData.Height || + blockData.TransactionStatusMerkleTreeRoot == null) + return false; + if (blockData.IndexedMerklePath.Any(indexedBlockInfo => State.ChildHeightToParentChainHeight[indexedBlockInfo.Key] != 0 || State.TxRootMerklePathInParentChain[indexedBlockInfo.Key] != null)) - return false; - - currentHeight += 1; - } - - if (parentChainBlockData.Count > 0) - validatedParentChainBlockData[parentChainId] = parentChainBlockData.ToList(); + return false; - return true; + currentHeight += 1; } - private bool IsPrimaryTokenNeeded(SideChainCreationRequest sideChainCreationRequest) - { - // there won't be new token creation if it is secondary side chain - // or the side chain is not exclusive - return sideChainCreationRequest.IsPrivilegePreserved && !IsParentChainExist(); - } + if (parentChainBlockData.Count > 0) + validatedParentChainBlockData[parentChainId] = parentChainBlockData.ToList(); - private bool IsParentChainExist() - { - return State.ParentChainId.Value != 0; - } + return true; + } - /// - /// Index parent chain block data. - /// - /// - private IndexedParentChainBlockData IndexParentChainBlockData(IList parentChainBlockData) - { - var parentChainId = State.ParentChainId.Value; - var currentHeight = State.CurrentParentChainHeight.Value; - var indexedParentChainBlockData = new IndexedParentChainBlockData - { - LocalChainHeight = Context.CurrentHeight - }; - for (var i = 0; i < parentChainBlockData.Count; i++) - { - var blockInfo = parentChainBlockData[i]; - AssertParentChainBlock(parentChainId, currentHeight, blockInfo); - long parentChainHeight = blockInfo.Height; - State.ParentChainTransactionStatusMerkleTreeRoot[parentChainHeight] = - blockInfo.TransactionStatusMerkleTreeRoot; - foreach (var indexedBlockInfo in blockInfo.IndexedMerklePath) - { - BindParentChainHeight(indexedBlockInfo.Key, parentChainHeight); - AddIndexedTxRootMerklePathInParentChain(indexedBlockInfo.Key, indexedBlockInfo.Value); - } + private bool IsPrimaryTokenNeeded(SideChainCreationRequest sideChainCreationRequest) + { + // there won't be new token creation if it is secondary side chain + // or the side chain is not exclusive + return sideChainCreationRequest.IsPrivilegePreserved && !IsParentChainExist(); + } - // send consensus data shared from main chain - if (i == parentChainBlockData.Count - 1 && - blockInfo.ExtraData.TryGetValue(ConsensusExtraDataName, out var bytes)) - { - Context.LogDebug(() => "Updating consensus information.."); - UpdateConsensusInformation(bytes); - } + private bool IsParentChainExist() + { + return State.ParentChainId.Value != 0; + } - if (blockInfo.CrossChainExtraData != null) - State.TransactionMerkleTreeRootRecordedInParentChain[parentChainHeight] = - blockInfo.CrossChainExtraData.TransactionStatusMerkleTreeRoot; + /// + /// Index parent chain block data. + /// + /// + private IndexedParentChainBlockData IndexParentChainBlockData(IList parentChainBlockData) + { + var parentChainId = State.ParentChainId.Value; + var currentHeight = State.CurrentParentChainHeight.Value; + var indexedParentChainBlockData = new IndexedParentChainBlockData + { + LocalChainHeight = Context.CurrentHeight + }; + for (var i = 0; i < parentChainBlockData.Count; i++) + { + var blockInfo = parentChainBlockData[i]; + AssertParentChainBlock(parentChainId, currentHeight, blockInfo); + var parentChainHeight = blockInfo.Height; + State.ParentChainTransactionStatusMerkleTreeRoot[parentChainHeight] = + blockInfo.TransactionStatusMerkleTreeRoot; + foreach (var indexedBlockInfo in blockInfo.IndexedMerklePath) + { + BindParentChainHeight(indexedBlockInfo.Key, parentChainHeight); + AddIndexedTxRootMerklePathInParentChain(indexedBlockInfo.Key, indexedBlockInfo.Value); + } - indexedParentChainBlockData.ParentChainBlockDataList.Add(blockInfo); - currentHeight += 1; + // send consensus data shared from main chain + if (i == parentChainBlockData.Count - 1 && + blockInfo.ExtraData.TryGetValue(ConsensusExtraDataName, out var bytes)) + { + Context.LogDebug(() => "Updating consensus information.."); + UpdateConsensusInformation(bytes); } - State.CurrentParentChainHeight.Value = currentHeight; + if (blockInfo.CrossChainExtraData != null) + State.TransactionMerkleTreeRootRecordedInParentChain[parentChainHeight] = + blockInfo.CrossChainExtraData.TransactionStatusMerkleTreeRoot; - return indexedParentChainBlockData; + indexedParentChainBlockData.ParentChainBlockDataList.Add(blockInfo); + currentHeight += 1; } - /// - /// Index side chain block data. - /// - /// Side chain block data to be indexed. - /// Charge indexing fee for the one who proposed side chain block data. - /// Chain id of side chain to be indexed. - /// Valid side chain block data which are indexed. - private List IndexSideChainBlockData(IList sideChainBlockDataList, - Address proposer, int chainId) - { - var indexedSideChainBlockData = new List(); + State.CurrentParentChainHeight.Value = currentHeight; - { - var formattedProposerAddress = proposer.ToByteString().ToBase64(); - long indexingFeeAmount = 0; + return indexedParentChainBlockData; + } - var sideChainInfo = State.SideChainInfo[chainId]; - var currentSideChainHeight = State.CurrentSideChainHeight[chainId]; - long arrearsAmount = 0; - var lockedToken = sideChainInfo.SideChainStatus == SideChainStatus.IndexingFeeDebt - ? 0 - : GetSideChainIndexingFeeDeposit(chainId); + /// + /// Index side chain block data. + /// + /// Side chain block data to be indexed. + /// Charge indexing fee for the one who proposed side chain block data. + /// Chain id of side chain to be indexed. + /// Valid side chain block data which are indexed. + private List IndexSideChainBlockData(IList sideChainBlockDataList, + Address proposer, int chainId) + { + var indexedSideChainBlockData = new List(); - foreach (var sideChainBlockData in sideChainBlockDataList) - { - var target = currentSideChainHeight != 0 - ? currentSideChainHeight + 1 - : AElfConstants.GenesisBlockHeight; - var sideChainHeight = sideChainBlockData.Height; - if (target != sideChainHeight) - break; + { + var formattedProposerAddress = proposer.ToByteString().ToBase64(); + long indexingFeeAmount = 0; - // indexing fee - var indexingPrice = sideChainInfo.IndexingPrice; + var sideChainInfo = State.SideChainInfo[chainId]; + var currentSideChainHeight = State.CurrentSideChainHeight[chainId]; + long arrearsAmount = 0; + var lockedToken = sideChainInfo.SideChainStatus == SideChainStatus.IndexingFeeDebt + ? 0 + : GetSideChainIndexingFeeDeposit(chainId); - lockedToken -= indexingPrice; + foreach (var sideChainBlockData in sideChainBlockDataList) + { + var target = currentSideChainHeight != 0 + ? currentSideChainHeight + 1 + : AElfConstants.GenesisBlockHeight; + var sideChainHeight = sideChainBlockData.Height; + if (target != sideChainHeight) + break; - if (lockedToken < 0) - { - // record arrears - arrearsAmount += indexingPrice; - sideChainInfo.SideChainStatus = SideChainStatus.IndexingFeeDebt; - } - else - { - indexingFeeAmount += indexingPrice; - } + // indexing fee + var indexingPrice = sideChainInfo.IndexingPrice; - currentSideChainHeight++; - indexedSideChainBlockData.Add(sideChainBlockData); - } + lockedToken -= indexingPrice; - if (indexingFeeAmount > 0) + if (lockedToken < 0) { - TransferDepositToken(new TransferInput - { - To = proposer, - Symbol = Context.Variables.NativeSymbol, - Amount = indexingFeeAmount, - Memo = "Index fee." - }, chainId); + // record arrears + arrearsAmount += indexingPrice; + sideChainInfo.SideChainStatus = SideChainStatus.IndexingFeeDebt; } - - if (arrearsAmount > 0) + else { - if (sideChainInfo.ArrearsInfo.TryGetValue(formattedProposerAddress, out var amount)) - { - sideChainInfo.ArrearsInfo[formattedProposerAddress] = amount + arrearsAmount; - } - else - sideChainInfo.ArrearsInfo[formattedProposerAddress] = arrearsAmount; + indexingFeeAmount += indexingPrice; } - State.SideChainInfo[chainId] = sideChainInfo; - State.CurrentSideChainHeight[chainId] = currentSideChainHeight; + currentSideChainHeight++; + indexedSideChainBlockData.Add(sideChainBlockData); } - if (indexedSideChainBlockData.Count > 0) - Context.LogDebug(() => - $"Last indexed height {indexedSideChainBlockData.Last().Height} for side chain {chainId}"); + if (indexingFeeAmount > 0) + TransferDepositToken(new TransferInput + { + To = proposer, + Symbol = Context.Variables.NativeSymbol, + Amount = indexingFeeAmount, + Memo = "Index fee." + }, chainId); - return indexedSideChainBlockData; - } + if (arrearsAmount > 0) + { + if (sideChainInfo.ArrearsInfo.TryGetValue(formattedProposerAddress, out var amount)) + sideChainInfo.ArrearsInfo[formattedProposerAddress] = amount + arrearsAmount; + else + sideChainInfo.ArrearsInfo[formattedProposerAddress] = arrearsAmount; + } - private void EnsureTransactionOnlyExecutedOnceInOneBlock() - { - Assert(State.LatestExecutedHeight.Value != Context.CurrentHeight, "Cannot execute this tx."); - State.LatestExecutedHeight.Value = Context.CurrentHeight; + State.SideChainInfo[chainId] = sideChainInfo; + State.CurrentSideChainHeight[chainId] = currentSideChainHeight; } - private Hash ConvertChainIdToHash(int chainId) - { - return HashHelper.ComputeFrom(chainId); - } + if (indexedSideChainBlockData.Count > 0) + Context.LogDebug(() => + $"Last indexed height {indexedSideChainBlockData.Last().Height} for side chain {chainId}"); + + return indexedSideChainBlockData; + } + + private void EnsureTransactionOnlyExecutedOnceInOneBlock() + { + Assert(State.LatestExecutedHeight.Value != Context.CurrentHeight, "Cannot execute this tx."); + State.LatestExecutedHeight.Value = Context.CurrentHeight; } - internal class CrossChainDataDto + private Hash ConvertChainIdToHash(int chainId) { - public Dictionary> SideChainToBeIndexedData { get; } + return HashHelper.ComputeFrom(chainId); + } +} - public Dictionary> ParentChainToBeIndexedData { get; } +internal class CrossChainDataDto +{ + public CrossChainDataDto(Dictionary> sideChainToBeIndexedData, + Dictionary> parentChainToBeIndexedData) + { + SideChainToBeIndexedData = sideChainToBeIndexedData; + ParentChainToBeIndexedData = parentChainToBeIndexedData; + } - public CrossChainDataDto(Dictionary> sideChainToBeIndexedData, - Dictionary> parentChainToBeIndexedData) - { - SideChainToBeIndexedData = sideChainToBeIndexedData; - ParentChainToBeIndexedData = parentChainToBeIndexedData; - } + public Dictionary> SideChainToBeIndexedData { get; } - public List GetChainIdList() - { - return ParentChainToBeIndexedData.Keys.Concat(SideChainToBeIndexedData.Keys).ToList(); - } + public Dictionary> ParentChainToBeIndexedData { get; } + + public List GetChainIdList() + { + return ParentChainToBeIndexedData.Keys.Concat(SideChainToBeIndexedData.Keys).ToList(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract_View.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract_View.cs index d79f86531c..bc370f56b6 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract_View.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract_View.cs @@ -1,216 +1,215 @@ -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using System.Linq; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.CrossChain +namespace AElf.Contracts.CrossChain; + +// ReSharper disable once PossibleNullReferenceException +public partial class CrossChainContract { - // ReSharper disable once PossibleNullReferenceException + public override IndexedSideChainBlockData GetIndexedSideChainBlockDataByHeight(Int64Value input) + { + var indexedSideChainBlockData = State.IndexedSideChainBlockData[input.Value]; + return indexedSideChainBlockData ?? new IndexedSideChainBlockData(); + } - public partial class CrossChainContract + public override CrossChainMerkleProofContext GetBoundParentChainHeightAndMerklePathByHeight(Int64Value input) { - public override IndexedSideChainBlockData GetIndexedSideChainBlockDataByHeight(Int64Value input) - { - var indexedSideChainBlockData = State.IndexedSideChainBlockData[input.Value]; - return indexedSideChainBlockData ?? new IndexedSideChainBlockData(); - } + var boundParentChainHeight = State.ChildHeightToParentChainHeight[input.Value]; + Assert(boundParentChainHeight != 0); + var merklePath = State.TxRootMerklePathInParentChain[input.Value]; + Assert(merklePath != null); + return new CrossChainMerkleProofContext + { + MerklePathFromParentChain = merklePath, + BoundParentChainHeight = boundParentChainHeight + }; + } - public override CrossChainMerkleProofContext GetBoundParentChainHeightAndMerklePathByHeight(Int64Value input) - { - var boundParentChainHeight = State.ChildHeightToParentChainHeight[input.Value]; - Assert(boundParentChainHeight != 0); - var merklePath = State.TxRootMerklePathInParentChain[input.Value]; - Assert(merklePath != null); - return new CrossChainMerkleProofContext - { - MerklePathFromParentChain = merklePath, - BoundParentChainHeight = boundParentChainHeight - }; - } + /// + /// Cross chain txn verification. + /// + /// + /// + public override BoolValue VerifyTransaction(VerifyTransactionInput input) + { + var parentChainHeight = input.ParentChainHeight; + var merkleTreeRoot = GetMerkleTreeRoot(input.VerifiedChainId, parentChainHeight); + Assert(merkleTreeRoot != null, + $"Parent chain block at height {parentChainHeight} is not recorded."); + var rootCalculated = ComputeRootWithTransactionStatusMerklePath(input.TransactionId, input.Path); - /// - /// Cross chain txn verification. - /// - /// - /// - public override BoolValue VerifyTransaction(VerifyTransactionInput input) - { - var parentChainHeight = input.ParentChainHeight; - var merkleTreeRoot = GetMerkleTreeRoot(input.VerifiedChainId, parentChainHeight); - Assert(merkleTreeRoot != null, - $"Parent chain block at height {parentChainHeight} is not recorded."); - var rootCalculated = ComputeRootWithTransactionStatusMerklePath(input.TransactionId, input.Path); + return new BoolValue { Value = merkleTreeRoot == rootCalculated }; + } - return new BoolValue {Value = merkleTreeRoot == rootCalculated}; - } + public override GetChainStatusOutput GetChainStatus(Int32Value input) + { + var info = State.SideChainInfo[input.Value]; + Assert(info != null, "Side chain not found."); + return new GetChainStatusOutput { Status = info.SideChainStatus }; + } - public override GetChainStatusOutput GetChainStatus(Int32Value input) - { - var info = State.SideChainInfo[input.Value]; - Assert(info != null, "Side chain not found."); - return new GetChainStatusOutput {Status = info.SideChainStatus}; - } + public override Int64Value GetSideChainHeight(Int32Value input) + { + var info = State.SideChainInfo[input.Value]; + Assert(info != null, "Side chain not found."); + var height = State.CurrentSideChainHeight[input.Value]; + return new Int64Value { Value = height }; + } - public override Int64Value GetSideChainHeight(Int32Value input) + public override Int64Value GetParentChainHeight(Empty input) + { + var parentChainId = State.ParentChainId.Value; + Assert(parentChainId != 0, "Parent chain not exist."); + var parentChainHeight = State.CurrentParentChainHeight.Value; + return new Int64Value { - var info = State.SideChainInfo[input.Value]; - Assert(info != null, "Side chain not found."); - var height = State.CurrentSideChainHeight[input.Value]; - return new Int64Value() {Value = height}; - } + Value = parentChainHeight + }; + } - public override Int64Value GetParentChainHeight(Empty input) - { - var parentChainId = State.ParentChainId.Value; - Assert(parentChainId != 0, "Parent chain not exist."); - var parentChainHeight = State.CurrentParentChainHeight.Value; - return new Int64Value - { - Value = parentChainHeight - }; - } + public override Int32Value GetParentChainId(Empty input) + { + var parentChainId = State.ParentChainId.Value; + Assert(parentChainId != 0, "Parent chain not exist."); + return new Int32Value { Value = parentChainId }; + } - public override Int32Value GetParentChainId(Empty input) - { - var parentChainId = State.ParentChainId.Value; - Assert(parentChainId != 0, "Parent chain not exist."); - return new Int32Value() {Value = parentChainId}; - } + public override Int64Value GetSideChainBalance(Int32Value input) + { + var chainId = input.Value; + var sideChainInfo = State.SideChainInfo[chainId]; + Assert(sideChainInfo != null, "Side chain not found."); + return new Int64Value { Value = GetSideChainIndexingFeeDeposit(chainId) }; + } + + public override Int64Value GetSideChainIndexingFeeDebt(Int32Value input) + { + var chainId = input.Value; + var sideChainInfo = State.SideChainInfo[chainId]; + Assert(sideChainInfo != null, "Side chain not found."); - public override Int64Value GetSideChainBalance(Int32Value input) + return new Int64Value { - var chainId = input.Value; - var sideChainInfo = State.SideChainInfo[chainId]; - Assert(sideChainInfo != null, "Side chain not found."); - return new Int64Value {Value = GetSideChainIndexingFeeDeposit(chainId)}; - } - - public override Int64Value GetSideChainIndexingFeeDebt(Int32Value input) + Value = sideChainInfo.ArrearsInfo.Values.Sum() + }; + } + + public override ChainIdAndHeightDict GetSideChainIdAndHeight(Empty input) + { + var dict = new ChainIdAndHeightDict(); + var serialNumber = State.SideChainSerialNumber.Value; + for (long i = 1; i <= serialNumber; i++) { - var chainId = input.Value; + var chainId = GetChainId(i); var sideChainInfo = State.SideChainInfo[chainId]; - Assert(sideChainInfo != null, "Side chain not found."); - - return new Int64Value - { - Value = sideChainInfo.ArrearsInfo.Values.Sum() - }; + if (sideChainInfo.SideChainStatus == SideChainStatus.Terminated) + continue; + var height = State.CurrentSideChainHeight[chainId]; + dict.IdHeightDict.Add(chainId, height); } - public override ChainIdAndHeightDict GetSideChainIdAndHeight(Empty input) - { - var dict = new ChainIdAndHeightDict(); - var serialNumber = State.SideChainSerialNumber.Value; - for (long i = 1; i <= serialNumber; i++) - { - int chainId = GetChainId(i); - var sideChainInfo = State.SideChainInfo[chainId]; - if (sideChainInfo.SideChainStatus == SideChainStatus.Terminated) - continue; - var height = State.CurrentSideChainHeight[chainId]; - dict.IdHeightDict.Add(chainId, height); - } - - return dict; - } + return dict; + } - public override ChainIdAndHeightDict GetAllChainsIdAndHeight(Empty input) - { - var dict = GetSideChainIdAndHeight(new Empty()); + public override ChainIdAndHeightDict GetAllChainsIdAndHeight(Empty input) + { + var dict = GetSideChainIdAndHeight(new Empty()); - if (State.ParentChainId.Value == 0) - return dict; - var parentChainHeight = GetParentChainHeight(new Empty()).Value; - Assert(parentChainHeight > AElfConstants.GenesisBlockHeight, "Invalid parent chain height"); - dict.IdHeightDict.Add(State.ParentChainId.Value, parentChainHeight); + if (State.ParentChainId.Value == 0) return dict; - } + var parentChainHeight = GetParentChainHeight(new Empty()).Value; + Assert(parentChainHeight > AElfConstants.GenesisBlockHeight, "Invalid parent chain height"); + dict.IdHeightDict.Add(State.ParentChainId.Value, parentChainHeight); + return dict; + } - public override SideChainIndexingInformationList GetSideChainIndexingInformationList(Empty input) + public override SideChainIndexingInformationList GetSideChainIndexingInformationList(Empty input) + { + var sideChainIndexingInformationList = new SideChainIndexingInformationList(); + var sideChainIdAndHeightDict = GetSideChainIdAndHeight(new Empty()); + foreach (var kv in sideChainIdAndHeightDict.IdHeightDict) { - var sideChainIndexingInformationList = new SideChainIndexingInformationList(); - var sideChainIdAndHeightDict = GetSideChainIdAndHeight(new Empty()); - foreach (var kv in sideChainIdAndHeightDict.IdHeightDict) + var chainId = kv.Key; + sideChainIndexingInformationList.IndexingInformationList.Add(new SideChainIndexingInformation { - var chainId = kv.Key; - sideChainIndexingInformationList.IndexingInformationList.Add(new SideChainIndexingInformation - { - ChainId = chainId, - IndexedHeight = kv.Value - }); - } - - return sideChainIndexingInformationList; + ChainId = chainId, + IndexedHeight = kv.Value + }); } - public override Address GetSideChainCreator(Int32Value input) - { - var info = State.SideChainInfo[input.Value]; - Assert(info != null, "Side chain not found."); - return info.Proposer; - } + return sideChainIndexingInformationList; + } - public override ChainInitializationData GetChainInitializationData(Int32Value input) - { - var res = State.SideChainInitializationData[input.Value]; - Assert(res!=null, "Side chain not found."); - return res; - } - - public override GetIndexingProposalStatusOutput GetIndexingProposalStatus(Empty input) - { - var res = new GetIndexingProposalStatusOutput(); - var pendingCrossChainIndexingProposal = State.IndexingPendingProposal.Value; - if (pendingCrossChainIndexingProposal == null) - return res; - - var crossChainIndexingController = GetCrossChainIndexingController(); - foreach (var chainIndexingProposal in pendingCrossChainIndexingProposal.ChainIndexingProposalCollections.Values) - { - var pendingChainIndexingProposalStatus = new PendingChainIndexingProposalStatus(); - var proposalInfo = Context.Call(crossChainIndexingController.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.GetProposal), - chainIndexingProposal.ProposalId); - pendingChainIndexingProposalStatus.Proposer = chainIndexingProposal.Proposer; - pendingChainIndexingProposalStatus.ProposalId = chainIndexingProposal.ProposalId; - pendingChainIndexingProposalStatus.ToBeReleased = - proposalInfo.ToBeReleased && - proposalInfo.OrganizationAddress == crossChainIndexingController.OwnerAddress; - pendingChainIndexingProposalStatus.ExpiredTime = proposalInfo.ExpiredTime; - pendingChainIndexingProposalStatus.ProposedCrossChainBlockData = chainIndexingProposal.ProposedCrossChainBlockData; - res.ChainIndexingProposalStatus[chainIndexingProposal.ChainId] = pendingChainIndexingProposalStatus; - } - + public override Address GetSideChainCreator(Int32Value input) + { + var info = State.SideChainInfo[input.Value]; + Assert(info != null, "Side chain not found."); + return info.Proposer; + } + + public override ChainInitializationData GetChainInitializationData(Int32Value input) + { + var res = State.SideChainInitializationData[input.Value]; + Assert(res != null, "Side chain not found."); + return res; + } + + public override GetIndexingProposalStatusOutput GetIndexingProposalStatus(Empty input) + { + var res = new GetIndexingProposalStatusOutput(); + var pendingCrossChainIndexingProposal = State.IndexingPendingProposal.Value; + if (pendingCrossChainIndexingProposal == null) return res; - } - public override Int64Value GetSideChainIndexingFeePrice(Int32Value input) - { - var sideChainInfo = State.SideChainInfo[input.Value]; - Assert(sideChainInfo != null, "Side chain not found."); - return new Int64Value - { - Value = sideChainInfo.IndexingPrice - }; - } + var crossChainIndexingController = GetCrossChainIndexingController(); + foreach (var chainIndexingProposal in pendingCrossChainIndexingProposal.ChainIndexingProposalCollections.Values) + { + var pendingChainIndexingProposalStatus = new PendingChainIndexingProposalStatus(); + var proposalInfo = Context.Call(crossChainIndexingController.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.GetProposal), + chainIndexingProposal.ProposalId); + pendingChainIndexingProposalStatus.Proposer = chainIndexingProposal.Proposer; + pendingChainIndexingProposalStatus.ProposalId = chainIndexingProposal.ProposalId; + pendingChainIndexingProposalStatus.ToBeReleased = + proposalInfo.ToBeReleased && + proposalInfo.OrganizationAddress == crossChainIndexingController.OwnerAddress; + pendingChainIndexingProposalStatus.ExpiredTime = proposalInfo.ExpiredTime; + pendingChainIndexingProposalStatus.ProposedCrossChainBlockData = + chainIndexingProposal.ProposedCrossChainBlockData; + res.ChainIndexingProposalStatus[chainIndexingProposal.ChainId] = pendingChainIndexingProposalStatus; + } + + return res; + } - public override AuthorityInfo GetCrossChainIndexingController(Empty input) + public override Int64Value GetSideChainIndexingFeePrice(Int32Value input) + { + var sideChainInfo = State.SideChainInfo[input.Value]; + Assert(sideChainInfo != null, "Side chain not found."); + return new Int64Value { - return GetCrossChainIndexingController(); - } + Value = sideChainInfo.IndexingPrice + }; + } - public override AuthorityInfo GetSideChainLifetimeController(Empty input) - { - return GetSideChainLifetimeController(); - } + public override AuthorityInfo GetCrossChainIndexingController(Empty input) + { + return GetCrossChainIndexingController(); + } - public override AuthorityInfo GetSideChainIndexingFeeController(Int32Value input) - { - var sideChainInfo = State.SideChainInfo[input.Value]; - Assert(sideChainInfo != null, "Side chain not found."); - return sideChainInfo.IndexingFeeController; - } + public override AuthorityInfo GetSideChainLifetimeController(Empty input) + { + return GetSideChainLifetimeController(); + } + + public override AuthorityInfo GetSideChainIndexingFeeController(Int32Value input) + { + var sideChainInfo = State.SideChainInfo[input.Value]; + Assert(sideChainInfo != null, "Side chain not found."); + return sideChainInfo.IndexingFeeController; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.CrossChain/CrossChainReferenceState.cs b/contract/AElf.Contracts.CrossChain/CrossChainReferenceState.cs index bab8853675..ada5f8f54b 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainReferenceState.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainReferenceState.cs @@ -1,19 +1,18 @@ -using AElf.Standards.ACS11; -using AElf.Standards.ACS0; using AElf.Contracts.Association; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; +using AElf.Standards.ACS0; +using AElf.Standards.ACS11; + +namespace AElf.Contracts.CrossChain; -namespace AElf.Contracts.CrossChain +public partial class CrossChainContractState { - public partial class CrossChainContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal AssociationContractContainer.AssociationContractReferenceState AssociationContract { get; set; } - internal ACS0Container.ACS0ReferenceState GenesisContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal AssociationContractContainer.AssociationContractReferenceState AssociationContract { get; set; } + internal ACS0Container.ACS0ReferenceState GenesisContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal CrossChainInteractionContractContainer.CrossChainInteractionContractReferenceState - CrossChainInteractionContract { get; set; } - } + internal CrossChainInteractionContractContainer.CrossChainInteractionContractReferenceState + CrossChainInteractionContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Economic/AElf.Contracts.Economic.csproj b/contract/AElf.Contracts.Economic/AElf.Contracts.Economic.csproj index 499345d9c7..0ec68211bf 100644 --- a/contract/AElf.Contracts.Economic/AElf.Contracts.Economic.csproj +++ b/contract/AElf.Contracts.Economic/AElf.Contracts.Economic.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Economic true - Economic is a contract that implements the basic functionality used to manage the economic - system. + Economic is a contract that implements the basic functionality used to manage the economic + system. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs0.proto @@ -63,5 +64,5 @@ true - + \ No newline at end of file diff --git a/contract/AElf.Contracts.Economic/EconomicContract.cs b/contract/AElf.Contracts.Economic/EconomicContract.cs index c5b3c621a5..f9c0fbe353 100644 --- a/contract/AElf.Contracts.Economic/EconomicContract.cs +++ b/contract/AElf.Contracts.Economic/EconomicContract.cs @@ -8,264 +8,256 @@ using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -using InitializeInput = AElf.Contracts.TokenConverter.InitializeInput; -namespace AElf.Contracts.Economic +namespace AElf.Contracts.Economic; + +public partial class EconomicContract : EconomicContractImplContainer.EconomicContractImplBase { - public partial class EconomicContract : EconomicContractImplContainer.EconomicContractImplBase + public override Empty InitialEconomicSystem(InitialEconomicSystemInput input) { - public override Empty InitialEconomicSystem(InitialEconomicSystemInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); + Assert(!State.Initialized.Value, "Already initialized."); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - Context.LogDebug(() => "Will create tokens."); - CreateNativeToken(input); - CreateResourceTokens(); - CreateElectionTokens(); + Context.LogDebug(() => "Will create tokens."); + CreateNativeToken(input); + CreateResourceTokens(); + CreateElectionTokens(); - Context.LogDebug(() => "Finished creating tokens."); + Context.LogDebug(() => "Finished creating tokens."); - InitialMiningReward(input.MiningRewardTotalAmount); + InitialMiningReward(input.MiningRewardTotalAmount); - RegisterElectionVotingEvent(); - SetTreasurySchemeIdsToElectionContract(); + RegisterElectionVotingEvent(); + SetTreasurySchemeIdsToElectionContract(); - InitializeTokenConverterContract(); - State.TokenContract.InitialCoefficients.Send(new Empty()); - State.TokenContract.InitializeAuthorizedController.Send(new Empty()); - State.Initialized.Value = true; - return new Empty(); - } + InitializeTokenConverterContract(); + State.TokenContract.InitialCoefficients.Send(new Empty()); + State.TokenContract.InitializeAuthorizedController.Send(new Empty()); + State.Initialized.Value = true; + return new Empty(); + } - private void CreateNativeToken(InitialEconomicSystemInput input) + private void CreateNativeToken(InitialEconomicSystemInput input) + { + var lockWhiteListBackups = new List
{ - var lockWhiteListBackups = new List
- { - Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName) - }; - var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); - State.TokenContract.Create.Send(new CreateInput - { - Symbol = input.NativeTokenSymbol, - TokenName = "Native Token", - TotalSupply = input.NativeTokenTotalSupply, - Decimals = input.NativeTokenDecimals, - IsBurnable = input.IsNativeTokenBurnable, - Issuer = Context.Self, - LockWhiteList = {lockWhiteList} - }); - - State.TokenContract.SetPrimaryTokenSymbol.Send(new SetPrimaryTokenSymbolInput - {Symbol = input.NativeTokenSymbol}); - } - - private void CreateResourceTokens() + Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName) + }; + var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); + State.TokenContract.Create.Send(new CreateInput { - var tokenConverter = - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - var lockWhiteListBackups = new List
- { - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) - }; - var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); - foreach (var resourceTokenSymbol in Context.Variables - .GetStringArray(EconomicContractConstants.PayTxFeeSymbolListName) - .Union(Context.Variables.GetStringArray(EconomicContractConstants.PayRentalSymbolListName))) - { - State.TokenContract.Create.Send(new CreateInput - { - Symbol = resourceTokenSymbol, - TokenName = $"{resourceTokenSymbol} Token", - TotalSupply = EconomicContractConstants.ResourceTokenTotalSupply, - Decimals = EconomicContractConstants.ResourceTokenDecimals, - Issuer = Context.Self, - LockWhiteList = {lockWhiteList}, - IsBurnable = true - }); + Symbol = input.NativeTokenSymbol, + TokenName = "Native Token", + TotalSupply = input.NativeTokenTotalSupply, + Decimals = input.NativeTokenDecimals, + IsBurnable = input.IsNativeTokenBurnable, + Issuer = Context.Self, + LockWhiteList = { lockWhiteList } + }); - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = resourceTokenSymbol, - Amount = EconomicContractConstants.ResourceTokenTotalSupply, - To = tokenConverter, - Memo = "Initialize for resource trade" - }); - } - } + State.TokenContract.SetPrimaryTokenSymbol.Send(new SetPrimaryTokenSymbolInput + { Symbol = input.NativeTokenSymbol }); + } - private void CreateElectionTokens() + private void CreateResourceTokens() + { + var tokenConverter = + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); + var lockWhiteListBackups = new List
{ - var lockWhiteListBackups = new List
- { - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName) - }; - var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); - foreach (var symbol in new List - {EconomicContractConstants.ElectionTokenSymbol, EconomicContractConstants.ShareTokenSymbol}) - { - State.TokenContract.Create.Send(new CreateInput - { - Symbol = symbol, - TokenName = $"{symbol} Token", - TotalSupply = EconomicContractConstants.ElectionTokenTotalSupply, - Decimals = EconomicContractConstants.ElectionTokenDecimals, - Issuer = Context.Self, - IsBurnable = true, - LockWhiteList = {lockWhiteList} - }); - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = symbol, - Amount = EconomicContractConstants.ElectionTokenTotalSupply, - To = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), - Memo = "Issue all election tokens to Election Contract." - }); - } - } - - /// - /// Only contract owner of Economic Contract can issue native token. - /// Mainly for testing. - /// - /// - /// - public override Empty IssueNativeToken(IssueNativeTokenInput input) + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) + }; + var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); + foreach (var resourceTokenSymbol in Context.Variables + .GetStringArray(EconomicContractConstants.PayTxFeeSymbolListName) + .Union(Context.Variables.GetStringArray(EconomicContractConstants.PayRentalSymbolListName))) { - AssertValidMemo(input.Memo); - if (State.ZeroContract.Value == null) - { - State.ZeroContract.Value = Context.GetZeroSmartContractAddress(); - } - - var contractOwner = State.ZeroContract.GetContractAuthor.Call(Context.Self); - if (contractOwner != Context.Sender) + State.TokenContract.Create.Send(new CreateInput { - return new Empty(); - } + Symbol = resourceTokenSymbol, + TokenName = $"{resourceTokenSymbol} Token", + TotalSupply = EconomicContractConstants.ResourceTokenTotalSupply, + Decimals = EconomicContractConstants.ResourceTokenDecimals, + Issuer = Context.Self, + LockWhiteList = { lockWhiteList }, + IsBurnable = true + }); State.TokenContract.Issue.Send(new IssueInput { - Symbol = Context.Variables.NativeSymbol, - Amount = input.Amount, - To = input.To, - Memo = input.Memo + Symbol = resourceTokenSymbol, + Amount = EconomicContractConstants.ResourceTokenTotalSupply, + To = tokenConverter, + Memo = "Initialize for resource trade" }); - return new Empty(); } + } - /// - /// Transfer all the tokens prepared for rewarding mining to consensus contract. - /// - /// - private void InitialMiningReward(long miningRewardAmount) + private void CreateElectionTokens() + { + var lockWhiteListBackups = new List
{ - var consensusContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName) + }; + var lockWhiteList = lockWhiteListBackups.Where(address => address != null).ToList(); + foreach (var symbol in new List + { EconomicContractConstants.ElectionTokenSymbol, EconomicContractConstants.ShareTokenSymbol }) + { + State.TokenContract.Create.Send(new CreateInput + { + Symbol = symbol, + TokenName = $"{symbol} Token", + TotalSupply = EconomicContractConstants.ElectionTokenTotalSupply, + Decimals = EconomicContractConstants.ElectionTokenDecimals, + Issuer = Context.Self, + IsBurnable = true, + LockWhiteList = { lockWhiteList } + }); State.TokenContract.Issue.Send(new IssueInput { - To = consensusContractAddress, - Amount = miningRewardAmount, - Symbol = Context.Variables.NativeSymbol, - Memo = "Initial mining reward." + Symbol = symbol, + Amount = EconomicContractConstants.ElectionTokenTotalSupply, + To = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName), + Memo = "Issue all election tokens to Election Contract." }); } + } + + /// + /// Only contract owner of Economic Contract can issue native token. + /// Mainly for testing. + /// + /// + /// + public override Empty IssueNativeToken(IssueNativeTokenInput input) + { + AssertValidMemo(input.Memo); + if (State.ZeroContract.Value == null) State.ZeroContract.Value = Context.GetZeroSmartContractAddress(); - private void RegisterElectionVotingEvent() + var contractOwner = State.ZeroContract.GetContractAuthor.Call(Context.Self); + if (contractOwner != Context.Sender) return new Empty(); + + State.TokenContract.Issue.Send(new IssueInput { - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - State.ElectionContract.RegisterElectionVotingEvent.Send(new Empty()); - } + Symbol = Context.Variables.NativeSymbol, + Amount = input.Amount, + To = input.To, + Memo = input.Memo + }); + return new Empty(); + } + + /// + /// Transfer all the tokens prepared for rewarding mining to consensus contract. + /// + /// + private void InitialMiningReward(long miningRewardAmount) + { + var consensusContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - private void SetTreasurySchemeIdsToElectionContract() + State.TokenContract.Issue.Send(new IssueInput { - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - var schemeIdsManagingByTreasuryContract = State.ProfitContract.GetManagingSchemeIds.Call( - new GetManagingSchemeIdsInput - { - Manager = Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) - }).SchemeIds; - var schemeIdsManagingByElectionContract = State.ProfitContract.GetManagingSchemeIds.Call( - new GetManagingSchemeIdsInput - { - Manager = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName) - }).SchemeIds; - State.ElectionContract.SetTreasurySchemeIds.Send(new SetTreasurySchemeIdsInput + To = consensusContractAddress, + Amount = miningRewardAmount, + Symbol = Context.Variables.NativeSymbol, + Memo = "Initial mining reward." + }); + } + + private void RegisterElectionVotingEvent() + { + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + State.ElectionContract.RegisterElectionVotingEvent.Send(new Empty()); + } + + private void SetTreasurySchemeIdsToElectionContract() + { + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); + var schemeIdsManagingByTreasuryContract = State.ProfitContract.GetManagingSchemeIds.Call( + new GetManagingSchemeIdsInput { - TreasuryHash = schemeIdsManagingByTreasuryContract[0], - WelcomeHash = schemeIdsManagingByTreasuryContract[3], - FlexibleHash = schemeIdsManagingByTreasuryContract[4], - SubsidyHash = schemeIdsManagingByElectionContract[0], - WelfareHash = schemeIdsManagingByElectionContract[1] - }); - } + Manager = Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) + }).SchemeIds; + var schemeIdsManagingByElectionContract = State.ProfitContract.GetManagingSchemeIds.Call( + new GetManagingSchemeIdsInput + { + Manager = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName) + }).SchemeIds; + State.ElectionContract.SetTreasurySchemeIds.Send(new SetTreasurySchemeIdsInput + { + TreasuryHash = schemeIdsManagingByTreasuryContract[0], + WelcomeHash = schemeIdsManagingByTreasuryContract[3], + FlexibleHash = schemeIdsManagingByTreasuryContract[4], + SubsidyHash = schemeIdsManagingByElectionContract[0], + WelfareHash = schemeIdsManagingByElectionContract[1] + }); + } - private void InitializeTokenConverterContract() + private void InitializeTokenConverterContract() + { + State.TokenConverterContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); + var connectors = new List { - State.TokenConverterContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - var connectors = new List - { - new Connector - { - Symbol = Context.Variables.NativeSymbol, - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - Weight = "0.5", - VirtualBalance = EconomicContractConstants.NativeTokenConnectorInitialVirtualBalance - }, - }; - foreach (var resourceTokenSymbol in Context.Variables - .GetStringArray(EconomicContractConstants.PayTxFeeSymbolListName) - .Union(Context.Variables.GetStringArray(EconomicContractConstants.PayRentalSymbolListName))) + new() { - var resourceTokenConnector = new Connector - { - Symbol = resourceTokenSymbol, - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - Weight = "0.005", - VirtualBalance = EconomicContractConstants.ResourceTokenInitialVirtualBalance, - RelatedSymbol = EconomicContractConstants.NativeTokenPrefix.Append(resourceTokenSymbol), - IsDepositAccount = false - }; - var nativeTokenConnector = new Connector - { - Symbol = EconomicContractConstants.NativeTokenPrefix.Append(resourceTokenSymbol), - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - Weight = "0.005", - VirtualBalance = EconomicContractConstants.NativeTokenToResourceBalance, - RelatedSymbol = resourceTokenSymbol, - IsDepositAccount = true - }; - connectors.Add(resourceTokenConnector); - connectors.Add(nativeTokenConnector); + Symbol = Context.Variables.NativeSymbol, + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + Weight = "0.5", + VirtualBalance = EconomicContractConstants.NativeTokenConnectorInitialVirtualBalance } - - State.TokenConverterContract.Initialize.Send(new InitializeInput + }; + foreach (var resourceTokenSymbol in Context.Variables + .GetStringArray(EconomicContractConstants.PayTxFeeSymbolListName) + .Union(Context.Variables.GetStringArray(EconomicContractConstants.PayRentalSymbolListName))) + { + var resourceTokenConnector = new Connector { - FeeRate = EconomicContractConstants.TokenConverterFeeRate, - Connectors = {connectors}, - BaseTokenSymbol = Context.Variables.NativeSymbol, - }); + Symbol = resourceTokenSymbol, + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + Weight = "0.005", + VirtualBalance = EconomicContractConstants.ResourceTokenInitialVirtualBalance, + RelatedSymbol = EconomicContractConstants.NativeTokenPrefix.Append(resourceTokenSymbol), + IsDepositAccount = false + }; + var nativeTokenConnector = new Connector + { + Symbol = EconomicContractConstants.NativeTokenPrefix.Append(resourceTokenSymbol), + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + Weight = "0.005", + VirtualBalance = EconomicContractConstants.NativeTokenToResourceBalance, + RelatedSymbol = resourceTokenSymbol, + IsDepositAccount = true + }; + connectors.Add(resourceTokenConnector); + connectors.Add(nativeTokenConnector); } - private void AssertValidMemo(string memo) + State.TokenConverterContract.Initialize.Send(new InitializeInput { - Assert(Encoding.UTF8.GetByteCount(memo) <= EconomicContractConstants.MemoMaxLength, "Invalid memo size."); - } + FeeRate = EconomicContractConstants.TokenConverterFeeRate, + Connectors = { connectors }, + BaseTokenSymbol = Context.Variables.NativeSymbol + }); + } + + private void AssertValidMemo(string memo) + { + Assert(Encoding.UTF8.GetByteCount(memo) <= EconomicContractConstants.MemoMaxLength, "Invalid memo size."); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Economic/EconomicContractConstants.cs b/contract/AElf.Contracts.Economic/EconomicContractConstants.cs index 400ac24983..66486a42a4 100644 --- a/contract/AElf.Contracts.Economic/EconomicContractConstants.cs +++ b/contract/AElf.Contracts.Economic/EconomicContractConstants.cs @@ -1,33 +1,32 @@ -namespace AElf.Contracts.Economic +namespace AElf.Contracts.Economic; + +public static class EconomicContractConstants { - public static class EconomicContractConstants - { - public const long NativeTokenConnectorInitialVirtualBalance = 100_000_00000000; + public const long NativeTokenConnectorInitialVirtualBalance = 100_000_00000000; + + // Token Converter Contract related. + public const string TokenConverterFeeRate = "0.005"; - // Token Converter Contract related. - public const string TokenConverterFeeRate = "0.005"; + // Resource token related. + public const long ResourceTokenTotalSupply = 500_000_000_00000000; - // Resource token related. - public const long ResourceTokenTotalSupply = 500_000_000_00000000; + public const int ResourceTokenDecimals = 8; - public const int ResourceTokenDecimals = 8; + //resource to sell + public const long ResourceTokenInitialVirtualBalance = 100_000; - //resource to sell - public const long ResourceTokenInitialVirtualBalance = 100_000; + public const string NativeTokenPrefix = "nt"; - public const string NativeTokenPrefix = "nt"; + public const long NativeTokenToResourceBalance = 10_000_000_00000000; - public const long NativeTokenToResourceBalance = 10_000_000_00000000; + // Election related. + public const string ElectionTokenSymbol = "VOTE"; + public const string ShareTokenSymbol = "SHARE"; + public const long ElectionTokenTotalSupply = 1_000_000_000_00000000; + public const int ElectionTokenDecimals = 8; - // Election related. - public const string ElectionTokenSymbol = "VOTE"; - public const string ShareTokenSymbol = "SHARE"; - public const long ElectionTokenTotalSupply = 1_000_000_000_00000000; - public const int ElectionTokenDecimals = 8; + public const int MemoMaxLength = 64; - public const int MemoMaxLength = 64; - - public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; - public const string PayRentalSymbolListName = "SymbolListToPayRental"; - } + public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; + public const string PayRentalSymbolListName = "SymbolListToPayRental"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Economic/EconomicContractState.cs b/contract/AElf.Contracts.Economic/EconomicContractState.cs index 000fb91747..3ec662bf7e 100644 --- a/contract/AElf.Contracts.Economic/EconomicContractState.cs +++ b/contract/AElf.Contracts.Economic/EconomicContractState.cs @@ -1,27 +1,25 @@ -using AElf.Standards.ACS0; -using AElf.Standards.ACS1; -using AElf.Contracts.Election; +using AElf.Contracts.Election; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.Contracts.TokenConverter; using AElf.Sdk.CSharp.State; -using AElf.Types; +using AElf.Standards.ACS0; +using AElf.Standards.ACS1; + +namespace AElf.Contracts.Economic; -namespace AElf.Contracts.Economic +public class EconomicContractState : ContractState { - public class EconomicContractState : ContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } - internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } - internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal ACS0Container.ACS0ReferenceState ZeroContract { get; set; } - internal MappedState TransactionFees { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } + internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal ACS0Container.ACS0ReferenceState ZeroContract { get; set; } + internal MappedState TransactionFees { get; set; } - public SingletonState Initialized { get; set; } + public SingletonState Initialized { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Economic/EconomicContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Economic/EconomicContract_ACS1_TransactionFeeProvider.cs index 811089c45b..2531982717 100644 --- a/contract/AElf.Contracts.Economic/EconomicContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Economic/EconomicContract_ACS1_TransactionFeeProvider.cs @@ -1,99 +1,90 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Economic +namespace AElf.Contracts.Economic; + +public partial class EconomicContract { - public partial class EconomicContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/AElf.Contracts.Election.csproj b/contract/AElf.Contracts.Election/AElf.Contracts.Election.csproj index 0c6283220c..30187f8423 100644 --- a/contract/AElf.Contracts.Election/AElf.Contracts.Election.csproj +++ b/contract/AElf.Contracts.Election/AElf.Contracts.Election.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,11 +9,11 @@ - true + true - true + true diff --git a/contract/AElf.Contracts.Election/ElectionContractConstants.cs b/contract/AElf.Contracts.Election/ElectionContractConstants.cs index b6c59da5b0..156aebfc8e 100644 --- a/contract/AElf.Contracts.Election/ElectionContractConstants.cs +++ b/contract/AElf.Contracts.Election/ElectionContractConstants.cs @@ -1,11 +1,10 @@ -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public static class ElectionContractConstants { - public static class ElectionContractConstants - { - public const long LockTokenForElection = 100_000_00000000; + public const long LockTokenForElection = 100_000_00000000; - public const string VoteSymbol = "VOTE"; + public const string VoteSymbol = "VOTE"; - public const string ShareSymbol = "SHARE"; - } + public const string ShareSymbol = "SHARE"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContractReferenceState.cs b/contract/AElf.Contracts.Election/ElectionContractReferenceState.cs index 613f35803b..3bb62b5de2 100644 --- a/contract/AElf.Contracts.Election/ElectionContractReferenceState.cs +++ b/contract/AElf.Contracts.Election/ElectionContractReferenceState.cs @@ -1,22 +1,21 @@ -using AElf.Standards.ACS10; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; -using AElf.Contracts.Profit; -using AElf.Contracts.Vote; using AElf.Contracts.Parliament; +using AElf.Contracts.Profit; using AElf.Contracts.Treasury; +using AElf.Contracts.Vote; +using AElf.Standards.ACS10; + +namespace AElf.Contracts.Election; -namespace AElf.Contracts.Election +// ReSharper disable InconsistentNaming +public partial class ElectionContractState { - // ReSharper disable InconsistentNaming - public partial class ElectionContractState - { - internal VoteContractContainer.VoteContractReferenceState VoteContract { get; set; } - internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal AEDPoSContractContainer.AEDPoSContractReferenceState AEDPoSContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } - internal TreasuryContractContainer.TreasuryContractReferenceState TreasuryContract { get; set; } - } + internal VoteContractContainer.VoteContractReferenceState VoteContract { get; set; } + internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal AEDPoSContractContainer.AEDPoSContractReferenceState AEDPoSContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } + internal TreasuryContractContainer.TreasuryContractReferenceState TreasuryContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContractState.cs b/contract/AElf.Contracts.Election/ElectionContractState.cs index 942279ae77..b0316be16a 100644 --- a/contract/AElf.Contracts.Election/ElectionContractState.cs +++ b/contract/AElf.Contracts.Election/ElectionContractState.cs @@ -1,101 +1,99 @@ -using System; -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractState : ContractState { - public partial class ElectionContractState : ContractState - { - public BoolState Initialized { get; set; } - public BoolState VotingEventRegistered { get; set; } + public BoolState Initialized { get; set; } + public BoolState VotingEventRegistered { get; set; } - public SingletonState TreasuryHash { get; set; } - public SingletonState WelfareHash { get; set; } - public SingletonState SubsidyHash { get; set; } - public SingletonState FlexibleHash { get; set; } - public SingletonState WelcomeHash { get; set; } + public SingletonState TreasuryHash { get; set; } + public SingletonState WelfareHash { get; set; } + public SingletonState SubsidyHash { get; set; } + public SingletonState FlexibleHash { get; set; } + public SingletonState WelcomeHash { get; set; } - public MappedState ElectorVotes { get; set; } + public MappedState ElectorVotes { get; set; } - public MappedState CandidateVotes { get; set; } + public MappedState CandidateVotes { get; set; } - public MappedState CandidateInformationMap { get; set; } + public MappedState CandidateInformationMap { get; set; } - public Int64State CurrentTermNumber { get; set; } + public Int64State CurrentTermNumber { get; set; } - public SingletonState Candidates { get; set; } + public SingletonState Candidates { get; set; } - public SingletonState DataCentersRankingList { get; set; } + public SingletonState DataCentersRankingList { get; set; } - public SingletonState InitialMiners { get; set; } + public SingletonState InitialMiners { get; set; } - public MappedState BannedPubkeyMap { get; set; } + public MappedState BannedPubkeyMap { get; set; } - /// - /// Vote Id -> Lock Time (seconds) - /// - public MappedState LockTimeMap { get; set; } + /// + /// Vote Id -> Lock Time (seconds) + /// + public MappedState LockTimeMap { get; set; } - public MappedState Snapshots { get; set; } + public MappedState Snapshots { get; set; } - public Int32State MinersCount { get; set; } + public Int32State MinersCount { get; set; } - /// - /// Time unit: seconds - /// - public Int64State MinimumLockTime { get; set; } + /// + /// Time unit: seconds + /// + public Int64State MinimumLockTime { get; set; } - /// - /// Time unit: seconds - /// - public Int64State MaximumLockTime { get; set; } + /// + /// Time unit: seconds + /// + public Int64State MaximumLockTime { get; set; } - public Int64State TimeEachTerm { get; set; } + public Int64State TimeEachTerm { get; set; } - public SingletonState MinerElectionVotingItemId { get; set; } + public SingletonState MinerElectionVotingItemId { get; set; } - public MappedState TransactionFees { get; set; } - public SingletonState VoteWeightInterestList { get; set; } - public SingletonState VoteWeightProportion { get; set; } - public SingletonState VoteWeightInterestController { get; set; } + public MappedState TransactionFees { get; set; } + public SingletonState VoteWeightInterestList { get; set; } + public SingletonState VoteWeightProportion { get; set; } + public SingletonState VoteWeightInterestController { get; set; } - public SingletonState MethodFeeController { get; set; } + public SingletonState MethodFeeController { get; set; } - /// - /// Pubkey -> Address who has the authority to replace it. - /// - public MappedState CandidateAdmins { get; set; } + /// + /// Pubkey -> Address who has the authority to replace it. + /// + public MappedState CandidateAdmins { get; set; } - /// - /// Admin address -> Pubkey - /// - public MappedState ManagedCandidatePubkeysMap { get; set; } + /// + /// Admin address -> Pubkey + /// + public MappedState ManagedCandidatePubkeysMap { get; set; } - /// - /// Pubkey -> Newest pubkey - /// - public MappedState CandidateReplacementMap { get; set; } + /// + /// Pubkey -> Newest pubkey + /// + public MappedState CandidateReplacementMap { get; set; } - /// - /// Pubkey -> Initial pubkey (First round initial miner pubkey or first announce election pubkey) - /// - public MappedState InitialPubkeyMap { get; set; } + /// + /// Pubkey -> Initial pubkey (First round initial miner pubkey or first announce election pubkey) + /// + public MappedState InitialPubkeyMap { get; set; } - /// - /// Initial pubkey -> Newest pubkey - /// - public MappedState InitialToNewestPubkeyMap { get; set; } + /// + /// Initial pubkey -> Newest pubkey + /// + public MappedState InitialToNewestPubkeyMap { get; set; } - public SingletonState
EmergencyResponseOrganizationAddress { get; set; } + public SingletonState
EmergencyResponseOrganizationAddress { get; set; } - /// - /// Pubkey -> Sponsor address (who will pay announce election fee for this pubkey) - /// - public MappedState CandidateSponsorMap { get; set; } + /// + /// Pubkey -> Sponsor address (who will pay announce election fee for this pubkey) + /// + public MappedState CandidateSponsorMap { get; set; } - public BoolState ElectionEnabled { get; set; } + public BoolState ElectionEnabled { get; set; } - public MappedState WeightsAlreadyFixedMap { get; set; } - } + public MappedState WeightsAlreadyFixedMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Election/ElectionContract_ACS1_TransactionFeeProvider.cs index 639f8adc89..ffcf19d5a4 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_ACS1_TransactionFeeProvider.cs @@ -1,93 +1,86 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContract { - public partial class ElectionContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; + return new Empty(); + } - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - #endregion + State.MethodFeeController.Value = input; + return new Empty(); + } - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); - - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } - - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #region Views + + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } + + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods + + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; - private void RequiredMethodFeeControllerSet() + var defaultAuthority = new AuthorityInfo { - if (State.MethodFeeController.Value != null) return; + OwnerAddress = GetParliamentDefaultAddress(), + ContractAddress = Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName) + }; - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = GetParliamentDefaultAddress(), - ContractAddress = Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName) - }; + State.MethodFeeController.Value = defaultAuthority; + } - State.MethodFeeController.Value = defaultAuthority; - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContract_Candidate.cs b/contract/AElf.Contracts.Election/ElectionContract_Candidate.cs index c4de9a63af..765ffa4ef5 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Candidate.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Candidate.cs @@ -7,322 +7,301 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +/// +/// AnnounceElection & QuitElection +/// +public partial class ElectionContract { - /// - /// AnnounceElection & QuitElection - /// - public partial class ElectionContract + #region SetCandidateAdmin + + public override Empty SetCandidateAdmin(SetCandidateAdminInput input) { - #region AnnounceElection - - /// - /// Actually this method is for adding an option of the Voting Item. - /// Thus the limitation of candidates will be limited by the capacity of voting options. - /// The input is candidate admin, better be an organization address of Association Contract. - /// - /// - /// - public override Empty AnnounceElection(Address input) - { - var recoveredPublicKey = Context.RecoverPublicKey(); - AnnounceElection(recoveredPublicKey); + Assert(IsCurrentCandidateOrInitialMiner(input.Pubkey), + "Pubkey is neither a current candidate nor an initial miner."); + Assert(!IsPubkeyBanned(input.Pubkey), "Pubkey is already banned."); - var pubkey = recoveredPublicKey.ToHex(); - var address = Address.FromPublicKey(recoveredPublicKey); + // Permission check + var pubkey = State.InitialPubkeyMap[input.Pubkey] ?? input.Pubkey; + if (Context.Sender != GetParliamentDefaultAddress()) + { + if (State.CandidateAdmins[pubkey] == null) + { + // If admin is not set before (due to old contract code) + Assert(Context.Sender == Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)), + "No permission."); + } + else + { + var oldCandidateAdmin = State.CandidateAdmins[pubkey]; + Assert(Context.Sender == oldCandidateAdmin, "No permission."); + } + } - Assert(input.Value.Any(), "Admin is needed while announcing election."); - Assert(State.ManagedCandidatePubkeysMap[address] == null, "Candidate cannot be others' admin."); - State.CandidateAdmins[pubkey] = input; - var managedPubkeys = State.ManagedCandidatePubkeysMap[input] ?? new PubkeyList(); - managedPubkeys.Value.Add(ByteString.CopyFrom(recoveredPublicKey)); - State.ManagedCandidatePubkeysMap[input] = managedPubkeys; + State.CandidateAdmins[pubkey] = input.Admin; - LockCandidateNativeToken(); + var pubkeyByteString = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(pubkey)); - AddCandidateAsOption(pubkey); + var newAdminManagedPubkeys = State.ManagedCandidatePubkeysMap[input.Admin] ?? new PubkeyList(); + if (!newAdminManagedPubkeys.Value.Contains(pubkeyByteString)) + newAdminManagedPubkeys.Value.Add(pubkeyByteString); + State.ManagedCandidatePubkeysMap[input.Admin] = newAdminManagedPubkeys; - if (State.Candidates.Value.Value.Count <= GetValidationDataCenterCount()) - { - State.DataCentersRankingList.Value.DataCenters.Add(pubkey, 0); - RegisterCandidateToSubsidyProfitScheme(address); - } + var oldAdminManagedPubkeys = State.ManagedCandidatePubkeysMap[Context.Sender] ?? new PubkeyList(); + if (oldAdminManagedPubkeys.Value.Contains(pubkeyByteString)) + oldAdminManagedPubkeys.Value.Remove(pubkeyByteString); + State.ManagedCandidatePubkeysMap[Context.Sender] = oldAdminManagedPubkeys; - return new Empty(); - } + return new Empty(); + } - public override Empty AnnounceElectionFor(AnnounceElectionForInput input) - { - var pubkey = input.Pubkey; - var pubkeyBytes = ByteArrayHelper.HexStringToByteArray(pubkey); - var address = Address.FromPublicKey(pubkeyBytes); - AnnounceElection(pubkeyBytes); - var admin = input.Admin ?? Context.Sender; - State.CandidateAdmins[pubkey] = admin; - var managedPubkeys = State.ManagedCandidatePubkeysMap[admin] ?? new PubkeyList(); - managedPubkeys.Value.Add(ByteString.CopyFrom(pubkeyBytes)); - State.ManagedCandidatePubkeysMap[admin] = managedPubkeys; - LockCandidateNativeToken(); - AddCandidateAsOption(pubkey); - if (State.Candidates.Value.Value.Count <= GetValidationDataCenterCount()) - { - State.DataCentersRankingList.Value.DataCenters.Add(pubkey, 0); - RegisterCandidateToSubsidyProfitScheme(address); - } + #endregion - State.CandidateSponsorMap[input.Pubkey] = Context.Sender; - return new Empty(); - } + private bool IsPubkeyBanned(string pubkey) + { + return State.BannedPubkeyMap[pubkey]; + } - private void AnnounceElection(byte[] pubkeyBytes) - { - var pubkey = pubkeyBytes.ToHex(); - var pubkeyByteString = ByteString.CopyFrom(pubkeyBytes); + private Address GetParliamentDefaultAddress() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - Assert(!State.InitialMiners.Value.Value.Contains(pubkeyByteString), - "Initial miner cannot announce election."); + return State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); + } - var candidateInformation = State.CandidateInformationMap[pubkey]; + private bool IsCurrentCandidateOrInitialMiner(string pubkey) + { + var isCurrentCandidate = State.CandidateInformationMap[pubkey] != null && + State.CandidateInformationMap[pubkey].IsCurrentCandidate; + var isInitialMiner = State.InitialMiners.Value.Value.Contains( + ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(pubkey))); + return isCurrentCandidate || isInitialMiner; + } - if (candidateInformation != null) - { - Assert(!candidateInformation.IsCurrentCandidate, - $"This public key already announced election. {pubkey}"); - candidateInformation.AnnouncementTransactionId = Context.OriginTransactionId; - candidateInformation.IsCurrentCandidate = true; - // In this way we can keep history of current candidate, like terms, missed time slots, etc. - State.CandidateInformationMap[pubkey] = candidateInformation; - } - else - { - Assert(!IsPubkeyBanned(pubkey), "This candidate already banned before."); - State.CandidateInformationMap[pubkey] = new CandidateInformation - { - Pubkey = pubkey, - AnnouncementTransactionId = Context.OriginTransactionId, - IsCurrentCandidate = true - }; - } + #region AnnounceElection - State.Candidates.Value.Value.Add(pubkeyByteString); - } + /// + /// Actually this method is for adding an option of the Voting Item. + /// Thus the limitation of candidates will be limited by the capacity of voting options. + /// The input is candidate admin, better be an organization address of Association Contract. + /// + /// + /// + public override Empty AnnounceElection(Address input) + { + var recoveredPublicKey = Context.RecoverPublicKey(); + AnnounceElection(recoveredPublicKey); - private void LockCandidateNativeToken() - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + var pubkey = recoveredPublicKey.ToHex(); + var address = Address.FromPublicKey(recoveredPublicKey); - // Lock the token from sender for deposit of announce election - var lockId = Context.OriginTransactionId; - var lockVirtualAddress = Context.ConvertVirtualAddressToContractAddress(lockId); - var sponsorAddress = Context.Sender; - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = sponsorAddress, - To = lockVirtualAddress, - Symbol = Context.Variables.NativeSymbol, - Amount = ElectionContractConstants.LockTokenForElection, - Memo = "Lock for announcing election." - }); - } + Assert(input.Value.Any(), "Admin is needed while announcing election."); + Assert(State.ManagedCandidatePubkeysMap[address] == null, "Candidate cannot be others' admin."); + State.CandidateAdmins[pubkey] = input; + var managedPubkeys = State.ManagedCandidatePubkeysMap[input] ?? new PubkeyList(); + managedPubkeys.Value.Add(ByteString.CopyFrom(recoveredPublicKey)); + State.ManagedCandidatePubkeysMap[input] = managedPubkeys; - private void AddCandidateAsOption(string publicKey) - { - if (State.VoteContract.Value == null) - { - State.VoteContract.Value = - Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName); - } + LockCandidateNativeToken(); - // Add this candidate as an option for the the Voting Item. - State.VoteContract.AddOption.Send(new AddOptionInput - { - VotingItemId = State.MinerElectionVotingItemId.Value, - Option = publicKey - }); - } + AddCandidateAsOption(pubkey); - private void RegisterCandidateToSubsidyProfitScheme(Address candidateAddress) + if (State.Candidates.Value.Value.Count <= GetValidationDataCenterCount()) { - if (State.ProfitContract.Value == null) - { - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - } - - // Add 1 Shares for this candidate in subsidy profit scheme. - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = candidateAddress, Shares = 1} - }); + State.DataCentersRankingList.Value.DataCenters.Add(pubkey, 0); + RegisterCandidateToSubsidyProfitScheme(address); } - #endregion - - #region QuitElection + return new Empty(); + } - /// - /// delete a option of voting,then sub the Shares from the corresponding ProfitItem - /// - /// Empty - /// - public override Empty QuitElection(StringValue input) + public override Empty AnnounceElectionFor(AnnounceElectionForInput input) + { + var pubkey = input.Pubkey; + var pubkeyBytes = ByteArrayHelper.HexStringToByteArray(pubkey); + var address = Address.FromPublicKey(pubkeyBytes); + AnnounceElection(pubkeyBytes); + var admin = input.Admin ?? Context.Sender; + State.CandidateAdmins[pubkey] = admin; + var managedPubkeys = State.ManagedCandidatePubkeysMap[admin] ?? new PubkeyList(); + managedPubkeys.Value.Add(ByteString.CopyFrom(pubkeyBytes)); + State.ManagedCandidatePubkeysMap[admin] = managedPubkeys; + LockCandidateNativeToken(); + AddCandidateAsOption(pubkey); + if (State.Candidates.Value.Value.Count <= GetValidationDataCenterCount()) { - var pubkeyBytes = ByteArrayHelper.HexStringToByteArray(input.Value); - QuitElection(pubkeyBytes); - var pubkey = input.Value; - - var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey; - Assert(Context.Sender == State.CandidateAdmins[initialPubkey], "Only admin can quit election."); - var candidateInformation = State.CandidateInformationMap[pubkey]; - - // Unlock candidate's native token. - var lockId = candidateInformation.AnnouncementTransactionId; - var lockVirtualAddress = Context.ConvertVirtualAddressToContractAddress(lockId); - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = lockVirtualAddress, - To = State.CandidateSponsorMap[input.Value] ?? Address.FromPublicKey(pubkeyBytes), - Symbol = Context.Variables.NativeSymbol, - Amount = ElectionContractConstants.LockTokenForElection, - Memo = "Quit election." - }); - - // Update candidate information. - candidateInformation.IsCurrentCandidate = false; - candidateInformation.AnnouncementTransactionId = Hash.Empty; - State.CandidateInformationMap[pubkey] = candidateInformation; + State.DataCentersRankingList.Value.DataCenters.Add(pubkey, 0); + RegisterCandidateToSubsidyProfitScheme(address); + } - // Remove candidate public key from the Voting Item options. - State.VoteContract.RemoveOption.Send(new RemoveOptionInput - { - VotingItemId = State.MinerElectionVotingItemId.Value, - Option = pubkey - }); - var dataCenterList = State.DataCentersRankingList.Value; - if (dataCenterList.DataCenters.ContainsKey(pubkey)) - { - dataCenterList.DataCenters[pubkey] = 0; - UpdateDataCenterAfterMemberVoteAmountChanged(dataCenterList, pubkey, true); - State.DataCentersRankingList.Value = dataCenterList; - } + State.CandidateSponsorMap[input.Pubkey] = Context.Sender; + return new Empty(); + } - var managedCandidatePubkey = State.ManagedCandidatePubkeysMap[Context.Sender]; - managedCandidatePubkey.Value.Remove(ByteString.CopyFrom(pubkeyBytes)); - if (managedCandidatePubkey.Value.Any()) - { - State.ManagedCandidatePubkeysMap[Context.Sender] = managedCandidatePubkey; - } - else - { - State.ManagedCandidatePubkeysMap.Remove(Context.Sender); - } + private void AnnounceElection(byte[] pubkeyBytes) + { + var pubkey = pubkeyBytes.ToHex(); + var pubkeyByteString = ByteString.CopyFrom(pubkeyBytes); - State.CandidateSponsorMap.Remove(pubkey); + Assert(!State.InitialMiners.Value.Value.Contains(pubkeyByteString), + "Initial miner cannot announce election."); - return new Empty(); - } + var candidateInformation = State.CandidateInformationMap[pubkey]; - private void QuitElection(byte[] recoveredPublicKey) + if (candidateInformation != null) { - var publicKeyByteString = ByteString.CopyFrom(recoveredPublicKey); - - Assert(State.Candidates.Value.Value.Contains(publicKeyByteString), "Target is not a candidate."); - - if (State.AEDPoSContract.Value == null) + Assert(!candidateInformation.IsCurrentCandidate, + $"This public key already announced election. {pubkey}"); + candidateInformation.AnnouncementTransactionId = Context.OriginTransactionId; + candidateInformation.IsCurrentCandidate = true; + // In this way we can keep history of current candidate, like terms, missed time slots, etc. + State.CandidateInformationMap[pubkey] = candidateInformation; + } + else + { + Assert(!IsPubkeyBanned(pubkey), "This candidate already banned before."); + State.CandidateInformationMap[pubkey] = new CandidateInformation { - State.AEDPoSContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + Pubkey = pubkey, + AnnouncementTransactionId = Context.OriginTransactionId, + IsCurrentCandidate = true + }; + } - if (State.AEDPoSContract.Value != null) - { - Assert( - !State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys - .Contains(publicKeyByteString), - "Current miners cannot quit election."); - } + State.Candidates.Value.Value.Add(pubkeyByteString); + } - State.Candidates.Value.Value.Remove(publicKeyByteString); - } + private void LockCandidateNativeToken() + { + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + // Lock the token from sender for deposit of announce election + var lockId = Context.OriginTransactionId; + var lockVirtualAddress = Context.ConvertVirtualAddressToContractAddress(lockId); + var sponsorAddress = Context.Sender; + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = sponsorAddress, + To = lockVirtualAddress, + Symbol = Context.Variables.NativeSymbol, + Amount = ElectionContractConstants.LockTokenForElection, + Memo = "Lock for announcing election." + }); + } - #endregion + private void AddCandidateAsOption(string publicKey) + { + if (State.VoteContract.Value == null) + State.VoteContract.Value = + Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName); - #region SetCandidateAdmin + // Add this candidate as an option for the the Voting Item. + State.VoteContract.AddOption.Send(new AddOptionInput + { + VotingItemId = State.MinerElectionVotingItemId.Value, + Option = publicKey + }); + } - public override Empty SetCandidateAdmin(SetCandidateAdminInput input) + private void RegisterCandidateToSubsidyProfitScheme(Address candidateAddress) + { + if (State.ProfitContract.Value == null) + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); + + // Add 1 Shares for this candidate in subsidy profit scheme. + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - Assert(IsCurrentCandidateOrInitialMiner(input.Pubkey), - "Pubkey is neither a current candidate nor an initial miner."); - Assert(!IsPubkeyBanned(input.Pubkey), "Pubkey is already banned."); + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = candidateAddress, Shares = 1 } + }); + } - // Permission check - var pubkey = State.InitialPubkeyMap[input.Pubkey] ?? input.Pubkey; - if (Context.Sender != GetParliamentDefaultAddress()) - { - if (State.CandidateAdmins[pubkey] == null) - { - // If admin is not set before (due to old contract code) - Assert(Context.Sender == Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)), - "No permission."); - } - else - { - var oldCandidateAdmin = State.CandidateAdmins[pubkey]; - Assert(Context.Sender == oldCandidateAdmin, "No permission."); - } - } + #endregion - State.CandidateAdmins[pubkey] = input.Admin; + #region QuitElection - var pubkeyByteString = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(pubkey)); + /// + /// delete a option of voting,then sub the Shares from the corresponding ProfitItem + /// + /// Empty + /// + public override Empty QuitElection(StringValue input) + { + var pubkeyBytes = ByteArrayHelper.HexStringToByteArray(input.Value); + QuitElection(pubkeyBytes); + var pubkey = input.Value; + + var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey; + Assert(Context.Sender == State.CandidateAdmins[initialPubkey], "Only admin can quit election."); + var candidateInformation = State.CandidateInformationMap[pubkey]; + + // Unlock candidate's native token. + var lockId = candidateInformation.AnnouncementTransactionId; + var lockVirtualAddress = Context.ConvertVirtualAddressToContractAddress(lockId); + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = lockVirtualAddress, + To = State.CandidateSponsorMap[input.Value] ?? Address.FromPublicKey(pubkeyBytes), + Symbol = Context.Variables.NativeSymbol, + Amount = ElectionContractConstants.LockTokenForElection, + Memo = "Quit election." + }); + + // Update candidate information. + candidateInformation.IsCurrentCandidate = false; + candidateInformation.AnnouncementTransactionId = Hash.Empty; + State.CandidateInformationMap[pubkey] = candidateInformation; + + // Remove candidate public key from the Voting Item options. + State.VoteContract.RemoveOption.Send(new RemoveOptionInput + { + VotingItemId = State.MinerElectionVotingItemId.Value, + Option = pubkey + }); + var dataCenterList = State.DataCentersRankingList.Value; + if (dataCenterList.DataCenters.ContainsKey(pubkey)) + { + dataCenterList.DataCenters[pubkey] = 0; + UpdateDataCenterAfterMemberVoteAmountChanged(dataCenterList, pubkey, true); + State.DataCentersRankingList.Value = dataCenterList; + } - var newAdminManagedPubkeys = State.ManagedCandidatePubkeysMap[input.Admin] ?? new PubkeyList(); - if (!newAdminManagedPubkeys.Value.Contains(pubkeyByteString)) - { - newAdminManagedPubkeys.Value.Add(pubkeyByteString); - } - State.ManagedCandidatePubkeysMap[input.Admin] = newAdminManagedPubkeys; + var managedCandidatePubkey = State.ManagedCandidatePubkeysMap[Context.Sender]; + managedCandidatePubkey.Value.Remove(ByteString.CopyFrom(pubkeyBytes)); + if (managedCandidatePubkey.Value.Any()) + State.ManagedCandidatePubkeysMap[Context.Sender] = managedCandidatePubkey; + else + State.ManagedCandidatePubkeysMap.Remove(Context.Sender); - var oldAdminManagedPubkeys = State.ManagedCandidatePubkeysMap[Context.Sender] ?? new PubkeyList(); - if (oldAdminManagedPubkeys.Value.Contains(pubkeyByteString)) - { - oldAdminManagedPubkeys.Value.Remove(pubkeyByteString); - } - State.ManagedCandidatePubkeysMap[Context.Sender] = oldAdminManagedPubkeys; + State.CandidateSponsorMap.Remove(pubkey); - return new Empty(); - } + return new Empty(); + } - #endregion + private void QuitElection(byte[] recoveredPublicKey) + { + var publicKeyByteString = ByteString.CopyFrom(recoveredPublicKey); - private bool IsPubkeyBanned(string pubkey) - { - return State.BannedPubkeyMap[pubkey]; - } + Assert(State.Candidates.Value.Value.Contains(publicKeyByteString), "Target is not a candidate."); - private Address GetParliamentDefaultAddress() - { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } + if (State.AEDPoSContract.Value == null) + State.AEDPoSContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - return State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); - } + if (State.AEDPoSContract.Value != null) + Assert( + !State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys + .Contains(publicKeyByteString), + "Current miners cannot quit election."); - private bool IsCurrentCandidateOrInitialMiner(string pubkey) - { - var isCurrentCandidate = State.CandidateInformationMap[pubkey] != null && - State.CandidateInformationMap[pubkey].IsCurrentCandidate; - var isInitialMiner = State.InitialMiners.Value.Value.Contains( - ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(pubkey))); - return isCurrentCandidate || isInitialMiner; - } + State.Candidates.Value.Value.Remove(publicKeyByteString); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index f3853752f5..3d0e1de4df 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -10,348 +10,386 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election -{ - /// - /// Vote & Withdraw - /// - public partial class ElectionContract - { - private const int DaySec = 86400; - - #region Vote +namespace AElf.Contracts.Election; - /// - /// Call the Vote function of VoteContract to do a voting. - /// - /// - /// - public override Hash Vote(VoteMinerInput input) - { - // Check candidate information map instead of candidates. - var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; - AssertValidCandidateInformation(targetInformation); - - var recoveredPublicKey = Context.RecoverPublicKey(); - - var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds; - AssertValidLockSeconds(lockSeconds); - - var voteId = GenerateVoteId(input); - Assert(State.LockTimeMap[voteId] == 0, "Vote already exists."); - State.LockTimeMap[voteId] = lockSeconds; +/// +/// Vote & Withdraw +/// +public partial class ElectionContract +{ + private const int DaySec = 86400; - UpdateElectorInformation(recoveredPublicKey, input.Amount, voteId); + #region ChangeVotingTarget - var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount, voteId); + public override Empty ChangeVotingOption(ChangeVotingOptionInput input) + { + var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; + AssertValidCandidateInformation(targetInformation); + var votingRecord = State.VoteContract.GetVotingRecord.Call(input.VoteId); + Assert(Context.Sender == votingRecord.Voter, "No permission to change current vote's option."); + var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); + var claimedLockDays = State.LockTimeMap[input.VoteId]; + Assert(actualLockedTime < claimedLockDays, "This vote already expired."); + + // Withdraw old votes + State.VoteContract.Withdraw.Send(new WithdrawInput + { + VoteId = input.VoteId + }); + + // Create new votes + State.VoteContract.Vote.Send(new VoteInput + { + VoteId = input.VoteId, + VotingItemId = State.MinerElectionVotingItemId.Value, + Amount = votingRecord.Amount, + Voter = votingRecord.Voter, + Option = input.CandidatePubkey, + IsChangeTarget = true + }); + + // Update related candidate + var oldVoteOptionPublicKey = GetNewestPubkey(votingRecord.Option); + var oldCandidateVotes = State.CandidateVotes[oldVoteOptionPublicKey]; + oldCandidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId); + oldCandidateVotes.ObtainedActiveVotedVotesAmount = + oldCandidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); + oldCandidateVotes.AllObtainedVotedVotesAmount = + oldCandidateVotes.AllObtainedVotedVotesAmount.Sub(votingRecord.Amount); + State.CandidateVotes[oldVoteOptionPublicKey] = oldCandidateVotes; + + long voteAmountOfNewCandidate; + var newCandidateVotes = State.CandidateVotes[input.CandidatePubkey]; + if (newCandidateVotes != null) + { + newCandidateVotes.ObtainedActiveVotingRecordIds.Add(input.VoteId); + newCandidateVotes.ObtainedActiveVotedVotesAmount = + newCandidateVotes.ObtainedActiveVotedVotesAmount.Add(votingRecord.Amount); + newCandidateVotes.AllObtainedVotedVotesAmount = + newCandidateVotes.AllObtainedVotedVotesAmount.Add(votingRecord.Amount); + State.CandidateVotes[input.CandidatePubkey] = newCandidateVotes; + voteAmountOfNewCandidate = newCandidateVotes.ObtainedActiveVotedVotesAmount; + } + else + { + State.CandidateVotes[input.CandidatePubkey] = new CandidateVote + { + Pubkey = ByteStringHelper.FromHexString(input.CandidatePubkey), + ObtainedActiveVotingRecordIds = { input.VoteId }, + ObtainedActiveVotedVotesAmount = votingRecord.Amount, + AllObtainedVotedVotesAmount = votingRecord.Amount + }; + voteAmountOfNewCandidate = votingRecord.Amount; + } - LockTokensOfVoter(input.Amount, voteId); - TransferTokensToVoter(input.Amount); - CallVoteContractVote(input.Amount, input.CandidatePubkey, voteId); - AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds); + var dataCenterList = State.DataCentersRankingList.Value; + if (dataCenterList.DataCenters.ContainsKey(input.CandidatePubkey)) + { + dataCenterList.DataCenters[input.CandidatePubkey] = + dataCenterList.DataCenters[input.CandidatePubkey].Add(votingRecord.Amount); + } + else if (dataCenterList.DataCenters.Count < GetValidationDataCenterCount()) + { + // add data center + dataCenterList.DataCenters.Add(input.CandidatePubkey, + State.CandidateVotes[input.CandidatePubkey].ObtainedActiveVotedVotesAmount); - var rankingList = State.DataCentersRankingList.Value; - if (rankingList.DataCenters.ContainsKey(input.CandidatePubkey)) - { - rankingList.DataCenters[input.CandidatePubkey] = - rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount); - State.DataCentersRankingList.Value = rankingList; - } - else + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - if (rankingList.DataCenters.Count < GetValidationDataCenterCount()) - { - State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, - candidateVotesAmount); - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)), - Shares = 1 - } - }); - } - else + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare { - TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList); + Beneficiary = + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)), + Shares = 1 } - } - - return voteId; + }); } - - public override Hash VoteWithExpiredVotes(VoteMinerInput input) + else { - // Check candidate information map instead of candidates. - var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; - AssertValidCandidateInformation(targetInformation); + CandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate); + } - var recoveredPublicKey = Context.RecoverPublicKey(); + if (dataCenterList.DataCenters.ContainsKey(oldVoteOptionPublicKey)) + { + dataCenterList.DataCenters[oldVoteOptionPublicKey] = + dataCenterList.DataCenters[oldVoteOptionPublicKey].Sub(votingRecord.Amount); + UpdateDataCenterAfterMemberVoteAmountChanged(dataCenterList, oldVoteOptionPublicKey); + } - var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds; - AssertValidLockSeconds(lockSeconds); + State.DataCentersRankingList.Value = dataCenterList; + return new Empty(); + } - var voteId = GenerateVoteId(input); - Assert(State.LockTimeMap[voteId] == 0, "Vote already exists."); - State.LockTimeMap[voteId] = lockSeconds; + #endregion - UpdateElectorInformation(recoveredPublicKey, input.Amount, voteId); + public override Empty SetVoteWeightInterest(VoteWeightInterestList input) + { + AssertPerformedByVoteWeightInterestController(); + Assert(input.VoteWeightInterestInfos.Count > 0, "invalid input"); + // ReSharper disable once PossibleNullReferenceException + foreach (var info in input.VoteWeightInterestInfos) + { + Assert(info.Capital > 0, "invalid input"); + Assert(info.Day > 0, "invalid input"); + Assert(info.Interest > 0, "invalid input"); + } + + Assert(input.VoteWeightInterestInfos.GroupBy(x => x.Day).Count() == input.VoteWeightInterestInfos.Count, + "repeat day input"); + var orderList = input.VoteWeightInterestInfos.OrderBy(x => x.Day).ToArray(); + input.VoteWeightInterestInfos.Clear(); + input.VoteWeightInterestInfos.AddRange(orderList); + State.VoteWeightInterestList.Value = input; + return new Empty(); + } - var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount, voteId); + public override Empty SetVoteWeightProportion(VoteWeightProportion input) + { + AssertPerformedByVoteWeightInterestController(); + Assert(input.TimeProportion > 0 && input.AmountProportion > 0, "invalid input"); + State.VoteWeightProportion.Value = input; + return new Empty(); + } - // TODO: De-vote previous one then call VoteContract.Vote - CallVoteContractVote(input.Amount, input.CandidatePubkey, voteId); - // TODO: Remove old beneficiary then add new. - AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds); + public override Empty ChangeVoteWeightInterestController(AuthorityInfo input) + { + AssertPerformedByVoteWeightInterestController(); + Assert(CheckOrganizationExist(input), "Invalid authority input."); + State.VoteWeightInterestController.Value = input; + return new Empty(); + } - var rankingList = State.DataCentersRankingList.Value; - if (rankingList.DataCenters.ContainsKey(input.CandidatePubkey)) - { - rankingList.DataCenters[input.CandidatePubkey] = - rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount); - State.DataCentersRankingList.Value = rankingList; - } - else + private VoteWeightInterestList GetDefaultVoteWeightInterest() + { + return new VoteWeightInterestList + { + VoteWeightInterestInfos = { - if (rankingList.DataCenters.Count < GetValidationDataCenterCount()) + new VoteWeightInterest { - State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, - candidateVotesAmount); - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)), - Shares = 1 - } - }); - } - else + Day = 365, + Interest = 1, + Capital = 1000 + }, + new VoteWeightInterest { - TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList); + Day = 730, + Interest = 15, + Capital = 10000 + }, + new VoteWeightInterest + { + Day = 1095, + Interest = 2, + Capital = 1000 } } + }; + } + + private VoteWeightProportion GetVoteWeightProportion() + { + return State.VoteWeightProportion.Value ?? + (State.VoteWeightProportion.Value = GetDefaultVoteWeightProportion()); + } - return voteId; - } - private void TryToBecomeAValidationDataCenter(VoteMinerInput input, long candidateVotesAmount, - DataCenterRankingList rankingList) + private VoteWeightProportion GetDefaultVoteWeightProportion() + { + return new VoteWeightProportion { - var minimumVotes = candidateVotesAmount; - var minimumVotesCandidate = input.CandidatePubkey; - bool replaceWillHappen = false; - foreach (var pubkeyToVotesAmount in rankingList.DataCenters.OrderBy(x => x.Value)) - { - if (pubkeyToVotesAmount.Value < minimumVotes) - { - replaceWillHappen = true; - minimumVotesCandidate = pubkeyToVotesAmount.Key; - break; - } - } + TimeProportion = 2, + AmountProportion = 1 + }; + } - if (replaceWillHappen) - { - State.DataCentersRankingList.Value.DataCenters.Remove(minimumVotesCandidate); - State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, - candidateVotesAmount); - NotifyProfitReplaceCandidateInDataCenter(minimumVotesCandidate, input.CandidatePubkey); - } - } + private void UnlockTokensOfVoter(Hash input, long amount, Address voterAddress = null) + { + State.TokenContract.Unlock.Send(new UnlockInput + { + Address = voterAddress ?? Context.Sender, + Symbol = Context.Variables.NativeSymbol, + Amount = amount, + LockId = input, + Usage = "Withdraw votes for Main Chain Miner Election." + }); + } - /// - /// Update Elector's Votes information. - /// - /// - /// - /// - private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Hash voteId) - { - var voterPublicKey = recoveredPublicKey.ToHex(); - var voterPublicKeyByteString = ByteString.CopyFrom(recoveredPublicKey); - var voterVotes = State.ElectorVotes[voterPublicKey]; - if (voterVotes == null) - { - voterVotes = new ElectorVote - { - Pubkey = voterPublicKeyByteString, - ActiveVotingRecordIds = {voteId}, - ActiveVotedVotesAmount = amount, - AllVotedVotesAmount = amount - }; - } - else + private void RetrieveTokensFromVoter(long amount, Address voterAddress = null) + { + foreach (var symbol in new List + { ElectionContractConstants.ShareSymbol, ElectionContractConstants.VoteSymbol }) + State.TokenContract.TransferFrom.Send(new TransferFromInput { - voterVotes.ActiveVotingRecordIds.Add(voteId); - voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Add(amount); - voterVotes.AllVotedVotesAmount = voterVotes.AllVotedVotesAmount.Add(amount); - } + From = voterAddress ?? Context.Sender, + To = Context.Self, + Amount = amount, + Symbol = symbol, + Memo = $"Return {symbol} tokens." + }); + } - State.ElectorVotes[voterPublicKey] = voterVotes; - } + private void WithdrawTokensOfVoter(Hash input) + { + State.VoteContract.Withdraw.Send(new WithdrawInput + { + VoteId = input + }); + } - /// - /// Update Candidate's Votes information. - /// - /// - /// - /// - private long UpdateCandidateInformation(string candidatePublicKey, long amount, Hash voteId) + private void RemoveBeneficiaryOfVoter(Address voterAddress = null) + { + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { - var candidateVotes = State.CandidateVotes[candidatePublicKey]; - if (candidateVotes == null) - { - candidateVotes = new CandidateVote - { - Pubkey = ByteStringHelper.FromHexString(candidatePublicKey), - ObtainedActiveVotingRecordIds = {voteId}, - ObtainedActiveVotedVotesAmount = amount, - AllObtainedVotedVotesAmount = amount - }; - } - else - { - candidateVotes.ObtainedActiveVotingRecordIds.Add(voteId); - candidateVotes.ObtainedActiveVotedVotesAmount = - candidateVotes.ObtainedActiveVotedVotesAmount.Add(amount); - candidateVotes.AllObtainedVotedVotesAmount = - candidateVotes.AllObtainedVotedVotesAmount.Add(amount); - } + SchemeId = State.WelfareHash.Value, + Beneficiary = voterAddress ?? Context.Sender + }); + } - State.CandidateVotes[candidatePublicKey] = candidateVotes; + private void AssertValidCandidateInformation(CandidateInformation candidateInformation) + { + Assert(candidateInformation != null, "Candidate not found."); + // ReSharper disable once PossibleNullReferenceException + Assert(candidateInformation.IsCurrentCandidate, "Candidate quited election."); + } - return candidateVotes.ObtainedActiveVotedVotesAmount; - } + private void AssertValidLockSeconds(long lockSeconds) + { + Assert(lockSeconds >= State.MinimumLockTime.Value, + $"Invalid lock time. At least {State.MinimumLockTime.Value.Div(60).Div(60).Div(24)} days"); + Assert(lockSeconds <= State.MaximumLockTime.Value, + $"Invalid lock time. At most {State.MaximumLockTime.Value.Div(60).Div(60).Div(24)} days"); + } - private long GetVotesWeight(long votesAmount, long lockTime) - { - var lockDays = lockTime.Div(DaySec); - var timeAndAmountProportion = GetVoteWeightProportion(); - if (State.VoteWeightInterestList.Value == null) - State.VoteWeightInterestList.Value = GetDefaultVoteWeightInterest(); - foreach (var instMap in State.VoteWeightInterestList.Value.VoteWeightInterestInfos) + private void LockTokensOfVoter(long amount, Hash voteId) + { + State.TokenContract.Lock.Send(new LockInput + { + Address = Context.Sender, + Symbol = Context.Variables.NativeSymbol, + LockId = voteId, + Amount = amount, + Usage = "Voting for Main Chain Miner Election." + }); + } + + /// + /// Issue VOTE tokens to this voter. + /// + /// + private void TransferTokensToVoter(long amount) + { + foreach (var symbol in new List + { ElectionContractConstants.ShareSymbol, ElectionContractConstants.VoteSymbol }) + State.TokenContract.Transfer.Send(new TransferInput { - if (lockDays > instMap.Day) - continue; - var initBase = 1 + (decimal) instMap.Interest / instMap.Capital; - return ((long) (Pow(initBase, (uint) lockDays) * votesAmount)).Add(votesAmount - .Mul(timeAndAmountProportion.AmountProportion).Div(timeAndAmountProportion.TimeProportion)); - } + Symbol = symbol, + To = Context.Sender, + Amount = amount, + Memo = $"Transfer {symbol}." + }); + } - var maxInterestInfo = State.VoteWeightInterestList.Value.VoteWeightInterestInfos.Last(); - var maxInterestBase = 1 + (decimal) maxInterestInfo.Interest / maxInterestInfo.Capital; - return ((long) (Pow(maxInterestBase, (uint) lockDays) * votesAmount)).Add(votesAmount - .Mul(timeAndAmountProportion.AmountProportion).Div(timeAndAmountProportion.TimeProportion)); - } + private void CallVoteContractVote(long amount, string candidatePubkey, Hash voteId) + { + State.VoteContract.Vote.Send(new VoteInput + { + Voter = Context.Sender, + VotingItemId = State.MinerElectionVotingItemId.Value, + Amount = amount, + Option = candidatePubkey, + VoteId = voteId + }); + } - private static decimal Pow(decimal x, uint y) + private void AddBeneficiaryToVoter(long votesWeight, long lockSeconds) + { + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - if (y == 1) - return (long) x; - decimal a = 1m; - if (y == 0) - return a; - var e = new BitArray(y.ToBytes(false)); - var t = e.Count; - for (var i = t - 1; i >= 0; --i) + SchemeId = State.WelfareHash.Value, + BeneficiaryShare = new BeneficiaryShare { - a *= a; - if (e[i]) - { - a *= x; - } - } + Beneficiary = Context.Sender, + Shares = votesWeight + }, + EndPeriod = GetEndPeriod(lockSeconds) + }); + } - return a; - } + private void AssertPerformedByVoteWeightInterestController() + { + if (State.VoteWeightInterestController.Value == null) + State.VoteWeightInterestController.Value = GetDefaultVoteWeightInterestController(); - private long GetEndPeriod(long lockTime) + Assert(Context.Sender == State.VoteWeightInterestController.Value.OwnerAddress, "No permission."); + } + + private AuthorityInfo GetDefaultVoteWeightInterestController() + { + return new AuthorityInfo { - var treasury = State.ProfitContract.GetScheme.Call(State.TreasuryHash.Value); - return lockTime.Div(State.TimeEachTerm.Value).Add(treasury.CurrentPeriod); - } + ContractAddress = Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName), + OwnerAddress = GetParliamentDefaultAddress() + }; + } - #endregion + private Hash GenerateVoteId(VoteMinerInput voteMinerInput) + { + if (voteMinerInput.Token != null) + return Context.GenerateId(Context.Self, voteMinerInput.Token); + + var candidateVotesCount = + State.CandidateVotes[voteMinerInput.CandidatePubkey]?.ObtainedActiveVotedVotesAmount ?? 0; + return Context.GenerateId(Context.Self, + ByteArrayHelper.ConcatArrays(voteMinerInput.CandidatePubkey.GetBytes(), + candidateVotesCount.ToBytes(false))); + } - #region ChangeVotingTarget + #region Vote - public override Empty ChangeVotingOption(ChangeVotingOptionInput input) - { - var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; - AssertValidCandidateInformation(targetInformation); - var votingRecord = State.VoteContract.GetVotingRecord.Call(input.VoteId); - Assert(Context.Sender == votingRecord.Voter, "No permission to change current vote's option."); - var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); - var claimedLockDays = State.LockTimeMap[input.VoteId]; - Assert(actualLockedTime < claimedLockDays, "This vote already expired."); + /// + /// Call the Vote function of VoteContract to do a voting. + /// + /// + /// + public override Hash Vote(VoteMinerInput input) + { + // Check candidate information map instead of candidates. + var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; + AssertValidCandidateInformation(targetInformation); - // Withdraw old votes - State.VoteContract.Withdraw.Send(new WithdrawInput - { - VoteId = input.VoteId - }); + var recoveredPublicKey = Context.RecoverPublicKey(); - // Create new votes - State.VoteContract.Vote.Send(new VoteInput - { - VoteId = input.VoteId, - VotingItemId = State.MinerElectionVotingItemId.Value, - Amount = votingRecord.Amount, - Voter = votingRecord.Voter, - Option = input.CandidatePubkey, - IsChangeTarget = true - }); + var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds; + AssertValidLockSeconds(lockSeconds); - // Update related candidate - var oldVoteOptionPublicKey = GetNewestPubkey(votingRecord.Option); - var oldCandidateVotes = State.CandidateVotes[oldVoteOptionPublicKey]; - oldCandidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId); - oldCandidateVotes.ObtainedActiveVotedVotesAmount = - oldCandidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); - oldCandidateVotes.AllObtainedVotedVotesAmount = - oldCandidateVotes.AllObtainedVotedVotesAmount.Sub(votingRecord.Amount); - State.CandidateVotes[oldVoteOptionPublicKey] = oldCandidateVotes; - - long voteAmountOfNewCandidate; - var newCandidateVotes = State.CandidateVotes[input.CandidatePubkey]; - if (newCandidateVotes != null) - { - newCandidateVotes.ObtainedActiveVotingRecordIds.Add(input.VoteId); - newCandidateVotes.ObtainedActiveVotedVotesAmount = - newCandidateVotes.ObtainedActiveVotedVotesAmount.Add(votingRecord.Amount); - newCandidateVotes.AllObtainedVotedVotesAmount = - newCandidateVotes.AllObtainedVotedVotesAmount.Add(votingRecord.Amount); - State.CandidateVotes[input.CandidatePubkey] = newCandidateVotes; - voteAmountOfNewCandidate = newCandidateVotes.ObtainedActiveVotedVotesAmount; - } - else - { - State.CandidateVotes[input.CandidatePubkey] = new CandidateVote - { - Pubkey = ByteStringHelper.FromHexString(input.CandidatePubkey), - ObtainedActiveVotingRecordIds = {input.VoteId}, - ObtainedActiveVotedVotesAmount = votingRecord.Amount, - AllObtainedVotedVotesAmount = votingRecord.Amount - }; - voteAmountOfNewCandidate = votingRecord.Amount; - } + var voteId = GenerateVoteId(input); + Assert(State.LockTimeMap[voteId] == 0, "Vote already exists."); + State.LockTimeMap[voteId] = lockSeconds; - var dataCenterList = State.DataCentersRankingList.Value; - if (dataCenterList.DataCenters.ContainsKey(input.CandidatePubkey)) - dataCenterList.DataCenters[input.CandidatePubkey] = - dataCenterList.DataCenters[input.CandidatePubkey].Add(votingRecord.Amount); - else if (dataCenterList.DataCenters.Count < GetValidationDataCenterCount()) - { - // add data center - dataCenterList.DataCenters.Add(input.CandidatePubkey, - State.CandidateVotes[input.CandidatePubkey].ObtainedActiveVotedVotesAmount); + UpdateElectorInformation(recoveredPublicKey, input.Amount, voteId); + + var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount, voteId); + LockTokensOfVoter(input.Amount, voteId); + TransferTokensToVoter(input.Amount); + CallVoteContractVote(input.Amount, input.CandidatePubkey, voteId); + AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds); + + var rankingList = State.DataCentersRankingList.Value; + if (rankingList.DataCenters.ContainsKey(input.CandidatePubkey)) + { + rankingList.DataCenters[input.CandidatePubkey] = + rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount); + State.DataCentersRankingList.Value = rankingList; + } + else + { + if (rankingList.DataCenters.Count < GetValidationDataCenterCount()) + { + State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, + candidateVotesAmount); State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { SchemeId = State.SubsidyHash.Value, @@ -364,482 +402,421 @@ public override Empty ChangeVotingOption(ChangeVotingOptionInput input) }); } else - CandidateReplaceMemberInDataCenter(dataCenterList, input.CandidatePubkey, voteAmountOfNewCandidate); - - if (dataCenterList.DataCenters.ContainsKey(oldVoteOptionPublicKey)) { - dataCenterList.DataCenters[oldVoteOptionPublicKey] = - dataCenterList.DataCenters[oldVoteOptionPublicKey].Sub(votingRecord.Amount); - UpdateDataCenterAfterMemberVoteAmountChanged(dataCenterList, oldVoteOptionPublicKey); + TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList); } - - State.DataCentersRankingList.Value = dataCenterList; - return new Empty(); } - #endregion + return voteId; + } - #region Withdraw + public override Hash VoteWithExpiredVotes(VoteMinerInput input) + { + // Check candidate information map instead of candidates. + var targetInformation = State.CandidateInformationMap[input.CandidatePubkey]; + AssertValidCandidateInformation(targetInformation); - /// - /// Withdraw a voting,recall the votes the voted by sender. - /// At the same time,the Shares that the voter occupied will sub form TotalShares. - /// and the "VOTE" token will be returned to ElectionContract; - /// - /// Hash - /// - public override Empty Withdraw(Hash input) - { - var votingRecord = State.VoteContract.GetVotingRecord.Call(input); + var recoveredPublicKey = Context.RecoverPublicKey(); - var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); - var claimedLockDays = State.LockTimeMap[input]; - Assert(actualLockedTime >= claimedLockDays, - $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock your token."); - - // Update Elector's Votes information. - var voterPublicKey = Context.RecoverPublicKey().ToHex(); - var voterVotes = State.ElectorVotes[voterPublicKey]; - if (voterVotes == null) - { - throw new AssertionException($"Voter {voterPublicKey} never votes before."); - } + var lockSeconds = (input.EndTimestamp - Context.CurrentBlockTime).Seconds; + AssertValidLockSeconds(lockSeconds); - voterVotes.ActiveVotingRecordIds.Remove(input); - voterVotes.WithdrawnVotingRecordIds.Add(input); - voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); - State.ElectorVotes[voterPublicKey] = voterVotes; + var voteId = GenerateVoteId(input); + Assert(State.LockTimeMap[voteId] == 0, "Vote already exists."); + State.LockTimeMap[voteId] = lockSeconds; - // Update Candidate's Votes information. - var newestPubkey = GetNewestPubkey(votingRecord.Option); - var candidateVotes = State.CandidateVotes[newestPubkey]; - if (candidateVotes == null) - { - throw new AssertionException( - $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); - } + UpdateElectorInformation(recoveredPublicKey, input.Amount, voteId); - candidateVotes.ObtainedActiveVotingRecordIds.Remove(input); - candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input); - candidateVotes.ObtainedActiveVotedVotesAmount = - candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); - State.CandidateVotes[newestPubkey] = candidateVotes; - - UnlockTokensOfVoter(input, votingRecord.Amount); - RetrieveTokensFromVoter(votingRecord.Amount); - WithdrawTokensOfVoter(input); - if (!State.WeightsAlreadyFixedMap[input]) - { - RemoveBeneficiaryOfVoter(); - State.WeightsAlreadyFixedMap.Remove(input); - } - - var rankingList = State.DataCentersRankingList.Value; - if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty(); - rankingList.DataCenters[newestPubkey] = - rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount); - UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, newestPubkey); - State.DataCentersRankingList.Value = rankingList; + var candidateVotesAmount = UpdateCandidateInformation(input.CandidatePubkey, input.Amount, voteId); - return new Empty(); - } + // TODO: De-vote previous one then call VoteContract.Vote + CallVoteContractVote(input.Amount, input.CandidatePubkey, voteId); + // TODO: Remove old beneficiary then add new. + AddBeneficiaryToVoter(GetVotesWeight(input.Amount, lockSeconds), lockSeconds); - public override Empty AssistWithdraw(AssistWithdrawInput input) + var rankingList = State.DataCentersRankingList.Value; + if (rankingList.DataCenters.ContainsKey(input.CandidatePubkey)) { - var votingRecord = State.VoteContract.GetVotingRecord.Call(input.VoteId); - - var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); - var claimedLockDays = State.LockTimeMap[input.VoteId]; - Assert(actualLockedTime >= claimedLockDays, - $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock {input.Pubkey}'s token."); - - // Update Elector's Votes information. - var voterPublicKey = input.Pubkey; - var voterVotes = State.ElectorVotes[voterPublicKey]; - if (voterVotes == null) - { - throw new AssertionException($"Voter {voterPublicKey} never votes before."); - } - - voterVotes.ActiveVotingRecordIds.Remove(input.VoteId); - voterVotes.WithdrawnVotingRecordIds.Add(input.VoteId); - voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); - State.ElectorVotes[voterPublicKey] = voterVotes; - - // Update Candidate's Votes information. - var newestPubkey = GetNewestPubkey(votingRecord.Option); - var candidateVotes = State.CandidateVotes[newestPubkey]; - if (candidateVotes == null) - { - throw new AssertionException( - $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); - } - - candidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId); - candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input.VoteId); - candidateVotes.ObtainedActiveVotedVotesAmount = - candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); - State.CandidateVotes[newestPubkey] = candidateVotes; - - var voterAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(voterPublicKey)); - UnlockTokensOfVoter(input.VoteId, votingRecord.Amount, voterAddress); - RetrieveTokensFromVoter(votingRecord.Amount, voterAddress); - WithdrawTokensOfVoter(input.VoteId); - if (!State.WeightsAlreadyFixedMap[input.VoteId]) - { - RemoveBeneficiaryOfVoter(voterAddress); - State.WeightsAlreadyFixedMap.Remove(input.VoteId); - } - - var rankingList = State.DataCentersRankingList.Value; - if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty(); - rankingList.DataCenters[newestPubkey] = - rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount); - UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, newestPubkey); + rankingList.DataCenters[input.CandidatePubkey] = + rankingList.DataCenters[input.CandidatePubkey].Add(input.Amount); State.DataCentersRankingList.Value = rankingList; - - return new Empty(); } - - public override Empty FixTotalWeights(FixTotalWeightsInput input) + else { - foreach (var voteId in input.VoteIds) + if (rankingList.DataCenters.Count < GetValidationDataCenterCount()) { - var votingRecord = State.VoteContract.GetVotingRecord.Call(voteId); - var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); - var claimedLockDays = State.LockTimeMap[voteId]; - if (actualLockedTime < claimedLockDays) - { - continue; - } - - State.WeightsAlreadyFixedMap[voteId] = true; - RemoveBeneficiaryOfVoter(votingRecord.Voter); - } - - return new Empty(); - } - - private void UpdateDataCenterAfterMemberVoteAmountChanged(DataCenterRankingList rankingList, - string targetMember, - bool isForceReplace = false) - { - var amountAfterWithdraw = rankingList.DataCenters[targetMember]; - if (isForceReplace) - Assert(amountAfterWithdraw == 0, "should update vote amount in data center firstly"); - else if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw)) - return; - - var validCandidates = State.Candidates.Value.Value.Select(x => x.ToHex()) - .Where(c => !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] != null) - .OrderByDescending(x => State.CandidateVotes[x].ObtainedActiveVotedVotesAmount); - string maxVoterPublicKeyStringOutOfDataCenter = null; - long maxVoteAmountOutOfDataCenter = 0; - var maxVoteCandidateOutDataCenter = validCandidates.FirstOrDefault(); - if (maxVoteCandidateOutDataCenter != null) - { - maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter; - maxVoteAmountOutOfDataCenter = State.CandidateVotes[maxVoteCandidateOutDataCenter] - .ObtainedActiveVotedVotesAmount; - } - - if (isForceReplace) - { - rankingList.DataCenters.Remove(targetMember); - if (maxVoteCandidateOutDataCenter == null) + State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, + candidateVotesAmount); + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - maxVoteCandidateOutDataCenter = State.Candidates.Value.Value.Select(x => x.ToHex()) - .FirstOrDefault(c => - !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] == null); - if (maxVoteCandidateOutDataCenter != null) + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare { - maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter; - maxVoteAmountOutOfDataCenter = 0; + Beneficiary = + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.CandidatePubkey)), + Shares = 1 } - } + }); } else { - if (maxVoteAmountOutOfDataCenter <= amountAfterWithdraw) - return; - rankingList.DataCenters.Remove(targetMember); - } - - if (maxVoterPublicKeyStringOutOfDataCenter != null) - { - rankingList.DataCenters[maxVoterPublicKeyStringOutOfDataCenter] = maxVoteAmountOutOfDataCenter; + TryToBecomeAValidationDataCenter(input, candidateVotesAmount, rankingList); } - - NotifyProfitReplaceCandidateInDataCenter(targetMember, maxVoterPublicKeyStringOutOfDataCenter); } - private void CandidateReplaceMemberInDataCenter(DataCenterRankingList rankingList, string candidate, - long voteAmount) - { - var dateCenter = rankingList.DataCenters; - if (dateCenter.Count < GetValidationDataCenterCount()) - return; - if (dateCenter.ContainsKey(candidate)) - return; - var list = dateCenter.ToList(); - var minimumVoteCandidateInDataCenter = list.OrderBy(x => x.Value).First(); - if (voteAmount <= minimumVoteCandidateInDataCenter.Value) return; - dateCenter.Remove(minimumVoteCandidateInDataCenter.Key); - dateCenter[candidate] = voteAmount; - NotifyProfitReplaceCandidateInDataCenter(minimumVoteCandidateInDataCenter.Key, candidate); - } - - private void NotifyProfitReplaceCandidateInDataCenter(string oldCandidateInDataCenter, - string newCandidateDataCenter) - { - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(oldCandidateInDataCenter)) - }); - if (newCandidateDataCenter == null) - return; - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(newCandidateDataCenter)), - Shares = 1 - } - }); - } - - #endregion + return voteId; + } - public override Empty SetVoteWeightInterest(VoteWeightInterestList input) - { - AssertPerformedByVoteWeightInterestController(); - Assert(input.VoteWeightInterestInfos.Count > 0, "invalid input"); - // ReSharper disable once PossibleNullReferenceException - foreach (var info in input.VoteWeightInterestInfos) - { - Assert(info.Capital > 0, "invalid input"); - Assert(info.Day > 0, "invalid input"); - Assert(info.Interest > 0, "invalid input"); + private void TryToBecomeAValidationDataCenter(VoteMinerInput input, long candidateVotesAmount, + DataCenterRankingList rankingList) + { + var minimumVotes = candidateVotesAmount; + var minimumVotesCandidate = input.CandidatePubkey; + var replaceWillHappen = false; + foreach (var pubkeyToVotesAmount in rankingList.DataCenters.OrderBy(x => x.Value)) + if (pubkeyToVotesAmount.Value < minimumVotes) + { + replaceWillHappen = true; + minimumVotesCandidate = pubkeyToVotesAmount.Key; + break; } - Assert(input.VoteWeightInterestInfos.GroupBy(x => x.Day).Count() == input.VoteWeightInterestInfos.Count, - "repeat day input"); - var orderList = input.VoteWeightInterestInfos.OrderBy(x => x.Day).ToArray(); - input.VoteWeightInterestInfos.Clear(); - input.VoteWeightInterestInfos.AddRange(orderList); - State.VoteWeightInterestList.Value = input; - return new Empty(); - } - - public override Empty SetVoteWeightProportion(VoteWeightProportion input) - { - AssertPerformedByVoteWeightInterestController(); - Assert(input.TimeProportion > 0 && input.AmountProportion > 0, "invalid input"); - State.VoteWeightProportion.Value = input; - return new Empty(); - } - - public override Empty ChangeVoteWeightInterestController(AuthorityInfo input) + if (replaceWillHappen) { - AssertPerformedByVoteWeightInterestController(); - Assert(CheckOrganizationExist(input), "Invalid authority input."); - State.VoteWeightInterestController.Value = input; - return new Empty(); + State.DataCentersRankingList.Value.DataCenters.Remove(minimumVotesCandidate); + State.DataCentersRankingList.Value.DataCenters.Add(input.CandidatePubkey, + candidateVotesAmount); + NotifyProfitReplaceCandidateInDataCenter(minimumVotesCandidate, input.CandidatePubkey); } + } - private VoteWeightInterestList GetDefaultVoteWeightInterest() + /// + /// Update Elector's Votes information. + /// + /// + /// + /// + private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Hash voteId) + { + var voterPublicKey = recoveredPublicKey.ToHex(); + var voterPublicKeyByteString = ByteString.CopyFrom(recoveredPublicKey); + var voterVotes = State.ElectorVotes[voterPublicKey]; + if (voterVotes == null) { - return new VoteWeightInterestList + voterVotes = new ElectorVote { - VoteWeightInterestInfos = - { - new VoteWeightInterest - { - Day = 365, - Interest = 1, - Capital = 1000 - }, - new VoteWeightInterest - { - Day = 730, - Interest = 15, - Capital = 10000 - }, - new VoteWeightInterest - { - Day = 1095, - Interest = 2, - Capital = 1000 - } - } + Pubkey = voterPublicKeyByteString, + ActiveVotingRecordIds = { voteId }, + ActiveVotedVotesAmount = amount, + AllVotedVotesAmount = amount }; } - - private VoteWeightProportion GetVoteWeightProportion() + else { - return State.VoteWeightProportion.Value ?? - (State.VoteWeightProportion.Value = GetDefaultVoteWeightProportion()); + voterVotes.ActiveVotingRecordIds.Add(voteId); + voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Add(amount); + voterVotes.AllVotedVotesAmount = voterVotes.AllVotedVotesAmount.Add(amount); } + State.ElectorVotes[voterPublicKey] = voterVotes; + } - private VoteWeightProportion GetDefaultVoteWeightProportion() + /// + /// Update Candidate's Votes information. + /// + /// + /// + /// + private long UpdateCandidateInformation(string candidatePublicKey, long amount, Hash voteId) + { + var candidateVotes = State.CandidateVotes[candidatePublicKey]; + if (candidateVotes == null) { - return new VoteWeightProportion + candidateVotes = new CandidateVote { - TimeProportion = 2, - AmountProportion = 1 + Pubkey = ByteStringHelper.FromHexString(candidatePublicKey), + ObtainedActiveVotingRecordIds = { voteId }, + ObtainedActiveVotedVotesAmount = amount, + AllObtainedVotedVotesAmount = amount }; } - - private void UnlockTokensOfVoter(Hash input, long amount, Address voterAddress = null) + else { - State.TokenContract.Unlock.Send(new UnlockInput - { - Address = voterAddress ?? Context.Sender, - Symbol = Context.Variables.NativeSymbol, - Amount = amount, - LockId = input, - Usage = "Withdraw votes for Main Chain Miner Election." - }); + candidateVotes.ObtainedActiveVotingRecordIds.Add(voteId); + candidateVotes.ObtainedActiveVotedVotesAmount = + candidateVotes.ObtainedActiveVotedVotesAmount.Add(amount); + candidateVotes.AllObtainedVotedVotesAmount = + candidateVotes.AllObtainedVotedVotesAmount.Add(amount); } - private void RetrieveTokensFromVoter(long amount, Address voterAddress = null) - { - foreach (var symbol in new List - {ElectionContractConstants.ShareSymbol, ElectionContractConstants.VoteSymbol}) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = voterAddress ?? Context.Sender, - To = Context.Self, - Amount = amount, - Symbol = symbol, - Memo = $"Return {symbol} tokens." - }); - } - } + State.CandidateVotes[candidatePublicKey] = candidateVotes; - private void WithdrawTokensOfVoter(Hash input) - { - State.VoteContract.Withdraw.Send(new WithdrawInput - { - VoteId = input - }); - } + return candidateVotes.ObtainedActiveVotedVotesAmount; + } - private void RemoveBeneficiaryOfVoter(Address voterAddress = null) - { - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.WelfareHash.Value, - Beneficiary = voterAddress ?? Context.Sender - }); + private long GetVotesWeight(long votesAmount, long lockTime) + { + var lockDays = lockTime.Div(DaySec); + var timeAndAmountProportion = GetVoteWeightProportion(); + if (State.VoteWeightInterestList.Value == null) + State.VoteWeightInterestList.Value = GetDefaultVoteWeightInterest(); + foreach (var instMap in State.VoteWeightInterestList.Value.VoteWeightInterestInfos) + { + if (lockDays > instMap.Day) + continue; + var initBase = 1 + (decimal)instMap.Interest / instMap.Capital; + return ((long)(Pow(initBase, (uint)lockDays) * votesAmount)).Add(votesAmount + .Mul(timeAndAmountProportion.AmountProportion).Div(timeAndAmountProportion.TimeProportion)); } - private void AssertValidCandidateInformation(CandidateInformation candidateInformation) - { - Assert(candidateInformation != null, "Candidate not found."); - // ReSharper disable once PossibleNullReferenceException - Assert(candidateInformation.IsCurrentCandidate, "Candidate quited election."); - } + var maxInterestInfo = State.VoteWeightInterestList.Value.VoteWeightInterestInfos.Last(); + var maxInterestBase = 1 + (decimal)maxInterestInfo.Interest / maxInterestInfo.Capital; + return ((long)(Pow(maxInterestBase, (uint)lockDays) * votesAmount)).Add(votesAmount + .Mul(timeAndAmountProportion.AmountProportion).Div(timeAndAmountProportion.TimeProportion)); + } - private void AssertValidLockSeconds(long lockSeconds) + private static decimal Pow(decimal x, uint y) + { + if (y == 1) + return (long)x; + var a = 1m; + if (y == 0) + return a; + var e = new BitArray(y.ToBytes(false)); + var t = e.Count; + for (var i = t - 1; i >= 0; --i) { - Assert(lockSeconds >= State.MinimumLockTime.Value, - $"Invalid lock time. At least {State.MinimumLockTime.Value.Div(60).Div(60).Div(24)} days"); - Assert(lockSeconds <= State.MaximumLockTime.Value, - $"Invalid lock time. At most {State.MaximumLockTime.Value.Div(60).Div(60).Div(24)} days"); + a *= a; + if (e[i]) a *= x; } - private void LockTokensOfVoter(long amount, Hash voteId) + return a; + } + + private long GetEndPeriod(long lockTime) + { + var treasury = State.ProfitContract.GetScheme.Call(State.TreasuryHash.Value); + return lockTime.Div(State.TimeEachTerm.Value).Add(treasury.CurrentPeriod); + } + + #endregion + + #region Withdraw + + /// + /// Withdraw a voting,recall the votes the voted by sender. + /// At the same time,the Shares that the voter occupied will sub form TotalShares. + /// and the "VOTE" token will be returned to ElectionContract; + /// + /// Hash + /// + public override Empty Withdraw(Hash input) + { + var votingRecord = State.VoteContract.GetVotingRecord.Call(input); + + var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); + var claimedLockDays = State.LockTimeMap[input]; + Assert(actualLockedTime >= claimedLockDays, + $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock your token."); + + // Update Elector's Votes information. + var voterPublicKey = Context.RecoverPublicKey().ToHex(); + var voterVotes = State.ElectorVotes[voterPublicKey]; + if (voterVotes == null) throw new AssertionException($"Voter {voterPublicKey} never votes before."); + + voterVotes.ActiveVotingRecordIds.Remove(input); + voterVotes.WithdrawnVotingRecordIds.Add(input); + voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); + State.ElectorVotes[voterPublicKey] = voterVotes; + + // Update Candidate's Votes information. + var newestPubkey = GetNewestPubkey(votingRecord.Option); + var candidateVotes = State.CandidateVotes[newestPubkey]; + if (candidateVotes == null) + throw new AssertionException( + $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); + + candidateVotes.ObtainedActiveVotingRecordIds.Remove(input); + candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input); + candidateVotes.ObtainedActiveVotedVotesAmount = + candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); + State.CandidateVotes[newestPubkey] = candidateVotes; + + UnlockTokensOfVoter(input, votingRecord.Amount); + RetrieveTokensFromVoter(votingRecord.Amount); + WithdrawTokensOfVoter(input); + if (!State.WeightsAlreadyFixedMap[input]) + { + RemoveBeneficiaryOfVoter(); + State.WeightsAlreadyFixedMap.Remove(input); + } + + var rankingList = State.DataCentersRankingList.Value; + if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty(); + rankingList.DataCenters[newestPubkey] = + rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount); + UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, newestPubkey); + State.DataCentersRankingList.Value = rankingList; + + return new Empty(); + } + + public override Empty AssistWithdraw(AssistWithdrawInput input) + { + var votingRecord = State.VoteContract.GetVotingRecord.Call(input.VoteId); + + var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); + var claimedLockDays = State.LockTimeMap[input.VoteId]; + Assert(actualLockedTime >= claimedLockDays, + $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock {input.Pubkey}'s token."); + + // Update Elector's Votes information. + var voterPublicKey = input.Pubkey; + var voterVotes = State.ElectorVotes[voterPublicKey]; + if (voterVotes == null) throw new AssertionException($"Voter {voterPublicKey} never votes before."); + + voterVotes.ActiveVotingRecordIds.Remove(input.VoteId); + voterVotes.WithdrawnVotingRecordIds.Add(input.VoteId); + voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); + State.ElectorVotes[voterPublicKey] = voterVotes; + + // Update Candidate's Votes information. + var newestPubkey = GetNewestPubkey(votingRecord.Option); + var candidateVotes = State.CandidateVotes[newestPubkey]; + if (candidateVotes == null) + throw new AssertionException( + $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); + + candidateVotes.ObtainedActiveVotingRecordIds.Remove(input.VoteId); + candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input.VoteId); + candidateVotes.ObtainedActiveVotedVotesAmount = + candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); + State.CandidateVotes[newestPubkey] = candidateVotes; + + var voterAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(voterPublicKey)); + UnlockTokensOfVoter(input.VoteId, votingRecord.Amount, voterAddress); + RetrieveTokensFromVoter(votingRecord.Amount, voterAddress); + WithdrawTokensOfVoter(input.VoteId); + if (!State.WeightsAlreadyFixedMap[input.VoteId]) + { + RemoveBeneficiaryOfVoter(voterAddress); + State.WeightsAlreadyFixedMap.Remove(input.VoteId); + } + + var rankingList = State.DataCentersRankingList.Value; + if (!rankingList.DataCenters.ContainsKey(newestPubkey)) return new Empty(); + rankingList.DataCenters[newestPubkey] = + rankingList.DataCenters[newestPubkey].Sub(votingRecord.Amount); + UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, newestPubkey); + State.DataCentersRankingList.Value = rankingList; + + return new Empty(); + } + + public override Empty FixTotalWeights(FixTotalWeightsInput input) + { + foreach (var voteId in input.VoteIds) { - State.TokenContract.Lock.Send(new LockInput - { - Address = Context.Sender, - Symbol = Context.Variables.NativeSymbol, - LockId = voteId, - Amount = amount, - Usage = "Voting for Main Chain Miner Election." - }); + var votingRecord = State.VoteContract.GetVotingRecord.Call(voteId); + var actualLockedTime = Context.CurrentBlockTime.Seconds.Sub(votingRecord.VoteTimestamp.Seconds); + var claimedLockDays = State.LockTimeMap[voteId]; + if (actualLockedTime < claimedLockDays) continue; + + State.WeightsAlreadyFixedMap[voteId] = true; + RemoveBeneficiaryOfVoter(votingRecord.Voter); } - /// - /// Issue VOTE tokens to this voter. - /// - /// - private void TransferTokensToVoter(long amount) - { - foreach (var symbol in new List - {ElectionContractConstants.ShareSymbol, ElectionContractConstants.VoteSymbol}) - { - State.TokenContract.Transfer.Send(new TransferInput + return new Empty(); + } + + private void UpdateDataCenterAfterMemberVoteAmountChanged(DataCenterRankingList rankingList, + string targetMember, + bool isForceReplace = false) + { + var amountAfterWithdraw = rankingList.DataCenters[targetMember]; + if (isForceReplace) + Assert(amountAfterWithdraw == 0, "should update vote amount in data center firstly"); + else if (rankingList.DataCenters.Any(x => x.Value < amountAfterWithdraw)) + return; + + var validCandidates = State.Candidates.Value.Value.Select(x => x.ToHex()) + .Where(c => !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] != null) + .OrderByDescending(x => State.CandidateVotes[x].ObtainedActiveVotedVotesAmount); + string maxVoterPublicKeyStringOutOfDataCenter = null; + long maxVoteAmountOutOfDataCenter = 0; + var maxVoteCandidateOutDataCenter = validCandidates.FirstOrDefault(); + if (maxVoteCandidateOutDataCenter != null) + { + maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter; + maxVoteAmountOutOfDataCenter = State.CandidateVotes[maxVoteCandidateOutDataCenter] + .ObtainedActiveVotedVotesAmount; + } + + if (isForceReplace) + { + rankingList.DataCenters.Remove(targetMember); + if (maxVoteCandidateOutDataCenter == null) + { + maxVoteCandidateOutDataCenter = State.Candidates.Value.Value.Select(x => x.ToHex()) + .FirstOrDefault(c => + !rankingList.DataCenters.ContainsKey(c) && State.CandidateVotes[c] == null); + if (maxVoteCandidateOutDataCenter != null) { - Symbol = symbol, - To = Context.Sender, - Amount = amount, - Memo = $"Transfer {symbol}." - }); + maxVoterPublicKeyStringOutOfDataCenter = maxVoteCandidateOutDataCenter; + maxVoteAmountOutOfDataCenter = 0; + } } } - - private void CallVoteContractVote(long amount, string candidatePubkey, Hash voteId) + else { - State.VoteContract.Vote.Send(new VoteInput - { - Voter = Context.Sender, - VotingItemId = State.MinerElectionVotingItemId.Value, - Amount = amount, - Option = candidatePubkey, - VoteId = voteId - }); + if (maxVoteAmountOutOfDataCenter <= amountAfterWithdraw) + return; + rankingList.DataCenters.Remove(targetMember); } - private void AddBeneficiaryToVoter(long votesWeight, long lockSeconds) - { - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.WelfareHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = Context.Sender, - Shares = votesWeight - }, - EndPeriod = GetEndPeriod(lockSeconds) - }); - } + if (maxVoterPublicKeyStringOutOfDataCenter != null) + rankingList.DataCenters[maxVoterPublicKeyStringOutOfDataCenter] = maxVoteAmountOutOfDataCenter; - private void AssertPerformedByVoteWeightInterestController() - { - if (State.VoteWeightInterestController.Value == null) - { - State.VoteWeightInterestController.Value = GetDefaultVoteWeightInterestController(); - } + NotifyProfitReplaceCandidateInDataCenter(targetMember, maxVoterPublicKeyStringOutOfDataCenter); + } - Assert(Context.Sender == State.VoteWeightInterestController.Value.OwnerAddress, "No permission."); - } + private void CandidateReplaceMemberInDataCenter(DataCenterRankingList rankingList, string candidate, + long voteAmount) + { + var dateCenter = rankingList.DataCenters; + if (dateCenter.Count < GetValidationDataCenterCount()) + return; + if (dateCenter.ContainsKey(candidate)) + return; + var list = dateCenter.ToList(); + var minimumVoteCandidateInDataCenter = list.OrderBy(x => x.Value).First(); + if (voteAmount <= minimumVoteCandidateInDataCenter.Value) return; + dateCenter.Remove(minimumVoteCandidateInDataCenter.Key); + dateCenter[candidate] = voteAmount; + NotifyProfitReplaceCandidateInDataCenter(minimumVoteCandidateInDataCenter.Key, candidate); + } - private AuthorityInfo GetDefaultVoteWeightInterestController() + private void NotifyProfitReplaceCandidateInDataCenter(string oldCandidateInDataCenter, + string newCandidateDataCenter) + { + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { - return new AuthorityInfo - { - ContractAddress = Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName), - OwnerAddress = GetParliamentDefaultAddress() - }; - } - - private Hash GenerateVoteId(VoteMinerInput voteMinerInput) + SchemeId = State.SubsidyHash.Value, + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(oldCandidateInDataCenter)) + }); + if (newCandidateDataCenter == null) + return; + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - if (voteMinerInput.Token != null) - return Context.GenerateId(Context.Self, voteMinerInput.Token); - - var candidateVotesCount = - State.CandidateVotes[voteMinerInput.CandidatePubkey]?.ObtainedActiveVotedVotesAmount ?? 0; - return Context.GenerateId(Context.Self, - ByteArrayHelper.ConcatArrays(voteMinerInput.CandidatePubkey.GetBytes(), - candidateVotesCount.ToBytes(false))); - } + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare + { + Beneficiary = + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(newCandidateDataCenter)), + Shares = 1 + } + }); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs b/contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs index a86bde0cd0..098f73241d 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Maintainence.cs @@ -2,7 +2,6 @@ using System.Linq; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Profit; -using AElf.Contracts.Treasury; using AElf.Contracts.Vote; using AElf.CSharp.Core; using AElf.Sdk.CSharp; @@ -10,521 +9,492 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContract : ElectionContractImplContainer.ElectionContractImplBase { - public partial class ElectionContract : ElectionContractImplContainer.ElectionContractImplBase + /// + /// Initialize the ElectionContract and corresponding contract states. + /// + /// InitialElectionContractInput + /// + public override Empty InitialElectionContract(InitialElectionContractInput input) { - /// - /// Initialize the ElectionContract and corresponding contract states. - /// - /// InitialElectionContractInput - /// - public override Empty InitialElectionContract(InitialElectionContractInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); + Assert(!State.Initialized.Value, "Already initialized."); - State.Candidates.Value = new PubkeyList(); + State.Candidates.Value = new PubkeyList(); - State.MinimumLockTime.Value = input.MinimumLockTime; - State.MaximumLockTime.Value = input.MaximumLockTime; + State.MinimumLockTime.Value = input.MinimumLockTime; + State.MaximumLockTime.Value = input.MaximumLockTime; - State.TimeEachTerm.Value = input.TimeEachTerm; - - State.MinersCount.Value = input.MinerList.Count; - State.InitialMiners.Value = new PubkeyList - { - Value = {input.MinerList.Select(ByteStringHelper.FromHexString)} - }; - foreach (var pubkey in input.MinerList) - { - State.CandidateInformationMap[pubkey] = new CandidateInformation - { - Pubkey = pubkey - }; - } - - State.CurrentTermNumber.Value = 1; - - State.DataCentersRankingList.Value = new DataCenterRankingList(); - - State.Initialized.Value = true; - - return new Empty(); - } + State.TimeEachTerm.Value = input.TimeEachTerm; - public override Empty RegisterElectionVotingEvent(Empty input) + State.MinersCount.Value = input.MinerList.Count; + State.InitialMiners.Value = new PubkeyList { - Assert(!State.VotingEventRegistered.Value, "Already registered."); - - State.VoteContract.Value = Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName); - - var votingRegisterInput = new VotingRegisterInput + Value = { input.MinerList.Select(ByteStringHelper.FromHexString) } + }; + foreach (var pubkey in input.MinerList) + State.CandidateInformationMap[pubkey] = new CandidateInformation { - IsLockToken = false, - AcceptedCurrency = Context.Variables.NativeSymbol, - TotalSnapshotNumber = long.MaxValue, - StartTimestamp = TimestampHelper.MinValue, - EndTimestamp = TimestampHelper.MaxValue + Pubkey = pubkey }; - State.VoteContract.Register.Send(votingRegisterInput); - State.MinerElectionVotingItemId.Value = HashHelper.ConcatAndCompute( - HashHelper.ComputeFrom(votingRegisterInput), - HashHelper.ComputeFrom(Context.Self)); + State.CurrentTermNumber.Value = 1; - State.VotingEventRegistered.Value = true; - return new Empty(); - } + State.DataCentersRankingList.Value = new DataCenterRankingList(); - #region TakeSnapshot + State.Initialized.Value = true; - public override Empty TakeSnapshot(TakeElectionSnapshotInput input) - { - if (State.AEDPoSContract.Value == null) - { - State.AEDPoSContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } - - Assert(State.AEDPoSContract.Value == Context.Sender, "No permission."); - - SavePreviousTermInformation(input); + return new Empty(); + } - if (State.ProfitContract.Value == null) - { - var profitContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - // Return if profit contract didn't deployed. (Often in test cases.) - if (profitContractAddress == null) return new Empty(); - State.ProfitContract.Value = profitContractAddress; - } + public override Empty RegisterElectionVotingEvent(Empty input) + { + Assert(!State.VotingEventRegistered.Value, "Already registered."); - // Update snapshot of corresponding voting record by the way. - State.VoteContract.TakeSnapshot.Send(new TakeSnapshotInput - { - SnapshotNumber = input.TermNumber, - VotingItemId = State.MinerElectionVotingItemId.Value - }); + State.VoteContract.Value = Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName); - State.CurrentTermNumber.Value = input.TermNumber.Add(1); + var votingRegisterInput = new VotingRegisterInput + { + IsLockToken = false, + AcceptedCurrency = Context.Variables.NativeSymbol, + TotalSnapshotNumber = long.MaxValue, + StartTimestamp = TimestampHelper.MinValue, + EndTimestamp = TimestampHelper.MaxValue + }; + State.VoteContract.Register.Send(votingRegisterInput); + + State.MinerElectionVotingItemId.Value = HashHelper.ConcatAndCompute( + HashHelper.ComputeFrom(votingRegisterInput), + HashHelper.ComputeFrom(Context.Self)); + + State.VotingEventRegistered.Value = true; + return new Empty(); + } - var previousTermMinerList = - State.AEDPoSContract.GetPreviousTermMinerPubkeyList.Call(new Empty()).Pubkeys.ToList(); + /// + /// Update the candidate information,if it's not evil node. + /// + /// UpdateCandidateInformationInput + /// + public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput input) + { + Assert( + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == + Context.Sender || Context.Sender == GetEmergencyResponseOrganizationAddress(), + "Only consensus contract can update candidate information."); - foreach (var pubkey in previousTermMinerList) - { - UpdateCandidateInformation(pubkey, input.TermNumber, previousTermMinerList); - } + var candidateInformation = State.CandidateInformationMap[input.Pubkey]; + if (candidateInformation == null) return new Empty(); - if (State.DividendPoolContract.Value == null) + if (input.IsEvilNode) + { + var publicKeyByte = ByteArrayHelper.HexStringToByteArray(input.Pubkey); + State.BannedPubkeyMap[input.Pubkey] = true; + var rankingList = State.DataCentersRankingList.Value; + if (rankingList.DataCenters.ContainsKey(input.Pubkey)) { - State.DividendPoolContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + rankingList.DataCenters[input.Pubkey] = 0; + UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, input.Pubkey, true); + State.DataCentersRankingList.Value = rankingList; } - var symbolList = State.DividendPoolContract.GetSymbolList.Call(new Empty()); - var amountsMap = symbolList.Value.ToDictionary(s => s, s => 0L); - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput + Context.LogDebug(() => $"Marked {input.Pubkey.Substring(0, 10)} as an evil node."); + Context.Fire(new EvilMinerDetected { Pubkey = input.Pubkey }); + State.CandidateInformationMap.Remove(input.Pubkey); + var candidates = State.Candidates.Value; + candidates.Value.Remove(ByteString.CopyFrom(publicKeyByte)); + State.Candidates.Value = candidates; + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { SchemeId = State.SubsidyHash.Value, - Period = input.TermNumber, - AmountsMap = {amountsMap} - }); - - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeId = State.WelfareHash.Value, - Period = input.TermNumber, - AmountsMap = {amountsMap} + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)) }); - return new Empty(); } - private void SavePreviousTermInformation(TakeElectionSnapshotInput input) - { - var snapshot = new TermSnapshot - { - MinedBlocks = input.MinedBlocks, - EndRoundNumber = input.RoundNumber - }; - - if (State.Candidates.Value == null) return; + candidateInformation.ProducedBlocks = candidateInformation.ProducedBlocks.Add(input.RecentlyProducedBlocks); + candidateInformation.MissedTimeSlots = + candidateInformation.MissedTimeSlots.Add(input.RecentlyMissedTimeSlots); + State.CandidateInformationMap[input.Pubkey] = candidateInformation; + return new Empty(); + } - foreach (var pubkey in State.Candidates.Value.Value) - { - var votes = State.CandidateVotes[pubkey.ToHex()]; - var validObtainedVotesAmount = 0L; - if (votes != null) - { - validObtainedVotesAmount = votes.ObtainedActiveVotedVotesAmount; - } + private Address GetEmergencyResponseOrganizationAddress() + { + if (State.EmergencyResponseOrganizationAddress.Value != null) + return State.EmergencyResponseOrganizationAddress.Value; - snapshot.ElectionResult.Add(pubkey.ToHex(), validObtainedVotesAmount); - } + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - State.Snapshots[input.TermNumber] = snapshot; - } + State.EmergencyResponseOrganizationAddress.Value = + State.ParliamentContract.GetEmergencyResponseOrganizationAddress.Call(new Empty()); - private void UpdateCandidateInformation(string pubkey, long lastTermNumber, - List previousMiners) - { - var candidateInformation = State.CandidateInformationMap[pubkey]; - if (candidateInformation == null) return; - candidateInformation.Terms.Add(lastTermNumber); - var victories = GetVictories(previousMiners); - candidateInformation.ContinualAppointmentCount = victories.Contains(ByteStringHelper.FromHexString(pubkey)) - ? candidateInformation.ContinualAppointmentCount.Add(1) - : 0; - State.CandidateInformationMap[pubkey] = candidateInformation; - } + return State.EmergencyResponseOrganizationAddress.Value; + } - #endregion + public override Empty UpdateMultipleCandidateInformation(UpdateMultipleCandidateInformationInput input) + { + Assert( + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, + "Only consensus contract can update candidate information."); - /// - /// Update the candidate information,if it's not evil node. - /// - /// UpdateCandidateInformationInput - /// - public override Empty UpdateCandidateInformation(UpdateCandidateInformationInput input) - { - Assert( - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == - Context.Sender || Context.Sender == GetEmergencyResponseOrganizationAddress(), - "Only consensus contract can update candidate information."); + foreach (var updateCandidateInformationInput in input.Value) + UpdateCandidateInformation(updateCandidateInformationInput); - var candidateInformation = State.CandidateInformationMap[input.Pubkey]; - if (candidateInformation == null) - { - return new Empty(); - } + return new Empty(); + } - if (input.IsEvilNode) - { - var publicKeyByte = ByteArrayHelper.HexStringToByteArray(input.Pubkey); - State.BannedPubkeyMap[input.Pubkey] = true; - var rankingList = State.DataCentersRankingList.Value; - if (rankingList.DataCenters.ContainsKey(input.Pubkey)) - { - rankingList.DataCenters[input.Pubkey] = 0; - UpdateDataCenterAfterMemberVoteAmountChanged(rankingList, input.Pubkey, true); - State.DataCentersRankingList.Value = rankingList; - } + public override Empty UpdateMinersCount(UpdateMinersCountInput input) + { + Context.LogDebug(() => + $"Consensus Contract Address: {Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName)}"); + Context.LogDebug(() => $"Sender Address: {Context.Sender}"); + Assert( + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, + "Only consensus contract can update miners count."); + State.MinersCount.Value = input.MinersCount; + SyncSubsidyInfoAfterReduceMiner(); + return new Empty(); + } - Context.LogDebug(() => $"Marked {input.Pubkey.Substring(0, 10)} as an evil node."); - Context.Fire(new EvilMinerDetected {Pubkey = input.Pubkey}); - State.CandidateInformationMap.Remove(input.Pubkey); - var candidates = State.Candidates.Value; - candidates.Value.Remove(ByteString.CopyFrom(publicKeyByte)); - State.Candidates.Value = candidates; - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)) - }); - return new Empty(); - } + public override Empty SetTreasurySchemeIds(SetTreasurySchemeIdsInput input) + { + Assert(State.TreasuryHash.Value == null, "Treasury profit ids already set."); + State.TreasuryHash.Value = input.TreasuryHash; + State.WelfareHash.Value = input.WelfareHash; + State.SubsidyHash.Value = input.SubsidyHash; + State.WelcomeHash.Value = input.WelcomeHash; + State.FlexibleHash.Value = input.FlexibleHash; + return new Empty(); + } - candidateInformation.ProducedBlocks = candidateInformation.ProducedBlocks.Add(input.RecentlyProducedBlocks); - candidateInformation.MissedTimeSlots = - candidateInformation.MissedTimeSlots.Add(input.RecentlyMissedTimeSlots); - State.CandidateInformationMap[input.Pubkey] = candidateInformation; - return new Empty(); - } + public override Empty ReplaceCandidatePubkey(ReplaceCandidatePubkeyInput input) + { + Assert(IsCurrentCandidateOrInitialMiner(input.OldPubkey), + "Pubkey is neither a current candidate nor an initial miner."); + Assert(!IsPubkeyBanned(input.OldPubkey) && !IsPubkeyBanned(input.NewPubkey), + "Pubkey is in already banned."); - private Address GetEmergencyResponseOrganizationAddress() - { - if (State.EmergencyResponseOrganizationAddress.Value != null) - { - return State.EmergencyResponseOrganizationAddress.Value; - } + // Permission check. + Assert(Context.Sender == GetCandidateAdmin(new StringValue { Value = input.OldPubkey }), "No permission."); - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } + // Record the replacement. + PerformReplacement(input.OldPubkey, input.NewPubkey); - State.EmergencyResponseOrganizationAddress.Value = - State.ParliamentContract.GetEmergencyResponseOrganizationAddress.Call(new Empty()); + var oldPubkeyBytes = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(input.OldPubkey)); + var newPubkeyBytes = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(input.NewPubkey)); - return State.EmergencyResponseOrganizationAddress.Value; + // Remove origin pubkey from Candidates, DataCentersRankingList and InitialMiners; then add new pubkey. + var candidates = State.Candidates.Value; + Assert(!candidates.Value.Contains(newPubkeyBytes), "New pubkey is already a candidate."); + if (candidates.Value.Contains(oldPubkeyBytes)) + { + candidates.Value.Remove(oldPubkeyBytes); + candidates.Value.Add(newPubkeyBytes); + State.Candidates.Value = candidates; } - public override Empty UpdateMultipleCandidateInformation(UpdateMultipleCandidateInformationInput input) + var rankingList = State.DataCentersRankingList.Value; + if (rankingList.DataCenters.ContainsKey(input.OldPubkey)) { - Assert( - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, - "Only consensus contract can update candidate information."); + rankingList.DataCenters.Add(input.NewPubkey, rankingList.DataCenters[input.OldPubkey]); + rankingList.DataCenters.Remove(input.OldPubkey); + State.DataCentersRankingList.Value = rankingList; - foreach (var updateCandidateInformationInput in input.Value) - { - UpdateCandidateInformation(updateCandidateInformationInput); - } + // Notify Profit Contract to update backup subsidy profiting item. + if (State.ProfitContract.Value == null) + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - return new Empty(); + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput + { + SchemeId = State.SubsidyHash.Value, + Beneficiary = Address.FromPublicKey(oldPubkeyBytes.ToByteArray()) + }); + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput + { + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare + { + Beneficiary = Address.FromPublicKey(newPubkeyBytes.ToByteArray()), + Shares = 1 + } + }); } - public override Empty UpdateMinersCount(UpdateMinersCountInput input) + var initialMiners = State.InitialMiners.Value; + if (initialMiners.Value.Contains(oldPubkeyBytes)) { - Context.LogDebug(() => - $"Consensus Contract Address: {Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName)}"); - Context.LogDebug(() => $"Sender Address: {Context.Sender}"); - Assert( - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, - "Only consensus contract can update miners count."); - State.MinersCount.Value = input.MinersCount; - SyncSubsidyInfoAfterReduceMiner(); - return new Empty(); + initialMiners.Value.Remove(oldPubkeyBytes); + initialMiners.Value.Add(newPubkeyBytes); + State.InitialMiners.Value = initialMiners; } - public override Empty SetTreasurySchemeIds(SetTreasurySchemeIdsInput input) + // For CandidateVotes and CandidateInformation, just replace value of origin pubkey. + var candidateVotes = State.CandidateVotes[input.OldPubkey]; + if (candidateVotes != null) { - Assert(State.TreasuryHash.Value == null, "Treasury profit ids already set."); - State.TreasuryHash.Value = input.TreasuryHash; - State.WelfareHash.Value = input.WelfareHash; - State.SubsidyHash.Value = input.SubsidyHash; - State.WelcomeHash.Value = input.WelcomeHash; - State.FlexibleHash.Value = input.FlexibleHash; - return new Empty(); + candidateVotes.Pubkey = newPubkeyBytes; + State.CandidateVotes[input.NewPubkey] = candidateVotes; + State.CandidateVotes.Remove(input.OldPubkey); } - public override Empty ReplaceCandidatePubkey(ReplaceCandidatePubkeyInput input) + var candidateInformation = State.CandidateInformationMap[input.OldPubkey]; + if (candidateInformation != null) { - Assert(IsCurrentCandidateOrInitialMiner(input.OldPubkey), - "Pubkey is neither a current candidate nor an initial miner."); - Assert(!IsPubkeyBanned(input.OldPubkey) && !IsPubkeyBanned(input.NewPubkey), - "Pubkey is in already banned."); - - // Permission check. - Assert(Context.Sender == GetCandidateAdmin(new StringValue {Value = input.OldPubkey}), "No permission."); + candidateInformation.Pubkey = input.NewPubkey; + State.CandidateInformationMap[input.NewPubkey] = candidateInformation; + State.CandidateInformationMap.Remove(input.OldPubkey); + } - // Record the replacement. - PerformReplacement(input.OldPubkey, input.NewPubkey); + // Ban old pubkey. + State.BannedPubkeyMap[input.OldPubkey] = true; - var oldPubkeyBytes = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(input.OldPubkey)); - var newPubkeyBytes = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(input.NewPubkey)); + // Update profits receiver if needed. + if (State.TreasuryContract.Value == null) + State.TreasuryContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - // Remove origin pubkey from Candidates, DataCentersRankingList and InitialMiners; then add new pubkey. - var candidates = State.Candidates.Value; - Assert(!candidates.Value.Contains(newPubkeyBytes), "New pubkey is already a candidate."); - if (candidates.Value.Contains(oldPubkeyBytes)) + var profitsReceiver = + State.TreasuryContract.GetProfitsReceiver.Call(new StringValue { Value = input.OldPubkey }); + if (!profitsReceiver.Value.IsEmpty) + State.TreasuryContract.SetProfitsReceiver.Send(new Treasury.SetProfitsReceiverInput { - candidates.Value.Remove(oldPubkeyBytes); - candidates.Value.Add(newPubkeyBytes); - State.Candidates.Value = candidates; - } + Pubkey = input.NewPubkey, + ProfitsReceiverAddress = profitsReceiver + }); - var rankingList = State.DataCentersRankingList.Value; - if (rankingList.DataCenters.ContainsKey(input.OldPubkey)) - { - rankingList.DataCenters.Add(input.NewPubkey, rankingList.DataCenters[input.OldPubkey]); - rankingList.DataCenters.Remove(input.OldPubkey); - State.DataCentersRankingList.Value = rankingList; + Context.Fire(new CandidatePubkeyReplaced + { + OldPubkey = input.OldPubkey, + NewPubkey = input.NewPubkey + }); - // Notify Profit Contract to update backup subsidy profiting item. - if (State.ProfitContract.Value == null) - { - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - } + return new Empty(); + } - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - Beneficiary = Address.FromPublicKey(oldPubkeyBytes.ToByteArray()) - }); - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = Address.FromPublicKey(newPubkeyBytes.ToByteArray()), - Shares = 1 - } - }); - } + private void PerformReplacement(string oldPubkey, string newPubkey) + { + State.CandidateReplacementMap[newPubkey] = oldPubkey; - var initialMiners = State.InitialMiners.Value; - if (initialMiners.Value.Contains(oldPubkeyBytes)) - { - initialMiners.Value.Remove(oldPubkeyBytes); - initialMiners.Value.Add(newPubkeyBytes); - State.InitialMiners.Value = initialMiners; - } + // Initial pubkey is: + // - miner pubkey of the first round (aka. Initial Miner), or + // - the pubkey announced election - // For CandidateVotes and CandidateInformation, just replace value of origin pubkey. - var candidateVotes = State.CandidateVotes[input.OldPubkey]; - if (candidateVotes != null) - { - candidateVotes.Pubkey = newPubkeyBytes; - State.CandidateVotes[input.NewPubkey] = candidateVotes; - State.CandidateVotes.Remove(input.OldPubkey); - } + var initialPubkey = State.InitialPubkeyMap[oldPubkey] ?? oldPubkey; + State.InitialPubkeyMap[newPubkey] = initialPubkey; - var candidateInformation = State.CandidateInformationMap[input.OldPubkey]; - if (candidateInformation != null) - { - candidateInformation.Pubkey = input.NewPubkey; - State.CandidateInformationMap[input.NewPubkey] = candidateInformation; - State.CandidateInformationMap.Remove(input.OldPubkey); - } + State.InitialToNewestPubkeyMap[initialPubkey] = newPubkey; - // Ban old pubkey. - State.BannedPubkeyMap[input.OldPubkey] = true; + // Notify Consensus Contract to update replacement information. (Update from old record.) + if (State.AEDPoSContract.Value == null) + State.AEDPoSContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - // Update profits receiver if needed. - if (State.TreasuryContract.Value == null) - { - State.TreasuryContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - } + State.AEDPoSContract.RecordCandidateReplacement.Send(new RecordCandidateReplacementInput + { + OldPubkey = oldPubkey, + NewPubkey = newPubkey + }); - var profitsReceiver = - State.TreasuryContract.GetProfitsReceiver.Call(new StringValue {Value = input.OldPubkey}); - if (!profitsReceiver.Value.IsEmpty) + var oldPubkeyByteString = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(oldPubkey)); + // Notify Vote Contract to replace option if this is not the initial miner case. + if (!State.InitialMiners.Value.Value.Contains(oldPubkeyByteString)) + { + State.VoteContract.RemoveOption.Send(new RemoveOptionInput { - State.TreasuryContract.SetProfitsReceiver.Send(new AElf.Contracts.Treasury.SetProfitsReceiverInput - { - Pubkey = input.NewPubkey, - ProfitsReceiverAddress = profitsReceiver - }); - } - - Context.Fire(new CandidatePubkeyReplaced + VotingItemId = State.MinerElectionVotingItemId.Value, + Option = oldPubkey + }); + State.VoteContract.AddOption.Send(new AddOptionInput { - OldPubkey = input.OldPubkey, - NewPubkey = input.NewPubkey + VotingItemId = State.MinerElectionVotingItemId.Value, + Option = newPubkey }); - - return new Empty(); } - private void PerformReplacement(string oldPubkey, string newPubkey) - { - State.CandidateReplacementMap[newPubkey] = oldPubkey; + State.CandidateSponsorMap[newPubkey] = State.CandidateSponsorMap[oldPubkey]; + State.CandidateSponsorMap.Remove(oldPubkey); - // Initial pubkey is: - // - miner pubkey of the first round (aka. Initial Miner), or - // - the pubkey announced election + var managedPubkeys = State.ManagedCandidatePubkeysMap[Context.Sender]; + managedPubkeys.Value.Remove(oldPubkeyByteString); + managedPubkeys.Value.Add(ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(newPubkey))); + State.ManagedCandidatePubkeysMap[Context.Sender] = managedPubkeys; - var initialPubkey = State.InitialPubkeyMap[oldPubkey] ?? oldPubkey; - State.InitialPubkeyMap[newPubkey] = initialPubkey; + Context.LogDebug(() => $"Pubkey replacement happened: {oldPubkey} -> {newPubkey}"); + } - State.InitialToNewestPubkeyMap[initialPubkey] = newPubkey; + public override StringValue GetNewestPubkey(StringValue input) + { + return new StringValue { Value = GetNewestPubkey(input.Value) }; + } - // Notify Consensus Contract to update replacement information. (Update from old record.) - if (State.AEDPoSContract.Value == null) - { - State.AEDPoSContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + public override Empty RemoveEvilNode(StringValue input) + { + Assert(Context.Sender == GetEmergencyResponseOrganizationAddress(), "No permission."); + var address = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)); + Assert( + State.Candidates.Value.Value.Select(p => p.ToHex()).Contains(input.Value) || + State.InitialMiners.Value.Value.Select(p => p.ToHex()).Contains(input.Value), + "Cannot remove normal node."); + Assert(!State.BannedPubkeyMap[input.Value], $"{input.Value} already banned."); + UpdateCandidateInformation(new UpdateCandidateInformationInput + { + Pubkey = input.Value, + IsEvilNode = true + }); + return new Empty(); + } + + private string GetNewestPubkey(string pubkey) + { + var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey; + return State.InitialToNewestPubkeyMap[initialPubkey] ?? initialPubkey; + } - State.AEDPoSContract.RecordCandidateReplacement.Send(new RecordCandidateReplacementInput + private void SyncSubsidyInfoAfterReduceMiner() + { + var rankingList = State.DataCentersRankingList.Value; + if (rankingList == null) + return; + var validDataCenterCount = GetValidationDataCenterCount(); + if (rankingList.DataCenters.Count <= validDataCenterCount) return; + Context.LogDebug(() => "sync DataCenter after reduce bp"); + var diffCount = rankingList.DataCenters.Count.Sub(validDataCenterCount); + var toRemoveList = rankingList.DataCenters.OrderBy(x => x.Value) + .Take(diffCount).ToList(); + foreach (var kv in toRemoveList) + { + rankingList.DataCenters.Remove(kv.Key); + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { - OldPubkey = oldPubkey, - NewPubkey = newPubkey + SchemeId = State.SubsidyHash.Value, + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(kv.Key)) }); + } - var oldPubkeyByteString = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(oldPubkey)); - // Notify Vote Contract to replace option if this is not the initial miner case. - if (!State.InitialMiners.Value.Value.Contains(oldPubkeyByteString)) + State.DataCentersRankingList.Value = rankingList; + } + + public override Empty SetProfitsReceiver(SetProfitsReceiverInput input) + { + Assert( + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) == Context.Sender, + "No permission."); + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput + { + SchemeId = State.SubsidyHash.Value, + Beneficiary = input.CandidateAddress + }); + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput + { + SchemeId = State.SubsidyHash.Value, + BeneficiaryShare = new BeneficiaryShare { - State.VoteContract.RemoveOption.Send(new RemoveOptionInput - { - VotingItemId = State.MinerElectionVotingItemId.Value, - Option = oldPubkey - }); - State.VoteContract.AddOption.Send(new AddOptionInput - { - VotingItemId = State.MinerElectionVotingItemId.Value, - Option = newPubkey - }); + Beneficiary = input.ReceiverAddress, + Shares = 1 } + }); + return new Empty(); + } - State.CandidateSponsorMap[newPubkey] = State.CandidateSponsorMap[oldPubkey]; - State.CandidateSponsorMap.Remove(oldPubkey); + #region TakeSnapshot - var managedPubkeys = State.ManagedCandidatePubkeysMap[Context.Sender]; - managedPubkeys.Value.Remove(oldPubkeyByteString); - managedPubkeys.Value.Add(ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(newPubkey))); - State.ManagedCandidatePubkeysMap[Context.Sender] = managedPubkeys; + public override Empty TakeSnapshot(TakeElectionSnapshotInput input) + { + if (State.AEDPoSContract.Value == null) + State.AEDPoSContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - Context.LogDebug(() => $"Pubkey replacement happened: {oldPubkey} -> {newPubkey}"); - } + Assert(State.AEDPoSContract.Value == Context.Sender, "No permission."); - public override StringValue GetNewestPubkey(StringValue input) + SavePreviousTermInformation(input); + + if (State.ProfitContract.Value == null) { - return new StringValue {Value = GetNewestPubkey(input.Value)}; + var profitContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); + // Return if profit contract didn't deployed. (Often in test cases.) + if (profitContractAddress == null) return new Empty(); + State.ProfitContract.Value = profitContractAddress; } - public override Empty RemoveEvilNode(StringValue input) + // Update snapshot of corresponding voting record by the way. + State.VoteContract.TakeSnapshot.Send(new TakeSnapshotInput { - Assert(Context.Sender == GetEmergencyResponseOrganizationAddress(), "No permission."); - var address = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)); - Assert( - State.Candidates.Value.Value.Select(p => p.ToHex()).Contains(input.Value) || - State.InitialMiners.Value.Value.Select(p => p.ToHex()).Contains(input.Value), - "Cannot remove normal node."); - Assert(!State.BannedPubkeyMap[input.Value], $"{input.Value} already banned."); - UpdateCandidateInformation(new UpdateCandidateInformationInput - { - Pubkey = input.Value, - IsEvilNode = true - }); - return new Empty(); - } + SnapshotNumber = input.TermNumber, + VotingItemId = State.MinerElectionVotingItemId.Value + }); + + State.CurrentTermNumber.Value = input.TermNumber.Add(1); + + var previousTermMinerList = + State.AEDPoSContract.GetPreviousTermMinerPubkeyList.Call(new Empty()).Pubkeys.ToList(); + + foreach (var pubkey in previousTermMinerList) + UpdateCandidateInformation(pubkey, input.TermNumber, previousTermMinerList); + + if (State.DividendPoolContract.Value == null) + State.DividendPoolContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - private string GetNewestPubkey(string pubkey) + var symbolList = State.DividendPoolContract.GetSymbolList.Call(new Empty()); + var amountsMap = symbolList.Value.ToDictionary(s => s, s => 0L); + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - var initialPubkey = State.InitialPubkeyMap[pubkey] ?? pubkey; - return State.InitialToNewestPubkeyMap[initialPubkey] ?? initialPubkey; - } + SchemeId = State.SubsidyHash.Value, + Period = input.TermNumber, + AmountsMap = { amountsMap } + }); - private void SyncSubsidyInfoAfterReduceMiner() + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - var rankingList = State.DataCentersRankingList.Value; - if (rankingList == null) - return; - var validDataCenterCount = GetValidationDataCenterCount(); - if (rankingList.DataCenters.Count <= validDataCenterCount) return; - Context.LogDebug(() => "sync DataCenter after reduce bp"); - var diffCount = rankingList.DataCenters.Count.Sub(validDataCenterCount); - var toRemoveList = rankingList.DataCenters.OrderBy(x => x.Value) - .Take(diffCount).ToList(); - foreach (var kv in toRemoveList) - { - rankingList.DataCenters.Remove(kv.Key); - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(kv.Key)) - }); - } + SchemeId = State.WelfareHash.Value, + Period = input.TermNumber, + AmountsMap = { amountsMap } + }); - State.DataCentersRankingList.Value = rankingList; - } + return new Empty(); + } - public override Empty SetProfitsReceiver(SetProfitsReceiverInput input) + private void SavePreviousTermInformation(TakeElectionSnapshotInput input) + { + var snapshot = new TermSnapshot { - Assert( - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) == Context.Sender, - "No permission."); - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - Beneficiary = input.CandidateAddress - }); - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = State.SubsidyHash.Value, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = input.ReceiverAddress, - Shares = 1 - } - }); - return new Empty(); + MinedBlocks = input.MinedBlocks, + EndRoundNumber = input.RoundNumber + }; + + if (State.Candidates.Value == null) return; + + foreach (var pubkey in State.Candidates.Value.Value) + { + var votes = State.CandidateVotes[pubkey.ToHex()]; + var validObtainedVotesAmount = 0L; + if (votes != null) validObtainedVotesAmount = votes.ObtainedActiveVotedVotesAmount; + + snapshot.ElectionResult.Add(pubkey.ToHex(), validObtainedVotesAmount); } + + State.Snapshots[input.TermNumber] = snapshot; + } + + private void UpdateCandidateInformation(string pubkey, long lastTermNumber, + List previousMiners) + { + var candidateInformation = State.CandidateInformationMap[pubkey]; + if (candidateInformation == null) return; + candidateInformation.Terms.Add(lastTermNumber); + var victories = GetVictories(previousMiners); + candidateInformation.ContinualAppointmentCount = victories.Contains(ByteStringHelper.FromHexString(pubkey)) + ? candidateInformation.ContinualAppointmentCount.Add(1) + : 0; + State.CandidateInformationMap[pubkey] = candidateInformation; } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/TimestampHelper.cs b/contract/AElf.Contracts.Election/TimestampHelper.cs index 0317e0df4d..858443e6a7 100644 --- a/contract/AElf.Contracts.Election/TimestampHelper.cs +++ b/contract/AElf.Contracts.Election/TimestampHelper.cs @@ -1,17 +1,16 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public static class TimestampHelper { - public static class TimestampHelper - { - /// - /// 0001-01-01T00:00:00Z - /// - public static Timestamp MinValue => new Timestamp {Nanos = 0, Seconds = -62135596800L}; - - /// - /// 9999-12-31T23:59:59.999999999Z - /// - public static Timestamp MaxValue => new Timestamp {Nanos = 999999999, Seconds = 253402300799L}; - } + /// + /// 0001-01-01T00:00:00Z + /// + public static Timestamp MinValue => new() { Nanos = 0, Seconds = -62135596800L }; + + /// + /// 9999-12-31T23:59:59.999999999Z + /// + public static Timestamp MaxValue => new() { Nanos = 999999999, Seconds = 253402300799L }; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ViewMethods.cs b/contract/AElf.Contracts.Election/ViewMethods.cs index bbdc2c4974..e3f318e211 100644 --- a/contract/AElf.Contracts.Election/ViewMethods.cs +++ b/contract/AElf.Contracts.Election/ViewMethods.cs @@ -1,444 +1,419 @@ -using AElf.Contracts.Vote; -using AElf.Types; using System; using System.Collections.Generic; using System.Linq; +using AElf.Contracts.Vote; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Sdk.CSharp; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContract { - public partial class ElectionContract + public override Hash GetMinerElectionVotingItemId(Empty input) { - public override Hash GetMinerElectionVotingItemId(Empty input) - { - return State.MinerElectionVotingItemId.Value; - } + return State.MinerElectionVotingItemId.Value; + } + + public override PubkeyList GetCandidates(Empty input) + { + return State.Candidates.Value ?? new PubkeyList(); + } - public override PubkeyList GetCandidates(Empty input) + public override PubkeyList GetVotedCandidates(Empty input) + { + var votedCandidates = new PubkeyList(); + if (State.Candidates.Value == null) return votedCandidates; + + foreach (var pubkey in State.Candidates.Value.Value) { - return State.Candidates.Value ?? new PubkeyList(); + var candidateVotes = State.CandidateVotes[pubkey.ToHex()]; + if (candidateVotes != null && candidateVotes.ObtainedActiveVotedVotesAmount > 0) + votedCandidates.Value.Add(pubkey); } - public override PubkeyList GetVotedCandidates(Empty input) - { - var votedCandidates = new PubkeyList(); - if (State.Candidates.Value == null) - { - return votedCandidates; - } + return votedCandidates; + } - foreach (var pubkey in State.Candidates.Value.Value) - { - var candidateVotes = State.CandidateVotes[pubkey.ToHex()]; - if (candidateVotes != null && candidateVotes.ObtainedActiveVotedVotesAmount > 0) - { - votedCandidates.Value.Add(pubkey); - } - } - - return votedCandidates; - } + public override PubkeyList GetVictories(Empty input) + { + if (State.AEDPoSContract.Value == null) + State.AEDPoSContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - public override PubkeyList GetVictories(Empty input) - { - if (State.AEDPoSContract.Value == null) - { - State.AEDPoSContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + var currentMiners = State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys + .Select(k => k.ToHex()).ToList(); + return new PubkeyList { Value = { GetVictories(currentMiners) } }; + } - var currentMiners = State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys - .Select(k => k.ToHex()).ToList(); - return new PubkeyList {Value = {GetVictories(currentMiners)}}; - } + private List GetVictories(List currentMiners) + { + var validCandidates = GetValidCandidates(); - private List GetVictories(List currentMiners) - { - var validCandidates = GetValidCandidates(); + List victories; - List victories; + Context.LogDebug(() => $"Valid candidates: {validCandidates.Count} / {State.MinersCount.Value}"); - Context.LogDebug(() => $"Valid candidates: {validCandidates.Count} / {State.MinersCount.Value}"); + var diff = State.MinersCount.Value - validCandidates.Count; + // Valid candidates not enough. + if (diff > 0) + { + victories = + new List(validCandidates.Select(ByteStringHelper.FromHexString)); + var backups = currentMiners.Where(k => !validCandidates.Contains(k)).ToList(); + if (State.InitialMiners.Value != null) + backups.AddRange( + State.InitialMiners.Value.Value.Select(k => k.ToHex()).Where(k => !backups.Contains(k))); - var diff = State.MinersCount.Value - validCandidates.Count; - // Valid candidates not enough. - if (diff > 0) - { - victories = - new List(validCandidates.Select(ByteStringHelper.FromHexString)); - var backups = currentMiners.Where(k => !validCandidates.Contains(k)).ToList(); - if (State.InitialMiners.Value != null) - { - backups.AddRange( - State.InitialMiners.Value.Value.Select(k => k.ToHex()).Where(k => !backups.Contains(k))); - } - - victories.AddRange(backups.OrderBy(p => p) - .Take(Math.Min(diff, currentMiners.Count)) - .Select(ByteStringHelper.FromHexString)); - Context.LogDebug(() => string.Join("\n", victories.Select(v => v.ToHex().Substring(0, 10)).ToList())); - return victories; - } - - victories = validCandidates.Select(k => State.CandidateVotes[k]) - .OrderByDescending(v => v.ObtainedActiveVotedVotesAmount).Select(v => v.Pubkey) - .Take(State.MinersCount.Value).ToList(); + victories.AddRange(backups.OrderBy(p => p) + .Take(Math.Min(diff, currentMiners.Count)) + .Select(ByteStringHelper.FromHexString)); Context.LogDebug(() => string.Join("\n", victories.Select(v => v.ToHex().Substring(0, 10)).ToList())); return victories; } - private List GetValidCandidates() - { - if (State.Candidates.Value == null) - { - return new List(); - } - - return State.Candidates.Value.Value - .Where(c => State.CandidateVotes[c.ToHex()] != null && - State.CandidateVotes[c.ToHex()].ObtainedActiveVotedVotesAmount > 0) - .Select(p => p.ToHex()) - .ToList(); - } + victories = validCandidates.Select(k => State.CandidateVotes[k]) + .OrderByDescending(v => v.ObtainedActiveVotedVotesAmount).Select(v => v.Pubkey) + .Take(State.MinersCount.Value).ToList(); + Context.LogDebug(() => string.Join("\n", victories.Select(v => v.ToHex().Substring(0, 10)).ToList())); + return victories; + } + + private List GetValidCandidates() + { + if (State.Candidates.Value == null) return new List(); - public override Int32Value GetMinersCount(Empty input) + return State.Candidates.Value.Value + .Where(c => State.CandidateVotes[c.ToHex()] != null && + State.CandidateVotes[c.ToHex()].ObtainedActiveVotedVotesAmount > 0) + .Select(p => p.ToHex()) + .ToList(); + } + + public override Int32Value GetMinersCount(Empty input) + { + return new Int32Value { Value = State.MinersCount.Value }; + } + + public override ElectionResult GetElectionResult(GetElectionResultInput input) + { + var votingResult = State.VoteContract.GetVotingResult.Call(new GetVotingResultInput { - return new Int32Value {Value = State.MinersCount.Value}; - } + VotingItemId = State.MinerElectionVotingItemId.Value, + SnapshotNumber = input.TermNumber + }); - public override ElectionResult GetElectionResult(GetElectionResultInput input) + var result = new ElectionResult { - var votingResult = State.VoteContract.GetVotingResult.Call(new GetVotingResultInput - { - VotingItemId = State.MinerElectionVotingItemId.Value, - SnapshotNumber = input.TermNumber, - }); + TermNumber = input.TermNumber, + IsActive = input.TermNumber == State.CurrentTermNumber.Value, + Results = { votingResult.Results } + }; - var result = new ElectionResult - { - TermNumber = input.TermNumber, - IsActive = input.TermNumber == State.CurrentTermNumber.Value, - Results = {votingResult.Results} - }; + return result; + } - return result; - } + public override CandidateInformation GetCandidateInformation(StringValue input) + { + return State.CandidateInformationMap[input.Value] ?? new CandidateInformation { Pubkey = input.Value }; + } - public override CandidateInformation GetCandidateInformation(StringValue input) - { - return State.CandidateInformationMap[input.Value] ?? new CandidateInformation {Pubkey = input.Value}; - } + public override TermSnapshot GetTermSnapshot(GetTermSnapshotInput input) + { + return State.Snapshots[input.TermNumber] ?? new TermSnapshot(); + } - public override TermSnapshot GetTermSnapshot(GetTermSnapshotInput input) + private TermSnapshot GetPreviousTermSnapshotWithNewestPubkey() + { + var termNumber = State.CurrentTermNumber.Value.Sub(1); + var snapshot = State.Snapshots[termNumber]; + if (snapshot == null) return null; + var invalidCandidates = snapshot.ElectionResult.Where(r => r.Value <= 0).Select(r => r.Key).ToList(); + Context.LogDebug(() => $"Invalid candidates count: {invalidCandidates.Count}"); + foreach (var invalidCandidate in invalidCandidates) { - return State.Snapshots[input.TermNumber] ?? new TermSnapshot(); + Context.LogDebug(() => $"Invalid candidate detected: {invalidCandidate}"); + if (snapshot.ElectionResult.ContainsKey(invalidCandidate)) snapshot.ElectionResult.Remove(invalidCandidate); } - private TermSnapshot GetPreviousTermSnapshotWithNewestPubkey() + if (!snapshot.ElectionResult.Any()) return snapshot; + + var bannedCandidates = snapshot.ElectionResult.Keys.Where(IsPubkeyBanned).ToList(); + Context.LogDebug(() => $"Banned candidates count: {bannedCandidates.Count}"); + if (!bannedCandidates.Any()) return snapshot; + Context.LogDebug(() => "Getting snapshot and there's miner replaced during current term."); + foreach (var bannedCandidate in bannedCandidates) { - var termNumber = State.CurrentTermNumber.Value.Sub(1); - var snapshot = State.Snapshots[termNumber]; - if (snapshot == null) return null; - var invalidCandidates = snapshot.ElectionResult.Where(r => r.Value <= 0).Select(r => r.Key).ToList(); - Context.LogDebug(() => $"Invalid candidates count: {invalidCandidates.Count}"); - foreach (var invalidCandidate in invalidCandidates) - { - Context.LogDebug(() => $"Invalid candidate detected: {invalidCandidate}"); - if (snapshot.ElectionResult.ContainsKey(invalidCandidate)) - { - snapshot.ElectionResult.Remove(invalidCandidate); - } - } - - if (!snapshot.ElectionResult.Any()) return snapshot; - - var bannedCandidates = snapshot.ElectionResult.Keys.Where(IsPubkeyBanned).ToList(); - Context.LogDebug(() => $"Banned candidates count: {bannedCandidates.Count}"); - if (!bannedCandidates.Any()) return snapshot; - Context.LogDebug(() => "Getting snapshot and there's miner replaced during current term."); - foreach (var bannedCandidate in bannedCandidates) - { - var newestPubkey = GetNewestPubkey(bannedCandidate); - // If newest pubkey not exists or same as old pubkey (which is banned), skip. - if (newestPubkey == null || newestPubkey == bannedCandidate || - snapshot.ElectionResult.ContainsKey(newestPubkey)) continue; - var electionResult = snapshot.ElectionResult[bannedCandidate]; - snapshot.ElectionResult.Add(newestPubkey, electionResult); - if (snapshot.ElectionResult.ContainsKey(bannedCandidate)) - { - snapshot.ElectionResult.Remove(bannedCandidate); - } - } - - return snapshot; + var newestPubkey = GetNewestPubkey(bannedCandidate); + // If newest pubkey not exists or same as old pubkey (which is banned), skip. + if (newestPubkey == null || newestPubkey == bannedCandidate || + snapshot.ElectionResult.ContainsKey(newestPubkey)) continue; + var electionResult = snapshot.ElectionResult[bannedCandidate]; + snapshot.ElectionResult.Add(newestPubkey, electionResult); + if (snapshot.ElectionResult.ContainsKey(bannedCandidate)) snapshot.ElectionResult.Remove(bannedCandidate); } - public override ElectorVote GetElectorVote(StringValue input) + return snapshot; + } + + public override ElectorVote GetElectorVote(StringValue input) + { + return State.ElectorVotes[input.Value] ?? new ElectorVote { - return State.ElectorVotes[input.Value] ?? new ElectorVote + Pubkey = ByteStringHelper.FromHexString(input.Value) + }; + } + + public override ElectorVote GetElectorVoteWithRecords(StringValue input) + { + var votes = State.ElectorVotes[input.Value]; + if (votes == null) + return new ElectorVote { Pubkey = ByteStringHelper.FromHexString(input.Value) }; - } - - public override ElectorVote GetElectorVoteWithRecords(StringValue input) + var votedRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput { - var votes = State.ElectorVotes[input.Value]; - if (votes == null) - return new ElectorVote - { - Pubkey = ByteStringHelper.FromHexString(input.Value) - }; - var votedRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput - { - Ids = {votes.ActiveVotingRecordIds} - }).Records; - var index = 0; - foreach (var record in votedRecords) - { - var voteId = votes.ActiveVotingRecordIds[index++]; - votes.ActiveVotingRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); - } - - return votes; - } - - public override ElectorVote GetElectorVoteWithAllRecords(StringValue input) + Ids = { votes.ActiveVotingRecordIds } + }).Records; + var index = 0; + foreach (var record in votedRecords) { - var votes = GetElectorVoteWithRecords(input); + var voteId = votes.ActiveVotingRecordIds[index++]; + votes.ActiveVotingRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); + } - if (!votes.WithdrawnVotingRecordIds.Any()) - { - return votes; - } + return votes; + } - var votedWithdrawnRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput - { - Ids = {votes.WithdrawnVotingRecordIds} - }).Records; - var index = 0; - foreach (var record in votedWithdrawnRecords) - { - var voteId = votes.WithdrawnVotingRecordIds[index++]; - votes.WithdrawnVotesRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); - } + public override ElectorVote GetElectorVoteWithAllRecords(StringValue input) + { + var votes = GetElectorVoteWithRecords(input); - return votes; - } + if (!votes.WithdrawnVotingRecordIds.Any()) return votes; - public override Int64Value GetVotersCount(Empty input) + var votedWithdrawnRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput { - return new Int64Value - { - Value = State.VoteContract.GetLatestVotingResult.Call(State.MinerElectionVotingItemId.Value).VotersCount - }; + Ids = { votes.WithdrawnVotingRecordIds } + }).Records; + var index = 0; + foreach (var record in votedWithdrawnRecords) + { + var voteId = votes.WithdrawnVotingRecordIds[index++]; + votes.WithdrawnVotesRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); } - public override Int64Value GetVotesAmount(Empty input) + return votes; + } + + public override Int64Value GetVotersCount(Empty input) + { + return new Int64Value { - return new Int64Value - { - Value = State.VoteContract.GetLatestVotingResult.Call(State.MinerElectionVotingItemId.Value).VotesAmount - }; - } + Value = State.VoteContract.GetLatestVotingResult.Call(State.MinerElectionVotingItemId.Value).VotersCount + }; + } - public override GetPageableCandidateInformationOutput GetPageableCandidateInformation(PageInformation input) + public override Int64Value GetVotesAmount(Empty input) + { + return new Int64Value { - var output = new GetPageableCandidateInformationOutput(); - var candidates = State.Candidates.Value; + Value = State.VoteContract.GetLatestVotingResult.Call(State.MinerElectionVotingItemId.Value).VotesAmount + }; + } - var count = candidates.Value.Count; - if (count <= input.Start) return output; + public override GetPageableCandidateInformationOutput GetPageableCandidateInformation(PageInformation input) + { + var output = new GetPageableCandidateInformationOutput(); + var candidates = State.Candidates.Value; - var length = Math.Min(Math.Min(input.Length, 20), candidates.Value.Count.Sub(input.Start)); - foreach (var candidate in candidates.Value.Skip(input.Start).Take(length)) - { - output.Value.Add(new CandidateDetail - { - CandidateInformation = State.CandidateInformationMap[candidate.ToHex()], - ObtainedVotesAmount = GetCandidateVote(new StringValue {Value = candidate.ToHex()}) - .ObtainedActiveVotedVotesAmount - }); - } - - return output; - } + var count = candidates.Value.Count; + if (count <= input.Start) return output; - public override CandidateVote GetCandidateVote(StringValue input) - { - return State.CandidateVotes[input.Value] ?? new CandidateVote + var length = Math.Min(Math.Min(input.Length, 20), candidates.Value.Count.Sub(input.Start)); + foreach (var candidate in candidates.Value.Skip(input.Start).Take(length)) + output.Value.Add(new CandidateDetail { - Pubkey = ByteStringHelper.FromHexString(input.Value) - }; - } + CandidateInformation = State.CandidateInformationMap[candidate.ToHex()], + ObtainedVotesAmount = GetCandidateVote(new StringValue { Value = candidate.ToHex() }) + .ObtainedActiveVotedVotesAmount + }); - public override CandidateVote GetCandidateVoteWithRecords(StringValue input) - { - var votes = State.CandidateVotes[input.Value]; - if (votes == null) - return new CandidateVote(); + return output; + } - var obtainedRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput - { - Ids = {votes.ObtainedActiveVotingRecordIds} - }).Records; - var index = 0; - foreach (var record in obtainedRecords) - { - var voteId = votes.ObtainedActiveVotingRecordIds[index++]; - votes.ObtainedActiveVotingRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); - } + public override CandidateVote GetCandidateVote(StringValue input) + { + return State.CandidateVotes[input.Value] ?? new CandidateVote + { + Pubkey = ByteStringHelper.FromHexString(input.Value) + }; + } - return votes; - } + public override CandidateVote GetCandidateVoteWithRecords(StringValue input) + { + var votes = State.CandidateVotes[input.Value]; + if (votes == null) + return new CandidateVote(); - public override CandidateVote GetCandidateVoteWithAllRecords(StringValue input) + var obtainedRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput + { + Ids = { votes.ObtainedActiveVotingRecordIds } + }).Records; + var index = 0; + foreach (var record in obtainedRecords) { - var votes = GetCandidateVoteWithRecords(input); + var voteId = votes.ObtainedActiveVotingRecordIds[index++]; + votes.ObtainedActiveVotingRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); + } - //get withdrawn records - var obtainedWithdrawnRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput - { - Ids = {votes.ObtainedWithdrawnVotingRecordIds} - }).Records; - var index = 0; - foreach (var record in obtainedWithdrawnRecords) - { - var voteId = votes.ObtainedWithdrawnVotingRecordIds[index++]; - votes.ObtainedWithdrawnVotesRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); - } + return votes; + } - return votes; - } + public override CandidateVote GetCandidateVoteWithAllRecords(StringValue input) + { + var votes = GetCandidateVoteWithRecords(input); - public override DataCenterRankingList GetDataCenterRankingList(Empty input) + //get withdrawn records + var obtainedWithdrawnRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput { - return State.DataCentersRankingList.Value; - } - - public override VoteWeightInterestList GetVoteWeightSetting(Empty input) + Ids = { votes.ObtainedWithdrawnVotingRecordIds } + }).Records; + var index = 0; + foreach (var record in obtainedWithdrawnRecords) { - return State.VoteWeightInterestList.Value ?? GetDefaultVoteWeightInterest(); + var voteId = votes.ObtainedWithdrawnVotingRecordIds[index++]; + votes.ObtainedWithdrawnVotesRecords.Add(TransferVotingRecordToElectionVotingRecord(record, voteId)); } - public override AuthorityInfo GetVoteWeightInterestController(Empty input) - { - if (State.VoteWeightInterestController.Value == null) - return GetDefaultVoteWeightInterestController(); - return State.VoteWeightInterestController.Value; - } + return votes; + } - public override VoteWeightProportion GetVoteWeightProportion(Empty input) - { - return State.VoteWeightProportion.Value ?? GetDefaultVoteWeightProportion(); - } + public override DataCenterRankingList GetDataCenterRankingList(Empty input) + { + return State.DataCentersRankingList.Value; + } - public override Int64Value GetCalculateVoteWeight(VoteInformation input) - { - return new Int64Value - { - Value = GetVotesWeight(input.Amount, input.LockTime) - }; - } + public override VoteWeightInterestList GetVoteWeightSetting(Empty input) + { + return State.VoteWeightInterestList.Value ?? GetDefaultVoteWeightInterest(); + } - private ElectionVotingRecord TransferVotingRecordToElectionVotingRecord(VotingRecord votingRecord, Hash voteId) - { - var lockSeconds = State.LockTimeMap[voteId]; - return new ElectionVotingRecord - { - Voter = votingRecord.Voter, - Candidate = GetNewestPubkey(votingRecord.Option), - Amount = votingRecord.Amount, - TermNumber = votingRecord.SnapshotNumber, - VoteId = voteId, - LockTime = lockSeconds, - VoteTimestamp = votingRecord.VoteTimestamp, - WithdrawTimestamp = votingRecord.WithdrawTimestamp, - UnlockTimestamp = votingRecord.VoteTimestamp.AddSeconds(lockSeconds), - IsWithdrawn = votingRecord.IsWithdrawn, - Weight = GetVotesWeight(votingRecord.Amount, lockSeconds), - IsChangeTarget = votingRecord.IsChangeTarget - }; - } + public override AuthorityInfo GetVoteWeightInterestController(Empty input) + { + if (State.VoteWeightInterestController.Value == null) + return GetDefaultVoteWeightInterestController(); + return State.VoteWeightInterestController.Value; + } - public override MinerReplacementInformation GetMinerReplacementInformation( - GetMinerReplacementInformationInput input) - { - var evilMinersPubKeys = GetEvilMinersPubkeys(input.CurrentMinerList); - Context.LogDebug(() => $"Got {evilMinersPubKeys.Count} evil miners pubkeys from {input.CurrentMinerList}"); - var alternativeCandidates = new List(); - var latestSnapshot = GetPreviousTermSnapshotWithNewestPubkey(); - // Check out election snapshot. - if (latestSnapshot != null && latestSnapshot.ElectionResult.Any()) - { - Context.LogDebug(() => $"Previous term snapshot:\n{latestSnapshot}"); - var maybeNextCandidates = latestSnapshot.ElectionResult - // Except initial miners. - .Where(cs => - !State.InitialMiners.Value.Value.Contains( - ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(cs.Key)))) - // Except current miners. - .Where(cs => !input.CurrentMinerList.Contains(cs.Key)) - .OrderByDescending(s => s.Value).ToList(); - var take = Math.Min(evilMinersPubKeys.Count, maybeNextCandidates.Count); - alternativeCandidates.AddRange(maybeNextCandidates.Select(c => c.Key).Take(take)); - Context.LogDebug(() => - $"Found alternative miner from candidate list: {alternativeCandidates.Aggregate("\n", (key1, key2) => key1 + "\n" + key2)}"); - } - - // If the count of evil miners is greater than alternative candidates, add some initial miners to alternative candidates. - var diff = evilMinersPubKeys.Count - alternativeCandidates.Count; - if (diff > 0) - { - var takeAmount = Math.Min(diff, State.InitialMiners.Value.Value.Count); - var selectedInitialMiners = State.InitialMiners.Value.Value - .Select(k => k.ToHex()) - .Where(k => !State.BannedPubkeyMap[k]) - .Where(k => !input.CurrentMinerList.Contains(k)).Take(takeAmount); - alternativeCandidates.AddRange(selectedInitialMiners); - } - - return new MinerReplacementInformation - { - EvilMinerPubkeys = {evilMinersPubKeys}, - AlternativeCandidatePubkeys = {alternativeCandidates} - }; - } + public override VoteWeightProportion GetVoteWeightProportion(Empty input) + { + return State.VoteWeightProportion.Value ?? GetDefaultVoteWeightProportion(); + } - private List GetEvilMinersPubkeys(IEnumerable currentMinerList) + public override Int64Value GetCalculateVoteWeight(VoteInformation input) + { + return new Int64Value { - return currentMinerList.Where((p => State.BannedPubkeyMap[p])).ToList(); - } + Value = GetVotesWeight(input.Amount, input.LockTime) + }; + } - private int GetValidationDataCenterCount() - { - return GetMinersCount(new Empty()).Value.Mul(5); - } + private ElectionVotingRecord TransferVotingRecordToElectionVotingRecord(VotingRecord votingRecord, Hash voteId) + { + var lockSeconds = State.LockTimeMap[voteId]; + return new ElectionVotingRecord + { + Voter = votingRecord.Voter, + Candidate = GetNewestPubkey(votingRecord.Option), + Amount = votingRecord.Amount, + TermNumber = votingRecord.SnapshotNumber, + VoteId = voteId, + LockTime = lockSeconds, + VoteTimestamp = votingRecord.VoteTimestamp, + WithdrawTimestamp = votingRecord.WithdrawTimestamp, + UnlockTimestamp = votingRecord.VoteTimestamp.AddSeconds(lockSeconds), + IsWithdrawn = votingRecord.IsWithdrawn, + Weight = GetVotesWeight(votingRecord.Amount, lockSeconds), + IsChangeTarget = votingRecord.IsChangeTarget + }; + } - public override Address GetCandidateAdmin(StringValue input) - { - return State.CandidateAdmins[State.InitialPubkeyMap[input.Value] ?? input.Value]; - } + public override MinerReplacementInformation GetMinerReplacementInformation( + GetMinerReplacementInformationInput input) + { + var evilMinersPubKeys = GetEvilMinersPubkeys(input.CurrentMinerList); + Context.LogDebug(() => $"Got {evilMinersPubKeys.Count} evil miners pubkeys from {input.CurrentMinerList}"); + var alternativeCandidates = new List(); + var latestSnapshot = GetPreviousTermSnapshotWithNewestPubkey(); + // Check out election snapshot. + if (latestSnapshot != null && latestSnapshot.ElectionResult.Any()) + { + Context.LogDebug(() => $"Previous term snapshot:\n{latestSnapshot}"); + var maybeNextCandidates = latestSnapshot.ElectionResult + // Except initial miners. + .Where(cs => + !State.InitialMiners.Value.Value.Contains( + ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(cs.Key)))) + // Except current miners. + .Where(cs => !input.CurrentMinerList.Contains(cs.Key)) + .OrderByDescending(s => s.Value).ToList(); + var take = Math.Min(evilMinersPubKeys.Count, maybeNextCandidates.Count); + alternativeCandidates.AddRange(maybeNextCandidates.Select(c => c.Key).Take(take)); + Context.LogDebug(() => + $"Found alternative miner from candidate list: {alternativeCandidates.Aggregate("\n", (key1, key2) => key1 + "\n" + key2)}"); + } + + // If the count of evil miners is greater than alternative candidates, add some initial miners to alternative candidates. + var diff = evilMinersPubKeys.Count - alternativeCandidates.Count; + if (diff > 0) + { + var takeAmount = Math.Min(diff, State.InitialMiners.Value.Value.Count); + var selectedInitialMiners = State.InitialMiners.Value.Value + .Select(k => k.ToHex()) + .Where(k => !State.BannedPubkeyMap[k]) + .Where(k => !input.CurrentMinerList.Contains(k)).Take(takeAmount); + alternativeCandidates.AddRange(selectedInitialMiners); + } + + return new MinerReplacementInformation + { + EvilMinerPubkeys = { evilMinersPubKeys }, + AlternativeCandidatePubkeys = { alternativeCandidates } + }; + } - public override StringValue GetReplacedPubkey(StringValue input) - { - return new StringValue {Value = State.CandidateReplacementMap[input.Value]}; - } + private List GetEvilMinersPubkeys(IEnumerable currentMinerList) + { + return currentMinerList.Where(p => State.BannedPubkeyMap[p]).ToList(); + } - public override Address GetSponsor(StringValue input) - { - return State.CandidateSponsorMap[input.Value] ?? - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)); - } + private int GetValidationDataCenterCount() + { + return GetMinersCount(new Empty()).Value.Mul(5); + } - public override PubkeyList GetManagedPubkeys(Address input) - { - return State.ManagedCandidatePubkeysMap[input]; - } - + public override Address GetCandidateAdmin(StringValue input) + { + return State.CandidateAdmins[State.InitialPubkeyMap[input.Value] ?? input.Value]; + } + + public override StringValue GetReplacedPubkey(StringValue input) + { + return new StringValue { Value = State.CandidateReplacementMap[input.Value] }; + } + + public override Address GetSponsor(StringValue input) + { + return State.CandidateSponsorMap[input.Value] ?? + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)); + } + + public override PubkeyList GetManagedPubkeys(Address input) + { + return State.ManagedCandidatePubkeysMap[input]; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/AElf.Contracts.Genesis.csproj b/contract/AElf.Contracts.Genesis/AElf.Contracts.Genesis.csproj index d3a7f4b841..60c1b9a740 100644 --- a/contract/AElf.Contracts.Genesis/AElf.Contracts.Genesis.csproj +++ b/contract/AElf.Contracts.Genesis/AElf.Contracts.Genesis.csproj @@ -1,19 +1,20 @@ - + net6.0 AElf.Contracts.Genesis true - Genesis is a contract that implements base functionality of the chain such as contract proposal - and updating. + Genesis is a contract that implements base functionality of the chain such as contract proposal + and updating. + - true + true - true + true - + Protobuf\Proto\authority_info.proto @@ -35,7 +36,7 @@ true - + Protobuf\Proto\reference\acs3.proto diff --git a/contract/AElf.Contracts.Genesis/BasicContractZero.cs b/contract/AElf.Contracts.Genesis/BasicContractZero.cs index df42918b14..29b63dc770 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZero.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZero.cs @@ -1,391 +1,379 @@ +using AElf.CSharp.Core.Extension; using AElf.Sdk.CSharp; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using AElf.Standards.ACS0; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.CSharp.Core.Extension; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZero : BasicContractZeroImplContainer.BasicContractZeroImplBase { - public partial class BasicContractZero : BasicContractZeroImplContainer.BasicContractZeroImplBase + #region Views + + public override Int64Value CurrentContractSerialNumber(Empty input) { - #region Views + return new Int64Value { Value = State.ContractSerialNumber.Value }; + } - public override Int64Value CurrentContractSerialNumber(Empty input) - { - return new Int64Value() {Value = State.ContractSerialNumber.Value}; - } + public override ContractInfo GetContractInfo(Address input) + { + var info = State.ContractInfos[input]; + if (info == null) return new ContractInfo(); - public override ContractInfo GetContractInfo(Address input) - { - var info = State.ContractInfos[input]; - if (info == null) - { - return new ContractInfo(); - } + return info; + } - return info; - } + public override Address GetContractAuthor(Address input) + { + var info = State.ContractInfos[input]; + return info?.Author; + } - public override Address GetContractAuthor(Address input) - { - var info = State.ContractInfos[input]; - return info?.Author; - } + public override Hash GetContractHash(Address input) + { + var info = State.ContractInfos[input]; + return info?.CodeHash; + } - public override Hash GetContractHash(Address input) - { - var info = State.ContractInfos[input]; - return info?.CodeHash; - } + public override Address GetContractAddressByName(Hash input) + { + var address = State.NameAddressMapping[input]; + return address; + } - public override Address GetContractAddressByName(Hash input) - { - var address = State.NameAddressMapping[input]; - return address; - } + public override SmartContractRegistration GetSmartContractRegistrationByAddress(Address input) + { + var info = State.ContractInfos[input]; + if (info == null) return null; - public override SmartContractRegistration GetSmartContractRegistrationByAddress(Address input) - { - var info = State.ContractInfos[input]; - if (info == null) - { - return null; - } + return State.SmartContractRegistrations[info.CodeHash]; + } - return State.SmartContractRegistrations[info.CodeHash]; - } - - public override SmartContractRegistration GetSmartContractRegistrationByCodeHash(Hash input) - { - return State.SmartContractRegistrations[input]; - } + public override SmartContractRegistration GetSmartContractRegistrationByCodeHash(Hash input) + { + return State.SmartContractRegistrations[input]; + } - public override Empty ValidateSystemContractAddress(ValidateSystemContractAddressInput input) - { - var actualAddress = GetContractAddressByName(input.SystemContractHashName); - Assert(actualAddress == input.Address, "Address not expected."); - return new Empty(); - } + public override Empty ValidateSystemContractAddress(ValidateSystemContractAddressInput input) + { + var actualAddress = GetContractAddressByName(input.SystemContractHashName); + Assert(actualAddress == input.Address, "Address not expected."); + return new Empty(); + } - public override AuthorityInfo GetContractDeploymentController(Empty input) - { - return State.ContractDeploymentController.Value; - } + public override AuthorityInfo GetContractDeploymentController(Empty input) + { + return State.ContractDeploymentController.Value; + } - public override AuthorityInfo GetCodeCheckController(Empty input) - { - return State.CodeCheckController.Value; - } + public override AuthorityInfo GetCodeCheckController(Empty input) + { + return State.CodeCheckController.Value; + } - public override ContractCodeHashList GetContractCodeHashListByDeployingBlockHeight(Int64Value input) - { - return State.ContractCodeHashListMap[input.Value]; - } + public override ContractCodeHashList GetContractCodeHashListByDeployingBlockHeight(Int64Value input) + { + return State.ContractCodeHashListMap[input.Value]; + } - #endregion Views + #endregion Views - #region Actions + #region Actions - public override Address DeploySystemSmartContract(SystemContractDeploymentInput input) - { - Assert(!State.Initialized.Value || !State.ContractDeploymentAuthorityRequired.Value, - "System contract deployment failed."); - RequireSenderAuthority(); - var name = input.Name; - var category = input.Category; - var code = input.Code.ToByteArray(); - var transactionMethodCallList = input.TransactionMethodCallList; - - // Context.Sender should be identical to Genesis contract address before initialization in production - var address = DeploySmartContract(name, category, code, true, Context.Sender); - - if (transactionMethodCallList != null) - { - foreach (var methodCall in transactionMethodCallList.Value) - { - Context.SendInline(address, methodCall.MethodName, methodCall.Params); - } - } + public override Address DeploySystemSmartContract(SystemContractDeploymentInput input) + { + Assert(!State.Initialized.Value || !State.ContractDeploymentAuthorityRequired.Value, + "System contract deployment failed."); + RequireSenderAuthority(); + var name = input.Name; + var category = input.Category; + var code = input.Code.ToByteArray(); + var transactionMethodCallList = input.TransactionMethodCallList; + + // Context.Sender should be identical to Genesis contract address before initialization in production + var address = DeploySmartContract(name, category, code, true, Context.Sender); + + if (transactionMethodCallList != null) + foreach (var methodCall in transactionMethodCallList.Value) + Context.SendInline(address, methodCall.MethodName, methodCall.Params); + + return address; + } - return address; - } + public override Hash ProposeNewContract(ContractDeploymentInput input) + { + // AssertDeploymentProposerAuthority(Context.Sender); + var proposedContractInputHash = CalculateHashFromInput(input); + RegisterContractProposingData(proposedContractInputHash); - public override Hash ProposeNewContract(ContractDeploymentInput input) + // Create proposal for deployment + var proposalCreationInput = new CreateProposalBySystemContractInput { - // AssertDeploymentProposerAuthority(Context.Sender); - var proposedContractInputHash = CalculateHashFromInput(input); - RegisterContractProposingData(proposedContractInputHash); - - // Create proposal for deployment - var proposalCreationInput = new CreateProposalBySystemContractInput + ProposalInput = new CreateProposalInput { - ProposalInput = new CreateProposalInput + ToAddress = Context.Self, + ContractMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.ProposeContractCodeCheck), + Params = new ContractCodeCheckInput { - ToAddress = Context.Self, - ContractMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.ProposeContractCodeCheck), - Params = new ContractCodeCheckInput - { - ContractInput = input.ToByteString(), - CodeCheckReleaseMethod = nameof(DeploySmartContract), - ProposedContractInputHash = proposedContractInputHash, - Category = input.Category, - IsSystemContract = false - }.ToByteString(), - OrganizationAddress = State.ContractDeploymentController.Value.OwnerAddress, - ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod) - }, - OriginProposer = Context.Sender - }; - Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState - .CreateProposalBySystemContract), proposalCreationInput.ToByteString()); - - Context.Fire(new ContractProposed - { - ProposedContractInputHash = proposedContractInputHash - }); - - return proposedContractInputHash; - } - - public override Hash ProposeUpdateContract(ContractUpdateInput input) + ContractInput = input.ToByteString(), + CodeCheckReleaseMethod = nameof(DeploySmartContract), + ProposedContractInputHash = proposedContractInputHash, + Category = input.Category, + IsSystemContract = false + }.ToByteString(), + OrganizationAddress = State.ContractDeploymentController.Value.OwnerAddress, + ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod) + }, + OriginProposer = Context.Sender + }; + Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState + .CreateProposalBySystemContract), proposalCreationInput.ToByteString()); + + Context.Fire(new ContractProposed { - var proposedContractInputHash = CalculateHashFromInput(input); - RegisterContractProposingData(proposedContractInputHash); + ProposedContractInputHash = proposedContractInputHash + }); - var contractAddress = input.Address; - var info = State.ContractInfos[contractAddress]; - Assert(info != null, "Contract not found."); - AssertAuthorityByContractInfo(info, Context.Sender); + return proposedContractInputHash; + } - // Create proposal for contract update - var proposalCreationInput = new CreateProposalBySystemContractInput - { - ProposalInput = new CreateProposalInput - { - ToAddress = Context.Self, - ContractMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.ProposeContractCodeCheck), - Params = new ContractCodeCheckInput - { - ContractInput = input.ToByteString(), - CodeCheckReleaseMethod = nameof(UpdateSmartContract), - ProposedContractInputHash = proposedContractInputHash, - Category = info.Category, - IsSystemContract = info.IsSystemContract - }.ToByteString(), - OrganizationAddress = State.ContractDeploymentController.Value.OwnerAddress, - ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod), - }, - OriginProposer = Context.Sender - }; - Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState - .CreateProposalBySystemContract), proposalCreationInput); - - Context.Fire(new ContractProposed - { - ProposedContractInputHash = proposedContractInputHash - }); + public override Hash ProposeUpdateContract(ContractUpdateInput input) + { + var proposedContractInputHash = CalculateHashFromInput(input); + RegisterContractProposingData(proposedContractInputHash); - return proposedContractInputHash; - } + var contractAddress = input.Address; + var info = State.ContractInfos[contractAddress]; + Assert(info != null, "Contract not found."); + AssertAuthorityByContractInfo(info, Context.Sender); - public override Hash ProposeContractCodeCheck(ContractCodeCheckInput input) + // Create proposal for contract update + var proposalCreationInput = new CreateProposalBySystemContractInput { - RequireSenderAuthority(State.ContractDeploymentController.Value.OwnerAddress); - AssertCodeCheckProposingInput(input); - var proposedContractInputHash = input.ProposedContractInputHash; - var proposedInfo = State.ContractProposingInputMap[proposedContractInputHash]; - Assert(proposedInfo != null && proposedInfo.Status == ContractProposingInputStatus.Approved, - "Invalid contract proposing status."); - proposedInfo.Status = ContractProposingInputStatus.CodeCheckProposed; - State.ContractProposingInputMap[proposedContractInputHash] = proposedInfo; - - var codeCheckController = State.CodeCheckController.Value; - var proposalCreationInput = new CreateProposalBySystemContractInput + ProposalInput = new CreateProposalInput { - ProposalInput = new CreateProposalInput + ToAddress = Context.Self, + ContractMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.ProposeContractCodeCheck), + Params = new ContractCodeCheckInput { - ToAddress = Context.Self, - ContractMethodName = input.CodeCheckReleaseMethod, - Params = input.ContractInput, - OrganizationAddress = codeCheckController.OwnerAddress, - ExpiredTime = Context.CurrentBlockTime.AddSeconds(CodeCheckProposalExpirationTimePeriod) - }, - OriginProposer = proposedInfo.Proposer - }; - - proposedInfo.ExpiredTime = proposalCreationInput.ProposalInput.ExpiredTime; - State.ContractProposingInputMap[proposedContractInputHash] = proposedInfo; - Context.SendInline(codeCheckController.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState - .CreateProposalBySystemContract), proposalCreationInput); - - // Fire event to trigger BPs checking contract code - Context.Fire(new CodeCheckRequired - { - Code = ExtractCodeFromContractCodeCheckInput(input), - ProposedContractInputHash = proposedContractInputHash, - Category = input.Category, - IsSystemContract = input.IsSystemContract - }); + ContractInput = input.ToByteString(), + CodeCheckReleaseMethod = nameof(UpdateSmartContract), + ProposedContractInputHash = proposedContractInputHash, + Category = info.Category, + IsSystemContract = info.IsSystemContract + }.ToByteString(), + OrganizationAddress = State.ContractDeploymentController.Value.OwnerAddress, + ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod) + }, + OriginProposer = Context.Sender + }; + Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState + .CreateProposalBySystemContract), proposalCreationInput); + + Context.Fire(new ContractProposed + { + ProposedContractInputHash = proposedContractInputHash + }); - return proposedContractInputHash; - } + return proposedContractInputHash; + } - public override Empty ReleaseApprovedContract(ReleaseContractInput input) - { - var contractProposingInput = State.ContractProposingInputMap[input.ProposedContractInputHash]; - Assert( - contractProposingInput != null && - contractProposingInput.Status == ContractProposingInputStatus.Proposed && - contractProposingInput.Proposer == Context.Sender, "Invalid contract proposing status."); - contractProposingInput.Status = ContractProposingInputStatus.Approved; - State.ContractProposingInputMap[input.ProposedContractInputHash] = contractProposingInput; - Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), - input.ProposalId.ToByteString()); - return new Empty(); - } - - public override Empty ReleaseCodeCheckedContract(ReleaseContractInput input) + public override Hash ProposeContractCodeCheck(ContractCodeCheckInput input) + { + RequireSenderAuthority(State.ContractDeploymentController.Value.OwnerAddress); + AssertCodeCheckProposingInput(input); + var proposedContractInputHash = input.ProposedContractInputHash; + var proposedInfo = State.ContractProposingInputMap[proposedContractInputHash]; + Assert(proposedInfo != null && proposedInfo.Status == ContractProposingInputStatus.Approved, + "Invalid contract proposing status."); + proposedInfo.Status = ContractProposingInputStatus.CodeCheckProposed; + State.ContractProposingInputMap[proposedContractInputHash] = proposedInfo; + + var codeCheckController = State.CodeCheckController.Value; + var proposalCreationInput = new CreateProposalBySystemContractInput { - var contractProposingInput = State.ContractProposingInputMap[input.ProposedContractInputHash]; - - Assert( - contractProposingInput != null && - contractProposingInput.Status == ContractProposingInputStatus.CodeCheckProposed && - contractProposingInput.Proposer == Context.Sender, "Invalid contract proposing status."); - contractProposingInput.Status = ContractProposingInputStatus.CodeChecked; - State.ContractProposingInputMap[input.ProposedContractInputHash] = contractProposingInput; - var codeCheckController = State.CodeCheckController.Value; - Context.SendInline(codeCheckController.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), input.ProposalId); - return new Empty(); - } - - - public override Address DeploySmartContract(ContractDeploymentInput input) + ProposalInput = new CreateProposalInput + { + ToAddress = Context.Self, + ContractMethodName = input.CodeCheckReleaseMethod, + Params = input.ContractInput, + OrganizationAddress = codeCheckController.OwnerAddress, + ExpiredTime = Context.CurrentBlockTime.AddSeconds(CodeCheckProposalExpirationTimePeriod) + }, + OriginProposer = proposedInfo.Proposer + }; + + proposedInfo.ExpiredTime = proposalCreationInput.ProposalInput.ExpiredTime; + State.ContractProposingInputMap[proposedContractInputHash] = proposedInfo; + Context.SendInline(codeCheckController.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState + .CreateProposalBySystemContract), proposalCreationInput); + + // Fire event to trigger BPs checking contract code + Context.Fire(new CodeCheckRequired { - RequireSenderAuthority(State.CodeCheckController.Value?.OwnerAddress); - // AssertDeploymentProposerAuthority(Context.Origin); + Code = ExtractCodeFromContractCodeCheckInput(input), + ProposedContractInputHash = proposedContractInputHash, + Category = input.Category, + IsSystemContract = input.IsSystemContract + }); - var inputHash = CalculateHashFromInput(input); - TryClearContractProposingData(inputHash, out var contractProposingInput); + return proposedContractInputHash; + } - var address = - DeploySmartContract(null, input.Category, input.Code.ToByteArray(), false, - DecideNonSystemContractAuthor(contractProposingInput?.Proposer, Context.Sender)); - return address; - } + public override Empty ReleaseApprovedContract(ReleaseContractInput input) + { + var contractProposingInput = State.ContractProposingInputMap[input.ProposedContractInputHash]; + Assert( + contractProposingInput != null && + contractProposingInput.Status == ContractProposingInputStatus.Proposed && + contractProposingInput.Proposer == Context.Sender, "Invalid contract proposing status."); + contractProposingInput.Status = ContractProposingInputStatus.Approved; + State.ContractProposingInputMap[input.ProposedContractInputHash] = contractProposingInput; + Context.SendInline(State.ContractDeploymentController.Value.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), + input.ProposalId.ToByteString()); + return new Empty(); + } - public override Address UpdateSmartContract(ContractUpdateInput input) - { - var contractAddress = input.Address; - var code = input.Code.ToByteArray(); - var info = State.ContractInfos[contractAddress]; - Assert(info != null, "Contract not found."); - RequireSenderAuthority(State.CodeCheckController.Value?.OwnerAddress); - var inputHash = CalculateHashFromInput(input); - - if (!TryClearContractProposingData(inputHash, out _)) - Assert(Context.Sender == info.Author, "No permission."); - - var oldCodeHash = info.CodeHash; - var newCodeHash = HashHelper.ComputeFrom(code); - Assert(oldCodeHash != newCodeHash, "Code is not changed."); - - Assert(State.SmartContractRegistrations[newCodeHash] == null, "Same code has been deployed before."); - - info.CodeHash = newCodeHash; - info.Version++; - State.ContractInfos[contractAddress] = info; - - var reg = new SmartContractRegistration - { - Category = info.Category, - Code = ByteString.CopyFrom(code), - CodeHash = newCodeHash, - IsSystemContract = info.IsSystemContract, - Version = info.Version - }; + public override Empty ReleaseCodeCheckedContract(ReleaseContractInput input) + { + var contractProposingInput = State.ContractProposingInputMap[input.ProposedContractInputHash]; + + Assert( + contractProposingInput != null && + contractProposingInput.Status == ContractProposingInputStatus.CodeCheckProposed && + contractProposingInput.Proposer == Context.Sender, "Invalid contract proposing status."); + contractProposingInput.Status = ContractProposingInputStatus.CodeChecked; + State.ContractProposingInputMap[input.ProposedContractInputHash] = contractProposingInput; + var codeCheckController = State.CodeCheckController.Value; + Context.SendInline(codeCheckController.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.Release), input.ProposalId); + return new Empty(); + } - State.SmartContractRegistrations[reg.CodeHash] = reg; - Context.UpdateContract(contractAddress, reg, null); + public override Address DeploySmartContract(ContractDeploymentInput input) + { + RequireSenderAuthority(State.CodeCheckController.Value?.OwnerAddress); + // AssertDeploymentProposerAuthority(Context.Origin); - Context.Fire(new CodeUpdated() - { - Address = contractAddress, - OldCodeHash = oldCodeHash, - NewCodeHash = newCodeHash, - Version = info.Version - }); + var inputHash = CalculateHashFromInput(input); + TryClearContractProposingData(inputHash, out var contractProposingInput); - Context.LogDebug(() => "BasicContractZero - update success: " + contractAddress.ToBase58()); - return contractAddress; - } + var address = + DeploySmartContract(null, input.Category, input.Code.ToByteArray(), false, + DecideNonSystemContractAuthor(contractProposingInput?.Proposer, Context.Sender)); + return address; + } - public override Empty Initialize(InitializeInput input) - { - Assert(!State.Initialized.Value, "Contract zero already initialized."); - Assert(Context.Sender == Context.Self, "No permission."); - State.ContractDeploymentAuthorityRequired.Value = input.ContractDeploymentAuthorityRequired; - State.Initialized.Value = true; - return new Empty(); - } - - public override Empty SetInitialControllerAddress(Address input) - { - Assert(State.ContractDeploymentController.Value == null && State.CodeCheckController.Value == null, - "Genesis owner already initialized"); - var parliamentContractAddress = - GetContractAddressByName(SmartContractConstants.ParliamentContractSystemHashName); - Assert(Context.Sender == parliamentContractAddress, "Unauthorized to initialize genesis contract."); - Assert(input != null, "Genesis Owner should not be null."); - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = input, - ContractAddress = parliamentContractAddress - }; - State.ContractDeploymentController.Value = defaultAuthority; - State.CodeCheckController.Value = defaultAuthority; - return new Empty(); - } - - public override Empty ChangeContractDeploymentController(AuthorityInfo input) + public override Address UpdateSmartContract(ContractUpdateInput input) + { + var contractAddress = input.Address; + var code = input.Code.ToByteArray(); + var info = State.ContractInfos[contractAddress]; + Assert(info != null, "Contract not found."); + RequireSenderAuthority(State.CodeCheckController.Value?.OwnerAddress); + var inputHash = CalculateHashFromInput(input); + + if (!TryClearContractProposingData(inputHash, out _)) + Assert(Context.Sender == info.Author, "No permission."); + + var oldCodeHash = info.CodeHash; + var newCodeHash = HashHelper.ComputeFrom(code); + Assert(oldCodeHash != newCodeHash, "Code is not changed."); + + Assert(State.SmartContractRegistrations[newCodeHash] == null, "Same code has been deployed before."); + + info.CodeHash = newCodeHash; + info.Version++; + State.ContractInfos[contractAddress] = info; + + var reg = new SmartContractRegistration { - AssertSenderAddressWith(State.ContractDeploymentController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); - State.ContractDeploymentController.Value = input; - return new Empty(); - } - - public override Empty ChangeCodeCheckController(AuthorityInfo input) + Category = info.Category, + Code = ByteString.CopyFrom(code), + CodeHash = newCodeHash, + IsSystemContract = info.IsSystemContract, + Version = info.Version + }; + + State.SmartContractRegistrations[reg.CodeHash] = reg; + + Context.UpdateContract(contractAddress, reg, null); + + Context.Fire(new CodeUpdated { - AssertSenderAddressWith(State.CodeCheckController.Value.OwnerAddress); - Assert(CheckOrganizationExist(input), - "Invalid authority input."); - State.CodeCheckController.Value = input; - return new Empty(); - } - - public override Empty SetContractProposerRequiredState(BoolValue input) + Address = contractAddress, + OldCodeHash = oldCodeHash, + NewCodeHash = newCodeHash, + Version = info.Version + }); + + Context.LogDebug(() => "BasicContractZero - update success: " + contractAddress.ToBase58()); + return contractAddress; + } + + public override Empty Initialize(InitializeInput input) + { + Assert(!State.Initialized.Value, "Contract zero already initialized."); + Assert(Context.Sender == Context.Self, "No permission."); + State.ContractDeploymentAuthorityRequired.Value = input.ContractDeploymentAuthorityRequired; + State.Initialized.Value = true; + return new Empty(); + } + + public override Empty SetInitialControllerAddress(Address input) + { + Assert(State.ContractDeploymentController.Value == null && State.CodeCheckController.Value == null, + "Genesis owner already initialized"); + var parliamentContractAddress = + GetContractAddressByName(SmartContractConstants.ParliamentContractSystemHashName); + Assert(Context.Sender == parliamentContractAddress, "Unauthorized to initialize genesis contract."); + Assert(input != null, "Genesis Owner should not be null."); + var defaultAuthority = new AuthorityInfo { - Assert(!State.Initialized.Value, "Genesis contract already initialized."); - var address = GetContractAddressByName(SmartContractConstants.CrossChainContractSystemHashName); - Assert(Context.Sender == address, "Unauthorized to set genesis contract state."); + OwnerAddress = input, + ContractAddress = parliamentContractAddress + }; + State.ContractDeploymentController.Value = defaultAuthority; + State.CodeCheckController.Value = defaultAuthority; + return new Empty(); + } + + public override Empty ChangeContractDeploymentController(AuthorityInfo input) + { + AssertSenderAddressWith(State.ContractDeploymentController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + State.ContractDeploymentController.Value = input; + return new Empty(); + } + + public override Empty ChangeCodeCheckController(AuthorityInfo input) + { + AssertSenderAddressWith(State.CodeCheckController.Value.OwnerAddress); + Assert(CheckOrganizationExist(input), + "Invalid authority input."); + State.CodeCheckController.Value = input; + return new Empty(); + } - CreateParliamentOrganizationForInitialControllerAddress(input.Value); - return new Empty(); - } + public override Empty SetContractProposerRequiredState(BoolValue input) + { + Assert(!State.Initialized.Value, "Genesis contract already initialized."); + var address = GetContractAddressByName(SmartContractConstants.CrossChainContractSystemHashName); + Assert(Context.Sender == address, "Unauthorized to set genesis contract state."); - #endregion Actions + CreateParliamentOrganizationForInitialControllerAddress(input.Value); + return new Empty(); } + + #endregion Actions } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/BasicContractZeroContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Genesis/BasicContractZeroContract_ACS1_TransactionFeeProvider.cs index 8bec9c7076..8aa1a70b1c 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZeroContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZeroContract_ACS1_TransactionFeeProvider.cs @@ -1,84 +1,75 @@ -using System.Collections.Generic; -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp; -using AElf.Types; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZero { - public partial class BasicContractZero + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + RequiredMethodFeeControllerSet(); - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - #endregion + return new Empty(); + } - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + + State.MethodFeeController.Value = input; + return new Empty(); + } - RequiredMethodFeeControllerSet(); + #region Views - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - return new Empty(); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #endregion - State.MethodFeeController.Value = input; - return new Empty(); - } + #region private method - #region private method + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + RequireParliamentContractAddressSet(); - private void RequiredMethodFeeControllerSet() + var defaultAuthority = new AuthorityInfo { - if (State.MethodFeeController.Value != null) return; - RequireParliamentContractAddressSet(); + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; + State.MethodFeeController.Value = defaultAuthority; + } - State.MethodFeeController.Value = defaultAuthority; - } + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/BasicContractZeroReferenceState.cs b/contract/AElf.Contracts.Genesis/BasicContractZeroReferenceState.cs index 754b627e04..f9d019dc66 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZeroReferenceState.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZeroReferenceState.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZeroState { - public partial class BasicContractZeroState - { - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/BasicContractZeroState.cs b/contract/AElf.Contracts.Genesis/BasicContractZeroState.cs index 0a7af0ab37..8852b11475 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZeroState.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZeroState.cs @@ -1,37 +1,35 @@ -using AElf.Standards.ACS0; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS0; using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZeroState : ContractState { - public partial class BasicContractZeroState : ContractState - { - public Int64State ContractSerialNumber { get; set; } - public MappedState ContractInfos { get; set; } + public Int64State ContractSerialNumber { get; set; } + public MappedState ContractInfos { get; set; } - public MappedState SmartContractRegistrations { get; set; } + public MappedState SmartContractRegistrations { get; set; } - public MappedState NameAddressMapping { get; set; } + public MappedState NameAddressMapping { get; set; } - public MappedState ContractProposingInputMap { get; set; } + public MappedState ContractProposingInputMap { get; set; } - /// - /// Genesis owner controls contract deployment if is true. - /// - public SingletonState ContractDeploymentController { get; set; } + /// + /// Genesis owner controls contract deployment if is true. + /// + public SingletonState ContractDeploymentController { get; set; } - public SingletonState CodeCheckController { get; set; } + public SingletonState CodeCheckController { get; set; } - public SingletonState ContractDeploymentAuthorityRequired { get; set; } + public SingletonState ContractDeploymentAuthorityRequired { get; set; } - public SingletonState Initialized { get; set; } + public SingletonState Initialized { get; set; } - public MappedState TransactionFees { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } + public SingletonState MethodFeeController { get; set; } - public MappedState ContractCodeHashListMap { get; set; } - } + public MappedState ContractCodeHashListMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/BasicContractZero_Constants.cs b/contract/AElf.Contracts.Genesis/BasicContractZero_Constants.cs index 6bd05c5091..3f834520d0 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZero_Constants.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZero_Constants.cs @@ -1,12 +1,11 @@ -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZero { - public partial class BasicContractZero - { - public const int ContractProposalExpirationTimePeriod = 86400; // 60 * 60 * 24 - public const int CodeCheckProposalExpirationTimePeriod = 600; // 60 * 10 - private const int MinimalApprovalThreshold = 6667; - private const int MaximalAbstentionThreshold = 1000; - private const int MaximalRejectionThreshold = 1000; - private const int MinimalVoteThresholdThreshold = 8000; - } + public const int ContractProposalExpirationTimePeriod = 86400; // 60 * 60 * 24 + public const int CodeCheckProposalExpirationTimePeriod = 600; // 60 * 10 + private const int MinimalApprovalThreshold = 6667; + private const int MaximalAbstentionThreshold = 1000; + private const int MaximalRejectionThreshold = 1000; + private const int MinimalVoteThresholdThreshold = 8000; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs b/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs index 6d5164dd41..602c269687 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs @@ -1,234 +1,229 @@ using System; -using AElf.Standards.ACS0; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Sdk.CSharp; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public partial class BasicContractZero { - public partial class BasicContractZero + private Address DeploySmartContract(Hash name, int category, byte[] code, bool isSystemContract, + Address author) { - private Address DeploySmartContract(Hash name, int category, byte[] code, bool isSystemContract, - Address author) - { - if (name != null) - Assert(State.NameAddressMapping[name] == null, "contract name has already been registered before"); - - var codeHash = HashHelper.ComputeFrom(code); - - Assert(State.SmartContractRegistrations[codeHash] == null, "contract code has already been deployed before"); - - var serialNumber = State.ContractSerialNumber.Value; - // Increment - State.ContractSerialNumber.Value = serialNumber + 1; - var contractAddress = AddressHelper.BuildContractAddress(Context.ChainId, serialNumber); - - var info = new ContractInfo - { - SerialNumber = serialNumber, - Author = author, - Category = category, - CodeHash = codeHash, - IsSystemContract = isSystemContract, - Version = 1 - }; - State.ContractInfos[contractAddress] = info; - - var reg = new SmartContractRegistration - { - Category = category, - Code = ByteString.CopyFrom(code), - CodeHash = codeHash, - IsSystemContract = info.IsSystemContract, - Version = info.Version - }; + if (name != null) + Assert(State.NameAddressMapping[name] == null, "contract name has already been registered before"); - State.SmartContractRegistrations[reg.CodeHash] = reg; + var codeHash = HashHelper.ComputeFrom(code); - Context.DeployContract(contractAddress, reg, name); + Assert(State.SmartContractRegistrations[codeHash] == null, "contract code has already been deployed before"); - Context.Fire(new ContractDeployed - { - CodeHash = codeHash, - Address = contractAddress, - Author = author, - Version = info.Version, - Name = name - }); + var serialNumber = State.ContractSerialNumber.Value; + // Increment + State.ContractSerialNumber.Value = serialNumber + 1; + var contractAddress = AddressHelper.BuildContractAddress(Context.ChainId, serialNumber); + + var info = new ContractInfo + { + SerialNumber = serialNumber, + Author = author, + Category = category, + CodeHash = codeHash, + IsSystemContract = isSystemContract, + Version = 1 + }; + State.ContractInfos[contractAddress] = info; - Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + codeHash.ToHex()); - Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58()); + var reg = new SmartContractRegistration + { + Category = category, + Code = ByteString.CopyFrom(code), + CodeHash = codeHash, + IsSystemContract = info.IsSystemContract, + Version = info.Version + }; - if (name != null) - State.NameAddressMapping[name] = contractAddress; + State.SmartContractRegistrations[reg.CodeHash] = reg; - var contractCodeHashList = - State.ContractCodeHashListMap[Context.CurrentHeight] ?? new ContractCodeHashList(); - contractCodeHashList.Value.Add(codeHash); - State.ContractCodeHashListMap[Context.CurrentHeight] = contractCodeHashList; + Context.DeployContract(contractAddress, reg, name); - return contractAddress; - } - - private void RequireSenderAuthority(Address address = null) + Context.Fire(new ContractDeployed { - if (!State.Initialized.Value) - { - // only authority of contract zero is valid before initialization - AssertSenderAddressWith(Context.Self); - return; - } + CodeHash = codeHash, + Address = contractAddress, + Author = author, + Version = info.Version, + Name = name + }); - var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; - if (!isGenesisOwnerAuthorityRequired) - return; + Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + codeHash.ToHex()); + Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58()); - if (address != null) - AssertSenderAddressWith(address); - } + if (name != null) + State.NameAddressMapping[name] = contractAddress; - private void RequireParliamentContractAddressSet() - { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - } + var contractCodeHashList = + State.ContractCodeHashListMap[Context.CurrentHeight] ?? new ContractCodeHashList(); + contractCodeHashList.Value.Add(codeHash); + State.ContractCodeHashListMap[Context.CurrentHeight] = contractCodeHashList; - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + return contractAddress; + } - private Hash CalculateHashFromInput(IMessage input) + private void RequireSenderAuthority(Address address = null) + { + if (!State.Initialized.Value) { - return HashHelper.ComputeFrom(input); + // only authority of contract zero is valid before initialization + AssertSenderAddressWith(Context.Self); + return; } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; + if (!isGenesisOwnerAuthorityRequired) + return; - private bool TryClearContractProposingData(Hash inputHash, out ContractProposingInput contractProposingInput) - { - contractProposingInput = State.ContractProposingInputMap[inputHash]; - var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; - if (isGenesisOwnerAuthorityRequired) - Assert( - contractProposingInput != null, "Contract proposing data not found."); - - if (contractProposingInput == null) - return false; - - Assert(contractProposingInput.Status == ContractProposingInputStatus.CodeChecked, - "Invalid contract proposing status."); - State.ContractProposingInputMap.Remove(inputHash); - return true; - } + if (address != null) + AssertSenderAddressWith(address); + } - private void RegisterContractProposingData(Hash proposedContractInputHash) - { - var registered = State.ContractProposingInputMap[proposedContractInputHash]; - Assert(registered == null || Context.CurrentBlockTime >= registered.ExpiredTime, "Already proposed."); - State.ContractProposingInputMap[proposedContractInputHash] = new ContractProposingInput - { - Proposer = Context.Sender, - Status = ContractProposingInputStatus.Proposed, - ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod) - }; - } - - private void CreateParliamentOrganizationForInitialControllerAddress(bool proposerAuthorityRequired) - { - RequireParliamentContractAddressSet(); - var parliamentProposerWhitelist = State.ParliamentContract.GetProposerWhiteList.Call(new Empty()); + private void RequireParliamentContractAddressSet() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + } - var isWhiteListEmpty = parliamentProposerWhitelist.Proposers.Count == 0; - State.ParliamentContract.CreateOrganizationBySystemContract.Send(new CreateOrganizationBySystemContractInput + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private Hash CalculateHashFromInput(IMessage input) + { + return HashHelper.ComputeFrom(input); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } + + private bool TryClearContractProposingData(Hash inputHash, out ContractProposingInput contractProposingInput) + { + contractProposingInput = State.ContractProposingInputMap[inputHash]; + var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; + if (isGenesisOwnerAuthorityRequired) + Assert( + contractProposingInput != null, "Contract proposing data not found."); + + if (contractProposingInput == null) + return false; + + Assert(contractProposingInput.Status == ContractProposingInputStatus.CodeChecked, + "Invalid contract proposing status."); + State.ContractProposingInputMap.Remove(inputHash); + return true; + } + + private void RegisterContractProposingData(Hash proposedContractInputHash) + { + var registered = State.ContractProposingInputMap[proposedContractInputHash]; + Assert(registered == null || Context.CurrentBlockTime >= registered.ExpiredTime, "Already proposed."); + State.ContractProposingInputMap[proposedContractInputHash] = new ContractProposingInput + { + Proposer = Context.Sender, + Status = ContractProposingInputStatus.Proposed, + ExpiredTime = Context.CurrentBlockTime.AddSeconds(ContractProposalExpirationTimePeriod) + }; + } + + private void CreateParliamentOrganizationForInitialControllerAddress(bool proposerAuthorityRequired) + { + RequireParliamentContractAddressSet(); + var parliamentProposerWhitelist = State.ParliamentContract.GetProposerWhiteList.Call(new Empty()); + + var isWhiteListEmpty = parliamentProposerWhitelist.Proposers.Count == 0; + State.ParliamentContract.CreateOrganizationBySystemContract.Send(new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = new CreateOrganizationInput { - OrganizationCreationInput = new CreateOrganizationInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = MinimalApprovalThreshold, - MinimalVoteThreshold = MinimalVoteThresholdThreshold, - MaximalRejectionThreshold = MaximalRejectionThreshold, - MaximalAbstentionThreshold = MaximalAbstentionThreshold - }, - ProposerAuthorityRequired = proposerAuthorityRequired, - ParliamentMemberProposingAllowed = isWhiteListEmpty + MinimalApprovalThreshold = MinimalApprovalThreshold, + MinimalVoteThreshold = MinimalVoteThresholdThreshold, + MaximalRejectionThreshold = MaximalRejectionThreshold, + MaximalAbstentionThreshold = MaximalAbstentionThreshold }, - OrganizationAddressFeedbackMethod = nameof(SetInitialControllerAddress) - }); - } + ProposerAuthorityRequired = proposerAuthorityRequired, + ParliamentMemberProposingAllowed = isWhiteListEmpty + }, + OrganizationAddressFeedbackMethod = nameof(SetInitialControllerAddress) + }); + } - private void AssertAuthorityByContractInfo(ContractInfo contractInfo, Address address) - { - Assert(contractInfo.Author == Context.Self || address == contractInfo.Author, "No permission."); - } + private void AssertAuthorityByContractInfo(ContractInfo contractInfo, Address address) + { + Assert(contractInfo.Author == Context.Self || address == contractInfo.Author, "No permission."); + } - private bool ValidateProposerAuthority(Address contractAddress, Address organizationAddress, Address proposer) - { - return Context.Call(contractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateProposerInWhiteList), - new ValidateProposerInWhiteListInput - { - OrganizationAddress = organizationAddress, - Proposer = proposer - }).Value; - } + private bool ValidateProposerAuthority(Address contractAddress, Address organizationAddress, Address proposer) + { + return Context.Call(contractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateProposerInWhiteList), + new ValidateProposerInWhiteListInput + { + OrganizationAddress = organizationAddress, + Proposer = proposer + }).Value; + } - private Address DecideNonSystemContractAuthor(Address proposer, Address sender) - { - if (!State.ContractDeploymentAuthorityRequired.Value) - return sender; + private Address DecideNonSystemContractAuthor(Address proposer, Address sender) + { + if (!State.ContractDeploymentAuthorityRequired.Value) + return sender; - var contractDeploymentController = State.ContractDeploymentController.Value; - var isProposerInWhiteList = ValidateProposerAuthority(contractDeploymentController.ContractAddress, - contractDeploymentController.OwnerAddress, proposer); - return isProposerInWhiteList ? proposer : Context.Self; - } + var contractDeploymentController = State.ContractDeploymentController.Value; + var isProposerInWhiteList = ValidateProposerAuthority(contractDeploymentController.ContractAddress, + contractDeploymentController.OwnerAddress, proposer); + return isProposerInWhiteList ? proposer : Context.Self; + } - private ByteString ExtractCodeFromContractCodeCheckInput(ContractCodeCheckInput input) - { - return input.CodeCheckReleaseMethod == nameof(DeploySmartContract) - ? ContractDeploymentInput.Parser.ParseFrom(input.ContractInput).Code - : ContractUpdateInput.Parser.ParseFrom(input.ContractInput).Code; - } + private ByteString ExtractCodeFromContractCodeCheckInput(ContractCodeCheckInput input) + { + return input.CodeCheckReleaseMethod == nameof(DeploySmartContract) + ? ContractDeploymentInput.Parser.ParseFrom(input.ContractInput).Code + : ContractUpdateInput.Parser.ParseFrom(input.ContractInput).Code; + } - private void AssertCodeCheckProposingInput(ContractCodeCheckInput input) - { - Assert( - input.CodeCheckReleaseMethod == nameof(DeploySmartContract) || - input.CodeCheckReleaseMethod == nameof(UpdateSmartContract), "Invalid input."); - } + private void AssertCodeCheckProposingInput(ContractCodeCheckInput input) + { + Assert( + input.CodeCheckReleaseMethod == nameof(DeploySmartContract) || + input.CodeCheckReleaseMethod == nameof(UpdateSmartContract), "Invalid input."); } +} - public static class AddressHelper +public static class AddressHelper +{ + /// + /// + /// + /// + private static Address BuildContractAddress(Hash chainId, long serialNumber) { - /// - /// - /// - /// - /// - private static Address BuildContractAddress(Hash chainId, long serialNumber) - { - var hash = HashHelper.ConcatAndCompute(chainId, HashHelper.ComputeFrom(serialNumber)); - return Address.FromBytes(hash.ToByteArray()); - } + var hash = HashHelper.ConcatAndCompute(chainId, HashHelper.ComputeFrom(serialNumber)); + return Address.FromBytes(hash.ToByteArray()); + } - public static Address BuildContractAddress(int chainId, long serialNumber) - { - return BuildContractAddress(HashHelper.ComputeFrom(chainId), serialNumber); - } + public static Address BuildContractAddress(int chainId, long serialNumber) + { + return BuildContractAddress(HashHelper.ComputeFrom(chainId), serialNumber); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj index d6d85ec80e..1848bf9104 100644 --- a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj +++ b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.MultiToken true - MultiToken is a contract that implements token functionality like creation, issuance and - transfer. + MultiToken is a contract that implements token functionality like creation, issuance and + transfer. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs0.proto diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 538bc70c58..2664d98820 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -1,18 +1,17 @@ -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public static class TokenContractConstants { - public static class TokenContractConstants - { - public const int TokenNameLength = 80; - public const int MaxDecimals = 18; - public const int SymbolMaxLength = 10; - public const int MemoMaxLength = 64; + public const int TokenNameLength = 80; + public const int MaxDecimals = 18; + public const int SymbolMaxLength = 10; + public const int MemoMaxLength = 64; - public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; - public const string PayRentalSymbolListName = "SymbolListToPayRental"; + public const string PayTxFeeSymbolListName = "SymbolListToPayTxFee"; + public const string PayRentalSymbolListName = "SymbolListToPayRental"; - public const string TransferCallbackExternalInfoKey = "aelf_transfer_callback"; - public const string LockCallbackExternalInfoKey = "aelf_lock_callback"; - public const string UnlockCallbackExternalInfoKey = "aelf_unlock_callback"; - public const string LogEventExternalInfoKey = "aelf_log_event"; - } + public const string TransferCallbackExternalInfoKey = "aelf_transfer_callback"; + public const string LockCallbackExternalInfoKey = "aelf_lock_callback"; + public const string UnlockCallbackExternalInfoKey = "aelf_unlock_callback"; + public const string LogEventExternalInfoKey = "aelf_log_event"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs index b2ca4d6242..4e18a1f840 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs @@ -1,17 +1,16 @@ -using AElf.Standards.ACS10; using AElf.Contracts.Association; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Parliament; using AElf.Contracts.Referendum; +using AElf.Standards.ACS10; + +namespace AElf.Contracts.MultiToken; -namespace AElf.Contracts.MultiToken +public partial class TokenContractState { - public partial class TokenContractState - { - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal AssociationContractContainer.AssociationContractReferenceState AssociationContract { get; set; } - internal ReferendumContractContainer.ReferendumContractReferenceState ReferendumContract { get; set; } - internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; } - internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract{ get; set; } - } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal AssociationContractContainer.AssociationContractReferenceState AssociationContract { get; set; } + internal ReferendumContractContainer.ReferendumContractReferenceState ReferendumContract { get; set; } + internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; } + internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index caf827e22a..9ae5404131 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -1,56 +1,55 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContractState : ContractState { - public partial class TokenContractState : ContractState - { - public StringState NativeTokenSymbol { get; set; } + public StringState NativeTokenSymbol { get; set; } - public StringState ChainPrimaryTokenSymbol { get; set; } - public MappedState TokenInfos { get; set; } - public MappedState Balances { get; set; } - public MappedState Allowances { get; set; } + public StringState ChainPrimaryTokenSymbol { get; set; } + public MappedState TokenInfos { get; set; } + public MappedState Balances { get; set; } + public MappedState Allowances { get; set; } - public SingletonState
FeeReceiver { get; set; } + public SingletonState
FeeReceiver { get; set; } - /// - /// Contract Address -> Advance Address -> Resource Token Symbol -> Amount. - /// - public MappedState AdvancedResourceToken { get; set; } + /// + /// Contract Address -> Advance Address -> Resource Token Symbol -> Amount. + /// + public MappedState AdvancedResourceToken { get; set; } - /// - /// Contract Address -> (Owning) Resource Token Symbol -> Amount. - /// - public MappedState OwningResourceToken { get; set; } + /// + /// Contract Address -> (Owning) Resource Token Symbol -> Amount. + /// + public MappedState OwningResourceToken { get; set; } - public BoolState InitializedFromParentChain { get; set; } + public BoolState InitializedFromParentChain { get; set; } - public SingletonState CrossChainTokenContractRegistrationController { get; set; } - public SingletonState UserFeeController { get; set; } - public SingletonState DeveloperFeeController { get; set; } - public SingletonState SymbolToPayTxFeeController { get; set; } - public SingletonState SideChainRentalController { get; set; } + public SingletonState CrossChainTokenContractRegistrationController { get; set; } + public SingletonState UserFeeController { get; set; } + public SingletonState DeveloperFeeController { get; set; } + public SingletonState SymbolToPayTxFeeController { get; set; } + public SingletonState SideChainRentalController { get; set; } - /// - /// symbol -> address -> is in white list. - /// - public MappedState LockWhiteLists { get; set; } + /// + /// symbol -> address -> is in white list. + /// + public MappedState LockWhiteLists { get; set; } - public MappedState CrossChainTransferWhiteList { get; set; } + public MappedState CrossChainTransferWhiteList { get; set; } - public MappedState VerifiedCrossChainTransferTransaction { get; set; } + public MappedState VerifiedCrossChainTransferTransaction { get; set; } - public SingletonState MethodFeeController { get; set; } + public SingletonState MethodFeeController { get; set; } - public SingletonState LatestTotalResourceTokensMapsHash { get; set; } - public SingletonState LatestTotalTransactionFeesMapHash { get; set; } + public SingletonState LatestTotalResourceTokensMapsHash { get; set; } + public SingletonState LatestTotalTransactionFeesMapHash { get; set; } - public SingletonState ClaimTransactionFeeExecuteHeight { get; set; } - public SingletonState DonateResourceTokenExecuteHeight { get; set; } + public SingletonState ClaimTransactionFeeExecuteHeight { get; set; } + public SingletonState DonateResourceTokenExecuteHeight { get; set; } - public SingletonState
NFTContractAddress { get; set; } + public SingletonState
NFTContractAddress { get; set; } - public MappedState CreateTokenWhiteListMap { get; set; } - } + public MappedState CreateTokenWhiteListMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index db8601d66b..dbea3b5609 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -1,38 +1,37 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContractState { - public partial class TokenContractState - { - internal MappedState TransactionFees { get; set; } - - public SingletonState LastPayRentTime { get; set; } - - public SingletonState
SideChainCreator { get; set; } - - public SingletonState AllCalculateFeeCoefficients { get; set; } - public SingletonState SymbolListToPayTxSizeFee { get; set; } - - /// - /// Symbol -> Amount (TBD) - /// (CPU: core) - /// (RAM: GiB) - /// (DISK: GiB) - /// (NET: MB) - /// - public MappedState ResourceAmount { get; set; } - - /// - /// Symbol -> Amount (Tokens per minute) - /// - public MappedState Rental { get; set; } - - /// - /// Symbol -> Amount - /// - public MappedState OwningRental { get; set; } - } + internal MappedState TransactionFees { get; set; } + + public SingletonState LastPayRentTime { get; set; } + + public SingletonState
SideChainCreator { get; set; } + + public SingletonState AllCalculateFeeCoefficients { get; set; } + public SingletonState SymbolListToPayTxSizeFee { get; set; } + + /// + /// Symbol -> Amount (TBD) + /// (CPU: core) + /// (RAM: GiB) + /// (DISK: GiB) + /// (NET: MB) + /// + public MappedState ResourceAmount { get; set; } + + /// + /// Symbol -> Amount (Tokens per minute) + /// + public MappedState Rental { get; set; } + + /// + /// Symbol -> Amount + /// + public MappedState OwningRental { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs index 50938498eb..5401ca926e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs @@ -1,136 +1,126 @@ using System.Collections.Generic; +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var symbolToAmount in input.Fees) AssertValidFeeToken(symbolToAmount.Symbol, symbolToAmount.BasicFee); - public override MethodFees GetMethodFee(StringValue input) - { - if (new List + RequiredMethodFeeControllerSet(); + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + + State.TransactionFees[input.MethodName] = input; + return new Empty(); + } + + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + + State.MethodFeeController.Value = input; + return new Empty(); + } + + #region Views + + public override MethodFees GetMethodFee(StringValue input) + { + if (new List { nameof(ClaimTransactionFees), nameof(DonateResourceToken), nameof(ChargeTransactionFees), nameof(CheckThreshold), nameof(CheckResourceToken), nameof(ChargeResourceToken), nameof(CrossChainReceiveToken) }.Contains(input.Value)) + return new MethodFees { - return new MethodFees - { - MethodName = input.Value, - IsSizeFeeFree = true - }; - } + MethodName = input.Value, + IsSizeFeeFree = true + }; - if (input.Value == nameof(Create)) + if (input.Value == nameof(Create)) + return new MethodFees { - return new MethodFees + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = + new MethodFee { - new MethodFee - { - Symbol = Context.Variables.NativeSymbol, - BasicFee = 10000_00000000 - } + Symbol = Context.Variables.NativeSymbol, + BasicFee = 10000_00000000 } - }; - } - - return State.TransactionFees[input.Value]; - } + } + }; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } - - #endregion + return State.TransactionFees[input.Value]; + } - public override Empty SetMethodFee(MethodFees input) - { - foreach (var symbolToAmount in input.Fees) - { - AssertValidFeeToken(symbolToAmount.Symbol, symbolToAmount.BasicFee); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - RequiredMethodFeeControllerSet(); - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + #endregion - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + #region private methods - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + private List GetMethodFeeSymbols() + { + var symbols = new List(); + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + if (primaryTokenSymbol != string.Empty) symbols.Add(primaryTokenSymbol); + return symbols; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - #region private methods + var defaultAuthority = new AuthorityInfo(); - private List GetMethodFeeSymbols() + // Parliament Auth Contract maybe not deployed. + if (State.ParliamentContract.Value != null) { - var symbols = new List(); - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (primaryTokenSymbol != string.Empty) symbols.Add(primaryTokenSymbol); - return symbols; + defaultAuthority.OwnerAddress = + State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); + defaultAuthority.ContractAddress = State.ParliamentContract.Value; } - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo(); - - // Parliament Auth Contract maybe not deployed. - if (State.ParliamentContract.Value != null) - { - defaultAuthority.OwnerAddress = - State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); - defaultAuthority.ContractAddress = State.ParliamentContract.Value; - } - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + State.MethodFeeController.Value = defaultAuthority; + } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - private void AssertValidFeeToken(string symbol, long amount) - { - AssertValidSymbolAndAmount(symbol, amount); - if (State.TokenInfos[symbol] == null) - throw new AssertionException("Token is not found"); - Assert(State.TokenInfos[symbol].IsBurnable, $"Token {symbol} cannot set as method fee."); - } + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } - #endregion + private void AssertValidFeeToken(string symbol, long amount) + { + AssertValidSymbolAndAmount(symbol, amount); + if (State.TokenInfos[symbol] == null) + throw new AssertionException("Token is not found"); + Assert(State.TokenInfos[symbol].IsBurnable, $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 96cabe4891..f69ec02995 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -1,92 +1,91 @@ -using AElf.Standards.ACS2; -using System.Linq; +using System.Linq; +using AElf.Standards.ACS2; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + public override ResourceInfo GetResourceInfo(Transaction txn) { - public override ResourceInfo GetResourceInfo(Transaction txn) + switch (txn.MethodName) { - switch (txn.MethodName) + case nameof(Transfer): { - case nameof(Transfer): + var args = TransferInput.Parser.ParseFrom(txn.Params); + var resourceInfo = new ResourceInfo { - var args = TransferInput.Parser.ParseFrom(txn.Params); - var resourceInfo = new ResourceInfo + WritePaths = + { + GetPath(nameof(TokenContractState.Balances), txn.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol) + }, + ReadPaths = { - WritePaths = - { - GetPath(nameof(TokenContractState.Balances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - }, - ReadPaths = - { - GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), - GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)) - } - }; + GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), + GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)) + } + }; - AddPathForTransactionFee(resourceInfo, txn.From); - return resourceInfo; - } + AddPathForTransactionFee(resourceInfo, txn.From); + return resourceInfo; + } - case nameof(TransferFrom): + case nameof(TransferFrom): + { + var args = TransferFromInput.Parser.ParseFrom(txn.Params); + var resourceInfo = new ResourceInfo { - var args = TransferFromInput.Parser.ParseFrom(txn.Params); - var resourceInfo = new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(TokenContractState.Allowances), args.From.ToString(), txn.From.ToString(), - args.Symbol), - GetPath(nameof(TokenContractState.Balances), args.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()), - }, - ReadPaths = - { - GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), - GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)) - } - }; - AddPathForTransactionFee(resourceInfo, txn.From); - return resourceInfo; - } - - default: - return new ResourceInfo {NonParallelizable = true}; + GetPath(nameof(TokenContractState.Allowances), args.From.ToString(), txn.From.ToString(), + args.Symbol), + GetPath(nameof(TokenContractState.Balances), args.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()) + }, + ReadPaths = + { + GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), + GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)) + } + }; + AddPathForTransactionFee(resourceInfo, txn.From); + return resourceInfo; } + + default: + return new ResourceInfo { NonParallelizable = true }; } + } - private void AddPathForTransactionFee(ResourceInfo resourceInfo, Address from) + private void AddPathForTransactionFee(ResourceInfo resourceInfo, Address from) + { + var symbols = GetMethodFeeSymbols(); + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + if (_primaryTokenSymbol != string.Empty && !symbols.Contains(primaryTokenSymbol)) + symbols.Add(primaryTokenSymbol); + var paths = symbols.Select(symbol => GetPath(nameof(TokenContractState.Balances), from.ToString(), symbol)); + foreach (var path in paths) { - var symbols = GetMethodFeeSymbols(); - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (_primaryTokenSymbol != string.Empty && !symbols.Contains(primaryTokenSymbol)) - symbols.Add(primaryTokenSymbol); - var paths = symbols.Select(symbol => GetPath(nameof(TokenContractState.Balances), from.ToString(), symbol)); - foreach (var path in paths) - { - if(resourceInfo.WritePaths.Contains(path)) continue; - resourceInfo.WritePaths.Add(path); - } + if (resourceInfo.WritePaths.Contains(path)) continue; + resourceInfo.WritePaths.Add(path); } + } - private ScopedStatePath GetPath(params string[] parts) + private ScopedStatePath GetPath(params string[] parts) + { + return new ScopedStatePath { - return new ScopedStatePath + Address = Context.Self, + Path = new StatePath { - Address = Context.Self, - Path = new StatePath + Parts = { - Parts = - { - parts - } + parts } - }; - } + } + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 641ff33b6c..fa4fd381d9 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -1,587 +1,564 @@ using System; using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS0; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract : TokenContractImplContainer.TokenContractImplBase { - public partial class TokenContract : TokenContractImplContainer.TokenContractImplBase + public override Empty InitializeFromParentChain(InitializeFromParentChainInput input) { - public override Empty InitializeFromParentChain(InitializeFromParentChainInput input) - { - Assert(!State.InitializedFromParentChain.Value, "MultiToken has been initialized"); - State.InitializedFromParentChain.Value = true; - Assert(input.Creator != null, "creator should not be null"); - foreach (var pair in input.ResourceAmount) - { - State.ResourceAmount[pair.Key] = pair.Value; - } - - foreach (var pair in input.RegisteredOtherTokenContractAddresses) - { - State.CrossChainTransferWhiteList[pair.Key] = pair.Value; - } - - SetSideChainCreator(input.Creator); - return new Empty(); - } - - /// - /// Register the TokenInfo into TokenContract add initial TokenContractState.LockWhiteLists; - /// - /// - /// - public override Empty Create(CreateInput input) - { - if (Context.Origin != Context.Sender) - { - Assert(IsAddressInCreateTokenWhiteList(Context.Sender), "No permission to create token via inline tx."); - } - - Assert(State.SideChainCreator.Value == null, "Failed to create token if side chain creator already set."); - AssertValidCreateInput(input); - var tokenInfo = new TokenInfo - { - Symbol = input.Symbol, - TokenName = input.TokenName, - TotalSupply = input.TotalSupply, - Decimals = input.Decimals, - Issuer = input.Issuer, - IsBurnable = input.IsBurnable, - IssueChainId = input.IssueChainId == 0 ? Context.ChainId : input.IssueChainId, - ExternalInfo = input.ExternalInfo ?? new ExternalInfo() - }; - Assert(input.Symbol.All(IsValidCreateSymbolChar), "Invalid symbol."); - RegisterTokenInfo(tokenInfo); - if (string.IsNullOrEmpty(State.NativeTokenSymbol.Value)) - { - Assert(Context.Variables.NativeSymbol == input.Symbol, "Invalid native token input."); - State.NativeTokenSymbol.Value = input.Symbol; - } - - var systemContractAddresses = Context.GetSystemContractNameToAddressMapping().Select(m => m.Value); - var isSystemContractAddress = input.LockWhiteList.All(l => systemContractAddresses.Contains(l)); - Assert(isSystemContractAddress, "Addresses in lock white list should be system contract addresses"); - foreach (var address in input.LockWhiteList) - { - State.LockWhiteLists[input.Symbol][address] = true; - } - - Context.LogDebug(() => $"Token created: {input.Symbol}"); + Assert(!State.InitializedFromParentChain.Value, "MultiToken has been initialized"); + State.InitializedFromParentChain.Value = true; + Assert(input.Creator != null, "creator should not be null"); + foreach (var pair in input.ResourceAmount) State.ResourceAmount[pair.Key] = pair.Value; - Context.Fire(new TokenCreated - { - Symbol = tokenInfo.Symbol, - TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply, - Decimals = tokenInfo.Decimals, - Issuer = tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - IssueChainId = tokenInfo.IssueChainId, - ExternalInfo = tokenInfo.ExternalInfo - }); - - return new Empty(); - } + foreach (var pair in input.RegisteredOtherTokenContractAddresses) + State.CrossChainTransferWhiteList[pair.Key] = pair.Value; - /// - /// Set primary token symbol. - /// - /// - /// - public override Empty SetPrimaryTokenSymbol(SetPrimaryTokenSymbolInput input) - { - Assert(State.ChainPrimaryTokenSymbol.Value == null, "Failed to set primary token symbol."); - Assert(State.TokenInfos[input.Symbol] != null, "Invalid input."); + SetSideChainCreator(input.Creator); + return new Empty(); + } - State.ChainPrimaryTokenSymbol.Value = input.Symbol; - Context.Fire(new ChainPrimaryTokenSymbolSet {TokenSymbol = input.Symbol}); - return new Empty(); - } + /// + /// Register the TokenInfo into TokenContract add initial TokenContractState.LockWhiteLists; + /// + /// + /// + public override Empty Create(CreateInput input) + { + if (Context.Origin != Context.Sender) + Assert(IsAddressInCreateTokenWhiteList(Context.Sender), "No permission to create token via inline tx."); - /// - /// Issue the token to issuer,then issuer will occupy the amount of token the issued. - /// - /// - /// - public override Empty Issue(IssueInput input) + Assert(State.SideChainCreator.Value == null, "Failed to create token if side chain creator already set."); + AssertValidCreateInput(input); + var tokenInfo = new TokenInfo { - Assert(input.To != null, "To address not filled."); - AssertValidMemo(input.Memo); - var tokenInfo = AssertValidToken(input.Symbol, input.Amount); - Assert(tokenInfo.IssueChainId == Context.ChainId, "Unable to issue token with wrong chainId."); - Assert(tokenInfo.Issuer == Context.Sender || Context.Sender == Context.GetZeroSmartContractAddress(), - $"Sender is not allowed to issue token {input.Symbol}."); - - tokenInfo.Issued = tokenInfo.Issued.Add(input.Amount); - tokenInfo.Supply = tokenInfo.Supply.Add(input.Amount); - - Assert(tokenInfo.Issued <= tokenInfo.TotalSupply, "Total supply exceeded"); - State.TokenInfos[input.Symbol] = tokenInfo; - ModifyBalance(input.To, input.Symbol, input.Amount); - Context.Fire(new Issued - { - Symbol = input.Symbol, - Amount = input.Amount, - To = input.To, - Memo = input.Memo - }); - return new Empty(); - } - - public override Empty Transfer(TransferInput input) + Symbol = input.Symbol, + TokenName = input.TokenName, + TotalSupply = input.TotalSupply, + Decimals = input.Decimals, + Issuer = input.Issuer, + IsBurnable = input.IsBurnable, + IssueChainId = input.IssueChainId == 0 ? Context.ChainId : input.IssueChainId, + ExternalInfo = input.ExternalInfo ?? new ExternalInfo() + }; + Assert(input.Symbol.All(IsValidCreateSymbolChar), "Invalid symbol."); + RegisterTokenInfo(tokenInfo); + if (string.IsNullOrEmpty(State.NativeTokenSymbol.Value)) { - AssertValidToken(input.Symbol, input.Amount); - DoTransfer(Context.Sender, input.To, input.Symbol, input.Amount, input.Memo); - DealWithExternalInfoDuringTransfer(new TransferFromInput - { - From = Context.Sender, - To = input.To, - Amount = input.Amount, - Symbol = input.Symbol, - Memo = input.Memo - }); - return new Empty(); + Assert(Context.Variables.NativeSymbol == input.Symbol, "Invalid native token input."); + State.NativeTokenSymbol.Value = input.Symbol; } - #region Cross chain + var systemContractAddresses = Context.GetSystemContractNameToAddressMapping().Select(m => m.Value); + var isSystemContractAddress = input.LockWhiteList.All(l => systemContractAddresses.Contains(l)); + Assert(isSystemContractAddress, "Addresses in lock white list should be system contract addresses"); + foreach (var address in input.LockWhiteList) State.LockWhiteLists[input.Symbol][address] = true; - public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) - { - var tokenContractAddress = State.CrossChainTransferWhiteList[input.FromChainId]; - Assert(tokenContractAddress != null, - $"Token contract address of chain {ChainHelper.ConvertChainIdToBase58(input.FromChainId)} not registered."); - - var originalTransaction = Transaction.Parser.ParseFrom(input.TransactionBytes); - AssertCrossChainTransaction(originalTransaction, tokenContractAddress, nameof(ValidateTokenInfoExists)); - var originalTransactionId = originalTransaction.GetHash(); - CrossChainVerify(originalTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); - ValidateTokenInfoExistsInput validateTokenInfoExistsInput = - ValidateTokenInfoExistsInput.Parser.ParseFrom(originalTransaction.Params); - - var tokenInfo = new TokenInfo - { - Symbol = validateTokenInfoExistsInput.Symbol, - TokenName = validateTokenInfoExistsInput.TokenName, - TotalSupply = validateTokenInfoExistsInput.TotalSupply, - Decimals = validateTokenInfoExistsInput.Decimals, - Issuer = validateTokenInfoExistsInput.Issuer, - IsBurnable = validateTokenInfoExistsInput.IsBurnable, - IssueChainId = validateTokenInfoExistsInput.IssueChainId, - ExternalInfo = new ExternalInfo {Value = {validateTokenInfoExistsInput.ExternalInfo}} - }; - RegisterTokenInfo(tokenInfo); - - Context.Fire(new TokenCreated - { - Symbol = validateTokenInfoExistsInput.Symbol, - TokenName = validateTokenInfoExistsInput.TokenName, - TotalSupply = validateTokenInfoExistsInput.TotalSupply, - Decimals = validateTokenInfoExistsInput.Decimals, - Issuer = validateTokenInfoExistsInput.Issuer, - IsBurnable = validateTokenInfoExistsInput.IsBurnable, - IssueChainId = validateTokenInfoExistsInput.IssueChainId, - ExternalInfo = new ExternalInfo {Value = {validateTokenInfoExistsInput.ExternalInfo}} - }); - - return new Empty(); - } + Context.LogDebug(() => $"Token created: {input.Symbol}"); - public override Empty RegisterCrossChainTokenContractAddress(RegisterCrossChainTokenContractAddressInput input) + Context.Fire(new TokenCreated { - CheckCrossChainTokenContractRegistrationControllerAuthority(); - - var originalTransaction = Transaction.Parser.ParseFrom(input.TransactionBytes); - AssertCrossChainTransaction(originalTransaction, Context.GetZeroSmartContractAddress(input.FromChainId), - nameof(ACS0Container.ACS0ReferenceState.ValidateSystemContractAddress)); - - var validAddress = ExtractTokenContractAddress(originalTransaction.Params); - - var originalTransactionId = originalTransaction.GetHash(); - CrossChainVerify(originalTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); + Symbol = tokenInfo.Symbol, + TokenName = tokenInfo.TokenName, + TotalSupply = tokenInfo.TotalSupply, + Decimals = tokenInfo.Decimals, + Issuer = tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + IssueChainId = tokenInfo.IssueChainId, + ExternalInfo = tokenInfo.ExternalInfo + }); + + return new Empty(); + } - State.CrossChainTransferWhiteList[input.FromChainId] = validAddress; + /// + /// Set primary token symbol. + /// + /// + /// + public override Empty SetPrimaryTokenSymbol(SetPrimaryTokenSymbolInput input) + { + Assert(State.ChainPrimaryTokenSymbol.Value == null, "Failed to set primary token symbol."); + Assert(State.TokenInfos[input.Symbol] != null, "Invalid input."); - return new Empty(); - } + State.ChainPrimaryTokenSymbol.Value = input.Symbol; + Context.Fire(new ChainPrimaryTokenSymbolSet { TokenSymbol = input.Symbol }); + return new Empty(); + } - /// - /// Transfer token form a chain to another chain - /// burn the tokens at the current chain - /// - /// - /// - public override Empty CrossChainTransfer(CrossChainTransferInput input) + /// + /// Issue the token to issuer,then issuer will occupy the amount of token the issued. + /// + /// + /// + public override Empty Issue(IssueInput input) + { + Assert(input.To != null, "To address not filled."); + AssertValidMemo(input.Memo); + var tokenInfo = AssertValidToken(input.Symbol, input.Amount); + Assert(tokenInfo.IssueChainId == Context.ChainId, "Unable to issue token with wrong chainId."); + Assert(tokenInfo.Issuer == Context.Sender || Context.Sender == Context.GetZeroSmartContractAddress(), + $"Sender is not allowed to issue token {input.Symbol}."); + + tokenInfo.Issued = tokenInfo.Issued.Add(input.Amount); + tokenInfo.Supply = tokenInfo.Supply.Add(input.Amount); + + Assert(tokenInfo.Issued <= tokenInfo.TotalSupply, "Total supply exceeded"); + State.TokenInfos[input.Symbol] = tokenInfo; + ModifyBalance(input.To, input.Symbol, input.Amount); + Context.Fire(new Issued { - AssertValidToken(input.Symbol, input.Amount); - AssertValidMemo(input.Memo); - int issueChainId = GetIssueChainId(input.Symbol); - Assert(issueChainId == input.IssueChainId, "Incorrect issue chain id."); - var burnInput = new BurnInput - { - Amount = input.Amount, - Symbol = input.Symbol - }; - Burn(burnInput); - Context.Fire(new CrossChainTransferred - { - From = Context.Sender, - To = input.To, - Symbol = input.Symbol, - Amount = input.Amount, - IssueChainId = input.IssueChainId, - Memo = input.Memo, - ToChainId = input.ToChainId - }); - return new Empty(); - } + Symbol = input.Symbol, + Amount = input.Amount, + To = input.To, + Memo = input.Memo + }); + return new Empty(); + } - /// - /// Receive the token from another chain - /// - /// - /// - public override Empty CrossChainReceiveToken(CrossChainReceiveTokenInput input) + public override Empty Transfer(TransferInput input) + { + AssertValidToken(input.Symbol, input.Amount); + DoTransfer(Context.Sender, input.To, input.Symbol, input.Amount, input.Memo); + DealWithExternalInfoDuringTransfer(new TransferFromInput { - var transferTransaction = Transaction.Parser.ParseFrom(input.TransferTransactionBytes); - var transferTransactionId = transferTransaction.GetHash(); - - Assert(!State.VerifiedCrossChainTransferTransaction[transferTransactionId], - "Token already claimed."); - - var crossChainTransferInput = - CrossChainTransferInput.Parser.ParseFrom(transferTransaction.Params.ToByteArray()); - var symbol = crossChainTransferInput.Symbol; - var amount = crossChainTransferInput.Amount; - var receivingAddress = crossChainTransferInput.To; - var targetChainId = crossChainTransferInput.ToChainId; - var transferSender = transferTransaction.From; - - var tokenInfo = AssertValidToken(symbol, amount); - int issueChainId = GetIssueChainId(symbol); - Assert(issueChainId == crossChainTransferInput.IssueChainId, "Incorrect issue chain id."); - Assert(transferSender == Context.Sender && targetChainId == Context.ChainId, - "Unable to claim cross chain token."); - var registeredTokenContractAddress = State.CrossChainTransferWhiteList[input.FromChainId]; - AssertCrossChainTransaction(transferTransaction, registeredTokenContractAddress, - nameof(CrossChainTransfer)); - Context.LogDebug(() => - $"symbol == {symbol}, amount == {amount}, receivingAddress == {receivingAddress}, targetChainId == {targetChainId}"); - - CrossChainVerify(transferTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); - - State.VerifiedCrossChainTransferTransaction[transferTransactionId] = true; - tokenInfo.Supply = tokenInfo.Supply.Add(amount); - Assert(tokenInfo.Supply <= tokenInfo.TotalSupply, "Total supply exceeded"); - State.TokenInfos[symbol] = tokenInfo; - ModifyBalance(receivingAddress, symbol, amount); - - Context.Fire(new CrossChainReceived - { - From = transferSender, - To = receivingAddress, - Symbol = symbol, - Amount = amount, - Memo = crossChainTransferInput.Memo, - FromChainId = input.FromChainId, - ParentChainHeight = input.ParentChainHeight, - IssueChainId = issueChainId - }); - return new Empty(); - } - - #endregion + From = Context.Sender, + To = input.To, + Amount = input.Amount, + Symbol = input.Symbol, + Memo = input.Memo + }); + return new Empty(); + } - public override Empty Lock(LockInput input) + public override Empty Lock(LockInput input) + { + AssertSystemContractOrLockWhiteListAddress(input.Symbol); + Assert(Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; + if (allowance >= input.Amount) + State.Allowances[input.Address][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); + AssertValidToken(input.Symbol, input.Amount); + var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) + .Concat(input.LockId.Value).ToArray()); + var virtualAddress = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress); + // Transfer token to virtual address. + DoTransfer(input.Address, virtualAddress, input.Symbol, input.Amount, input.Usage); + DealWithExternalInfoDuringLocking(new TransferFromInput { - AssertSystemContractOrLockWhiteListAddress(input.Symbol); - Assert(Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); - var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; - if (allowance >= input.Amount) - State.Allowances[input.Address][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); - AssertValidToken(input.Symbol, input.Amount); - var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) - .Concat(input.LockId.Value).ToArray()); - var virtualAddress = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress); - // Transfer token to virtual address. - DoTransfer(input.Address, virtualAddress, input.Symbol, input.Amount, input.Usage); - DealWithExternalInfoDuringLocking(new TransferFromInput - { - From = input.Address, - To = virtualAddress, - Symbol = input.Symbol, - Amount = input.Amount, - Memo = input.Usage - }); - return new Empty(); - } + From = input.Address, + To = virtualAddress, + Symbol = input.Symbol, + Amount = input.Amount, + Memo = input.Usage + }); + return new Empty(); + } - public override Empty Unlock(UnlockInput input) + public override Empty Unlock(UnlockInput input) + { + AssertSystemContractOrLockWhiteListAddress(input.Symbol); + Assert(Context.Origin == input.Address, "Unlock behaviour should be initialed by origin address."); + AssertValidToken(input.Symbol, input.Amount); + var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) + .Concat(input.LockId.Value).ToArray()); + Context.SendVirtualInline(fromVirtualAddress, Context.Self, nameof(Transfer), new TransferInput { - AssertSystemContractOrLockWhiteListAddress(input.Symbol); - Assert(Context.Origin == input.Address, "Unlock behaviour should be initialed by origin address."); - AssertValidToken(input.Symbol, input.Amount); - var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) - .Concat(input.LockId.Value).ToArray()); - Context.SendVirtualInline(fromVirtualAddress, Context.Self, nameof(Transfer), new TransferInput - { - To = input.Address, - Symbol = input.Symbol, - Amount = input.Amount, - Memo = input.Usage, - }); - DealWithExternalInfoDuringUnlock(new TransferFromInput - { - From = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress), - To = input.Address, - Symbol = input.Symbol, - Amount = input.Amount, - Memo = input.Usage - }); - return new Empty(); - } + To = input.Address, + Symbol = input.Symbol, + Amount = input.Amount, + Memo = input.Usage + }); + DealWithExternalInfoDuringUnlock(new TransferFromInput + { + From = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress), + To = input.Address, + Symbol = input.Symbol, + Amount = input.Amount, + Memo = input.Usage + }); + return new Empty(); + } - public override Empty TransferFrom(TransferFromInput input) + public override Empty TransferFrom(TransferFromInput input) + { + AssertValidToken(input.Symbol, input.Amount); + // First check allowance. + var allowance = State.Allowances[input.From][Context.Sender][input.Symbol]; + if (allowance < input.Amount) { - AssertValidToken(input.Symbol, input.Amount); - // First check allowance. - var allowance = State.Allowances[input.From][Context.Sender][input.Symbol]; - if (allowance < input.Amount) + if (IsInWhiteList(new IsInWhiteListInput { Symbol = input.Symbol, Address = Context.Sender }).Value) { - if (IsInWhiteList(new IsInWhiteListInput {Symbol = input.Symbol, Address = Context.Sender}).Value) - { - DoTransfer(input.From, input.To, input.Symbol, input.Amount, input.Memo); - DealWithExternalInfoDuringTransfer(input); - return new Empty(); - } - - Assert(false, - $"[TransferFrom]Insufficient allowance. Token: {input.Symbol}; {allowance}/{input.Amount}.\n" + - $"From:{input.From}\tSpender:{Context.Sender}\tTo:{input.To}"); + DoTransfer(input.From, input.To, input.Symbol, input.Amount, input.Memo); + DealWithExternalInfoDuringTransfer(input); + return new Empty(); } - DoTransfer(input.From, input.To, input.Symbol, input.Amount, input.Memo); - DealWithExternalInfoDuringTransfer(input); - State.Allowances[input.From][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); - return new Empty(); + Assert(false, + $"[TransferFrom]Insufficient allowance. Token: {input.Symbol}; {allowance}/{input.Amount}.\n" + + $"From:{input.From}\tSpender:{Context.Sender}\tTo:{input.To}"); } - public override Empty Approve(ApproveInput input) + DoTransfer(input.From, input.To, input.Symbol, input.Amount, input.Memo); + DealWithExternalInfoDuringTransfer(input); + State.Allowances[input.From][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); + return new Empty(); + } + + public override Empty Approve(ApproveInput input) + { + AssertValidToken(input.Symbol, input.Amount); + State.Allowances[Context.Sender][input.Spender][input.Symbol] = input.Amount; + Context.Fire(new Approved { - AssertValidToken(input.Symbol, input.Amount); - State.Allowances[Context.Sender][input.Spender][input.Symbol] = input.Amount; - Context.Fire(new Approved() - { - Owner = Context.Sender, - Spender = input.Spender, - Symbol = input.Symbol, - Amount = input.Amount - }); - return new Empty(); - } + Owner = Context.Sender, + Spender = input.Spender, + Symbol = input.Symbol, + Amount = input.Amount + }); + return new Empty(); + } - public override Empty UnApprove(UnApproveInput input) + public override Empty UnApprove(UnApproveInput input) + { + AssertValidToken(input.Symbol, input.Amount); + var oldAllowance = State.Allowances[Context.Sender][input.Spender][input.Symbol]; + var amountOrAll = Math.Min(input.Amount, oldAllowance); + State.Allowances[Context.Sender][input.Spender][input.Symbol] = oldAllowance.Sub(amountOrAll); + Context.Fire(new UnApproved { - AssertValidToken(input.Symbol, input.Amount); - var oldAllowance = State.Allowances[Context.Sender][input.Spender][input.Symbol]; - var amountOrAll = Math.Min(input.Amount, oldAllowance); - State.Allowances[Context.Sender][input.Spender][input.Symbol] = oldAllowance.Sub(amountOrAll); - Context.Fire(new UnApproved() - { - Owner = Context.Sender, - Spender = input.Spender, - Symbol = input.Symbol, - Amount = amountOrAll - }); - return new Empty(); - } + Owner = Context.Sender, + Spender = input.Spender, + Symbol = input.Symbol, + Amount = amountOrAll + }); + return new Empty(); + } - public override Empty Burn(BurnInput input) + public override Empty Burn(BurnInput input) + { + var tokenInfo = AssertValidToken(input.Symbol, input.Amount); + Assert(tokenInfo.IsBurnable, "The token is not burnable."); + ModifyBalance(Context.Sender, input.Symbol, -input.Amount); + tokenInfo.Supply = tokenInfo.Supply.Sub(input.Amount); + Context.Fire(new Burned { - var tokenInfo = AssertValidToken(input.Symbol, input.Amount); - Assert(tokenInfo.IsBurnable, "The token is not burnable."); - ModifyBalance(Context.Sender, input.Symbol, -input.Amount); - tokenInfo.Supply = tokenInfo.Supply.Sub(input.Amount); - Context.Fire(new Burned - { - Burner = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount - }); - return new Empty(); - } + Burner = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount + }); + return new Empty(); + } - public override Empty CheckThreshold(CheckThresholdInput input) + public override Empty CheckThreshold(CheckThresholdInput input) + { + var meetThreshold = false; + var meetBalanceSymbolList = new List(); + foreach (var symbolToThreshold in input.SymbolToThreshold) { - var meetThreshold = false; - var meetBalanceSymbolList = new List(); - foreach (var symbolToThreshold in input.SymbolToThreshold) - { - if (GetBalance(input.Sender, symbolToThreshold.Key) < symbolToThreshold.Value) - continue; - meetBalanceSymbolList.Add(symbolToThreshold.Key); - } + if (GetBalance(input.Sender, symbolToThreshold.Key) < symbolToThreshold.Value) + continue; + meetBalanceSymbolList.Add(symbolToThreshold.Key); + } - if (meetBalanceSymbolList.Count > 0) - { - if (input.IsCheckAllowance) - { - foreach (var symbol in meetBalanceSymbolList) - { - if (State.Allowances[input.Sender][Context.Sender][symbol] < - input.SymbolToThreshold[symbol]) continue; - meetThreshold = true; - break; - } - } - else + if (meetBalanceSymbolList.Count > 0) + { + if (input.IsCheckAllowance) + foreach (var symbol in meetBalanceSymbolList) { + if (State.Allowances[input.Sender][Context.Sender][symbol] < + input.SymbolToThreshold[symbol]) continue; meetThreshold = true; + break; } - } + else + meetThreshold = true; + } + + if (input.SymbolToThreshold.Count == 0) meetThreshold = true; - if (input.SymbolToThreshold.Count == 0) + Assert(meetThreshold, "Cannot meet the calling threshold."); + return new Empty(); + } + + /// + /// Transfer from Context.Origin to Context.Sender. + /// Used for contract developers to receive / share profits. + /// + /// + /// + public override Empty TransferToContract(TransferToContractInput input) + { + AssertValidToken(input.Symbol, input.Amount); + + var transferFromInput = new TransferFromInput + { + From = Context.Origin, + To = Context.Sender, + Amount = input.Amount, + Symbol = input.Symbol, + Memo = input.Memo + }; + // First check allowance. + var allowance = State.Allowances[Context.Origin][Context.Sender][input.Symbol]; + if (allowance < input.Amount) + { + if (IsInWhiteList(new IsInWhiteListInput { Symbol = input.Symbol, Address = Context.Sender }).Value) { - meetThreshold = true; + DoTransfer(Context.Origin, Context.Sender, input.Symbol, input.Amount, input.Memo); + DealWithExternalInfoDuringTransfer(transferFromInput); + return new Empty(); } - Assert(meetThreshold, "Cannot meet the calling threshold."); - return new Empty(); + Assert(false, + $"[TransferToContract]Insufficient allowance. Token: {input.Symbol}; {allowance}/{input.Amount}." + + $"From:{Context.Origin}\tSpender & To:{Context.Sender}"); } - /// - /// Transfer from Context.Origin to Context.Sender. - /// Used for contract developers to receive / share profits. - /// - /// - /// - public override Empty TransferToContract(TransferToContractInput input) - { - AssertValidToken(input.Symbol, input.Amount); + DoTransfer(Context.Origin, Context.Sender, input.Symbol, input.Amount, input.Memo); + DealWithExternalInfoDuringTransfer(transferFromInput); + State.Allowances[Context.Origin][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); + return new Empty(); + } - var transferFromInput = new TransferFromInput - { - From = Context.Origin, - To = Context.Sender, - Amount = input.Amount, - Symbol = input.Symbol, - Memo = input.Memo - }; - // First check allowance. - var allowance = State.Allowances[Context.Origin][Context.Sender][input.Symbol]; - if (allowance < input.Amount) - { - if (IsInWhiteList(new IsInWhiteListInput {Symbol = input.Symbol, Address = Context.Sender}).Value) - { - DoTransfer(Context.Origin, Context.Sender, input.Symbol, input.Amount, input.Memo); - DealWithExternalInfoDuringTransfer(transferFromInput); - return new Empty(); - } + public override Empty AdvanceResourceToken(AdvanceResourceTokenInput input) + { + Assert( + Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName) + .Contains(input.ResourceTokenSymbol), + "Invalid resource token symbol."); + State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] = + State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] + .Add(input.Amount); + DoTransfer(Context.Sender, input.ContractAddress, input.ResourceTokenSymbol, input.Amount); + return new Empty(); + } - Assert(false, - $"[TransferToContract]Insufficient allowance. Token: {input.Symbol}; {allowance}/{input.Amount}." + - $"From:{Context.Origin}\tSpender & To:{Context.Sender}"); - } + public override Empty TakeResourceTokenBack(TakeResourceTokenBackInput input) + { + var advancedAmount = + State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol]; + Assert(advancedAmount >= input.Amount, "Can't take back that more."); + DoTransfer(input.ContractAddress, Context.Sender, input.ResourceTokenSymbol, input.Amount); + State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] = + advancedAmount.Sub(input.Amount); + return new Empty(); + } - DoTransfer(Context.Origin, Context.Sender, input.Symbol, input.Amount, input.Memo); - DealWithExternalInfoDuringTransfer(transferFromInput); - State.Allowances[Context.Origin][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); - return new Empty(); - } + public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + if (tokenInfo == null) throw new AssertionException("Token validation failed."); - public override Empty AdvanceResourceToken(AdvanceResourceTokenInput input) - { - Assert( - Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName) - .Contains(input.ResourceTokenSymbol), - "Invalid resource token symbol."); - State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] = - State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] - .Add(input.Amount); - DoTransfer(Context.Sender, input.ContractAddress, input.ResourceTokenSymbol, input.Amount); - return new Empty(); - } + var validationResult = tokenInfo.TokenName == input.TokenName && + tokenInfo.IsBurnable == input.IsBurnable && tokenInfo.Decimals == input.Decimals && + tokenInfo.Issuer == input.Issuer && tokenInfo.TotalSupply == input.TotalSupply && + tokenInfo.IssueChainId == input.IssueChainId; - public override Empty TakeResourceTokenBack(TakeResourceTokenBackInput input) + if (tokenInfo.ExternalInfo != null && tokenInfo.ExternalInfo.Value.Count > 0) { - var advancedAmount = - State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol]; - Assert(advancedAmount >= input.Amount, "Can't take back that more."); - DoTransfer(input.ContractAddress, Context.Sender, input.ResourceTokenSymbol, input.Amount); - State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol] = - advancedAmount.Sub(input.Amount); - return new Empty(); + validationResult = validationResult && tokenInfo.ExternalInfo.Value.Count == input.ExternalInfo.Count; + if (tokenInfo.ExternalInfo.Value.Any(keyPair => + !input.ExternalInfo.ContainsKey(keyPair.Key) || input.ExternalInfo[keyPair.Key] != keyPair.Value)) + throw new AssertionException("Token validation failed."); } - public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input) + Assert(validationResult, "Token validation failed."); + return new Empty(); + } + + public override Empty ChangeTokenIssuer(ChangeTokenIssuerInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + Assert(tokenInfo != null, $"invalid token symbol: {input.Symbol}"); + // ReSharper disable once PossibleNullReferenceException + Assert(tokenInfo.Issuer == Context.Sender && tokenInfo.IssueChainId == Context.ChainId, + "Permission denied"); + tokenInfo.Issuer = input.NewTokenIssuer; + State.TokenInfos[input.Symbol] = tokenInfo; + return new Empty(); + } + + public override Empty ResetExternalInfo(ResetExternalInfoInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + Assert(tokenInfo.Issuer == Context.Sender, "No permission to reset external info."); + tokenInfo.ExternalInfo = input.ExternalInfo; + State.TokenInfos[input.Symbol] = tokenInfo; + Context.Fire(new ExternalInfoChanged { - var tokenInfo = State.TokenInfos[input.Symbol]; - if (tokenInfo == null) - { - throw new AssertionException("Token validation failed."); - } + Symbol = input.Symbol, + ExternalInfo = input.ExternalInfo + }); + return new Empty(); + } - var validationResult = tokenInfo.TokenName == input.TokenName && - tokenInfo.IsBurnable == input.IsBurnable && tokenInfo.Decimals == input.Decimals && - tokenInfo.Issuer == input.Issuer && tokenInfo.TotalSupply == input.TotalSupply && - tokenInfo.IssueChainId == input.IssueChainId; + public override Empty AddAddressToCreateTokenWhiteList(Address input) + { + AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); + State.CreateTokenWhiteListMap[input] = true; + return new Empty(); + } - if (tokenInfo.ExternalInfo != null && tokenInfo.ExternalInfo.Value.Count > 0) - { - validationResult = validationResult && tokenInfo.ExternalInfo.Value.Count == input.ExternalInfo.Count; - if (tokenInfo.ExternalInfo.Value.Any(keyPair => - !input.ExternalInfo.ContainsKey(keyPair.Key) || input.ExternalInfo[keyPair.Key] != keyPair.Value)) - { - throw new AssertionException("Token validation failed."); - } - } + public override Empty RemoveAddressFromCreateTokenWhiteList(Address input) + { + AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); + State.CreateTokenWhiteListMap.Remove(input); + return new Empty(); + } - Assert(validationResult, "Token validation failed."); - return new Empty(); - } + #region Cross chain - public override Empty ChangeTokenIssuer(ChangeTokenIssuerInput input) + public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) + { + var tokenContractAddress = State.CrossChainTransferWhiteList[input.FromChainId]; + Assert(tokenContractAddress != null, + $"Token contract address of chain {ChainHelper.ConvertChainIdToBase58(input.FromChainId)} not registered."); + + var originalTransaction = Transaction.Parser.ParseFrom(input.TransactionBytes); + AssertCrossChainTransaction(originalTransaction, tokenContractAddress, nameof(ValidateTokenInfoExists)); + var originalTransactionId = originalTransaction.GetHash(); + CrossChainVerify(originalTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); + var validateTokenInfoExistsInput = + ValidateTokenInfoExistsInput.Parser.ParseFrom(originalTransaction.Params); + + var tokenInfo = new TokenInfo { - var tokenInfo = State.TokenInfos[input.Symbol]; - Assert(tokenInfo != null, $"invalid token symbol: {input.Symbol}"); - // ReSharper disable once PossibleNullReferenceException - Assert(tokenInfo.Issuer == Context.Sender && tokenInfo.IssueChainId == Context.ChainId, - "Permission denied"); - tokenInfo.Issuer = input.NewTokenIssuer; - State.TokenInfos[input.Symbol] = tokenInfo; - return new Empty(); - } - - public override Empty ResetExternalInfo(ResetExternalInfoInput input) + Symbol = validateTokenInfoExistsInput.Symbol, + TokenName = validateTokenInfoExistsInput.TokenName, + TotalSupply = validateTokenInfoExistsInput.TotalSupply, + Decimals = validateTokenInfoExistsInput.Decimals, + Issuer = validateTokenInfoExistsInput.Issuer, + IsBurnable = validateTokenInfoExistsInput.IsBurnable, + IssueChainId = validateTokenInfoExistsInput.IssueChainId, + ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } } + }; + RegisterTokenInfo(tokenInfo); + + Context.Fire(new TokenCreated { - var tokenInfo = State.TokenInfos[input.Symbol]; - Assert(tokenInfo.Issuer == Context.Sender, "No permission to reset external info."); - tokenInfo.ExternalInfo = input.ExternalInfo; - State.TokenInfos[input.Symbol] = tokenInfo; - Context.Fire(new ExternalInfoChanged - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - return new Empty(); - } + Symbol = validateTokenInfoExistsInput.Symbol, + TokenName = validateTokenInfoExistsInput.TokenName, + TotalSupply = validateTokenInfoExistsInput.TotalSupply, + Decimals = validateTokenInfoExistsInput.Decimals, + Issuer = validateTokenInfoExistsInput.Issuer, + IsBurnable = validateTokenInfoExistsInput.IsBurnable, + IssueChainId = validateTokenInfoExistsInput.IssueChainId, + ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } } + }); + + return new Empty(); + } + + public override Empty RegisterCrossChainTokenContractAddress(RegisterCrossChainTokenContractAddressInput input) + { + CheckCrossChainTokenContractRegistrationControllerAuthority(); + + var originalTransaction = Transaction.Parser.ParseFrom(input.TransactionBytes); + AssertCrossChainTransaction(originalTransaction, Context.GetZeroSmartContractAddress(input.FromChainId), + nameof(ACS0Container.ACS0ReferenceState.ValidateSystemContractAddress)); + + var validAddress = ExtractTokenContractAddress(originalTransaction.Params); + + var originalTransactionId = originalTransaction.GetHash(); + CrossChainVerify(originalTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); + + State.CrossChainTransferWhiteList[input.FromChainId] = validAddress; - public override Empty AddAddressToCreateTokenWhiteList(Address input) + return new Empty(); + } + + /// + /// Transfer token form a chain to another chain + /// burn the tokens at the current chain + /// + /// + /// + public override Empty CrossChainTransfer(CrossChainTransferInput input) + { + AssertValidToken(input.Symbol, input.Amount); + AssertValidMemo(input.Memo); + var issueChainId = GetIssueChainId(input.Symbol); + Assert(issueChainId == input.IssueChainId, "Incorrect issue chain id."); + var burnInput = new BurnInput { - AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - State.CreateTokenWhiteListMap[input] = true; - return new Empty(); - } + Amount = input.Amount, + Symbol = input.Symbol + }; + Burn(burnInput); + Context.Fire(new CrossChainTransferred + { + From = Context.Sender, + To = input.To, + Symbol = input.Symbol, + Amount = input.Amount, + IssueChainId = input.IssueChainId, + Memo = input.Memo, + ToChainId = input.ToChainId + }); + return new Empty(); + } - public override Empty RemoveAddressFromCreateTokenWhiteList(Address input) + /// + /// Receive the token from another chain + /// + /// + /// + public override Empty CrossChainReceiveToken(CrossChainReceiveTokenInput input) + { + var transferTransaction = Transaction.Parser.ParseFrom(input.TransferTransactionBytes); + var transferTransactionId = transferTransaction.GetHash(); + + Assert(!State.VerifiedCrossChainTransferTransaction[transferTransactionId], + "Token already claimed."); + + var crossChainTransferInput = + CrossChainTransferInput.Parser.ParseFrom(transferTransaction.Params.ToByteArray()); + var symbol = crossChainTransferInput.Symbol; + var amount = crossChainTransferInput.Amount; + var receivingAddress = crossChainTransferInput.To; + var targetChainId = crossChainTransferInput.ToChainId; + var transferSender = transferTransaction.From; + + var tokenInfo = AssertValidToken(symbol, amount); + var issueChainId = GetIssueChainId(symbol); + Assert(issueChainId == crossChainTransferInput.IssueChainId, "Incorrect issue chain id."); + Assert(transferSender == Context.Sender && targetChainId == Context.ChainId, + "Unable to claim cross chain token."); + var registeredTokenContractAddress = State.CrossChainTransferWhiteList[input.FromChainId]; + AssertCrossChainTransaction(transferTransaction, registeredTokenContractAddress, + nameof(CrossChainTransfer)); + Context.LogDebug(() => + $"symbol == {symbol}, amount == {amount}, receivingAddress == {receivingAddress}, targetChainId == {targetChainId}"); + + CrossChainVerify(transferTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath); + + State.VerifiedCrossChainTransferTransaction[transferTransactionId] = true; + tokenInfo.Supply = tokenInfo.Supply.Add(amount); + Assert(tokenInfo.Supply <= tokenInfo.TotalSupply, "Total supply exceeded"); + State.TokenInfos[symbol] = tokenInfo; + ModifyBalance(receivingAddress, symbol, amount); + + Context.Fire(new CrossChainReceived { - AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - State.CreateTokenWhiteListMap.Remove(input); - return new Empty(); - } + From = transferSender, + To = receivingAddress, + Symbol = symbol, + Amount = amount, + Memo = crossChainTransferInput.Memo, + FromChainId = input.FromChainId, + ParentChainHeight = input.ParentChainHeight, + IssueChainId = issueChainId + }); + return new Empty(); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_CacheFileds.cs b/contract/AElf.Contracts.MultiToken/TokenContract_CacheFileds.cs index e22baeace8..df423d0f2a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_CacheFileds.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_CacheFileds.cs @@ -1,7 +1,6 @@ -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract - { - private string _primaryTokenSymbol; - } + private string _primaryTokenSymbol; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs index 09cb0f31d8..8efefd5df0 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs @@ -4,311 +4,308 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + /// + /// Can only update one token at one time. + /// + /// + /// + public override Empty UpdateCoefficientsForContract(UpdateCoefficientsInput input) { - /// - /// Can only update one token at one time. - /// - /// - /// - public override Empty UpdateCoefficientsForContract(UpdateCoefficientsInput input) - { - Assert(input.Coefficients.FeeTokenType != (int) FeeTypeEnum.Tx, "Invalid fee type."); - AssertDeveloperFeeController(); - UpdateCoefficients(input); - return new Empty(); - } - - public override Empty UpdateCoefficientsForSender(UpdateCoefficientsInput input) - { - AssertUserFeeController(); - input.Coefficients.FeeTokenType = (int) FeeTypeEnum.Tx; // The only possible for now. - UpdateCoefficients(input); - return new Empty(); - } + Assert(input.Coefficients.FeeTokenType != (int)FeeTypeEnum.Tx, "Invalid fee type."); + AssertDeveloperFeeController(); + UpdateCoefficients(input); + return new Empty(); + } - private void UpdateCoefficients(UpdateCoefficientsInput input) - { - var feeType = input.Coefficients.FeeTokenType; - var currentAllCoefficients = State.AllCalculateFeeCoefficients.Value; + public override Empty UpdateCoefficientsForSender(UpdateCoefficientsInput input) + { + AssertUserFeeController(); + input.Coefficients.FeeTokenType = (int)FeeTypeEnum.Tx; // The only possible for now. + UpdateCoefficients(input); + return new Empty(); + } - // Get coefficients for specific fee type. - var currentCoefficients = currentAllCoefficients.Value.SingleOrDefault(x => - x.FeeTokenType == feeType); - Assert(currentCoefficients != null, "Specific fee type not existed before."); + private void UpdateCoefficients(UpdateCoefficientsInput input) + { + var feeType = input.Coefficients.FeeTokenType; + var currentAllCoefficients = State.AllCalculateFeeCoefficients.Value; - var inputPieceCoefficientsList = input.Coefficients.PieceCoefficientsList; - // ReSharper disable once PossibleNullReferenceException - var currentPieceCoefficientList = currentCoefficients.PieceCoefficientsList; + // Get coefficients for specific fee type. + var currentCoefficients = currentAllCoefficients.Value.SingleOrDefault(x => + x.FeeTokenType == feeType); + Assert(currentCoefficients != null, "Specific fee type not existed before."); - var inputPieceCount = input.PieceNumbers.Count; - Assert(inputPieceCount == inputPieceCoefficientsList.Count, - "Piece numbers not match."); + var inputPieceCoefficientsList = input.Coefficients.PieceCoefficientsList; + // ReSharper disable once PossibleNullReferenceException + var currentPieceCoefficientList = currentCoefficients.PieceCoefficientsList; - foreach (var coefficients in inputPieceCoefficientsList) - AssertCoefficientsValid(coefficients); + var inputPieceCount = input.PieceNumbers.Count; + Assert(inputPieceCount == inputPieceCoefficientsList.Count, + "Piece numbers not match."); - for (var i = 0; i < inputPieceCount; i++) - { - Assert(currentPieceCoefficientList.Count >= input.PieceNumbers[i], - "Piece number exceeded."); - var pieceIndex = input.PieceNumbers[i].Sub(1); - var pieceCoefficients = inputPieceCoefficientsList[i]; - currentPieceCoefficientList[pieceIndex] = pieceCoefficients; - } + foreach (var coefficients in inputPieceCoefficientsList) + AssertCoefficientsValid(coefficients); - AssertPieceUpperBoundsIsInOrder(currentPieceCoefficientList); + for (var i = 0; i < inputPieceCount; i++) + { + Assert(currentPieceCoefficientList.Count >= input.PieceNumbers[i], + "Piece number exceeded."); + var pieceIndex = input.PieceNumbers[i].Sub(1); + var pieceCoefficients = inputPieceCoefficientsList[i]; + currentPieceCoefficientList[pieceIndex] = pieceCoefficients; + } - State.AllCalculateFeeCoefficients.Value = currentAllCoefficients; + AssertPieceUpperBoundsIsInOrder(currentPieceCoefficientList); - Context.Fire(new CalculateFeeAlgorithmUpdated - { - AllTypeFeeCoefficients = currentAllCoefficients - }); - } + State.AllCalculateFeeCoefficients.Value = currentAllCoefficients; - private void AssertCoefficientsValid(CalculateFeePieceCoefficients coefficients) + Context.Fire(new CalculateFeeAlgorithmUpdated { - // Assert the count should be (3n + 1), n >= 1. - var count = coefficients.Value.Count; - Assert(count > 0 && (count - 1) % 3 == 0, "Coefficients count should be (3n + 1), n >= 1."); + AllTypeFeeCoefficients = currentAllCoefficients + }); + } - // Assert every unit. one [(B / C) * x ^ A] means one unit. - for (var i = 1; i < count; i += 3) - { - var power = coefficients.Value[i]; - var divisor = coefficients.Value[i + 1]; - var dividend = coefficients.Value[i + 2]; - Assert(power >= 0 && divisor >= 0 && dividend > 0, "Invalid coefficient."); - } - } + private void AssertCoefficientsValid(CalculateFeePieceCoefficients coefficients) + { + // Assert the count should be (3n + 1), n >= 1. + var count = coefficients.Value.Count; + Assert(count > 0 && (count - 1) % 3 == 0, "Coefficients count should be (3n + 1), n >= 1."); - private void AssertPieceUpperBoundsIsInOrder( - IReadOnlyCollection calculateFeePieceCoefficientsList) + // Assert every unit. one [(B / C) * x ^ A] means one unit. + for (var i = 1; i < count; i += 3) { - // No same piece upper bound. - Assert(!calculateFeePieceCoefficientsList.GroupBy(i => i.Value[0]).Any(g => g.Count() > 1), - "Piece upper bounds contains same elements."); - - var pieceUpperBounds = calculateFeePieceCoefficientsList.Select(l => l.Value[0]).ToList(); - var orderedEnumerable = pieceUpperBounds.OrderBy(i => i).ToList(); - for (var i = 0; i < calculateFeePieceCoefficientsList.Count; i++) - { - Assert(pieceUpperBounds[i] == orderedEnumerable[i], "Piece upper bounds not in order."); - } + var power = coefficients.Value[i]; + var divisor = coefficients.Value[i + 1]; + var dividend = coefficients.Value[i + 2]; + Assert(power >= 0 && divisor >= 0 && dividend > 0, "Invalid coefficient."); } + } + + private void AssertPieceUpperBoundsIsInOrder( + IReadOnlyCollection calculateFeePieceCoefficientsList) + { + // No same piece upper bound. + Assert(!calculateFeePieceCoefficientsList.GroupBy(i => i.Value[0]).Any(g => g.Count() > 1), + "Piece upper bounds contains same elements."); + + var pieceUpperBounds = calculateFeePieceCoefficientsList.Select(l => l.Value[0]).ToList(); + var orderedEnumerable = pieceUpperBounds.OrderBy(i => i).ToList(); + for (var i = 0; i < calculateFeePieceCoefficientsList.Count; i++) + Assert(pieceUpperBounds[i] == orderedEnumerable[i], "Piece upper bounds not in order."); + } + + /// + /// Initialize coefficients of every type of tokens supporting charging fee. + /// Currently for acs1, charge primary token, like ELF; + /// for acs8, charge resource tokens including READ, STO, WRITE, TRAFFIC. + /// + public override Empty InitialCoefficients(Empty input) + { + Assert(State.AllCalculateFeeCoefficients.Value == null, "Coefficient already initialized"); + var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); + if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int)FeeTypeEnum.Read)) + allCalculateFeeCoefficients.Value.Add(GetReadFeeInitialCoefficient()); + if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int)FeeTypeEnum.Storage)) + allCalculateFeeCoefficients.Value.Add(GetStorageFeeInitialCoefficient()); + if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int)FeeTypeEnum.Write)) + allCalculateFeeCoefficients.Value.Add(GetWriteFeeInitialCoefficient()); + if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int)FeeTypeEnum.Traffic)) + allCalculateFeeCoefficients.Value.Add(GetTrafficFeeInitialCoefficient()); + if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int)FeeTypeEnum.Tx)) + allCalculateFeeCoefficients.Value.Add(GetTxFeeInitialCoefficient()); + State.AllCalculateFeeCoefficients.Value = allCalculateFeeCoefficients; - /// - /// Initialize coefficients of every type of tokens supporting charging fee. - /// Currently for acs1, charge primary token, like ELF; - /// for acs8, charge resource tokens including READ, STO, WRITE, TRAFFIC. - /// - public override Empty InitialCoefficients(Empty input) + Context.Fire(new CalculateFeeAlgorithmUpdated { - Assert(State.AllCalculateFeeCoefficients.Value == null, "Coefficient already initialized"); - var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); - if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int) FeeTypeEnum.Read)) - allCalculateFeeCoefficients.Value.Add(GetReadFeeInitialCoefficient()); - if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int) FeeTypeEnum.Storage)) - allCalculateFeeCoefficients.Value.Add(GetStorageFeeInitialCoefficient()); - if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int) FeeTypeEnum.Write)) - allCalculateFeeCoefficients.Value.Add(GetWriteFeeInitialCoefficient()); - if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int) FeeTypeEnum.Traffic)) - allCalculateFeeCoefficients.Value.Add(GetTrafficFeeInitialCoefficient()); - if (allCalculateFeeCoefficients.Value.All(x => x.FeeTokenType != (int) FeeTypeEnum.Tx)) - allCalculateFeeCoefficients.Value.Add(GetTxFeeInitialCoefficient()); - State.AllCalculateFeeCoefficients.Value = allCalculateFeeCoefficients; + AllTypeFeeCoefficients = allCalculateFeeCoefficients + }); - Context.Fire(new CalculateFeeAlgorithmUpdated - { - AllTypeFeeCoefficients = allCalculateFeeCoefficients, - }); - - return new Empty(); - } + return new Empty(); + } - private CalculateFeeCoefficients GetReadFeeInitialCoefficient() + private CalculateFeeCoefficients GetReadFeeInitialCoefficient() + { + return new CalculateFeeCoefficients { - return new CalculateFeeCoefficients + FeeTokenType = (int)FeeTypeEnum.Read, + PieceCoefficientsList = { - FeeTokenType = (int) FeeTypeEnum.Read, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients + // Interval [0, 10]: x/8 + 1 / 100000 + Value = { - // Interval [0, 10]: x/8 + 1 / 100000 - Value = - { - 10, - 1, 1, 8, - 0, 1, 100000 - } - }, - new CalculateFeePieceCoefficients + 10, + 1, 1, 8, + 0, 1, 100000 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (10, 100]: x/4 + Value = { - // Interval (10, 100]: x/4 - Value = - { - 100, - 1, 1, 4 - } - }, - new CalculateFeePieceCoefficients + 100, + 1, 1, 4 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (100, +∞): 25 / 16 * x^2 + x / 4 + Value = { - // Interval (100, +∞): 25 / 16 * x^2 + x / 4 - Value = - { - int.MaxValue, - 2, 25, 16, - 1, 1, 4 - } + int.MaxValue, + 2, 25, 16, + 1, 1, 4 } } - }; - } + } + }; + } - private CalculateFeeCoefficients GetStorageFeeInitialCoefficient() + private CalculateFeeCoefficients GetStorageFeeInitialCoefficient() + { + return new CalculateFeeCoefficients { - return new CalculateFeeCoefficients + FeeTokenType = (int)FeeTypeEnum.Storage, + PieceCoefficientsList = { - FeeTokenType = (int) FeeTypeEnum.Storage, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients + // Interval [0, 1000000]: x / 4 + 1 / 100000 + Value = { - // Interval [0, 1000000]: x / 4 + 1 / 100000 - Value = - { - 1000000, - 1, 1, 4, - 0, 1, 100000 - } - }, - new CalculateFeePieceCoefficients + 1000000, + 1, 1, 4, + 0, 1, 100000 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (1000000, +∞): x ^ 2 / 20000 + x / 64 + Value = { - // Interval (1000000, +∞): x ^ 2 / 20000 + x / 64 - Value = - { - int.MaxValue, - 2, 1, 20000, - 1, 1, 64 - } + int.MaxValue, + 2, 1, 20000, + 1, 1, 64 } } - }; - } + } + }; + } - private CalculateFeeCoefficients GetWriteFeeInitialCoefficient() + private CalculateFeeCoefficients GetWriteFeeInitialCoefficient() + { + return new CalculateFeeCoefficients { - return new CalculateFeeCoefficients + FeeTokenType = (int)FeeTypeEnum.Write, + PieceCoefficientsList = { - FeeTokenType = (int) FeeTypeEnum.Write, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients + // Interval [0, 10]: x / 8 + 1 / 10000 + Value = { - // Interval [0, 10]: x / 8 + 1 / 10000 - Value = - { - 10, - 1, 1, 8, - 0, 1, 10000 - } - }, - new CalculateFeePieceCoefficients + 10, + 1, 1, 8, + 0, 1, 10000 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (10, 100]: x / 4 + Value = { - // Interval (10, 100]: x / 4 - Value = - { - 100, - 1, 1, 4 - } - }, - new CalculateFeePieceCoefficients + 100, + 1, 1, 4 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (100, +∞): x / 4 + x^2 * 25 / 16 + Value = { - // Interval (100, +∞): x / 4 + x^2 * 25 / 16 - Value = - { - int.MaxValue, - 1, 1, 4, - 2, 25, 16 - } + int.MaxValue, + 1, 1, 4, + 2, 25, 16 } } - }; - } + } + }; + } - private CalculateFeeCoefficients GetTrafficFeeInitialCoefficient() + private CalculateFeeCoefficients GetTrafficFeeInitialCoefficient() + { + return new CalculateFeeCoefficients { - return new CalculateFeeCoefficients + FeeTokenType = (int)FeeTypeEnum.Traffic, + PieceCoefficientsList = { - FeeTokenType = (int) FeeTypeEnum.Traffic, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients + // Interval [0, 1000000]: x / 64 + 1 / 10000 + Value = { - // Interval [0, 1000000]: x / 64 + 1 / 10000 - Value = - { - 1000000, - 1, 1, 64, - 0, 1, 10000 - } - }, - new CalculateFeePieceCoefficients + 1000000, + 1, 1, 64, + 0, 1, 10000 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (1000000, +∞): x / 64 + x^2 / 20000 + Value = { - // Interval (1000000, +∞): x / 64 + x^2 / 20000 - Value = - { - int.MaxValue, - 1, 1, 64, - 2, 1, 20000 - } + int.MaxValue, + 1, 1, 64, + 2, 1, 20000 } } - }; - } + } + }; + } - private CalculateFeeCoefficients GetTxFeeInitialCoefficient() + private CalculateFeeCoefficients GetTxFeeInitialCoefficient() + { + return new CalculateFeeCoefficients { - return new CalculateFeeCoefficients + FeeTokenType = (int)FeeTypeEnum.Tx, + PieceCoefficientsList = { - FeeTokenType = (int) FeeTypeEnum.Tx, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients + // Interval [0, 1000000]: x / 800 + 1 / 10000 + Value = { - // Interval [0, 1000000]: x / 800 + 1 / 10000 - Value = - { - 1000000, - 1, 1, 800, - 0, 1, 10000 - } - }, - new CalculateFeePieceCoefficients + 1000000, + 1, 1, 800, + 0, 1, 10000 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (1000000, 5000000): x / 80 + Value = { - // Interval (1000000, 5000000): x / 80 - Value = - { - 5000000, - 1, 1, 80, - } - }, - new CalculateFeePieceCoefficients + 5000000, + 1, 1, 80 + } + }, + new CalculateFeePieceCoefficients + { + // Interval (5000000, ∞): x / 80 + x^2 / 100000 + Value = { - // Interval (5000000, ∞): x / 80 + x^2 / 100000 - Value = - { - int.MaxValue, - 1, 1, 80, - 2, 1, 100000 - } - }, + int.MaxValue, + 1, 1, 80, + 2, 1, 100000 + } } - }; - } + } + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index f9fa9e8baa..eebe7188ce 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1,714 +1,642 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS1; -using AElf.Standards.ACS10; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + /// + /// Related transactions will be generated by acs1 pre-plugin service, + /// and will be executed before the origin transaction. + /// + /// + /// + public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransactionFeesInput input) { - /// - /// Related transactions will be generated by acs1 pre-plugin service, - /// and will be executed before the origin transaction. - /// - /// - /// - public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransactionFeesInput input) + AssertTransactionGeneratedByPlugin(); + Assert(input.MethodName != null && input.ContractAddress != null, "Invalid charge transaction fees input."); + + // Primary token not created yet. + if (State.ChainPrimaryTokenSymbol.Value == null) return new ChargeTransactionFeesOutput { Success = true }; + + // Record tx fee bill during current charging process. + var bill = new TransactionFeeBill(); + + var fromAddress = Context.Sender; + var methodFees = Context.Call(input.ContractAddress, nameof(GetMethodFee), + new StringValue { Value = input.MethodName }); + var successToChargeBaseFee = true; + if (methodFees != null && methodFees.Fees.Any()) + // If base fee is set before, charge base fee. + successToChargeBaseFee = ChargeBaseFee(GetBaseFeeDictionary(methodFees), ref bill); + + var successToChargeSizeFee = true; + if (methodFees != null && !methodFees.IsSizeFeeFree) + // If IsSizeFeeFree == true, do not charge size fee. + successToChargeSizeFee = ChargeSizeFee(input, ref bill); + + // Update balances. + foreach (var tokenToAmount in bill.FeesMap) { - AssertTransactionGeneratedByPlugin(); - Assert(input.MethodName != null && input.ContractAddress != null, "Invalid charge transaction fees input."); - - // Primary token not created yet. - if (State.ChainPrimaryTokenSymbol.Value == null) + ModifyBalance(fromAddress, tokenToAmount.Key, -tokenToAmount.Value); + Context.Fire(new TransactionFeeCharged { - return new ChargeTransactionFeesOutput {Success = true}; - } - - // Record tx fee bill during current charging process. - var bill = new TransactionFeeBill(); - - var fromAddress = Context.Sender; - var methodFees = Context.Call(input.ContractAddress, nameof(GetMethodFee), - new StringValue {Value = input.MethodName}); - var successToChargeBaseFee = true; - if (methodFees != null && methodFees.Fees.Any()) - { - // If base fee is set before, charge base fee. - successToChargeBaseFee = ChargeBaseFee(GetBaseFeeDictionary(methodFees), ref bill); - } + Symbol = tokenToAmount.Key, + Amount = tokenToAmount.Value + }); + if (tokenToAmount.Value == 0) + Context.LogDebug(() => $"Maybe incorrect charged tx fee of {tokenToAmount.Key}: it's 0."); + } - var successToChargeSizeFee = true; - if (methodFees != null && !methodFees.IsSizeFeeFree) - { - // If IsSizeFeeFree == true, do not charge size fee. - successToChargeSizeFee = ChargeSizeFee(input, ref bill); - } + var chargingResult = successToChargeBaseFee && successToChargeSizeFee; + var chargingOutput = new ChargeTransactionFeesOutput { Success = chargingResult }; + if (!chargingResult) + chargingOutput.ChargingInformation = "Transaction fee not enough."; + return chargingOutput; + } - // Update balances. - foreach (var tokenToAmount in bill.FeesMap) - { - ModifyBalance(fromAddress, tokenToAmount.Key, -tokenToAmount.Value); - Context.Fire(new TransactionFeeCharged - { - Symbol = tokenToAmount.Key, - Amount = tokenToAmount.Value - }); - if (tokenToAmount.Value == 0) - { - Context.LogDebug(() => $"Maybe incorrect charged tx fee of {tokenToAmount.Key}: it's 0."); - } - } + private Dictionary GetBaseFeeDictionary(MethodFees methodFees) + { + var dict = new Dictionary(); + foreach (var methodFee in methodFees.Fees) + if (dict.ContainsKey(methodFee.Symbol)) + dict[methodFee.Symbol] = dict[methodFee.Symbol].Add(methodFee.BasicFee); + else + dict[methodFee.Symbol] = methodFee.BasicFee; - var chargingResult = successToChargeBaseFee && successToChargeSizeFee; - var chargingOutput = new ChargeTransactionFeesOutput {Success = chargingResult}; - if (!chargingResult) - chargingOutput.ChargingInformation = "Transaction fee not enough."; - return chargingOutput; - } + return dict; + } - private Dictionary GetBaseFeeDictionary(MethodFees methodFees) + private bool ChargeBaseFee(Dictionary methodFeeMap, ref TransactionFeeBill bill) + { + if (!ChargeFirstSufficientToken(methodFeeMap, out var symbolToChargeBaseFee, + out var amountToChargeBaseFee, out var existingBalance)) { - var dict = new Dictionary(); - foreach (var methodFee in methodFees.Fees) - { - if (dict.ContainsKey(methodFee.Symbol)) - { - dict[methodFee.Symbol] = dict[methodFee.Symbol].Add(methodFee.BasicFee); - } - else - { - dict[methodFee.Symbol] = methodFee.BasicFee; - } - } + Context.LogDebug(() => "Failed to charge first sufficient token."); + if (symbolToChargeBaseFee != null) bill.FeesMap.Add(symbolToChargeBaseFee, existingBalance); - return dict; + return false; } - private bool ChargeBaseFee(Dictionary methodFeeMap, ref TransactionFeeBill bill) - { - if (!ChargeFirstSufficientToken(methodFeeMap, out var symbolToChargeBaseFee, - out var amountToChargeBaseFee, out var existingBalance)) - { - Context.LogDebug(() => "Failed to charge first sufficient token."); - if (symbolToChargeBaseFee != null) - { - bill.FeesMap.Add(symbolToChargeBaseFee, existingBalance); - } // If symbol == null, then charge nothing in base fee part. - - return false; - } + bill.FeesMap.Add(symbolToChargeBaseFee, amountToChargeBaseFee); - bill.FeesMap.Add(symbolToChargeBaseFee, amountToChargeBaseFee); + return true; + } - return true; + private bool ChargeSizeFee(ChargeTransactionFeesInput input, ref TransactionFeeBill bill) + { + string symbolChargedForBaseFee = null; + var amountChargedForBaseFee = 0L; + var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; + if (bill.FeesMap.Any()) + { + symbolChargedForBaseFee = bill.FeesMap.First().Key; + amountChargedForBaseFee = bill.FeesMap.First().Value; } - private bool ChargeSizeFee(ChargeTransactionFeesInput input, ref TransactionFeeBill bill) + var availableBalance = symbolChargedForBaseFee == symbolToPayTxFee + // Available balance need to deduct amountChargedForBaseFee + ? GetBalance(Context.Sender, symbolToPayTxFee).Sub(amountChargedForBaseFee) + : GetBalance(Context.Sender, symbolToPayTxFee); + var txSizeFeeAmount = input.TransactionSizeFee; + + if (input.SymbolsToPayTxSizeFee.Any()) { - string symbolChargedForBaseFee = null; - var amountChargedForBaseFee = 0L; - var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; - if (bill.FeesMap.Any()) - { - symbolChargedForBaseFee = bill.FeesMap.First().Key; - amountChargedForBaseFee = bill.FeesMap.First().Value; + var allSymbolToTxFee = input.SymbolsToPayTxSizeFee; + var availableSymbol = allSymbolToTxFee.FirstOrDefault(x => + GetBalanceCalculatedBaseOnPrimaryToken(x, symbolChargedForBaseFee, + amountChargedForBaseFee) >= txSizeFeeAmount) ?? + allSymbolToTxFee.FirstOrDefault(x => + GetBalanceCalculatedBaseOnPrimaryToken(x, symbolChargedForBaseFee, + amountChargedForBaseFee) > 0); + if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) + { + symbolToPayTxFee = availableSymbol.TokenSymbol; + txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) + .Div(availableSymbol.BaseTokenWeight); + availableBalance = symbolChargedForBaseFee == symbolToPayTxFee + ? GetBalance(Context.Sender, symbolToPayTxFee).Sub(amountChargedForBaseFee) + : GetBalance(Context.Sender, symbolToPayTxFee); } + } - var availableBalance = symbolChargedForBaseFee == symbolToPayTxFee - // Available balance need to deduct amountChargedForBaseFee - ? GetBalance(Context.Sender, symbolToPayTxFee).Sub(amountChargedForBaseFee) - : GetBalance(Context.Sender, symbolToPayTxFee); - var txSizeFeeAmount = input.TransactionSizeFee; + var chargeAmount = availableBalance > txSizeFeeAmount + ? txSizeFeeAmount + : availableBalance; - if (input.SymbolsToPayTxSizeFee.Any()) - { - var allSymbolToTxFee = input.SymbolsToPayTxSizeFee; - var availableSymbol = allSymbolToTxFee.FirstOrDefault(x => - GetBalanceCalculatedBaseOnPrimaryToken(x, symbolChargedForBaseFee, - amountChargedForBaseFee) >= txSizeFeeAmount) ?? - allSymbolToTxFee.FirstOrDefault(x => - GetBalanceCalculatedBaseOnPrimaryToken(x, symbolChargedForBaseFee, - amountChargedForBaseFee) > 0); - if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) - { - symbolToPayTxFee = availableSymbol.TokenSymbol; - txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) - .Div(availableSymbol.BaseTokenWeight); - availableBalance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetBalance(Context.Sender, symbolToPayTxFee).Sub(amountChargedForBaseFee) - : GetBalance(Context.Sender, symbolToPayTxFee); - } - } + if (symbolToPayTxFee == null) return availableBalance >= txSizeFeeAmount; - var chargeAmount = availableBalance > txSizeFeeAmount - ? txSizeFeeAmount - : availableBalance; + if (symbolChargedForBaseFee == symbolToPayTxFee) + bill.FeesMap[symbolToPayTxFee] = + bill.FeesMap[symbolToPayTxFee].Add(chargeAmount); + else + bill.FeesMap.Add(symbolToPayTxFee, chargeAmount); - if (symbolToPayTxFee == null) return availableBalance >= txSizeFeeAmount; + return availableBalance >= txSizeFeeAmount; + } - if (symbolChargedForBaseFee == symbolToPayTxFee) - { - bill.FeesMap[symbolToPayTxFee] = - bill.FeesMap[symbolToPayTxFee].Add(chargeAmount); - } - else - { - bill.FeesMap.Add(symbolToPayTxFee, chargeAmount); - } + public override Empty ChargeResourceToken(ChargeResourceTokenInput input) + { + AssertTransactionGeneratedByPlugin(); + Context.LogDebug(() => $"Start executing ChargeResourceToken.{input}"); + if (input.Equals(new ChargeResourceTokenInput())) return new Empty(); - return availableBalance >= txSizeFeeAmount; + var bill = new TransactionFeeBill(); + foreach (var pair in input.CostDic) + { + Context.LogDebug(() => $"Charging {pair.Value} {pair.Key} tokens."); + var existingBalance = GetBalance(Context.Sender, pair.Key); + Assert(existingBalance >= pair.Value, + $"Insufficient resource of {pair.Key}. Need balance: {pair.Value}; Current balance: {existingBalance}."); + bill.FeesMap.Add(pair.Key, pair.Value); } - public override Empty ChargeResourceToken(ChargeResourceTokenInput input) + foreach (var pair in bill.FeesMap) { - AssertTransactionGeneratedByPlugin(); - Context.LogDebug(() => $"Start executing ChargeResourceToken.{input}"); - if (input.Equals(new ChargeResourceTokenInput())) - { - return new Empty(); - } - - var bill = new TransactionFeeBill(); - foreach (var pair in input.CostDic) + Context.Fire(new ResourceTokenCharged { - Context.LogDebug(() => $"Charging {pair.Value} {pair.Key} tokens."); - var existingBalance = GetBalance(Context.Sender, pair.Key); - Assert(existingBalance >= pair.Value, - $"Insufficient resource of {pair.Key}. Need balance: {pair.Value}; Current balance: {existingBalance}."); - bill.FeesMap.Add(pair.Key, pair.Value); - } + Symbol = pair.Key, + Amount = pair.Value, + ContractAddress = Context.Sender + }); + if (pair.Value == 0) Context.LogDebug(() => $"Maybe incorrect charged resource fee of {pair.Key}: it's 0."); + } - foreach (var pair in bill.FeesMap) - { - Context.Fire(new ResourceTokenCharged - { - Symbol = pair.Key, - Amount = pair.Value, - ContractAddress = Context.Sender - }); - if (pair.Value == 0) - { - Context.LogDebug(() => $"Maybe incorrect charged resource fee of {pair.Key}: it's 0."); - } - } + return new Empty(); + } - return new Empty(); + public override Empty CheckResourceToken(Empty input) + { + AssertTransactionGeneratedByPlugin(); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName)) + { + var balance = GetBalance(Context.Sender, symbol); + var owningBalance = State.OwningResourceToken[Context.Sender][symbol]; + Assert(balance > owningBalance, + $"Contract balance of {symbol} token is not enough. Owning {owningBalance}."); } - public override Empty CheckResourceToken(Empty input) + return new Empty(); + } + + public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) + { + AssertControllerForSymbolToPayTxSizeFee(); + if (input == null) + throw new AssertionException("invalid input"); + var isPrimaryTokenExist = false; + var symbolList = new List(); + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()); + var primaryTokenInfo = State.TokenInfos[primaryTokenSymbol.Value]; + Assert(!string.IsNullOrEmpty(primaryTokenSymbol.Value), "primary token does not exist"); + foreach (var tokenWeightInfo in input.SymbolsToPayTxSizeFee) { - AssertTransactionGeneratedByPlugin(); - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName)) + if (tokenWeightInfo.TokenSymbol == primaryTokenSymbol.Value) { - var balance = GetBalance(Context.Sender, symbol); - var owningBalance = State.OwningResourceToken[Context.Sender][symbol]; - Assert(balance > owningBalance, - $"Contract balance of {symbol} token is not enough. Owning {owningBalance}."); + isPrimaryTokenExist = true; + Assert(tokenWeightInfo.AddedTokenWeight == 1 && tokenWeightInfo.BaseTokenWeight == 1, + $"symbol:{tokenWeightInfo.TokenSymbol} weight should be 1"); } - return new Empty(); + Assert(tokenWeightInfo.AddedTokenWeight > 0 && tokenWeightInfo.BaseTokenWeight > 0, + $"symbol:{tokenWeightInfo.TokenSymbol} weight should be greater than 0"); + Assert(!symbolList.Contains(tokenWeightInfo.TokenSymbol), + $"symbol:{tokenWeightInfo.TokenSymbol} repeat"); + AssertSymbolToPayTxFeeIsValid(tokenWeightInfo.TokenSymbol, out var addedTokenTotalSupply); + symbolList.Add(tokenWeightInfo.TokenSymbol); } - public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) + Assert(isPrimaryTokenExist, $"primary token:{primaryTokenSymbol.Value} not included"); + State.SymbolListToPayTxSizeFee.Value = input; + Context.Fire(new ExtraTokenListModified { - AssertControllerForSymbolToPayTxSizeFee(); - if (input == null) - throw new AssertionException("invalid input"); - var isPrimaryTokenExist = false; - var symbolList = new List(); - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()); - var primaryTokenInfo = State.TokenInfos[primaryTokenSymbol.Value]; - Assert(!string.IsNullOrEmpty(primaryTokenSymbol.Value), "primary token does not exist"); - foreach (var tokenWeightInfo in input.SymbolsToPayTxSizeFee) - { - if (tokenWeightInfo.TokenSymbol == primaryTokenSymbol.Value) - { - isPrimaryTokenExist = true; - Assert(tokenWeightInfo.AddedTokenWeight == 1 && tokenWeightInfo.BaseTokenWeight == 1, - $"symbol:{tokenWeightInfo.TokenSymbol} weight should be 1"); - } + SymbolListToPayTxSizeFee = input + }); + return new Empty(); + } - Assert(tokenWeightInfo.AddedTokenWeight > 0 && tokenWeightInfo.BaseTokenWeight > 0, - $"symbol:{tokenWeightInfo.TokenSymbol} weight should be greater than 0"); - Assert(!symbolList.Contains(tokenWeightInfo.TokenSymbol), - $"symbol:{tokenWeightInfo.TokenSymbol} repeat"); - AssertSymbolToPayTxFeeIsValid(tokenWeightInfo.TokenSymbol, out var addedTokenTotalSupply); - symbolList.Add(tokenWeightInfo.TokenSymbol); - } + /// + /// Example 1: + /// symbolToAmountMap: {{"ELF", 10}, {"TSA", 1}, {"TSB", 2}} + /// [Charge successful] + /// Sender's balance: + /// ELF - 9 + /// TSA - 0 + /// TSB - 3 + /// Then charge 2 TSBs. + /// [Charge failed] + /// Sender's balance: + /// ELF - 9 + /// TSA - 0 + /// TSB - 1 + /// Then charge 9 ELFs + /// Example 2: + /// symbolToAmountMap: {{"TSA", 1}, {"TSB", 2}} + /// which means the charging token symbol list doesn't contain the native symbol. + /// [Charge successful] + /// Sender's balance: + /// ELF - 1 + /// TSA - 2 + /// TSB - 2 + /// Then charge 1 TSA + /// [Charge failed] + /// Sender's balance: + /// ELF - 1 + /// TSA - 0 + /// TSB - 1 + /// Then charge 1 TSB + /// [Charge failed] + /// Sender's balance: + /// ELF - 1000000000 + /// TSA - 0 + /// TSB - 0 + /// Then charge nothing. + /// (Contract developer should be suggested to implement acs5 to check certain balance or allowance of sender.) + /// + /// + /// + /// + /// + /// + private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, out string symbol, + out long amount, out long existingBalance) + { + symbol = null; + amount = 0L; + existingBalance = 0L; + var fromAddress = Context.Sender; + string symbolOfValidBalance = null; + + // Traverse available token symbols, check balance one by one + // until there's balance of one certain token is enough to pay the fee. + foreach (var symbolToAmount in symbolToAmountMap) + { + existingBalance = GetBalance(fromAddress, symbolToAmount.Key); + symbol = symbolToAmount.Key; + amount = symbolToAmount.Value; - Assert(isPrimaryTokenExist, $"primary token:{primaryTokenSymbol.Value} not included"); - State.SymbolListToPayTxSizeFee.Value = input; - Context.Fire(new ExtraTokenListModified - { - SymbolListToPayTxSizeFee = input - }); - return new Empty(); + if (existingBalance > 0) symbolOfValidBalance = symbol; + + if (existingBalance >= amount) break; } - /// - /// Example 1: - /// symbolToAmountMap: {{"ELF", 10}, {"TSA", 1}, {"TSB", 2}} - /// - /// [Charge successful] - /// Sender's balance: - /// ELF - 9 - /// TSA - 0 - /// TSB - 3 - /// Then charge 2 TSBs. - /// - /// [Charge failed] - /// Sender's balance: - /// ELF - 9 - /// TSA - 0 - /// TSB - 1 - /// Then charge 9 ELFs - /// - /// Example 2: - /// symbolToAmountMap: {{"TSA", 1}, {"TSB", 2}} - /// which means the charging token symbol list doesn't contain the native symbol. - /// - /// [Charge successful] - /// Sender's balance: - /// ELF - 1 - /// TSA - 2 - /// TSB - 2 - /// Then charge 1 TSA - /// - /// [Charge failed] - /// Sender's balance: - /// ELF - 1 - /// TSA - 0 - /// TSB - 1 - /// Then charge 1 TSB - /// - /// [Charge failed] - /// Sender's balance: - /// ELF - 1000000000 - /// TSA - 0 - /// TSB - 0 - /// Then charge nothing. - /// (Contract developer should be suggested to implement acs5 to check certain balance or allowance of sender.) - /// - /// - /// - /// - /// - /// - private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, out string symbol, - out long amount, out long existingBalance) + if (existingBalance >= amount) return true; + + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + if (symbolToAmountMap.Keys.Contains(primaryTokenSymbol)) { - symbol = null; - amount = 0L; - existingBalance = 0L; - var fromAddress = Context.Sender; - string symbolOfValidBalance = null; - - // Traverse available token symbols, check balance one by one - // until there's balance of one certain token is enough to pay the fee. - foreach (var symbolToAmount in symbolToAmountMap) - { - existingBalance = GetBalance(fromAddress, symbolToAmount.Key); - symbol = symbolToAmount.Key; - amount = symbolToAmount.Value; + symbol = primaryTokenSymbol; + existingBalance = GetBalance(fromAddress, primaryTokenSymbol); + } + else + { + symbol = symbolOfValidBalance; + if (symbol != null) existingBalance = GetBalance(fromAddress, symbolOfValidBalance); + } - if (existingBalance > 0) - { - symbolOfValidBalance = symbol; - } + return false; + } - if (existingBalance >= amount) break; - } + public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) + { + AssertSenderIsCurrentMiner(); + var claimTransactionExecuteHeight = State.ClaimTransactionFeeExecuteHeight.Value; + + Assert(claimTransactionExecuteHeight < Context.CurrentHeight, + $"This method already executed in height {State.ClaimTransactionFeeExecuteHeight.Value}"); + State.ClaimTransactionFeeExecuteHeight.Value = Context.CurrentHeight; + Context.LogDebug(() => $"Claim transaction fee. {input}"); + State.LatestTotalTransactionFeesMapHash.Value = HashHelper.ComputeFrom(input); + foreach (var bill in input.Value) + { + var symbol = bill.Key; + var amount = bill.Value; + ModifyBalance(Context.Self, symbol, amount); + TransferTransactionFeesToFeeReceiver(symbol, amount); + } - if (existingBalance >= amount) return true; + Context.LogDebug(() => "Finish claim transaction fee."); - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (symbolToAmountMap.Keys.Contains(primaryTokenSymbol)) - { - symbol = primaryTokenSymbol; - existingBalance = GetBalance(fromAddress, primaryTokenSymbol); - } - else - { - symbol = symbolOfValidBalance; - if (symbol != null) - { - existingBalance = GetBalance(fromAddress, symbolOfValidBalance); - } - } + return new Empty(); + } - return false; - } + private void AssertSenderIsCurrentMiner() + { + if (State.ConsensusContract.Value == null) + State.ConsensusContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) - { - AssertSenderIsCurrentMiner(); - var claimTransactionExecuteHeight = State.ClaimTransactionFeeExecuteHeight.Value; - - Assert(claimTransactionExecuteHeight < Context.CurrentHeight, - $"This method already executed in height {State.ClaimTransactionFeeExecuteHeight.Value}"); - State.ClaimTransactionFeeExecuteHeight.Value = Context.CurrentHeight; - Context.LogDebug(() => $"Claim transaction fee. {input}"); - State.LatestTotalTransactionFeesMapHash.Value = HashHelper.ComputeFrom(input); - foreach (var bill in input.Value) - { - var symbol = bill.Key; - var amount = bill.Value; - ModifyBalance(Context.Self, symbol, amount); - TransferTransactionFeesToFeeReceiver(symbol, amount); - } + Assert(State.ConsensusContract.IsCurrentMiner.Call(Context.Sender).Value, "No permission."); + } - Context.LogDebug(() => "Finish claim transaction fee."); + public override Hash GetLatestTotalTransactionFeesMapHash(Empty input) + { + return State.LatestTotalTransactionFeesMapHash.Value; + } - return new Empty(); + public override Empty DonateResourceToken(TotalResourceTokensMaps input) + { + AssertSenderIsCurrentMiner(); + var donateResourceTokenExecuteHeight = State.DonateResourceTokenExecuteHeight.Value; + if (donateResourceTokenExecuteHeight == 0) donateResourceTokenExecuteHeight = Context.CurrentHeight; + + Assert(donateResourceTokenExecuteHeight == Context.CurrentHeight, + $"This method already executed in height {State.DonateResourceTokenExecuteHeight.Value}"); + State.DonateResourceTokenExecuteHeight.Value = donateResourceTokenExecuteHeight.Add(1); + Context.LogDebug(() => $"Start donate resource token. {input}"); + State.LatestTotalResourceTokensMapsHash.Value = HashHelper.ComputeFrom(input); + Context.LogDebug(() => + $"Now LatestTotalResourceTokensMapsHash is {State.LatestTotalResourceTokensMapsHash.Value}"); + + var isMainChain = true; + if (State.DividendPoolContract.Value == null) + { + var treasuryContractAddress = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + if (treasuryContractAddress == null) + isMainChain = false; + else + State.DividendPoolContract.Value = treasuryContractAddress; } - private void AssertSenderIsCurrentMiner() - { - if (State.ConsensusContract.Value == null) - { - State.ConsensusContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + PayResourceTokens(input, isMainChain); - Assert(State.ConsensusContract.IsCurrentMiner.Call(Context.Sender).Value, "No permission."); - } + if (!isMainChain) PayRental(); - public override Hash GetLatestTotalTransactionFeesMapHash(Empty input) - { - return State.LatestTotalTransactionFeesMapHash.Value; - } + return new Empty(); + } - public override Empty DonateResourceToken(TotalResourceTokensMaps input) + public override Hash GetLatestTotalResourceTokensMapsHash(Empty input) + { + return State.LatestTotalResourceTokensMapsHash.Value; + } + + private void PayResourceTokens(TotalResourceTokensMaps billMaps, bool isMainChain) + { + foreach (var bill in billMaps.Value) + foreach (var feeMap in bill.TokensMap.Value) { - AssertSenderIsCurrentMiner(); - var donateResourceTokenExecuteHeight = State.DonateResourceTokenExecuteHeight.Value; - if (donateResourceTokenExecuteHeight == 0) - { - donateResourceTokenExecuteHeight = Context.CurrentHeight; + var symbol = feeMap.Key; + var amount = feeMap.Value; + // Check balance in case of insufficient balance. + var existingBalance = GetBalance(bill.ContractAddress, symbol); + if (amount > existingBalance) + { + var owned = amount.Sub(existingBalance); + var currentOwning = State.OwningResourceToken[bill.ContractAddress][symbol].Add(owned); + State.OwningResourceToken[bill.ContractAddress][symbol] = currentOwning; + Context.Fire(new ResourceTokenOwned + { + Symbol = symbol, + Amount = currentOwning, + ContractAddress = bill.ContractAddress + }); + amount = existingBalance; } - Assert(donateResourceTokenExecuteHeight == Context.CurrentHeight, - $"This method already executed in height {State.DonateResourceTokenExecuteHeight.Value}"); - State.DonateResourceTokenExecuteHeight.Value = donateResourceTokenExecuteHeight.Add(1); - Context.LogDebug(() => $"Start donate resource token. {input}"); - State.LatestTotalResourceTokensMapsHash.Value = HashHelper.ComputeFrom(input); - Context.LogDebug(() => - $"Now LatestTotalResourceTokensMapsHash is {State.LatestTotalResourceTokensMapsHash.Value}"); - - var isMainChain = true; - if (State.DividendPoolContract.Value == null) + if (amount > 0) { - var treasuryContractAddress = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - if (treasuryContractAddress == null) + ModifyBalance(bill.ContractAddress, symbol, -amount); + if (isMainChain) { - isMainChain = false; + Context.LogDebug(() => $"Adding {amount} of {symbol}s to dividend pool."); + // Main Chain. + ModifyBalance(Context.Self, symbol, amount); + State.DividendPoolContract.Donate.Send(new DonateInput + { + Symbol = symbol, + Amount = amount + }); } else { - State.DividendPoolContract.Value = treasuryContractAddress; + Context.LogDebug(() => $"Adding {amount} of {symbol}s to consensus address account."); + // Side Chain + var consensusContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + ModifyBalance(consensusContractAddress, symbol, amount); } } - - PayResourceTokens(input, isMainChain); - - if (!isMainChain) - { - PayRental(); - } - - return new Empty(); - } - - public override Hash GetLatestTotalResourceTokensMapsHash(Empty input) - { - return State.LatestTotalResourceTokensMapsHash.Value; } + } - private void PayResourceTokens(TotalResourceTokensMaps billMaps, bool isMainChain) + private void PayRental() + { + var creator = State.SideChainCreator.Value; + if (creator == null) return; + if (State.LastPayRentTime.Value == null) { - foreach (var bill in billMaps.Value) - { - foreach (var feeMap in bill.TokensMap.Value) - { - var symbol = feeMap.Key; - var amount = feeMap.Value; - // Check balance in case of insufficient balance. - var existingBalance = GetBalance(bill.ContractAddress, symbol); - if (amount > existingBalance) - { - var owned = amount.Sub(existingBalance); - var currentOwning = State.OwningResourceToken[bill.ContractAddress][symbol].Add(owned); - State.OwningResourceToken[bill.ContractAddress][symbol] = currentOwning; - Context.Fire(new ResourceTokenOwned - { - Symbol = symbol, - Amount = currentOwning, - ContractAddress = bill.ContractAddress - }); - amount = existingBalance; - } - - if (amount > 0) - { - ModifyBalance(bill.ContractAddress, symbol, -amount); - if (isMainChain) - { - Context.LogDebug(() => $"Adding {amount} of {symbol}s to dividend pool."); - // Main Chain. - ModifyBalance(Context.Self, symbol, amount); - State.DividendPoolContract.Donate.Send(new DonateInput - { - Symbol = symbol, - Amount = amount - }); - } - else - { - Context.LogDebug(() => $"Adding {amount} of {symbol}s to consensus address account."); - // Side Chain - var consensusContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - ModifyBalance(consensusContractAddress, symbol, amount); - } - } - } - } + // Initial LastPayRentTime first calling DonateResourceToken. + State.LastPayRentTime.Value = Context.CurrentBlockTime; + return; } - private void PayRental() - { - var creator = State.SideChainCreator.Value; - if (creator == null) return; - if (State.LastPayRentTime.Value == null) - { - // Initial LastPayRentTime first calling DonateResourceToken. - State.LastPayRentTime.Value = Context.CurrentBlockTime; - return; - } - - // We need minutes. - var duration = (Context.CurrentBlockTime - State.LastPayRentTime.Value).Seconds.Div(60); - if (duration == 0) - { - return; - } - - // Update LastPayRentTime if it is ready to charge rental. - State.LastPayRentTime.Value += new Duration {Seconds = duration.Mul(60)}; + // We need minutes. + var duration = (Context.CurrentBlockTime - State.LastPayRentTime.Value).Seconds.Div(60); + if (duration == 0) return; - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) - { - var donates = 0L; + // Update LastPayRentTime if it is ready to charge rental. + State.LastPayRentTime.Value += new Duration { Seconds = duration.Mul(60) }; - var availableBalance = GetBalance(creator, symbol); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) + { + var donates = 0L; - // Try to update owning rental. - var owningRental = State.OwningRental[symbol]; - if (owningRental > 0) - { - // If Creator own this symbol and current balance can cover the debt, pay the debt at first. - if (availableBalance > owningRental) - { - donates = owningRental; - // Need to update available balance, - // cause existing balance not necessary equals to available balance. - availableBalance = availableBalance.Sub(owningRental); - State.OwningRental[symbol] = 0; - } - } + var availableBalance = GetBalance(creator, symbol); - var rental = duration.Mul(State.ResourceAmount[symbol]).Mul(State.Rental[symbol]); - if (availableBalance >= rental) // Success + // Try to update owning rental. + var owningRental = State.OwningRental[symbol]; + if (owningRental > 0) + // If Creator own this symbol and current balance can cover the debt, pay the debt at first. + if (availableBalance > owningRental) { - donates = donates.Add(rental); - ModifyBalance(creator, symbol, -donates); + donates = owningRental; + // Need to update available balance, + // cause existing balance not necessary equals to available balance. + availableBalance = availableBalance.Sub(owningRental); + State.OwningRental[symbol] = 0; } - else // Fail - { - // Donate all existing balance. Directly reset the donates. - donates = GetBalance(creator, symbol); - State.Balances[creator][symbol] = 0; - // Update owning rental to record a new debt. - var own = rental.Sub(availableBalance); - State.OwningRental[symbol] = State.OwningRental[symbol].Add(own); - - Context.Fire(new RentalAccountBalanceInsufficient - { - Symbol = symbol, - Amount = own - }); - } + var rental = duration.Mul(State.ResourceAmount[symbol]).Mul(State.Rental[symbol]); + if (availableBalance >= rental) // Success + { + donates = donates.Add(rental); + ModifyBalance(creator, symbol, -donates); + } + else // Fail + { + // Donate all existing balance. Directly reset the donates. + donates = GetBalance(creator, symbol); + State.Balances[creator][symbol] = 0; - // Side Chain donates. - var consensusContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - ModifyBalance(consensusContractAddress, symbol, donates); + // Update owning rental to record a new debt. + var own = rental.Sub(availableBalance); + State.OwningRental[symbol] = State.OwningRental[symbol].Add(own); - Context.Fire(new RentalCharged() + Context.Fire(new RentalAccountBalanceInsufficient { Symbol = symbol, - Amount = donates + Amount = own }); } - } - public override Empty UpdateRental(UpdateRentalInput input) - { - AssertControllerForSideChainRental(); - foreach (var pair in input.Rental) - { - Assert( - Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName).Contains(pair.Key), - "Invalid symbol."); - Assert(pair.Value >= 0, "Invalid amount."); - State.Rental[pair.Key] = pair.Value; - } + // Side Chain donates. + var consensusContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + ModifyBalance(consensusContractAddress, symbol, donates); - return new Empty(); + Context.Fire(new RentalCharged + { + Symbol = symbol, + Amount = donates + }); } + } - public override Empty UpdateRentedResources(UpdateRentedResourcesInput input) + public override Empty UpdateRental(UpdateRentalInput input) + { + AssertControllerForSideChainRental(); + foreach (var pair in input.Rental) { - AssertControllerForSideChainRental(); - foreach (var pair in input.ResourceAmount) - { - Assert( - Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName).Contains(pair.Key), - "Invalid symbol."); - Assert(pair.Value >= 0, "Invalid amount."); - State.ResourceAmount[pair.Key] = pair.Value; - } - - return new Empty(); + Assert( + Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName).Contains(pair.Key), + "Invalid symbol."); + Assert(pair.Value >= 0, "Invalid amount."); + State.Rental[pair.Key] = pair.Value; } - private void SetSideChainCreator(Address input) - { - Assert(State.SideChainCreator.Value == null, "Creator already set."); - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } + return new Empty(); + } - Assert(Context.Sender == Context.GetZeroSmartContractAddress() || - Context.Sender == State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - "No permission."); - State.SideChainCreator.Value = input; + public override Empty UpdateRentedResources(UpdateRentedResourcesInput input) + { + AssertControllerForSideChainRental(); + foreach (var pair in input.ResourceAmount) + { + Assert( + Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName).Contains(pair.Key), + "Invalid symbol."); + Assert(pair.Value >= 0, "Invalid amount."); + State.ResourceAmount[pair.Key] = pair.Value; } - /// - /// Burn 10% of tx fees. - /// If Side Chain didn't set FeeReceiver, burn all. - /// - /// - /// - private void TransferTransactionFeesToFeeReceiver(string symbol, long totalAmount) - { - Context.LogDebug(() => "Transfer transaction fee to receiver."); + return new Empty(); + } - if (totalAmount <= 0) return; + private void SetSideChainCreator(Address input) + { + Assert(State.SideChainCreator.Value == null, "Creator already set."); + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + + Assert(Context.Sender == Context.GetZeroSmartContractAddress() || + Context.Sender == State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + "No permission."); + State.SideChainCreator.Value = input; + } - var tokenInfo = State.TokenInfos[symbol]; - if (!tokenInfo.IsBurnable) - { - return; - } + /// + /// Burn 10% of tx fees. + /// If Side Chain didn't set FeeReceiver, burn all. + /// + /// + /// + private void TransferTransactionFeesToFeeReceiver(string symbol, long totalAmount) + { + Context.LogDebug(() => "Transfer transaction fee to receiver."); - var burnAmount = totalAmount.Div(10); - if (burnAmount > 0) - Context.SendInline(Context.Self, nameof(Burn), new BurnInput - { - Symbol = symbol, - Amount = burnAmount - }); + if (totalAmount <= 0) return; - var transferAmount = totalAmount.Sub(burnAmount); - if (transferAmount == 0) - return; - var treasuryContractAddress = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - var isMainChain = treasuryContractAddress != null; - if (isMainChain) + var tokenInfo = State.TokenInfos[symbol]; + if (!tokenInfo.IsBurnable) return; + + var burnAmount = totalAmount.Div(10); + if (burnAmount > 0) + Context.SendInline(Context.Self, nameof(Burn), new BurnInput + { + Symbol = symbol, + Amount = burnAmount + }); + + var transferAmount = totalAmount.Sub(burnAmount); + if (transferAmount == 0) + return; + var treasuryContractAddress = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + var isMainChain = treasuryContractAddress != null; + if (isMainChain) + { + // Main chain would donate tx fees to dividend pool. + if (State.DividendPoolContract.Value == null) + State.DividendPoolContract.Value = treasuryContractAddress; + State.Allowances[Context.Self][State.DividendPoolContract.Value][symbol] = + State.Allowances[Context.Self][State.DividendPoolContract.Value][symbol].Add(transferAmount); + State.DividendPoolContract.Donate.Send(new DonateInput { - // Main chain would donate tx fees to dividend pool. - if (State.DividendPoolContract.Value == null) - State.DividendPoolContract.Value = treasuryContractAddress; - State.Allowances[Context.Self][State.DividendPoolContract.Value][symbol] = - State.Allowances[Context.Self][State.DividendPoolContract.Value][symbol].Add(transferAmount); - State.DividendPoolContract.Donate.Send(new DonateInput + Symbol = symbol, + Amount = transferAmount + }); + } + else + { + if (State.FeeReceiver.Value != null) + Context.SendInline(Context.Self, nameof(Transfer), new TransferInput { + To = State.FeeReceiver.Value, Symbol = symbol, Amount = transferAmount }); - } else - { - if (State.FeeReceiver.Value != null) - { - Context.SendInline(Context.Self, nameof(Transfer), new TransferInput - { - To = State.FeeReceiver.Value, - Symbol = symbol, - Amount = transferAmount, - }); - } - else + // Burn all! + Context.SendInline(Context.Self, nameof(Burn), new BurnInput { - // Burn all! - Context.SendInline(Context.Self, nameof(Burn), new BurnInput - { - Symbol = symbol, - Amount = transferAmount - }); - } - } + Symbol = symbol, + Amount = transferAmount + }); } + } - public override Empty SetFeeReceiver(Address input) - { - Assert(State.SideChainCreator.Value == Context.Sender, "No permission."); - State.FeeReceiver.Value = input; - return new Empty(); - } + public override Empty SetFeeReceiver(Address input) + { + Assert(State.SideChainCreator.Value == Context.Sender, "No permission."); + State.FeeReceiver.Value = input; + return new Empty(); + } - public override Address GetFeeReceiver(Empty input) - { - return State.FeeReceiver.Value; - } + public override Address GetFeeReceiver(Empty input) + { + return State.FeeReceiver.Value; + } - private long GetBalanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, string baseSymbol, - long cost) - { - var availableBalance = GetBalance(Context.Sender, tokenInfo.TokenSymbol); - if (tokenInfo.TokenSymbol == baseSymbol) - availableBalance -= cost; - return availableBalance.Mul(tokenInfo.BaseTokenWeight) - .Div(tokenInfo.AddedTokenWeight); - } + private long GetBalanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, string baseSymbol, + long cost) + { + var availableBalance = GetBalance(Context.Sender, tokenInfo.TokenSymbol); + if (tokenInfo.TokenSymbol == baseSymbol) + availableBalance -= cost; + return availableBalance.Mul(tokenInfo.BaseTokenWeight) + .Div(tokenInfo.AddedTokenWeight); + } - private void AssertSymbolToPayTxFeeIsValid(string tokenSymbol, out long totalSupply) - { - var tokenInfo = State.TokenInfos[tokenSymbol]; - if (tokenInfo == null) - { - throw new AssertionException($"Token is not found. {tokenSymbol}"); - } + private void AssertSymbolToPayTxFeeIsValid(string tokenSymbol, out long totalSupply) + { + var tokenInfo = State.TokenInfos[tokenSymbol]; + if (tokenInfo == null) throw new AssertionException($"Token is not found. {tokenSymbol}"); - Assert(IsTokenAvailableForMethodFee(tokenSymbol), $"Token {tokenSymbol} cannot set as method fee."); - totalSupply = tokenInfo.TotalSupply; - } + Assert(IsTokenAvailableForMethodFee(tokenSymbol), $"Token {tokenSymbol} cannot set as method fee."); + totalSupply = tokenInfo.TotalSupply; + } - private void AssertTransactionGeneratedByPlugin() - { - Assert(Context.TransactionId != Context.OriginTransactionId, - "This method can only be executed in plugin tx."); - } + private void AssertTransactionGeneratedByPlugin() + { + Assert(Context.TransactionId != Context.OriginTransactionId, + "This method can only be executed in plugin tx."); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index a14e67b9bb..441c2055c4 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -1,243 +1,234 @@ using System.Linq; +using System.Text; using AElf.Contracts.Parliament; +using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS0; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using System.Text; -using AElf.Standards.ACS0; -using AElf.Standards.ACS7; -using AElf.CSharp.Core; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + private static bool IsValidSymbolChar(char character) { - private static bool IsValidSymbolChar(char character) - { - return character >= 'A' && character <= 'Z' || character >= '0' && character <= '9'; - } + return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9'); + } - private bool IsValidCreateSymbolChar(char character) - { - if (State.CreateTokenWhiteListMap[Context.Sender]) - { - return character >= 'A' && character <= 'Z' || character >= '0' && character <= '9'; - } + private bool IsValidCreateSymbolChar(char character) + { + if (State.CreateTokenWhiteListMap[Context.Sender]) + return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9'); - return character >= 'A' && character <= 'Z'; - } + return character >= 'A' && character <= 'Z'; + } - private TokenInfo AssertValidToken(string symbol, long amount) - { - AssertValidSymbolAndAmount(symbol, amount); - var tokenInfo = State.TokenInfos[symbol]; - Assert(tokenInfo != null && !string.IsNullOrEmpty(tokenInfo.Symbol), $"Token is not found. {symbol}"); - return tokenInfo; - } + private TokenInfo AssertValidToken(string symbol, long amount) + { + AssertValidSymbolAndAmount(symbol, amount); + var tokenInfo = State.TokenInfos[symbol]; + Assert(tokenInfo != null && !string.IsNullOrEmpty(tokenInfo.Symbol), $"Token is not found. {symbol}"); + return tokenInfo; + } - private void AssertValidSymbolAndAmount(string symbol, long amount) - { - Assert(!string.IsNullOrEmpty(symbol) && symbol.All(IsValidSymbolChar), - "Invalid symbol."); - Assert(amount > 0, "Invalid amount."); - } + private void AssertValidSymbolAndAmount(string symbol, long amount) + { + Assert(!string.IsNullOrEmpty(symbol) && symbol.All(IsValidSymbolChar), + "Invalid symbol."); + Assert(amount > 0, "Invalid amount."); + } - private void AssertValidMemo(string memo) - { - Assert(memo == null || Encoding.UTF8.GetByteCount(memo) <= TokenContractConstants.MemoMaxLength, - "Invalid memo size."); - } + private void AssertValidMemo(string memo) + { + Assert(memo == null || Encoding.UTF8.GetByteCount(memo) <= TokenContractConstants.MemoMaxLength, + "Invalid memo size."); + } - private void DoTransfer(Address from, Address to, string symbol, long amount, string memo = null) - { - Assert(from != to, "Can't do transfer to sender itself."); - AssertValidMemo(memo); - ModifyBalance(from, symbol, -amount); - ModifyBalance(to, symbol, amount); - Context.Fire(new Transferred - { - From = from, - To = to, - Symbol = symbol, - Amount = amount, - Memo = memo ?? string.Empty - }); - } + private void DoTransfer(Address from, Address to, string symbol, long amount, string memo = null) + { + Assert(from != to, "Can't do transfer to sender itself."); + AssertValidMemo(memo); + ModifyBalance(from, symbol, -amount); + ModifyBalance(to, symbol, amount); + Context.Fire(new Transferred + { + From = from, + To = to, + Symbol = symbol, + Amount = amount, + Memo = memo ?? string.Empty + }); + } - private void ModifyBalance(Address address, string symbol, long addAmount) - { - var before = GetBalance(address, symbol); - if (addAmount < 0 && before < -addAmount) - { - Assert(false, - $"{address}. Insufficient balance of {symbol}. Need balance: {-addAmount}; Current balance: {before}"); - } + private void ModifyBalance(Address address, string symbol, long addAmount) + { + var before = GetBalance(address, symbol); + if (addAmount < 0 && before < -addAmount) + Assert(false, + $"{address}. Insufficient balance of {symbol}. Need balance: {-addAmount}; Current balance: {before}"); - var target = before.Add(addAmount); - State.Balances[address][symbol] = target; - } + var target = before.Add(addAmount); + State.Balances[address][symbol] = target; + } - private long GetBalance(Address address, string symbol) - { - return State.Balances[address][symbol]; - } + private long GetBalance(Address address, string symbol) + { + return State.Balances[address][symbol]; + } - private void AssertSystemContractOrLockWhiteListAddress(string symbol) - { - var symbolState = State.LockWhiteLists[symbol]; - var isInWhiteList = symbolState != null && symbolState[Context.Sender]; - var systemContractAddresses = Context.GetSystemContractNameToAddressMapping().Values; - var isSystemContractAddress = systemContractAddresses.Contains(Context.Sender); - Assert(isInWhiteList || isSystemContractAddress, "No Permission."); - } + private void AssertSystemContractOrLockWhiteListAddress(string symbol) + { + var symbolState = State.LockWhiteLists[symbol]; + var isInWhiteList = symbolState != null && symbolState[Context.Sender]; + var systemContractAddresses = Context.GetSystemContractNameToAddressMapping().Values; + var isSystemContractAddress = systemContractAddresses.Contains(Context.Sender); + Assert(isInWhiteList || isSystemContractAddress, "No Permission."); + } - private Address ExtractTokenContractAddress(ByteString bytes) - { - var validateSystemContractAddressInput = ValidateSystemContractAddressInput.Parser.ParseFrom(bytes); - var validatedAddress = validateSystemContractAddressInput.Address; - var validatedContractHashName = validateSystemContractAddressInput.SystemContractHashName; + private Address ExtractTokenContractAddress(ByteString bytes) + { + var validateSystemContractAddressInput = ValidateSystemContractAddressInput.Parser.ParseFrom(bytes); + var validatedAddress = validateSystemContractAddressInput.Address; + var validatedContractHashName = validateSystemContractAddressInput.SystemContractHashName; - Assert(validatedContractHashName == SmartContractConstants.TokenContractSystemHashName, - "Address validation failed."); - return validatedAddress; - } + Assert(validatedContractHashName == SmartContractConstants.TokenContractSystemHashName, + "Address validation failed."); + return validatedAddress; + } - private void AssertCrossChainTransaction(Transaction originalTransaction, Address validAddress, - params string[] validMethodNames) - { - var validateResult = validMethodNames.Contains(originalTransaction.MethodName) - && originalTransaction.To == validAddress; - Assert(validateResult, "Invalid transaction."); - } + private void AssertCrossChainTransaction(Transaction originalTransaction, Address validAddress, + params string[] validMethodNames) + { + var validateResult = validMethodNames.Contains(originalTransaction.MethodName) + && originalTransaction.To == validAddress; + Assert(validateResult, "Invalid transaction."); + } - private void RegisterTokenInfo(TokenInfo tokenInfo) - { - var existing = State.TokenInfos[tokenInfo.Symbol]; - Assert(existing == null || existing.Equals(new TokenInfo()), "Token already exists."); - Assert(!string.IsNullOrEmpty(tokenInfo.Symbol) && tokenInfo.Symbol.All(IsValidSymbolChar), - "Invalid symbol."); - Assert(!string.IsNullOrEmpty(tokenInfo.TokenName), $"Token name can neither be null nor empty."); - Assert(tokenInfo.TotalSupply > 0, "Invalid total supply."); - Assert(tokenInfo.Issuer != null, "Invalid issuer address."); - State.TokenInfos[tokenInfo.Symbol] = tokenInfo; - } + private void RegisterTokenInfo(TokenInfo tokenInfo) + { + var existing = State.TokenInfos[tokenInfo.Symbol]; + Assert(existing == null || existing.Equals(new TokenInfo()), "Token already exists."); + Assert(!string.IsNullOrEmpty(tokenInfo.Symbol) && tokenInfo.Symbol.All(IsValidSymbolChar), + "Invalid symbol."); + Assert(!string.IsNullOrEmpty(tokenInfo.TokenName), "Token name can neither be null nor empty."); + Assert(tokenInfo.TotalSupply > 0, "Invalid total supply."); + Assert(tokenInfo.Issuer != null, "Invalid issuer address."); + State.TokenInfos[tokenInfo.Symbol] = tokenInfo; + } - private void CrossChainVerify(Hash transactionId, long parentChainHeight, int chainId, MerklePath merklePath) - { - var verificationInput = new VerifyTransactionInput - { - TransactionId = transactionId, - ParentChainHeight = parentChainHeight, - VerifiedChainId = chainId, - Path = merklePath - }; - var address = Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName); - - var verificationResult = Context.Call(address, - nameof(ACS7Container.ACS7ReferenceState.VerifyTransaction), verificationInput); - Assert(verificationResult.Value, "Cross chain verification failed."); - } + private void CrossChainVerify(Hash transactionId, long parentChainHeight, int chainId, MerklePath merklePath) + { + var verificationInput = new VerifyTransactionInput + { + TransactionId = transactionId, + ParentChainHeight = parentChainHeight, + VerifiedChainId = chainId, + Path = merklePath + }; + var address = Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName); + + var verificationResult = Context.Call(address, + nameof(ACS7Container.ACS7ReferenceState.VerifyTransaction), verificationInput); + Assert(verificationResult.Value, "Cross chain verification failed."); + } - private AuthorityInfo GetCrossChainTokenContractRegistrationController() - { - var parliamentContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - var controller = new AuthorityInfo - { - ContractAddress = State.ParliamentContract.Value, - OwnerAddress = Context.Call
(parliamentContractAddress, - nameof(ParliamentContractContainer.ParliamentContractReferenceState.GetDefaultOrganizationAddress), - new Empty()) - }; - return controller; - } + private AuthorityInfo GetCrossChainTokenContractRegistrationController() + { + var parliamentContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + var controller = new AuthorityInfo + { + ContractAddress = State.ParliamentContract.Value, + OwnerAddress = Context.Call
(parliamentContractAddress, + nameof(ParliamentContractContainer.ParliamentContractReferenceState.GetDefaultOrganizationAddress), + new Empty()) + }; + return controller; + } - private int GetIssueChainId(string symbol) - { - var tokenInfo = State.TokenInfos[symbol]; - return tokenInfo.IssueChainId; - } + private int GetIssueChainId(string symbol) + { + var tokenInfo = State.TokenInfos[symbol]; + return tokenInfo.IssueChainId; + } - private void AssertValidCreateInput(CreateInput input) - { - var isValid = input.TokenName.Length <= TokenContractConstants.TokenNameLength - && input.Symbol.Length > 0 - && input.Decimals >= 0 - && input.Decimals <= TokenContractConstants.MaxDecimals; - if (!State.CreateTokenWhiteListMap[Context.Sender]) - { - isValid = isValid && input.Symbol.Length <= TokenContractConstants.SymbolMaxLength; - } + private void AssertValidCreateInput(CreateInput input) + { + var isValid = input.TokenName.Length <= TokenContractConstants.TokenNameLength + && input.Symbol.Length > 0 + && input.Decimals >= 0 + && input.Decimals <= TokenContractConstants.MaxDecimals; + if (!State.CreateTokenWhiteListMap[Context.Sender]) + isValid = isValid && input.Symbol.Length <= TokenContractConstants.SymbolMaxLength; + + Assert(isValid, "Invalid input."); + } - Assert(isValid, "Invalid input."); - } + private void CheckCrossChainTokenContractRegistrationControllerAuthority() + { + if (State.CrossChainTokenContractRegistrationController.Value == null) + State.CrossChainTokenContractRegistrationController.Value = + GetCrossChainTokenContractRegistrationController(); + Assert(State.CrossChainTokenContractRegistrationController.Value.OwnerAddress == Context.Sender, + "No permission."); + } - private void CheckCrossChainTokenContractRegistrationControllerAuthority() + private void DealWithExternalInfoDuringLocking(TransferFromInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + if (tokenInfo.ExternalInfo == null) return; + if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.LockCallbackExternalInfoKey)) { - if (State.CrossChainTokenContractRegistrationController.Value == null) - State.CrossChainTokenContractRegistrationController.Value = - GetCrossChainTokenContractRegistrationController(); - Assert(State.CrossChainTokenContractRegistrationController.Value.OwnerAddress == Context.Sender, - "No permission."); + var callbackInfo = + JsonParser.Default.Parse( + tokenInfo.ExternalInfo.Value[TokenContractConstants.LockCallbackExternalInfoKey]); + Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); } - private void DealWithExternalInfoDuringLocking(TransferFromInput input) - { - var tokenInfo = State.TokenInfos[input.Symbol]; - if (tokenInfo.ExternalInfo == null) return; - if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.LockCallbackExternalInfoKey)) - { - var callbackInfo = - JsonParser.Default.Parse( - tokenInfo.ExternalInfo.Value[TokenContractConstants.LockCallbackExternalInfoKey]); - Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); - } - - FireExternalLogEvent(tokenInfo, input); - } + FireExternalLogEvent(tokenInfo, input); + } - private void DealWithExternalInfoDuringTransfer(TransferFromInput input) + private void DealWithExternalInfoDuringTransfer(TransferFromInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + if (tokenInfo.ExternalInfo == null) return; + if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.TransferCallbackExternalInfoKey)) { - var tokenInfo = State.TokenInfos[input.Symbol]; - if (tokenInfo.ExternalInfo == null) return; - if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.TransferCallbackExternalInfoKey)) - { - var callbackInfo = - JsonParser.Default.Parse( - tokenInfo.ExternalInfo.Value[TokenContractConstants.TransferCallbackExternalInfoKey]); - Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); - } - - FireExternalLogEvent(tokenInfo, input); + var callbackInfo = + JsonParser.Default.Parse( + tokenInfo.ExternalInfo.Value[TokenContractConstants.TransferCallbackExternalInfoKey]); + Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); } - private void DealWithExternalInfoDuringUnlock(TransferFromInput input) - { - var tokenInfo = State.TokenInfos[input.Symbol]; - if (tokenInfo.ExternalInfo == null) return; - if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.UnlockCallbackExternalInfoKey)) - { - var callbackInfo = - JsonParser.Default.Parse( - tokenInfo.ExternalInfo.Value[TokenContractConstants.UnlockCallbackExternalInfoKey]); - Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); - } + FireExternalLogEvent(tokenInfo, input); + } - FireExternalLogEvent(tokenInfo, input); + private void DealWithExternalInfoDuringUnlock(TransferFromInput input) + { + var tokenInfo = State.TokenInfos[input.Symbol]; + if (tokenInfo.ExternalInfo == null) return; + if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.UnlockCallbackExternalInfoKey)) + { + var callbackInfo = + JsonParser.Default.Parse( + tokenInfo.ExternalInfo.Value[TokenContractConstants.UnlockCallbackExternalInfoKey]); + Context.SendInline(callbackInfo.ContractAddress, callbackInfo.MethodName, input); } - private void FireExternalLogEvent(TokenInfo tokenInfo, TransferFromInput input) - { - if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.LogEventExternalInfoKey)) + FireExternalLogEvent(tokenInfo, input); + } + + private void FireExternalLogEvent(TokenInfo tokenInfo, TransferFromInput input) + { + if (tokenInfo.ExternalInfo.Value.ContainsKey(TokenContractConstants.LogEventExternalInfoKey)) + Context.FireLogEvent(new LogEvent { - Context.FireLogEvent(new LogEvent - { - Name = tokenInfo.ExternalInfo.Value[TokenContractConstants.LogEventExternalInfoKey], - Address = Context.Self, - NonIndexed = input.ToByteString() - }); - } - } + Name = tokenInfo.ExternalInfo.Value[TokenContractConstants.LogEventExternalInfoKey], + Address = Context.Self, + NonIndexed = input.ToByteString() + }); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Method_Authorization.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Method_Authorization.cs index 4923f04db7..cc1833f49f 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Method_Authorization.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Method_Authorization.cs @@ -1,408 +1,400 @@ using System.Collections.Generic; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; +using AElf.Contracts.Association; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; +using CreateOrganizationBySystemContractInput = AElf.Contracts.Referendum.CreateOrganizationBySystemContractInput; +using CreateOrganizationInput = AElf.Contracts.Referendum.CreateOrganizationInput; + +namespace AElf.Contracts.MultiToken; -namespace AElf.Contracts.MultiToken +public partial class TokenContract { - public partial class TokenContract - { - #region orgnanization init + #region orgnanization init - public override Empty InitializeAuthorizedController(Empty input) + public override Empty InitializeAuthorizedController(Empty input) + { + var defaultParliamentController = GetDefaultParliamentController(); + if (State.UserFeeController.Value == null) { - var defaultParliamentController = GetDefaultParliamentController(); - if (State.UserFeeController.Value == null) - { - var defaultUserFeeController = GetDefaultUserFeeController(defaultParliamentController); - CreateReferendumControllerForUserFee(defaultParliamentController.OwnerAddress); - CreateAssociationControllerForUserFee(defaultParliamentController.OwnerAddress, - defaultUserFeeController.ReferendumController.OwnerAddress); - State.UserFeeController.Value = defaultUserFeeController; - } - - if (State.DeveloperFeeController.Value == null) - { - var developerController = GetDefaultDeveloperFeeController(defaultParliamentController); - CreateDeveloperController(defaultParliamentController.OwnerAddress); - CreateAssociationControllerForDeveloperFee(defaultParliamentController.OwnerAddress, - developerController.DeveloperController.OwnerAddress); - State.DeveloperFeeController.Value = developerController; - } - - if (State.SideChainCreator.Value == null || State.SideChainRentalController.Value != null) return new Empty(); - var sideChainRentalController = GetDefaultSideChainRentalController(defaultParliamentController); - CreateAssociationControllerForSideChainRental(State.SideChainCreator.Value, defaultParliamentController.OwnerAddress); - State.SideChainRentalController.Value = sideChainRentalController; - return new Empty(); + var defaultUserFeeController = GetDefaultUserFeeController(defaultParliamentController); + CreateReferendumControllerForUserFee(defaultParliamentController.OwnerAddress); + CreateAssociationControllerForUserFee(defaultParliamentController.OwnerAddress, + defaultUserFeeController.ReferendumController.OwnerAddress); + State.UserFeeController.Value = defaultUserFeeController; } - public override Empty ChangeSymbolsToPayTXSizeFeeController(AuthorityInfo input) + if (State.DeveloperFeeController.Value == null) { - AssertControllerForSymbolToPayTxSizeFee(); - Assert(CheckOrganizationExist(input), "new controller does not exist"); - State.SymbolToPayTxFeeController.Value = input; - return new Empty(); + var developerController = GetDefaultDeveloperFeeController(defaultParliamentController); + CreateDeveloperController(defaultParliamentController.OwnerAddress); + CreateAssociationControllerForDeveloperFee(defaultParliamentController.OwnerAddress, + developerController.DeveloperController.OwnerAddress); + State.DeveloperFeeController.Value = developerController; } - public override Empty ChangeSideChainRentalController(AuthorityInfo input) - { - AssertControllerForSideChainRental(); - Assert(CheckOrganizationExist(input), "new controller does not exist"); - State.SideChainRentalController.Value = input; - return new Empty(); - } + if (State.SideChainCreator.Value == null || State.SideChainRentalController.Value != null) return new Empty(); + var sideChainRentalController = GetDefaultSideChainRentalController(defaultParliamentController); + CreateAssociationControllerForSideChainRental(State.SideChainCreator.Value, + defaultParliamentController.OwnerAddress); + State.SideChainRentalController.Value = sideChainRentalController; + return new Empty(); + } - public override Empty ChangeCrossChainTokenContractRegistrationController(AuthorityInfo input) - { - CheckCrossChainTokenContractRegistrationControllerAuthority(); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); - State.CrossChainTokenContractRegistrationController.Value = input; - return new Empty(); - } - - public override Empty ChangeUserFeeController(AuthorityInfo input) - { - AssertUserFeeController(); - Assert(CheckOrganizationExist(input), "Invalid authority input."); - State.UserFeeController.Value.RootController = input; - State.UserFeeController.Value.ParliamentController = null; - State.UserFeeController.Value.ReferendumController = null; - return new Empty(); - } - - public override Empty ChangeDeveloperController(AuthorityInfo input) - { - AssertDeveloperFeeController(); - Assert(CheckOrganizationExist(input), "Invalid authority input."); - State.DeveloperFeeController.Value.RootController = input; - State.DeveloperFeeController.Value.ParliamentController = null; - State.DeveloperFeeController.Value.DeveloperController = null; - return new Empty(); - } + public override Empty ChangeSymbolsToPayTXSizeFeeController(AuthorityInfo input) + { + AssertControllerForSymbolToPayTxSizeFee(); + Assert(CheckOrganizationExist(input), "new controller does not exist"); + State.SymbolToPayTxFeeController.Value = input; + return new Empty(); + } - private void CreateReferendumControllerForUserFee(Address parliamentAddress) - { - State.ReferendumContract.CreateOrganizationBySystemContract.Send( - GetReferendumControllerCreateInputForUserFee(parliamentAddress)); - } + public override Empty ChangeSideChainRentalController(AuthorityInfo input) + { + AssertControllerForSideChainRental(); + Assert(CheckOrganizationExist(input), "new controller does not exist"); + State.SideChainRentalController.Value = input; + return new Empty(); + } - private void CreateAssociationControllerForUserFee(Address parliamentAddress, Address referendumAddress) - { - State.AssociationContract.CreateOrganizationBySystemContract.Send( - GetAssociationControllerCreateInputForUserFee(parliamentAddress, referendumAddress)); - } + public override Empty ChangeCrossChainTokenContractRegistrationController(AuthorityInfo input) + { + CheckCrossChainTokenContractRegistrationControllerAuthority(); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + State.CrossChainTokenContractRegistrationController.Value = input; + return new Empty(); + } - private void CreateDeveloperController(Address parliamentAddress) - { - State.AssociationContract.CreateOrganizationBySystemContract.Send( - GetDeveloperControllerCreateInput(parliamentAddress)); - } + public override Empty ChangeUserFeeController(AuthorityInfo input) + { + AssertUserFeeController(); + Assert(CheckOrganizationExist(input), "Invalid authority input."); + State.UserFeeController.Value.RootController = input; + State.UserFeeController.Value.ParliamentController = null; + State.UserFeeController.Value.ReferendumController = null; + return new Empty(); + } - private void CreateAssociationControllerForDeveloperFee(Address parliamentAddress, Address developerAddress) - { - State.AssociationContract.CreateOrganizationBySystemContract.Send( - GetAssociationControllerCreateInputForDeveloperFee(parliamentAddress, developerAddress)); - } - private void CreateAssociationControllerForSideChainRental(Address sideChainCreator, Address parliamentAddress) - { - State.AssociationContract.CreateOrganizationBySystemContract.Send( - GetControllerCreateInputForSideChainRental(sideChainCreator, parliamentAddress)); - } + public override Empty ChangeDeveloperController(AuthorityInfo input) + { + AssertDeveloperFeeController(); + Assert(CheckOrganizationExist(input), "Invalid authority input."); + State.DeveloperFeeController.Value.RootController = input; + State.DeveloperFeeController.Value.ParliamentController = null; + State.DeveloperFeeController.Value.DeveloperController = null; + return new Empty(); + } + + private void CreateReferendumControllerForUserFee(Address parliamentAddress) + { + State.ReferendumContract.CreateOrganizationBySystemContract.Send( + GetReferendumControllerCreateInputForUserFee(parliamentAddress)); + } + + private void CreateAssociationControllerForUserFee(Address parliamentAddress, Address referendumAddress) + { + State.AssociationContract.CreateOrganizationBySystemContract.Send( + GetAssociationControllerCreateInputForUserFee(parliamentAddress, referendumAddress)); + } + + private void CreateDeveloperController(Address parliamentAddress) + { + State.AssociationContract.CreateOrganizationBySystemContract.Send( + GetDeveloperControllerCreateInput(parliamentAddress)); + } + + private void CreateAssociationControllerForDeveloperFee(Address parliamentAddress, Address developerAddress) + { + State.AssociationContract.CreateOrganizationBySystemContract.Send( + GetAssociationControllerCreateInputForDeveloperFee(parliamentAddress, developerAddress)); + } + + private void CreateAssociationControllerForSideChainRental(Address sideChainCreator, Address parliamentAddress) + { + State.AssociationContract.CreateOrganizationBySystemContract.Send( + GetControllerCreateInputForSideChainRental(sideChainCreator, parliamentAddress)); + } - #endregion + #endregion - #region organization create input + #region organization create input - private Referendum.CreateOrganizationBySystemContractInput GetReferendumControllerCreateInputForUserFee( - Address parliamentAddress) + private CreateOrganizationBySystemContractInput GetReferendumControllerCreateInputForUserFee( + Address parliamentAddress) + { + var whiteList = new List
{ parliamentAddress }; + var tokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + return new CreateOrganizationBySystemContractInput { - var whiteList = new List
{parliamentAddress}; - var tokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - return new Referendum.CreateOrganizationBySystemContractInput + OrganizationCreationInput = new CreateOrganizationInput { - OrganizationCreationInput = new Referendum.CreateOrganizationInput + TokenSymbol = tokenSymbol, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList { - TokenSymbol = tokenSymbol, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {whiteList} - } + Proposers = { whiteList } } - }; - } + } + }; + } - private Association.CreateOrganizationBySystemContractInput GetAssociationControllerCreateInputForUserFee( - Address parliamentAddress, Address referendumAddress) + private Association.CreateOrganizationBySystemContractInput GetAssociationControllerCreateInputForUserFee( + Address parliamentAddress, Address referendumAddress) + { + var proposers = new List
+ { referendumAddress, parliamentAddress }; + return new Association.CreateOrganizationBySystemContractInput { - var proposers = new List
- {referendumAddress, parliamentAddress}; - return new Association.CreateOrganizationBySystemContractInput + OrganizationCreationInput = new Association.CreateOrganizationInput { - OrganizationCreationInput = new Association.CreateOrganizationInput + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { proposers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - OrganizationMemberList = new Association.OrganizationMemberList - { - OrganizationMembers = {proposers} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = proposers.Count, - MinimalVoteThreshold = proposers.Count, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } + MinimalApprovalThreshold = proposers.Count, + MinimalVoteThreshold = proposers.Count, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { proposers } } - }; - } + } + }; + } - private Association.CreateOrganizationBySystemContractInput GetDeveloperControllerCreateInput( - Address parliamentAddress) + private Association.CreateOrganizationBySystemContractInput GetDeveloperControllerCreateInput( + Address parliamentAddress) + { + var proposers = new List
{ parliamentAddress }; + return new Association.CreateOrganizationBySystemContractInput { - var proposers = new List
{parliamentAddress}; - return new Association.CreateOrganizationBySystemContractInput + OrganizationCreationInput = new Association.CreateOrganizationInput { - OrganizationCreationInput = new Association.CreateOrganizationInput + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { proposers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = proposers.Count, + MinimalVoteThreshold = proposers.Count, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList { - OrganizationMemberList = new Association.OrganizationMemberList - { - OrganizationMembers = {proposers} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = proposers.Count, - MinimalVoteThreshold = proposers.Count, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } + Proposers = { proposers } } - }; - } + } + }; + } - private Association.CreateOrganizationBySystemContractInput GetAssociationControllerCreateInputForDeveloperFee( - Address parliamentAddress, Address developerAddress) + private Association.CreateOrganizationBySystemContractInput GetAssociationControllerCreateInputForDeveloperFee( + Address parliamentAddress, Address developerAddress) + { + var proposers = new List
{ - var proposers = new List
- { - developerAddress, parliamentAddress - }; - var actualProposalCount = proposers.Count; - return new Association.CreateOrganizationBySystemContractInput + developerAddress, parliamentAddress + }; + var actualProposalCount = proposers.Count; + return new Association.CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = new Association.CreateOrganizationInput { - OrganizationCreationInput = new Association.CreateOrganizationInput + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { proposers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - OrganizationMemberList = new Association.OrganizationMemberList - { - OrganizationMembers = {proposers} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = actualProposalCount, - MinimalVoteThreshold = actualProposalCount, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } + MinimalApprovalThreshold = actualProposalCount, + MinimalVoteThreshold = actualProposalCount, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { proposers } } - }; - } + } + }; + } - private Association.CreateOrganizationBySystemContractInput GetControllerCreateInputForSideChainRental( - Address sideChainCreator, Address parliamentAddress) + private Association.CreateOrganizationBySystemContractInput GetControllerCreateInputForSideChainRental( + Address sideChainCreator, Address parliamentAddress) + { + var proposers = new List
{ parliamentAddress, sideChainCreator }; + return new Association.CreateOrganizationBySystemContractInput { - var proposers = new List
{parliamentAddress, sideChainCreator}; - return new Association.CreateOrganizationBySystemContractInput + OrganizationCreationInput = new Association.CreateOrganizationInput { - OrganizationCreationInput = new Association.CreateOrganizationInput + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { proposers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - OrganizationMemberList = new Association.OrganizationMemberList - { - OrganizationMembers = {proposers} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = proposers.Count, - MinimalVoteThreshold = proposers.Count, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } + MinimalApprovalThreshold = proposers.Count, + MinimalVoteThreshold = proposers.Count, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { proposers } } - }; - } + } + }; + } - #endregion + #endregion - #region controller management + #region controller management - private AuthorityInfo GetDefaultParliamentController() + private AuthorityInfo GetDefaultParliamentController() + { + if (State.ParliamentContract.Value == null) { - if (State.ParliamentContract.Value == null) - { - var parliamentContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - if (parliamentContractAddress == null) - { - // Test environment. - return new AuthorityInfo(); - } - - State.ParliamentContract.Value = parliamentContractAddress; - } + var parliamentContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + if (parliamentContractAddress == null) + // Test environment. + return new AuthorityInfo(); - var defaultOrganizationAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); - return new AuthorityInfo - { - ContractAddress = State.ParliamentContract.Value, - OwnerAddress = defaultOrganizationAddress - }; + State.ParliamentContract.Value = parliamentContractAddress; } - private DeveloperFeeController GetDefaultDeveloperFeeController(AuthorityInfo defaultParliamentController) + var defaultOrganizationAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); + return new AuthorityInfo { - if (State.AssociationContract.Value == null) - { - State.AssociationContract.Value = - Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); - } + ContractAddress = State.ParliamentContract.Value, + OwnerAddress = defaultOrganizationAddress + }; + } - var developerFeeController = new DeveloperFeeController - { - ParliamentController = new AuthorityInfo(), - DeveloperController = new AuthorityInfo(), - RootController = new AuthorityInfo() - }; - developerFeeController.ParliamentController = defaultParliamentController; - developerFeeController.DeveloperController.ContractAddress = State.AssociationContract.Value; - developerFeeController.DeveloperController.OwnerAddress = - State.AssociationContract.CalculateOrganizationAddress.Call( - GetDeveloperControllerCreateInput(defaultParliamentController.OwnerAddress) - .OrganizationCreationInput); - developerFeeController.RootController.ContractAddress = State.AssociationContract.Value; - developerFeeController.RootController.OwnerAddress = - State.AssociationContract.CalculateOrganizationAddress.Call( - GetAssociationControllerCreateInputForDeveloperFee( - defaultParliamentController.OwnerAddress, - developerFeeController.DeveloperController.OwnerAddress) - .OrganizationCreationInput); - return developerFeeController; - } - - private UserFeeController GetDefaultUserFeeController(AuthorityInfo defaultParliamentController) + private DeveloperFeeController GetDefaultDeveloperFeeController(AuthorityInfo defaultParliamentController) + { + if (State.AssociationContract.Value == null) + State.AssociationContract.Value = + Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); + + var developerFeeController = new DeveloperFeeController { - if (State.AssociationContract.Value == null) - { - State.AssociationContract.Value = - Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); - } + ParliamentController = new AuthorityInfo(), + DeveloperController = new AuthorityInfo(), + RootController = new AuthorityInfo() + }; + developerFeeController.ParliamentController = defaultParliamentController; + developerFeeController.DeveloperController.ContractAddress = State.AssociationContract.Value; + developerFeeController.DeveloperController.OwnerAddress = + State.AssociationContract.CalculateOrganizationAddress.Call( + GetDeveloperControllerCreateInput(defaultParliamentController.OwnerAddress) + .OrganizationCreationInput); + developerFeeController.RootController.ContractAddress = State.AssociationContract.Value; + developerFeeController.RootController.OwnerAddress = + State.AssociationContract.CalculateOrganizationAddress.Call( + GetAssociationControllerCreateInputForDeveloperFee( + defaultParliamentController.OwnerAddress, + developerFeeController.DeveloperController.OwnerAddress) + .OrganizationCreationInput); + return developerFeeController; + } - if (State.ReferendumContract.Value == null) - { - State.ReferendumContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ReferendumContractSystemName); - } + private UserFeeController GetDefaultUserFeeController(AuthorityInfo defaultParliamentController) + { + if (State.AssociationContract.Value == null) + State.AssociationContract.Value = + Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); - var userFeeController = new UserFeeController - { - RootController = new AuthorityInfo(), - ParliamentController = new AuthorityInfo(), - ReferendumController = new AuthorityInfo() - }; - userFeeController.ParliamentController = defaultParliamentController; - userFeeController.ReferendumController.ContractAddress = State.ReferendumContract.Value; - userFeeController.ReferendumController.OwnerAddress = - State.ReferendumContract.CalculateOrganizationAddress.Call( - GetReferendumControllerCreateInputForUserFee(defaultParliamentController.OwnerAddress) - .OrganizationCreationInput); - userFeeController.RootController.ContractAddress = State.AssociationContract.Value; - userFeeController.RootController.OwnerAddress = State.AssociationContract.CalculateOrganizationAddress.Call( - GetAssociationControllerCreateInputForUserFee(defaultParliamentController.OwnerAddress, - userFeeController.ReferendumController.OwnerAddress) - .OrganizationCreationInput); - return userFeeController; - } + if (State.ReferendumContract.Value == null) + State.ReferendumContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ReferendumContractSystemName); - private AuthorityInfo GetDefaultSymbolToPayTxFeeController() - { - return GetDefaultParliamentController(); - } - - private AuthorityInfo GetDefaultSideChainRentalController(AuthorityInfo defaultParliamentController) - { - if (State.AssociationContract.Value == null) - { - State.AssociationContract.Value = - Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); - } - var calculatedAddress = State.AssociationContract.CalculateOrganizationAddress.Call( - GetControllerCreateInputForSideChainRental( - State.SideChainCreator.Value, - defaultParliamentController.OwnerAddress) - .OrganizationCreationInput); - return new AuthorityInfo - { - ContractAddress = State.AssociationContract.Value, - OwnerAddress = calculatedAddress - }; - } - - private void AssertDeveloperFeeController() + var userFeeController = new UserFeeController { - Assert(State.DeveloperFeeController.Value != null, - "controller does not initialize, call InitializeAuthorizedController first"); + RootController = new AuthorityInfo(), + ParliamentController = new AuthorityInfo(), + ReferendumController = new AuthorityInfo() + }; + userFeeController.ParliamentController = defaultParliamentController; + userFeeController.ReferendumController.ContractAddress = State.ReferendumContract.Value; + userFeeController.ReferendumController.OwnerAddress = + State.ReferendumContract.CalculateOrganizationAddress.Call( + GetReferendumControllerCreateInputForUserFee(defaultParliamentController.OwnerAddress) + .OrganizationCreationInput); + userFeeController.RootController.ContractAddress = State.AssociationContract.Value; + userFeeController.RootController.OwnerAddress = State.AssociationContract.CalculateOrganizationAddress.Call( + GetAssociationControllerCreateInputForUserFee(defaultParliamentController.OwnerAddress, + userFeeController.ReferendumController.OwnerAddress) + .OrganizationCreationInput); + return userFeeController; + } - Assert(Context.Sender == State.DeveloperFeeController.Value.RootController.OwnerAddress, "no permission"); - } - - private void AssertUserFeeController() - { - Assert(State.UserFeeController.Value != null, - "controller does not initialize, call InitializeAuthorizedController first"); - // ReSharper disable once PossibleNullReferenceException - Assert(Context.Sender == State.UserFeeController.Value.RootController.OwnerAddress, "no permission"); - } - - private void AssertControllerForSymbolToPayTxSizeFee() - { - if (State.SymbolToPayTxFeeController.Value == null) - { - State.SymbolToPayTxFeeController.Value = GetDefaultSymbolToPayTxFeeController(); - } + private AuthorityInfo GetDefaultSymbolToPayTxFeeController() + { + return GetDefaultParliamentController(); + } - Assert(State.SymbolToPayTxFeeController.Value.OwnerAddress == Context.Sender, "no permission"); - } - - private void AssertControllerForSideChainRental() + private AuthorityInfo GetDefaultSideChainRentalController(AuthorityInfo defaultParliamentController) + { + if (State.AssociationContract.Value == null) + State.AssociationContract.Value = + Context.GetContractAddressByName(SmartContractConstants.AssociationContractSystemName); + var calculatedAddress = State.AssociationContract.CalculateOrganizationAddress.Call( + GetControllerCreateInputForSideChainRental( + State.SideChainCreator.Value, + defaultParliamentController.OwnerAddress) + .OrganizationCreationInput); + return new AuthorityInfo { - Assert(State.SideChainRentalController.Value != null, "controller does not initialize, call InitializeAuthorizedController first"); - // ReSharper disable once PossibleNullReferenceException - Assert(State.SideChainRentalController.Value.OwnerAddress == Context.Sender, "no permission"); - } + ContractAddress = State.AssociationContract.Value, + OwnerAddress = calculatedAddress + }; + } + + private void AssertDeveloperFeeController() + { + Assert(State.DeveloperFeeController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + + Assert(Context.Sender == State.DeveloperFeeController.Value.RootController.OwnerAddress, "no permission"); + } - #endregion + private void AssertUserFeeController() + { + Assert(State.UserFeeController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + // ReSharper disable once PossibleNullReferenceException + Assert(Context.Sender == State.UserFeeController.Value.RootController.OwnerAddress, "no permission"); + } + + private void AssertControllerForSymbolToPayTxSizeFee() + { + if (State.SymbolToPayTxFeeController.Value == null) + State.SymbolToPayTxFeeController.Value = GetDefaultSymbolToPayTxFeeController(); + + Assert(State.SymbolToPayTxFeeController.Value.OwnerAddress == Context.Sender, "no permission"); } + + private void AssertControllerForSideChainRental() + { + Assert(State.SideChainRentalController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + // ReSharper disable once PossibleNullReferenceException + Assert(State.SideChainRentalController.Value.OwnerAddress == Context.Sender, "no permission"); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Views.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Views.cs index 3c98ba8900..7cf35dc2c5 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Views.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Views.cs @@ -3,256 +3,239 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class TokenContract { - public partial class TokenContract + [View] + public override TokenInfo GetTokenInfo(GetTokenInfoInput input) { - [View] - public override TokenInfo GetTokenInfo(GetTokenInfoInput input) - { - return State.TokenInfos[input.Symbol]; - } + return State.TokenInfos[input.Symbol]; + } - public override TokenInfo GetNativeTokenInfo(Empty input) - { - return State.TokenInfos[State.NativeTokenSymbol.Value]; - } + public override TokenInfo GetNativeTokenInfo(Empty input) + { + return State.TokenInfos[State.NativeTokenSymbol.Value]; + } - public override TokenInfoList GetResourceTokenInfo(Empty input) + public override TokenInfoList GetResourceTokenInfo(Empty input) + { + var tokenInfoList = new TokenInfoList(); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName) + .Where(symbol => + State.TokenInfos[symbol] != null)) + tokenInfoList.Value.Add(State.TokenInfos[symbol]); + + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName) + .Where(symbol => + State.TokenInfos[symbol] != null)) + tokenInfoList.Value.Add(State.TokenInfos[symbol]); + + return tokenInfoList; + } + + [View] + public override GetBalanceOutput GetBalance(GetBalanceInput input) + { + return new GetBalanceOutput { - var tokenInfoList = new TokenInfoList(); - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName) - .Where(symbol => - State.TokenInfos[symbol] != null)) - { - tokenInfoList.Value.Add(State.TokenInfos[symbol]); - } + Symbol = input.Symbol, + Owner = input.Owner, + Balance = GetBalance(input.Owner, input.Symbol) + }; + } - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName) - .Where(symbol => - State.TokenInfos[symbol] != null)) - { - tokenInfoList.Value.Add(State.TokenInfos[symbol]); - } + [View] + public override GetAllowanceOutput GetAllowance(GetAllowanceInput input) + { + return new GetAllowanceOutput + { + Symbol = input.Symbol, + Owner = input.Owner, + Spender = input.Spender, + Allowance = State.Allowances[input.Owner][input.Spender][input.Symbol] + }; + } - return tokenInfoList; - } + public override BoolValue IsInWhiteList(IsInWhiteListInput input) + { + return new BoolValue { Value = State.LockWhiteLists[input.Symbol][input.Address] }; + } - [View] - public override GetBalanceOutput GetBalance(GetBalanceInput input) - { - return new GetBalanceOutput() - { - Symbol = input.Symbol, - Owner = input.Owner, - Balance = GetBalance(input.Owner, input.Symbol) - }; - } - - [View] - public override GetAllowanceOutput GetAllowance(GetAllowanceInput input) - { - return new GetAllowanceOutput() - { - Symbol = input.Symbol, - Owner = input.Owner, - Spender = input.Spender, - Allowance = State.Allowances[input.Owner][input.Spender][input.Symbol] - }; - } - - public override BoolValue IsInWhiteList(IsInWhiteListInput input) - { - return new BoolValue {Value = State.LockWhiteLists[input.Symbol][input.Address]}; - } + public override GetLockedAmountOutput GetLockedAmount(GetLockedAmountInput input) + { + Assert(input.LockId != null, "Lock id cannot be null."); + var virtualAddress = GetVirtualAddressForLocking(new GetVirtualAddressForLockingInput + { + Address = input.Address, + LockId = input.LockId + }); + return new GetLockedAmountOutput + { + Symbol = input.Symbol, + Address = input.Address, + LockId = input.LockId, + Amount = GetBalance(virtualAddress, input.Symbol) + }; + } - public override GetLockedAmountOutput GetLockedAmount(GetLockedAmountInput input) - { - Assert(input.LockId != null, "Lock id cannot be null."); - var virtualAddress = GetVirtualAddressForLocking(new GetVirtualAddressForLockingInput - { - Address = input.Address, - LockId = input.LockId - }); - return new GetLockedAmountOutput - { - Symbol = input.Symbol, - Address = input.Address, - LockId = input.LockId, - Amount = GetBalance(virtualAddress, input.Symbol) - }; - } - - public override Address GetVirtualAddressForLocking(GetVirtualAddressForLockingInput input) - { - var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) - .Concat(input.LockId.Value).ToArray()); - var virtualAddress = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress); - return virtualAddress; - } - - public override Address GetCrossChainTransferTokenContractAddress( - GetCrossChainTransferTokenContractAddressInput input) - { - return State.CrossChainTransferWhiteList[input.ChainId]; - } + public override Address GetVirtualAddressForLocking(GetVirtualAddressForLockingInput input) + { + var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) + .Concat(input.LockId.Value).ToArray()); + var virtualAddress = Context.ConvertVirtualAddressToContractAddress(fromVirtualAddress); + return virtualAddress; + } - public override StringValue GetPrimaryTokenSymbol(Empty input) - { - if (string.IsNullOrWhiteSpace(_primaryTokenSymbol) && State.ChainPrimaryTokenSymbol.Value != null) - { - _primaryTokenSymbol = State.ChainPrimaryTokenSymbol.Value; - } + public override Address GetCrossChainTransferTokenContractAddress( + GetCrossChainTransferTokenContractAddressInput input) + { + return State.CrossChainTransferWhiteList[input.ChainId]; + } - return new StringValue - { - Value = _primaryTokenSymbol ?? Context.Variables.NativeSymbol - }; - } + public override StringValue GetPrimaryTokenSymbol(Empty input) + { + if (string.IsNullOrWhiteSpace(_primaryTokenSymbol) && State.ChainPrimaryTokenSymbol.Value != null) + _primaryTokenSymbol = State.ChainPrimaryTokenSymbol.Value; - public override CalculateFeeCoefficients GetCalculateFeeCoefficientsForContract(Int32Value input) + return new StringValue { - if (input.Value == (int) FeeTypeEnum.Tx) - return new CalculateFeeCoefficients(); - var targetTokenCoefficient = - State.AllCalculateFeeCoefficients.Value.Value.FirstOrDefault(x => - x.FeeTokenType == input.Value); - return targetTokenCoefficient; - } - - public override CalculateFeeCoefficients GetCalculateFeeCoefficientsForSender(Empty input) - { - var targetTokenCoefficient = - State.AllCalculateFeeCoefficients.Value.Value.FirstOrDefault(x => - x.FeeTokenType == (int) FeeTypeEnum.Tx) ?? new CalculateFeeCoefficients(); - return targetTokenCoefficient; - } + Value = _primaryTokenSymbol ?? Context.Variables.NativeSymbol + }; + } - public override OwningRental GetOwningRental(Empty input) - { - var owingRental = new OwningRental(); - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) - { - owingRental.ResourceAmount[symbol] = State.OwningRental[symbol]; - } + public override CalculateFeeCoefficients GetCalculateFeeCoefficientsForContract(Int32Value input) + { + if (input.Value == (int)FeeTypeEnum.Tx) + return new CalculateFeeCoefficients(); + var targetTokenCoefficient = + State.AllCalculateFeeCoefficients.Value.Value.FirstOrDefault(x => + x.FeeTokenType == input.Value); + return targetTokenCoefficient; + } - return owingRental; - } + public override CalculateFeeCoefficients GetCalculateFeeCoefficientsForSender(Empty input) + { + var targetTokenCoefficient = + State.AllCalculateFeeCoefficients.Value.Value.FirstOrDefault(x => + x.FeeTokenType == (int)FeeTypeEnum.Tx) ?? new CalculateFeeCoefficients(); + return targetTokenCoefficient; + } - public override OwningRentalUnitValue GetOwningRentalUnitValue(Empty input) - { - var rentalResourceUnitValue = new OwningRentalUnitValue(); - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) - { - rentalResourceUnitValue.ResourceUnitValue[symbol] = State.Rental[symbol]; - } + public override OwningRental GetOwningRental(Empty input) + { + var owingRental = new OwningRental(); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) + owingRental.ResourceAmount[symbol] = State.OwningRental[symbol]; - return rentalResourceUnitValue; - } + return owingRental; + } - public override ResourceUsage GetResourceUsage(Empty input) - { - var usage = new ResourceUsage(); - foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) - { - usage.Value.Add(symbol, State.ResourceAmount[symbol]); - } + public override OwningRentalUnitValue GetOwningRentalUnitValue(Empty input) + { + var rentalResourceUnitValue = new OwningRentalUnitValue(); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) + rentalResourceUnitValue.ResourceUnitValue[symbol] = State.Rental[symbol]; - return usage; - } + return rentalResourceUnitValue; + } - public override SymbolListToPayTxSizeFee GetSymbolsToPayTxSizeFee(Empty input) - { - return State.SymbolListToPayTxSizeFee.Value; - } + public override ResourceUsage GetResourceUsage(Empty input) + { + var usage = new ResourceUsage(); + foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) + usage.Value.Add(symbol, State.ResourceAmount[symbol]); - public override UserFeeController GetUserFeeController(Empty input) - { - Assert(State.UserFeeController.Value != null, - "controller does not initialize, call InitializeAuthorizedController first"); - return State.UserFeeController.Value; - } + return usage; + } - public override DeveloperFeeController GetDeveloperFeeController(Empty input) - { - Assert(State.DeveloperFeeController.Value != null, - "controller does not initialize, call InitializeAuthorizedController first"); - return State.DeveloperFeeController.Value; - } + public override SymbolListToPayTxSizeFee GetSymbolsToPayTxSizeFee(Empty input) + { + return State.SymbolListToPayTxSizeFee.Value; + } - public override AuthorityInfo GetSideChainRentalControllerCreateInfo(Empty input) - { - Assert(State.SideChainCreator.Value != null, "side chain creator dose not exist"); - Assert(State.SideChainRentalController.Value != null, - "controller does not initialize, call InitializeAuthorizedController first"); - return State.SideChainRentalController.Value; - } + public override UserFeeController GetUserFeeController(Empty input) + { + Assert(State.UserFeeController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + return State.UserFeeController.Value; + } - public override AuthorityInfo GetSymbolsToPayTXSizeFeeController(Empty input) - { - if (State.SymbolToPayTxFeeController.Value == null) - return GetDefaultSymbolToPayTxFeeController(); - return State.SymbolToPayTxFeeController.Value; - } + public override DeveloperFeeController GetDeveloperFeeController(Empty input) + { + Assert(State.DeveloperFeeController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + return State.DeveloperFeeController.Value; + } - public override AuthorityInfo GetCrossChainTokenContractRegistrationController(Empty input) - { - if (State.CrossChainTokenContractRegistrationController.Value == null) - { - return GetCrossChainTokenContractRegistrationController(); - } + public override AuthorityInfo GetSideChainRentalControllerCreateInfo(Empty input) + { + Assert(State.SideChainCreator.Value != null, "side chain creator dose not exist"); + Assert(State.SideChainRentalController.Value != null, + "controller does not initialize, call InitializeAuthorizedController first"); + return State.SideChainRentalController.Value; + } - return State.CrossChainTokenContractRegistrationController.Value; - } + public override AuthorityInfo GetSymbolsToPayTXSizeFeeController(Empty input) + { + if (State.SymbolToPayTxFeeController.Value == null) + return GetDefaultSymbolToPayTxFeeController(); + return State.SymbolToPayTxFeeController.Value; + } - public override BoolValue IsTokenAvailableForMethodFee(StringValue input) - { - return new BoolValue - { - Value = IsTokenAvailableForMethodFee(input.Value) - }; - } + public override AuthorityInfo GetCrossChainTokenContractRegistrationController(Empty input) + { + if (State.CrossChainTokenContractRegistrationController.Value == null) + return GetCrossChainTokenContractRegistrationController(); - public override BoolValue IsInCreateTokenWhiteList(Address input) - { - return new BoolValue - { - Value = IsAddressInCreateTokenWhiteList(input) - }; - } + return State.CrossChainTokenContractRegistrationController.Value; + } - public override StringList GetReservedExternalInfoKeyList(Empty input) + public override BoolValue IsTokenAvailableForMethodFee(StringValue input) + { + return new BoolValue { - return new StringList - { - Value = - { - TokenContractConstants.LockCallbackExternalInfoKey, - TokenContractConstants.LogEventExternalInfoKey, - TokenContractConstants.TransferCallbackExternalInfoKey, - TokenContractConstants.UnlockCallbackExternalInfoKey, - } - }; - } - - private bool IsTokenAvailableForMethodFee(string symbol) + Value = IsTokenAvailableForMethodFee(input.Value) + }; + } + + public override BoolValue IsInCreateTokenWhiteList(Address input) + { + return new BoolValue { - var tokenInfo = State.TokenInfos[symbol]; - if (tokenInfo == null) throw new AssertionException("Token is not found."); - return tokenInfo.IsBurnable; - } + Value = IsAddressInCreateTokenWhiteList(input) + }; + } - private bool IsAddressInCreateTokenWhiteList(Address address) + public override StringList GetReservedExternalInfoKeyList(Empty input) + { + return new StringList { - if (address == Context.GetZeroSmartContractAddress() || - address == GetDefaultParliamentController().OwnerAddress || address == - Context.GetContractAddressByName(SmartContractConstants.EconomicContractSystemName) || - address == Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName)) + Value = { - return true; + TokenContractConstants.LockCallbackExternalInfoKey, + TokenContractConstants.LogEventExternalInfoKey, + TokenContractConstants.TransferCallbackExternalInfoKey, + TokenContractConstants.UnlockCallbackExternalInfoKey } + }; + } + + private bool IsTokenAvailableForMethodFee(string symbol) + { + var tokenInfo = State.TokenInfos[symbol]; + if (tokenInfo == null) throw new AssertionException("Token is not found."); + return tokenInfo.IsBurnable; + } + + private bool IsAddressInCreateTokenWhiteList(Address address) + { + if (address == Context.GetZeroSmartContractAddress() || + address == GetDefaultParliamentController().OwnerAddress || address == + Context.GetContractAddressByName(SmartContractConstants.EconomicContractSystemName) || + address == Context.GetContractAddressByName(SmartContractConstants.CrossChainContractSystemName)) + return true; - return State.CreateTokenWhiteListMap[address]; - } + return State.CreateTokenWhiteListMap[address]; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/AElf.Contracts.NFT.csproj b/contract/AElf.Contracts.NFT/AElf.Contracts.NFT.csproj index e91df17824..9b9bf5e782 100644 --- a/contract/AElf.Contracts.NFT/AElf.Contracts.NFT.csproj +++ b/contract/AElf.Contracts.NFT/AElf.Contracts.NFT.csproj @@ -1,12 +1,13 @@ - + net6.0 AElf.Contracts.NFT true NFT Contract is a contract that implements Non-Fungible-Token functionality like creation, issuance and - transfer. + transfer. + diff --git a/contract/AElf.Contracts.NFT/NFTContractConstants.cs b/contract/AElf.Contracts.NFT/NFTContractConstants.cs index 0d84bcc931..84bbf9a1fc 100644 --- a/contract/AElf.Contracts.NFT/NFTContractConstants.cs +++ b/contract/AElf.Contracts.NFT/NFTContractConstants.cs @@ -1,13 +1,12 @@ -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract { - public partial class NFTContract - { - private const int NumberMinLength = 9; + private const int NumberMinLength = 9; - private const string NftTypeMetadataKey = "aelf_nft_type"; - private const string NftBaseUriMetadataKey = "aelf_nft_base_uri"; - private const string NftTokenIdReuseMetadataKey = "aelf_nft_token_id_reuse"; - private const string AssembledNftsKey = "aelf_assembled_nfts"; - private const string AssembledFtsKey = "aelf_assembled_fts"; - } + private const string NftTypeMetadataKey = "aelf_nft_type"; + private const string NftBaseUriMetadataKey = "aelf_nft_base_uri"; + private const string NftTokenIdReuseMetadataKey = "aelf_nft_token_id_reuse"; + private const string AssembledNftsKey = "aelf_assembled_nfts"; + private const string AssembledFtsKey = "aelf_assembled_fts"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContractReferenceState.cs b/contract/AElf.Contracts.NFT/NFTContractReferenceState.cs index 56acdbe9ff..1f6dc39fc1 100644 --- a/contract/AElf.Contracts.NFT/NFTContractReferenceState.cs +++ b/contract/AElf.Contracts.NFT/NFTContractReferenceState.cs @@ -2,15 +2,14 @@ using AElf.Contracts.Parliament; using AElf.Standards.ACS6; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractState { - public partial class NFTContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal RandomNumberProviderContractContainer.RandomNumberProviderContractReferenceState - RandomNumberProviderContract { get; set; } + internal RandomNumberProviderContractContainer.RandomNumberProviderContractReferenceState + RandomNumberProviderContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContractState.cs b/contract/AElf.Contracts.NFT/NFTContractState.cs index fe0590b5ee..ad35848df0 100644 --- a/contract/AElf.Contracts.NFT/NFTContractState.cs +++ b/contract/AElf.Contracts.NFT/NFTContractState.cs @@ -1,47 +1,46 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractState : ContractState { - public partial class NFTContractState : ContractState - { - public Int64State NftProtocolNumberFlag { get; set; } - public Int32State CurrentSymbolNumberLength { get; set; } - public MappedState IsCreatedMap { get; set; } + public Int64State NftProtocolNumberFlag { get; set; } + public Int32State CurrentSymbolNumberLength { get; set; } + public MappedState IsCreatedMap { get; set; } - /// - /// Symbol -> Addresses have permission to mint this token - /// - public MappedState MinterListMap { get; set; } + /// + /// Symbol -> Addresses have permission to mint this token + /// + public MappedState MinterListMap { get; set; } - public MappedState NftInfoMap { get; set; } + public MappedState NftInfoMap { get; set; } - /// - /// Token Hash -> Owner Address -> Balance - /// - public MappedState BalanceMap { get; set; } + /// + /// Token Hash -> Owner Address -> Balance + /// + public MappedState BalanceMap { get; set; } - public MappedState NftProtocolMap { get; set; } + public MappedState NftProtocolMap { get; set; } - /// - /// Token Hash -> Owner Address -> Spender Address -> Approved Amount - /// Need to record approved by whom. - /// - public MappedState AllowanceMap { get; set; } + /// + /// Token Hash -> Owner Address -> Spender Address -> Approved Amount + /// Need to record approved by whom. + /// + public MappedState AllowanceMap { get; set; } - public MappedState AssembledNftsMap { get; set; } - public MappedState AssembledFtsMap { get; set; } + public MappedState AssembledNftsMap { get; set; } + public MappedState AssembledFtsMap { get; set; } - public MappedState NFTTypeShortNameMap { get; set; } - public MappedState NFTTypeFullNameMap { get; set; } + public MappedState NFTTypeShortNameMap { get; set; } + public MappedState NFTTypeFullNameMap { get; set; } - public SingletonState
ParliamentDefaultAddress { get; set; } + public SingletonState
ParliamentDefaultAddress { get; set; } - public SingletonState NFTTypes { get; set; } + public SingletonState NFTTypes { get; set; } - /// - /// Symbol (Protocol) -> Owner Address -> Operator Address List - /// - public MappedState OperatorMap { get; set; } - } + /// + /// Symbol (Protocol) -> Owner Address -> Operator Address List + /// + public MappedState OperatorMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContract_ACS1.cs b/contract/AElf.Contracts.NFT/NFTContract_ACS1.cs index c365c1656a..43c05b5625 100644 --- a/contract/AElf.Contracts.NFT/NFTContract_ACS1.cs +++ b/contract/AElf.Contracts.NFT/NFTContract_ACS1.cs @@ -1,48 +1,45 @@ using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract { - public partial class NFTContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) - { - if (input.Value == nameof(Create)) + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + return new Empty(); + } + + #region Views + + public override MethodFees GetMethodFee(StringValue input) + { + if (input.Value == nameof(Create)) + return new MethodFees { - return new MethodFees + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = + new MethodFee { - new MethodFee - { - Symbol = Context.Variables.NativeSymbol, - BasicFee = 100_00000000 - } + Symbol = Context.Variables.NativeSymbol, + BasicFee = 100_00000000 } - }; - } + } + }; - return new MethodFees(); - } - - public override AuthorityInfo GetMethodFeeController(Empty input) - { - return new AuthorityInfo(); - } - - #endregion - - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } + return new MethodFees(); + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - return new Empty(); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + return new AuthorityInfo(); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContract_Create.cs b/contract/AElf.Contracts.NFT/NFTContract_Create.cs index 7aca627e4d..b8ba766942 100644 --- a/contract/AElf.Contracts.NFT/NFTContract_Create.cs +++ b/contract/AElf.Contracts.NFT/NFTContract_Create.cs @@ -2,216 +2,201 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract : NFTContractContainer.NFTContractBase { - public partial class NFTContract : NFTContractContainer.NFTContractBase + /// + /// The Create method can only be executed in aelf MainChain. + /// + /// + /// + public override StringValue Create(CreateInput input) { - /// - /// The Create method can only be executed in aelf MainChain. - /// - /// - /// - public override StringValue Create(CreateInput input) + Assert(Context.ChainId == ChainHelper.ConvertBase58ToChainId("AELF"), + "NFT Protocol can only be created at aelf mainchain."); + MakeSureTokenContractAddressSet(); + MakeSureRandomNumberProviderContractAddressSet(); + var symbol = GetSymbol(input.NftType); + var tokenExternalInfo = GetTokenExternalInfo(input); + var creator = input.Creator ?? Context.Sender; + var tokenCreateInput = new MultiToken.CreateInput { - Assert(Context.ChainId == ChainHelper.ConvertBase58ToChainId("AELF"), - "NFT Protocol can only be created at aelf mainchain."); - MakeSureTokenContractAddressSet(); - MakeSureRandomNumberProviderContractAddressSet(); - var symbol = GetSymbol(input.NftType); - var tokenExternalInfo = GetTokenExternalInfo(input); - var creator = input.Creator ?? Context.Sender; - var tokenCreateInput = new MultiToken.CreateInput - { - Symbol = symbol, - Decimals = 0, // Fixed - Issuer = creator, - IsBurnable = input.IsBurnable, - IssueChainId = input.IssueChainId, - TokenName = input.ProtocolName, - TotalSupply = input.TotalSupply, - ExternalInfo = tokenExternalInfo - }; - State.TokenContract.Create.Send(tokenCreateInput); - - var minterList = input.MinterList ?? new MinterList(); - if (!minterList.Value.Contains(creator)) - { - minterList.Value.Add(creator); - } - State.MinterListMap[symbol] = minterList; - - var protocolInfo = new NFTProtocolInfo - { - Symbol = symbol, - BaseUri = input.BaseUri, - TotalSupply = tokenCreateInput.TotalSupply, - Creator = tokenCreateInput.Issuer, - Metadata = new Metadata {Value = {tokenExternalInfo.Value}}, - ProtocolName = tokenCreateInput.TokenName, - IsTokenIdReuse = input.IsTokenIdReuse, - IssueChainId = tokenCreateInput.IssueChainId, - IsBurnable = tokenCreateInput.IsBurnable, - NftType = input.NftType - }; - State.NftProtocolMap[symbol] = protocolInfo; - - Context.Fire(new NFTProtocolCreated - { - Symbol = tokenCreateInput.Symbol, - Creator = tokenCreateInput.Issuer, - IsBurnable = tokenCreateInput.IsBurnable, - IssueChainId = tokenCreateInput.IssueChainId, - ProtocolName = tokenCreateInput.TokenName, - TotalSupply = tokenCreateInput.TotalSupply, - Metadata = protocolInfo.Metadata, - BaseUri = protocolInfo.BaseUri, - IsTokenIdReuse = protocolInfo.IsTokenIdReuse, - NftType = protocolInfo.NftType - }); - - return new StringValue - { - Value = symbol - }; - } - - public override Empty CrossChainCreate(CrossChainCreateInput input) + Symbol = symbol, + Decimals = 0, // Fixed + Issuer = creator, + IsBurnable = input.IsBurnable, + IssueChainId = input.IssueChainId, + TokenName = input.ProtocolName, + TotalSupply = input.TotalSupply, + ExternalInfo = tokenExternalInfo + }; + State.TokenContract.Create.Send(tokenCreateInput); + + var minterList = input.MinterList ?? new MinterList(); + if (!minterList.Value.Contains(creator)) minterList.Value.Add(creator); + State.MinterListMap[symbol] = minterList; + + var protocolInfo = new NFTProtocolInfo { - MakeSureTokenContractAddressSet(); - InitialNFTTypeNameMap(); - Assert(State.NftProtocolMap[input.Symbol] == null, $"Protocol {input.Symbol} already created."); - var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput - { - Symbol = input.Symbol - }); - if (string.IsNullOrEmpty(tokenInfo.Symbol)) - { - throw new AssertionException($"Token info {input.Symbol} not exists."); - } - - var baseUri = tokenInfo.ExternalInfo.Value[NftBaseUriMetadataKey]; - var isTokenIdReuse = bool.Parse(tokenInfo.ExternalInfo.Value[NftTokenIdReuseMetadataKey]); - var nftTypeShortName = input.Symbol.Substring(0, 2); - var nftTypeFullName = State.NFTTypeFullNameMap[nftTypeShortName]; - if (nftTypeFullName == null) - { - throw new AssertionException( - $"Full name of {nftTypeShortName} not found. Use AddNFTType to add this new pair."); - } - - var nftProtocolInfo = new NFTProtocolInfo - { - Symbol = input.Symbol, - TotalSupply = tokenInfo.TotalSupply, - BaseUri = baseUri, - Creator = tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - IssueChainId = tokenInfo.IssueChainId, - IsTokenIdReuse = isTokenIdReuse, - Metadata = new Metadata {Value = {tokenInfo.ExternalInfo.Value}}, - ProtocolName = tokenInfo.TokenName, - NftType = nftTypeFullName - }; - State.NftProtocolMap[input.Symbol] = nftProtocolInfo; + Symbol = symbol, + BaseUri = input.BaseUri, + TotalSupply = tokenCreateInput.TotalSupply, + Creator = tokenCreateInput.Issuer, + Metadata = new Metadata { Value = { tokenExternalInfo.Value } }, + ProtocolName = tokenCreateInput.TokenName, + IsTokenIdReuse = input.IsTokenIdReuse, + IssueChainId = tokenCreateInput.IssueChainId, + IsBurnable = tokenCreateInput.IsBurnable, + NftType = input.NftType + }; + State.NftProtocolMap[symbol] = protocolInfo; + + Context.Fire(new NFTProtocolCreated + { + Symbol = tokenCreateInput.Symbol, + Creator = tokenCreateInput.Issuer, + IsBurnable = tokenCreateInput.IsBurnable, + IssueChainId = tokenCreateInput.IssueChainId, + ProtocolName = tokenCreateInput.TokenName, + TotalSupply = tokenCreateInput.TotalSupply, + Metadata = protocolInfo.Metadata, + BaseUri = protocolInfo.BaseUri, + IsTokenIdReuse = protocolInfo.IsTokenIdReuse, + NftType = protocolInfo.NftType + }); + + return new StringValue + { + Value = symbol + }; + } - State.MinterListMap[input.Symbol] = new MinterList - { - Value = {nftProtocolInfo.Creator} - }; + public override Empty CrossChainCreate(CrossChainCreateInput input) + { + MakeSureTokenContractAddressSet(); + InitialNFTTypeNameMap(); + Assert(State.NftProtocolMap[input.Symbol] == null, $"Protocol {input.Symbol} already created."); + var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput + { + Symbol = input.Symbol + }); + if (string.IsNullOrEmpty(tokenInfo.Symbol)) + throw new AssertionException($"Token info {input.Symbol} not exists."); + + var baseUri = tokenInfo.ExternalInfo.Value[NftBaseUriMetadataKey]; + var isTokenIdReuse = bool.Parse(tokenInfo.ExternalInfo.Value[NftTokenIdReuseMetadataKey]); + var nftTypeShortName = input.Symbol.Substring(0, 2); + var nftTypeFullName = State.NFTTypeFullNameMap[nftTypeShortName]; + if (nftTypeFullName == null) + throw new AssertionException( + $"Full name of {nftTypeShortName} not found. Use AddNFTType to add this new pair."); + + var nftProtocolInfo = new NFTProtocolInfo + { + Symbol = input.Symbol, + TotalSupply = tokenInfo.TotalSupply, + BaseUri = baseUri, + Creator = tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + IssueChainId = tokenInfo.IssueChainId, + IsTokenIdReuse = isTokenIdReuse, + Metadata = new Metadata { Value = { tokenInfo.ExternalInfo.Value } }, + ProtocolName = tokenInfo.TokenName, + NftType = nftTypeFullName + }; + State.NftProtocolMap[input.Symbol] = nftProtocolInfo; + + State.MinterListMap[input.Symbol] = new MinterList + { + Value = { nftProtocolInfo.Creator } + }; - Context.Fire(new NFTProtocolCreated - { - Symbol = input.Symbol, - Creator = nftProtocolInfo.Creator, - IsBurnable = nftProtocolInfo.IsBurnable, - IssueChainId = nftProtocolInfo.IssueChainId, - ProtocolName = nftProtocolInfo.ProtocolName, - TotalSupply = nftProtocolInfo.TotalSupply, - Metadata = nftProtocolInfo.Metadata, - BaseUri = nftProtocolInfo.BaseUri, - IsTokenIdReuse = isTokenIdReuse, - NftType = nftProtocolInfo.NftType - }); - return new Empty(); - } - - public override Empty AddNFTType(AddNFTTypeInput input) + Context.Fire(new NFTProtocolCreated { - AssertSenderIsParliamentDefaultAddress(); - InitialNFTTypeNameMap(); - var fullName = input.FullName; - Assert(input.ShortName.Length == 2, "Incorrect short name."); - Assert(State.NFTTypeFullNameMap[input.ShortName] == null, $"Short name {input.ShortName} already exists."); - Assert(State.NFTTypeShortNameMap[fullName] == null, $"Full name {fullName} already exists."); - State.NFTTypeFullNameMap[input.ShortName] = fullName; - State.NFTTypeShortNameMap[fullName] = input.ShortName; - var nftTypes = State.NFTTypes.Value; - nftTypes.Value.Add(input.ShortName, fullName); - State.NFTTypes.Value = nftTypes; - Context.Fire(new NFTTypeAdded - { - ShortName = input.ShortName, - FullName = input.FullName - }); - return new Empty(); - } + Symbol = input.Symbol, + Creator = nftProtocolInfo.Creator, + IsBurnable = nftProtocolInfo.IsBurnable, + IssueChainId = nftProtocolInfo.IssueChainId, + ProtocolName = nftProtocolInfo.ProtocolName, + TotalSupply = nftProtocolInfo.TotalSupply, + Metadata = nftProtocolInfo.Metadata, + BaseUri = nftProtocolInfo.BaseUri, + IsTokenIdReuse = isTokenIdReuse, + NftType = nftProtocolInfo.NftType + }); + return new Empty(); + } - public override Empty RemoveNFTType(StringValue input) + public override Empty AddNFTType(AddNFTTypeInput input) + { + AssertSenderIsParliamentDefaultAddress(); + InitialNFTTypeNameMap(); + var fullName = input.FullName; + Assert(input.ShortName.Length == 2, "Incorrect short name."); + Assert(State.NFTTypeFullNameMap[input.ShortName] == null, $"Short name {input.ShortName} already exists."); + Assert(State.NFTTypeShortNameMap[fullName] == null, $"Full name {fullName} already exists."); + State.NFTTypeFullNameMap[input.ShortName] = fullName; + State.NFTTypeShortNameMap[fullName] = input.ShortName; + var nftTypes = State.NFTTypes.Value; + nftTypes.Value.Add(input.ShortName, fullName); + State.NFTTypes.Value = nftTypes; + Context.Fire(new NFTTypeAdded { - AssertSenderIsParliamentDefaultAddress(); - InitialNFTTypeNameMap(); - Assert(input.Value.Length == 2, "Incorrect short name."); - Assert(State.NFTTypeFullNameMap[input.Value] != null, $"Short name {input.Value} does not exist."); - var fullName = State.NFTTypeFullNameMap[input.Value]; - State.NFTTypeFullNameMap.Remove(input.Value); - State.NFTTypeShortNameMap.Remove(fullName); - var nftTypes = State.NFTTypes.Value; - nftTypes.Value.Remove(input.Value); - State.NFTTypes.Value = nftTypes; - Context.Fire(new NFTTypeRemoved() - { - ShortName = input.Value, - }); - return new Empty(); - } + ShortName = input.ShortName, + FullName = input.FullName + }); + return new Empty(); + } - private void AssertSenderIsParliamentDefaultAddress() + public override Empty RemoveNFTType(StringValue input) + { + AssertSenderIsParliamentDefaultAddress(); + InitialNFTTypeNameMap(); + Assert(input.Value.Length == 2, "Incorrect short name."); + Assert(State.NFTTypeFullNameMap[input.Value] != null, $"Short name {input.Value} does not exist."); + var fullName = State.NFTTypeFullNameMap[input.Value]; + State.NFTTypeFullNameMap.Remove(input.Value); + State.NFTTypeShortNameMap.Remove(fullName); + var nftTypes = State.NFTTypes.Value; + nftTypes.Value.Remove(input.Value); + State.NFTTypes.Value = nftTypes; + Context.Fire(new NFTTypeRemoved { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } + ShortName = input.Value + }); + return new Empty(); + } - if (State.ParliamentDefaultAddress.Value == null) - { - State.ParliamentDefaultAddress.Value = - State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); - } + private void AssertSenderIsParliamentDefaultAddress() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - Assert(Context.Sender == State.ParliamentDefaultAddress.Value, "No permission."); - } + if (State.ParliamentDefaultAddress.Value == null) + State.ParliamentDefaultAddress.Value = + State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()); - private ExternalInfo GetTokenExternalInfo(CreateInput input) - { - if (input.Metadata != null) + Assert(Context.Sender == State.ParliamentDefaultAddress.Value, "No permission."); + } + + private ExternalInfo GetTokenExternalInfo(CreateInput input) + { + if (input.Metadata != null) AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); + + var tokenExternalInfo = input.Metadata == null + ? new ExternalInfo() + : new ExternalInfo { - AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); - } - - var tokenExternalInfo = input.Metadata == null - ? new ExternalInfo() - : new ExternalInfo - { - Value = {input.Metadata.Value} - }; - - // Add NFT Type to external info. - tokenExternalInfo.Value[NftTypeMetadataKey] = input.NftType; - // Add Uri to external info. - tokenExternalInfo.Value[NftBaseUriMetadataKey] = input.BaseUri; - tokenExternalInfo.Value[NftTokenIdReuseMetadataKey] = input.IsTokenIdReuse.ToString(); - return tokenExternalInfo; - } + Value = { input.Metadata.Value } + }; + + // Add NFT Type to external info. + tokenExternalInfo.Value[NftTypeMetadataKey] = input.NftType; + // Add Uri to external info. + tokenExternalInfo.Value[NftBaseUriMetadataKey] = input.BaseUri; + tokenExternalInfo.Value[NftTokenIdReuseMetadataKey] = input.IsTokenIdReuse.ToString(); + return tokenExternalInfo; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContract_Helpers.cs b/contract/AElf.Contracts.NFT/NFTContract_Helpers.cs index ae5898e8ef..6a1974023b 100644 --- a/contract/AElf.Contracts.NFT/NFTContract_Helpers.cs +++ b/contract/AElf.Contracts.NFT/NFTContract_Helpers.cs @@ -3,147 +3,122 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract { - public partial class NFTContract + private void MakeSureTokenContractAddressSet() { - private void MakeSureTokenContractAddressSet() - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - } + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + } - private void MakeSureRandomNumberProviderContractAddressSet() - { - if (State.RandomNumberProviderContract.Value == null) - { - State.RandomNumberProviderContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } - } + private void MakeSureRandomNumberProviderContractAddressSet() + { + if (State.RandomNumberProviderContract.Value == null) + State.RandomNumberProviderContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + } - private string GetSymbol(string nftType) + private string GetSymbol(string nftType) + { + var randomNumber = GenerateSymbolNumber(); + State.IsCreatedMap[randomNumber] = true; + var shortName = State.NFTTypeShortNameMap[nftType]; + if (shortName == null) { - var randomNumber = GenerateSymbolNumber(); - State.IsCreatedMap[randomNumber] = true; - var shortName = State.NFTTypeShortNameMap[nftType]; - if (shortName == null) - { - InitialNFTTypeNameMap(); - shortName = State.NFTTypeShortNameMap[nftType]; - if (shortName == null) - { - throw new AssertionException($"Short name of NFT Type {nftType} not found."); - } - } - - return $"{shortName}{randomNumber}"; + InitialNFTTypeNameMap(); + shortName = State.NFTTypeShortNameMap[nftType]; + if (shortName == null) throw new AssertionException($"Short name of NFT Type {nftType} not found."); } - private NFTTypes InitialNFTTypeNameMap() + return $"{shortName}{randomNumber}"; + } + + private NFTTypes InitialNFTTypeNameMap() + { + if (State.NFTTypes.Value != null) return State.NFTTypes.Value; + + var nftTypes = new NFTTypes(); + nftTypes.Value.Add("XX", NFTType.Any.ToString()); + nftTypes.Value.Add("AR", NFTType.Art.ToString()); + nftTypes.Value.Add("MU", NFTType.Music.ToString()); + nftTypes.Value.Add("DN", NFTType.DomainNames.ToString()); + nftTypes.Value.Add("VW", NFTType.VirtualWorlds.ToString()); + nftTypes.Value.Add("TC", NFTType.TradingCards.ToString()); + nftTypes.Value.Add("CO", NFTType.Collectables.ToString()); + nftTypes.Value.Add("SP", NFTType.Sports.ToString()); + nftTypes.Value.Add("UT", NFTType.Utility.ToString()); + nftTypes.Value.Add("BA", NFTType.Badges.ToString()); + State.NFTTypes.Value = nftTypes; + + foreach (var pair in nftTypes.Value) { - if (State.NFTTypes.Value != null) - { - return State.NFTTypes.Value; - } - - var nftTypes = new NFTTypes(); - nftTypes.Value.Add("XX", NFTType.Any.ToString()); - nftTypes.Value.Add("AR", NFTType.Art.ToString()); - nftTypes.Value.Add("MU", NFTType.Music.ToString()); - nftTypes.Value.Add("DN", NFTType.DomainNames.ToString()); - nftTypes.Value.Add("VW", NFTType.VirtualWorlds.ToString()); - nftTypes.Value.Add("TC", NFTType.TradingCards.ToString()); - nftTypes.Value.Add("CO", NFTType.Collectables.ToString()); - nftTypes.Value.Add("SP", NFTType.Sports.ToString()); - nftTypes.Value.Add("UT", NFTType.Utility.ToString()); - nftTypes.Value.Add("BA", NFTType.Badges.ToString()); - State.NFTTypes.Value = nftTypes; - - foreach (var pair in nftTypes.Value) - { - State.NFTTypeShortNameMap[pair.Value] = pair.Key; - State.NFTTypeFullNameMap[pair.Key] = pair.Value; - } - - return nftTypes; + State.NFTTypeShortNameMap[pair.Value] = pair.Key; + State.NFTTypeFullNameMap[pair.Key] = pair.Value; } - private long GenerateSymbolNumber() + return nftTypes; + } + + private long GenerateSymbolNumber() + { + var length = GetCurrentNumberLength(); + var from = 1L; + for (var i = 1; i < length; i++) from = from.Mul(10); + + var randomBytes = State.RandomNumberProviderContract.GetRandomBytes.Call(new Int64Value { - var length = GetCurrentNumberLength(); - var from = 1L; - for (var i = 1; i < length; i++) - { - from = from.Mul(10); - } - - var randomBytes = State.RandomNumberProviderContract.GetRandomBytes.Call(new Int64Value - { - Value = Context.CurrentHeight.Sub(1) - }.ToBytesValue()); - var randomHash = - HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(Context.Sender), - HashHelper.ComputeFrom(randomBytes)); - long randomNumber; - do - { - randomNumber = Context.ConvertHashToInt64(randomHash, from, from.Mul(10)); - } while (State.IsCreatedMap[randomNumber]); - - return randomNumber; - } + Value = Context.CurrentHeight.Sub(1) + }.ToBytesValue()); + var randomHash = + HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(Context.Sender), + HashHelper.ComputeFrom(randomBytes)); + long randomNumber; + do + { + randomNumber = Context.ConvertHashToInt64(randomHash, from, from.Mul(10)); + } while (State.IsCreatedMap[randomNumber]); + + return randomNumber; + } + + private int GetCurrentNumberLength() + { + if (State.CurrentSymbolNumberLength.Value == 0) State.CurrentSymbolNumberLength.Value = NumberMinLength; - private int GetCurrentNumberLength() + var flag = State.NftProtocolNumberFlag.Value; + + if (flag == 0) { - if (State.CurrentSymbolNumberLength.Value == 0) - { - State.CurrentSymbolNumberLength.Value = NumberMinLength; - } - - var flag = State.NftProtocolNumberFlag.Value; - - if (flag == 0) - { - // Initial protocol number flag. - var protocolNumber = 1; - for (var i = 1; i < State.CurrentSymbolNumberLength.Value; i++) - { - protocolNumber = protocolNumber.Mul(10); - } - - State.NftProtocolNumberFlag.Value = protocolNumber; - flag = protocolNumber; - } - - var upperNumberFlag = flag.Mul(2); - if (upperNumberFlag.ToString().Length > State.CurrentSymbolNumberLength.Value) - { - var newSymbolNumberLength = State.CurrentSymbolNumberLength.Value.Add(1); - State.CurrentSymbolNumberLength.Value = newSymbolNumberLength; - var protocolNumber = 1; - for (var i = 1; i < newSymbolNumberLength; i++) - { - protocolNumber = protocolNumber.Mul(10); - } - - State.NftProtocolNumberFlag.Value = protocolNumber; - return newSymbolNumberLength; - } - - return State.CurrentSymbolNumberLength.Value; + // Initial protocol number flag. + var protocolNumber = 1; + for (var i = 1; i < State.CurrentSymbolNumberLength.Value; i++) protocolNumber = protocolNumber.Mul(10); + + State.NftProtocolNumberFlag.Value = protocolNumber; + flag = protocolNumber; } - private void AssertMetadataKeysAreCorrect(IEnumerable metadataKeys) + var upperNumberFlag = flag.Mul(2); + if (upperNumberFlag.ToString().Length > State.CurrentSymbolNumberLength.Value) { - var reservedMetadataKey = GetNftMetadataReservedKeys(); - foreach (var metadataKey in metadataKeys) - { - Assert(!reservedMetadataKey.Contains(metadataKey), $"Metadata key {metadataKey} is reserved."); - } + var newSymbolNumberLength = State.CurrentSymbolNumberLength.Value.Add(1); + State.CurrentSymbolNumberLength.Value = newSymbolNumberLength; + var protocolNumber = 1; + for (var i = 1; i < newSymbolNumberLength; i++) protocolNumber = protocolNumber.Mul(10); + + State.NftProtocolNumberFlag.Value = protocolNumber; + return newSymbolNumberLength; } + + return State.CurrentSymbolNumberLength.Value; + } + + private void AssertMetadataKeysAreCorrect(IEnumerable metadataKeys) + { + var reservedMetadataKey = GetNftMetadataReservedKeys(); + foreach (var metadataKey in metadataKeys) + Assert(!reservedMetadataKey.Contains(metadataKey), $"Metadata key {metadataKey} is reserved."); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContract_UseChain.cs b/contract/AElf.Contracts.NFT/NFTContract_UseChain.cs index 3ff8327bfe..a0b0ab481b 100644 --- a/contract/AElf.Contracts.NFT/NFTContract_UseChain.cs +++ b/contract/AElf.Contracts.NFT/NFTContract_UseChain.cs @@ -5,524 +5,460 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract { - public partial class NFTContract + public override Hash Mint(MintInput input) { - public override Hash Mint(MintInput input) - { - if (input.Metadata != null && input.Metadata.Value.Any()) - { - AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); - } + if (input.Metadata != null && input.Metadata.Value.Any()) + AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); - var nftMinted = PerformMint(input); - return nftMinted.TokenHash; - } + var nftMinted = PerformMint(input); + return nftMinted.TokenHash; + } - public override Empty Transfer(TransferInput input) + public override Empty Transfer(TransferInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + DoTransfer(tokenHash, Context.Sender, input.To, input.Amount); + Context.Fire(new Transferred { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - DoTransfer(tokenHash, Context.Sender, input.To, input.Amount); - Context.Fire(new Transferred - { - From = Context.Sender, - To = input.To, - Amount = input.Amount, - Symbol = input.Symbol, - TokenId = input.TokenId, - Memo = input.Memo - }); - return new Empty(); - } + From = Context.Sender, + To = input.To, + Amount = input.Amount, + Symbol = input.Symbol, + TokenId = input.TokenId, + Memo = input.Memo + }); + return new Empty(); + } - /// - /// Throw Assertion Exception if amount is negative or balance insufficient. - /// Do nothing if amount is 0 or balance of from address is 0. - /// - /// - /// - /// - /// - /// - private void DoTransfer(Hash tokenHash, Address from, Address to, long amount) - { - if (amount < 0) - { - throw new AssertionException("Invalid transfer amount."); - } + /// + /// Throw Assertion Exception if amount is negative or balance insufficient. + /// Do nothing if amount is 0 or balance of from address is 0. + /// + /// + /// + /// + /// + /// + private void DoTransfer(Hash tokenHash, Address from, Address to, long amount) + { + if (amount < 0) throw new AssertionException("Invalid transfer amount."); - if (amount == 0) - { - return; - } + if (amount == 0) return; - Assert(State.BalanceMap[tokenHash][from] >= amount, "Insufficient balance."); - State.BalanceMap[tokenHash][from] = State.BalanceMap[tokenHash][from].Sub(amount); - State.BalanceMap[tokenHash][to] = State.BalanceMap[tokenHash][to].Add(amount); - } + Assert(State.BalanceMap[tokenHash][from] >= amount, "Insufficient balance."); + State.BalanceMap[tokenHash][from] = State.BalanceMap[tokenHash][from].Sub(amount); + State.BalanceMap[tokenHash][to] = State.BalanceMap[tokenHash][to].Add(amount); + } - public override Empty TransferFrom(TransferFromInput input) + public override Empty TransferFrom(TransferFromInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var operatorList = State.OperatorMap[input.Symbol][input.From]; + var isOperator = operatorList?.Value.Contains(Context.Sender) ?? false; + if (!isOperator) { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var operatorList = State.OperatorMap[input.Symbol][input.From]; - var isOperator = operatorList?.Value.Contains(Context.Sender) ?? false; - if (!isOperator) - { - var allowance = State.AllowanceMap[tokenHash][input.From][Context.Sender]; - Assert(allowance >= input.Amount, "Not approved."); - State.AllowanceMap[tokenHash][input.From][Context.Sender] = allowance.Sub(input.Amount); - } - - DoTransfer(tokenHash, input.From, input.To, input.Amount); - Context.Fire(new Transferred - { - From = input.From, - To = input.To, - Amount = input.Amount, - Symbol = input.Symbol, - TokenId = input.TokenId, - Memo = input.Memo - }); - return new Empty(); + var allowance = State.AllowanceMap[tokenHash][input.From][Context.Sender]; + Assert(allowance >= input.Amount, "Not approved."); + State.AllowanceMap[tokenHash][input.From][Context.Sender] = allowance.Sub(input.Amount); } - public override Empty Burn(BurnInput input) + DoTransfer(tokenHash, input.From, input.To, input.Amount); + Context.Fire(new Transferred { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var nftInfo = GetNFTInfoByTokenHash(tokenHash); - var nftProtocolInfo = State.NftProtocolMap[input.Symbol]; - Assert(nftProtocolInfo.IsBurnable, - $"NFT Protocol {nftProtocolInfo.ProtocolName} of symbol {nftProtocolInfo.Symbol} is not burnable."); - var minterList = State.MinterListMap[input.Symbol] ?? new MinterList(); - Assert( - State.BalanceMap[tokenHash][Context.Sender] >= input.Amount && - minterList.Value.Contains(Context.Sender), - "No permission."); - State.BalanceMap[tokenHash][Context.Sender] = State.BalanceMap[tokenHash][Context.Sender].Sub(input.Amount); - nftProtocolInfo.Supply = nftProtocolInfo.Supply.Sub(input.Amount); - nftInfo.Quantity = nftInfo.Quantity.Sub(input.Amount); - - State.NftProtocolMap[input.Symbol] = nftProtocolInfo; - if (nftInfo.Quantity == 0 && !nftProtocolInfo.IsTokenIdReuse) - { - nftInfo.IsBurned = true; - } + From = input.From, + To = input.To, + Amount = input.Amount, + Symbol = input.Symbol, + TokenId = input.TokenId, + Memo = input.Memo + }); + return new Empty(); + } + + public override Empty Burn(BurnInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var nftInfo = GetNFTInfoByTokenHash(tokenHash); + var nftProtocolInfo = State.NftProtocolMap[input.Symbol]; + Assert(nftProtocolInfo.IsBurnable, + $"NFT Protocol {nftProtocolInfo.ProtocolName} of symbol {nftProtocolInfo.Symbol} is not burnable."); + var minterList = State.MinterListMap[input.Symbol] ?? new MinterList(); + Assert( + State.BalanceMap[tokenHash][Context.Sender] >= input.Amount && + minterList.Value.Contains(Context.Sender), + "No permission."); + State.BalanceMap[tokenHash][Context.Sender] = State.BalanceMap[tokenHash][Context.Sender].Sub(input.Amount); + nftProtocolInfo.Supply = nftProtocolInfo.Supply.Sub(input.Amount); + nftInfo.Quantity = nftInfo.Quantity.Sub(input.Amount); + + State.NftProtocolMap[input.Symbol] = nftProtocolInfo; + if (nftInfo.Quantity == 0 && !nftProtocolInfo.IsTokenIdReuse) nftInfo.IsBurned = true; + + State.NftInfoMap[tokenHash] = nftInfo; + + Context.Fire(new Burned + { + Burner = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount, + TokenId = input.TokenId + }); + return new Empty(); + } - State.NftInfoMap[tokenHash] = nftInfo; + public override Hash Assemble(AssembleInput input) + { + if (input.Metadata != null && input.Metadata.Value.Any()) + AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); - Context.Fire(new Burned - { - Burner = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount, - TokenId = input.TokenId - }); - return new Empty(); - } + var metadata = input.Metadata ?? new Metadata(); - public override Hash Assemble(AssembleInput input) + if (input.AssembledNfts.Value.Any()) { - if (input.Metadata != null && input.Metadata.Value.Any()) - { - AssertMetadataKeysAreCorrect(input.Metadata.Value.Keys); + metadata.Value[AssembledNftsKey] = input.AssembledNfts.ToString(); + // Check owner. + foreach (var pair in input.AssembledNfts.Value) + { + var nftHash = Hash.LoadFromHex(pair.Key); + var nftInfo = GetNFTInfoByTokenHash(nftHash); + Assert(State.BalanceMap[nftHash][Context.Sender] >= pair.Value, + $"Insufficient balance of {nftInfo.Symbol}{nftInfo.TokenId}."); + DoTransfer(nftHash, Context.Sender, Context.Self, pair.Value); } + } - var metadata = input.Metadata ?? new Metadata(); - - if (input.AssembledNfts.Value.Any()) + if (input.AssembledFts.Value.Any()) + { + metadata.Value[AssembledFtsKey] = input.AssembledFts.ToString(); + // Check balance and allowance. + foreach (var pair in input.AssembledFts.Value) { - metadata.Value[AssembledNftsKey] = input.AssembledNfts.ToString(); - // Check owner. - foreach (var pair in input.AssembledNfts.Value) + var symbol = pair.Key; + var amount = pair.Value; + var balance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput { - var nftHash = Hash.LoadFromHex(pair.Key); - var nftInfo = GetNFTInfoByTokenHash(nftHash); - Assert(State.BalanceMap[nftHash][Context.Sender] >= pair.Value, - $"Insufficient balance of {nftInfo.Symbol}{nftInfo.TokenId}."); - DoTransfer(nftHash, Context.Sender, Context.Self, pair.Value); - } - } - - if (input.AssembledFts.Value.Any()) - { - metadata.Value[AssembledFtsKey] = input.AssembledFts.ToString(); - // Check balance and allowance. - foreach (var pair in input.AssembledFts.Value) + Owner = Context.Sender, + Symbol = symbol + }).Balance; + Assert(balance >= amount, $"Insufficient balance of {symbol}"); + var allowance = State.TokenContract.GetAllowance.Call(new MultiToken.GetAllowanceInput { - var symbol = pair.Key; - var amount = pair.Value; - var balance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput() - { - Owner = Context.Sender, - Symbol = symbol - }).Balance; - Assert(balance >= amount, $"Insufficient balance of {symbol}"); - var allowance = State.TokenContract.GetAllowance.Call((new MultiToken.GetAllowanceInput() - { - Owner = Context.Sender, - Spender = Context.Self, - Symbol = symbol - })).Allowance; - Assert(allowance >= amount, $"Insufficient allowance of {symbol}"); - State.TokenContract.TransferFrom.Send(new MultiToken.TransferFromInput - { - From = Context.Sender, - To = Context.Self, - Symbol = symbol, - Amount = amount - }); - } - } - - var mingInput = new MintInput - { - Symbol = input.Symbol, - Alias = input.Alias, - Owner = input.Owner, - Uri = input.Uri, - Metadata = metadata, - TokenId = input.TokenId - }; - - var nftMinted = PerformMint(mingInput, true); - if (input.AssembledNfts.Value.Any()) - { - State.AssembledNftsMap[nftMinted.TokenHash] = input.AssembledNfts; - } - - if (input.AssembledFts.Value.Any()) - { - State.AssembledFtsMap[nftMinted.TokenHash] = input.AssembledFts; + Owner = Context.Sender, + Spender = Context.Self, + Symbol = symbol + }).Allowance; + Assert(allowance >= amount, $"Insufficient allowance of {symbol}"); + State.TokenContract.TransferFrom.Send(new MultiToken.TransferFromInput + { + From = Context.Sender, + To = Context.Self, + Symbol = symbol, + Amount = amount + }); } - - Context.Fire(new Assembled - { - Symbol = input.Symbol, - TokenId = nftMinted.TokenId, - AssembledNfts = input.AssembledNfts, - AssembledFts = input.AssembledFts - }); - - return nftMinted.TokenHash; } - public override Empty Disassemble(DisassembleInput input) + var mingInput = new MintInput { - Burn(new BurnInput - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Amount = 1 - }); + Symbol = input.Symbol, + Alias = input.Alias, + Owner = input.Owner, + Uri = input.Uri, + Metadata = metadata, + TokenId = input.TokenId + }; - var receiver = input.Owner ?? Context.Sender; + var nftMinted = PerformMint(mingInput, true); + if (input.AssembledNfts.Value.Any()) State.AssembledNftsMap[nftMinted.TokenHash] = input.AssembledNfts; - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var assembledNfts = State.AssembledNftsMap[tokenHash].Clone(); - if (assembledNfts != null) - { - var nfts = assembledNfts; - foreach (var pair in nfts.Value) - { - DoTransfer(Hash.LoadFromHex(pair.Key), Context.Self, receiver, pair.Value); - } + if (input.AssembledFts.Value.Any()) State.AssembledFtsMap[nftMinted.TokenHash] = input.AssembledFts; - State.AssembledNftsMap.Remove(tokenHash); - } + Context.Fire(new Assembled + { + Symbol = input.Symbol, + TokenId = nftMinted.TokenId, + AssembledNfts = input.AssembledNfts, + AssembledFts = input.AssembledFts + }); - var assembledFts = State.AssembledFtsMap[tokenHash].Clone(); - if (assembledFts != null) - { - var fts = assembledFts; - foreach (var pair in fts.Value) - { - State.TokenContract.Transfer.Send(new MultiToken.TransferInput - { - Symbol = pair.Key, - Amount = pair.Value, - To = receiver - }); - } - - State.AssembledFtsMap.Remove(tokenHash); - } + return nftMinted.TokenHash; + } - Context.Fire(new Disassembled - { - Symbol = input.Symbol, - TokenId = input.TokenId, - DisassembledNfts = assembledNfts ?? new AssembledNfts(), - DisassembledFts = assembledFts ?? new AssembledFts() - }); + public override Empty Disassemble(DisassembleInput input) + { + Burn(new BurnInput + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Amount = 1 + }); - return new Empty(); - } + var receiver = input.Owner ?? Context.Sender; - public override Empty ApproveProtocol(ApproveProtocolInput input) + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var assembledNfts = State.AssembledNftsMap[tokenHash].Clone(); + if (assembledNfts != null) { - Assert(State.NftProtocolMap[input.Symbol] != null, $"Protocol {input.Symbol} not exists."); - var operatorList = State.OperatorMap[input.Symbol][Context.Sender] ?? new AddressList(); - switch (input.Approved) - { - case true when !operatorList.Value.Contains(input.Operator): - operatorList.Value.Add(input.Operator); - break; - case false when operatorList.Value.Contains(input.Operator): - operatorList.Value.Remove(input.Operator); - break; - } + var nfts = assembledNfts; + foreach (var pair in nfts.Value) DoTransfer(Hash.LoadFromHex(pair.Key), Context.Self, receiver, pair.Value); - State.OperatorMap[input.Symbol][Context.Sender] = operatorList; - return new Empty(); + State.AssembledNftsMap.Remove(tokenHash); } - public override Empty Recast(RecastInput input) + var assembledFts = State.AssembledFtsMap[tokenHash].Clone(); + if (assembledFts != null) { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var minterList = State.MinterListMap[input.Symbol] ?? new MinterList(); - Assert(minterList.Value.Contains(Context.Sender), "No permission."); - var nftInfo = GetNFTInfoByTokenHash(tokenHash); - Assert(nftInfo.Quantity != 0 && nftInfo.Quantity == State.BalanceMap[tokenHash][Context.Sender], - "Do not support recast."); - if (input.Alias != null) - { - nftInfo.Alias = input.Alias; - } - - if (input.Uri != null) - { - nftInfo.Uri = input.Uri; - } - - var oldMetadata = nftInfo.Metadata.Clone(); - var metadata = new Metadata(); - // Need to keep reserved metadata key. - foreach (var reservedKey in GetNftMetadataReservedKeys()) - { - if (oldMetadata.Value.ContainsKey(reservedKey)) + var fts = assembledFts; + foreach (var pair in fts.Value) + State.TokenContract.Transfer.Send(new MultiToken.TransferInput { - metadata.Value[reservedKey] = oldMetadata.Value[reservedKey]; - } + Symbol = pair.Key, + Amount = pair.Value, + To = receiver + }); - if (input.Metadata.Value.ContainsKey(reservedKey)) - { - input.Metadata.Value.Remove(reservedKey); - } - } + State.AssembledFtsMap.Remove(tokenHash); + } - metadata.Value.Add(input.Metadata.Value); - nftInfo.Metadata = metadata; + Context.Fire(new Disassembled + { + Symbol = input.Symbol, + TokenId = input.TokenId, + DisassembledNfts = assembledNfts ?? new AssembledNfts(), + DisassembledFts = assembledFts ?? new AssembledFts() + }); - State.NftInfoMap[tokenHash] = nftInfo; - Context.Fire(new Recasted - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OldMetadata = oldMetadata, - NewMetadata = nftInfo.Metadata, - Alias = nftInfo.Alias, - Uri = nftInfo.Uri - }); - return new Empty(); - } + return new Empty(); + } - public override Empty Approve(ApproveInput input) + public override Empty ApproveProtocol(ApproveProtocolInput input) + { + Assert(State.NftProtocolMap[input.Symbol] != null, $"Protocol {input.Symbol} not exists."); + var operatorList = State.OperatorMap[input.Symbol][Context.Sender] ?? new AddressList(); + switch (input.Approved) { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - State.AllowanceMap[tokenHash][Context.Sender][input.Spender] = input.Amount; - Context.Fire(new Approved - { - Owner = Context.Sender, - Spender = input.Spender, - Symbol = input.Symbol, - Amount = input.Amount, - TokenId = input.TokenId - }); - return new Empty(); + case true when !operatorList.Value.Contains(input.Operator): + operatorList.Value.Add(input.Operator); + break; + case false when operatorList.Value.Contains(input.Operator): + operatorList.Value.Remove(input.Operator); + break; } - public override Empty UnApprove(UnApproveInput input) - { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var oldAllowance = State.AllowanceMap[tokenHash][Context.Sender][input.Spender]; - var currentAllowance = oldAllowance.Sub(input.Amount); - if (currentAllowance <= 0) - { - currentAllowance = 0; - } + State.OperatorMap[input.Symbol][Context.Sender] = operatorList; + return new Empty(); + } - State.AllowanceMap[tokenHash][Context.Sender][input.Spender] = currentAllowance; + public override Empty Recast(RecastInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var minterList = State.MinterListMap[input.Symbol] ?? new MinterList(); + Assert(minterList.Value.Contains(Context.Sender), "No permission."); + var nftInfo = GetNFTInfoByTokenHash(tokenHash); + Assert(nftInfo.Quantity != 0 && nftInfo.Quantity == State.BalanceMap[tokenHash][Context.Sender], + "Do not support recast."); + if (input.Alias != null) nftInfo.Alias = input.Alias; + + if (input.Uri != null) nftInfo.Uri = input.Uri; + + var oldMetadata = nftInfo.Metadata.Clone(); + var metadata = new Metadata(); + // Need to keep reserved metadata key. + foreach (var reservedKey in GetNftMetadataReservedKeys()) + { + if (oldMetadata.Value.ContainsKey(reservedKey)) + metadata.Value[reservedKey] = oldMetadata.Value[reservedKey]; - Context.Fire(new UnApproved - { - Owner = Context.Sender, - Spender = input.Spender, - Symbol = input.Symbol, - CurrentAllowance = currentAllowance, - TokenId = input.TokenId - }); - return new Empty(); + if (input.Metadata.Value.ContainsKey(reservedKey)) input.Metadata.Value.Remove(reservedKey); } - private Hash CalculateTokenHash(string symbol, long tokenId) - { - return HashHelper.ComputeFrom($"{symbol}{tokenId}"); - } + metadata.Value.Add(input.Metadata.Value); + nftInfo.Metadata = metadata; - public override Empty AddMinters(AddMintersInput input) + State.NftInfoMap[tokenHash] = nftInfo; + Context.Fire(new Recasted { - var protocolInfo = State.NftProtocolMap[input.Symbol]; - Assert(Context.Sender == protocolInfo.Creator, "No permission."); - var minterList = State.MinterListMap[protocolInfo.Symbol] ?? new MinterList(); + Symbol = input.Symbol, + TokenId = input.TokenId, + OldMetadata = oldMetadata, + NewMetadata = nftInfo.Metadata, + Alias = nftInfo.Alias, + Uri = nftInfo.Uri + }); + return new Empty(); + } - foreach (var minter in input.MinterList.Value) - { - if (!minterList.Value.Contains(minter)) - { - minterList.Value.Add(minter); - } - } + public override Empty Approve(ApproveInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + State.AllowanceMap[tokenHash][Context.Sender][input.Spender] = input.Amount; + Context.Fire(new Approved + { + Owner = Context.Sender, + Spender = input.Spender, + Symbol = input.Symbol, + Amount = input.Amount, + TokenId = input.TokenId + }); + return new Empty(); + } - State.MinterListMap[input.Symbol] = minterList; + public override Empty UnApprove(UnApproveInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var oldAllowance = State.AllowanceMap[tokenHash][Context.Sender][input.Spender]; + var currentAllowance = oldAllowance.Sub(input.Amount); + if (currentAllowance <= 0) currentAllowance = 0; - Context.Fire(new MinterListAdded - { - Symbol = input.Symbol, - MinterList = input.MinterList - }); - return new Empty(); - } + State.AllowanceMap[tokenHash][Context.Sender][input.Spender] = currentAllowance; - public override Empty RemoveMinters(RemoveMintersInput input) + Context.Fire(new UnApproved { - var protocolInfo = State.NftProtocolMap[input.Symbol]; - Assert(Context.Sender == protocolInfo.Creator, "No permission."); - var minterList = State.MinterListMap[protocolInfo.Symbol]; - - foreach (var minter in input.MinterList.Value) - { - if (minterList.Value.Contains(minter)) - { - minterList.Value.Remove(minter); - } - } + Owner = Context.Sender, + Spender = input.Spender, + Symbol = input.Symbol, + CurrentAllowance = currentAllowance, + TokenId = input.TokenId + }); + return new Empty(); + } - State.MinterListMap[input.Symbol] = minterList; + private Hash CalculateTokenHash(string symbol, long tokenId) + { + return HashHelper.ComputeFrom($"{symbol}{tokenId}"); + } - Context.Fire(new MinterListRemoved - { - Symbol = input.Symbol, - MinterList = input.MinterList - }); - return new Empty(); - } + public override Empty AddMinters(AddMintersInput input) + { + var protocolInfo = State.NftProtocolMap[input.Symbol]; + Assert(Context.Sender == protocolInfo.Creator, "No permission."); + var minterList = State.MinterListMap[protocolInfo.Symbol] ?? new MinterList(); - private MinterList GetMinterList(TokenInfo tokenInfo) - { - var minterList = State.MinterListMap[tokenInfo.Symbol] ?? new MinterList(); - if (!minterList.Value.Contains(tokenInfo.Issuer)) - { - minterList.Value.Add(tokenInfo.Issuer); - } + foreach (var minter in input.MinterList.Value) + if (!minterList.Value.Contains(minter)) + minterList.Value.Add(minter); - return minterList; - } + State.MinterListMap[input.Symbol] = minterList; - private NFTMinted PerformMint(MintInput input, bool isTokenIdMustBeUnique = false) + Context.Fire(new MinterListAdded { - var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput - { - Symbol = input.Symbol - }); - var protocolInfo = State.NftProtocolMap[input.Symbol]; - if (protocolInfo == null) - { - throw new AssertionException($"Invalid NFT Token symbol: {input.Symbol}"); - } + Symbol = input.Symbol, + MinterList = input.MinterList + }); + return new Empty(); + } - var tokenId = input.TokenId == 0 ? protocolInfo.Issued.Add(1) : input.TokenId; - var tokenHash = CalculateTokenHash(input.Symbol, tokenId); - var nftInfo = State.NftInfoMap[tokenHash]; - if (!protocolInfo.IsTokenIdReuse || isTokenIdMustBeUnique) - { - Assert(nftInfo == null, $"Token id {tokenId} already exists. Please assign a different token id."); - } + public override Empty RemoveMinters(RemoveMintersInput input) + { + var protocolInfo = State.NftProtocolMap[input.Symbol]; + Assert(Context.Sender == protocolInfo.Creator, "No permission."); + var minterList = State.MinterListMap[protocolInfo.Symbol]; - var minterList = GetMinterList(tokenInfo); - Assert(minterList.Value.Contains(Context.Sender), "No permission to mint."); - Assert(tokenInfo.IssueChainId == Context.ChainId, "Incorrect chain."); + foreach (var minter in input.MinterList.Value) + if (minterList.Value.Contains(minter)) + minterList.Value.Remove(minter); - var quantity = input.Quantity > 0 ? input.Quantity : 1; - protocolInfo.Supply = protocolInfo.Supply.Add(quantity); - protocolInfo.Issued = protocolInfo.Issued.Add(quantity); - Assert(protocolInfo.Issued <= protocolInfo.TotalSupply, "Total supply exceeded."); - State.NftProtocolMap[input.Symbol] = protocolInfo; + State.MinterListMap[input.Symbol] = minterList; - // Inherit from protocol info. - var nftMetadata = protocolInfo.Metadata.Clone(); - if (input.Metadata != null) - { - foreach (var pair in input.Metadata.Value) - { - if (!nftMetadata.Value.ContainsKey(pair.Key)) - { - nftMetadata.Value[pair.Key] = pair.Value; - } - } - } + Context.Fire(new MinterListRemoved + { + Symbol = input.Symbol, + MinterList = input.MinterList + }); + return new Empty(); + } - if (nftInfo == null) - { - nftInfo = new NFTInfo - { - Symbol = input.Symbol, - Uri = input.Uri ?? string.Empty, - TokenId = tokenId, - Metadata = nftMetadata, - Minters = {Context.Sender}, - Quantity = quantity, - Alias = input.Alias, - - // No need. - //BaseUri = protocolInfo.BaseUri, - //Creator = protocolInfo.Creator, - //ProtocolName = protocolInfo.ProtocolName - }; - } - else - { - nftInfo.Quantity = nftInfo.Quantity.Add(quantity); - if (!nftInfo.Minters.Contains(Context.Sender)) - { - nftInfo.Minters.Add(Context.Sender); - } - } + private MinterList GetMinterList(TokenInfo tokenInfo) + { + var minterList = State.MinterListMap[tokenInfo.Symbol] ?? new MinterList(); + if (!minterList.Value.Contains(tokenInfo.Issuer)) minterList.Value.Add(tokenInfo.Issuer); - State.NftInfoMap[tokenHash] = nftInfo; - var owner = input.Owner ?? Context.Sender; - State.BalanceMap[tokenHash][owner] = State.BalanceMap[tokenHash][owner].Add(quantity); + return minterList; + } - var nftMinted = new NFTMinted + private NFTMinted PerformMint(MintInput input, bool isTokenIdMustBeUnique = false) + { + var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput + { + Symbol = input.Symbol + }); + var protocolInfo = State.NftProtocolMap[input.Symbol]; + if (protocolInfo == null) throw new AssertionException($"Invalid NFT Token symbol: {input.Symbol}"); + + var tokenId = input.TokenId == 0 ? protocolInfo.Issued.Add(1) : input.TokenId; + var tokenHash = CalculateTokenHash(input.Symbol, tokenId); + var nftInfo = State.NftInfoMap[tokenHash]; + if (!protocolInfo.IsTokenIdReuse || isTokenIdMustBeUnique) + Assert(nftInfo == null, $"Token id {tokenId} already exists. Please assign a different token id."); + + var minterList = GetMinterList(tokenInfo); + Assert(minterList.Value.Contains(Context.Sender), "No permission to mint."); + Assert(tokenInfo.IssueChainId == Context.ChainId, "Incorrect chain."); + + var quantity = input.Quantity > 0 ? input.Quantity : 1; + protocolInfo.Supply = protocolInfo.Supply.Add(quantity); + protocolInfo.Issued = protocolInfo.Issued.Add(quantity); + Assert(protocolInfo.Issued <= protocolInfo.TotalSupply, "Total supply exceeded."); + State.NftProtocolMap[input.Symbol] = protocolInfo; + + // Inherit from protocol info. + var nftMetadata = protocolInfo.Metadata.Clone(); + if (input.Metadata != null) + foreach (var pair in input.Metadata.Value) + if (!nftMetadata.Value.ContainsKey(pair.Key)) + nftMetadata.Value[pair.Key] = pair.Value; + + if (nftInfo == null) + { + nftInfo = new NFTInfo { Symbol = input.Symbol, - ProtocolName = protocolInfo.ProtocolName, + Uri = input.Uri ?? string.Empty, TokenId = tokenId, Metadata = nftMetadata, - Owner = owner, - Minter = Context.Sender, + Minters = { Context.Sender }, Quantity = quantity, - Alias = input.Alias, - BaseUri = protocolInfo.BaseUri, - Uri = input.Uri ?? string.Empty, - Creator = protocolInfo.Creator, - NftType = protocolInfo.NftType, - TotalQuantity = nftInfo.Quantity, - TokenHash = tokenHash - }; - Context.Fire(nftMinted); + Alias = input.Alias - return nftMinted; + // No need. + //BaseUri = protocolInfo.BaseUri, + //Creator = protocolInfo.Creator, + //ProtocolName = protocolInfo.ProtocolName + }; } + else + { + nftInfo.Quantity = nftInfo.Quantity.Add(quantity); + if (!nftInfo.Minters.Contains(Context.Sender)) nftInfo.Minters.Add(Context.Sender); + } + + State.NftInfoMap[tokenHash] = nftInfo; + var owner = input.Owner ?? Context.Sender; + State.BalanceMap[tokenHash][owner] = State.BalanceMap[tokenHash][owner].Add(quantity); + + var nftMinted = new NFTMinted + { + Symbol = input.Symbol, + ProtocolName = protocolInfo.ProtocolName, + TokenId = tokenId, + Metadata = nftMetadata, + Owner = owner, + Minter = Context.Sender, + Quantity = quantity, + Alias = input.Alias, + BaseUri = protocolInfo.BaseUri, + Uri = input.Uri ?? string.Empty, + Creator = protocolInfo.Creator, + NftType = protocolInfo.NftType, + TotalQuantity = nftInfo.Quantity, + TokenHash = tokenHash + }; + Context.Fire(nftMinted); + + return nftMinted; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFT/NFTContract_View.cs b/contract/AElf.Contracts.NFT/NFTContract_View.cs index 5d4ec12dd1..2ad97f2250 100644 --- a/contract/AElf.Contracts.NFT/NFTContract_View.cs +++ b/contract/AElf.Contracts.NFT/NFTContract_View.cs @@ -2,108 +2,107 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContract { - public partial class NFTContract + public override NFTProtocolInfo GetNFTProtocolInfo(StringValue input) { - public override NFTProtocolInfo GetNFTProtocolInfo(StringValue input) - { - return State.NftProtocolMap[input.Value]; - } + return State.NftProtocolMap[input.Value]; + } - public override NFTInfo GetNFTInfo(GetNFTInfoInput input) - { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - return GetNFTInfoByTokenHash(tokenHash); - } + public override NFTInfo GetNFTInfo(GetNFTInfoInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + return GetNFTInfoByTokenHash(tokenHash); + } - public override NFTInfo GetNFTInfoByTokenHash(Hash input) - { - var nftInfo = State.NftInfoMap[input]; - if (nftInfo == null) return new NFTInfo(); - var nftProtocolInfo = State.NftProtocolMap[nftInfo.Symbol]; - nftInfo.ProtocolName = nftProtocolInfo.ProtocolName; - nftInfo.Creator = nftProtocolInfo.Creator; - nftInfo.BaseUri = nftProtocolInfo.BaseUri; - nftInfo.NftType = nftProtocolInfo.NftType; - return nftInfo; - } + public override NFTInfo GetNFTInfoByTokenHash(Hash input) + { + var nftInfo = State.NftInfoMap[input]; + if (nftInfo == null) return new NFTInfo(); + var nftProtocolInfo = State.NftProtocolMap[nftInfo.Symbol]; + nftInfo.ProtocolName = nftProtocolInfo.ProtocolName; + nftInfo.Creator = nftProtocolInfo.Creator; + nftInfo.BaseUri = nftProtocolInfo.BaseUri; + nftInfo.NftType = nftProtocolInfo.NftType; + return nftInfo; + } - public override GetBalanceOutput GetBalance(GetBalanceInput input) + public override GetBalanceOutput GetBalance(GetBalanceInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + var balance = State.BalanceMap[tokenHash][input.Owner]; + return new GetBalanceOutput { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - var balance = State.BalanceMap[tokenHash][input.Owner]; - return new GetBalanceOutput - { - Owner = input.Owner, - Balance = balance, - TokenHash = tokenHash - }; - } + Owner = input.Owner, + Balance = balance, + TokenHash = tokenHash + }; + } - public override GetBalanceOutput GetBalanceByTokenHash(GetBalanceByTokenHashInput input) + public override GetBalanceOutput GetBalanceByTokenHash(GetBalanceByTokenHashInput input) + { + return new GetBalanceOutput { - return new GetBalanceOutput - { - Owner = input.Owner, - Balance = State.BalanceMap[input.TokenHash][input.Owner], - TokenHash = input.TokenHash - }; - } + Owner = input.Owner, + Balance = State.BalanceMap[input.TokenHash][input.Owner], + TokenHash = input.TokenHash + }; + } - public override GetAllowanceOutput GetAllowance(GetAllowanceInput input) + public override GetAllowanceOutput GetAllowance(GetAllowanceInput input) + { + var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); + return new GetAllowanceOutput { - var tokenHash = CalculateTokenHash(input.Symbol, input.TokenId); - return new GetAllowanceOutput - { - Owner = input.Owner, - Spender = input.Spender, - TokenHash = tokenHash, - Allowance = State.AllowanceMap[tokenHash][input.Owner][input.Spender] - }; - } + Owner = input.Owner, + Spender = input.Spender, + TokenHash = tokenHash, + Allowance = State.AllowanceMap[tokenHash][input.Owner][input.Spender] + }; + } - public override GetAllowanceOutput GetAllowanceByTokenHash(GetAllowanceByTokenHashInput input) + public override GetAllowanceOutput GetAllowanceByTokenHash(GetAllowanceByTokenHashInput input) + { + return new GetAllowanceOutput { - return new GetAllowanceOutput - { - Owner = input.Owner, - Spender = input.Spender, - TokenHash = input.TokenHash, - Allowance = State.AllowanceMap[input.TokenHash][input.Owner][input.Spender] - }; - } + Owner = input.Owner, + Spender = input.Spender, + TokenHash = input.TokenHash, + Allowance = State.AllowanceMap[input.TokenHash][input.Owner][input.Spender] + }; + } - public override MinterList GetMinterList(StringValue input) - { - return State.MinterListMap[input.Value]; - } + public override MinterList GetMinterList(StringValue input) + { + return State.MinterListMap[input.Value]; + } - public override Hash CalculateTokenHash(CalculateTokenHashInput input) - { - return CalculateTokenHash(input.Symbol, input.TokenId); - } + public override Hash CalculateTokenHash(CalculateTokenHashInput input) + { + return CalculateTokenHash(input.Symbol, input.TokenId); + } - public override NFTTypes GetNFTTypes(Empty input) - { - return State.NFTTypes.Value ?? InitialNFTTypeNameMap(); - } + public override NFTTypes GetNFTTypes(Empty input) + { + return State.NFTTypes.Value ?? InitialNFTTypeNameMap(); + } - public override AddressList GetOperatorList(GetOperatorListInput input) - { - return State.OperatorMap[input.Symbol][input.Owner]; - } + public override AddressList GetOperatorList(GetOperatorListInput input) + { + return State.OperatorMap[input.Symbol][input.Owner]; + } - private List GetNftMetadataReservedKeys() + private List GetNftMetadataReservedKeys() + { + return new List { - return new List - { - NftTypeMetadataKey, - NftBaseUriMetadataKey, - AssembledNftsKey, - AssembledFtsKey, - NftTokenIdReuseMetadataKey - }; - } + NftTypeMetadataKey, + NftBaseUriMetadataKey, + AssembledNftsKey, + AssembledFtsKey, + NftTokenIdReuseMetadataKey + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/AElf.Contracts.NFTMarket.csproj b/contract/AElf.Contracts.NFTMarket/AElf.Contracts.NFTMarket.csproj index cdc2212ebe..3586317afd 100644 --- a/contract/AElf.Contracts.NFTMarket/AElf.Contracts.NFTMarket.csproj +++ b/contract/AElf.Contracts.NFTMarket/AElf.Contracts.NFTMarket.csproj @@ -1,5 +1,5 @@ - + net6.0 diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract.cs index 3e2a2577af..84d6c11d08 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract.cs @@ -1,59 +1,55 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract : NFTMarketContractContainer.NFTMarketContractBase { - public partial class NFTMarketContract : NFTMarketContractContainer.NFTMarketContractBase + public override Empty Initialize(InitializeInput input) { - public override Empty Initialize(InitializeInput input) + Assert(State.NFTContract.Value == null, "Already initialized."); + State.NFTContract.Value = input.NftContractAddress; + State.Admin.Value = input.AdminAddress ?? Context.Sender; + State.ServiceFeeRate.Value = input.ServiceFeeRate == 0 ? DefaultServiceFeeRate : input.ServiceFeeRate; + State.ServiceFeeReceiver.Value = input.ServiceFeeReceiver ?? State.Admin.Value; + State.ServiceFee.Value = input.ServiceFee == 0 ? DefaultServiceFeeAmount : input.ServiceFee; + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.GlobalTokenWhiteList.Value = new StringList { - Assert(State.NFTContract.Value == null, "Already initialized."); - State.NFTContract.Value = input.NftContractAddress; - State.Admin.Value = input.AdminAddress ?? Context.Sender; - State.ServiceFeeRate.Value = input.ServiceFeeRate == 0 ? DefaultServiceFeeRate : input.ServiceFeeRate; - State.ServiceFeeReceiver.Value = input.ServiceFeeReceiver ?? State.Admin.Value; - State.ServiceFee.Value = input.ServiceFee == 0 ? DefaultServiceFeeAmount : input.ServiceFee; - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.GlobalTokenWhiteList.Value = new StringList - { - Value = {Context.Variables.NativeSymbol} - }; - return new Empty(); - } + Value = { Context.Variables.NativeSymbol } + }; + return new Empty(); + } - public override Empty SetServiceFee(SetServiceFeeInput input) - { - AssertSenderIsAdmin(); - State.ServiceFeeRate.Value = input.ServiceFeeRate; - State.ServiceFeeReceiver.Value = input.ServiceFeeReceiver ?? State.Admin.Value; - return new Empty(); - } + public override Empty SetServiceFee(SetServiceFeeInput input) + { + AssertSenderIsAdmin(); + State.ServiceFeeRate.Value = input.ServiceFeeRate; + State.ServiceFeeReceiver.Value = input.ServiceFeeReceiver ?? State.Admin.Value; + return new Empty(); + } - public override Empty SetGlobalTokenWhiteList(StringList input) + public override Empty SetGlobalTokenWhiteList(StringList input) + { + AssertSenderIsAdmin(); + if (!input.Value.Contains(Context.Variables.NativeSymbol)) input.Value.Add(Context.Variables.NativeSymbol); + State.GlobalTokenWhiteList.Value = input; + Context.Fire(new GlobalTokenWhiteListChanged { - AssertSenderIsAdmin(); - if (!input.Value.Contains(Context.Variables.NativeSymbol)) - { - input.Value.Add(Context.Variables.NativeSymbol); - } - State.GlobalTokenWhiteList.Value = input; - Context.Fire(new GlobalTokenWhiteListChanged - { - TokenWhiteList = input - }); - return new Empty(); - } + TokenWhiteList = input + }); + return new Empty(); + } - private void AssertSenderIsAdmin() - { - AssertContractInitialized(); - Assert(Context.Sender == State.Admin.Value, "No permission."); - } + private void AssertSenderIsAdmin() + { + AssertContractInitialized(); + Assert(Context.Sender == State.Admin.Value, "No permission."); + } - private void AssertContractInitialized() - { - Assert(State.Admin.Value != null, "Contract not initialized."); - } + private void AssertContractInitialized() + { + Assert(State.Admin.Value != null, "Contract not initialized."); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContractConstants.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContractConstants.cs index f9bd31793d..9d9f9ada08 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContractConstants.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContractConstants.cs @@ -1,11 +1,10 @@ -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract - { - private const int FeeDenominator = 10000; - private const int DefaultExpireDays = 100000; - private const int DefaultServiceFeeRate = 10; - private const int DefaultServiceFeeAmount = 1_00000000; - private const int DefaultDepositConfirmRate = FeeDenominator / 2; - } + private const int FeeDenominator = 10000; + private const int DefaultExpireDays = 100000; + private const int DefaultServiceFeeRate = 10; + private const int DefaultServiceFeeAmount = 1_00000000; + private const int DefaultDepositConfirmRate = FeeDenominator / 2; } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContractReferenceState.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContractReferenceState.cs index 8a785523b1..aae9b72c61 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContractReferenceState.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContractReferenceState.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.NFT; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContractState { - public partial class NFTMarketContractState - { - internal NFTContractContainer.NFTContractReferenceState NFTContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal NFTContractContainer.NFTContractReferenceState NFTContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContractState.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContractState.cs index 2d189061cb..d7e0db1814 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContractState.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContractState.cs @@ -1,56 +1,55 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContractState : ContractState { - public partial class NFTMarketContractState : ContractState - { - public SingletonState
Admin { get; set; } + public SingletonState
Admin { get; set; } - public SingletonState
ServiceFeeReceiver { get; set; } + public SingletonState
ServiceFeeReceiver { get; set; } - public Int32State ServiceFeeRate { get; set; } - public Int64State ServiceFee { get; set; } + public Int32State ServiceFeeRate { get; set; } + public Int64State ServiceFee { get; set; } - public SingletonState GlobalTokenWhiteList { get; set; } + public SingletonState GlobalTokenWhiteList { get; set; } - /// - /// Symbol -> Token Id -> Owner -> List NFT Info List - /// - public MappedState ListedNFTInfoListMap { get; set; } + /// + /// Symbol -> Token Id -> Owner -> List NFT Info List + /// + public MappedState ListedNFTInfoListMap { get; set; } - /// - /// Symbol -> Token Id -> Owner -> White List Address Price List - /// - public MappedState WhiteListAddressPriceListMap { get; set; } + /// + /// Symbol -> Token Id -> Owner -> White List Address Price List + /// + public MappedState WhiteListAddressPriceListMap { get; set; } - /// - /// Symbol -> Token Id -> Offer Address List - /// - public MappedState OfferAddressListMap { get; set; } + /// + /// Symbol -> Token Id -> Offer Address List + /// + public MappedState OfferAddressListMap { get; set; } - /// - /// Symbol -> Token Id -> Offer Maker -> Offer List - /// - public MappedState OfferListMap { get; set; } + /// + /// Symbol -> Token Id -> Offer Maker -> Offer List + /// + public MappedState OfferListMap { get; set; } - public MappedState BidMap { get; set; } + public MappedState BidMap { get; set; } - public MappedState BidAddressListMap { get; set; } + public MappedState BidAddressListMap { get; set; } - /// - /// Symbol -> Token Id -> Royalty - /// - public MappedState RoyaltyMap { get; set; } + /// + /// Symbol -> Token Id -> Royalty + /// + public MappedState RoyaltyMap { get; set; } - public MappedState RoyaltyFeeReceiverMap { get; set; } - public MappedState CertainNFTRoyaltyMap { get; set; } - public MappedState TokenWhiteListMap { get; set; } + public MappedState RoyaltyFeeReceiverMap { get; set; } + public MappedState CertainNFTRoyaltyMap { get; set; } + public MappedState TokenWhiteListMap { get; set; } - public MappedState CustomizeInfoMap { get; set; } - public MappedState RequestInfoMap { get; set; } + public MappedState CustomizeInfoMap { get; set; } + public MappedState RequestInfoMap { get; set; } - public MappedState EnglishAuctionInfoMap { get; set; } - public MappedState DutchAuctionInfoMap { get; set; } - } + public MappedState EnglishAuctionInfoMap { get; set; } + public MappedState DutchAuctionInfoMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_ACS1.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_ACS1.cs index 9311291e23..7e951c8de4 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_ACS1.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_ACS1.cs @@ -1,32 +1,31 @@ using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + public override Empty SetMethodFee(MethodFees input) { - #region Views - - public override MethodFees GetMethodFee(StringValue input) - { - return new MethodFees(); - } + return new Empty(); + } - public override AuthorityInfo GetMethodFeeController(Empty input) - { - return new AuthorityInfo(); - } + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + return new Empty(); + } - #endregion + #region Views - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return new MethodFees(); + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - return new Empty(); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + return new AuthorityInfo(); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Buyers.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Buyers.cs index d5889f6e1b..3117d2a5c7 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Buyers.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Buyers.cs @@ -10,592 +10,519 @@ using TransferFromInput = AElf.Contracts.MultiToken.TransferFromInput; using TransferInput = AElf.Contracts.MultiToken.TransferInput; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + /// + /// There are 2 types of making offer. + /// 1. Aiming a owner. + /// 2. Only aiming nft. Owner will be the nft protocol creator. + /// + /// + /// + public override Empty MakeOffer(MakeOfferInput input) { - /// - /// There are 2 types of making offer. - /// 1. Aiming a owner. - /// 2. Only aiming nft. Owner will be the nft protocol creator. - /// - /// - /// - public override Empty MakeOffer(MakeOfferInput input) - { - AssertContractInitialized(); + AssertContractInitialized(); - Assert(Context.Sender != input.OfferTo, "Origin owner cannot be sender himself."); + Assert(Context.Sender != input.OfferTo, "Origin owner cannot be sender himself."); - var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }); + var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput + { + Symbol = input.Symbol, + TokenId = input.TokenId + }); - if (nftInfo.Quantity != 0 && input.OfferTo == null) - { - input.OfferTo = nftInfo.Creator; - } + if (nftInfo.Quantity != 0 && input.OfferTo == null) input.OfferTo = nftInfo.Creator; - var protocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = input.Symbol}); + var protocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); - if (nftInfo.Quantity == 0 && !protocolInfo.IsTokenIdReuse && input.Quantity == 1) - { - // NFT not minted. - PerformRequestNewItem(input.Symbol, input.TokenId, input.Price, input.ExpireTime); - return new Empty(); - } + if (nftInfo.Quantity == 0 && !protocolInfo.IsTokenIdReuse && input.Quantity == 1) + { + // NFT not minted. + PerformRequestNewItem(input.Symbol, input.TokenId, input.Price, input.ExpireTime); + return new Empty(); + } - Assert(nftInfo.Quantity > 0, "NFT does not exist."); + Assert(nftInfo.Quantity > 0, "NFT does not exist."); - var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.OfferTo]; + var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.OfferTo]; - if (listedNftInfoList == null || listedNftInfoList.Value.All(i => i.ListType == ListType.NotListed)) - { - // NFT not listed by the owner. - PerformMakeOffer(input); - return new Empty(); - } + if (listedNftInfoList == null || listedNftInfoList.Value.All(i => i.ListType == ListType.NotListed)) + { + // NFT not listed by the owner. + PerformMakeOffer(input); + return new Empty(); + } - var validListedNftInfoList = listedNftInfoList.Value.Where(i => - (i.Price.Symbol == input.Price.Symbol && i.Price.Amount <= input.Price.Amount || - i.ListType != ListType.FixedPrice) && - !IsListedNftTimedOut(i)).ToList(); - ListedNFTInfo listedNftInfo; - if (validListedNftInfoList.Any()) - { - listedNftInfo = validListedNftInfoList.First(); + var validListedNftInfoList = listedNftInfoList.Value.Where(i => + ((i.Price.Symbol == input.Price.Symbol && i.Price.Amount <= input.Price.Amount) || + i.ListType != ListType.FixedPrice) && + !IsListedNftTimedOut(i)).ToList(); + ListedNFTInfo listedNftInfo; + if (validListedNftInfoList.Any()) + { + listedNftInfo = validListedNftInfoList.First(); - if (validListedNftInfoList.Count > 1) - { - var totalQuantity = validListedNftInfoList.Sum(i => i.Quantity); - listedNftInfo.Quantity = totalQuantity; - } - } - else + if (validListedNftInfoList.Count > 1) { - listedNftInfo = listedNftInfoList.Value.First(); + var totalQuantity = validListedNftInfoList.Sum(i => i.Quantity); + listedNftInfo.Quantity = totalQuantity; } + } + else + { + listedNftInfo = listedNftInfoList.Value.First(); + } - var whiteListAddressPriceList = - State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo]; + var whiteListAddressPriceList = + State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo]; - if (listedNftInfo == null || listedNftInfo.ListType == ListType.NotListed) + if (listedNftInfo == null || listedNftInfo.ListType == ListType.NotListed) + { + if (whiteListAddressPriceList == null) { - if (whiteListAddressPriceList == null) - { - PerformMakeOffer(input); - return new Empty(); - } - - var maybeWhiteListAddressPrice = - whiteListAddressPriceList.Value.SingleOrDefault(p => - p.Address == Context.Sender && p.Price.Amount <= input.Price.Amount && - p.Price.Symbol == input.Price.Symbol); - if (maybeWhiteListAddressPrice != null) - { - listedNftInfo = new ListedNFTInfo - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Price = maybeWhiteListAddressPrice.Price, - ListType = ListType.FixedPrice, - Quantity = 1, - Owner = listedNftInfoList.Value.First().Owner, - Duration = listedNftInfoList.Value.First().Duration - }; - } - else - { - PerformMakeOffer(input); - return new Empty(); - } + PerformMakeOffer(input); + return new Empty(); } - var quantity = input.Quantity; - if (quantity > listedNftInfo.Quantity) + var maybeWhiteListAddressPrice = + whiteListAddressPriceList.Value.SingleOrDefault(p => + p.Address == Context.Sender && p.Price.Amount <= input.Price.Amount && + p.Price.Symbol == input.Price.Symbol); + if (maybeWhiteListAddressPrice != null) { - var makerOfferInput = input.Clone(); - makerOfferInput.Quantity = quantity.Sub(listedNftInfo.Quantity); - PerformMakeOffer(makerOfferInput); - input.Quantity = listedNftInfo.Quantity; + listedNftInfo = new ListedNFTInfo + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Price = maybeWhiteListAddressPrice.Price, + ListType = ListType.FixedPrice, + Quantity = 1, + Owner = listedNftInfoList.Value.First().Owner, + Duration = listedNftInfoList.Value.First().Duration + }; } - - if (IsListedNftTimedOut(listedNftInfo)) + else { PerformMakeOffer(input); return new Empty(); } + } - switch (listedNftInfo.ListType) - { - case ListType.FixedPrice when whiteListAddressPriceList != null && - whiteListAddressPriceList.Value.Any(p => p.Address == Context.Sender): - if (TryDealWithFixedPrice(input, listedNftInfo, out var actualQuantity)) - { - MaybeRemoveRequest(input.Symbol, input.TokenId); - listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(actualQuantity); - if (listedNftInfo.Quantity == 0 && listedNftInfoList.Value.Contains(listedNftInfo)) - { - listedNftInfoList.Value.Remove(listedNftInfo); - Context.Fire(new ListedNFTRemoved - { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner - }); - } - } - - break; - case ListType.FixedPrice when input.Price.Symbol == listedNftInfo.Price.Symbol && - input.Price.Amount >= listedNftInfo.Price.Amount: - input.Price.Amount = Math.Min(input.Price.Amount, listedNftInfo.Price.Amount); - input.Quantity = Math.Min(input.Quantity, listedNftInfo.Quantity); - if (TryDealWithFixedPrice(input, listedNftInfo, out var dealQuantity)) - { - listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(dealQuantity); - if (listedNftInfo.Quantity == 0) - { - listedNftInfoList.Value.Remove(listedNftInfo); - Context.Fire(new ListedNFTRemoved - { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner - }); - } - } - - break; - - case ListType.EnglishAuction: - TryPlaceBidForEnglishAuction(input); - break; - case ListType.DutchAuction: - if (PerformMakeOfferToDutchAuction(input)) - { - listedNftInfoList.Value.Remove(listedNftInfo); - } - - break; - default: - PerformMakeOffer(input); - break; - } - - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.OfferTo] = listedNftInfoList; + var quantity = input.Quantity; + if (quantity > listedNftInfo.Quantity) + { + var makerOfferInput = input.Clone(); + makerOfferInput.Quantity = quantity.Sub(listedNftInfo.Quantity); + PerformMakeOffer(makerOfferInput); + input.Quantity = listedNftInfo.Quantity; + } + if (IsListedNftTimedOut(listedNftInfo)) + { + PerformMakeOffer(input); return new Empty(); } - public override Empty CancelOffer(CancelOfferInput input) + switch (listedNftInfo.ListType) { - AssertContractInitialized(); - - OfferList offerList; - var newOfferList = new OfferList(); - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - - // Admin can remove expired offer. - if (input.OfferFrom != null && input.OfferFrom != Context.Sender) - { - AssertSenderIsAdmin(); - - offerList = State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom]; - - if (offerList != null) + case ListType.FixedPrice when whiteListAddressPriceList != null && + whiteListAddressPriceList.Value.Any(p => p.Address == Context.Sender): + if (TryDealWithFixedPrice(input, listedNftInfo, out var actualQuantity)) { - foreach (var offer in offerList.Value) + MaybeRemoveRequest(input.Symbol, input.TokenId); + listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(actualQuantity); + if (listedNftInfo.Quantity == 0 && listedNftInfoList.Value.Contains(listedNftInfo)) { - if (offer.ExpireTime >= Context.CurrentBlockTime) - { - newOfferList.Value.Add(offer); - } - else + listedNftInfoList.Value.Remove(listedNftInfo); + Context.Fire(new ListedNFTRemoved { - Context.Fire(new OfferRemoved - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = offer.From, - OfferTo = offer.To, - ExpireTime = offer.ExpireTime - }); - } + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner + }); } - - State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom] = newOfferList; } - if (requestInfo != null && !requestInfo.IsConfirmed && - requestInfo.ExpireTime > Context.CurrentBlockTime) + break; + case ListType.FixedPrice when input.Price.Symbol == listedNftInfo.Price.Symbol && + input.Price.Amount >= listedNftInfo.Price.Amount: + input.Price.Amount = Math.Min(input.Price.Amount, listedNftInfo.Price.Amount); + input.Quantity = Math.Min(input.Quantity, listedNftInfo.Quantity); + if (TryDealWithFixedPrice(input, listedNftInfo, out var dealQuantity)) { - MaybeRemoveRequest(input.Symbol, input.TokenId); - var protocolVirtualAddressFrom = CalculateTokenHash(input.Symbol); - var protocolVirtualAddress = - Context.ConvertVirtualAddressToContractAddress(protocolVirtualAddressFrom); - var balanceOfNftProtocolVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Symbol = requestInfo.Price.Symbol, - Owner = protocolVirtualAddress - }).Balance; - - if (balanceOfNftProtocolVirtualAddress > 0) + listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(dealQuantity); + if (listedNftInfo.Quantity == 0) { - State.TokenContract.Transfer.VirtualSend(protocolVirtualAddressFrom, new TransferInput + listedNftInfoList.Value.Remove(listedNftInfo); + Context.Fire(new ListedNFTRemoved { - To = requestInfo.Requester, - Symbol = requestInfo.Price.Symbol, - Amount = balanceOfNftProtocolVirtualAddress + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner }); } - - Context.Fire(new NFTRequestCancelled - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Requester = Context.Sender - }); } - var bid = State.BidMap[input.Symbol][input.TokenId][input.OfferFrom]; + break; - if (bid != null) - { - if (bid.ExpireTime < Context.CurrentBlockTime) - { - State.BidMap[input.Symbol][input.TokenId].Remove(input.OfferFrom); - var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - if (auctionInfo != null && auctionInfo.EarnestMoney > 0) - { - State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), - new TransferInput - { - To = bid.From, - Symbol = auctionInfo.PurchaseSymbol, - Amount = auctionInfo.EarnestMoney - }); - } - - var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId]; - if (bidAddressList != null && bidAddressList.Value.Contains(Context.Sender)) - { - State.BidAddressListMap[input.Symbol][input.TokenId].Value.Remove(Context.Sender); - } + case ListType.EnglishAuction: + TryPlaceBidForEnglishAuction(input); + break; + case ListType.DutchAuction: + if (PerformMakeOfferToDutchAuction(input)) listedNftInfoList.Value.Remove(listedNftInfo); + + break; + default: + PerformMakeOffer(input); + break; + } + + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.OfferTo] = listedNftInfoList; + + return new Empty(); + } + + public override Empty CancelOffer(CancelOfferInput input) + { + AssertContractInitialized(); + + OfferList offerList; + var newOfferList = new OfferList(); + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + + // Admin can remove expired offer. + if (input.OfferFrom != null && input.OfferFrom != Context.Sender) + { + AssertSenderIsAdmin(); + + offerList = State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom]; - Context.Fire(new BidCanceled + if (offerList != null) + { + foreach (var offer in offerList.Value) + if (offer.ExpireTime >= Context.CurrentBlockTime) + newOfferList.Value.Add(offer); + else + Context.Fire(new OfferRemoved { Symbol = input.Symbol, TokenId = input.TokenId, - BidFrom = bid.From, - BidTo = bid.To + OfferFrom = offer.From, + OfferTo = offer.To, + ExpireTime = offer.ExpireTime }); - } - } - return new Empty(); + State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom] = newOfferList; } - offerList = State.OfferListMap[input.Symbol][input.TokenId][Context.Sender]; - - // Check Request Map first. - if (requestInfo != null) + if (requestInfo != null && !requestInfo.IsConfirmed && + requestInfo.ExpireTime > Context.CurrentBlockTime) { - PerformCancelRequest(input, requestInfo); - // Only one request for each token id. - Context.Fire(new OfferRemoved + MaybeRemoveRequest(input.Symbol, input.TokenId); + var protocolVirtualAddressFrom = CalculateTokenHash(input.Symbol); + var protocolVirtualAddress = + Context.ConvertVirtualAddressToContractAddress(protocolVirtualAddressFrom); + var balanceOfNftProtocolVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Symbol = requestInfo.Price.Symbol, + Owner = protocolVirtualAddress + }).Balance; + + if (balanceOfNftProtocolVirtualAddress > 0) + State.TokenContract.Transfer.VirtualSend(protocolVirtualAddressFrom, new TransferInput + { + To = requestInfo.Requester, + Symbol = requestInfo.Price.Symbol, + Amount = balanceOfNftProtocolVirtualAddress + }); + + Context.Fire(new NFTRequestCancelled { Symbol = input.Symbol, TokenId = input.TokenId, - OfferFrom = Context.Sender, - OfferTo = offerList.Value.FirstOrDefault()?.To, - ExpireTime = offerList.Value.FirstOrDefault()?.ExpireTime + Requester = Context.Sender }); - State.OfferListMap[input.Symbol][input.TokenId].Remove(Context.Sender); - return new Empty(); } - var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }); - if (nftInfo.Creator == null) - { - // This nft does not exist. - State.OfferListMap[input.Symbol][input.TokenId].Remove(Context.Sender); - } + var bid = State.BidMap[input.Symbol][input.TokenId][input.OfferFrom]; - if (input.IsCancelBid) - { - var bid = State.BidMap[input.Symbol][input.TokenId][Context.Sender]; - if (bid != null) + if (bid != null) + if (bid.ExpireTime < Context.CurrentBlockTime) { + State.BidMap[input.Symbol][input.TokenId].Remove(input.OfferFrom); var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - var finishTime = auctionInfo.Duration.StartTime.AddHours(auctionInfo.Duration.DurationHours); - if (auctionInfo.DealTo != null || Context.CurrentBlockTime >= finishTime || - Context.CurrentBlockTime >= bid.ExpireTime) - { - if (auctionInfo.EarnestMoney > 0) - { - State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), - new TransferInput - { - To = Context.Sender, - Symbol = auctionInfo.PurchaseSymbol, - Amount = auctionInfo.EarnestMoney - }); - } - } - - State.BidMap[input.Symbol][input.TokenId].Remove(Context.Sender); + if (auctionInfo != null && auctionInfo.EarnestMoney > 0) + State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), + new TransferInput + { + To = bid.From, + Symbol = auctionInfo.PurchaseSymbol, + Amount = auctionInfo.EarnestMoney + }); var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId]; if (bidAddressList != null && bidAddressList.Value.Contains(Context.Sender)) - { State.BidAddressListMap[input.Symbol][input.TokenId].Value.Remove(Context.Sender); - } Context.Fire(new BidCanceled { Symbol = input.Symbol, TokenId = input.TokenId, - BidFrom = Context.Sender, + BidFrom = bid.From, BidTo = bid.To }); } - } - - if (input.IndexList != null && input.IndexList.Value.Any()) - { - for (var i = 0; i < offerList.Value.Count; i++) - { - if (!input.IndexList.Value.Contains(i)) - { - newOfferList.Value.Add(offerList.Value[i]); - } - else - { - Context.Fire(new OfferRemoved - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = Context.Sender, - OfferTo = offerList.Value[i].To, - ExpireTime = offerList.Value[i].ExpireTime - }); - } - } - - Context.Fire(new OfferCanceled - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = Context.Sender, - IndexList = input.IndexList - }); - } - else - { - newOfferList.Value.Add(offerList.Value); - } - - State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] = newOfferList; return new Empty(); } - private void PerformCancelRequest(CancelOfferInput input, RequestInfo requestInfo) + offerList = State.OfferListMap[input.Symbol][input.TokenId][Context.Sender]; + + // Check Request Map first. + if (requestInfo != null) { - Assert(requestInfo.Requester == Context.Sender, "No permission."); - var virtualAddress = CalculateNFTVirtuaAddress(input.Symbol, input.TokenId); - var balanceOfNftVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput + PerformCancelRequest(input, requestInfo); + // Only one request for each token id. + Context.Fire(new OfferRemoved { - Symbol = requestInfo.Price.Symbol, - Owner = virtualAddress - }).Balance; - - var depositReceiver = requestInfo.Requester; + Symbol = input.Symbol, + TokenId = input.TokenId, + OfferFrom = Context.Sender, + OfferTo = offerList.Value.FirstOrDefault()?.To, + ExpireTime = offerList.Value.FirstOrDefault()?.ExpireTime + }); + State.OfferListMap[input.Symbol][input.TokenId].Remove(Context.Sender); + return new Empty(); + } - if (requestInfo.IsConfirmed) - { - if (requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) < Context.CurrentBlockTime) - { - // Creator missed the deadline. + var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput + { + Symbol = input.Symbol, + TokenId = input.TokenId + }); + if (nftInfo.Creator == null) + // This nft does not exist. + State.OfferListMap[input.Symbol][input.TokenId].Remove(Context.Sender); + + if (input.IsCancelBid) + { + var bid = State.BidMap[input.Symbol][input.TokenId][Context.Sender]; + if (bid != null) + { + var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; + var finishTime = auctionInfo.Duration.StartTime.AddHours(auctionInfo.Duration.DurationHours); + if (auctionInfo.DealTo != null || Context.CurrentBlockTime >= finishTime || + Context.CurrentBlockTime >= bid.ExpireTime) + if (auctionInfo.EarnestMoney > 0) + State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), + new TransferInput + { + To = Context.Sender, + Symbol = auctionInfo.PurchaseSymbol, + Amount = auctionInfo.EarnestMoney + }); - var protocolVirtualAddressFrom = CalculateTokenHash(input.Symbol); - var protocolVirtualAddress = - Context.ConvertVirtualAddressToContractAddress(protocolVirtualAddressFrom); - var balanceOfNftProtocolVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Symbol = requestInfo.Price.Symbol, - Owner = protocolVirtualAddress - }).Balance; - var deposit = balanceOfNftVirtualAddress.Mul(FeeDenominator).Div(DefaultDepositConfirmRate) - .Sub(balanceOfNftVirtualAddress); - if (balanceOfNftProtocolVirtualAddress > 0) - { - State.TokenContract.Transfer.VirtualSend(protocolVirtualAddressFrom, new TransferInput - { - To = requestInfo.Requester, - Symbol = requestInfo.Price.Symbol, - Amount = Math.Min(balanceOfNftProtocolVirtualAddress, deposit) - }); - } - } - else - { - depositReceiver = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = input.Symbol}) - .Creator; - } - } + State.BidMap[input.Symbol][input.TokenId].Remove(Context.Sender); - var virtualAddressFrom = CalculateTokenHash(input.Symbol, input.TokenId); + var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId]; + if (bidAddressList != null && bidAddressList.Value.Contains(Context.Sender)) + State.BidAddressListMap[input.Symbol][input.TokenId].Value.Remove(Context.Sender); - if (balanceOfNftVirtualAddress > 0) - { - State.TokenContract.Transfer.VirtualSend(virtualAddressFrom, new TransferInput + Context.Fire(new BidCanceled { - To = depositReceiver, - Symbol = requestInfo.Price.Symbol, - Amount = balanceOfNftVirtualAddress + Symbol = input.Symbol, + TokenId = input.TokenId, + BidFrom = Context.Sender, + BidTo = bid.To }); } + } - MaybeRemoveRequest(input.Symbol, input.TokenId); + if (input.IndexList != null && input.IndexList.Value.Any()) + { + for (var i = 0; i < offerList.Value.Count; i++) + if (!input.IndexList.Value.Contains(i)) + newOfferList.Value.Add(offerList.Value[i]); + else + Context.Fire(new OfferRemoved + { + Symbol = input.Symbol, + TokenId = input.TokenId, + OfferFrom = Context.Sender, + OfferTo = offerList.Value[i].To, + ExpireTime = offerList.Value[i].ExpireTime + }); - Context.Fire(new NFTRequestCancelled + Context.Fire(new OfferCanceled { Symbol = input.Symbol, TokenId = input.TokenId, - Requester = Context.Sender + OfferFrom = Context.Sender, + IndexList = input.IndexList }); } + else + { + newOfferList.Value.Add(offerList.Value); + } - /// - /// Sender is buyer. - /// - private bool TryDealWithFixedPrice(MakeOfferInput input, ListedNFTInfo listedNftInfo, out long actualQuantity) - { - var whiteList = State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo] ?? - new WhiteListAddressPriceList(); - var whiteListPrice = whiteList.Value.FirstOrDefault(p => p.Address == Context.Sender); - var usePrice = input.Price; - actualQuantity = Math.Min(input.Quantity, listedNftInfo.Quantity); - if (Context.CurrentBlockTime < listedNftInfo.Duration.StartTime) - { - PerformMakeOffer(input); - return false; - } + State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] = newOfferList; + + return new Empty(); + } + + private void PerformCancelRequest(CancelOfferInput input, RequestInfo requestInfo) + { + Assert(requestInfo.Requester == Context.Sender, "No permission."); + var virtualAddress = CalculateNFTVirtuaAddress(input.Symbol, input.TokenId); + var balanceOfNftVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Symbol = requestInfo.Price.Symbol, + Owner = virtualAddress + }).Balance; + + var depositReceiver = requestInfo.Requester; - if (whiteListPrice != null) + if (requestInfo.IsConfirmed) + { + if (requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) < Context.CurrentBlockTime) { - // May cause problems, but can be fixed via re-sorting the white list price list. - Assert(input.Price.Symbol == whiteListPrice.Price.Symbol, - $"Need to use token {whiteListPrice.Price.Symbol}, not {input.Price.Symbol}"); - if (input.Price.Amount < whiteListPrice.Price.Amount) - { - PerformMakeOffer(input); - return false; - } + // Creator missed the deadline. - usePrice = whiteListPrice.Price; - if (actualQuantity > 1) + var protocolVirtualAddressFrom = CalculateTokenHash(input.Symbol); + var protocolVirtualAddress = + Context.ConvertVirtualAddressToContractAddress(protocolVirtualAddressFrom); + var balanceOfNftProtocolVirtualAddress = State.TokenContract.GetBalance.Call(new GetBalanceInput { - var makeOfferInput = input.Clone(); - makeOfferInput.Quantity = actualQuantity.Sub(1); - PerformMakeOffer(makeOfferInput); - } - // One record in white list price list for one NFT. - actualQuantity = 1; - whiteList.Value.Remove(whiteListPrice); - State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo] = whiteList; + Symbol = requestInfo.Price.Symbol, + Owner = protocolVirtualAddress + }).Balance; + var deposit = balanceOfNftVirtualAddress.Mul(FeeDenominator).Div(DefaultDepositConfirmRate) + .Sub(balanceOfNftVirtualAddress); + if (balanceOfNftProtocolVirtualAddress > 0) + State.TokenContract.Transfer.VirtualSend(protocolVirtualAddressFrom, new TransferInput + { + To = requestInfo.Requester, + Symbol = requestInfo.Price.Symbol, + Amount = Math.Min(balanceOfNftProtocolVirtualAddress, deposit) + }); } - else if (listedNftInfo.Duration.PublicTime > Context.CurrentBlockTime) + else { - // Public time not reached and sender is not in white list. - PerformMakeOffer(input); - return false; + depositReceiver = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }) + .Creator; } + } - var totalAmount = usePrice.Amount.Mul(actualQuantity); - PerformDeal(new PerformDealInput + var virtualAddressFrom = CalculateTokenHash(input.Symbol, input.TokenId); + + if (balanceOfNftVirtualAddress > 0) + State.TokenContract.Transfer.VirtualSend(virtualAddressFrom, new TransferInput { - NFTFrom = input.OfferTo, - NFTTo = Context.Sender, - NFTSymbol = input.Symbol, - NFTTokenId = input.TokenId, - NFTQuantity = actualQuantity, - PurchaseSymbol = usePrice.Symbol, - PurchaseAmount = totalAmount, - PurchaseTokenId = input.Price.TokenId + To = depositReceiver, + Symbol = requestInfo.Price.Symbol, + Amount = balanceOfNftVirtualAddress }); - return true; + MaybeRemoveRequest(input.Symbol, input.TokenId); + + Context.Fire(new NFTRequestCancelled + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Requester = Context.Sender + }); + } + + /// + /// Sender is buyer. + /// + private bool TryDealWithFixedPrice(MakeOfferInput input, ListedNFTInfo listedNftInfo, out long actualQuantity) + { + var whiteList = State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo] ?? + new WhiteListAddressPriceList(); + var whiteListPrice = whiteList.Value.FirstOrDefault(p => p.Address == Context.Sender); + var usePrice = input.Price; + actualQuantity = Math.Min(input.Quantity, listedNftInfo.Quantity); + if (Context.CurrentBlockTime < listedNftInfo.Duration.StartTime) + { + PerformMakeOffer(input); + return false; } - /// - /// Will go to Offer List. - /// - /// - private void PerformMakeOffer(MakeOfferInput input) - { - var offerList = State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] ?? new OfferList(); - var expireTime = input.ExpireTime ?? Context.CurrentBlockTime.AddDays(DefaultExpireDays); - var maybeSameOffer = offerList.Value.SingleOrDefault(o => - o.Price.Symbol == input.Price.Symbol && o.Price.Amount == input.Price.Amount && - o.ExpireTime == expireTime && o.To == input.OfferTo && o.From == Context.Sender); - if (maybeSameOffer == null) + if (whiteListPrice != null) + { + // May cause problems, but can be fixed via re-sorting the white list price list. + Assert(input.Price.Symbol == whiteListPrice.Price.Symbol, + $"Need to use token {whiteListPrice.Price.Symbol}, not {input.Price.Symbol}"); + if (input.Price.Amount < whiteListPrice.Price.Amount) { - offerList.Value.Add(new Offer - { - From = Context.Sender, - To = input.OfferTo, - Price = input.Price, - ExpireTime = expireTime, - Quantity = input.Quantity - }); - Context.Fire(new OfferAdded - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = Context.Sender, - OfferTo = input.OfferTo, - ExpireTime = expireTime, - Price = input.Price, - Quantity = input.Quantity - }); + PerformMakeOffer(input); + return false; } - else + + usePrice = whiteListPrice.Price; + if (actualQuantity > 1) { - maybeSameOffer.Quantity = maybeSameOffer.Quantity.Add(input.Quantity); - Context.Fire(new OfferChanged - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = Context.Sender, - OfferTo = input.OfferTo, - Price = input.Price, - ExpireTime = expireTime, - Quantity = maybeSameOffer.Quantity - }); + var makeOfferInput = input.Clone(); + makeOfferInput.Quantity = actualQuantity.Sub(1); + PerformMakeOffer(makeOfferInput); } - State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] = offerList; + // One record in white list price list for one NFT. + actualQuantity = 1; + whiteList.Value.Remove(whiteListPrice); + State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.OfferTo] = whiteList; + } + else if (listedNftInfo.Duration.PublicTime > Context.CurrentBlockTime) + { + // Public time not reached and sender is not in white list. + PerformMakeOffer(input); + return false; + } - var addressList = State.OfferAddressListMap[input.Symbol][input.TokenId] ?? new AddressList(); + var totalAmount = usePrice.Amount.Mul(actualQuantity); + PerformDeal(new PerformDealInput + { + NFTFrom = input.OfferTo, + NFTTo = Context.Sender, + NFTSymbol = input.Symbol, + NFTTokenId = input.TokenId, + NFTQuantity = actualQuantity, + PurchaseSymbol = usePrice.Symbol, + PurchaseAmount = totalAmount, + PurchaseTokenId = input.Price.TokenId + }); + + return true; + } - if (!addressList.Value.Contains(Context.Sender)) + /// + /// Will go to Offer List. + /// + /// + private void PerformMakeOffer(MakeOfferInput input) + { + var offerList = State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] ?? new OfferList(); + var expireTime = input.ExpireTime ?? Context.CurrentBlockTime.AddDays(DefaultExpireDays); + var maybeSameOffer = offerList.Value.SingleOrDefault(o => + o.Price.Symbol == input.Price.Symbol && o.Price.Amount == input.Price.Amount && + o.ExpireTime == expireTime && o.To == input.OfferTo && o.From == Context.Sender); + if (maybeSameOffer == null) + { + offerList.Value.Add(new Offer { - addressList.Value.Add(Context.Sender); - State.OfferAddressListMap[input.Symbol][input.TokenId] = addressList; - } - - Context.Fire(new OfferMade + From = Context.Sender, + To = input.OfferTo, + Price = input.Price, + ExpireTime = expireTime, + Quantity = input.Quantity + }); + Context.Fire(new OfferAdded { Symbol = input.Symbol, TokenId = input.TokenId, @@ -606,196 +533,222 @@ private void PerformMakeOffer(MakeOfferInput input) Quantity = input.Quantity }); } - - private void TryPlaceBidForEnglishAuction(MakeOfferInput input) + else { - var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - if (auctionInfo == null) + maybeSameOffer.Quantity = maybeSameOffer.Quantity.Add(input.Quantity); + Context.Fire(new OfferChanged { - throw new AssertionException($"Auction info of {input.Symbol}-{input.TokenId} not found."); - } + Symbol = input.Symbol, + TokenId = input.TokenId, + OfferFrom = Context.Sender, + OfferTo = input.OfferTo, + Price = input.Price, + ExpireTime = expireTime, + Quantity = maybeSameOffer.Quantity + }); + } - var duration = auctionInfo.Duration; - if (Context.CurrentBlockTime < duration.StartTime) - { - PerformMakeOffer(input); - return; - } + State.OfferListMap[input.Symbol][input.TokenId][Context.Sender] = offerList; - Assert(Context.CurrentBlockTime <= duration.StartTime.AddHours(duration.DurationHours), - "Auction already finished."); - Assert(input.Price.Symbol == auctionInfo.PurchaseSymbol, "Incorrect symbol."); - Assert(input.Price.TokenId == 0, "Do not support use NFT to purchase auction."); + var addressList = State.OfferAddressListMap[input.Symbol][input.TokenId] ?? new AddressList(); - if (input.Price.Amount < auctionInfo.StartingPrice) - { - PerformMakeOffer(input); - return; - } + if (!addressList.Value.Contains(Context.Sender)) + { + addressList.Value.Add(Context.Sender); + State.OfferAddressListMap[input.Symbol][input.TokenId] = addressList; + } - var bidList = GetBidList(new GetBidListInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }); - var sortedBitList = new BidList - { - Value = - { - bidList.Value.OrderByDescending(o => o.Price.Amount) - } - }; - if (sortedBitList.Value.Any() && input.Price.Amount <= sortedBitList.Value.First().Price.Amount) - { - PerformMakeOffer(input); - return; - } + Context.Fire(new OfferMade + { + Symbol = input.Symbol, + TokenId = input.TokenId, + OfferFrom = Context.Sender, + OfferTo = input.OfferTo, + ExpireTime = expireTime, + Price = input.Price, + Quantity = input.Quantity + }); + } - var bid = new Bid - { - From = Context.Sender, - To = input.OfferTo, - Price = new Price - { - Symbol = input.Price.Symbol, - Amount = input.Price.Amount - }, - ExpireTime = input.ExpireTime ?? Context.CurrentBlockTime.AddDays(DefaultExpireDays) - }; - - var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId] ?? new AddressList(); - if (!bidAddressList.Value.Contains(Context.Sender)) - { - bidAddressList.Value.Add(Context.Sender); - State.BidAddressListMap[input.Symbol][input.TokenId] = bidAddressList; - // Charge earnest if the Sender is the first time to place a bid. - ChargeEarnestMoney(input.Symbol, input.TokenId, auctionInfo.PurchaseSymbol, auctionInfo.EarnestMoney); - } + private void TryPlaceBidForEnglishAuction(MakeOfferInput input) + { + var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; + if (auctionInfo == null) + throw new AssertionException($"Auction info of {input.Symbol}-{input.TokenId} not found."); - State.BidMap[input.Symbol][input.TokenId][Context.Sender] = bid; + var duration = auctionInfo.Duration; + if (Context.CurrentBlockTime < duration.StartTime) + { + PerformMakeOffer(input); + return; + } - var remainAmount = input.Price.Amount.Sub(auctionInfo.EarnestMoney); - Assert( - State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Symbol = auctionInfo.PurchaseSymbol, - Owner = Context.Sender - }).Balance >= remainAmount, - "Insufficient balance to bid."); - Assert( - State.TokenContract.GetAllowance.Call(new GetAllowanceInput - { - Symbol = auctionInfo.PurchaseSymbol, - Owner = Context.Sender, - Spender = Context.Self - }).Allowance >= remainAmount, - "Insufficient allowance to bid."); + Assert(Context.CurrentBlockTime <= duration.StartTime.AddHours(duration.DurationHours), + "Auction already finished."); + Assert(input.Price.Symbol == auctionInfo.PurchaseSymbol, "Incorrect symbol."); + Assert(input.Price.TokenId == 0, "Do not support use NFT to purchase auction."); - Context.Fire(new BidPlaced - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Price = bid.Price, - ExpireTime = bid.ExpireTime, - OfferFrom = bid.From, - OfferTo = input.OfferTo - }); + if (input.Price.Amount < auctionInfo.StartingPrice) + { + PerformMakeOffer(input); + return; } - private void ChargeEarnestMoney(string nftSymbol, long nftTokenId, string purchaseSymbol, long earnestMoney) + var bidList = GetBidList(new GetBidListInput + { + Symbol = input.Symbol, + TokenId = input.TokenId + }); + var sortedBitList = new BidList { - if (earnestMoney > 0) + Value = { - var virtualAddress = CalculateNFTVirtuaAddress(nftSymbol, nftTokenId); - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = virtualAddress, - Symbol = purchaseSymbol, - Amount = earnestMoney - }); + bidList.Value.OrderByDescending(o => o.Price.Amount) } + }; + if (sortedBitList.Value.Any() && input.Price.Amount <= sortedBitList.Value.First().Price.Amount) + { + PerformMakeOffer(input); + return; } - private bool PerformMakeOfferToDutchAuction(MakeOfferInput input) + var bid = new Bid { - var auctionInfo = State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; - if (auctionInfo == null) - { - throw new AssertionException($"Auction info of {input.Symbol}-{input.TokenId} not found."); - } + From = Context.Sender, + To = input.OfferTo, + Price = new Price + { + Symbol = input.Price.Symbol, + Amount = input.Price.Amount + }, + ExpireTime = input.ExpireTime ?? Context.CurrentBlockTime.AddDays(DefaultExpireDays) + }; + + var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId] ?? new AddressList(); + if (!bidAddressList.Value.Contains(Context.Sender)) + { + bidAddressList.Value.Add(Context.Sender); + State.BidAddressListMap[input.Symbol][input.TokenId] = bidAddressList; + // Charge earnest if the Sender is the first time to place a bid. + ChargeEarnestMoney(input.Symbol, input.TokenId, auctionInfo.PurchaseSymbol, auctionInfo.EarnestMoney); + } - var duration = auctionInfo.Duration; - if (Context.CurrentBlockTime < duration.StartTime) - { - PerformMakeOffer(input); - return false; - } + State.BidMap[input.Symbol][input.TokenId][Context.Sender] = bid; - Assert(Context.CurrentBlockTime <= duration.StartTime.AddHours(duration.DurationHours), - "Auction already finished."); - Assert(input.Price.Symbol == auctionInfo.PurchaseSymbol, "Incorrect symbol"); - var currentBiddingPrice = CalculateCurrentBiddingPrice(auctionInfo.StartingPrice, auctionInfo.EndingPrice, - auctionInfo.Duration); - if (input.Price.Amount < currentBiddingPrice) + var remainAmount = input.Price.Amount.Sub(auctionInfo.EarnestMoney); + Assert( + State.TokenContract.GetBalance.Call(new GetBalanceInput { - PerformMakeOffer(input); - return false; - } + Symbol = auctionInfo.PurchaseSymbol, + Owner = Context.Sender + }).Balance >= remainAmount, + "Insufficient balance to bid."); + Assert( + State.TokenContract.GetAllowance.Call(new GetAllowanceInput + { + Symbol = auctionInfo.PurchaseSymbol, + Owner = Context.Sender, + Spender = Context.Self + }).Allowance >= remainAmount, + "Insufficient allowance to bid."); - PerformDeal(new PerformDealInput + Context.Fire(new BidPlaced + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Price = bid.Price, + ExpireTime = bid.ExpireTime, + OfferFrom = bid.From, + OfferTo = input.OfferTo + }); + } + + private void ChargeEarnestMoney(string nftSymbol, long nftTokenId, string purchaseSymbol, long earnestMoney) + { + if (earnestMoney > 0) + { + var virtualAddress = CalculateNFTVirtuaAddress(nftSymbol, nftTokenId); + State.TokenContract.TransferFrom.Send(new TransferFromInput { - NFTFrom = auctionInfo.Owner, - NFTTo = Context.Sender, - NFTQuantity = 1, - NFTSymbol = input.Symbol, - NFTTokenId = input.TokenId, - PurchaseSymbol = input.Price.Symbol, - PurchaseAmount = input.Price.Amount, - PurchaseTokenId = 0 + From = Context.Sender, + To = virtualAddress, + Symbol = purchaseSymbol, + Amount = earnestMoney }); - return true; } + } + + private bool PerformMakeOfferToDutchAuction(MakeOfferInput input) + { + var auctionInfo = State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; + if (auctionInfo == null) + throw new AssertionException($"Auction info of {input.Symbol}-{input.TokenId} not found."); - private long CalculateCurrentBiddingPrice(long startingPrice, long endingPrice, ListDuration duration) + var duration = auctionInfo.Duration; + if (Context.CurrentBlockTime < duration.StartTime) { - var passedSeconds = (Context.CurrentBlockTime - duration.StartTime).Seconds; - var durationSeconds = duration.DurationHours.Mul(3600); - if (passedSeconds == 0) - { - return startingPrice; - } + PerformMakeOffer(input); + return false; + } - var diffPrice = endingPrice.Sub(startingPrice); - return Math.Max(startingPrice.Sub(diffPrice.Mul(durationSeconds).Div(passedSeconds)), endingPrice); + Assert(Context.CurrentBlockTime <= duration.StartTime.AddHours(duration.DurationHours), + "Auction already finished."); + Assert(input.Price.Symbol == auctionInfo.PurchaseSymbol, "Incorrect symbol"); + var currentBiddingPrice = CalculateCurrentBiddingPrice(auctionInfo.StartingPrice, auctionInfo.EndingPrice, + auctionInfo.Duration); + if (input.Price.Amount < currentBiddingPrice) + { + PerformMakeOffer(input); + return false; } - private void MaybeReceiveRemainDeposit(RequestInfo requestInfo) + PerformDeal(new PerformDealInput { - if (requestInfo == null) return; - Assert(Context.CurrentBlockTime > requestInfo.WhiteListDueTime, "Due time not passed."); - var nftProtocolInfo = - State.NFTContract.GetNFTProtocolInfo.Call((new StringValue {Value = requestInfo.Symbol})); - Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can claim remain deposit."); + NFTFrom = auctionInfo.Owner, + NFTTo = Context.Sender, + NFTQuantity = 1, + NFTSymbol = input.Symbol, + NFTTokenId = input.TokenId, + PurchaseSymbol = input.Price.Symbol, + PurchaseAmount = input.Price.Amount, + PurchaseTokenId = 0 + }); + return true; + } + + private long CalculateCurrentBiddingPrice(long startingPrice, long endingPrice, ListDuration duration) + { + var passedSeconds = (Context.CurrentBlockTime - duration.StartTime).Seconds; + var durationSeconds = duration.DurationHours.Mul(3600); + if (passedSeconds == 0) return startingPrice; - var nftVirtualAddressFrom = CalculateTokenHash(requestInfo.Symbol, requestInfo.TokenId); - var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput + var diffPrice = endingPrice.Sub(startingPrice); + return Math.Max(startingPrice.Sub(diffPrice.Mul(durationSeconds).Div(passedSeconds)), endingPrice); + } + + private void MaybeReceiveRemainDeposit(RequestInfo requestInfo) + { + if (requestInfo == null) return; + Assert(Context.CurrentBlockTime > requestInfo.WhiteListDueTime, "Due time not passed."); + var nftProtocolInfo = + State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = requestInfo.Symbol }); + Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can claim remain deposit."); + + var nftVirtualAddressFrom = CalculateTokenHash(requestInfo.Symbol, requestInfo.TokenId); + var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Symbol = requestInfo.Price.Symbol, + Owner = nftVirtualAddress + }).Balance; + if (balance > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput { + To = nftProtocolInfo.Creator, Symbol = requestInfo.Price.Symbol, - Owner = nftVirtualAddress - }).Balance; - if (balance > 0) - { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = nftProtocolInfo.Creator, - Symbol = requestInfo.Price.Symbol, - Amount = balance - }); - } + Amount = balance + }); - MaybeRemoveRequest(requestInfo.Symbol, requestInfo.TokenId); - } + MaybeRemoveRequest(requestInfo.Symbol, requestInfo.TokenId); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Creators.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Creators.cs index 737d3b2fee..628f205fbc 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Creators.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Creators.cs @@ -9,271 +9,252 @@ using TransferFromInput = AElf.Contracts.MultiToken.TransferFromInput; using TransferInput = AElf.Contracts.MultiToken.TransferInput; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + public override Empty SetRoyalty(SetRoyaltyInput input) { - public override Empty SetRoyalty(SetRoyaltyInput input) - { - AssertContractInitialized(); + AssertContractInitialized(); - // 0% - 10% - Assert(0 <= input.Royalty && input.Royalty <= 1000, "Royalty should be between 0% to 10%."); - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = input.Symbol}); - Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); - if (input.TokenId == 0) - { - Assert(nftProtocolInfo.Creator == Context.Sender, - "Only NFT Protocol Creator can set royalty for whole protocol."); - // Set for whole NFT Protocol. - State.RoyaltyMap[input.Symbol] = input.Royalty; - } - else - { - var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }); - Assert(nftProtocolInfo.Creator == Context.Sender || nftInfo.Minters.Contains(Context.Sender), - "No permission."); - State.CertainNFTRoyaltyMap[input.Symbol][input.TokenId] = new CertainNFTRoyaltyInfo - { - IsManuallySet = true, - Royalty = input.Royalty - }; - } - - State.RoyaltyFeeReceiverMap[input.Symbol] = input.RoyaltyFeeReceiver; - return new Empty(); + // 0% - 10% + Assert(0 <= input.Royalty && input.Royalty <= 1000, "Royalty should be between 0% to 10%."); + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); + if (input.TokenId == 0) + { + Assert(nftProtocolInfo.Creator == Context.Sender, + "Only NFT Protocol Creator can set royalty for whole protocol."); + // Set for whole NFT Protocol. + State.RoyaltyMap[input.Symbol] = input.Royalty; } - - public override Empty SetTokenWhiteList(SetTokenWhiteListInput input) + else { - AssertContractInitialized(); - - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = input.Symbol}); - Assert(nftProtocolInfo.Creator != null, "NFT Protocol not found."); - Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can set token white list."); - State.TokenWhiteListMap[input.Symbol] = input.TokenWhiteList; - Context.Fire(new TokenWhiteListChanged + var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput { Symbol = input.Symbol, - TokenWhiteList = input.TokenWhiteList + TokenId = input.TokenId }); - return new Empty(); + Assert(nftProtocolInfo.Creator == Context.Sender || nftInfo.Minters.Contains(Context.Sender), + "No permission."); + State.CertainNFTRoyaltyMap[input.Symbol][input.TokenId] = new CertainNFTRoyaltyInfo + { + IsManuallySet = true, + Royalty = input.Royalty + }; } - public override Empty SetCustomizeInfo(CustomizeInfo input) - { - AssertContractInitialized(); + State.RoyaltyFeeReceiverMap[input.Symbol] = input.RoyaltyFeeReceiver; + return new Empty(); + } - if (input.Price == null) - { - var customizeInfo = State.CustomizeInfoMap[input.Symbol]; - if (customizeInfo?.Price == null) - { - return new Empty(); - } + public override Empty SetTokenWhiteList(SetTokenWhiteListInput input) + { + AssertContractInitialized(); + + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(nftProtocolInfo.Creator != null, "NFT Protocol not found."); + Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can set token white list."); + State.TokenWhiteListMap[input.Symbol] = input.TokenWhiteList; + Context.Fire(new TokenWhiteListChanged + { + Symbol = input.Symbol, + TokenWhiteList = input.TokenWhiteList + }); + return new Empty(); + } - State.CustomizeInfoMap[input.Symbol].Price.Amount = 0; - return new Empty(); - } + public override Empty SetCustomizeInfo(CustomizeInfo input) + { + AssertContractInitialized(); - Assert(input.StakingAmount >= 0, "Invalid staking amount."); - Assert(input.DepositRate >= 0, "Invalid deposit rate."); - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call((new StringValue {Value = input.Symbol})); - Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); - Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can set customize info."); - Assert(!nftProtocolInfo.IsTokenIdReuse, "Not support customize."); - var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput {Symbol = input.Price.Symbol}); - Assert(!string.IsNullOrEmpty(tokenInfo.Symbol), "Invalid staking token symbol."); - if (input.StakingAmount > 0) - { - var virtualAddress = CalculateNFTVirtuaAddress(input.Symbol); - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = virtualAddress, - Symbol = input.Price.Symbol, - Amount = input.StakingAmount - }); - } + if (input.Price == null) + { + var customizeInfo = State.CustomizeInfoMap[input.Symbol]; + if (customizeInfo?.Price == null) return new Empty(); - State.CustomizeInfoMap[input.Symbol] = input; - Context.Fire(new CustomizeInfoSet - { - Symbol = input.Symbol, - Price = input.Price, - DepositRate = input.DepositRate, - StakingAmount = input.StakingAmount, - WhiteListHours = input.WhiteListHours, - WorkHours = input.WorkHours - }); + State.CustomizeInfoMap[input.Symbol].Price.Amount = 0; return new Empty(); } - public override Empty StakeForRequests(StakeForRequestsInput input) + Assert(input.StakingAmount >= 0, "Invalid staking amount."); + Assert(input.DepositRate >= 0, "Invalid deposit rate."); + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); + Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can set customize info."); + Assert(!nftProtocolInfo.IsTokenIdReuse, "Not support customize."); + var tokenInfo = State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput { Symbol = input.Price.Symbol }); + Assert(!string.IsNullOrEmpty(tokenInfo.Symbol), "Invalid staking token symbol."); + if (input.StakingAmount > 0) { - AssertContractInitialized(); - - Assert(input.StakingAmount > 0, "Invalid staking amount."); - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = input.Symbol}); - Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); - Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can stake for requests."); - var customizeInfo = State.CustomizeInfoMap[input.Symbol]; - if (customizeInfo == null) - { - throw new AssertionException("Customize info not found."); - } - var virtualAddress = CalculateNFTVirtuaAddress(input.Symbol); State.TokenContract.TransferFrom.Send(new TransferFromInput { From = Context.Sender, To = virtualAddress, - Symbol = customizeInfo.Price.Symbol, + Symbol = input.Price.Symbol, Amount = input.StakingAmount }); - customizeInfo.StakingAmount = customizeInfo.StakingAmount.Add(input.StakingAmount); - State.CustomizeInfoMap[input.Symbol] = customizeInfo; - Context.Fire(new StakingAmountChanged - { - Symbol = input.Symbol, - StakingAmount = customizeInfo.StakingAmount - }); - return new Empty(); } - public override Empty WithdrawStakingTokens(WithdrawStakingTokensInput input) + State.CustomizeInfoMap[input.Symbol] = input; + Context.Fire(new CustomizeInfoSet { - AssertContractInitialized(); + Symbol = input.Symbol, + Price = input.Price, + DepositRate = input.DepositRate, + StakingAmount = input.StakingAmount, + WhiteListHours = input.WhiteListHours, + WorkHours = input.WorkHours + }); + return new Empty(); + } - Assert(input.WithdrawAmount > 0, "Invalid withdraw amount."); - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call((new StringValue {Value = input.Symbol})); - Assert(nftProtocolInfo.Creator == Context.Sender, "NFT symbol does not exist."); - var customizeInfo = State.CustomizeInfoMap[input.Symbol]; - Assert(input.WithdrawAmount <= customizeInfo.StakingAmount, "Insufficient staking amount."); - Assert(customizeInfo.ReservedTokenIds.Count == 0, - "Cannot withdraw staking tokens before complete all the demands."); - var virtualAddressFrom = CalculateTokenHash(input.Symbol); - State.TokenContract.Transfer.VirtualSend(virtualAddressFrom, new TransferInput - { - To = Context.Sender, - Symbol = customizeInfo.Price.Symbol, - Amount = input.WithdrawAmount - }); - customizeInfo.StakingAmount = customizeInfo.StakingAmount.Sub(input.WithdrawAmount); - State.CustomizeInfoMap[input.Symbol] = customizeInfo; - Context.Fire(new StakingAmountChanged - { - Symbol = input.Symbol, - StakingAmount = customizeInfo.StakingAmount - }); - return new Empty(); - } + public override Empty StakeForRequests(StakeForRequestsInput input) + { + AssertContractInitialized(); + + Assert(input.StakingAmount > 0, "Invalid staking amount."); + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(!string.IsNullOrEmpty(nftProtocolInfo.Symbol), "NFT Protocol not found."); + Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can stake for requests."); + var customizeInfo = State.CustomizeInfoMap[input.Symbol]; + if (customizeInfo == null) throw new AssertionException("Customize info not found."); - public override Empty HandleRequest(HandleRequestInput input) + var virtualAddress = CalculateNFTVirtuaAddress(input.Symbol); + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + To = virtualAddress, + Symbol = customizeInfo.Price.Symbol, + Amount = input.StakingAmount + }); + customizeInfo.StakingAmount = customizeInfo.StakingAmount.Add(input.StakingAmount); + State.CustomizeInfoMap[input.Symbol] = customizeInfo; + Context.Fire(new StakingAmountChanged { - AssertContractInitialized(); + Symbol = input.Symbol, + StakingAmount = customizeInfo.StakingAmount + }); + return new Empty(); + } - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - if (requestInfo == null) - { - throw new AssertionException("Request not exists."); - } + public override Empty WithdrawStakingTokens(WithdrawStakingTokensInput input) + { + AssertContractInitialized(); - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call((new StringValue {Value = input.Symbol})); - Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can handle request."); + Assert(input.WithdrawAmount > 0, "Invalid withdraw amount."); + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(nftProtocolInfo.Creator == Context.Sender, "NFT symbol does not exist."); + var customizeInfo = State.CustomizeInfoMap[input.Symbol]; + Assert(input.WithdrawAmount <= customizeInfo.StakingAmount, "Insufficient staking amount."); + Assert(customizeInfo.ReservedTokenIds.Count == 0, + "Cannot withdraw staking tokens before complete all the demands."); + var virtualAddressFrom = CalculateTokenHash(input.Symbol); + State.TokenContract.Transfer.VirtualSend(virtualAddressFrom, new TransferInput + { + To = Context.Sender, + Symbol = customizeInfo.Price.Symbol, + Amount = input.WithdrawAmount + }); + customizeInfo.StakingAmount = customizeInfo.StakingAmount.Sub(input.WithdrawAmount); + State.CustomizeInfoMap[input.Symbol] = customizeInfo; + Context.Fire(new StakingAmountChanged + { + Symbol = input.Symbol, + StakingAmount = customizeInfo.StakingAmount + }); + return new Empty(); + } - var nftVirtualAddressFrom = CalculateTokenHash(input.Symbol, input.TokenId); - var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); - var nftVirtualAddressBalance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Symbol = requestInfo.Price.Symbol, - Owner = nftVirtualAddress - }).Balance; + public override Empty HandleRequest(HandleRequestInput input) + { + AssertContractInitialized(); - if (input.IsConfirm) - { - requestInfo.IsConfirmed = true; - requestInfo.ConfirmTime = Context.CurrentBlockTime; - requestInfo.WorkHours = Math.Min(requestInfo.WorkHoursFromCustomizeInfo, - (requestInfo.ExpireTime - Context.CurrentBlockTime).Seconds.Div(3600)); - requestInfo.WhiteListDueTime = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) - .AddHours(requestInfo.WhiteListHours); - State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + if (requestInfo == null) throw new AssertionException("Request not exists."); - var transferAmount = nftVirtualAddressBalance.Mul(DefaultDepositConfirmRate).Div(FeeDenominator); - var serviceFee = transferAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); - transferAmount = transferAmount.Sub(serviceFee); + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = input.Symbol }); + Assert(nftProtocolInfo.Creator == Context.Sender, "Only NFT Protocol Creator can handle request."); - if (transferAmount > 0) - { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = Context.Sender, - Symbol = requestInfo.Price.Symbol, - Amount = transferAmount - }); - } + var nftVirtualAddressFrom = CalculateTokenHash(input.Symbol, input.TokenId); + var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); + var nftVirtualAddressBalance = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Symbol = requestInfo.Price.Symbol, + Owner = nftVirtualAddress + }).Balance; - if (serviceFee > 0) - { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = State.ServiceFeeReceiver.Value, - Symbol = requestInfo.Price.Symbol, - Amount = serviceFee - }); - } + if (input.IsConfirm) + { + requestInfo.IsConfirmed = true; + requestInfo.ConfirmTime = Context.CurrentBlockTime; + requestInfo.WorkHours = Math.Min(requestInfo.WorkHoursFromCustomizeInfo, + (requestInfo.ExpireTime - Context.CurrentBlockTime).Seconds.Div(3600)); + requestInfo.WhiteListDueTime = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) + .AddHours(requestInfo.WhiteListHours); + State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; + + var transferAmount = nftVirtualAddressBalance.Mul(DefaultDepositConfirmRate).Div(FeeDenominator); + var serviceFee = transferAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); + transferAmount = transferAmount.Sub(serviceFee); - Context.Fire(new NewNFTRequestConfirmed + if (transferAmount > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput { - Symbol = input.Symbol, - TokenId = input.TokenId, - Requester = input.Requester, - ConfirmedWorkHours = requestInfo.WorkHours, - Price = requestInfo.Price + To = Context.Sender, + Symbol = requestInfo.Price.Symbol, + Amount = transferAmount }); - } - else - { - MaybeRemoveRequest(input.Symbol, input.TokenId); - if (nftVirtualAddressBalance > 0) - { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = requestInfo.Requester, - Symbol = requestInfo.Price.Symbol, - Amount = nftVirtualAddressBalance - }); - } - Context.Fire(new NewNFTRequestRejected + if (serviceFee > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput { - Symbol = input.Symbol, - TokenId = input.TokenId, - Requester = input.Requester + To = State.ServiceFeeReceiver.Value, + Symbol = requestInfo.Price.Symbol, + Amount = serviceFee }); - } - return new Empty(); + Context.Fire(new NewNFTRequestConfirmed + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Requester = input.Requester, + ConfirmedWorkHours = requestInfo.WorkHours, + Price = requestInfo.Price + }); } - - public override Empty ClaimRemainDeposit(ClaimRemainDepositInput input) + else { - AssertContractInitialized(); + MaybeRemoveRequest(input.Symbol, input.TokenId); + if (nftVirtualAddressBalance > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput + { + To = requestInfo.Requester, + Symbol = requestInfo.Price.Symbol, + Amount = nftVirtualAddressBalance + }); - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - if (requestInfo == null) + Context.Fire(new NewNFTRequestRejected { - throw new AssertionException("Request info does not exist."); - } + Symbol = input.Symbol, + TokenId = input.TokenId, + Requester = input.Requester + }); + } - MaybeReceiveRemainDeposit(requestInfo); + return new Empty(); + } - return new Empty(); - } + public override Empty ClaimRemainDeposit(ClaimRemainDepositInput input) + { + AssertContractInitialized(); + + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + if (requestInfo == null) throw new AssertionException("Request info does not exist."); + + MaybeReceiveRemainDeposit(requestInfo); + + return new Empty(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Helpers.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Helpers.cs index 8e030d0748..8c84a76206 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Helpers.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Helpers.cs @@ -9,480 +9,426 @@ using TransferFromInput = AElf.Contracts.MultiToken.TransferFromInput; using TransferInput = AElf.Contracts.MultiToken.TransferInput; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + private void CheckSenderNFTBalanceAndAllowance(string symbol, long tokenId, long quantity) { - private void CheckSenderNFTBalanceAndAllowance(string symbol, long tokenId, long quantity) + var balance = State.NFTContract.GetBalance.Call(new GetBalanceInput { - var balance = State.NFTContract.GetBalance.Call(new GetBalanceInput - { - Symbol = symbol, - TokenId = tokenId, - Owner = Context.Sender - }).Balance; - Assert(balance >= quantity, $"Check sender NFT balance failed. {balance} / {quantity}"); - var allowance = State.NFTContract.GetAllowance.Call(new GetAllowanceInput - { - Symbol = symbol, - TokenId = tokenId, - Owner = Context.Sender, - Spender = Context.Self - }).Allowance; - Assert(allowance >= quantity, $"Check sender NFT allowance failed. {allowance} / {quantity}"); - } + Symbol = symbol, + TokenId = tokenId, + Owner = Context.Sender + }).Balance; + Assert(balance >= quantity, $"Check sender NFT balance failed. {balance} / {quantity}"); + var allowance = State.NFTContract.GetAllowance.Call(new GetAllowanceInput + { + Symbol = symbol, + TokenId = tokenId, + Owner = Context.Sender, + Spender = Context.Self + }).Allowance; + Assert(allowance >= quantity, $"Check sender NFT allowance failed. {allowance} / {quantity}"); + } - private bool CheckAllowanceAndBalanceIsEnough(Address owner, string symbol, long enoughAmount) + private bool CheckAllowanceAndBalanceIsEnough(Address owner, string symbol, long enoughAmount) + { + var balance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput { - var balance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput - { - Symbol = symbol, - Owner = owner - }).Balance; - if (balance < enoughAmount) return false; - var allowance = State.TokenContract.GetAllowance.Call(new MultiToken.GetAllowanceInput - { - Symbol = symbol, - Owner = owner, - Spender = Context.Self - }).Allowance; - return allowance >= enoughAmount; - } + Symbol = symbol, + Owner = owner + }).Balance; + if (balance < enoughAmount) return false; + var allowance = State.TokenContract.GetAllowance.Call(new MultiToken.GetAllowanceInput + { + Symbol = symbol, + Owner = owner, + Spender = Context.Self + }).Allowance; + return allowance >= enoughAmount; + } - private void PayRemainDepositInCustomizeCase(PerformDealInput performDealInput) + private void PayRemainDepositInCustomizeCase(PerformDealInput performDealInput) + { + var requestInfo = State.RequestInfoMap[performDealInput.NFTSymbol][performDealInput.NFTTokenId]; + if (requestInfo == null) return; + var nftVirtualAddressFrom = CalculateTokenHash(performDealInput.NFTSymbol, performDealInput.NFTTokenId); + var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); + var balanceOfNftVirtualAddress = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput { - var requestInfo = State.RequestInfoMap[performDealInput.NFTSymbol][performDealInput.NFTTokenId]; - if (requestInfo == null) return; - var nftVirtualAddressFrom = CalculateTokenHash(performDealInput.NFTSymbol, performDealInput.NFTTokenId); - var nftVirtualAddress = Context.ConvertVirtualAddressToContractAddress(nftVirtualAddressFrom); - var balanceOfNftVirtualAddress = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput - { - Symbol = performDealInput.PurchaseSymbol, - Owner = nftVirtualAddress - }).Balance; - var transferAmount = balanceOfNftVirtualAddress; - var serviceFee = transferAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); - transferAmount = transferAmount.Sub(serviceFee); - if (transferAmount > 0) + Symbol = performDealInput.PurchaseSymbol, + Owner = nftVirtualAddress + }).Balance; + var transferAmount = balanceOfNftVirtualAddress; + var serviceFee = transferAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); + transferAmount = transferAmount.Sub(serviceFee); + if (transferAmount > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = performDealInput.NFTFrom, - Symbol = requestInfo.Price.Symbol, - Amount = transferAmount - }); - } + To = performDealInput.NFTFrom, + Symbol = requestInfo.Price.Symbol, + Amount = transferAmount + }); - if (serviceFee > 0) + if (serviceFee > 0) + State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput { - State.TokenContract.Transfer.VirtualSend(nftVirtualAddressFrom, new TransferInput - { - To = State.ServiceFeeReceiver.Value, - Symbol = requestInfo.Price.Symbol, - Amount = serviceFee - }); - } - } + To = State.ServiceFeeReceiver.Value, + Symbol = requestInfo.Price.Symbol, + Amount = serviceFee + }); + } - private void PerformDeal(PerformDealInput performDealInput) + private void PerformDeal(PerformDealInput performDealInput) + { + Assert(performDealInput.NFTFrom != performDealInput.NFTTo, "NFT From address cannot be NFT To address."); + PayRemainDepositInCustomizeCase(performDealInput); + if (performDealInput.PurchaseTokenId == 0) { - Assert(performDealInput.NFTFrom != performDealInput.NFTTo, "NFT From address cannot be NFT To address."); - PayRemainDepositInCustomizeCase(performDealInput); - if (performDealInput.PurchaseTokenId == 0) + var serviceFee = performDealInput.PurchaseAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); + var royalty = GetRoyalty(new GetRoyaltyInput { - var serviceFee = performDealInput.PurchaseAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); - var royalty = GetRoyalty(new GetRoyaltyInput - { - Symbol = performDealInput.NFTSymbol, - TokenId = performDealInput.NFTTokenId - }); + Symbol = performDealInput.NFTSymbol, + TokenId = performDealInput.NFTTokenId + }); - var royaltyFee = performDealInput.PurchaseAmount.Mul(royalty.Royalty).Div(FeeDenominator); - var royaltyFeeReceiver = State.RoyaltyFeeReceiverMap[performDealInput.NFTSymbol]; - if (royaltyFeeReceiver == null) - { - royaltyFee = 0; - } + var royaltyFee = performDealInput.PurchaseAmount.Mul(royalty.Royalty).Div(FeeDenominator); + var royaltyFeeReceiver = State.RoyaltyFeeReceiverMap[performDealInput.NFTSymbol]; + if (royaltyFeeReceiver == null) royaltyFee = 0; - var actualAmount = performDealInput.PurchaseAmount.Sub(serviceFee).Sub(royaltyFee); - Assert(actualAmount > 0, "Incorrect deal amount."); + var actualAmount = performDealInput.PurchaseAmount.Sub(serviceFee).Sub(royaltyFee); + Assert(actualAmount > 0, "Incorrect deal amount."); + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = performDealInput.NFTTo, + To = performDealInput.NFTFrom, + Symbol = performDealInput.PurchaseSymbol, + Amount = actualAmount + }); + if (serviceFee > 0) State.TokenContract.TransferFrom.Send(new TransferFromInput { From = performDealInput.NFTTo, - To = performDealInput.NFTFrom, + To = State.ServiceFeeReceiver.Value, Symbol = performDealInput.PurchaseSymbol, - Amount = actualAmount + Amount = serviceFee }); - if (serviceFee > 0) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = performDealInput.NFTTo, - To = State.ServiceFeeReceiver.Value, - Symbol = performDealInput.PurchaseSymbol, - Amount = serviceFee - }); - } - if (royaltyFeeReceiver != null && royaltyFee > 0) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = performDealInput.NFTTo, - To = royaltyFeeReceiver, - Symbol = performDealInput.PurchaseSymbol, - Amount = royaltyFee - }); - } - } - else - { - // Exchange NFTs for NFTs. - - State.NFTContract.TransferFrom.Send(new NFT.TransferFromInput + if (royaltyFeeReceiver != null && royaltyFee > 0) + State.TokenContract.TransferFrom.Send(new TransferFromInput { From = performDealInput.NFTTo, - To = performDealInput.NFTFrom, + To = royaltyFeeReceiver, Symbol = performDealInput.PurchaseSymbol, - TokenId = performDealInput.PurchaseTokenId, - Amount = performDealInput.PurchaseAmount + Amount = royaltyFee }); - - if (State.ServiceFee.Value > 0) - { - // Charge a fixed service fee. - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = performDealInput.NFTTo, - To = State.ServiceFeeReceiver.Value, - Symbol = Context.Variables.NativeSymbol, - Amount = State.ServiceFee.Value - }); - } - } + } + else + { + // Exchange NFTs for NFTs. State.NFTContract.TransferFrom.Send(new NFT.TransferFromInput { - From = performDealInput.NFTFrom, - To = performDealInput.NFTTo, - Symbol = performDealInput.NFTSymbol, - TokenId = performDealInput.NFTTokenId, - Amount = performDealInput.NFTQuantity + From = performDealInput.NFTTo, + To = performDealInput.NFTFrom, + Symbol = performDealInput.PurchaseSymbol, + TokenId = performDealInput.PurchaseTokenId, + Amount = performDealInput.PurchaseAmount }); - Context.Fire(new Sold - { - NftFrom = performDealInput.NFTFrom, - NftTo = performDealInput.NFTTo, - NftSymbol = performDealInput.NFTSymbol, - NftTokenId = performDealInput.NFTTokenId, - NftQuantity = performDealInput.NFTQuantity, - PurchaseSymbol = performDealInput.PurchaseSymbol, - PurchaseTokenId = performDealInput.PurchaseTokenId, - PurchaseAmount = performDealInput.PurchaseAmount - }); + if (State.ServiceFee.Value > 0) + // Charge a fixed service fee. + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = performDealInput.NFTTo, + To = State.ServiceFeeReceiver.Value, + Symbol = Context.Variables.NativeSymbol, + Amount = State.ServiceFee.Value + }); } - private struct PerformDealInput + State.NFTContract.TransferFrom.Send(new NFT.TransferFromInput { - public Address NFTFrom { get; set; } - public Address NFTTo { get; set; } - public string NFTSymbol { get; set; } - public long NFTTokenId { get; set; } - public long NFTQuantity { get; set; } - public string PurchaseSymbol { get; set; } - - /// - /// If PurchaseSymbol is a Fungible token, PurchaseTokenIs shall always be 0. - /// - public long PurchaseTokenId { get; set; } - - /// - /// Be aware of that this stands for total amount. - /// - public long PurchaseAmount { get; set; } - } - - private StringList GetTokenWhiteList(string symbol) + From = performDealInput.NFTFrom, + To = performDealInput.NFTTo, + Symbol = performDealInput.NFTSymbol, + TokenId = performDealInput.NFTTokenId, + Amount = performDealInput.NFTQuantity + }); + + Context.Fire(new Sold { - var tokenWhiteList = State.TokenWhiteListMap[symbol] ?? State.GlobalTokenWhiteList.Value; - foreach (var globalWhiteListSymbol in State.GlobalTokenWhiteList.Value.Value) - { - if (!tokenWhiteList.Value.Contains(globalWhiteListSymbol)) - { - tokenWhiteList.Value.Add(globalWhiteListSymbol); - } - } + NftFrom = performDealInput.NFTFrom, + NftTo = performDealInput.NFTTo, + NftSymbol = performDealInput.NFTSymbol, + NftTokenId = performDealInput.NFTTokenId, + NftQuantity = performDealInput.NFTQuantity, + PurchaseSymbol = performDealInput.PurchaseSymbol, + PurchaseTokenId = performDealInput.PurchaseTokenId, + PurchaseAmount = performDealInput.PurchaseAmount + }); + } - return tokenWhiteList; - } + private StringList GetTokenWhiteList(string symbol) + { + var tokenWhiteList = State.TokenWhiteListMap[symbol] ?? State.GlobalTokenWhiteList.Value; + foreach (var globalWhiteListSymbol in State.GlobalTokenWhiteList.Value.Value) + if (!tokenWhiteList.Value.Contains(globalWhiteListSymbol)) + tokenWhiteList.Value.Add(globalWhiteListSymbol); - private void PerformRequestNewItem(string symbol, long tokenId, Price price, Timestamp expireTime) - { - var customizeInfo = State.CustomizeInfoMap[symbol]; - if (customizeInfo?.Price == null || customizeInfo.Price.Amount == 0) - { - throw new AssertionException("Cannot request new item for this protocol."); - } + return tokenWhiteList; + } - Assert(State.RequestInfoMap[symbol][tokenId] == null, "Request already existed."); - - var nftVirtualAddress = CalculateNFTVirtuaAddress(symbol, tokenId); - var priceSymbol = customizeInfo.Price.Symbol; - var priceAmount = price.Amount == 0 - ? customizeInfo.Price.Amount - : Math.Max(price.Amount, customizeInfo.Price.Amount); - Assert(price.Symbol == customizeInfo.Price.Symbol, "Incorrect symbol."); - Assert(priceAmount >= customizeInfo.Price.Amount, "Incorrect amount."); - // Check allowance. - var allowance = State.TokenContract.GetAllowance.Call(new MultiToken.GetAllowanceInput + private void PerformRequestNewItem(string symbol, long tokenId, Price price, Timestamp expireTime) + { + var customizeInfo = State.CustomizeInfoMap[symbol]; + if (customizeInfo?.Price == null || customizeInfo.Price.Amount == 0) + throw new AssertionException("Cannot request new item for this protocol."); + + Assert(State.RequestInfoMap[symbol][tokenId] == null, "Request already existed."); + + var nftVirtualAddress = CalculateNFTVirtuaAddress(symbol, tokenId); + var priceSymbol = customizeInfo.Price.Symbol; + var priceAmount = price.Amount == 0 + ? customizeInfo.Price.Amount + : Math.Max(price.Amount, customizeInfo.Price.Amount); + Assert(price.Symbol == customizeInfo.Price.Symbol, "Incorrect symbol."); + Assert(priceAmount >= customizeInfo.Price.Amount, "Incorrect amount."); + // Check allowance. + var allowance = State.TokenContract.GetAllowance.Call(new MultiToken.GetAllowanceInput + { + Symbol = priceSymbol, + Owner = Context.Sender, + Spender = Context.Self + }).Allowance; + Assert(allowance >= priceAmount, "Insufficient allowance."); + + var deposit = priceAmount.Mul(customizeInfo.DepositRate).Div(FeeDenominator); + if (deposit > 0) + State.TokenContract.TransferFrom.Send(new TransferFromInput { + From = Context.Sender, + To = nftVirtualAddress, Symbol = priceSymbol, - Owner = Context.Sender, - Spender = Context.Self - }).Allowance; - Assert(allowance >= priceAmount, "Insufficient allowance."); - - var deposit = priceAmount.Mul(customizeInfo.DepositRate).Div(FeeDenominator); - if (deposit > 0) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = nftVirtualAddress, - Symbol = priceSymbol, - Amount = deposit - }); - } + Amount = deposit + }); - var defaultExpireTime = Context.CurrentBlockTime.AddDays(DefaultExpireDays); - State.RequestInfoMap[symbol][tokenId] = new RequestInfo + var defaultExpireTime = Context.CurrentBlockTime.AddDays(DefaultExpireDays); + State.RequestInfoMap[symbol][tokenId] = new RequestInfo + { + Symbol = symbol, + TokenId = tokenId, + DepositRate = customizeInfo.DepositRate, + Price = new Price { - Symbol = symbol, - TokenId = tokenId, - DepositRate = customizeInfo.DepositRate, - Price = new Price - { - Symbol = priceSymbol, - Amount = priceAmount - }, - WhiteListHours = customizeInfo.WhiteListHours, - WorkHoursFromCustomizeInfo = customizeInfo.WorkHours, - Requester = Context.Sender, - ExpireTime = expireTime ?? defaultExpireTime - }; + Symbol = priceSymbol, + Amount = priceAmount + }, + WhiteListHours = customizeInfo.WhiteListHours, + WorkHoursFromCustomizeInfo = customizeInfo.WorkHours, + Requester = Context.Sender, + ExpireTime = expireTime ?? defaultExpireTime + }; + + customizeInfo.ReservedTokenIds.Add(tokenId); + State.CustomizeInfoMap[symbol] = customizeInfo; + + Context.Fire(new NewNFTRequested + { + Symbol = symbol, + Requester = Context.Sender, + TokenId = tokenId + }); + } - customizeInfo.ReservedTokenIds.Add(tokenId); - State.CustomizeInfoMap[symbol] = customizeInfo; + private bool CanBeListedWithAuction(string symbol, long tokenId, out RequestInfo requestInfo) + { + requestInfo = State.RequestInfoMap[symbol][tokenId]; - Context.Fire(new NewNFTRequested - { - Symbol = symbol, - Requester = Context.Sender, - TokenId = tokenId - }); - } + var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = symbol }); + if (nftProtocolInfo.IsTokenIdReuse) return false; - private bool CanBeListedWithAuction(string symbol, long tokenId, out RequestInfo requestInfo) + var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput { - requestInfo = State.RequestInfoMap[symbol][tokenId]; + Symbol = symbol, + TokenId = tokenId + }); + if (nftInfo.Quantity != 1) return false; - var nftProtocolInfo = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = symbol}); - if (nftProtocolInfo.IsTokenIdReuse) - { + if (requestInfo != null) + { + if (requestInfo.IsConfirmed && requestInfo.ListTime == null) + // Confirmed but never listed by fixed price. return false; - } - var nftInfo = State.NFTContract.GetNFTInfo.Call(new GetNFTInfoInput - { - Symbol = symbol, - TokenId = tokenId - }); - if (nftInfo.Quantity != 1) - { + var whiteListDueTime1 = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) + .AddHours(requestInfo.WhiteListHours); + var whiteListDueTime2 = requestInfo.ListTime.AddHours(requestInfo.WhiteListHours); + if (Context.CurrentBlockTime <= whiteListDueTime1 || Context.CurrentBlockTime <= whiteListDueTime2) return false; - } - - if (requestInfo != null) - { - if (requestInfo.IsConfirmed && requestInfo.ListTime == null) - { - // Confirmed but never listed by fixed price. - return false; - } - - var whiteListDueTime1 = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) - .AddHours(requestInfo.WhiteListHours); - var whiteListDueTime2 = requestInfo.ListTime.AddHours(requestInfo.WhiteListHours); - if (Context.CurrentBlockTime <= whiteListDueTime1 || Context.CurrentBlockTime <= whiteListDueTime2) - { - return false; - } - } - - return true; } - private Hash CalculateTokenHash(string symbol, long tokenId = 0) - { - return HashHelper.ComputeFrom($"{symbol}{tokenId}"); - } + return true; + } - private Address CalculateNFTVirtuaAddress(string symbol, long tokenId = 0) - { - return Context.ConvertVirtualAddressToContractAddress(CalculateTokenHash(symbol, tokenId)); - } + private Hash CalculateTokenHash(string symbol, long tokenId = 0) + { + return HashHelper.ComputeFrom($"{symbol}{tokenId}"); + } + + private Address CalculateNFTVirtuaAddress(string symbol, long tokenId = 0) + { + return Context.ConvertVirtualAddressToContractAddress(CalculateTokenHash(symbol, tokenId)); + } - private ListDuration AdjustListDuration(ListDuration duration) + private ListDuration AdjustListDuration(ListDuration duration) + { + if (duration == null) { - if (duration == null) - { - duration = new ListDuration - { - StartTime = Context.CurrentBlockTime, - PublicTime = Context.CurrentBlockTime, - DurationHours = int.MaxValue - }; - } - else + duration = new ListDuration { - if (duration.StartTime == null || duration.StartTime < Context.CurrentBlockTime) - { - duration.StartTime = Context.CurrentBlockTime; - } - - if (duration.PublicTime == null || duration.PublicTime < duration.StartTime) - { - duration.PublicTime = duration.StartTime; - } - - if (duration.DurationHours == 0) - { - duration.DurationHours = int.MaxValue; - } - } - - return duration; + StartTime = Context.CurrentBlockTime, + PublicTime = Context.CurrentBlockTime, + DurationHours = int.MaxValue + }; } - - private void ListRequestedNFT(ListWithFixedPriceInput input, RequestInfo requestInfo, - WhiteListAddressPriceList whiteListAddressPriceList) + else { - if (whiteListAddressPriceList == null) - { - throw new AssertionException("Incorrect white list address price list."); - } - - Assert(whiteListAddressPriceList.Value.Count == 1 && - whiteListAddressPriceList.Value.Any(p => p.Address == requestInfo.Requester), - "Incorrect white list address price list."); - Assert(input.Price.Symbol == requestInfo.Price.Symbol, $"Need to use token {requestInfo.Price.Symbol}"); - - var supposedPublicTime1 = Context.CurrentBlockTime.AddHours(requestInfo.WhiteListHours); - var supposedPublicTime2 = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) - .AddHours(requestInfo.WhiteListHours); - Assert( - input.Duration.PublicTime >= supposedPublicTime1 && - input.Duration.PublicTime >= supposedPublicTime2, "Incorrect white list hours."); + if (duration.StartTime == null || duration.StartTime < Context.CurrentBlockTime) + duration.StartTime = Context.CurrentBlockTime; - Assert(requestInfo.Price.Amount <= input.Price.Amount, "List price too low."); + if (duration.PublicTime == null || duration.PublicTime < duration.StartTime) + duration.PublicTime = duration.StartTime; - var whiteListRemainPrice = - requestInfo.Price.Amount.Sub(requestInfo.Price.Amount.Mul(requestInfo.DepositRate) - .Div(FeeDenominator)); - var delayDuration = Context.CurrentBlockTime - requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours); - if (delayDuration.Seconds > 0) - { - var reducePrice = whiteListRemainPrice.Mul(delayDuration.Seconds) - .Div(delayDuration.Seconds.Add(requestInfo.WorkHours.Mul(3600))); - whiteListRemainPrice = whiteListRemainPrice.Sub(reducePrice); - } - - whiteListAddressPriceList.Value[0].Price.Amount = Math.Min(input.Price.Amount, - Math.Min(whiteListRemainPrice, whiteListAddressPriceList.Value[0].Price.Amount)); - requestInfo.ListTime = Context.CurrentBlockTime; - State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; + if (duration.DurationHours == 0) duration.DurationHours = int.MaxValue; } - private void ClearBids(string symbol, long tokenId, Address except = null) + return duration; + } + + private void ListRequestedNFT(ListWithFixedPriceInput input, RequestInfo requestInfo, + WhiteListAddressPriceList whiteListAddressPriceList) + { + if (whiteListAddressPriceList == null) throw new AssertionException("Incorrect white list address price list."); + + Assert(whiteListAddressPriceList.Value.Count == 1 && + whiteListAddressPriceList.Value.Any(p => p.Address == requestInfo.Requester), + "Incorrect white list address price list."); + Assert(input.Price.Symbol == requestInfo.Price.Symbol, $"Need to use token {requestInfo.Price.Symbol}"); + + var supposedPublicTime1 = Context.CurrentBlockTime.AddHours(requestInfo.WhiteListHours); + var supposedPublicTime2 = requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours) + .AddHours(requestInfo.WhiteListHours); + Assert( + input.Duration.PublicTime >= supposedPublicTime1 && + input.Duration.PublicTime >= supposedPublicTime2, "Incorrect white list hours."); + + Assert(requestInfo.Price.Amount <= input.Price.Amount, "List price too low."); + + var whiteListRemainPrice = + requestInfo.Price.Amount.Sub(requestInfo.Price.Amount.Mul(requestInfo.DepositRate) + .Div(FeeDenominator)); + var delayDuration = Context.CurrentBlockTime - requestInfo.ConfirmTime.AddHours(requestInfo.WorkHours); + if (delayDuration.Seconds > 0) { - var bidAddressList = State.BidAddressListMap[symbol][tokenId]; - var auctionInfo = State.EnglishAuctionInfoMap[symbol][tokenId]; + var reducePrice = whiteListRemainPrice.Mul(delayDuration.Seconds) + .Div(delayDuration.Seconds.Add(requestInfo.WorkHours.Mul(3600))); + whiteListRemainPrice = whiteListRemainPrice.Sub(reducePrice); + } - if (bidAddressList == null || !bidAddressList.Value.Any() || auctionInfo == null) return; + whiteListAddressPriceList.Value[0].Price.Amount = Math.Min(input.Price.Amount, + Math.Min(whiteListRemainPrice, whiteListAddressPriceList.Value[0].Price.Amount)); + requestInfo.ListTime = Context.CurrentBlockTime; + State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; + } - if (except != null) - { - bidAddressList.Value.Remove(except); - } + private void ClearBids(string symbol, long tokenId, Address except = null) + { + var bidAddressList = State.BidAddressListMap[symbol][tokenId]; + var auctionInfo = State.EnglishAuctionInfoMap[symbol][tokenId]; - var transferredEarnestMoney = 0L; - foreach (var bidAddress in bidAddressList.Value) - { - if (auctionInfo.EarnestMoney > 0) - { - var earnestMoneyReceiver = State.BidMap[symbol][tokenId] == null ? auctionInfo.Owner : bidAddress; - State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(symbol, tokenId), - new TransferInput - { - To = earnestMoneyReceiver, - Symbol = auctionInfo.PurchaseSymbol, - Amount = auctionInfo.EarnestMoney - }); - transferredEarnestMoney = transferredEarnestMoney.Add(auctionInfo.EarnestMoney); - } - - State.BidMap[symbol][tokenId].Remove(bidAddress); - - Context.Fire(new BidCanceled - { - Symbol = symbol, - TokenId = tokenId, - BidFrom = bidAddress, - BidTo = Context.Sender, - }); - } + if (bidAddressList == null || !bidAddressList.Value.Any() || auctionInfo == null) return; - State.BidAddressListMap[symbol].Remove(tokenId); + if (except != null) bidAddressList.Value.Remove(except); - var virtualAddressBalance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput - { - Owner = CalculateNFTVirtuaAddress(symbol, tokenId), - Symbol = auctionInfo.PurchaseSymbol - }).Balance; - var remainAmount = virtualAddressBalance.Sub(transferredEarnestMoney); - if (except != null) - { - remainAmount = remainAmount.Sub(auctionInfo.EarnestMoney.Mul(except.Value.Length)); - } - if (remainAmount > 0) + var transferredEarnestMoney = 0L; + foreach (var bidAddress in bidAddressList.Value) + { + if (auctionInfo.EarnestMoney > 0) { + var earnestMoneyReceiver = State.BidMap[symbol][tokenId] == null ? auctionInfo.Owner : bidAddress; State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(symbol, tokenId), new TransferInput { - To = auctionInfo.Owner, + To = earnestMoneyReceiver, Symbol = auctionInfo.PurchaseSymbol, - Amount = remainAmount + Amount = auctionInfo.EarnestMoney }); + transferredEarnestMoney = transferredEarnestMoney.Add(auctionInfo.EarnestMoney); } - } - private void MaybeRemoveRequest(string symbol, long tokenId) - { - State.RequestInfoMap[symbol].Remove(tokenId); - if (State.CustomizeInfoMap[symbol] != null && State.CustomizeInfoMap[symbol].ReservedTokenIds != null && - State.CustomizeInfoMap[symbol].ReservedTokenIds.Any()) + State.BidMap[symbol][tokenId].Remove(bidAddress); + + Context.Fire(new BidCanceled { - if (State.CustomizeInfoMap[symbol].ReservedTokenIds.Contains(tokenId)) - { - State.CustomizeInfoMap[symbol].ReservedTokenIds.Remove(tokenId); - } - } + Symbol = symbol, + TokenId = tokenId, + BidFrom = bidAddress, + BidTo = Context.Sender + }); } - private bool IsListedNftTimedOut(ListedNFTInfo listedNftInfo) + State.BidAddressListMap[symbol].Remove(tokenId); + + var virtualAddressBalance = State.TokenContract.GetBalance.Call(new MultiToken.GetBalanceInput { - var expireTime = listedNftInfo.Duration.StartTime.AddHours(listedNftInfo.Duration.DurationHours); - return Context.CurrentBlockTime > expireTime; - } + Owner = CalculateNFTVirtuaAddress(symbol, tokenId), + Symbol = auctionInfo.PurchaseSymbol + }).Balance; + var remainAmount = virtualAddressBalance.Sub(transferredEarnestMoney); + if (except != null) remainAmount = remainAmount.Sub(auctionInfo.EarnestMoney.Mul(except.Value.Length)); + if (remainAmount > 0) + State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(symbol, tokenId), + new TransferInput + { + To = auctionInfo.Owner, + Symbol = auctionInfo.PurchaseSymbol, + Amount = remainAmount + }); + } + + private void MaybeRemoveRequest(string symbol, long tokenId) + { + State.RequestInfoMap[symbol].Remove(tokenId); + if (State.CustomizeInfoMap[symbol] != null && State.CustomizeInfoMap[symbol].ReservedTokenIds != null && + State.CustomizeInfoMap[symbol].ReservedTokenIds.Any()) + if (State.CustomizeInfoMap[symbol].ReservedTokenIds.Contains(tokenId)) + State.CustomizeInfoMap[symbol].ReservedTokenIds.Remove(tokenId); + } + + private bool IsListedNftTimedOut(ListedNFTInfo listedNftInfo) + { + var expireTime = listedNftInfo.Duration.StartTime.AddHours(listedNftInfo.Duration.DurationHours); + return Context.CurrentBlockTime > expireTime; + } + + private struct PerformDealInput + { + public Address NFTFrom { get; set; } + public Address NFTTo { get; set; } + public string NFTSymbol { get; set; } + public long NFTTokenId { get; set; } + public long NFTQuantity { get; set; } + public string PurchaseSymbol { get; set; } + + /// + /// If PurchaseSymbol is a Fungible token, PurchaseTokenIs shall always be 0. + /// + public long PurchaseTokenId { get; set; } + + /// + /// Be aware of that this stands for total amount. + /// + public long PurchaseAmount { get; set; } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Sellers.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Sellers.cs index 838d2de7e5..f7dfac8ee8 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Sellers.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Sellers.cs @@ -5,583 +5,546 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; using GetBalanceInput = AElf.Contracts.NFT.GetBalanceInput; -using TransferInput = AElf.Contracts.MultiToken.TransferInput; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + public override Empty ListWithFixedPrice(ListWithFixedPriceInput input) { - public override Empty ListWithFixedPrice(ListWithFixedPriceInput input) + AssertContractInitialized(); + Assert(input.Price.Amount > 0, "Incorrect listing price."); + Assert(input.Quantity > 0, "Incorrect quantity."); + var duration = AdjustListDuration(input.Duration); + var whiteListAddressPriceList = input.WhiteListAddressPriceList; + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + if (requestInfo != null) { - AssertContractInitialized(); - Assert(input.Price.Amount > 0, "Incorrect listing price."); - Assert(input.Quantity > 0, "Incorrect quantity."); - var duration = AdjustListDuration(input.Duration); - var whiteListAddressPriceList = input.WhiteListAddressPriceList; - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - if (requestInfo != null) - { - bool isWhiteListDueTimePassed; - if (requestInfo.ListTime == null) // Never listed before or delisted before. - { - isWhiteListDueTimePassed = requestInfo.WhiteListDueTime > Context.CurrentBlockTime; - } - else - { - isWhiteListDueTimePassed = requestInfo.ListTime.AddHours(requestInfo.WhiteListHours) > - Context.CurrentBlockTime; - } - - if (isWhiteListDueTimePassed) - { - // White list hours not passed -> will refresh list time and white list price. - ListRequestedNFT(input, requestInfo, whiteListAddressPriceList); - duration.StartTime = Context.CurrentBlockTime; - } - else - { - MaybeReceiveRemainDeposit(requestInfo); - } - } - - Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.Price.Symbol), - $"{input.Price.Symbol} is not in token white list."); - - var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] ?? - new ListedNFTInfoList(); - ListedNFTInfo listedNftInfo; - if (input.IsMergeToPreviousListedInfo) - { - listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => - i.Price.Symbol == input.Price.Symbol && i.Price.Amount == input.Price.Amount && - i.Owner == Context.Sender); - } + bool isWhiteListDueTimePassed; + if (requestInfo.ListTime == null) // Never listed before or delisted before. + isWhiteListDueTimePassed = requestInfo.WhiteListDueTime > Context.CurrentBlockTime; else - { - listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => - i.Price.Symbol == input.Price.Symbol && i.Price.Amount == input.Price.Amount && - i.Owner == Context.Sender && i.Duration.StartTime == input.Duration.StartTime && - i.Duration.PublicTime == input.Duration.PublicTime && - i.Duration.DurationHours == input.Duration.DurationHours); - } + isWhiteListDueTimePassed = requestInfo.ListTime.AddHours(requestInfo.WhiteListHours) > + Context.CurrentBlockTime; - bool isMergedToPreviousListedInfo; - if (listedNftInfo == null) + if (isWhiteListDueTimePassed) { - listedNftInfo = new ListedNFTInfo - { - ListType = ListType.FixedPrice, - Owner = Context.Sender, - Price = input.Price, - Quantity = input.Quantity, - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - }; - listedNftInfoList.Value.Add(listedNftInfo); - isMergedToPreviousListedInfo = false; - Context.Fire(new ListedNFTAdded - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - Owner = Context.Sender, - Price = input.Price, - Quantity = input.Quantity, - }); + // White list hours not passed -> will refresh list time and white list price. + ListRequestedNFT(input, requestInfo, whiteListAddressPriceList); + duration.StartTime = Context.CurrentBlockTime; } else { - listedNftInfo.Quantity = listedNftInfo.Quantity.Add(input.Quantity); - var previousDuration = listedNftInfo.Duration.Clone(); - listedNftInfo.Duration = duration; - isMergedToPreviousListedInfo = true; - Context.Fire(new ListedNFTChanged - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - Owner = Context.Sender, - Price = input.Price, - Quantity = listedNftInfo.Quantity, - PreviousDuration = previousDuration - }); - } - - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = listedNftInfoList; - - var totalQuantity = listedNftInfoList.Value.Where(i => i.Owner == Context.Sender).Sum(i => i.Quantity); - CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, totalQuantity); - - if (whiteListAddressPriceList != null) - { - State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][Context.Sender] = - whiteListAddressPriceList; + MaybeReceiveRemainDeposit(requestInfo); } - - ClearBids(input.Symbol, input.TokenId); - State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); - State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); - - Context.Fire(new FixedPriceNFTListed - { - Owner = listedNftInfo.Owner, - Price = listedNftInfo.Price, - Quantity = listedNftInfo.Quantity, - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - IsMergedToPreviousListedInfo = isMergedToPreviousListedInfo, - WhiteListAddressPriceList = whiteListAddressPriceList - }); - - return new Empty(); } - public override Empty ListWithEnglishAuction(ListWithEnglishAuctionInput input) + Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.Price.Symbol), + $"{input.Price.Symbol} is not in token white list."); + + var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] ?? + new ListedNFTInfoList(); + ListedNFTInfo listedNftInfo; + if (input.IsMergeToPreviousListedInfo) + listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => + i.Price.Symbol == input.Price.Symbol && i.Price.Amount == input.Price.Amount && + i.Owner == Context.Sender); + else + listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => + i.Price.Symbol == input.Price.Symbol && i.Price.Amount == input.Price.Amount && + i.Owner == Context.Sender && i.Duration.StartTime == input.Duration.StartTime && + i.Duration.PublicTime == input.Duration.PublicTime && + i.Duration.DurationHours == input.Duration.DurationHours); + + bool isMergedToPreviousListedInfo; + if (listedNftInfo == null) { - AssertContractInitialized(); - Assert(input.StartingPrice > 0, "Incorrect listing price."); - Assert(input.EarnestMoney <= input.StartingPrice, "Earnest money too high."); - if (CanBeListedWithAuction(input.Symbol, input.TokenId, out var requestInfo)) + listedNftInfo = new ListedNFTInfo { - MaybeReceiveRemainDeposit(requestInfo); - } - else - { - throw new AssertionException("This NFT cannot be listed with auction for now."); - } - - CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, 1); - - Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.PurchaseSymbol), - $"{input.PurchaseSymbol} is not in token white list."); - Assert( - string.IsNullOrEmpty(State.NFTContract.GetNFTProtocolInfo - .Call(new StringValue {Value = input.PurchaseSymbol}).Symbol), - $"Token {input.PurchaseSymbol} not support purchase for auction."); - - ClearBids(input.Symbol, input.TokenId); - - var duration = AdjustListDuration(input.Duration); - - var englishAuctionInfo = new EnglishAuctionInfo + ListType = ListType.FixedPrice, + Owner = Context.Sender, + Price = input.Price, + Quantity = input.Quantity, + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = duration + }; + listedNftInfoList.Value.Add(listedNftInfo); + isMergedToPreviousListedInfo = false; + Context.Fire(new ListedNFTAdded { Symbol = input.Symbol, TokenId = input.TokenId, Duration = duration, - PurchaseSymbol = input.PurchaseSymbol, - StartingPrice = input.StartingPrice, Owner = Context.Sender, - EarnestMoney = input.EarnestMoney - }; - State.EnglishAuctionInfoMap[input.Symbol][input.TokenId] = englishAuctionInfo; - - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = new ListedNFTInfoList - { - Value = - { - new ListedNFTInfo - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - ListType = ListType.EnglishAuction, - Owner = Context.Sender, - Price = new Price - { - Symbol = input.PurchaseSymbol, - Amount = input.StartingPrice - }, - Quantity = 1 - } - } - }; - - State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); - - Context.Fire(new EnglishAuctionNFTListed - { - Owner = englishAuctionInfo.Owner, - Symbol = englishAuctionInfo.Symbol, - PurchaseSymbol = englishAuctionInfo.PurchaseSymbol, - StartingPrice = englishAuctionInfo.StartingPrice, - TokenId = englishAuctionInfo.TokenId, - Duration = englishAuctionInfo.Duration, - EarnestMoney = englishAuctionInfo.EarnestMoney + Price = input.Price, + Quantity = input.Quantity }); - - Context.Fire(new ListedNFTAdded + } + else + { + listedNftInfo.Quantity = listedNftInfo.Quantity.Add(input.Quantity); + var previousDuration = listedNftInfo.Duration.Clone(); + listedNftInfo.Duration = duration; + isMergedToPreviousListedInfo = true; + Context.Fire(new ListedNFTChanged { Symbol = input.Symbol, TokenId = input.TokenId, - Duration = englishAuctionInfo.Duration, - Owner = englishAuctionInfo.Owner, - Price = new Price - { - Symbol = englishAuctionInfo.PurchaseSymbol, - Amount = englishAuctionInfo.StartingPrice - }, - Quantity = 1 + Duration = duration, + Owner = Context.Sender, + Price = input.Price, + Quantity = listedNftInfo.Quantity, + PreviousDuration = previousDuration }); - - return new Empty(); } - public override Empty ListWithDutchAuction(ListWithDutchAuctionInput input) - { - AssertContractInitialized(); - Assert(input.StartingPrice > 0 && input.EndingPrice > 0 && input.StartingPrice > input.EndingPrice, - "Incorrect listing price."); - if (CanBeListedWithAuction(input.Symbol, input.TokenId, out var requestInfo)) - { - MaybeReceiveRemainDeposit(requestInfo); - } - else - { - throw new AssertionException("This NFT cannot be listed with auction for now."); - } + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = listedNftInfoList; - CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, 1); + var totalQuantity = listedNftInfoList.Value.Where(i => i.Owner == Context.Sender).Sum(i => i.Quantity); + CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, totalQuantity); - Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.PurchaseSymbol), - $"{input.PurchaseSymbol} is not in token white list."); - Assert( - string.IsNullOrEmpty(State.NFTContract.GetNFTProtocolInfo - .Call(new StringValue {Value = input.PurchaseSymbol}).Symbol), - $"Token {input.PurchaseSymbol} not support purchase for auction."); + if (whiteListAddressPriceList != null) + State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][Context.Sender] = + whiteListAddressPriceList; - var duration = AdjustListDuration(input.Duration); + ClearBids(input.Symbol, input.TokenId); + State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); + State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); - var dutchAuctionInfo = new DutchAuctionInfo - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - PurchaseSymbol = input.PurchaseSymbol, - StartingPrice = input.StartingPrice, - EndingPrice = input.EndingPrice, - Owner = Context.Sender - }; - State.DutchAuctionInfoMap[input.Symbol][input.TokenId] = dutchAuctionInfo; + Context.Fire(new FixedPriceNFTListed + { + Owner = listedNftInfo.Owner, + Price = listedNftInfo.Price, + Quantity = listedNftInfo.Quantity, + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + IsMergedToPreviousListedInfo = isMergedToPreviousListedInfo, + WhiteListAddressPriceList = whiteListAddressPriceList + }); + + return new Empty(); + } - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = new ListedNFTInfoList - { - Value = - { - new ListedNFTInfo - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = duration, - ListType = ListType.DutchAuction, - Owner = Context.Sender, - Price = new Price - { - Symbol = input.PurchaseSymbol, - Amount = input.StartingPrice - }, - Quantity = 1 - } - } - }; + public override Empty ListWithEnglishAuction(ListWithEnglishAuctionInput input) + { + AssertContractInitialized(); + Assert(input.StartingPrice > 0, "Incorrect listing price."); + Assert(input.EarnestMoney <= input.StartingPrice, "Earnest money too high."); + if (CanBeListedWithAuction(input.Symbol, input.TokenId, out var requestInfo)) + MaybeReceiveRemainDeposit(requestInfo); + else + throw new AssertionException("This NFT cannot be listed with auction for now."); - ClearBids(input.Symbol, input.TokenId); - State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); + CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, 1); - Context.Fire(new DutchAuctionNFTListed - { - Owner = dutchAuctionInfo.Owner, - PurchaseSymbol = dutchAuctionInfo.PurchaseSymbol, - StartingPrice = dutchAuctionInfo.StartingPrice, - EndingPrice = dutchAuctionInfo.EndingPrice, - Symbol = dutchAuctionInfo.Symbol, - TokenId = dutchAuctionInfo.TokenId, - Duration = dutchAuctionInfo.Duration - }); + Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.PurchaseSymbol), + $"{input.PurchaseSymbol} is not in token white list."); + Assert( + string.IsNullOrEmpty(State.NFTContract.GetNFTProtocolInfo + .Call(new StringValue { Value = input.PurchaseSymbol }).Symbol), + $"Token {input.PurchaseSymbol} not support purchase for auction."); - Context.Fire(new ListedNFTAdded - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Duration = dutchAuctionInfo.Duration, - Owner = dutchAuctionInfo.Owner, - Price = new Price - { - Symbol = dutchAuctionInfo.PurchaseSymbol, - Amount = dutchAuctionInfo.StartingPrice - }, - Quantity = 1 - }); + ClearBids(input.Symbol, input.TokenId); - return new Empty(); - } + var duration = AdjustListDuration(input.Duration); - public override Empty Delist(DelistInput input) + var englishAuctionInfo = new EnglishAuctionInfo { - CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, input.Quantity); - var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender]; - if (listedNftInfoList == null || listedNftInfoList.Value.All(i => i.ListType == ListType.NotListed)) + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = duration, + PurchaseSymbol = input.PurchaseSymbol, + StartingPrice = input.StartingPrice, + Owner = Context.Sender, + EarnestMoney = input.EarnestMoney + }; + State.EnglishAuctionInfoMap[input.Symbol][input.TokenId] = englishAuctionInfo; + + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = new ListedNFTInfoList + { + Value = { - throw new AssertionException("Listed NFT Info not exists. (Or already delisted.)"); + new ListedNFTInfo + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = duration, + ListType = ListType.EnglishAuction, + Owner = Context.Sender, + Price = new Price + { + Symbol = input.PurchaseSymbol, + Amount = input.StartingPrice + }, + Quantity = 1 + } } + }; - Assert(input.Price != null, "Need to specific list record."); - var listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => - i.Price.Amount == input.Price.Amount && i.Price.Symbol == input.Price.Symbol && - i.Owner == Context.Sender); - if (listedNftInfo == null) - { - throw new AssertionException("Listed NFT Info not exists. (Or already delisted.)"); - } + State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - if (requestInfo != null) - { - requestInfo.ListTime = null; - State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; - } + Context.Fire(new EnglishAuctionNFTListed + { + Owner = englishAuctionInfo.Owner, + Symbol = englishAuctionInfo.Symbol, + PurchaseSymbol = englishAuctionInfo.PurchaseSymbol, + StartingPrice = englishAuctionInfo.StartingPrice, + TokenId = englishAuctionInfo.TokenId, + Duration = englishAuctionInfo.Duration, + EarnestMoney = englishAuctionInfo.EarnestMoney + }); + + Context.Fire(new ListedNFTAdded + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = englishAuctionInfo.Duration, + Owner = englishAuctionInfo.Owner, + Price = new Price + { + Symbol = englishAuctionInfo.PurchaseSymbol, + Amount = englishAuctionInfo.StartingPrice + }, + Quantity = 1 + }); + + return new Empty(); + } - switch (listedNftInfo.ListType) + public override Empty ListWithDutchAuction(ListWithDutchAuctionInput input) + { + AssertContractInitialized(); + Assert(input.StartingPrice > 0 && input.EndingPrice > 0 && input.StartingPrice > input.EndingPrice, + "Incorrect listing price."); + if (CanBeListedWithAuction(input.Symbol, input.TokenId, out var requestInfo)) + MaybeReceiveRemainDeposit(requestInfo); + else + throw new AssertionException("This NFT cannot be listed with auction for now."); + + CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, 1); + + Assert(GetTokenWhiteList(input.Symbol).Value.Contains(input.PurchaseSymbol), + $"{input.PurchaseSymbol} is not in token white list."); + Assert( + string.IsNullOrEmpty(State.NFTContract.GetNFTProtocolInfo + .Call(new StringValue { Value = input.PurchaseSymbol }).Symbol), + $"Token {input.PurchaseSymbol} not support purchase for auction."); + + var duration = AdjustListDuration(input.Duration); + + var dutchAuctionInfo = new DutchAuctionInfo + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = duration, + PurchaseSymbol = input.PurchaseSymbol, + StartingPrice = input.StartingPrice, + EndingPrice = input.EndingPrice, + Owner = Context.Sender + }; + State.DutchAuctionInfoMap[input.Symbol][input.TokenId] = dutchAuctionInfo; + + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = new ListedNFTInfoList + { + Value = { - case ListType.FixedPrice when input.Quantity >= listedNftInfo.Quantity: - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); - Context.Fire(new ListedNFTRemoved - { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner - }); - break; - case ListType.FixedPrice: - listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(input.Quantity); - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = listedNftInfoList; - Context.Fire(new ListedNFTChanged - { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner, - Price = listedNftInfo.Price, - Quantity = listedNftInfo.Quantity - }); - break; - case ListType.EnglishAuction: - var englishAuctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId]; - if (bidAddressList != null && bidAddressList.Value.Any()) - { - // Charge service fee if anyone placed a bid. - ChargeSenderServiceFee(englishAuctionInfo.PurchaseSymbol, englishAuctionInfo.StartingPrice); - } - ClearBids(englishAuctionInfo.Symbol, englishAuctionInfo.TokenId); - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); - State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); - Context.Fire(new ListedNFTRemoved - { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner - }); - break; - case ListType.DutchAuction: - var dutchAuctionInfo = State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; - State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); - State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); - ChargeSenderServiceFee(dutchAuctionInfo.PurchaseSymbol, dutchAuctionInfo.StartingPrice); - Context.Fire(new ListedNFTRemoved + new ListedNFTInfo + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = duration, + ListType = ListType.DutchAuction, + Owner = Context.Sender, + Price = new Price { - Symbol = listedNftInfo.Symbol, - TokenId = listedNftInfo.TokenId, - Duration = listedNftInfo.Duration, - Owner = listedNftInfo.Owner - }); - break; + Symbol = input.PurchaseSymbol, + Amount = input.StartingPrice + }, + Quantity = 1 + } } + }; - Context.Fire(new NFTDelisted - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Owner = Context.Sender, - Quantity = input.Quantity - }); + ClearBids(input.Symbol, input.TokenId); + State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); + + Context.Fire(new DutchAuctionNFTListed + { + Owner = dutchAuctionInfo.Owner, + PurchaseSymbol = dutchAuctionInfo.PurchaseSymbol, + StartingPrice = dutchAuctionInfo.StartingPrice, + EndingPrice = dutchAuctionInfo.EndingPrice, + Symbol = dutchAuctionInfo.Symbol, + TokenId = dutchAuctionInfo.TokenId, + Duration = dutchAuctionInfo.Duration + }); + + Context.Fire(new ListedNFTAdded + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Duration = dutchAuctionInfo.Duration, + Owner = dutchAuctionInfo.Owner, + Price = new Price + { + Symbol = dutchAuctionInfo.PurchaseSymbol, + Amount = dutchAuctionInfo.StartingPrice + }, + Quantity = 1 + }); + + return new Empty(); + } - return new Empty(); + public override Empty Delist(DelistInput input) + { + CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, input.Quantity); + var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender]; + if (listedNftInfoList == null || listedNftInfoList.Value.All(i => i.ListType == ListType.NotListed)) + throw new AssertionException("Listed NFT Info not exists. (Or already delisted.)"); + + Assert(input.Price != null, "Need to specific list record."); + var listedNftInfo = listedNftInfoList.Value.FirstOrDefault(i => + i.Price.Amount == input.Price.Amount && i.Price.Symbol == input.Price.Symbol && + i.Owner == Context.Sender); + if (listedNftInfo == null) throw new AssertionException("Listed NFT Info not exists. (Or already delisted.)"); + + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + if (requestInfo != null) + { + requestInfo.ListTime = null; + State.RequestInfoMap[input.Symbol][input.TokenId] = requestInfo; } - private void ChargeSenderServiceFee(string symbol, long baseAmount) + switch (listedNftInfo.ListType) { - var amount = baseAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); - if (amount > 0) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput + case ListType.FixedPrice when input.Quantity >= listedNftInfo.Quantity: + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); + Context.Fire(new ListedNFTRemoved { - Symbol = symbol, - Amount = amount, - From = Context.Sender, - To = State.ServiceFeeReceiver.Value ?? State.Admin.Value + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner }); - } + break; + case ListType.FixedPrice: + listedNftInfo.Quantity = listedNftInfo.Quantity.Sub(input.Quantity); + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender] = listedNftInfoList; + Context.Fire(new ListedNFTChanged + { + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner, + Price = listedNftInfo.Price, + Quantity = listedNftInfo.Quantity + }); + break; + case ListType.EnglishAuction: + var englishAuctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; + var bidAddressList = State.BidAddressListMap[input.Symbol][input.TokenId]; + if (bidAddressList != null && bidAddressList.Value.Any()) + // Charge service fee if anyone placed a bid. + ChargeSenderServiceFee(englishAuctionInfo.PurchaseSymbol, englishAuctionInfo.StartingPrice); + ClearBids(englishAuctionInfo.Symbol, englishAuctionInfo.TokenId); + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); + State.EnglishAuctionInfoMap[input.Symbol].Remove(input.TokenId); + Context.Fire(new ListedNFTRemoved + { + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner + }); + break; + case ListType.DutchAuction: + var dutchAuctionInfo = State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; + State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender].Value.Remove(listedNftInfo); + State.DutchAuctionInfoMap[input.Symbol].Remove(input.TokenId); + ChargeSenderServiceFee(dutchAuctionInfo.PurchaseSymbol, dutchAuctionInfo.StartingPrice); + Context.Fire(new ListedNFTRemoved + { + Symbol = listedNftInfo.Symbol, + TokenId = listedNftInfo.TokenId, + Duration = listedNftInfo.Duration, + Owner = listedNftInfo.Owner + }); + break; } - /// - /// Sender is the seller. - /// - /// - /// - /// - public override Empty Deal(DealInput input) + Context.Fire(new NFTDelisted { - AssertContractInitialized(); - - Assert(input.Symbol != null, "Incorrect symbol."); - Assert(input.TokenId != 0, "Incorrect token id."); - Assert(input.OfferFrom != null, "Incorrect offer maker."); - if (input.Price?.Symbol == null) - { - throw new AssertionException("Incorrect price."); - } + Symbol = input.Symbol, + TokenId = input.TokenId, + Owner = Context.Sender, + Quantity = input.Quantity + }); - CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, input.Quantity); + return new Empty(); + } - var balance = State.NFTContract.GetBalance.Call(new GetBalanceInput - { - Symbol = input.Symbol, - TokenId = input.TokenId, - Owner = Context.Sender + private void ChargeSenderServiceFee(string symbol, long baseAmount) + { + var amount = baseAmount.Mul(State.ServiceFeeRate.Value).Div(FeeDenominator); + if (amount > 0) + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + Symbol = symbol, + Amount = amount, + From = Context.Sender, + To = State.ServiceFeeReceiver.Value ?? State.Admin.Value }); - Assert(balance.Balance >= input.Quantity, "Insufficient NFT balance."); + } - var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; - if (requestInfo != null) - { - Assert(Context.CurrentBlockTime > requestInfo.WhiteListDueTime, "Due time not passed."); - } + /// + /// Sender is the seller. + /// + /// + /// + /// + public override Empty Deal(DealInput input) + { + AssertContractInitialized(); - var offer = State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom]?.Value - .FirstOrDefault(o => - o.From == input.OfferFrom && o.Price.Symbol == input.Price.Symbol && - o.Price.Amount == input.Price.Amount && o.ExpireTime >= Context.CurrentBlockTime); - var bid = State.BidMap[input.Symbol][input.TokenId][input.OfferFrom]; - Price price; - long totalAmount; - if (offer == null) - { - // Check bid. + Assert(input.Symbol != null, "Incorrect symbol."); + Assert(input.TokenId != 0, "Incorrect token id."); + Assert(input.OfferFrom != null, "Incorrect offer maker."); + if (input.Price?.Symbol == null) throw new AssertionException("Incorrect price."); - if (bid == null || bid.From != input.OfferFrom || - bid.Price.Amount != input.Price.Amount || bid.Price.Symbol != input.Price.Symbol || - bid.ExpireTime < Context.CurrentBlockTime) - { - throw new AssertionException("Neither related offer nor bid are found."); - } + CheckSenderNFTBalanceAndAllowance(input.Symbol, input.TokenId, input.Quantity); + + var balance = State.NFTContract.GetBalance.Call(new GetBalanceInput + { + Symbol = input.Symbol, + TokenId = input.TokenId, + Owner = Context.Sender + }); + Assert(balance.Balance >= input.Quantity, "Insufficient NFT balance."); + + var requestInfo = State.RequestInfoMap[input.Symbol][input.TokenId]; + if (requestInfo != null) + Assert(Context.CurrentBlockTime > requestInfo.WhiteListDueTime, "Due time not passed."); + + var offer = State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom]?.Value + .FirstOrDefault(o => + o.From == input.OfferFrom && o.Price.Symbol == input.Price.Symbol && + o.Price.Amount == input.Price.Amount && o.ExpireTime >= Context.CurrentBlockTime); + var bid = State.BidMap[input.Symbol][input.TokenId][input.OfferFrom]; + Price price; + long totalAmount; + if (offer == null) + { + // Check bid. - price = bid.Price; + if (bid == null || bid.From != input.OfferFrom || + bid.Price.Amount != input.Price.Amount || bid.Price.Symbol != input.Price.Symbol || + bid.ExpireTime < Context.CurrentBlockTime) + throw new AssertionException("Neither related offer nor bid are found."); - Assert(price.TokenId == 0, "Do not support use NFT to purchase auction."); + price = bid.Price; - var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; + Assert(price.TokenId == 0, "Do not support use NFT to purchase auction."); - totalAmount = price.Amount; + var auctionInfo = State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - // Transfer earnest money back to the bidder at first. - if (auctionInfo.EarnestMoney > 0) - { - State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), - new TransferInput - { - To = bid.From, - Symbol = price.Symbol, - Amount = auctionInfo.EarnestMoney - }); - } + totalAmount = price.Amount; - if (!CheckAllowanceAndBalanceIsEnough(bid.From, price.Symbol, totalAmount.Sub(auctionInfo.EarnestMoney))) - { - State.BidMap[input.Symbol][input.TokenId].Remove(bid.From); - Context.Fire(new BidCanceled + // Transfer earnest money back to the bidder at first. + if (auctionInfo.EarnestMoney > 0) + State.TokenContract.Transfer.VirtualSend(CalculateTokenHash(input.Symbol, input.TokenId), + new TransferInput { - Symbol = input.Symbol, - TokenId = input.TokenId, - BidFrom = input.OfferFrom, - BidTo = Context.Sender + To = bid.From, + Symbol = price.Symbol, + Amount = auctionInfo.EarnestMoney }); - return new Empty(); - } - - auctionInfo.DealPrice = input.Price.Amount; - auctionInfo.DealTo = input.OfferFrom; - State.EnglishAuctionInfoMap[input.Symbol][input.TokenId] = auctionInfo; - ClearBids(input.Symbol, input.TokenId, input.OfferFrom); - } - else + if (!CheckAllowanceAndBalanceIsEnough(bid.From, price.Symbol, totalAmount.Sub(auctionInfo.EarnestMoney))) { - Assert(offer.Quantity >= input.Quantity, "Deal quantity exceeded."); - offer.Quantity = offer.Quantity.Sub(input.Quantity); - if (offer.Quantity == 0) + State.BidMap[input.Symbol][input.TokenId].Remove(bid.From); + Context.Fire(new BidCanceled { - State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom].Value.Remove(offer); - Context.Fire(new OfferRemoved - { - Symbol = input.Symbol, - TokenId = input.TokenId, - OfferFrom = input.OfferFrom, - OfferTo = Context.Sender, - ExpireTime = offer.ExpireTime - }); - } - - price = offer.Price; - totalAmount = price.Amount.Mul(input.Quantity); + Symbol = input.Symbol, + TokenId = input.TokenId, + BidFrom = input.OfferFrom, + BidTo = Context.Sender + }); + return new Empty(); } - var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender]; - if (listedNftInfoList != null && listedNftInfoList.Value.Any()) + auctionInfo.DealPrice = input.Price.Amount; + auctionInfo.DealTo = input.OfferFrom; + State.EnglishAuctionInfoMap[input.Symbol][input.TokenId] = auctionInfo; + + ClearBids(input.Symbol, input.TokenId, input.OfferFrom); + } + else + { + Assert(offer.Quantity >= input.Quantity, "Deal quantity exceeded."); + offer.Quantity = offer.Quantity.Sub(input.Quantity); + if (offer.Quantity == 0) { - var firstListedNftInfo = listedNftInfoList.Value.First(); - if (firstListedNftInfo.ListType != ListType.EnglishAuction && firstListedNftInfo.ListType != ListType.DutchAuction) + State.OfferListMap[input.Symbol][input.TokenId][input.OfferFrom].Value.Remove(offer); + Context.Fire(new OfferRemoved { - // Listed with fixed price. + Symbol = input.Symbol, + TokenId = input.TokenId, + OfferFrom = input.OfferFrom, + OfferTo = Context.Sender, + ExpireTime = offer.ExpireTime + }); + } - var nftBalance = State.NFTContract.GetBalance.Call(new GetBalanceInput - { - Symbol = input.Symbol, - Owner = Context.Sender, - TokenId = input.TokenId - }).Balance; - var listedQuantity = listedNftInfoList.Value.Where(i => i.Owner == Context.Sender).Sum(i => i.Quantity); - Assert(nftBalance >= listedQuantity.Add(input.Quantity), - $"Need to delist at least {listedQuantity.Add(input.Quantity).Sub(nftBalance)} NFT(s) before deal."); - } - else + price = offer.Price; + totalAmount = price.Amount.Mul(input.Quantity); + } + + var listedNftInfoList = State.ListedNFTInfoListMap[input.Symbol][input.TokenId][Context.Sender]; + if (listedNftInfoList != null && listedNftInfoList.Value.Any()) + { + var firstListedNftInfo = listedNftInfoList.Value.First(); + if (firstListedNftInfo.ListType != ListType.EnglishAuction && + firstListedNftInfo.ListType != ListType.DutchAuction) + { + // Listed with fixed price. + + var nftBalance = State.NFTContract.GetBalance.Call(new GetBalanceInput { - State.ListedNFTInfoListMap[input.Symbol][input.TokenId].Remove(Context.Sender); - Context.Fire(new ListedNFTRemoved - { - Symbol = firstListedNftInfo.Symbol, - TokenId = firstListedNftInfo.TokenId, - Duration = firstListedNftInfo.Duration, - Owner = firstListedNftInfo.Owner - }); - } + Symbol = input.Symbol, + Owner = Context.Sender, + TokenId = input.TokenId + }).Balance; + var listedQuantity = listedNftInfoList.Value.Where(i => i.Owner == Context.Sender).Sum(i => i.Quantity); + Assert(nftBalance >= listedQuantity.Add(input.Quantity), + $"Need to delist at least {listedQuantity.Add(input.Quantity).Sub(nftBalance)} NFT(s) before deal."); } - - PerformDeal(new PerformDealInput + else { - NFTFrom = Context.Sender, - NFTTo = offer?.From ?? bid.From, - NFTSymbol = input.Symbol, - NFTTokenId = input.TokenId, - NFTQuantity = input.Quantity, - PurchaseSymbol = price.Symbol, - PurchaseAmount = totalAmount, - PurchaseTokenId = price.TokenId - }); - return new Empty(); + State.ListedNFTInfoListMap[input.Symbol][input.TokenId].Remove(Context.Sender); + Context.Fire(new ListedNFTRemoved + { + Symbol = firstListedNftInfo.Symbol, + TokenId = firstListedNftInfo.TokenId, + Duration = firstListedNftInfo.Duration, + Owner = firstListedNftInfo.Owner + }); + } } + + PerformDeal(new PerformDealInput + { + NFTFrom = Context.Sender, + NFTTo = offer?.From ?? bid.From, + NFTSymbol = input.Symbol, + NFTTokenId = input.TokenId, + NFTQuantity = input.Quantity, + PurchaseSymbol = price.Symbol, + PurchaseAmount = totalAmount, + PurchaseTokenId = price.TokenId + }); + return new Empty(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Views.cs b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Views.cs index f04bf30c74..966a14be1a 100644 --- a/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Views.cs +++ b/contract/AElf.Contracts.NFTMarket/NFTMarketContract_Views.cs @@ -1,156 +1,138 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMarket +namespace AElf.Contracts.NFTMarket; + +public partial class NFTMarketContract { - public partial class NFTMarketContract + public override ListedNFTInfoList GetListedNFTInfoList(GetListedNFTInfoListInput input) { - public override ListedNFTInfoList GetListedNFTInfoList(GetListedNFTInfoListInput input) - { - return State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.Owner]; - } + return State.ListedNFTInfoListMap[input.Symbol][input.TokenId][input.Owner]; + } - public override WhiteListAddressPriceList GetWhiteListAddressPriceList(GetWhiteListAddressPriceListInput input) - { - return State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.Owner]; - } + public override WhiteListAddressPriceList GetWhiteListAddressPriceList(GetWhiteListAddressPriceListInput input) + { + return State.WhiteListAddressPriceListMap[input.Symbol][input.TokenId][input.Owner]; + } - public override AddressList GetOfferAddressList(GetAddressListInput input) - { - return State.OfferAddressListMap[input.Symbol][input.TokenId]; - } + public override AddressList GetOfferAddressList(GetAddressListInput input) + { + return State.OfferAddressListMap[input.Symbol][input.TokenId]; + } - public override OfferList GetOfferList(GetOfferListInput input) - { - if (input.Address != null) - { - return State.OfferListMap[input.Symbol][input.TokenId][input.Address]; - } - - var addressList = GetOfferAddressList(new GetAddressListInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }) ?? new AddressList(); - var allOfferList = new OfferList(); - foreach (var address in addressList.Value) - { - var offerList = State.OfferListMap[input.Symbol][input.TokenId][address]; - if (offerList != null) - { - allOfferList.Value.Add(offerList.Value); - } - } - - return allOfferList; - } + public override OfferList GetOfferList(GetOfferListInput input) + { + if (input.Address != null) return State.OfferListMap[input.Symbol][input.TokenId][input.Address]; - public override AddressList GetBidAddressList(GetAddressListInput input) + var addressList = GetOfferAddressList(new GetAddressListInput { - return State.BidAddressListMap[input.Symbol][input.TokenId]; - } - - public override Bid GetBid(GetBidInput input) + Symbol = input.Symbol, + TokenId = input.TokenId + }) ?? new AddressList(); + var allOfferList = new OfferList(); + foreach (var address in addressList.Value) { - return State.BidMap[input.Symbol][input.TokenId][input.Address]; + var offerList = State.OfferListMap[input.Symbol][input.TokenId][address]; + if (offerList != null) allOfferList.Value.Add(offerList.Value); } - public override BidList GetBidList(GetBidListInput input) - { - var addressList = GetBidAddressList(new GetAddressListInput - { - Symbol = input.Symbol, - TokenId = input.TokenId - }) ?? new AddressList(); - var allBidList = new BidList(); - foreach (var address in addressList.Value) - { - var bid = State.BidMap[input.Symbol][input.TokenId][address]; - if (bid != null) - { - allBidList.Value.Add(bid); - } - } - - return allBidList; - } + return allOfferList; + } - public override CustomizeInfo GetCustomizeInfo(StringValue input) - { - return State.CustomizeInfoMap[input.Value]; - } + public override AddressList GetBidAddressList(GetAddressListInput input) + { + return State.BidAddressListMap[input.Symbol][input.TokenId]; + } - public override RequestInfo GetRequestInfo(GetRequestInfoInput input) - { - return State.RequestInfoMap[input.Symbol][input.TokenId]; - } + public override Bid GetBid(GetBidInput input) + { + return State.BidMap[input.Symbol][input.TokenId][input.Address]; + } - public override EnglishAuctionInfo GetEnglishAuctionInfo(GetEnglishAuctionInfoInput input) + public override BidList GetBidList(GetBidListInput input) + { + var addressList = GetBidAddressList(new GetAddressListInput { - return State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; - } - - public override DutchAuctionInfo GetDutchAuctionInfo(GetDutchAuctionInfoInput input) + Symbol = input.Symbol, + TokenId = input.TokenId + }) ?? new AddressList(); + var allBidList = new BidList(); + foreach (var address in addressList.Value) { - return State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; + var bid = State.BidMap[input.Symbol][input.TokenId][address]; + if (bid != null) allBidList.Value.Add(bid); } - public override StringList GetTokenWhiteList(StringValue input) - { - return GetTokenWhiteList(input.Value); - } + return allBidList; + } + + public override CustomizeInfo GetCustomizeInfo(StringValue input) + { + return State.CustomizeInfoMap[input.Value]; + } + + public override RequestInfo GetRequestInfo(GetRequestInfoInput input) + { + return State.RequestInfoMap[input.Symbol][input.TokenId]; + } - public override StringList GetGlobalTokenWhiteList(Empty input) + public override EnglishAuctionInfo GetEnglishAuctionInfo(GetEnglishAuctionInfoInput input) + { + return State.EnglishAuctionInfoMap[input.Symbol][input.TokenId]; + } + + public override DutchAuctionInfo GetDutchAuctionInfo(GetDutchAuctionInfoInput input) + { + return State.DutchAuctionInfoMap[input.Symbol][input.TokenId]; + } + + public override StringList GetTokenWhiteList(StringValue input) + { + return GetTokenWhiteList(input.Value); + } + + public override StringList GetGlobalTokenWhiteList(Empty input) + { + return State.GlobalTokenWhiteList.Value; + } + + public override Price GetStakingTokens(StringValue input) + { + var customizeInfo = State.CustomizeInfoMap[input.Value]; + if (customizeInfo == null) return new Price(); + + return new Price { - return State.GlobalTokenWhiteList.Value; - } + Symbol = customizeInfo.Price.Symbol, + Amount = customizeInfo.StakingAmount + }; + } - public override Price GetStakingTokens(StringValue input) + public override RoyaltyInfo GetRoyalty(GetRoyaltyInput input) + { + var royaltyInfo = new RoyaltyInfo { - var customizeInfo = State.CustomizeInfoMap[input.Value]; - if (customizeInfo == null) - { - return new Price(); - } - - return new Price - { - Symbol = customizeInfo.Price.Symbol, - Amount = customizeInfo.StakingAmount - }; - } + Royalty = State.RoyaltyMap[input.Symbol] + }; - public override RoyaltyInfo GetRoyalty(GetRoyaltyInput input) + if (input.TokenId != 0) { - var royaltyInfo = new RoyaltyInfo - { - Royalty = State.RoyaltyMap[input.Symbol] - }; - - if (input.TokenId != 0) - { - var certainNftRoyalty = State.CertainNFTRoyaltyMap[input.Symbol][input.TokenId] ?? - new CertainNFTRoyaltyInfo(); - if (certainNftRoyalty.IsManuallySet) - { - royaltyInfo.Royalty = certainNftRoyalty.Royalty; - } - } - - if (State.RoyaltyFeeReceiverMap[input.Symbol] != null) - { - royaltyInfo.RoyaltyFeeReceiver = State.RoyaltyFeeReceiverMap[input.Symbol]; - } - - return royaltyInfo; + var certainNftRoyalty = State.CertainNFTRoyaltyMap[input.Symbol][input.TokenId] ?? + new CertainNFTRoyaltyInfo(); + if (certainNftRoyalty.IsManuallySet) royaltyInfo.Royalty = certainNftRoyalty.Royalty; } - public override ServiceFeeInfo GetServiceFeeInfo(Empty input) + if (State.RoyaltyFeeReceiverMap[input.Symbol] != null) + royaltyInfo.RoyaltyFeeReceiver = State.RoyaltyFeeReceiverMap[input.Symbol]; + + return royaltyInfo; + } + + public override ServiceFeeInfo GetServiceFeeInfo(Empty input) + { + return new ServiceFeeInfo { - return new ServiceFeeInfo - { - ServiceFeeRate = State.ServiceFeeRate.Value, - ServiceFeeReceiver = State.ServiceFeeReceiver.Value - }; - } + ServiceFeeRate = State.ServiceFeeRate.Value, + ServiceFeeReceiver = State.ServiceFeeReceiver.Value + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/AElf.Contracts.NFTMinter.csproj b/contract/AElf.Contracts.NFTMinter/AElf.Contracts.NFTMinter.csproj index c77773a66a..7be100ce75 100644 --- a/contract/AElf.Contracts.NFTMinter/AElf.Contracts.NFTMinter.csproj +++ b/contract/AElf.Contracts.NFTMinter/AElf.Contracts.NFTMinter.csproj @@ -1,5 +1,5 @@ - + net6.0 diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterConrtract_Creator.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterConrtract_Creator.cs index 36a5a73bb5..f477047a9f 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterConrtract_Creator.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterConrtract_Creator.cs @@ -5,205 +5,190 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract { - public partial class NFTMinterContract + public override Empty CreateBadge(CreateBadgeInput input) { - public override Empty CreateBadge(CreateBadgeInput input) - { - CheckSymbolAndPermission(input.Symbol); - var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; - if (badgeInfo != null) - { - throw new AssertionException("Badge already created."); - } - - badgeInfo = new BadgeInfo - { - BadgeName = input.Alias, - BadgeCreator = Context.Sender - }; - State.BadgeInfoMap[input.Symbol][input.TokenId] = badgeInfo; - - var nftProtocol = ValidNFTProtocol(input.Symbol); - var metadata = input.Metadata == null ? new Metadata() : new Metadata {Value = {input.Metadata.Value}}; - metadata.Value[BadgeNameMetadataKey] = input.Alias; - State.NFTContract.Mint.Send(new MintInput - { - Symbol = input.Symbol, - Alias = input.Alias, - Metadata = metadata, - Owner = input.Owner ?? nftProtocol.Creator, - Quantity = 1, - TokenId = input.TokenId, - Uri = input.Uri - }); - return new Empty(); - } + CheckSymbolAndPermission(input.Symbol); + var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; + if (badgeInfo != null) throw new AssertionException("Badge already created."); - public override Empty ConfigBadge(ConfigBadgeInput input) + badgeInfo = new BadgeInfo { - CheckSymbolAndPermission(input.Symbol); - var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; - if (badgeInfo == null) - { - throw new AssertionException("Badge not created."); - } - - if (badgeInfo.StartTime != null) - { - // Cannot change badge info if minting period already started. - Assert(badgeInfo.StartTime < Context.CurrentBlockTime, "Badge minting period already started."); - } + BadgeName = input.Alias, + BadgeCreator = Context.Sender + }; + State.BadgeInfoMap[input.Symbol][input.TokenId] = badgeInfo; + + var nftProtocol = ValidNFTProtocol(input.Symbol); + var metadata = input.Metadata == null ? new Metadata() : new Metadata { Value = { input.Metadata.Value } }; + metadata.Value[BadgeNameMetadataKey] = input.Alias; + State.NFTContract.Mint.Send(new MintInput + { + Symbol = input.Symbol, + Alias = input.Alias, + Metadata = metadata, + Owner = input.Owner ?? nftProtocol.Creator, + Quantity = 1, + TokenId = input.TokenId, + Uri = input.Uri + }); + return new Empty(); + } - Assert(input.Limit > 0, "Invalid limit."); - var startTime = badgeInfo.StartTime == null - ? input.StartTime ?? Context.CurrentBlockTime - : badgeInfo.StartTime; - var endTime = badgeInfo.StartTime == null - ? input.EndTime ?? Context.CurrentBlockTime.AddDays(100000) - : badgeInfo.EndTime; + public override Empty ConfigBadge(ConfigBadgeInput input) + { + CheckSymbolAndPermission(input.Symbol); + var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; + if (badgeInfo == null) throw new AssertionException("Badge not created."); + + if (badgeInfo.StartTime != null) + // Cannot change badge info if minting period already started. + Assert(badgeInfo.StartTime < Context.CurrentBlockTime, "Badge minting period already started."); + + Assert(input.Limit > 0, "Invalid limit."); + var startTime = badgeInfo.StartTime == null + ? input.StartTime ?? Context.CurrentBlockTime + : badgeInfo.StartTime; + var endTime = badgeInfo.StartTime == null + ? input.EndTime ?? Context.CurrentBlockTime.AddDays(100000) + : badgeInfo.EndTime; + + State.BadgeInfoMap[input.Symbol][input.TokenId] = new BadgeInfo + { + Symbol = input.Symbol, + TokenId = input.TokenId, + StartTime = startTime, + EndTime = endTime, + IsPublic = input.IsPublic + }; - State.BadgeInfoMap[input.Symbol][input.TokenId] = new BadgeInfo - { - Symbol = input.Symbol, - TokenId = input.TokenId, - StartTime = startTime, - EndTime = endTime, - IsPublic = input.IsPublic - }; + State.MintLimitMap[input.Symbol][input.TokenId] = input.Limit; - State.MintLimitMap[input.Symbol][input.TokenId] = input.Limit; + Context.Fire(new BadgeInfoChanged + { + Symbol = input.Symbol, + TokenId = input.TokenId, + StartTime = input.StartTime, + EndTime = input.EndTime, + IsPublic = input.IsPublic, + Limit = input.Limit + }); + return new Empty(); + } - Context.Fire(new BadgeInfoChanged - { - Symbol = input.Symbol, - TokenId = input.TokenId, - StartTime = input.StartTime, - EndTime = input.EndTime, - IsPublic = input.IsPublic, - Limit = input.Limit - }); - return new Empty(); - } + public override Empty ManageMintingWhiteList(ManageMintingWhiteListInput input) + { + CheckSymbolAndPermission(input.Symbol); + var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; + Assert(!badgeInfo.IsPublic, "This badge is not whitelist only."); + foreach (var address in input.AddressList.Value) + if (input.IsRemove) + State.IsInWhiteListMap[input.Symbol][input.TokenId].Remove(address); + else + State.IsInWhiteListMap[input.Symbol][input.TokenId][address] = true; - public override Empty ManageMintingWhiteList(ManageMintingWhiteListInput input) + Context.Fire(new MintingWhiteListChanged { - CheckSymbolAndPermission(input.Symbol); - var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; - Assert(!badgeInfo.IsPublic, "This badge is not whitelist only."); - foreach (var address in input.AddressList.Value) - { - if (input.IsRemove) - { - State.IsInWhiteListMap[input.Symbol][input.TokenId].Remove(address); - } - else - { - State.IsInWhiteListMap[input.Symbol][input.TokenId][address] = true; - } - } + Symbol = input.Symbol, + TokenId = input.TokenId, + IsRemove = input.IsRemove, + AddressList = input.AddressList + }); - Context.Fire(new MintingWhiteListChanged - { - Symbol = input.Symbol, - TokenId = input.TokenId, - IsRemove = input.IsRemove, - AddressList = input.AddressList - }); - - return new Empty(); - } + return new Empty(); + } - public override Empty Box(BoxInput input) + public override Empty Box(BoxInput input) + { + CheckSymbolAndPermission(input.Symbol); + Assert(State.BlindBoxInfoMap[input.Symbol][input.Index] == null, $"Index {input.Index} already existed."); + var templateList = new NFTTemplateList { - CheckSymbolAndPermission(input.Symbol); - Assert(State.BlindBoxInfoMap[input.Symbol][input.Index] == null, $"Index {input.Index} already existed."); - var templateList = new NFTTemplateList - { - Value = {input.TemplateList.Value.OrderBy(t => t.TokenId)} - }; - Assert(templateList.Value.All(t => t.Quantity > 0), "Incorrect quantity."); - Assert(templateList.Value.All(t => t.Weight > 0), "Incorrect weight."); - CheckTemplateTokenIds(templateList, input.IsTokenIdFixed, out var startTokenId, out var endTokenId); - var blindBoxInfo = new BlindBoxInfo - { - Symbol = input.Symbol, - TemplateList = templateList, - IsTokenIdFixed = input.IsTokenIdFixed, - CostSymbol = input.CostSymbol, - CostTokenId = input.CostTokenId, - CostAmount = input.CostAmount, - CostReceiver = input.CostReceiver, - StartTokenId = startTokenId, - SupposedEndTokenId = endTokenId, - TotalWeights = templateList.Value.Sum(t => t.Weight) - }; - State.BlindBoxInfoMap[input.Symbol][input.Index] = blindBoxInfo; - var vector = ConstructWeightVector(templateList); - Assert(blindBoxInfo.TotalWeights == vector.Value.Last(), "Something wrong with weight."); - State.BlindBoxWeightVectorMap[input.Symbol][input.Index] = vector; - Context.Fire(new BlindBoxForged - { - Symbol = blindBoxInfo.Symbol, - TemplateList = templateList, - IsTokenIdFixed = blindBoxInfo.IsTokenIdFixed, - CostSymbol = blindBoxInfo.CostSymbol, - CostTokenId = blindBoxInfo.CostTokenId, - CostAmount = blindBoxInfo.CostAmount, - CostReceiver = blindBoxInfo.CostReceiver, - StartTokenId = startTokenId, - SupposedEndTokenId = endTokenId, - }); - return new Empty(); - } + Value = { input.TemplateList.Value.OrderBy(t => t.TokenId) } + }; + Assert(templateList.Value.All(t => t.Quantity > 0), "Incorrect quantity."); + Assert(templateList.Value.All(t => t.Weight > 0), "Incorrect weight."); + CheckTemplateTokenIds(templateList, input.IsTokenIdFixed, out var startTokenId, out var endTokenId); + var blindBoxInfo = new BlindBoxInfo + { + Symbol = input.Symbol, + TemplateList = templateList, + IsTokenIdFixed = input.IsTokenIdFixed, + CostSymbol = input.CostSymbol, + CostTokenId = input.CostTokenId, + CostAmount = input.CostAmount, + CostReceiver = input.CostReceiver, + StartTokenId = startTokenId, + SupposedEndTokenId = endTokenId, + TotalWeights = templateList.Value.Sum(t => t.Weight) + }; + State.BlindBoxInfoMap[input.Symbol][input.Index] = blindBoxInfo; + var vector = ConstructWeightVector(templateList); + Assert(blindBoxInfo.TotalWeights == vector.Value.Last(), "Something wrong with weight."); + State.BlindBoxWeightVectorMap[input.Symbol][input.Index] = vector; + Context.Fire(new BlindBoxForged + { + Symbol = blindBoxInfo.Symbol, + TemplateList = templateList, + IsTokenIdFixed = blindBoxInfo.IsTokenIdFixed, + CostSymbol = blindBoxInfo.CostSymbol, + CostTokenId = blindBoxInfo.CostTokenId, + CostAmount = blindBoxInfo.CostAmount, + CostReceiver = blindBoxInfo.CostReceiver, + StartTokenId = startTokenId, + SupposedEndTokenId = endTokenId + }); + return new Empty(); + } - private void CheckTemplateTokenIds(NFTTemplateList templateList, bool isTokenIdFixed, out long startTokenId, - out long endTokenId) + private void CheckTemplateTokenIds(NFTTemplateList templateList, bool isTokenIdFixed, out long startTokenId, + out long endTokenId) + { + if (isTokenIdFixed) { - if (isTokenIdFixed) - { - startTokenId = templateList.Value.First().TokenId; - endTokenId = startTokenId.Add(1); - var checkTokenId = startTokenId; - foreach (var template in templateList.Value.Skip(1)) - { - Assert(template.TokenId >= checkTokenId, - $"{template.Alias} cannot start from token id {checkTokenId}"); - checkTokenId = template.TokenId; - endTokenId = checkTokenId; - } - } - else - { - var firstTemplate = templateList.Value.First(); - startTokenId = firstTemplate.TokenId; - var checkTokenId = startTokenId.Add(firstTemplate.Quantity).Sub(1); + startTokenId = templateList.Value.First().TokenId; + endTokenId = startTokenId.Add(1); + var checkTokenId = startTokenId; + foreach (var template in templateList.Value.Skip(1)) + { + Assert(template.TokenId >= checkTokenId, + $"{template.Alias} cannot start from token id {checkTokenId}"); + checkTokenId = template.TokenId; endTokenId = checkTokenId; - foreach (var template in templateList.Value.Skip(1)) - { - Assert(template.TokenId > checkTokenId, - $"{template.Alias} cannot start from token id {checkTokenId}"); - checkTokenId = template.TokenId.Add(template.Quantity).Sub(1); - endTokenId = checkTokenId; - } } } - - private Int64List ConstructWeightVector(NFTTemplateList templateList) + else { - var weightList = templateList.Value.OrderBy(t => t.Weight).Select(t => t.Weight).ToList(); - var vector = new Int64List - { - Value = {weightList.First()} - }; - foreach (var weight in weightList.Skip(1)) - { - var lastValue = vector.Value.Last(); - vector.Value.Add(lastValue.Add(weight)); + var firstTemplate = templateList.Value.First(); + startTokenId = firstTemplate.TokenId; + var checkTokenId = startTokenId.Add(firstTemplate.Quantity).Sub(1); + endTokenId = checkTokenId; + foreach (var template in templateList.Value.Skip(1)) + { + Assert(template.TokenId > checkTokenId, + $"{template.Alias} cannot start from token id {checkTokenId}"); + checkTokenId = template.TokenId.Add(template.Quantity).Sub(1); + endTokenId = checkTokenId; } + } + } - return vector; + private Int64List ConstructWeightVector(NFTTemplateList templateList) + { + var weightList = templateList.Value.OrderBy(t => t.Weight).Select(t => t.Weight).ToList(); + var vector = new Int64List + { + Value = { weightList.First() } + }; + foreach (var weight in weightList.Skip(1)) + { + var lastValue = vector.Value.Last(); + vector.Value.Add(lastValue.Add(weight)); } + + return vector; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContract.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContract.cs index b87b091e8f..2d7de9ae7a 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContract.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContract.cs @@ -1,20 +1,19 @@ using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract : NFTMinterContractContainer.NFTMinterContractBase { - public partial class NFTMinterContract : NFTMinterContractContainer.NFTMinterContractBase + public override Empty Initialize(InitializeInput input) { - public override Empty Initialize(InitializeInput input) - { - State.NFTContract.Value = input.NftContractAddress; - State.AdminAddress.Value = input.AdminAddress ?? Context.Sender; - State.RandomNumberProviderContract.Value = input.RandomNumberProviderContractAddress ?? - Context.GetContractAddressByName(SmartContractConstants - .ConsensusContractSystemName); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - return new Empty(); - } + State.NFTContract.Value = input.NftContractAddress; + State.AdminAddress.Value = input.AdminAddress ?? Context.Sender; + State.RandomNumberProviderContract.Value = input.RandomNumberProviderContractAddress ?? + Context.GetContractAddressByName(SmartContractConstants + .ConsensusContractSystemName); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + return new Empty(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContractConstants.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContractConstants.cs index bf9ab9aaa6..6312a2b596 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContractConstants.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContractConstants.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract { - public partial class NFTMinterContract - { - private const string BadgeNameMetadataKey = "badge_name"; - private const int MaxMintKeys = 100000; - } + private const string BadgeNameMetadataKey = "badge_name"; + private const int MaxMintKeys = 100000; } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContractReferenceState.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContractReferenceState.cs index c8e340c404..80864ab6e8 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContractReferenceState.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContractReferenceState.cs @@ -2,14 +2,13 @@ using AElf.Contracts.NFT; using AElf.Standards.ACS6; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContractState { - public partial class NFTMinterContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal NFTContractContainer.NFTContractReferenceState NFTContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal NFTContractContainer.NFTContractReferenceState NFTContract { get; set; } - internal RandomNumberProviderContractContainer.RandomNumberProviderContractReferenceState - RandomNumberProviderContract { get; set; } - } + internal RandomNumberProviderContractContainer.RandomNumberProviderContractReferenceState + RandomNumberProviderContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContractState.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContractState.cs index f1de7d3eb0..d707015809 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContractState.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContractState.cs @@ -1,33 +1,32 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContractState : ContractState { - public partial class NFTMinterContractState : ContractState - { - public SingletonState
AdminAddress { get; set; } + public SingletonState
AdminAddress { get; set; } - /// - /// Symbol -> Token Id -> BadgeInfo - /// - public MappedState BadgeInfoMap { get; set; } + /// + /// Symbol -> Token Id -> BadgeInfo + /// + public MappedState BadgeInfoMap { get; set; } - /// - /// Symbol -> Token Id -> Limit - /// - public MappedState MintLimitMap { get; set; } + /// + /// Symbol -> Token Id -> Limit + /// + public MappedState MintLimitMap { get; set; } - /// - /// Symbol -> Token Id -> Minted Count - /// - public MappedState MintedMap { get; set; } + /// + /// Symbol -> Token Id -> Minted Count + /// + public MappedState MintedMap { get; set; } - /// - /// Symbol -> Token Id -> Address -> Is in white list - /// - public MappedState IsInWhiteListMap { get; set; } + /// + /// Symbol -> Token Id -> Address -> Is in white list + /// + public MappedState IsInWhiteListMap { get; set; } - public MappedState BlindBoxInfoMap { get; set; } - public MappedState BlindBoxWeightVectorMap { get; set; } - } + public MappedState BlindBoxInfoMap { get; set; } + public MappedState BlindBoxWeightVectorMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Helpers.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Helpers.cs index aeb345c5b5..d27d298dbb 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Helpers.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Helpers.cs @@ -3,33 +3,29 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract { - public partial class NFTMinterContract + private Address GetNFTProtocolCreator(string symbol) { - private Address GetNFTProtocolCreator(string symbol) - { - return State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = symbol}).Creator; - } + return State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = symbol }).Creator; + } - private void CheckSymbolAndPermission(string symbol) - { - Assert(!string.IsNullOrEmpty(symbol.Trim()), "Symbol is empty."); - var creator = GetNFTProtocolCreator(symbol); - if (creator == null) - { - throw new AssertionException("NFT Protocol not exists."); - } - Assert(creator == Context.Sender, "No permission."); - } + private void CheckSymbolAndPermission(string symbol) + { + Assert(!string.IsNullOrEmpty(symbol.Trim()), "Symbol is empty."); + var creator = GetNFTProtocolCreator(symbol); + if (creator == null) throw new AssertionException("NFT Protocol not exists."); + Assert(creator == Context.Sender, "No permission."); + } - private NFTProtocolInfo ValidNFTProtocol(string symbol) - { - var nftProtocol = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue {Value = symbol}); - Assert(nftProtocol.NftType == NFTType.Badges.ToString(), "Invalid NFT Protocol."); - var minterList = State.NFTContract.GetMinterList.Call(new StringValue {Value = symbol}); - Assert(minterList.Value.Contains(Context.Self), $"NFT Minter Contract is not in minter list of {symbol}"); - return nftProtocol; - } + private NFTProtocolInfo ValidNFTProtocol(string symbol) + { + var nftProtocol = State.NFTContract.GetNFTProtocolInfo.Call(new StringValue { Value = symbol }); + Assert(nftProtocol.NftType == NFTType.Badges.ToString(), "Invalid NFT Protocol."); + var minterList = State.NFTContract.GetMinterList.Call(new StringValue { Value = symbol }); + Assert(minterList.Value.Contains(Context.Self), $"NFT Minter Contract is not in minter list of {symbol}"); + return nftProtocol; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_User.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_User.cs index 06a7bad7a9..e8aa908318 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_User.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_User.cs @@ -2,149 +2,139 @@ using AElf.CSharp.Core; using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; +using TransferFromInput = AElf.Contracts.MultiToken.TransferFromInput; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract { - public partial class NFTMinterContract + public override Empty MintBadge(MintBadgeInput input) { - public override Empty MintBadge(MintBadgeInput input) - { - var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; - if (badgeInfo?.BadgeName == null) - { - throw new AssertionException("Badge info not exists."); - } + var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; + if (badgeInfo?.BadgeName == null) throw new AssertionException("Badge info not exists."); - var limit = State.MintLimitMap[input.Symbol][input.TokenId]; - Assert(limit > 0, "Minting of this badge not started."); + var limit = State.MintLimitMap[input.Symbol][input.TokenId]; + Assert(limit > 0, "Minting of this badge not started."); - // Check the limit. - var minted = State.MintedMap[input.Symbol][input.TokenId]; - Assert(minted < limit, $"Reached the minting limit {limit}"); + // Check the limit. + var minted = State.MintedMap[input.Symbol][input.TokenId]; + Assert(minted < limit, $"Reached the minting limit {limit}"); - var owner = input.Owner ?? Context.Sender; - // Check whether owner in whitelist. - if (!badgeInfo.IsPublic) - { - Assert(State.IsInWhiteListMap[input.Symbol][input.TokenId][owner], - $"{owner} is not in the white list."); - } + var owner = input.Owner ?? Context.Sender; + // Check whether owner in whitelist. + if (!badgeInfo.IsPublic) + Assert(State.IsInWhiteListMap[input.Symbol][input.TokenId][owner], + $"{owner} is not in the white list."); - State.NFTContract.Mint.Send(new MintInput - { - Symbol = input.Symbol, - Owner = owner, - Quantity = 1, - TokenId = input.TokenId - }); + State.NFTContract.Mint.Send(new MintInput + { + Symbol = input.Symbol, + Owner = owner, + Quantity = 1, + TokenId = input.TokenId + }); + + State.MintedMap[input.Symbol][input.TokenId] = minted.Add(1); + return new Empty(); + } - State.MintedMap[input.Symbol][input.TokenId] = minted.Add(1); - return new Empty(); - } + public override Empty Unbox(UnboxInput input) + { + var blindBoxInfo = State.BlindBoxInfoMap[input.Symbol][input.Index]; + if (blindBoxInfo == null) throw new AssertionException($"Index {input.Index} not existed."); + + PayForBlindBox(blindBoxInfo); + + var weightVector = State.BlindBoxWeightVectorMap[input.Symbol][input.Index]; + var totalWeights = blindBoxInfo.TotalWeights; + + var randomBytes = State.RandomNumberProviderContract.GetRandomBytes.Call(new Int64Value + { + Value = Context.CurrentHeight.Sub(1) + }.ToBytesValue()); + var randomHash = + HashHelper.ConcatAndCompute(Context.PreviousBlockHash, HashHelper.ComputeFrom(randomBytes)); - public override Empty Unbox(UnboxInput input) + NFTTemplate useTemplate; + do { - var blindBoxInfo = State.BlindBoxInfoMap[input.Symbol][input.Index]; - if (blindBoxInfo == null) + var randomNumber = Context.ConvertHashToInt64(randomHash, 0, totalWeights); + var blindBoxIndex = 0; + for (var i = 0; i < weightVector.Value.Count; i++) { - throw new AssertionException($"Index {input.Index} not existed."); + blindBoxIndex = i; + if (randomNumber > weightVector.Value[i]) break; } - PayForBlindBox(blindBoxInfo); + useTemplate = blindBoxInfo.TemplateList.Value[blindBoxIndex]; + randomHash = HashHelper.ComputeFrom(randomHash); + } while (useTemplate.MintedQuantity > useTemplate.Quantity); - var weightVector = State.BlindBoxWeightVectorMap[input.Symbol][input.Index]; - var totalWeights = blindBoxInfo.TotalWeights; + State.NFTContract.Mint.Send(new MintInput + { + Symbol = useTemplate.Symbol, + TokenId = useTemplate.TokenId, + Alias = useTemplate.Alias, + Owner = Context.Sender, + Metadata = new Metadata { Value = { useTemplate.Metadata.Value } }, + Quantity = 1, + Uri = useTemplate.Uri + }); - var randomBytes = State.RandomNumberProviderContract.GetRandomBytes.Call(new Int64Value - { - Value = Context.CurrentHeight.Sub(1) - }.ToBytesValue()); - var randomHash = - HashHelper.ConcatAndCompute(Context.PreviousBlockHash, HashHelper.ComputeFrom(randomBytes)); + if (!blindBoxInfo.IsTokenIdFixed) useTemplate.TokenId = useTemplate.TokenId.Add(1); - NFTTemplate useTemplate; - do - { - var randomNumber = Context.ConvertHashToInt64(randomHash, 0, totalWeights); - var blindBoxIndex = 0; - for (var i = 0; i < weightVector.Value.Count; i++) - { - blindBoxIndex = i; - if (randomNumber > weightVector.Value[i]) break; - } - useTemplate = blindBoxInfo.TemplateList.Value[blindBoxIndex]; - randomHash = HashHelper.ComputeFrom(randomHash); - } while (useTemplate.MintedQuantity > useTemplate.Quantity); - - State.NFTContract.Mint.Send(new MintInput - { - Symbol = useTemplate.Symbol, - TokenId = useTemplate.TokenId, - Alias = useTemplate.Alias, - Owner = Context.Sender, - Metadata = new Metadata {Value = {useTemplate.Metadata.Value}}, - Quantity = 1, - Uri = useTemplate.Uri - }); + useTemplate.MintedQuantity = useTemplate.MintedQuantity.Add(1); - if (!blindBoxInfo.IsTokenIdFixed) - { - useTemplate.TokenId = useTemplate.TokenId.Add(1); - } + State.BlindBoxInfoMap[input.Symbol][input.Index] = blindBoxInfo; - useTemplate.MintedQuantity = useTemplate.MintedQuantity.Add(1); - - State.BlindBoxInfoMap[input.Symbol][input.Index] = blindBoxInfo; + return new Empty(); + } - return new Empty(); + private void PayForBlindBox(BlindBoxInfo blindBoxInfo) + { + var costReceiver = blindBoxInfo.CostReceiver; + if (blindBoxInfo.CostTokenId == 0) + { + // User fungible tokens. + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + To = costReceiver ?? GetNFTProtocolCreator(blindBoxInfo.Symbol), + Symbol = blindBoxInfo.CostSymbol, + Amount = blindBoxInfo.CostAmount + }); } - - private void PayForBlindBox(BlindBoxInfo blindBoxInfo) + else { - var costReceiver = blindBoxInfo.CostReceiver; - if (blindBoxInfo.CostTokenId == 0) + if (costReceiver == null) { - // User fungible tokens. - State.TokenContract.TransferFrom.Send(new MultiToken.TransferFromInput + // Burn cost nft. + + State.NFTContract.TransferFrom.Send(new NFT.TransferFromInput { From = Context.Sender, - To = costReceiver ?? GetNFTProtocolCreator(blindBoxInfo.Symbol), + TokenId = blindBoxInfo.CostTokenId, + To = Context.Self, + Symbol = blindBoxInfo.CostSymbol, + Amount = blindBoxInfo.CostAmount + }); + State.NFTContract.Burn.Send(new BurnInput + { Symbol = blindBoxInfo.CostSymbol, + TokenId = blindBoxInfo.CostTokenId, Amount = blindBoxInfo.CostAmount }); } else { - if (costReceiver == null) + State.NFTContract.TransferFrom.Send(new NFT.TransferFromInput { - // Burn cost nft. - - State.NFTContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - TokenId = blindBoxInfo.CostTokenId, - To = Context.Self, - Symbol = blindBoxInfo.CostSymbol, - Amount = blindBoxInfo.CostAmount - }); - State.NFTContract.Burn.Send(new BurnInput - { - Symbol = blindBoxInfo.CostSymbol, - TokenId = blindBoxInfo.CostTokenId, - Amount = blindBoxInfo.CostAmount - }); - } - else - { - State.NFTContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - TokenId = blindBoxInfo.CostTokenId, - To = blindBoxInfo.CostReceiver, - Symbol = blindBoxInfo.CostSymbol, - Amount = blindBoxInfo.CostAmount - }); - } + From = Context.Sender, + TokenId = blindBoxInfo.CostTokenId, + To = blindBoxInfo.CostReceiver, + Symbol = blindBoxInfo.CostSymbol, + Amount = blindBoxInfo.CostAmount + }); } } } diff --git a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Views.cs b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Views.cs index 8bc2f38ed5..41be0afa73 100644 --- a/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Views.cs +++ b/contract/AElf.Contracts.NFTMinter/NFTMinterContract_Views.cs @@ -1,24 +1,23 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.NFTMinter +namespace AElf.Contracts.NFTMinter; + +public partial class NFTMinterContract { - public partial class NFTMinterContract + public override BadgeInfo GetBadgeInfo(GetBadgeInfoInput input) { - public override BadgeInfo GetBadgeInfo(GetBadgeInfoInput input) - { - var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; - badgeInfo.Limit = State.MintLimitMap[input.Symbol][input.TokenId]; - return badgeInfo; - } + var badgeInfo = State.BadgeInfoMap[input.Symbol][input.TokenId]; + badgeInfo.Limit = State.MintLimitMap[input.Symbol][input.TokenId]; + return badgeInfo; + } - public override BoolValue IsInMintingWhiteList(IsInMintingWhiteListInput input) - { - return new BoolValue {Value = State.IsInWhiteListMap[input.Symbol][input.TokenId][input.Address]}; - } + public override BoolValue IsInMintingWhiteList(IsInMintingWhiteListInput input) + { + return new BoolValue { Value = State.IsInWhiteListMap[input.Symbol][input.TokenId][input.Address] }; + } - public override BlindBoxInfo GetBlindBoxInfo(GetBlindBoxInfoInput input) - { - return State.BlindBoxInfoMap[input.Symbol][input.Index]; - } + public override BlindBoxInfo GetBlindBoxInfo(GetBlindBoxInfoInput input) + { + return State.BlindBoxInfoMap[input.Symbol][input.Index]; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Parliament/AElf.Contracts.Parliament.csproj b/contract/AElf.Contracts.Parliament/AElf.Contracts.Parliament.csproj index 96ef994689..aa4fe7db45 100644 --- a/contract/AElf.Contracts.Parliament/AElf.Contracts.Parliament.csproj +++ b/contract/AElf.Contracts.Parliament/AElf.Contracts.Parliament.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Parliament true - Parliament is a contract that enables the creation of organizations and approvals. The created - proposals can be voted for and eventually released. + Parliament is a contract that enables the creation of organizations and approvals. The created + proposals can be voted for and eventually released. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\aedpos_contract.proto diff --git a/contract/AElf.Contracts.Parliament/Parliament.cs b/contract/AElf.Contracts.Parliament/Parliament.cs index f153a44f97..6858048406 100644 --- a/contract/AElf.Contracts.Parliament/Parliament.cs +++ b/contract/AElf.Contracts.Parliament/Parliament.cs @@ -1,324 +1,317 @@ using System.Linq; -using AElf.Standards.ACS3; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; -using CreateProposalInput = AElf.Standards.ACS3.CreateProposalInput; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public partial class ParliamentContract : ParliamentContractImplContainer.ParliamentContractImplBase { - public partial class ParliamentContract : ParliamentContractImplContainer.ParliamentContractImplBase + public override Empty Initialize(InitializeInput input) { - #region View + Assert(!State.Initialized.Value, "Already initialized."); + State.Initialized.Value = true; - public override Organization GetOrganization(Address address) - { - var organization = State.Organizations[address]; - return organization ?? new Organization(); - } + var proposerWhiteList = new ProposerWhiteList(); + + if (input.PrivilegedProposer != null) + proposerWhiteList.Proposers.Add(input.PrivilegedProposer); - public override ProposalOutput GetProposal(Hash proposalId) + State.ProposerWhiteList.Value = proposerWhiteList; + var organizationInput = new CreateOrganizationInput { - var proposal = State.Proposals[proposalId]; - if (proposal == null) + ProposalReleaseThreshold = new ProposalReleaseThreshold { - return new ProposalOutput(); - } + MinimalApprovalThreshold = DefaultOrganizationMinimalApprovalThreshold, + MinimalVoteThreshold = DefaultOrganizationMinimalVoteThresholdThreshold, + MaximalAbstentionThreshold = DefaultOrganizationMaximalAbstentionThreshold, + MaximalRejectionThreshold = DefaultOrganizationMaximalRejectionThreshold + }, + ProposerAuthorityRequired = input.ProposerAuthorityRequired, + ParliamentMemberProposingAllowed = true + }; + var defaultOrganizationAddress = CreateNewOrganization(organizationInput); + State.DefaultOrganizationAddress.Value = defaultOrganizationAddress; + return new Empty(); + } - var organization = State.Organizations[proposal.OrganizationAddress]; + public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Unauthorized to create organization."); + var organizationAddress = CreateNewOrganization(input.OrganizationCreationInput); + if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) + Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - return new ProposalOutput - { - ProposalId = proposalId, - ContractMethodName = proposal.ContractMethodName, - ExpiredTime = proposal.ExpiredTime, - OrganizationAddress = proposal.OrganizationAddress, - Params = proposal.Params, - Proposer = proposal.Proposer, - ToAddress = proposal.ToAddress, - ToBeReleased = Validate(proposal) && IsReleaseThresholdReached(proposal, organization), - ApprovalCount = proposal.Approvals.Count, - RejectionCount = proposal.Rejections.Count, - AbstentionCount = proposal.Abstentions.Count - }; - } + return organizationAddress; + } - public override Address GetDefaultOrganizationAddress(Empty input) - { - Assert(State.Initialized.Value, "Not initialized."); - return State.DefaultOrganizationAddress.Value; - } + public override Address CreateOrganization(CreateOrganizationInput input) + { + Assert( + ValidateAddressInWhiteList(Context.Sender) || ValidateParliamentMemberAuthority(Context.Sender) || + State.DefaultOrganizationAddress.Value == Context.Sender, + "Unauthorized to create organization."); + var organizationAddress = CreateNewOrganization(input); - public override Address CalculateOrganizationAddress(CreateOrganizationInput input) - { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - return organizationAddress; - } + return organizationAddress; + } - public override BoolValue ValidateAddressIsParliamentMember(Address address) - { - return new BoolValue { Value = ValidateParliamentMemberAuthority(address) }; - } + public override Hash CreateProposal(CreateProposalInput input) + { + AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); + var proposalId = CreateNewProposal(input); + return proposalId; + } - public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) - { - return new BoolValue { Value = ValidateAddressInWhiteList(input.Proposer) }; - } + public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Unauthorized to propose."); + AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); - public override ProposerWhiteList GetProposerWhiteList(Empty input) - { - var res = new ProposerWhiteList(); - var whitelist = State.ProposerWhiteList.Value; - res.Proposers.AddRange(whitelist.Proposers); - return res; - } + var proposalId = CreateNewProposal(input.ProposalInput); + return proposalId; + } - public override BoolValue ValidateOrganizationExist(Address input) + public override Empty Approve(Hash input) + { + var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); + proposal.Approvals.Add(parliamentMemberAddress); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - return new BoolValue { Value = State.Organizations[input] != null }; - } + Address = parliamentMemberAddress, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Approve), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - public override ProposalIdList GetNotVotedProposals(ProposalIdList input) + public override Empty Reject(Hash input) + { + var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); + proposal.Rejections.Add(parliamentMemberAddress); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - var result = new ProposalIdList(); - foreach (var proposalId in input.ProposalIds) - { - var proposal = State.Proposals[proposalId]; - if (proposal == null || !Validate(proposal) || CheckProposalAlreadyVotedBy(proposal, Context.Sender)) - continue; - result.ProposalIds.Add(proposalId); - } - - return result; - } + Address = parliamentMemberAddress, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Reject), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - public override ProposalIdList GetNotVotedPendingProposals(ProposalIdList input) + public override Empty Abstain(Hash input) + { + var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); + var proposal = GetValidProposal(input); + AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); + proposal.Abstentions.Add(parliamentMemberAddress); + State.Proposals[input] = proposal; + Context.Fire(new ReceiptCreated { - var result = new ProposalIdList(); - var currentParliament = GetCurrentMinerList(); - foreach (var proposalId in input.ProposalIds) - { - var proposal = State.Proposals[proposalId]; - if (proposal == null || !Validate(proposal) || CheckProposalAlreadyVotedBy(proposal, Context.Sender)) - continue; - var organization = State.Organizations[proposal.OrganizationAddress]; - if (organization == null || !IsProposalStillPending(proposal, organization, currentParliament)) - continue; - result.ProposalIds.Add(proposalId); - } - - return result; - } + Address = parliamentMemberAddress, + ProposalId = input, + Time = Context.CurrentBlockTime, + ReceiptType = nameof(Abstain), + OrganizationAddress = proposal.OrganizationAddress + }); + return new Empty(); + } - #endregion view + public override Empty Release(Hash proposalId) + { + var proposalInfo = GetValidProposal(proposalId); + Assert(Context.Sender.Equals(proposalInfo.Proposer), "No permission."); + var organization = State.Organizations[proposalInfo.OrganizationAddress]; + Assert(IsReleaseThresholdReached(proposalInfo, organization), "Not approved."); + Context.SendVirtualInlineBySystemContract( + CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposalInfo.ToAddress, + proposalInfo.ContractMethodName, proposalInfo.Params); + Context.Fire(new ProposalReleased { ProposalId = proposalId }); + State.Proposals.Remove(proposalId); + + return new Empty(); + } - public override Empty Initialize(InitializeInput input) + public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.ProposalReleaseThreshold = input; + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new OrganizationThresholdChanged { - Assert(!State.Initialized.Value, "Already initialized."); - State.Initialized.Value = true; + OrganizationAddress = Context.Sender, + ProposerReleaseThreshold = input + }); + return new Empty(); + } - var proposerWhiteList = new ProposerWhiteList(); + public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) + { + var defaultOrganizationAddress = State.DefaultOrganizationAddress.Value; + Assert(defaultOrganizationAddress == Context.Sender, "No permission."); + var organization = State.Organizations[defaultOrganizationAddress]; + Assert( + input.Proposers.Count > 0 || !organization.ProposerAuthorityRequired || + organization.ParliamentMemberProposingAllowed, "White list can't be empty."); + State.ProposerWhiteList.Value = input; + Context.Fire(new OrganizationWhiteListChanged + { + OrganizationAddress = Context.Sender, + ProposerWhiteList = input + }); + return new Empty(); + } - if (input.PrivilegedProposer != null) - proposerWhiteList.Proposers.Add(input.PrivilegedProposer); + public override Empty ClearProposal(Hash input) + { + // anyone can clear proposal if it is expired + var proposal = State.Proposals[input]; + Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); + State.Proposals.Remove(input); + return new Empty(); + } - State.ProposerWhiteList.Value = proposerWhiteList; - var organizationInput = new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = DefaultOrganizationMinimalApprovalThreshold, - MinimalVoteThreshold = DefaultOrganizationMinimalVoteThresholdThreshold, - MaximalAbstentionThreshold = DefaultOrganizationMaximalAbstentionThreshold, - MaximalRejectionThreshold = DefaultOrganizationMaximalRejectionThreshold - }, - ProposerAuthorityRequired = input.ProposerAuthorityRequired, - ParliamentMemberProposingAllowed = true - }; - var defaultOrganizationAddress = CreateNewOrganization(organizationInput); - State.DefaultOrganizationAddress.Value = defaultOrganizationAddress; - return new Empty(); + public override Empty ApproveMultiProposals(ProposalIdList input) + { + AssertCurrentMiner(); + foreach (var proposalId in input.ProposalIds) + { + var proposal = State.Proposals[proposalId]; + if (proposal == null || !CheckProposalNotExpired(proposal)) + continue; + Approve(proposalId); + Context.LogDebug(() => $"Proposal {proposalId} approved by {Context.Sender}"); } - public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) - { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Unauthorized to create organization."); - var organizationAddress = CreateNewOrganization(input.OrganizationCreationInput); - if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) - { - Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - } + return new Empty(); + } - return organizationAddress; - } + public override Empty CreateEmergencyResponseOrganization(Empty input) + { + Assert(State.EmergencyResponseOrganizationAddress.Value == null, + "Emergency Response Organization already exists."); + AssertSenderAddressWith(State.DefaultOrganizationAddress.Value); + CreateEmergencyResponseOrganization(); + return new Empty(); + } - public override Address CreateOrganization(CreateOrganizationInput input) - { - Assert( - ValidateAddressInWhiteList(Context.Sender) || ValidateParliamentMemberAuthority(Context.Sender) || - State.DefaultOrganizationAddress.Value == Context.Sender, - "Unauthorized to create organization."); - var organizationAddress = CreateNewOrganization(input); + public override Address GetEmergencyResponseOrganizationAddress(Empty input) + { + return State.EmergencyResponseOrganizationAddress.Value; + } - return organizationAddress; - } + #region View - public override Hash CreateProposal(CreateProposalInput input) - { - AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); - var proposalId = CreateNewProposal(input); - return proposalId; - } + public override Organization GetOrganization(Address address) + { + var organization = State.Organizations[address]; + return organization ?? new Organization(); + } - public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) - { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Unauthorized to propose."); - AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); + public override ProposalOutput GetProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + if (proposal == null) return new ProposalOutput(); - var proposalId = CreateNewProposal(input.ProposalInput); - return proposalId; - } + var organization = State.Organizations[proposal.OrganizationAddress]; - public override Empty Approve(Hash input) + return new ProposalOutput { - var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); - proposal.Approvals.Add(parliamentMemberAddress); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated() - { - Address = parliamentMemberAddress, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Approve), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + ProposalId = proposalId, + ContractMethodName = proposal.ContractMethodName, + ExpiredTime = proposal.ExpiredTime, + OrganizationAddress = proposal.OrganizationAddress, + Params = proposal.Params, + Proposer = proposal.Proposer, + ToAddress = proposal.ToAddress, + ToBeReleased = Validate(proposal) && IsReleaseThresholdReached(proposal, organization), + ApprovalCount = proposal.Approvals.Count, + RejectionCount = proposal.Rejections.Count, + AbstentionCount = proposal.Abstentions.Count + }; + } - public override Empty Reject(Hash input) - { - var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); - proposal.Rejections.Add(parliamentMemberAddress); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated() - { - Address = parliamentMemberAddress, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Reject), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + public override Address GetDefaultOrganizationAddress(Empty input) + { + Assert(State.Initialized.Value, "Not initialized."); + return State.DefaultOrganizationAddress.Value; + } - public override Empty Abstain(Hash input) - { - var parliamentMemberAddress = GetAndCheckActualParliamentMemberAddress(); - var proposal = GetValidProposal(input); - AssertProposalNotYetVotedByMember(proposal, parliamentMemberAddress); - proposal.Abstentions.Add(parliamentMemberAddress); - State.Proposals[input] = proposal; - Context.Fire(new ReceiptCreated() - { - Address = parliamentMemberAddress, - ProposalId = input, - Time = Context.CurrentBlockTime, - ReceiptType = nameof(Abstain), - OrganizationAddress = proposal.OrganizationAddress - }); - return new Empty(); - } + public override Address CalculateOrganizationAddress(CreateOrganizationInput input) + { + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + return organizationAddress; + } - public override Empty Release(Hash proposalId) - { - var proposalInfo = GetValidProposal(proposalId); - Assert(Context.Sender.Equals(proposalInfo.Proposer), "No permission."); - var organization = State.Organizations[proposalInfo.OrganizationAddress]; - Assert(IsReleaseThresholdReached(proposalInfo, organization), "Not approved."); - Context.SendVirtualInlineBySystemContract( - CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposalInfo.ToAddress, - proposalInfo.ContractMethodName, proposalInfo.Params); - Context.Fire(new ProposalReleased { ProposalId = proposalId }); - State.Proposals.Remove(proposalId); - - return new Empty(); - } + public override BoolValue ValidateAddressIsParliamentMember(Address address) + { + return new BoolValue { Value = ValidateParliamentMemberAuthority(address) }; + } - public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) - { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.ProposalReleaseThreshold = input; - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new OrganizationThresholdChanged - { - OrganizationAddress = Context.Sender, - ProposerReleaseThreshold = input - }); - return new Empty(); - } + public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) + { + return new BoolValue { Value = ValidateAddressInWhiteList(input.Proposer) }; + } - public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) - { - var defaultOrganizationAddress = State.DefaultOrganizationAddress.Value; - Assert(defaultOrganizationAddress == Context.Sender, "No permission."); - var organization = State.Organizations[defaultOrganizationAddress]; - Assert( - input.Proposers.Count > 0 || !organization.ProposerAuthorityRequired || - organization.ParliamentMemberProposingAllowed, "White list can't be empty."); - State.ProposerWhiteList.Value = input; - Context.Fire(new OrganizationWhiteListChanged - { - OrganizationAddress = Context.Sender, - ProposerWhiteList = input - }); - return new Empty(); - } + public override ProposerWhiteList GetProposerWhiteList(Empty input) + { + var res = new ProposerWhiteList(); + var whitelist = State.ProposerWhiteList.Value; + res.Proposers.AddRange(whitelist.Proposers); + return res; + } - public override Empty ClearProposal(Hash input) - { - // anyone can clear proposal if it is expired - var proposal = State.Proposals[input]; - Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); - State.Proposals.Remove(input); - return new Empty(); - } + public override BoolValue ValidateOrganizationExist(Address input) + { + return new BoolValue { Value = State.Organizations[input] != null }; + } - public override Empty ApproveMultiProposals(ProposalIdList input) + public override ProposalIdList GetNotVotedProposals(ProposalIdList input) + { + var result = new ProposalIdList(); + foreach (var proposalId in input.ProposalIds) { - AssertCurrentMiner(); - foreach (var proposalId in input.ProposalIds) - { - var proposal = State.Proposals[proposalId]; - if (proposal == null || !CheckProposalNotExpired(proposal)) - continue; - Approve(proposalId); - Context.LogDebug(() => $"Proposal {proposalId} approved by {Context.Sender}"); - } - - return new Empty(); + var proposal = State.Proposals[proposalId]; + if (proposal == null || !Validate(proposal) || CheckProposalAlreadyVotedBy(proposal, Context.Sender)) + continue; + result.ProposalIds.Add(proposalId); } - public override Empty CreateEmergencyResponseOrganization(Empty input) - { - Assert(State.EmergencyResponseOrganizationAddress.Value == null, - "Emergency Response Organization already exists."); - AssertSenderAddressWith(State.DefaultOrganizationAddress.Value); - CreateEmergencyResponseOrganization(); - return new Empty(); - } + return result; + } - public override Address GetEmergencyResponseOrganizationAddress(Empty input) + public override ProposalIdList GetNotVotedPendingProposals(ProposalIdList input) + { + var result = new ProposalIdList(); + var currentParliament = GetCurrentMinerList(); + foreach (var proposalId in input.ProposalIds) { - return State.EmergencyResponseOrganizationAddress.Value; + var proposal = State.Proposals[proposalId]; + if (proposal == null || !Validate(proposal) || CheckProposalAlreadyVotedBy(proposal, Context.Sender)) + continue; + var organization = State.Organizations[proposal.OrganizationAddress]; + if (organization == null || !IsProposalStillPending(proposal, organization, currentParliament)) + continue; + result.ProposalIds.Add(proposalId); } + + return result; } + + #endregion view } \ No newline at end of file diff --git a/contract/AElf.Contracts.Parliament/ParliamentContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Parliament/ParliamentContract_ACS1_TransactionFeeProvider.cs index 1b3d14abfb..228af87c20 100644 --- a/contract/AElf.Contracts.Parliament/ParliamentContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Parliament/ParliamentContract_ACS1_TransactionFeeProvider.cs @@ -1,101 +1,92 @@ -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public partial class ParliamentContract { - public partial class ParliamentContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - if (input.Value == nameof(ApproveMultiProposals)) - { - return new MethodFees - { - MethodName = input.Value, - IsSizeFeeFree = true - }; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - return State.TransactionFees[input.Value]; - } + return new Empty(); + } - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - #endregion + State.MethodFeeController.Value = input; + return new Empty(); + } - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) + #region Views + + public override MethodFees GetMethodFee(StringValue input) + { + if (input.Value == nameof(ApproveMultiProposals)) + return new MethodFees { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + MethodName = input.Value, + IsSizeFeeFree = true + }; - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + return State.TransactionFees[input.Value]; + } - return new Empty(); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #endregion - State.MethodFeeController.Value = input; - return new Empty(); - } + #region private methods - #region private methods + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; + } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; - private void RequiredMethodFeeControllerSet() + var defaultAuthority = new AuthorityInfo { - if (State.MethodFeeController.Value != null) return; - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.DefaultOrganizationAddress.Value, - ContractAddress = Context.Self - }; - - State.MethodFeeController.Value = defaultAuthority; - } + OwnerAddress = State.DefaultOrganizationAddress.Value, + ContractAddress = Context.Self + }; - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + State.MethodFeeController.Value = defaultAuthority; + } - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - #endregion + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Parliament/ParliamentState.cs b/contract/AElf.Contracts.Parliament/ParliamentState.cs index f05bc45d4c..b0d67c871b 100644 --- a/contract/AElf.Contracts.Parliament/ParliamentState.cs +++ b/contract/AElf.Contracts.Parliament/ParliamentState.cs @@ -1,30 +1,29 @@ -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Election; using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public class ParliamentState : ContractState { - public class ParliamentState : ContractState - { - public MappedState Organizations { get; set; } + public MappedState Organizations { get; set; } - public BoolState Initialized { get; set; } + public BoolState Initialized { get; set; } - public SingletonState
DefaultOrganizationAddress { get; set; } + public SingletonState
DefaultOrganizationAddress { get; set; } - internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } - public MappedState Proposals { get; set; } - public MappedState TransactionFees { get; set; } + internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } + public MappedState Proposals { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState ProposerWhiteList { get; set; } - public SingletonState MethodFeeController { get; set; } + public SingletonState ProposerWhiteList { get; set; } + public SingletonState MethodFeeController { get; set; } - public SingletonState
EmergencyResponseOrganizationAddress { get; set; } - } + public SingletonState
EmergencyResponseOrganizationAddress { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Parliament/Parliament_Constants.cs b/contract/AElf.Contracts.Parliament/Parliament_Constants.cs index fcc25f7353..65e1219d78 100644 --- a/contract/AElf.Contracts.Parliament/Parliament_Constants.cs +++ b/contract/AElf.Contracts.Parliament/Parliament_Constants.cs @@ -1,11 +1,10 @@ -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public partial class ParliamentContract { - public partial class ParliamentContract - { - private const int DefaultOrganizationMinimalApprovalThreshold = 6667; - private const int DefaultOrganizationMaximalAbstentionThreshold = 2000; - private const int DefaultOrganizationMaximalRejectionThreshold = 2000; - private const int DefaultOrganizationMinimalVoteThresholdThreshold = 7500; - private const int AbstractVoteTotal = 10000; - } + private const int DefaultOrganizationMinimalApprovalThreshold = 6667; + private const int DefaultOrganizationMaximalAbstentionThreshold = 2000; + private const int DefaultOrganizationMaximalRejectionThreshold = 2000; + private const int DefaultOrganizationMinimalVoteThresholdThreshold = 7500; + private const int AbstractVoteTotal = 10000; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Parliament/Parliament_Helper.cs b/contract/AElf.Contracts.Parliament/Parliament_Helper.cs index dd282feaca..7e1a763d2b 100644 --- a/contract/AElf.Contracts.Parliament/Parliament_Helper.cs +++ b/contract/AElf.Contracts.Parliament/Parliament_Helper.cs @@ -1,325 +1,312 @@ using System; using System.Collections.Generic; using System.Linq; +using AElf.Sdk.CSharp; using AElf.Standards.ACS3; using AElf.Types; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public partial class ParliamentContract { - public partial class ParliamentContract + private List
GetCurrentMinerList() { - private List
GetCurrentMinerList() - { - RequireConsensusContractStateSet(); - var miner = State.ConsensusContract.GetCurrentMinerList.Call(new Empty()); - var members = miner.Pubkeys.Select(publicKey => - Address.FromPublicKey(publicKey.ToByteArray())).ToList(); - return members; - } + RequireConsensusContractStateSet(); + var miner = State.ConsensusContract.GetCurrentMinerList.Call(new Empty()); + var members = miner.Pubkeys.Select(publicKey => + Address.FromPublicKey(publicKey.ToByteArray())).ToList(); + return members; + } - private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) - { - var organization = State.Organizations[organizationAddress]; - Assert(organization != null, "No registered organization."); - // It is a valid proposer if - // authority check is disable, - // or sender is in proposer white list, - // or sender is one of miners when member proposing allowed. - Assert( - !organization.ProposerAuthorityRequired || ValidateAddressInWhiteList(proposer) || - organization.ParliamentMemberProposingAllowed && ValidateParliamentMemberAuthority(proposer), - "Unauthorized to propose."); - } + private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) + { + var organization = State.Organizations[organizationAddress]; + Assert(organization != null, "No registered organization."); + // It is a valid proposer if + // authority check is disable, + // or sender is in proposer white list, + // or sender is one of miners when member proposing allowed. + Assert( + !organization.ProposerAuthorityRequired || ValidateAddressInWhiteList(proposer) || + (organization.ParliamentMemberProposingAllowed && ValidateParliamentMemberAuthority(proposer)), + "Unauthorized to propose."); + } - private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) - { - var parliamentMembers = GetCurrentMinerList(); - var isRejected = IsProposalRejected(proposal, organization, parliamentMembers); - if (isRejected) - return false; + private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) + { + var parliamentMembers = GetCurrentMinerList(); + var isRejected = IsProposalRejected(proposal, organization, parliamentMembers); + if (isRejected) + return false; - var isAbstained = IsProposalAbstained(proposal, organization, parliamentMembers); - if (isAbstained) - return false; + var isAbstained = IsProposalAbstained(proposal, organization, parliamentMembers); + if (isAbstained) + return false; - return CheckEnoughVoteAndApprovals(proposal, organization, parliamentMembers); - } + return CheckEnoughVoteAndApprovals(proposal, organization, parliamentMembers); + } - private bool IsProposalStillPending(ProposalInfo proposal, Organization organization, - ICollection
parliamentMembers) - { - var isRejected = IsProposalRejected(proposal, organization, parliamentMembers); - if (isRejected) - return false; + private bool IsProposalStillPending(ProposalInfo proposal, Organization organization, + ICollection
parliamentMembers) + { + var isRejected = IsProposalRejected(proposal, organization, parliamentMembers); + if (isRejected) + return false; - var isAbstained = IsProposalAbstained(proposal, organization, parliamentMembers); - if (isAbstained) - return false; + var isAbstained = IsProposalAbstained(proposal, organization, parliamentMembers); + if (isAbstained) + return false; - return !CheckEnoughVoteAndApprovals(proposal, organization, parliamentMembers); - } + return !CheckEnoughVoteAndApprovals(proposal, organization, parliamentMembers); + } - private bool IsProposalRejected(ProposalInfo proposal, Organization organization, - ICollection
parliamentMembers) - { - var rejectionMemberCount = proposal.Rejections.Count(parliamentMembers.Contains); - return rejectionMemberCount * AbstractVoteTotal > - organization.ProposalReleaseThreshold.MaximalRejectionThreshold * parliamentMembers.Count; - } + private bool IsProposalRejected(ProposalInfo proposal, Organization organization, + ICollection
parliamentMembers) + { + var rejectionMemberCount = proposal.Rejections.Count(parliamentMembers.Contains); + return rejectionMemberCount * AbstractVoteTotal > + organization.ProposalReleaseThreshold.MaximalRejectionThreshold * parliamentMembers.Count; + } - private bool IsProposalAbstained(ProposalInfo proposal, Organization organization, - ICollection
parliamentMembers) - { - var abstentionMemberCount = proposal.Abstentions.Count(parliamentMembers.Contains); - return abstentionMemberCount * AbstractVoteTotal > - organization.ProposalReleaseThreshold.MaximalAbstentionThreshold * parliamentMembers.Count; - } + private bool IsProposalAbstained(ProposalInfo proposal, Organization organization, + ICollection
parliamentMembers) + { + var abstentionMemberCount = proposal.Abstentions.Count(parliamentMembers.Contains); + return abstentionMemberCount * AbstractVoteTotal > + organization.ProposalReleaseThreshold.MaximalAbstentionThreshold * parliamentMembers.Count; + } - private bool CheckEnoughVoteAndApprovals(ProposalInfo proposal, Organization organization, - ICollection
parliamentMembers) - { - var approvedMemberCount = proposal.Approvals.Count(parliamentMembers.Contains); - var isApprovalEnough = approvedMemberCount * AbstractVoteTotal >= - organization.ProposalReleaseThreshold.MinimalApprovalThreshold * - parliamentMembers.Count; - if (!isApprovalEnough) - return false; - - var isVoteThresholdReached = IsVoteThresholdReached(proposal, organization, parliamentMembers); - return isVoteThresholdReached; - } + private bool CheckEnoughVoteAndApprovals(ProposalInfo proposal, Organization organization, + ICollection
parliamentMembers) + { + var approvedMemberCount = proposal.Approvals.Count(parliamentMembers.Contains); + var isApprovalEnough = approvedMemberCount * AbstractVoteTotal >= + organization.ProposalReleaseThreshold.MinimalApprovalThreshold * + parliamentMembers.Count; + if (!isApprovalEnough) + return false; + + var isVoteThresholdReached = IsVoteThresholdReached(proposal, organization, parliamentMembers); + return isVoteThresholdReached; + } - private bool IsVoteThresholdReached(ProposalInfo proposal, Organization organization, - ICollection
parliamentMembers) - { - var isVoteThresholdReached = - proposal.Abstentions.Concat(proposal.Approvals).Concat(proposal.Rejections) - .Count(parliamentMembers.Contains) * AbstractVoteTotal >= - organization.ProposalReleaseThreshold.MinimalVoteThreshold * parliamentMembers.Count; - return isVoteThresholdReached; - } + private bool IsVoteThresholdReached(ProposalInfo proposal, Organization organization, + ICollection
parliamentMembers) + { + var isVoteThresholdReached = + proposal.Abstentions.Concat(proposal.Approvals).Concat(proposal.Rejections) + .Count(parliamentMembers.Contains) * AbstractVoteTotal >= + organization.ProposalReleaseThreshold.MinimalVoteThreshold * parliamentMembers.Count; + return isVoteThresholdReached; + } - private void RequireConsensusContractStateSet() - { - if (State.ConsensusContract.Value != null) - return; - State.ConsensusContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + private void RequireConsensusContractStateSet() + { + if (State.ConsensusContract.Value != null) + return; + State.ConsensusContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + } - private Address GetAndCheckActualParliamentMemberAddress() - { - var currentParliament = GetCurrentMinerList(); + private Address GetAndCheckActualParliamentMemberAddress() + { + var currentParliament = GetCurrentMinerList(); - if (currentParliament.Any(r => r.Equals(Context.Sender))) - { - return Context.Sender; - } + if (currentParliament.Any(r => r.Equals(Context.Sender))) return Context.Sender; - if (State.ElectionContract.Value == null) - { - var electionContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - if (electionContractAddress == null) - { - // Election Contract not deployed - only possible in test environment. - throw new AssertionException("Unauthorized sender."); - } - - State.ElectionContract.Value = electionContractAddress; - } - - var managedPubkey = State.ElectionContract.GetManagedPubkeys.Call(Context.Sender); - if (!managedPubkey.Value.Any()) - { + if (State.ElectionContract.Value == null) + { + var electionContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + if (electionContractAddress == null) + // Election Contract not deployed - only possible in test environment. throw new AssertionException("Unauthorized sender."); - } - if (managedPubkey.Value.Count > 1) - { - throw new AssertionException("Admin with multiple managed pubkeys cannot handle proposal."); - } + State.ElectionContract.Value = electionContractAddress; + } - var actualMemberAddress = Address.FromPublicKey(managedPubkey.Value.Single().ToByteArray()); - if (!currentParliament.Any(r => r.Equals(actualMemberAddress))) - { - throw new AssertionException("Unauthorized sender."); - } + var managedPubkey = State.ElectionContract.GetManagedPubkeys.Call(Context.Sender); + if (!managedPubkey.Value.Any()) throw new AssertionException("Unauthorized sender."); - return actualMemberAddress; - } + if (managedPubkey.Value.Count > 1) + throw new AssertionException("Admin with multiple managed pubkeys cannot handle proposal."); - private bool Validate(Organization organization) - { - var proposalReleaseThreshold = organization.ProposalReleaseThreshold; - - return proposalReleaseThreshold.MinimalVoteThreshold <= AbstractVoteTotal && - proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && - proposalReleaseThreshold.MinimalApprovalThreshold > 0 && - proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && - proposalReleaseThreshold.MaximalRejectionThreshold >= 0 && - proposalReleaseThreshold.MaximalAbstentionThreshold + - proposalReleaseThreshold.MinimalApprovalThreshold <= AbstractVoteTotal && - proposalReleaseThreshold.MaximalRejectionThreshold + - proposalReleaseThreshold.MinimalApprovalThreshold <= AbstractVoteTotal; - } + var actualMemberAddress = Address.FromPublicKey(managedPubkey.Value.Single().ToByteArray()); + if (!currentParliament.Any(r => r.Equals(actualMemberAddress))) + throw new AssertionException("Unauthorized sender."); - private bool Validate(ProposalInfo proposal) - { - var validDestinationAddress = proposal.ToAddress != null; - var validDestinationMethodName = !string.IsNullOrWhiteSpace(proposal.ContractMethodName); - var validExpiredTime = CheckProposalNotExpired(proposal); - var hasOrganizationAddress = proposal.OrganizationAddress != null; - var validDescriptionUrl = ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl); - return validDestinationAddress && validDestinationMethodName && validExpiredTime && - hasOrganizationAddress && validDescriptionUrl; - } + return actualMemberAddress; + } - private bool ValidateDescriptionUrlScheme(string uriString) - { - if (string.IsNullOrEmpty(uriString)) - return true; - bool result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - return result; - } + private bool Validate(Organization organization) + { + var proposalReleaseThreshold = organization.ProposalReleaseThreshold; + + return proposalReleaseThreshold.MinimalVoteThreshold <= AbstractVoteTotal && + proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && + proposalReleaseThreshold.MinimalApprovalThreshold > 0 && + proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && + proposalReleaseThreshold.MaximalRejectionThreshold >= 0 && + proposalReleaseThreshold.MaximalAbstentionThreshold + + proposalReleaseThreshold.MinimalApprovalThreshold <= AbstractVoteTotal && + proposalReleaseThreshold.MaximalRejectionThreshold + + proposalReleaseThreshold.MinimalApprovalThreshold <= AbstractVoteTotal; + } - private bool CheckProposalNotExpired(ProposalInfo proposal) - { - return proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; - } + private bool Validate(ProposalInfo proposal) + { + var validDestinationAddress = proposal.ToAddress != null; + var validDestinationMethodName = !string.IsNullOrWhiteSpace(proposal.ContractMethodName); + var validExpiredTime = CheckProposalNotExpired(proposal); + var hasOrganizationAddress = proposal.OrganizationAddress != null; + var validDescriptionUrl = ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl); + return validDestinationAddress && validDestinationMethodName && validExpiredTime && + hasOrganizationAddress && validDescriptionUrl; + } - private ProposalInfo GetValidProposal(Hash proposalId) - { - var proposal = State.Proposals[proposalId]; - Assert(proposal != null, "Proposal not found."); - Assert(Validate(proposal), "Invalid proposal."); - return proposal; - } + private bool ValidateDescriptionUrlScheme(string uriString) + { + if (string.IsNullOrEmpty(uriString)) + return true; + var result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + return result; + } - private void AssertProposalNotYetVotedByMember(ProposalInfo proposal, Address parliamentMemberAddress) - { - Assert(!CheckProposalAlreadyVotedBy(proposal, parliamentMemberAddress), "Already approved."); - } + private bool CheckProposalNotExpired(ProposalInfo proposal) + { + return proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; + } - private bool CheckProposalAlreadyVotedBy(ProposalInfo proposal, Address address) - { - return proposal.Approvals.Contains(address) || proposal.Rejections.Contains(address) || - proposal.Abstentions.Contains(address); - } + private ProposalInfo GetValidProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + Assert(proposal != null, "Proposal not found."); + Assert(Validate(proposal), "Invalid proposal."); + return proposal; + } - private bool ValidateAddressInWhiteList(Address address) - { - return State.ProposerWhiteList.Value.Proposers.Any(p => p == address); - } + private void AssertProposalNotYetVotedByMember(ProposalInfo proposal, Address parliamentMemberAddress) + { + Assert(!CheckProposalAlreadyVotedBy(proposal, parliamentMemberAddress), "Already approved."); + } - private bool ValidateParliamentMemberAuthority(Address address) - { - var currentMinerList = GetCurrentMinerList(); - return currentMinerList.Any(m => m == address); - } + private bool CheckProposalAlreadyVotedBy(ProposalInfo proposal, Address address) + { + return proposal.Approvals.Contains(address) || proposal.Rejections.Contains(address) || + proposal.Abstentions.Contains(address); + } - private void AssertCurrentMiner() - { - RequireConsensusContractStateSet(); - var isCurrentMiner = State.ConsensusContract.IsCurrentMiner.Call(Context.Sender).Value; - Context.LogDebug(() => $"Sender is currentMiner : {isCurrentMiner}."); - Assert(isCurrentMiner, "No permission."); - } + private bool ValidateAddressInWhiteList(Address address) + { + return State.ProposerWhiteList.Value.Proposers.Any(p => p == address); + } - private Hash GenerateProposalId(CreateProposalInput input) - { - return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); - } + private bool ValidateParliamentMemberAuthority(Address address) + { + var currentMinerList = GetCurrentMinerList(); + return currentMinerList.Any(m => m == address); + } - private Hash CreateNewProposal(CreateProposalInput input) - { - Hash proposalId = GenerateProposalId(input); - var proposal = new ProposalInfo - { - ContractMethodName = input.ContractMethodName, - ExpiredTime = input.ExpiredTime, - Params = input.Params, - ToAddress = input.ToAddress, - OrganizationAddress = input.OrganizationAddress, - ProposalId = proposalId, - Proposer = Context.Sender, - ProposalDescriptionUrl = input.ProposalDescriptionUrl - }; - Assert(Validate(proposal), "Invalid proposal."); - Assert(State.Proposals[proposalId] == null, "Proposal already exists."); - State.Proposals[proposalId] = proposal; - Context.Fire(new ProposalCreated - { ProposalId = proposalId, OrganizationAddress = input.OrganizationAddress }); - return proposalId; - } + private void AssertCurrentMiner() + { + RequireConsensusContractStateSet(); + var isCurrentMiner = State.ConsensusContract.IsCurrentMiner.Call(Context.Sender).Value; + Context.LogDebug(() => $"Sender is currentMiner : {isCurrentMiner}."); + Assert(isCurrentMiner, "No permission."); + } - private Address CreateNewOrganization(CreateOrganizationInput input) + private Hash GenerateProposalId(CreateProposalInput input) + { + return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); + } + + private Hash CreateNewProposal(CreateProposalInput input) + { + var proposalId = GenerateProposalId(input); + var proposal = new ProposalInfo { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - var organizationHash = organizationHashAddressPair.OrganizationHash; - var organization = new Organization - { - ProposalReleaseThreshold = input.ProposalReleaseThreshold, - OrganizationAddress = organizationAddress, - OrganizationHash = organizationHash, - ProposerAuthorityRequired = input.ProposerAuthorityRequired, - ParliamentMemberProposingAllowed = input.ParliamentMemberProposingAllowed, - CreationToken = input.CreationToken - }; - Assert(Validate(organization), "Invalid organization."); - if (State.Organizations[organizationAddress] != null) - return organizationAddress; - - State.Organizations[organizationAddress] = organization; - Context.Fire(new OrganizationCreated - { - OrganizationAddress = organizationAddress - }); + ContractMethodName = input.ContractMethodName, + ExpiredTime = input.ExpiredTime, + Params = input.Params, + ToAddress = input.ToAddress, + OrganizationAddress = input.OrganizationAddress, + ProposalId = proposalId, + Proposer = Context.Sender, + ProposalDescriptionUrl = input.ProposalDescriptionUrl + }; + Assert(Validate(proposal), "Invalid proposal."); + Assert(State.Proposals[proposalId] == null, "Proposal already exists."); + State.Proposals[proposalId] = proposal; + Context.Fire(new ProposalCreated + { ProposalId = proposalId, OrganizationAddress = input.OrganizationAddress }); + return proposalId; + } + private Address CreateNewOrganization(CreateOrganizationInput input) + { + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + var organizationHash = organizationHashAddressPair.OrganizationHash; + var organization = new Organization + { + ProposalReleaseThreshold = input.ProposalReleaseThreshold, + OrganizationAddress = organizationAddress, + OrganizationHash = organizationHash, + ProposerAuthorityRequired = input.ProposerAuthorityRequired, + ParliamentMemberProposingAllowed = input.ParliamentMemberProposingAllowed, + CreationToken = input.CreationToken + }; + Assert(Validate(organization), "Invalid organization."); + if (State.Organizations[organizationAddress] != null) return organizationAddress; - } - private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( - CreateOrganizationInput createOrganizationInput) + State.Organizations[organizationAddress] = organization; + Context.Fire(new OrganizationCreated { - var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); - var organizationAddress = - Context.ConvertVirtualAddressToContractAddressWithContractHashName( - CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); - return new OrganizationHashAddressPair - { - OrganizationAddress = organizationAddress, - OrganizationHash = organizationHash - }; - } + OrganizationAddress = organizationAddress + }); - private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) + return organizationAddress; + } + + private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( + CreateOrganizationInput createOrganizationInput) + { + var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); + var organizationAddress = + Context.ConvertVirtualAddressToContractAddressWithContractHashName( + CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); + return new OrganizationHashAddressPair { - return creationToken == null - ? organizationHash - : HashHelper.ConcatAndCompute(organizationHash, creationToken); - } + OrganizationAddress = organizationAddress, + OrganizationHash = organizationHash + }; + } - private void CreateEmergencyResponseOrganization() + private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) + { + return creationToken == null + ? organizationHash + : HashHelper.ConcatAndCompute(organizationHash, creationToken); + } + + private void CreateEmergencyResponseOrganization() + { + var createOrganizationInput = new CreateOrganizationInput { - var createOrganizationInput = new CreateOrganizationInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 9000, - MinimalVoteThreshold = 9000, - MaximalAbstentionThreshold = 1000, - MaximalRejectionThreshold = 1000 - }, - ProposerAuthorityRequired = false, - ParliamentMemberProposingAllowed = true - }; - - State.EmergencyResponseOrganizationAddress.Value = CreateOrganization(createOrganizationInput); - } + MinimalApprovalThreshold = 9000, + MinimalVoteThreshold = 9000, + MaximalAbstentionThreshold = 1000, + MaximalRejectionThreshold = 1000 + }, + ProposerAuthorityRequired = false, + ParliamentMemberProposingAllowed = true + }; + + State.EmergencyResponseOrganizationAddress.Value = CreateOrganization(createOrganizationInput); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/AElf.Contracts.Profit.csproj b/contract/AElf.Contracts.Profit/AElf.Contracts.Profit.csproj index 9621d4a5a6..66a51ddbc2 100644 --- a/contract/AElf.Contracts.Profit/AElf.Contracts.Profit.csproj +++ b/contract/AElf.Contracts.Profit/AElf.Contracts.Profit.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,11 +9,11 @@ - true + true - true + true @@ -21,7 +21,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs0.proto diff --git a/contract/AElf.Contracts.Profit/ContractsReferences.cs b/contract/AElf.Contracts.Profit/ContractsReferences.cs index 8bae6d38a5..a938d1c013 100644 --- a/contract/AElf.Contracts.Profit/ContractsReferences.cs +++ b/contract/AElf.Contracts.Profit/ContractsReferences.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public partial class ProfitContractState { - public partial class ProfitContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/ProfitContract.cs b/contract/AElf.Contracts.Profit/ProfitContract.cs index 994255d5fd..f996a41a4c 100644 --- a/contract/AElf.Contracts.Profit/ProfitContract.cs +++ b/contract/AElf.Contracts.Profit/ProfitContract.cs @@ -9,832 +9,769 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +/// +/// Let's imagine a scenario: +/// 1. Ean creates a profit scheme FOO: Ean calls CreateScheme. We call this profit scheme PI_FOO. +/// 2. GL creates another profit scheme BAR: GL calls CreateScheme. We call this profit scheme PI_BAR. +/// 3. Ean (as the creator of PI_FOO) register PI_BAR as a sub profit scheme as PI_FOO: +/// Ean call RemoveSubScheme (SchemeId: PI_BAR's profit id, Shares : 1) +/// 4. Anil has an account which address is ADDR_Anil. +/// 5. Ean registers address ADDR_Anil as a profit Beneficiary of PI_FOO: Ean calls AddBeneficiary (Beneficiary: +/// ADDR_Anil, Shares : 1) +/// 6: Now PI_FOO is organized like this: +/// PI_FOO +/// / \ +/// 1 1 +/// / \ +/// PI_BAR ADDR_Anil +/// (Total Shares is 2) +/// 7. Ean adds some ELF tokens to PI_FOO: Ean calls DistributeProfits (Symbol: "ELF", Amount: 1000L, Period: 1) +/// 8. Ean calls DistributeProfits: Balance of PI_BAR is 500L (PI_BAR's general ledger balance, also we can say balance +/// of virtual address of PI_BAR is 500L), +/// 9. Balance of PI_FOO's virtual address of first period is 500L. +/// 10. Anil can only get his profits by calling Profit (SchemeId: PI_BAR's profit id, Symbol: "ELF") +/// +public partial class ProfitContract : ProfitContractImplContainer.ProfitContractImplBase { /// - /// Let's imagine a scenario: - /// 1. Ean creates a profit scheme FOO: Ean calls CreateScheme. We call this profit scheme PI_FOO. - /// 2. GL creates another profit scheme BAR: GL calls CreateScheme. We call this profit scheme PI_BAR. - /// 3. Ean (as the creator of PI_FOO) register PI_BAR as a sub profit scheme as PI_FOO: - /// Ean call RemoveSubScheme (SchemeId: PI_BAR's profit id, Shares : 1) - /// 4. Anil has an account which address is ADDR_Anil. - /// 5. Ean registers address ADDR_Anil as a profit Beneficiary of PI_FOO: Ean calls AddBeneficiary (Beneficiary: ADDR_Anil, Shares : 1) - /// 6: Now PI_FOO is organized like this: - /// PI_FOO - /// / \ - /// 1 1 - /// / \ - /// PI_BAR ADDR_Anil - /// (Total Shares is 2) - /// 7. Ean adds some ELF tokens to PI_FOO: Ean calls DistributeProfits (Symbol: "ELF", Amount: 1000L, Period: 1) - /// 8. Ean calls DistributeProfits: Balance of PI_BAR is 500L (PI_BAR's general ledger balance, also we can say balance of virtual address of PI_BAR is 500L), - /// 9. Balance of PI_FOO's virtual address of first period is 500L. - /// 10. Anil can only get his profits by calling Profit (SchemeId: PI_BAR's profit id, Symbol: "ELF") + /// Create a Scheme of profit distribution. + /// At the first time, the scheme's id is unknown,it may create by transaction id and createdSchemeIds; /// - public partial class ProfitContract : ProfitContractImplContainer.ProfitContractImplBase + /// + /// + public override Hash CreateScheme(CreateSchemeInput input) { - /// - /// Create a Scheme of profit distribution. - /// At the first time, the scheme's id is unknown,it may create by transaction id and createdSchemeIds; - /// - /// - /// - public override Hash CreateScheme(CreateSchemeInput input) - { - ValidateContractState(State.TokenContract, SmartContractConstants.TokenContractSystemName); + ValidateContractState(State.TokenContract, SmartContractConstants.TokenContractSystemName); - if (input.ProfitReceivingDuePeriodCount == 0) - { - input.ProfitReceivingDuePeriodCount = ProfitContractConstants.DefaultProfitReceivingDuePeriodCount; - } - else - { - Assert( - input.ProfitReceivingDuePeriodCount > 0 && - input.ProfitReceivingDuePeriodCount <= ProfitContractConstants.MaximumProfitReceivingDuePeriodCount, - "Invalid profit receiving due period count."); - } + if (input.ProfitReceivingDuePeriodCount == 0) + input.ProfitReceivingDuePeriodCount = ProfitContractConstants.DefaultProfitReceivingDuePeriodCount; + else + Assert( + input.ProfitReceivingDuePeriodCount > 0 && + input.ProfitReceivingDuePeriodCount <= ProfitContractConstants.MaximumProfitReceivingDuePeriodCount, + "Invalid profit receiving due period count."); - var schemeId = GenerateSchemeId(input); - var manager = input.Manager ?? Context.Sender; - var scheme = GetNewScheme(input, schemeId, manager); - Assert(State.SchemeInfos[schemeId] == null, "Already exists."); - State.SchemeInfos[schemeId] = scheme; + var schemeId = GenerateSchemeId(input); + var manager = input.Manager ?? Context.Sender; + var scheme = GetNewScheme(input, schemeId, manager); + Assert(State.SchemeInfos[schemeId] == null, "Already exists."); + State.SchemeInfos[schemeId] = scheme; - var schemeIds = State.ManagingSchemeIds[scheme.Manager]; - if (schemeIds == null) + var schemeIds = State.ManagingSchemeIds[scheme.Manager]; + if (schemeIds == null) + schemeIds = new CreatedSchemeIds { - schemeIds = new CreatedSchemeIds - { - SchemeIds = {schemeId} - }; - } - else - { - schemeIds.SchemeIds.Add(schemeId); - } + SchemeIds = { schemeId } + }; + else + schemeIds.SchemeIds.Add(schemeId); + + State.ManagingSchemeIds[scheme.Manager] = schemeIds; - State.ManagingSchemeIds[scheme.Manager] = schemeIds; + Context.LogDebug(() => $"Created scheme {State.SchemeInfos[schemeId]}"); - Context.LogDebug(() => $"Created scheme {State.SchemeInfos[schemeId]}"); + Context.Fire(new SchemeCreated + { + SchemeId = scheme.SchemeId, + Manager = scheme.Manager, + IsReleaseAllBalanceEveryTimeByDefault = scheme.IsReleaseAllBalanceEveryTimeByDefault, + ProfitReceivingDuePeriodCount = scheme.ProfitReceivingDuePeriodCount, + VirtualAddress = scheme.VirtualAddress + }); + return schemeId; + } - Context.Fire(new SchemeCreated + /// + /// Add a child to a existed scheme. + /// + /// AddSubSchemeInput + /// + public override Empty AddSubScheme(AddSubSchemeInput input) + { + Assert(input.SchemeId != input.SubSchemeId, "Two schemes cannot be same."); + Assert(input.SubSchemeShares > 0, "Shares of sub scheme should greater than 0."); + + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); + // ReSharper disable once PossibleNullReferenceException + Assert(Context.Sender == scheme.Manager, "Only manager can add sub-scheme."); + Assert(scheme.SubSchemes.All(s => s.SchemeId != input.SubSchemeId), + $"Sub scheme {input.SubSchemeId} already exist."); + + var subSchemeId = input.SubSchemeId; + var subScheme = State.SchemeInfos[subSchemeId]; + Assert(subScheme != null, "Sub scheme not found."); + + var subSchemeVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId); + // Add profit details and total shares of the father scheme. + AddBeneficiary(new AddBeneficiaryInput + { + SchemeId = input.SchemeId, + BeneficiaryShare = new BeneficiaryShare { - SchemeId = scheme.SchemeId, - Manager = scheme.Manager, - IsReleaseAllBalanceEveryTimeByDefault = scheme.IsReleaseAllBalanceEveryTimeByDefault, - ProfitReceivingDuePeriodCount = scheme.ProfitReceivingDuePeriodCount, - VirtualAddress = scheme.VirtualAddress - }); - return schemeId; - } + Beneficiary = subSchemeVirtualAddress, + Shares = input.SubSchemeShares + }, + EndPeriod = long.MaxValue + }); - /// - /// Add a child to a existed scheme. - /// - /// AddSubSchemeInput - /// - public override Empty AddSubScheme(AddSubSchemeInput input) + // Add a sub profit scheme. + scheme.SubSchemes.Add(new SchemeBeneficiaryShare { - Assert(input.SchemeId != input.SubSchemeId, "Two schemes cannot be same."); - Assert(input.SubSchemeShares > 0, "Shares of sub scheme should greater than 0."); + SchemeId = input.SubSchemeId, + Shares = input.SubSchemeShares + }); + State.SchemeInfos[input.SchemeId] = scheme; - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); - // ReSharper disable once PossibleNullReferenceException - Assert(Context.Sender == scheme.Manager, "Only manager can add sub-scheme."); - Assert(scheme.SubSchemes.All(s => s.SchemeId != input.SubSchemeId), $"Sub scheme {input.SubSchemeId} already exist."); + return new Empty(); + } - var subSchemeId = input.SubSchemeId; - var subScheme = State.SchemeInfos[subSchemeId]; - Assert(subScheme != null, "Sub scheme not found."); + public override Empty RemoveSubScheme(RemoveSubSchemeInput input) + { + Assert(input.SchemeId != input.SubSchemeId, "Two schemes cannot be same."); - var subSchemeVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId); - // Add profit details and total shares of the father scheme. - AddBeneficiary(new AddBeneficiaryInput - { - SchemeId = input.SchemeId, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = subSchemeVirtualAddress, - Shares = input.SubSchemeShares - }, - EndPeriod = long.MaxValue - }); + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); - // Add a sub profit scheme. - scheme.SubSchemes.Add(new SchemeBeneficiaryShare - { - SchemeId = input.SubSchemeId, - Shares = input.SubSchemeShares - }); - State.SchemeInfos[input.SchemeId] = scheme; + // ReSharper disable once PossibleNullReferenceException + Assert(Context.Sender == scheme.Manager, "Only manager can remove sub-scheme."); - return new Empty(); - } + var shares = scheme.SubSchemes.SingleOrDefault(d => d.SchemeId == input.SubSchemeId); + if (shares == null) return new Empty(); - public override Empty RemoveSubScheme(RemoveSubSchemeInput input) - { - Assert(input.SchemeId != input.SubSchemeId, "Two schemes cannot be same."); + var subSchemeId = input.SubSchemeId; + var subScheme = State.SchemeInfos[subSchemeId]; + Assert(subScheme != null, "Sub scheme not found."); - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); + var subSchemeVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId); + // Remove profit details + State.ProfitDetailsMap[input.SchemeId][subSchemeVirtualAddress] = new ProfitDetails(); + scheme.SubSchemes.Remove(shares); + scheme.TotalShares = scheme.TotalShares.Sub(shares.Shares); + State.SchemeInfos[input.SchemeId] = scheme; - // ReSharper disable once PossibleNullReferenceException - Assert(Context.Sender == scheme.Manager, "Only manager can remove sub-scheme."); + return new Empty(); + } - var shares = scheme.SubSchemes.SingleOrDefault(d => d.SchemeId == input.SubSchemeId); - if (shares == null) - { - return new Empty(); - } + public override Empty AddBeneficiary(AddBeneficiaryInput input) + { + AssertValidInput(input); + if (input.EndPeriod == 0) + // Which means this profit Beneficiary will never expired unless removed. + input.EndPeriod = long.MaxValue; - var subSchemeId = input.SubSchemeId; - var subScheme = State.SchemeInfos[subSchemeId]; - Assert(subScheme != null, "Sub scheme not found."); + var schemeId = input.SchemeId; + var scheme = State.SchemeInfos[schemeId]; - var subSchemeVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeId); - // Remove profit details - State.ProfitDetailsMap[input.SchemeId][subSchemeVirtualAddress] = new ProfitDetails(); - scheme.SubSchemes.Remove(shares); - scheme.TotalShares = scheme.TotalShares.Sub(shares.Shares); - State.SchemeInfos[input.SchemeId] = scheme; + Assert(scheme != null, "Scheme not found."); - return new Empty(); - } + // ReSharper disable once PossibleNullReferenceException + Assert( + Context.Sender == scheme.Manager || Context.Sender == + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), + "Only manager can add beneficiary."); + + Context.LogDebug(() => + $"{input.SchemeId}.\n End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); + + Assert(input.EndPeriod >= scheme.CurrentPeriod, + $"Invalid end period. End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); - public override Empty AddBeneficiary(AddBeneficiaryInput input) + scheme.TotalShares = scheme.TotalShares.Add(input.BeneficiaryShare.Shares); + + State.SchemeInfos[schemeId] = scheme; + + var profitDetail = new ProfitDetail { - AssertValidInput(input); - if (input.EndPeriod == 0) + StartPeriod = scheme.CurrentPeriod.Add(scheme.DelayDistributePeriodCount), + EndPeriod = input.EndPeriod, + Shares = input.BeneficiaryShare.Shares + }; + + var currentProfitDetails = State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary]; + if (currentProfitDetails == null) + currentProfitDetails = new ProfitDetails { - // Which means this profit Beneficiary will never expired unless removed. - input.EndPeriod = long.MaxValue; - } + Details = { profitDetail } + }; + else + currentProfitDetails.Details.Add(profitDetail); - var schemeId = input.SchemeId; - var scheme = State.SchemeInfos[schemeId]; + // Remove details too old. + var oldProfitDetails = currentProfitDetails.Details.Where( + d => d.EndPeriod != long.MaxValue && d.LastProfitPeriod >= d.EndPeriod && + d.EndPeriod.Add(scheme.ProfitReceivingDuePeriodCount) < scheme.CurrentPeriod).ToList(); + foreach (var detail in oldProfitDetails) currentProfitDetails.Details.Remove(detail); - Assert(scheme != null, "Scheme not found."); + State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary] = currentProfitDetails; - // ReSharper disable once PossibleNullReferenceException - Assert( - Context.Sender == scheme.Manager || Context.Sender == - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), - "Only manager can add beneficiary."); + Context.LogDebug(() => + $"Added {input.BeneficiaryShare.Shares} weights to scheme {input.SchemeId.ToHex()}: {profitDetail}"); - Context.LogDebug(() => - $"{input.SchemeId}.\n End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); + return new Empty(); + } - Assert(input.EndPeriod >= scheme.CurrentPeriod, - $"Invalid end period. End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); + private void AssertValidInput(AddBeneficiaryInput input) + { + Assert(input.SchemeId != null, "Invalid scheme id."); + Assert(input.BeneficiaryShare?.Beneficiary != null, "Invalid beneficiary address."); + Assert(input.BeneficiaryShare?.Shares >= 0, "Invalid share."); + } - scheme.TotalShares = scheme.TotalShares.Add(input.BeneficiaryShare.Shares); + public override Empty RemoveBeneficiary(RemoveBeneficiaryInput input) + { + Assert(input.SchemeId != null, "Invalid scheme id."); + Assert(input.Beneficiary != null, "Invalid Beneficiary address."); - State.SchemeInfos[schemeId] = scheme; + var scheme = State.SchemeInfos[input.SchemeId]; - var profitDetail = new ProfitDetail - { - StartPeriod = scheme.CurrentPeriod.Add(scheme.DelayDistributePeriodCount), - EndPeriod = input.EndPeriod, - Shares = input.BeneficiaryShare.Shares, - }; + Assert(scheme != null, "Scheme not found."); - var currentProfitDetails = State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary]; - if (currentProfitDetails == null) - { - currentProfitDetails = new ProfitDetails - { - Details = {profitDetail} - }; - } - else - { - currentProfitDetails.Details.Add(profitDetail); - } + var currentDetail = State.ProfitDetailsMap[input.SchemeId][input.Beneficiary]; - // Remove details too old. - var oldProfitDetails = currentProfitDetails.Details.Where( - d => d.EndPeriod != long.MaxValue && d.LastProfitPeriod >= d.EndPeriod && - d.EndPeriod.Add(scheme.ProfitReceivingDuePeriodCount) < scheme.CurrentPeriod).ToList(); - foreach (var detail in oldProfitDetails) - { - currentProfitDetails.Details.Remove(detail); - } + if (scheme == null || currentDetail == null) return new Empty(); - State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary] = currentProfitDetails; + Assert(Context.Sender == scheme.Manager || Context.Sender == + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), + "Only manager can remove beneficiary."); - Context.LogDebug(() => - $"Added {input.BeneficiaryShare.Shares} weights to scheme {input.SchemeId.ToHex()}: {profitDetail}"); + var expiryDetails = scheme.CanRemoveBeneficiaryDirectly + ? currentDetail.Details.Where(d => !d.IsWeightRemoved).ToList() + : currentDetail.Details + .Where(d => d.EndPeriod < scheme.CurrentPeriod && !d.IsWeightRemoved).ToList(); - return new Empty(); - } + if (!expiryDetails.Any()) return new Empty(); - private void AssertValidInput(AddBeneficiaryInput input) + var shares = expiryDetails.Sum(d => d.Shares); + foreach (var expiryDetail in expiryDetails) { - Assert(input.SchemeId != null, "Invalid scheme id."); - Assert(input.BeneficiaryShare?.Beneficiary != null, "Invalid beneficiary address."); - Assert(input.BeneficiaryShare?.Shares >= 0, "Invalid share."); + expiryDetail.IsWeightRemoved = true; + if (expiryDetail.LastProfitPeriod >= scheme.CurrentPeriod) + currentDetail.Details.Remove(expiryDetail); + else if (expiryDetail.EndPeriod >= scheme.CurrentPeriod) + expiryDetail.EndPeriod = scheme.CurrentPeriod.Sub(1); } - public override Empty RemoveBeneficiary(RemoveBeneficiaryInput input) - { - Assert(input.SchemeId != null, "Invalid scheme id."); - Assert(input.Beneficiary != null, "Invalid Beneficiary address."); - - var scheme = State.SchemeInfos[input.SchemeId]; - - Assert(scheme != null, "Scheme not found."); + Context.LogDebug(() => $"ProfitDetails after removing expiry details: {currentDetail}"); - var currentDetail = State.ProfitDetailsMap[input.SchemeId][input.Beneficiary]; + // Clear old profit details. + if (currentDetail.Details.Count != 0) + State.ProfitDetailsMap[input.SchemeId][input.Beneficiary] = currentDetail; + else + State.ProfitDetailsMap[input.SchemeId].Remove(input.Beneficiary); - if (scheme == null || currentDetail == null) return new Empty(); + scheme.TotalShares = scheme.TotalShares.Sub(shares); + State.SchemeInfos[input.SchemeId] = scheme; - Assert(Context.Sender == scheme.Manager || Context.Sender == - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), - "Only manager can remove beneficiary."); + return new Empty(); + } - var expiryDetails = scheme.CanRemoveBeneficiaryDirectly - ? currentDetail.Details.Where(d => !d.IsWeightRemoved).ToList() - : currentDetail.Details - .Where(d => d.EndPeriod < scheme.CurrentPeriod && !d.IsWeightRemoved).ToList(); + public override Empty AddBeneficiaries(AddBeneficiariesInput input) + { + foreach (var beneficiaryShare in input.BeneficiaryShares) + AddBeneficiary(new AddBeneficiaryInput + { + SchemeId = input.SchemeId, + BeneficiaryShare = beneficiaryShare, + EndPeriod = input.EndPeriod + }); - if (!expiryDetails.Any()) return new Empty(); + return new Empty(); + } - var shares = expiryDetails.Sum(d => d.Shares); - foreach (var expiryDetail in expiryDetails) + public override Empty RemoveBeneficiaries(RemoveBeneficiariesInput input) + { + foreach (var beneficiary in input.Beneficiaries) + RemoveBeneficiary(new RemoveBeneficiaryInput { - expiryDetail.IsWeightRemoved = true; - if (expiryDetail.LastProfitPeriod >= scheme.CurrentPeriod) - { - currentDetail.Details.Remove(expiryDetail); - } - else if (expiryDetail.EndPeriod >= scheme.CurrentPeriod) - { - expiryDetail.EndPeriod = scheme.CurrentPeriod.Sub(1); - } - } + SchemeId = input.SchemeId, Beneficiary = beneficiary + }); - Context.LogDebug(() => $"ProfitDetails after removing expiry details: {currentDetail}"); + return new Empty(); + } - // Clear old profit details. - if (currentDetail.Details.Count != 0) - { - State.ProfitDetailsMap[input.SchemeId][input.Beneficiary] = currentDetail; - } - else - { - State.ProfitDetailsMap[input.SchemeId].Remove(input.Beneficiary); - } + /// + /// Will burn/destroy a certain amount of profits if `input.Period` is less than 0. + /// + /// + /// + public override Empty DistributeProfits(DistributeProfitsInput input) + { + if (input.AmountsMap.Any()) + Assert(input.AmountsMap.All(a => !string.IsNullOrEmpty(a.Key)), "Invalid token symbol."); - scheme.TotalShares = scheme.TotalShares.Sub(shares); - State.SchemeInfos[input.SchemeId] = scheme; + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); - return new Empty(); - } + // ReSharper disable once PossibleNullReferenceException + Assert(Context.Sender == scheme.Manager || Context.Sender == + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), + "Only manager can distribute profits."); - public override Empty AddBeneficiaries(AddBeneficiariesInput input) + ValidateContractState(State.TokenContract, SmartContractConstants.TokenContractSystemName); + + var profitsMap = new Dictionary(); + if (input.AmountsMap.Any()) { - foreach (var beneficiaryShare in input.BeneficiaryShares) + foreach (var amount in input.AmountsMap) { - AddBeneficiary(new AddBeneficiaryInput - { - SchemeId = input.SchemeId, - BeneficiaryShare = beneficiaryShare, - EndPeriod = input.EndPeriod - }); + var actualAmount = amount.Value == 0 + ? State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Owner = scheme.VirtualAddress, + Symbol = amount.Key + }).Balance + : amount.Value; + profitsMap.Add(amount.Key, actualAmount); } - - return new Empty(); } - - public override Empty RemoveBeneficiaries(RemoveBeneficiariesInput input) + else { - foreach (var beneficiary in input.Beneficiaries) - { - RemoveBeneficiary(new RemoveBeneficiaryInput + if (scheme.IsReleaseAllBalanceEveryTimeByDefault && scheme.ReceivedTokenSymbols.Any()) + // Prepare to distribute all from general ledger. + foreach (var symbol in scheme.ReceivedTokenSymbols) { - SchemeId = input.SchemeId, Beneficiary = beneficiary - }); - } - - return new Empty(); + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Owner = scheme.VirtualAddress, + Symbol = symbol + }).Balance; + profitsMap.Add(symbol, balance); + } } - /// - /// - /// Will burn/destroy a certain amount of profits if `input.Period` is less than 0. - /// - /// - /// - public override Empty DistributeProfits(DistributeProfitsInput input) - { - if (input.AmountsMap.Any()) - { - Assert(input.AmountsMap.All(a => !string.IsNullOrEmpty(a.Key)), "Invalid token symbol."); - } - - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); + var totalShares = scheme.TotalShares; - // ReSharper disable once PossibleNullReferenceException - Assert(Context.Sender == scheme.Manager || Context.Sender == - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), - "Only manager can distribute profits."); - - ValidateContractState(State.TokenContract, SmartContractConstants.TokenContractSystemName); - - var profitsMap = new Dictionary(); - if (input.AmountsMap.Any()) + if (scheme.DelayDistributePeriodCount > 0) + { + scheme.CachedDelayTotalShares.Add(input.Period.Add(scheme.DelayDistributePeriodCount), totalShares); + if (scheme.CachedDelayTotalShares.ContainsKey(input.Period)) { - foreach (var amount in input.AmountsMap) - { - var actualAmount = amount.Value == 0 - ? State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = scheme.VirtualAddress, - Symbol = amount.Key - }).Balance - : amount.Value; - profitsMap.Add(amount.Key, actualAmount); - } + totalShares = scheme.CachedDelayTotalShares[input.Period]; + scheme.CachedDelayTotalShares.Remove(input.Period); } else { - if (scheme.IsReleaseAllBalanceEveryTimeByDefault && scheme.ReceivedTokenSymbols.Any()) - { - // Prepare to distribute all from general ledger. - foreach (var symbol in scheme.ReceivedTokenSymbols) - { - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = scheme.VirtualAddress, - Symbol = symbol - }).Balance; - profitsMap.Add(symbol, balance); - } - } + totalShares = 0; } + } - var totalShares = scheme.TotalShares; - - if (scheme.DelayDistributePeriodCount > 0) - { - scheme.CachedDelayTotalShares.Add(input.Period.Add(scheme.DelayDistributePeriodCount), totalShares); - if (scheme.CachedDelayTotalShares.ContainsKey(input.Period)) - { - totalShares = scheme.CachedDelayTotalShares[input.Period]; - scheme.CachedDelayTotalShares.Remove(input.Period); - } - else - { - totalShares = 0; - } - } + var releasingPeriod = scheme.CurrentPeriod; + Assert(input.Period == releasingPeriod, + $"Invalid period. When release scheme {input.SchemeId.ToHex()} of period {input.Period}. Current period is {releasingPeriod}"); - var releasingPeriod = scheme.CurrentPeriod; - Assert(input.Period == releasingPeriod, - $"Invalid period. When release scheme {input.SchemeId.ToHex()} of period {input.Period}. Current period is {releasingPeriod}"); + var profitsReceivingVirtualAddress = + GetDistributedPeriodProfitsVirtualAddress(scheme.SchemeId, releasingPeriod); - var profitsReceivingVirtualAddress = - GetDistributedPeriodProfitsVirtualAddress(scheme.SchemeId, releasingPeriod); + if (input.Period < 0 || totalShares <= 0) + return BurnProfits(input.Period, profitsMap, scheme, profitsReceivingVirtualAddress); - if (input.Period < 0 || totalShares <= 0) - { - return BurnProfits(input.Period, profitsMap, scheme, profitsReceivingVirtualAddress); - } + Context.LogDebug(() => $"Receiving virtual address: {profitsReceivingVirtualAddress}"); - Context.LogDebug(() => $"Receiving virtual address: {profitsReceivingVirtualAddress}"); + UpdateDistributedProfits(profitsMap, profitsReceivingVirtualAddress, totalShares); - UpdateDistributedProfits(profitsMap, profitsReceivingVirtualAddress, totalShares); + PerformDistributeProfits(profitsMap, scheme, totalShares, profitsReceivingVirtualAddress); - PerformDistributeProfits(profitsMap, scheme, totalShares, profitsReceivingVirtualAddress); + scheme.CurrentPeriod = input.Period.Add(1); - scheme.CurrentPeriod = input.Period.Add(1); + State.SchemeInfos[input.SchemeId] = scheme; - State.SchemeInfos[input.SchemeId] = scheme; + return new Empty(); + } - return new Empty(); - } + /// + /// Just burn balance in general ledger. + /// + /// + /// + /// + /// + /// + private Empty BurnProfits(long period, Dictionary profitsMap, Scheme scheme, + Address profitsReceivingVirtualAddress) + { + scheme.CurrentPeriod = period.Add(1); - /// - /// Just burn balance in general ledger. - /// - /// - /// - /// - /// - /// - private Empty BurnProfits(long period, Dictionary profitsMap, Scheme scheme, - Address profitsReceivingVirtualAddress) + var distributedProfitsInfo = new DistributedProfitsInfo { - scheme.CurrentPeriod = period.Add(1); - - var distributedProfitsInfo = new DistributedProfitsInfo - { - IsReleased = true - }; - foreach (var profits in profitsMap) + IsReleased = true + }; + foreach (var profits in profitsMap) + { + var symbol = profits.Key; + var amount = profits.Value; + if (amount > 0) { - var symbol = profits.Key; - var amount = profits.Value; - if (amount > 0) + var balanceOfToken = State.TokenContract.GetBalance.Call(new GetBalanceInput { - var balanceOfToken = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = scheme.VirtualAddress, - Symbol = symbol - }); - if (balanceOfToken.Balance < amount) - continue; - Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, - nameof(State.TokenContract.Transfer), new TransferInput - { - To = Context.Self, - Amount = amount, - Symbol = symbol - }.ToByteString()); - State.TokenContract.Burn.Send(new BurnInput + Owner = scheme.VirtualAddress, + Symbol = symbol + }); + if (balanceOfToken.Balance < amount) + continue; + Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, + nameof(State.TokenContract.Transfer), new TransferInput { + To = Context.Self, Amount = amount, Symbol = symbol - }); - distributedProfitsInfo.AmountsMap.Add(symbol, -amount); - } + }.ToByteString()); + State.TokenContract.Burn.Send(new BurnInput + { + Amount = amount, + Symbol = symbol + }); + distributedProfitsInfo.AmountsMap.Add(symbol, -amount); } - - State.SchemeInfos[scheme.SchemeId] = scheme; - State.DistributedProfitsMap[profitsReceivingVirtualAddress] = distributedProfitsInfo; - return new Empty(); } - private void UpdateDistributedProfits(Dictionary profitsMap, - Address profitsReceivingVirtualAddress, long totalShares) - { - var distributedProfitsInformation = - State.DistributedProfitsMap[profitsReceivingVirtualAddress] ?? - new DistributedProfitsInfo(); + State.SchemeInfos[scheme.SchemeId] = scheme; + State.DistributedProfitsMap[profitsReceivingVirtualAddress] = distributedProfitsInfo; + return new Empty(); + } - distributedProfitsInformation.TotalShares = totalShares; - distributedProfitsInformation.IsReleased = true; + private void UpdateDistributedProfits(Dictionary profitsMap, + Address profitsReceivingVirtualAddress, long totalShares) + { + var distributedProfitsInformation = + State.DistributedProfitsMap[profitsReceivingVirtualAddress] ?? + new DistributedProfitsInfo(); - foreach (var profits in profitsMap) - { - var symbol = profits.Key; - var amount = profits.Value; - var balanceOfVirtualAddressForCurrentPeriod = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = profitsReceivingVirtualAddress, - Symbol = symbol - }).Balance; - distributedProfitsInformation.AmountsMap[symbol] = amount.Add(balanceOfVirtualAddressForCurrentPeriod); - } + distributedProfitsInformation.TotalShares = totalShares; + distributedProfitsInformation.IsReleased = true; - State.DistributedProfitsMap[profitsReceivingVirtualAddress] = distributedProfitsInformation; + foreach (var profits in profitsMap) + { + var symbol = profits.Key; + var amount = profits.Value; + var balanceOfVirtualAddressForCurrentPeriod = State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Owner = profitsReceivingVirtualAddress, + Symbol = symbol + }).Balance; + distributedProfitsInformation.AmountsMap[symbol] = amount.Add(balanceOfVirtualAddressForCurrentPeriod); } - private void PerformDistributeProfits(Dictionary profitsMap, Scheme scheme, long totalShares, - Address profitsReceivingVirtualAddress) + State.DistributedProfitsMap[profitsReceivingVirtualAddress] = distributedProfitsInformation; + } + + private void PerformDistributeProfits(Dictionary profitsMap, Scheme scheme, long totalShares, + Address profitsReceivingVirtualAddress) + { + foreach (var profits in profitsMap) { - foreach (var profits in profitsMap) - { - var symbol = profits.Key; - var amount = profits.Value; - var remainAmount = DistributeProfitsForSubSchemes(symbol, amount, scheme, totalShares); - Context.LogDebug(() => $"Distributing {remainAmount} {symbol} tokens."); - // Transfer remain amount to individuals' receiving profits address. - if (remainAmount != 0) - { - Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, - nameof(State.TokenContract.Transfer), new TransferInput - { - To = profitsReceivingVirtualAddress, - Amount = remainAmount, - Symbol = symbol - }.ToByteString()); - } - } + var symbol = profits.Key; + var amount = profits.Value; + var remainAmount = DistributeProfitsForSubSchemes(symbol, amount, scheme, totalShares); + Context.LogDebug(() => $"Distributing {remainAmount} {symbol} tokens."); + // Transfer remain amount to individuals' receiving profits address. + if (remainAmount != 0) + Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, + nameof(State.TokenContract.Transfer), new TransferInput + { + To = profitsReceivingVirtualAddress, + Amount = remainAmount, + Symbol = symbol + }.ToByteString()); } + } - private long DistributeProfitsForSubSchemes(string symbol, long totalAmount, Scheme scheme, long totalShares) + private long DistributeProfitsForSubSchemes(string symbol, long totalAmount, Scheme scheme, long totalShares) + { + Context.LogDebug(() => $"Sub schemes count: {scheme.SubSchemes.Count}"); + var remainAmount = totalAmount; + foreach (var subSchemeShares in scheme.SubSchemes) { - Context.LogDebug(() => $"Sub schemes count: {scheme.SubSchemes.Count}"); - var remainAmount = totalAmount; - foreach (var subSchemeShares in scheme.SubSchemes) - { - Context.LogDebug(() => $"Releasing {subSchemeShares.SchemeId}"); + Context.LogDebug(() => $"Releasing {subSchemeShares.SchemeId}"); - // General ledger of this sub profit scheme. - var subItemVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeShares.SchemeId); + // General ledger of this sub profit scheme. + var subItemVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subSchemeShares.SchemeId); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - var distributeAmount = SafeCalculateProfits(subSchemeShares.Shares, totalAmount, totalShares); - if (distributeAmount != 0) - { - Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, - nameof(State.TokenContract.Transfer), new TransferInput - { - To = subItemVirtualAddress, - Amount = distributeAmount, - Symbol = symbol - }.ToByteString()); - } + var distributeAmount = SafeCalculateProfits(subSchemeShares.Shares, totalAmount, totalShares); + if (distributeAmount != 0) + Context.SendVirtualInline(scheme.SchemeId, State.TokenContract.Value, + nameof(State.TokenContract.Transfer), new TransferInput + { + To = subItemVirtualAddress, + Amount = distributeAmount, + Symbol = symbol + }.ToByteString()); - remainAmount = remainAmount.Sub(distributeAmount); + remainAmount = remainAmount.Sub(distributeAmount); - // Update current_period of detail of sub profit scheme. - var subItemDetail = State.ProfitDetailsMap[scheme.SchemeId][subItemVirtualAddress]; - foreach (var detail in subItemDetail.Details) - { - detail.LastProfitPeriod = scheme.CurrentPeriod; - } + // Update current_period of detail of sub profit scheme. + var subItemDetail = State.ProfitDetailsMap[scheme.SchemeId][subItemVirtualAddress]; + foreach (var detail in subItemDetail.Details) detail.LastProfitPeriod = scheme.CurrentPeriod; - State.ProfitDetailsMap[scheme.SchemeId][subItemVirtualAddress] = subItemDetail; + State.ProfitDetailsMap[scheme.SchemeId][subItemVirtualAddress] = subItemDetail; - // Update sub scheme. - var subScheme = State.SchemeInfos[subSchemeShares.SchemeId]; - if (!subScheme.ReceivedTokenSymbols.Contains(symbol)) - { - subScheme.ReceivedTokenSymbols.Add(symbol); - State.SchemeInfos[subSchemeShares.SchemeId] = subScheme; - } + // Update sub scheme. + var subScheme = State.SchemeInfos[subSchemeShares.SchemeId]; + if (!subScheme.ReceivedTokenSymbols.Contains(symbol)) + { + subScheme.ReceivedTokenSymbols.Add(symbol); + State.SchemeInfos[subSchemeShares.SchemeId] = subScheme; } - - return remainAmount; } - public override Empty ContributeProfits(ContributeProfitsInput input) - { - Assert(!string.IsNullOrEmpty(input.Symbol), "Invalid token symbol."); - Assert(input.Amount > 0, "Amount need to greater than 0."); + return remainAmount; + } - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); + public override Empty ContributeProfits(ContributeProfitsInput input) + { + Assert(!string.IsNullOrEmpty(input.Symbol), "Invalid token symbol."); + Assert(input.Amount > 0, "Amount need to greater than 0."); - // ReSharper disable once PossibleNullReferenceException - var virtualAddress = scheme.VirtualAddress; + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); - if (input.Period == 0) - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + // ReSharper disable once PossibleNullReferenceException + var virtualAddress = scheme.VirtualAddress; - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = virtualAddress, - Symbol = input.Symbol, - Amount = input.Amount, - Memo = $"Add {input.Amount} dividends." - }); - } - else - { - Assert(input.Period >= scheme.CurrentPeriod, "Invalid contributing period."); - var distributedPeriodProfitsVirtualAddress = - GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); - - var distributedProfitsInformation = State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress]; - if (distributedProfitsInformation == null) - { - distributedProfitsInformation = new DistributedProfitsInfo - { - AmountsMap = {{input.Symbol, input.Amount}} - }; - } - else - { - Assert(!distributedProfitsInformation.IsReleased, - $"Scheme of period {input.Period} already released."); - distributedProfitsInformation.AmountsMap[input.Symbol] = - distributedProfitsInformation.AmountsMap[input.Symbol].Add(input.Amount); - } - - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = distributedPeriodProfitsVirtualAddress, - Symbol = input.Symbol, - Amount = input.Amount, - }); - - State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress] = distributedProfitsInformation; - } + if (input.Period == 0) + { + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - // If someone directly use virtual address to do the contribution, won't sense the token symbol he was using. - if (!scheme.ReceivedTokenSymbols.Contains(input.Symbol)) + State.TokenContract.TransferFrom.Send(new TransferFromInput { - scheme.ReceivedTokenSymbols.Add(input.Symbol); - } - - State.SchemeInfos[scheme.SchemeId] = scheme; - - return new Empty(); + From = Context.Sender, + To = virtualAddress, + Symbol = input.Symbol, + Amount = input.Amount, + Memo = $"Add {input.Amount} dividends." + }); } - - public override Empty ResetManager(ResetManagerInput input) + else { - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); - - // ReSharper disable once PossibleNullReferenceException - Assert(Context.Sender == scheme.Manager, "Only scheme manager can reset manager."); - Assert(input.NewManager.Value.Any(), "Invalid new sponsor."); - - // Transfer managing scheme id. - var oldManagerSchemeIds = State.ManagingSchemeIds[scheme.Manager]; - oldManagerSchemeIds.SchemeIds.Remove(input.SchemeId); - State.ManagingSchemeIds[scheme.Manager] = oldManagerSchemeIds; - var newManagerSchemeIds = State.ManagingSchemeIds[input.NewManager] ?? new CreatedSchemeIds(); - newManagerSchemeIds.SchemeIds.Add(input.SchemeId); - State.ManagingSchemeIds[input.NewManager] = newManagerSchemeIds; - - scheme.Manager = input.NewManager; - State.SchemeInfos[input.SchemeId] = scheme; - return new Empty(); - } + Assert(input.Period >= scheme.CurrentPeriod, "Invalid contributing period."); + var distributedPeriodProfitsVirtualAddress = + GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); - /// - /// Gain the profit form SchemeId from Details.lastPeriod to scheme.currentPeriod - 1; - /// - /// ClaimProfitsInput - /// - public override Empty ClaimProfits(ClaimProfitsInput input) - { - var scheme = State.SchemeInfos[input.SchemeId]; - if (scheme == null) + var distributedProfitsInformation = State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress]; + if (distributedProfitsInformation == null) { - throw new AssertionException("Scheme not found."); + distributedProfitsInformation = new DistributedProfitsInfo + { + AmountsMap = { { input.Symbol, input.Amount } } + }; } - var beneficiary = input.Beneficiary ?? Context.Sender; - var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; - if (profitDetails == null) + else { - throw new AssertionException("Profit details not found."); + Assert(!distributedProfitsInformation.IsReleased, + $"Scheme of period {input.Period} already released."); + distributedProfitsInformation.AmountsMap[input.Symbol] = + distributedProfitsInformation.AmountsMap[input.Symbol].Add(input.Amount); } - Context.LogDebug( - () => $"{Context.Sender} is trying to profit from {input.SchemeId.ToHex()} for {beneficiary}."); + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + From = Context.Sender, + To = distributedPeriodProfitsVirtualAddress, + Symbol = input.Symbol, + Amount = input.Amount + }); - var availableDetails = profitDetails.Details.Where(d => - d.LastProfitPeriod == 0 ? d.EndPeriod >= d.StartPeriod : d.EndPeriod >= d.LastProfitPeriod).ToList(); - var profitableDetails = availableDetails.Where(d => d.LastProfitPeriod < scheme.CurrentPeriod).ToList(); + State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress] = distributedProfitsInformation; + } - Context.LogDebug(() => - $"Profitable details: {profitableDetails.Aggregate("\n", (profit1, profit2) => profit1.ToString() + "\n" + profit2)}"); + // If someone directly use virtual address to do the contribution, won't sense the token symbol he was using. + if (!scheme.ReceivedTokenSymbols.Contains(input.Symbol)) scheme.ReceivedTokenSymbols.Add(input.Symbol); - // Only can get profit from last profit period to actual last period (profit.CurrentPeriod - 1), - // because current period not released yet. - for (var i = 0; - i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, profitableDetails.Count); - i++) - { - var profitDetail = profitableDetails[i]; - if (profitDetail.LastProfitPeriod == 0) - { - // This detail never performed profit before. - profitDetail.LastProfitPeriod = profitDetail.StartPeriod; - } + State.SchemeInfos[scheme.SchemeId] = scheme; - ProfitAllPeriods(scheme, profitDetail, beneficiary); - } + return new Empty(); + } - State.ProfitDetailsMap[input.SchemeId][beneficiary] = new ProfitDetails {Details = {availableDetails}}; + public override Empty ResetManager(ResetManagerInput input) + { + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); + + // ReSharper disable once PossibleNullReferenceException + Assert(Context.Sender == scheme.Manager, "Only scheme manager can reset manager."); + Assert(input.NewManager.Value.Any(), "Invalid new sponsor."); + + // Transfer managing scheme id. + var oldManagerSchemeIds = State.ManagingSchemeIds[scheme.Manager]; + oldManagerSchemeIds.SchemeIds.Remove(input.SchemeId); + State.ManagingSchemeIds[scheme.Manager] = oldManagerSchemeIds; + var newManagerSchemeIds = State.ManagingSchemeIds[input.NewManager] ?? new CreatedSchemeIds(); + newManagerSchemeIds.SchemeIds.Add(input.SchemeId); + State.ManagingSchemeIds[input.NewManager] = newManagerSchemeIds; + + scheme.Manager = input.NewManager; + State.SchemeInfos[input.SchemeId] = scheme; + return new Empty(); + } + + /// + /// Gain the profit form SchemeId from Details.lastPeriod to scheme.currentPeriod - 1; + /// + /// ClaimProfitsInput + /// + public override Empty ClaimProfits(ClaimProfitsInput input) + { + var scheme = State.SchemeInfos[input.SchemeId]; + if (scheme == null) throw new AssertionException("Scheme not found."); + var beneficiary = input.Beneficiary ?? Context.Sender; + var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; + if (profitDetails == null) throw new AssertionException("Profit details not found."); + + Context.LogDebug( + () => $"{Context.Sender} is trying to profit from {input.SchemeId.ToHex()} for {beneficiary}."); + + var availableDetails = profitDetails.Details.Where(d => + d.LastProfitPeriod == 0 ? d.EndPeriod >= d.StartPeriod : d.EndPeriod >= d.LastProfitPeriod).ToList(); + var profitableDetails = availableDetails.Where(d => d.LastProfitPeriod < scheme.CurrentPeriod).ToList(); + + Context.LogDebug(() => + $"Profitable details: {profitableDetails.Aggregate("\n", (profit1, profit2) => profit1.ToString() + "\n" + profit2)}"); + + // Only can get profit from last profit period to actual last period (profit.CurrentPeriod - 1), + // because current period not released yet. + for (var i = 0; + i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, profitableDetails.Count); + i++) + { + var profitDetail = profitableDetails[i]; + if (profitDetail.LastProfitPeriod == 0) + // This detail never performed profit before. + profitDetail.LastProfitPeriod = profitDetail.StartPeriod; - return new Empty(); + ProfitAllPeriods(scheme, profitDetail, beneficiary); } - private Dictionary ProfitAllPeriods(Scheme scheme, ProfitDetail profitDetail, Address beneficiary, - bool isView = false, string targetSymbol = null) - { - var profitsMap = new Dictionary(); - var lastProfitPeriod = profitDetail.LastProfitPeriod; + State.ProfitDetailsMap[input.SchemeId][beneficiary] = new ProfitDetails { Details = { availableDetails } }; - var symbols = targetSymbol == null ? scheme.ReceivedTokenSymbols.ToList() : new List {targetSymbol}; + return new Empty(); + } - foreach (var symbol in symbols) - { - var totalAmount = 0L; - for (var period = profitDetail.LastProfitPeriod; - period <= (profitDetail.EndPeriod == long.MaxValue - ? Math.Min(scheme.CurrentPeriod - 1, - profitDetail.LastProfitPeriod.Add(ProfitContractConstants - .MaximumProfitReceivingPeriodCountOfOneTime)) - : Math.Min(scheme.CurrentPeriod - 1, profitDetail.EndPeriod)); - period++) - { - var periodToPrint = period; - var detailToPrint = profitDetail; - var distributedPeriodProfitsVirtualAddress = - GetDistributedPeriodProfitsVirtualAddress(scheme.SchemeId, period); - var distributedProfitsInformation = - State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress]; - if (distributedProfitsInformation == null || distributedProfitsInformation.TotalShares == 0 || - !distributedProfitsInformation.AmountsMap.Any() || - !distributedProfitsInformation.AmountsMap.ContainsKey(symbol)) - { - continue; - } + private Dictionary ProfitAllPeriods(Scheme scheme, ProfitDetail profitDetail, Address beneficiary, + bool isView = false, string targetSymbol = null) + { + var profitsMap = new Dictionary(); + var lastProfitPeriod = profitDetail.LastProfitPeriod; - var amount = SafeCalculateProfits(profitDetail.Shares, - distributedProfitsInformation.AmountsMap[symbol], distributedProfitsInformation.TotalShares); + var symbols = targetSymbol == null ? scheme.ReceivedTokenSymbols.ToList() : new List { targetSymbol }; - if (!isView) + foreach (var symbol in symbols) + { + var totalAmount = 0L; + for (var period = profitDetail.LastProfitPeriod; + period <= (profitDetail.EndPeriod == long.MaxValue + ? Math.Min(scheme.CurrentPeriod - 1, + profitDetail.LastProfitPeriod.Add(ProfitContractConstants + .MaximumProfitReceivingPeriodCountOfOneTime)) + : Math.Min(scheme.CurrentPeriod - 1, profitDetail.EndPeriod)); + period++) + { + var periodToPrint = period; + var detailToPrint = profitDetail; + var distributedPeriodProfitsVirtualAddress = + GetDistributedPeriodProfitsVirtualAddress(scheme.SchemeId, period); + var distributedProfitsInformation = + State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress]; + if (distributedProfitsInformation == null || distributedProfitsInformation.TotalShares == 0 || + !distributedProfitsInformation.AmountsMap.Any() || + !distributedProfitsInformation.AmountsMap.ContainsKey(symbol)) + continue; + + var amount = SafeCalculateProfits(profitDetail.Shares, + distributedProfitsInformation.AmountsMap[symbol], distributedProfitsInformation.TotalShares); + + if (!isView) + { + Context.LogDebug(() => + $"{beneficiary} is profiting {amount} {symbol} tokens from {scheme.SchemeId.ToHex()} in period {periodToPrint}." + + $"Sender's Shares: {detailToPrint.Shares}, total Shares: {distributedProfitsInformation.TotalShares}"); + if (distributedProfitsInformation.IsReleased && amount > 0) { - Context.LogDebug(() => - $"{beneficiary} is profiting {amount} {symbol} tokens from {scheme.SchemeId.ToHex()} in period {periodToPrint}." + - $"Sender's Shares: {detailToPrint.Shares}, total Shares: {distributedProfitsInformation.TotalShares}"); - if (distributedProfitsInformation.IsReleased && amount > 0) - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Context.SendVirtualInline( - GeneratePeriodVirtualAddressFromHash(scheme.SchemeId, period), - State.TokenContract.Value, - nameof(State.TokenContract.Transfer), new TransferInput - { - To = beneficiary, - Symbol = symbol, - Amount = amount - }.ToByteString()); - - Context.Fire(new ProfitsClaimed + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Context.SendVirtualInline( + GeneratePeriodVirtualAddressFromHash(scheme.SchemeId, period), + State.TokenContract.Value, + nameof(State.TokenContract.Transfer), new TransferInput { - Beneficiary = beneficiary, + To = beneficiary, Symbol = symbol, - Amount = amount, - ClaimerShares = detailToPrint.Shares, - TotalShares = distributedProfitsInformation.TotalShares, - Period = periodToPrint - }); - } - - lastProfitPeriod = period + 1; + Amount = amount + }.ToByteString()); + + Context.Fire(new ProfitsClaimed + { + Beneficiary = beneficiary, + Symbol = symbol, + Amount = amount, + ClaimerShares = detailToPrint.Shares, + TotalShares = distributedProfitsInformation.TotalShares, + Period = periodToPrint + }); } - totalAmount = totalAmount.Add(amount); + lastProfitPeriod = period + 1; } - profitsMap.Add(symbol, totalAmount); + totalAmount = totalAmount.Add(amount); } - profitDetail.LastProfitPeriod = lastProfitPeriod; - - return profitsMap; + profitsMap.Add(symbol, totalAmount); } - private void ValidateContractState(ContractReferenceState state, string contractSystemName) - { - if (state.Value != null) - return; - state.Value = Context.GetContractAddressByName(contractSystemName); - } + profitDetail.LastProfitPeriod = lastProfitPeriod; - private Scheme GetNewScheme(CreateSchemeInput input, Hash schemeId, Address manager) - { - var scheme = new Scheme - { - SchemeId = schemeId, - // The address of general ledger for current profit scheme. - VirtualAddress = Context.ConvertVirtualAddressToContractAddress(schemeId), - Manager = manager, - ProfitReceivingDuePeriodCount = input.ProfitReceivingDuePeriodCount, - CurrentPeriod = 1, - IsReleaseAllBalanceEveryTimeByDefault = input.IsReleaseAllBalanceEveryTimeByDefault, - DelayDistributePeriodCount = input.DelayDistributePeriodCount, - CanRemoveBeneficiaryDirectly = input.CanRemoveBeneficiaryDirectly - }; + return profitsMap; + } - return scheme; - } + private void ValidateContractState(ContractReferenceState state, string contractSystemName) + { + if (state.Value != null) + return; + state.Value = Context.GetContractAddressByName(contractSystemName); + } - private static long SafeCalculateProfits(long totalAmount, long shares, long totalShares) + private Scheme GetNewScheme(CreateSchemeInput input, Hash schemeId, Address manager) + { + var scheme = new Scheme { - var decimalTotalAmount = (decimal) totalAmount; - var decimalShares = (decimal) shares; - var decimalTotalShares = (decimal) totalShares; - return (long) (decimalTotalAmount * decimalShares / decimalTotalShares); - } + SchemeId = schemeId, + // The address of general ledger for current profit scheme. + VirtualAddress = Context.ConvertVirtualAddressToContractAddress(schemeId), + Manager = manager, + ProfitReceivingDuePeriodCount = input.ProfitReceivingDuePeriodCount, + CurrentPeriod = 1, + IsReleaseAllBalanceEveryTimeByDefault = input.IsReleaseAllBalanceEveryTimeByDefault, + DelayDistributePeriodCount = input.DelayDistributePeriodCount, + CanRemoveBeneficiaryDirectly = input.CanRemoveBeneficiaryDirectly + }; + + return scheme; + } - private Hash GenerateSchemeId(CreateSchemeInput createSchemeInput) - { - var manager = createSchemeInput.Manager ?? Context.Sender; - if (createSchemeInput.Token != null) - return Context.GenerateId(Context.Self, createSchemeInput.Token); - var createdSchemeCount = State.ManagingSchemeIds[manager]?.SchemeIds.Count ?? 0; - return Context.GenerateId(Context.Self, createdSchemeCount.ToBytes(false)); - } + private static long SafeCalculateProfits(long totalAmount, long shares, long totalShares) + { + var decimalTotalAmount = (decimal)totalAmount; + var decimalShares = (decimal)shares; + var decimalTotalShares = (decimal)totalShares; + return (long)(decimalTotalAmount * decimalShares / decimalTotalShares); + } + + private Hash GenerateSchemeId(CreateSchemeInput createSchemeInput) + { + var manager = createSchemeInput.Manager ?? Context.Sender; + if (createSchemeInput.Token != null) + return Context.GenerateId(Context.Self, createSchemeInput.Token); + var createdSchemeCount = State.ManagingSchemeIds[manager]?.SchemeIds.Count ?? 0; + return Context.GenerateId(Context.Self, createdSchemeCount.ToBytes(false)); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/ProfitContractConstants.cs b/contract/AElf.Contracts.Profit/ProfitContractConstants.cs index 53f4a27415..59b80b971f 100644 --- a/contract/AElf.Contracts.Profit/ProfitContractConstants.cs +++ b/contract/AElf.Contracts.Profit/ProfitContractConstants.cs @@ -1,11 +1,10 @@ -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public class ProfitContractConstants { - public class ProfitContractConstants - { - public const int ProfitReceivingLimitForEachTime = 10; - public const int DefaultProfitReceivingDuePeriodCount = 10; - public const int MaximumProfitReceivingDuePeriodCount = 1024; - public const int TokenAmountLimit = 5; - public const int MaximumProfitReceivingPeriodCountOfOneTime = 100; - } + public const int ProfitReceivingLimitForEachTime = 10; + public const int DefaultProfitReceivingDuePeriodCount = 10; + public const int MaximumProfitReceivingDuePeriodCount = 1024; + public const int TokenAmountLimit = 5; + public const int MaximumProfitReceivingPeriodCountOfOneTime = 100; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/ProfitContractState.cs b/contract/AElf.Contracts.Profit/ProfitContractState.cs index db2453689c..7a525e3ff6 100644 --- a/contract/AElf.Contracts.Profit/ProfitContractState.cs +++ b/contract/AElf.Contracts.Profit/ProfitContractState.cs @@ -1,21 +1,20 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public partial class ProfitContractState : ContractState { - public partial class ProfitContractState : ContractState - { - public MappedState SchemeInfos { get; set; } + public MappedState SchemeInfos { get; set; } + + public MappedState DistributedProfitsMap { get; set; } - public MappedState DistributedProfitsMap { get; set; } + public MappedState ProfitDetailsMap { get; set; } - public MappedState ProfitDetailsMap { get; set; } + public MappedState ManagingSchemeIds { get; set; } - public MappedState ManagingSchemeIds { get; set; } - - public MappedState TransactionFees { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/ProfitContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Profit/ProfitContract_ACS1_TransactionFeeProvider.cs index a341efa9d0..8fed60b59e 100644 --- a/contract/AElf.Contracts.Profit/ProfitContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Profit/ProfitContract_ACS1_TransactionFeeProvider.cs @@ -1,119 +1,109 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public partial class ProfitContract { - public partial class ProfitContract + public override Empty SetMethodFee(MethodFees input) + { + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + Assert(input.Fees.Count <= ProfitContractConstants.TokenAmountLimit, "Invalid input."); + RequiredMethodFeeControllerSet(); + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; + + return new Empty(); + } + + public override Empty ChangeMethodFeeController(AuthorityInfo input) { - #region Views + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + + State.MethodFeeController.Value = input; + return new Empty(); + } + + #region Views - public override MethodFees GetMethodFee(StringValue input) + public override MethodFees GetMethodFee(StringValue input) + { + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) return methodFees; + + switch (input.Value) { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - { - return methodFees; - } - - switch (input.Value) - { - case nameof(CreateScheme): - return new MethodFees + case nameof(CreateScheme): + return new MethodFees + { + Fees = { - Fees = - { - new MethodFee {Symbol = Context.Variables.NativeSymbol, BasicFee = 10_00000000} - } - }; - default: - return new MethodFees + new MethodFee { Symbol = Context.Variables.NativeSymbol, BasicFee = 10_00000000 } + } + }; + default: + return new MethodFees + { + Fees = { - Fees = - { - new MethodFee {Symbol = Context.Variables.NativeSymbol, BasicFee = 1_00000000} - } - }; - } - } - - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; + new MethodFee { Symbol = Context.Variables.NativeSymbol, BasicFee = 1_00000000 } + } + }; } + } - #endregion - - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - Assert(input.Fees.Count <= ProfitContractConstants.TokenAmountLimit, "Invalid input."); - RequiredMethodFeeControllerSet(); - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; - - return new Empty(); - } + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #endregion - State.MethodFeeController.Value = input; - return new Empty(); - } + #region private methods - #region private methods + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + ValidateContractState(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - private void RequiredMethodFeeControllerSet() + var defaultAuthority = new AuthorityInfo { - if (State.MethodFeeController.Value != null) return; - ValidateContractState(State.ParliamentContract, SmartContractConstants.ParliamentContractSystemName); - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - State.MethodFeeController.Value = defaultAuthority; - } + State.MethodFeeController.Value = defaultAuthority; + } - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - #endregion + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Profit/README.md b/contract/AElf.Contracts.Profit/README.md index 2d0eb5da19..869e19521d 100644 --- a/contract/AElf.Contracts.Profit/README.md +++ b/contract/AElf.Contracts.Profit/README.md @@ -10,7 +10,8 @@ Call `CreateScheme` and provide the token symbol you gonna use in this item. Als -## Actions +## Actions +
InitializeProfitContract @@ -41,9 +42,11 @@ For anyone to create a `ProfitItem`. ### Notes -- A `ProfitItem` will be identified by a Hash value which called `SchemeId`. This Hash value is calculated from `TransactionId` of `CreateScheme` transction and the address of `Profit Contract`. +- A `ProfitItem` will be identified by a Hash value which called `SchemeId`. This Hash value is calculated + from `TransactionId` of `CreateScheme` transction and the address of `Profit Contract`. -- To create a `ProfitItem`, the creator need to provide its binded token symbol. Like for item `Treasury` created by `AElf Consensus Contract`, the binded token symbol is `ELF`. +- To create a `ProfitItem`, the creator need to provide its binded token symbol. Like for item `Treasury` created + by `AElf Consensus Contract`, the binded token symbol is `ELF`. - `ExpiredPeriodNumber` is optional. @@ -63,7 +66,8 @@ For a profit scheme `Creator` to register a `SubProfitScheme` to one `ProfitSche - Sender must be the `Creator` of the `ProfitItem` to register to. -- To register a `ProfitItem` as `SubProfitItem`, sender should provide `SchemeId`s of two `ProfitItem`s and the `Shares` of `SubProfitItem`. +- To register a `ProfitItem` as `SubProfitItem`, sender should provide `SchemeId`s of two `ProfitItem`s and the `Shares` + of `SubProfitItem`. - This method will actually call `AddBeneficiary` to add the `Shares` of `SubProfitItem`. @@ -83,7 +87,8 @@ For a profit scheme `Creator` to add an Address to receive profits of one `Profi - `TotalShares` of this `ProfitItem` will be increased. -- Will add a `ProfitDetail` to record this addition for Beneficiary address to profit from this `ProfitItem` in the future. +- Will add a `ProfitDetail` to record this addition for Beneficiary address to profit from this `ProfitItem` in the + future. - Will remove expired `ProfitDetail`s. @@ -107,7 +112,8 @@ For a profit scheme `Creator` to remove an Address to receive profits of one `Pr ### Purpose -For a profit scheme `Creator` to release an amount of profits to a virtual address calculated by `ProfitItem` and current period number. +For a profit scheme `Creator` to release an amount of profits to a virtual address calculated by `ProfitItem` and +current period number. If this `ProfitItem` has `SubProfitItem`s, transfer tokens to `SubProfitItem`s' virtual addresses. diff --git a/contract/AElf.Contracts.Profit/ViewMethods.cs b/contract/AElf.Contracts.Profit/ViewMethods.cs index 7e2e3cbc1b..31d8c0d4d6 100644 --- a/contract/AElf.Contracts.Profit/ViewMethods.cs +++ b/contract/AElf.Contracts.Profit/ViewMethods.cs @@ -5,147 +5,132 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public partial class ProfitContract { - public partial class ProfitContract + public override CreatedSchemeIds GetManagingSchemeIds(GetManagingSchemeIdsInput input) { - public override CreatedSchemeIds GetManagingSchemeIds(GetManagingSchemeIdsInput input) - { - return State.ManagingSchemeIds[input.Manager]; - } + return State.ManagingSchemeIds[input.Manager]; + } - public override Scheme GetScheme(Hash input) - { - return State.SchemeInfos[input]; - } + public override Scheme GetScheme(Hash input) + { + return State.SchemeInfos[input]; + } - /// - /// If input.Period == 0, the result will be the address of general ledger of a certain profit scheme; - /// Otherwise the result will be the address of a specific account period of a certain profit scheme, - /// which profit receivers will gain profits from. - /// - /// - /// - public override Address GetSchemeAddress(SchemePeriod input) - { - var virtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); - return input.Period == 0 - ? virtualAddress - : GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); - } + /// + /// If input.Period == 0, the result will be the address of general ledger of a certain profit scheme; + /// Otherwise the result will be the address of a specific account period of a certain profit scheme, + /// which profit receivers will gain profits from. + /// + /// + /// + public override Address GetSchemeAddress(SchemePeriod input) + { + var virtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); + return input.Period == 0 + ? virtualAddress + : GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); + } - public override DistributedProfitsInfo GetDistributedProfitsInfo(SchemePeriod input) + public override DistributedProfitsInfo GetDistributedProfitsInfo(SchemePeriod input) + { + var releasedProfitsVirtualAddress = GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); + return State.DistributedProfitsMap[releasedProfitsVirtualAddress] ?? new DistributedProfitsInfo { - var releasedProfitsVirtualAddress = GetDistributedPeriodProfitsVirtualAddress(input.SchemeId, input.Period); - return State.DistributedProfitsMap[releasedProfitsVirtualAddress] ?? new DistributedProfitsInfo - { - TotalShares = -1 - }; - } + TotalShares = -1 + }; + } - public override ProfitDetails GetProfitDetails(GetProfitDetailsInput input) - { - return State.ProfitDetailsMap[input.SchemeId][input.Beneficiary]; - } + public override ProfitDetails GetProfitDetails(GetProfitDetailsInput input) + { + return State.ProfitDetailsMap[input.SchemeId][input.Beneficiary]; + } - private Address GetDistributedPeriodProfitsVirtualAddress(Hash schemeId, long period) - { - return Context.ConvertVirtualAddressToContractAddress( - GeneratePeriodVirtualAddressFromHash(schemeId, period)); - } + private Address GetDistributedPeriodProfitsVirtualAddress(Hash schemeId, long period) + { + return Context.ConvertVirtualAddressToContractAddress( + GeneratePeriodVirtualAddressFromHash(schemeId, period)); + } + + private Hash GeneratePeriodVirtualAddressFromHash(Hash schemeId, long period) + { + return HashHelper.XorAndCompute(schemeId, HashHelper.ComputeFrom(period)); + } + + public override Int64Value GetProfitAmount(GetProfitAmountInput input) + { + var profitItem = State.SchemeInfos[input.SchemeId]; + Assert(profitItem != null, "Scheme not found."); + var beneficiary = input.Beneficiary ?? Context.Sender; + var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; - private Hash GeneratePeriodVirtualAddressFromHash(Hash schemeId, long period) + if (profitDetails == null) return new Int64Value { Value = 0 }; + + var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); + + // ReSharper disable once PossibleNullReferenceException + var availableDetails = profitDetails.Details.Where(d => + d.LastProfitPeriod < profitItem.CurrentPeriod && (d.LastProfitPeriod == 0 + ? d.EndPeriod >= d.StartPeriod + : d.EndPeriod >= d.LastProfitPeriod) + ).ToList(); + + var amount = 0L; + + for (var i = 0; + i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, availableDetails.Count); + i++) { - return HashHelper.XorAndCompute(schemeId, HashHelper.ComputeFrom(period)); + var profitDetail = availableDetails[i]; + if (profitDetail.LastProfitPeriod == 0) profitDetail.LastProfitPeriod = profitDetail.StartPeriod; + + var profitsDict = ProfitAllPeriods(profitItem, profitDetail, beneficiary, true, + input.Symbol); + amount = amount.Add(profitsDict[input.Symbol]); } - public override Int64Value GetProfitAmount(GetProfitAmountInput input) + return new Int64Value { Value = amount }; + } + + public override ReceivedProfitsMap GetProfitsMap(ClaimProfitsInput input) + { + var scheme = State.SchemeInfos[input.SchemeId]; + Assert(scheme != null, "Scheme not found."); + var beneficiary = input.Beneficiary ?? Context.Sender; + var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; + + if (profitDetails == null) return new ReceivedProfitsMap(); + + var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); + + // ReSharper disable once PossibleNullReferenceException + var availableDetails = profitDetails.Details.Where(d => + d.LastProfitPeriod < scheme.CurrentPeriod && (d.LastProfitPeriod == 0 + ? d.EndPeriod >= d.StartPeriod + : d.EndPeriod >= d.LastProfitPeriod) + ).ToList(); + + var profitsDict = new Dictionary(); + for (var i = 0; + i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, availableDetails.Count); + i++) { - var profitItem = State.SchemeInfos[input.SchemeId]; - Assert(profitItem != null, "Scheme not found."); - var beneficiary = input.Beneficiary ?? Context.Sender; - var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; - - if (profitDetails == null) - { - return new Int64Value {Value = 0}; - } - - var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); - - // ReSharper disable once PossibleNullReferenceException - var availableDetails = profitDetails.Details.Where(d => - d.LastProfitPeriod < profitItem.CurrentPeriod && (d.LastProfitPeriod == 0 - ? d.EndPeriod >= d.StartPeriod - : d.EndPeriod >= d.LastProfitPeriod) - ).ToList(); - - var amount = 0L; - - for (var i = 0; - i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, availableDetails.Count); - i++) - { - var profitDetail = availableDetails[i]; - if (profitDetail.LastProfitPeriod == 0) - { - profitDetail.LastProfitPeriod = profitDetail.StartPeriod; - } - - var profitsDict = ProfitAllPeriods(profitItem, profitDetail, beneficiary, true, - input.Symbol); - amount = amount.Add(profitsDict[input.Symbol]); - } - - return new Int64Value {Value = amount}; + var profitDetail = availableDetails[i]; + if (profitDetail.LastProfitPeriod == 0) profitDetail.LastProfitPeriod = profitDetail.StartPeriod; + + var profitsDictForEachProfitDetail = ProfitAllPeriods(scheme, profitDetail, beneficiary, true); + foreach (var kv in profitsDictForEachProfitDetail) + if (profitsDict.ContainsKey(kv.Key)) + profitsDict[kv.Key] = profitsDict[kv.Key].Add(kv.Value); + else + profitsDict[kv.Key] = kv.Value; } - public override ReceivedProfitsMap GetProfitsMap(ClaimProfitsInput input) + return new ReceivedProfitsMap { - var scheme = State.SchemeInfos[input.SchemeId]; - Assert(scheme != null, "Scheme not found."); - var beneficiary = input.Beneficiary ?? Context.Sender; - var profitDetails = State.ProfitDetailsMap[input.SchemeId][beneficiary]; - - if (profitDetails == null) - { - return new ReceivedProfitsMap(); - } - - var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.SchemeId); - - // ReSharper disable once PossibleNullReferenceException - var availableDetails = profitDetails.Details.Where(d => - d.LastProfitPeriod < scheme.CurrentPeriod && (d.LastProfitPeriod == 0 - ? d.EndPeriod >= d.StartPeriod - : d.EndPeriod >= d.LastProfitPeriod) - ).ToList(); - - var profitsDict = new Dictionary(); - for (var i = 0; - i < Math.Min(ProfitContractConstants.ProfitReceivingLimitForEachTime, availableDetails.Count); - i++) - { - var profitDetail = availableDetails[i]; - if (profitDetail.LastProfitPeriod == 0) - { - profitDetail.LastProfitPeriod = profitDetail.StartPeriod; - } - - var profitsDictForEachProfitDetail = ProfitAllPeriods(scheme, profitDetail, beneficiary, true); - foreach (var kv in profitsDictForEachProfitDetail) - { - if (profitsDict.ContainsKey(kv.Key)) - profitsDict[kv.Key] = profitsDict[kv.Key].Add(kv.Value); - else - profitsDict[kv.Key] = kv.Value; - } - } - - return new ReceivedProfitsMap - { - Value = {profitsDict} - }; - } + Value = { profitsDict } + }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Referendum/AElf.Contracts.Referendum.csproj b/contract/AElf.Contracts.Referendum/AElf.Contracts.Referendum.csproj index 09735aa5f4..a59a11dedb 100644 --- a/contract/AElf.Contracts.Referendum/AElf.Contracts.Referendum.csproj +++ b/contract/AElf.Contracts.Referendum/AElf.Contracts.Referendum.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Referendum true - Referendum is a contract that enables the creation of organizations and approvals. The created - proposals can be voted for and eventually released. + Referendum is a contract that enables the creation of organizations and approvals. The created + proposals can be voted for and eventually released. + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\token_contract.proto diff --git a/contract/AElf.Contracts.Referendum/ProposerWhiteListExtensions.cs b/contract/AElf.Contracts.Referendum/ProposerWhiteListExtensions.cs index 7e26f7e220..32a6aac37d 100644 --- a/contract/AElf.Contracts.Referendum/ProposerWhiteListExtensions.cs +++ b/contract/AElf.Contracts.Referendum/ProposerWhiteListExtensions.cs @@ -1,23 +1,22 @@ using AElf.Standards.ACS3; using AElf.Types; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public static class ProposerWhiteListExtensions { - public static class ProposerWhiteListExtensions + public static int Count(this ProposerWhiteList proposerWhiteList) { - public static int Count(this ProposerWhiteList proposerWhiteList) - { - return proposerWhiteList.Proposers.Count; - } + return proposerWhiteList.Proposers.Count; + } - public static bool Empty(this ProposerWhiteList proposerWhiteList) - { - return proposerWhiteList.Count() == 0; - } + public static bool Empty(this ProposerWhiteList proposerWhiteList) + { + return proposerWhiteList.Count() == 0; + } - public static bool Contains(this ProposerWhiteList proposerWhiteList, Address address) - { - return proposerWhiteList.Proposers.Contains(address); - } + public static bool Contains(this ProposerWhiteList proposerWhiteList, Address address) + { + return proposerWhiteList.Proposers.Contains(address); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Referendum/Referendum.cs b/contract/AElf.Contracts.Referendum/Referendum.cs index 8988553b5c..f6112e2827 100644 --- a/contract/AElf.Contracts.Referendum/Referendum.cs +++ b/contract/AElf.Contracts.Referendum/Referendum.cs @@ -1,242 +1,236 @@ using System.Linq; -using AElf.Standards.ACS3; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public partial class ReferendumContract : ReferendumContractImplContainer.ReferendumContractImplBase { - public partial class ReferendumContract : ReferendumContractImplContainer.ReferendumContractImplBase + public override Address CreateOrganization(CreateOrganizationInput input) { - #region View + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + var organizationHash = organizationHashAddressPair.OrganizationHash; + if (State.Organizations[organizationAddress] != null) + return organizationAddress; + var organization = new Organization + { + ProposalReleaseThreshold = input.ProposalReleaseThreshold, + OrganizationAddress = organizationAddress, + TokenSymbol = input.TokenSymbol, + OrganizationHash = organizationHash, + ProposerWhiteList = input.ProposerWhiteList, + CreationToken = input.CreationToken + }; + Assert(Validate(organization), "Invalid organization data."); + + if (State.Organizations[organizationAddress] != null) + return organizationAddress; - public override Organization GetOrganization(Address address) + State.Organizations[organizationAddress] = organization; + Context.Fire(new OrganizationCreated { - return State.Organizations[address] ?? new Organization(); - } + OrganizationAddress = organizationAddress + }); - public override ProposalOutput GetProposal(Hash proposalId) - { - var proposal = State.Proposals[proposalId]; - if (proposal == null) - { - return new ProposalOutput(); - } - - var organization = State.Organizations[proposal.OrganizationAddress]; - var readyToRelease = IsReleaseThresholdReached(proposal, organization); - return new ProposalOutput - { - ProposalId = proposalId, - ContractMethodName = proposal.ContractMethodName, - ExpiredTime = proposal.ExpiredTime, - OrganizationAddress = proposal.OrganizationAddress, - Params = proposal.Params, - Proposer = proposal.Proposer, - ToAddress = proposal.ToAddress, - ToBeReleased = readyToRelease, - ApprovalCount = proposal.ApprovalCount, - RejectionCount = proposal.RejectionCount, - AbstentionCount = proposal.AbstentionCount - }; - } - - public override Address CalculateOrganizationAddress(CreateOrganizationInput input) - { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - return organizationAddress; - } + return organizationAddress; + } - public override BoolValue ValidateOrganizationExist(Address input) - { - return new BoolValue {Value = State.Organizations[input] != null}; - } + public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Unauthorized to create organization."); + var organizationAddress = CreateOrganization(input.OrganizationCreationInput); + if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) + Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) - { - var organization = State.Organizations[input.OrganizationAddress]; - return new BoolValue - { - Value = organization.ProposerWhiteList.Contains(input.Proposer) - }; - } - - public override Address GetProposalVirtualAddress(Hash input) - { - return Context.ConvertVirtualAddressToContractAddress(input); - } + return organizationAddress; + } - #endregion + public override Hash CreateProposal(CreateProposalInput input) + { + AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); + var proposalId = CreateNewProposal(input); - public override Address CreateOrganization(CreateOrganizationInput input) - { - var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); - var organizationAddress = organizationHashAddressPair.OrganizationAddress; - var organizationHash = organizationHashAddressPair.OrganizationHash; - if (State.Organizations[organizationAddress] != null) - return organizationAddress; - var organization = new Organization - { - ProposalReleaseThreshold = input.ProposalReleaseThreshold, - OrganizationAddress = organizationAddress, - TokenSymbol = input.TokenSymbol, - OrganizationHash = organizationHash, - ProposerWhiteList = input.ProposerWhiteList, - CreationToken = input.CreationToken - }; - Assert(Validate(organization), "Invalid organization data."); - - if (State.Organizations[organizationAddress] != null) - return organizationAddress; - - State.Organizations[organizationAddress] = organization; - Context.Fire(new OrganizationCreated - { - OrganizationAddress = organizationAddress - }); + return proposalId; + } - return organizationAddress; - } + public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) + { + Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), + "Not authorized to propose."); + AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); + var proposalId = CreateNewProposal(input.ProposalInput); + return proposalId; + } - public override Address CreateOrganizationBySystemContract(CreateOrganizationBySystemContractInput input) - { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Unauthorized to create organization."); - var organizationAddress = CreateOrganization(input.OrganizationCreationInput); - if (!string.IsNullOrEmpty(input.OrganizationAddressFeedbackMethod)) - { - Context.SendInline(Context.Sender, input.OrganizationAddressFeedbackMethod, organizationAddress); - } + public override Empty Approve(Hash input) + { + var proposal = GetValidProposal(input); + var organization = State.Organizations[proposal.OrganizationAddress]; + var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); + + proposal.ApprovalCount = proposal.ApprovalCount.Add(allowance); + State.Proposals[input] = proposal; + var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, + proposal.OrganizationAddress); + referendumReceiptCreated.ReceiptType = nameof(Approve); + Context.Fire(referendumReceiptCreated); + return new Empty(); + } - return organizationAddress; - } + public override Empty Reject(Hash input) + { + var proposal = GetValidProposal(input); + var organization = State.Organizations[proposal.OrganizationAddress]; + var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); + + proposal.RejectionCount = proposal.RejectionCount.Add(allowance); + State.Proposals[input] = proposal; + var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, + proposal.OrganizationAddress); + referendumReceiptCreated.ReceiptType = nameof(Reject); + Context.Fire(referendumReceiptCreated); + return new Empty(); + } - public override Hash CreateProposal(CreateProposalInput input) - { - AssertIsAuthorizedProposer(input.OrganizationAddress, Context.Sender); - var proposalId = CreateNewProposal(input); + public override Empty Abstain(Hash input) + { + var proposal = GetValidProposal(input); + var organization = State.Organizations[proposal.OrganizationAddress]; + var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); + + proposal.AbstentionCount = proposal.AbstentionCount.Add(allowance); + State.Proposals[input] = proposal; + var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, + proposal.OrganizationAddress); + referendumReceiptCreated.ReceiptType = nameof(Abstain); + Context.Fire(referendumReceiptCreated); + return new Empty(); + } - return proposalId; - } + public override Empty ReclaimVoteToken(Hash input) + { + var proposal = State.Proposals[input]; + Assert(proposal == null || + Context.CurrentBlockTime >= proposal.ExpiredTime, "Unable to reclaim at this time."); + UnlockToken(input, Context.Sender); + return new Empty(); + } - public override Hash CreateProposalBySystemContract(CreateProposalBySystemContractInput input) - { - Assert(Context.GetSystemContractNameToAddressMapping().Values.Contains(Context.Sender), - "Not authorized to propose."); - AssertIsAuthorizedProposer(input.ProposalInput.OrganizationAddress, input.OriginProposer); - var proposalId = CreateNewProposal(input.ProposalInput); - return proposalId; - } - - public override Empty Approve(Hash input) - { - var proposal = GetValidProposal(input); - var organization = State.Organizations[proposal.OrganizationAddress]; - var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); - - proposal.ApprovalCount = proposal.ApprovalCount.Add(allowance); - State.Proposals[input] = proposal; - var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, - proposal.OrganizationAddress); - referendumReceiptCreated.ReceiptType = nameof(Approve); - Context.Fire(referendumReceiptCreated); - return new Empty(); - } - - public override Empty Reject(Hash input) - { - var proposal = GetValidProposal(input); - var organization = State.Organizations[proposal.OrganizationAddress]; - var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); - - proposal.RejectionCount = proposal.RejectionCount.Add(allowance); - State.Proposals[input] = proposal; - var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, - proposal.OrganizationAddress); - referendumReceiptCreated.ReceiptType = nameof(Reject); - Context.Fire(referendumReceiptCreated); - return new Empty(); - } - - public override Empty Abstain(Hash input) - { - var proposal = GetValidProposal(input); - var organization = State.Organizations[proposal.OrganizationAddress]; - var allowance = GetAllowance(Context.Sender, organization.TokenSymbol, input); - - proposal.AbstentionCount = proposal.AbstentionCount.Add(allowance); - State.Proposals[input] = proposal; - var referendumReceiptCreated = LockToken(organization.TokenSymbol, allowance, input, Context.Sender, - proposal.OrganizationAddress); - referendumReceiptCreated.ReceiptType = nameof(Abstain); - Context.Fire(referendumReceiptCreated); - return new Empty(); - } - - public override Empty ReclaimVoteToken(Hash input) - { - var proposal = State.Proposals[input]; - Assert(proposal == null || - Context.CurrentBlockTime >= proposal.ExpiredTime, "Unable to reclaim at this time."); - UnlockToken(input, Context.Sender); - return new Empty(); - } - - public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) - { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.ProposalReleaseThreshold = input; - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new OrganizationThresholdChanged - { - OrganizationAddress = Context.Sender, - ProposerReleaseThreshold = input - }); - return new Empty(); - } - - public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) - { - var organization = State.Organizations[Context.Sender]; - Assert(organization != null, "Organization not found."); - organization.ProposerWhiteList = input; - Assert(Validate(organization), "Invalid organization."); - State.Organizations[Context.Sender] = organization; - Context.Fire(new OrganizationWhiteListChanged - { - OrganizationAddress = Context.Sender, - ProposerWhiteList = input - }); - return new Empty(); - } - - public override Empty ClearProposal(Hash input) - { - // anyone can clear proposal if it is expired - var proposal = State.Proposals[input]; - Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); - State.Proposals.Remove(input); - return new Empty(); - } - - public override Empty Release(Hash input) - { - var proposal = GetValidProposal(input); - Assert(Context.Sender.Equals(proposal.Proposer), "No permission."); - var organization = State.Organizations[proposal.OrganizationAddress]; - Assert(IsReleaseThresholdReached(proposal, organization), "Not approved."); - Context.SendVirtualInlineBySystemContract( - CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposal.ToAddress, - proposal.ContractMethodName, proposal.Params); + public override Empty ChangeOrganizationThreshold(ProposalReleaseThreshold input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.ProposalReleaseThreshold = input; + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new OrganizationThresholdChanged + { + OrganizationAddress = Context.Sender, + ProposerReleaseThreshold = input + }); + return new Empty(); + } + + public override Empty ChangeOrganizationProposerWhiteList(ProposerWhiteList input) + { + var organization = State.Organizations[Context.Sender]; + Assert(organization != null, "Organization not found."); + organization.ProposerWhiteList = input; + Assert(Validate(organization), "Invalid organization."); + State.Organizations[Context.Sender] = organization; + Context.Fire(new OrganizationWhiteListChanged + { + OrganizationAddress = Context.Sender, + ProposerWhiteList = input + }); + return new Empty(); + } + + public override Empty ClearProposal(Hash input) + { + // anyone can clear proposal if it is expired + var proposal = State.Proposals[input]; + Assert(proposal != null && Context.CurrentBlockTime >= proposal.ExpiredTime, "Proposal clear failed"); + State.Proposals.Remove(input); + return new Empty(); + } + + public override Empty Release(Hash input) + { + var proposal = GetValidProposal(input); + Assert(Context.Sender.Equals(proposal.Proposer), "No permission."); + var organization = State.Organizations[proposal.OrganizationAddress]; + Assert(IsReleaseThresholdReached(proposal, organization), "Not approved."); + Context.SendVirtualInlineBySystemContract( + CalculateVirtualHash(organization.OrganizationHash, organization.CreationToken), proposal.ToAddress, + proposal.ContractMethodName, proposal.Params); + + Context.Fire(new ProposalReleased { ProposalId = input }); + State.Proposals.Remove(input); + + return new Empty(); + } + + #region View - Context.Fire(new ProposalReleased {ProposalId = input}); - State.Proposals.Remove(input); + public override Organization GetOrganization(Address address) + { + return State.Organizations[address] ?? new Organization(); + } + + public override ProposalOutput GetProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + if (proposal == null) return new ProposalOutput(); + + var organization = State.Organizations[proposal.OrganizationAddress]; + var readyToRelease = IsReleaseThresholdReached(proposal, organization); + return new ProposalOutput + { + ProposalId = proposalId, + ContractMethodName = proposal.ContractMethodName, + ExpiredTime = proposal.ExpiredTime, + OrganizationAddress = proposal.OrganizationAddress, + Params = proposal.Params, + Proposer = proposal.Proposer, + ToAddress = proposal.ToAddress, + ToBeReleased = readyToRelease, + ApprovalCount = proposal.ApprovalCount, + RejectionCount = proposal.RejectionCount, + AbstentionCount = proposal.AbstentionCount + }; + } - return new Empty(); - } + public override Address CalculateOrganizationAddress(CreateOrganizationInput input) + { + var organizationHashAddressPair = CalculateOrganizationHashAddressPair(input); + var organizationAddress = organizationHashAddressPair.OrganizationAddress; + return organizationAddress; + } + + public override BoolValue ValidateOrganizationExist(Address input) + { + return new BoolValue { Value = State.Organizations[input] != null }; } + + public override BoolValue ValidateProposerInWhiteList(ValidateProposerInWhiteListInput input) + { + var organization = State.Organizations[input.OrganizationAddress]; + return new BoolValue + { + Value = organization.ProposerWhiteList.Contains(input.Proposer) + }; + } + + public override Address GetProposalVirtualAddress(Hash input) + { + return Context.ConvertVirtualAddressToContractAddress(input); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Referendum/ReferendumContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Referendum/ReferendumContract_ACS1_TransactionFeeProvider.cs index 67b5db9095..befb7eefb9 100644 --- a/contract/AElf.Contracts.Referendum/ReferendumContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Referendum/ReferendumContract_ACS1_TransactionFeeProvider.cs @@ -1,97 +1,88 @@ -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public partial class ReferendumContract { - public partial class ReferendumContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(ValidateOrganizationExist), authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Referendum/ReferendumState.cs b/contract/AElf.Contracts.Referendum/ReferendumState.cs index 0558381265..5a30f6430d 100644 --- a/contract/AElf.Contracts.Referendum/ReferendumState.cs +++ b/contract/AElf.Contracts.Referendum/ReferendumState.cs @@ -1,22 +1,20 @@ -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public class ReferendumState : ContractState { - public class ReferendumState : ContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - public BoolState Initialized { get; set; } - public MappedState LockedTokenAmount { get; set; } - public MappedState Organizations { get; set; } - public MappedState Proposals { get; set; } - public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public BoolState Initialized { get; set; } + public MappedState LockedTokenAmount { get; set; } + public MappedState Organizations { get; set; } + public MappedState Proposals { get; set; } + public MappedState TransactionFees { get; set; } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Referendum/Referendum_Helper.cs b/contract/AElf.Contracts.Referendum/Referendum_Helper.cs index f024ef5736..02b00d07c1 100644 --- a/contract/AElf.Contracts.Referendum/Referendum_Helper.cs +++ b/contract/AElf.Contracts.Referendum/Referendum_Helper.cs @@ -1,208 +1,207 @@ using System; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; -using AElf.Types; using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; +using AElf.Types; + +namespace AElf.Contracts.Referendum; -namespace AElf.Contracts.Referendum +public partial class ReferendumContract { - public partial class ReferendumContract + private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) { - private bool IsReleaseThresholdReached(ProposalInfo proposal, Organization organization) - { - var proposalReleaseThreshold = organization.ProposalReleaseThreshold; - var enoughVote = proposal.RejectionCount.Add(proposal.AbstentionCount).Add(proposal.ApprovalCount) >= - proposalReleaseThreshold.MinimalVoteThreshold; - if (!enoughVote) - return false; + var proposalReleaseThreshold = organization.ProposalReleaseThreshold; + var enoughVote = proposal.RejectionCount.Add(proposal.AbstentionCount).Add(proposal.ApprovalCount) >= + proposalReleaseThreshold.MinimalVoteThreshold; + if (!enoughVote) + return false; - var isRejected = proposal.RejectionCount > proposalReleaseThreshold.MaximalRejectionThreshold; - if (isRejected) - return false; + var isRejected = proposal.RejectionCount > proposalReleaseThreshold.MaximalRejectionThreshold; + if (isRejected) + return false; - var isAbstained = proposal.AbstentionCount > proposalReleaseThreshold.MaximalAbstentionThreshold; - if (isAbstained) - return false; + var isAbstained = proposal.AbstentionCount > proposalReleaseThreshold.MaximalAbstentionThreshold; + if (isAbstained) + return false; - return proposal.ApprovalCount >= proposalReleaseThreshold.MinimalApprovalThreshold; - } + return proposal.ApprovalCount >= proposalReleaseThreshold.MinimalApprovalThreshold; + } - private void RequireTokenContractStateSet() - { - if (State.TokenContract.Value != null) - return; - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - private ReferendumReceiptCreated LockToken(string symbol, long amount, Hash proposalId, Address lockedAddress, - Address organizationAddress) - { - Assert(State.LockedTokenAmount[lockedAddress][proposalId] == null, "Already locked."); - - var lockId = Context.GenerateId(Context.Self, - HashHelper.ConcatAndCompute(proposalId, HashHelper.ComputeFrom(lockedAddress))); - RequireTokenContractStateSet(); - Context.SendVirtualInline(proposalId, State.TokenContract.Value, - nameof(TokenContractContainer.TokenContractReferenceState.TransferFrom), new TransferFromInput - { - From = Context.Sender, - To = GetProposalVirtualAddress(proposalId), - Symbol = symbol, - Amount = amount, - Memo = "Referendum." - }); - State.LockedTokenAmount[Context.Sender][proposalId] = new Receipt - { - Amount = amount, - LockId = lockId, - TokenSymbol = symbol - }; - - return new ReferendumReceiptCreated() + private void RequireTokenContractStateSet() + { + if (State.TokenContract.Value != null) + return; + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + } + + private ReferendumReceiptCreated LockToken(string symbol, long amount, Hash proposalId, Address lockedAddress, + Address organizationAddress) + { + Assert(State.LockedTokenAmount[lockedAddress][proposalId] == null, "Already locked."); + + var lockId = Context.GenerateId(Context.Self, + HashHelper.ConcatAndCompute(proposalId, HashHelper.ComputeFrom(lockedAddress))); + RequireTokenContractStateSet(); + Context.SendVirtualInline(proposalId, State.TokenContract.Value, + nameof(TokenContractContainer.TokenContractReferenceState.TransferFrom), new TransferFromInput { - Address = Context.Sender, - ProposalId = proposalId, - Amount = amount, + From = Context.Sender, + To = GetProposalVirtualAddress(proposalId), Symbol = symbol, - Time = Context.CurrentBlockTime, - OrganizationAddress = organizationAddress - }; - } - - private void UnlockToken(Hash proposalId, Address lockedAddress) - { - RequireTokenContractStateSet(); - var receipt = State.LockedTokenAmount[lockedAddress][proposalId]; - Assert(receipt != null, "Nothing to reclaim."); - Context.SendVirtualInline(proposalId, State.TokenContract.Value, - nameof(TokenContractContainer.TokenContractReferenceState.Transfer), new TransferInput - { - Amount = receipt.Amount, - To = Context.Sender, - Symbol = receipt.TokenSymbol, - Memo = "Referendum." - }); - State.LockedTokenAmount[Context.Sender].Remove(proposalId); - } - - private bool Validate(Organization organization) - { - if (string.IsNullOrEmpty(organization.TokenSymbol) || organization.OrganizationAddress == null || - organization.OrganizationHash == null || organization.ProposerWhiteList.Empty()) - return false; - Assert(!string.IsNullOrEmpty(GetTokenInfo(organization.TokenSymbol).Symbol), "Token not exists."); - - var proposalReleaseThreshold = organization.ProposalReleaseThreshold; - return proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && - proposalReleaseThreshold.MinimalApprovalThreshold > 0 && - proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && - proposalReleaseThreshold.MaximalRejectionThreshold >= 0; - } - - private bool Validate(ProposalInfo proposal) - { - var validDestinationAddress = proposal.ToAddress != null; - var validDestinationMethodName = !string.IsNullOrWhiteSpace(proposal.ContractMethodName); - var validExpiredTime = proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; - var hasOrganizationAddress = proposal.OrganizationAddress != null; - var validDescriptionUrl = ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl); - return validDestinationAddress && validDestinationMethodName && validExpiredTime && - hasOrganizationAddress && validDescriptionUrl; - } - - private bool ValidateDescriptionUrlScheme(string uriString) - { - if (string.IsNullOrEmpty(uriString)) - return true; - bool result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - return result; - } - - private ProposalInfo GetValidProposal(Hash proposalId) + Amount = amount, + Memo = "Referendum." + }); + State.LockedTokenAmount[Context.Sender][proposalId] = new Receipt { - var proposal = State.Proposals[proposalId]; - Assert(proposal != null, "Invalid proposal id."); - Assert(Validate(proposal), "Invalid proposal."); - return proposal; - } - - private TokenInfo GetTokenInfo(string symbol) + Amount = amount, + LockId = lockId, + TokenSymbol = symbol + }; + + return new ReferendumReceiptCreated { - RequireTokenContractStateSet(); - return State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput + Address = Context.Sender, + ProposalId = proposalId, + Amount = amount, + Symbol = symbol, + Time = Context.CurrentBlockTime, + OrganizationAddress = organizationAddress + }; + } + + private void UnlockToken(Hash proposalId, Address lockedAddress) + { + RequireTokenContractStateSet(); + var receipt = State.LockedTokenAmount[lockedAddress][proposalId]; + Assert(receipt != null, "Nothing to reclaim."); + Context.SendVirtualInline(proposalId, State.TokenContract.Value, + nameof(TokenContractContainer.TokenContractReferenceState.Transfer), new TransferInput { - Symbol = symbol + Amount = receipt.Amount, + To = Context.Sender, + Symbol = receipt.TokenSymbol, + Memo = "Referendum." }); - } + State.LockedTokenAmount[Context.Sender].Remove(proposalId); + } - private long GetAllowance(Address owner, string tokenSymbol, Hash proposalId) - { - RequireTokenContractStateSet(); - var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput - { - Owner = owner, - Spender = GetProposalVirtualAddress(proposalId), - Symbol = tokenSymbol - }).Allowance; - Assert(allowance > 0, "Allowance not enough."); - return allowance; - } - - private Hash GenerateProposalId(CreateProposalInput input) - { - return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); - } - - private Hash CreateNewProposal(CreateProposalInput input) + private bool Validate(Organization organization) + { + if (string.IsNullOrEmpty(organization.TokenSymbol) || organization.OrganizationAddress == null || + organization.OrganizationHash == null || organization.ProposerWhiteList.Empty()) + return false; + Assert(!string.IsNullOrEmpty(GetTokenInfo(organization.TokenSymbol).Symbol), "Token not exists."); + + var proposalReleaseThreshold = organization.ProposalReleaseThreshold; + return proposalReleaseThreshold.MinimalApprovalThreshold <= proposalReleaseThreshold.MinimalVoteThreshold && + proposalReleaseThreshold.MinimalApprovalThreshold > 0 && + proposalReleaseThreshold.MaximalAbstentionThreshold >= 0 && + proposalReleaseThreshold.MaximalRejectionThreshold >= 0; + } + + private bool Validate(ProposalInfo proposal) + { + var validDestinationAddress = proposal.ToAddress != null; + var validDestinationMethodName = !string.IsNullOrWhiteSpace(proposal.ContractMethodName); + var validExpiredTime = proposal.ExpiredTime != null && Context.CurrentBlockTime < proposal.ExpiredTime; + var hasOrganizationAddress = proposal.OrganizationAddress != null; + var validDescriptionUrl = ValidateDescriptionUrlScheme(proposal.ProposalDescriptionUrl); + return validDestinationAddress && validDestinationMethodName && validExpiredTime && + hasOrganizationAddress && validDescriptionUrl; + } + + private bool ValidateDescriptionUrlScheme(string uriString) + { + if (string.IsNullOrEmpty(uriString)) + return true; + var result = Uri.TryCreate(uriString, UriKind.Absolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + return result; + } + + private ProposalInfo GetValidProposal(Hash proposalId) + { + var proposal = State.Proposals[proposalId]; + Assert(proposal != null, "Invalid proposal id."); + Assert(Validate(proposal), "Invalid proposal."); + return proposal; + } + + private TokenInfo GetTokenInfo(string symbol) + { + RequireTokenContractStateSet(); + return State.TokenContract.GetTokenInfo.Call(new GetTokenInfoInput { - Hash proposalId = GenerateProposalId(input); - Assert(State.Proposals[proposalId] == null, "Proposal already exists."); - var proposal = new ProposalInfo - { - ContractMethodName = input.ContractMethodName, - ToAddress = input.ToAddress, - ExpiredTime = input.ExpiredTime, - Params = input.Params, - OrganizationAddress = input.OrganizationAddress, - Proposer = Context.Sender, - ProposalDescriptionUrl = input.ProposalDescriptionUrl - }; - Assert(Validate(proposal), "Invalid proposal."); - State.Proposals[proposalId] = proposal; - Context.Fire(new ProposalCreated {ProposalId = proposalId, OrganizationAddress = input.OrganizationAddress}); - - return proposalId; - } - - private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) + Symbol = symbol + }); + } + + private long GetAllowance(Address owner, string tokenSymbol, Hash proposalId) + { + RequireTokenContractStateSet(); + var allowance = State.TokenContract.GetAllowance.Call(new GetAllowanceInput { - var organization = State.Organizations[organizationAddress]; - Assert(organization != null, "Organization not found."); - Assert(organization.ProposerWhiteList.Contains(proposer), "Unauthorized to propose."); - } + Owner = owner, + Spender = GetProposalVirtualAddress(proposalId), + Symbol = tokenSymbol + }).Allowance; + Assert(allowance > 0, "Allowance not enough."); + return allowance; + } + + private Hash GenerateProposalId(CreateProposalInput input) + { + return Context.GenerateId(Context.Self, input.Token ?? HashHelper.ComputeFrom(input)); + } - private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( - CreateOrganizationInput createOrganizationInput) + private Hash CreateNewProposal(CreateProposalInput input) + { + var proposalId = GenerateProposalId(input); + Assert(State.Proposals[proposalId] == null, "Proposal already exists."); + var proposal = new ProposalInfo { - var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); - var organizationAddress = Context.ConvertVirtualAddressToContractAddressWithContractHashName( - CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); - - return new OrganizationHashAddressPair - { - OrganizationAddress = organizationAddress, - OrganizationHash = organizationHash - }; - } - - private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) + ContractMethodName = input.ContractMethodName, + ToAddress = input.ToAddress, + ExpiredTime = input.ExpiredTime, + Params = input.Params, + OrganizationAddress = input.OrganizationAddress, + Proposer = Context.Sender, + ProposalDescriptionUrl = input.ProposalDescriptionUrl + }; + Assert(Validate(proposal), "Invalid proposal."); + State.Proposals[proposalId] = proposal; + Context.Fire(new ProposalCreated { ProposalId = proposalId, OrganizationAddress = input.OrganizationAddress }); + + return proposalId; + } + + private void AssertIsAuthorizedProposer(Address organizationAddress, Address proposer) + { + var organization = State.Organizations[organizationAddress]; + Assert(organization != null, "Organization not found."); + Assert(organization.ProposerWhiteList.Contains(proposer), "Unauthorized to propose."); + } + + private OrganizationHashAddressPair CalculateOrganizationHashAddressPair( + CreateOrganizationInput createOrganizationInput) + { + var organizationHash = HashHelper.ComputeFrom(createOrganizationInput); + var organizationAddress = Context.ConvertVirtualAddressToContractAddressWithContractHashName( + CalculateVirtualHash(organizationHash, createOrganizationInput.CreationToken)); + + return new OrganizationHashAddressPair { - return creationToken == null - ? organizationHash - : HashHelper.ConcatAndCompute(organizationHash, creationToken); - } + OrganizationAddress = organizationAddress, + OrganizationHash = organizationHash + }; + } + + private Hash CalculateVirtualHash(Hash organizationHash, Hash creationToken) + { + return creationToken == null + ? organizationHash + : HashHelper.ConcatAndCompute(organizationHash, creationToken); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/AElf.Contracts.TokenConverter.csproj b/contract/AElf.Contracts.TokenConverter/AElf.Contracts.TokenConverter.csproj index 747b778b3e..073abc3ec4 100644 --- a/contract/AElf.Contracts.TokenConverter/AElf.Contracts.TokenConverter.csproj +++ b/contract/AElf.Contracts.TokenConverter/AElf.Contracts.TokenConverter.csproj @@ -1,17 +1,18 @@ - + net6.0 AElf.Contracts.TokenConverter true - TokenConverter is a contract that enables buying and selling tokens based on connector - pairs. + TokenConverter is a contract that enables buying and selling tokens based on connector + pairs. + - true + true - true + true diff --git a/contract/AElf.Contracts.TokenConverter/BancorHelper.cs b/contract/AElf.Contracts.TokenConverter/BancorHelper.cs index 3761de31ca..74a2ddb012 100644 --- a/contract/AElf.Contracts.TokenConverter/BancorHelper.cs +++ b/contract/AElf.Contracts.TokenConverter/BancorHelper.cs @@ -4,184 +4,165 @@ using System.Linq; using AElf.Sdk.CSharp; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public static class BancorHelper { - public static class BancorHelper + static BancorHelper() { - static BancorHelper() - { - Fact = Array.AsReadOnly(Enumerable.Range(0, 20).Select(x => DynFact(x)).ToArray()); - } - - private static long DynFact(long number) - { - var fact = number == 0 ? 1 : number; - for (var i = number - 1; i >= 1; i--) - { - fact *= i; - } - return fact; - } + Fact = Array.AsReadOnly(Enumerable.Range(0, 20).Select(x => DynFact(x)).ToArray()); + } - /// - /// Get token return: - /// Return = (1 - (fromConnectorBalance / (fromConnectorBalance + paidAmount)) ^(fromConnectorWeight/toConnectorWeight))*toConnectorBalance - /// - /// - /// - /// - /// - /// - /// - public static long GetReturnFromPaid(long fromConnectorBalance, decimal fromConnectorWeight, - long toConnectorBalance, decimal toConnectorWeight, long paidAmount) - { - if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) - { - throw new InvalidValueException("Connector balance needs to be a positive number."); - } + private static long DynFact(long number) + { + var fact = number == 0 ? 1 : number; + for (var i = number - 1; i >= 1; i--) fact *= i; + return fact; + } - if (paidAmount <= 0) - { - throw new InvalidValueException("Amount needs to be a positive number."); - } + /// + /// Get token return: + /// Return = (1 - (fromConnectorBalance / (fromConnectorBalance + paidAmount)) + /// ^(fromConnectorWeight/toConnectorWeight))*toConnectorBalance + /// + /// + /// + /// + /// + /// + /// + public static long GetReturnFromPaid(long fromConnectorBalance, decimal fromConnectorWeight, + long toConnectorBalance, decimal toConnectorWeight, long paidAmount) + { + if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) + throw new InvalidValueException("Connector balance needs to be a positive number."); + + if (paidAmount <= 0) throw new InvalidValueException("Amount needs to be a positive number."); + + decimal bf = fromConnectorBalance; + var wf = fromConnectorWeight; + decimal bt = toConnectorBalance; + var wt = toConnectorWeight; + decimal a = paidAmount; + if (wf == wt) + // if both weights are the same, the formula can be reduced + return (long)(bt / (bf + a) * a); + + var x = bf / (bf + a); + var y = wf / wt; + return (long)(bt * (decimal.One - Exp(y * Ln(x)))); + } - decimal bf = fromConnectorBalance; - decimal wf = fromConnectorWeight; - decimal bt = toConnectorBalance; - decimal wt = toConnectorWeight; - decimal a = paidAmount; - if (wf == wt) + /// + /// Get amount of token to pay: + /// amountToPay = ((toConnectorBalance / (toConnectorBalance - amountToReceive)) + /// ^(toConnectorWeight/fromConnectorWeight) - 1)*fromConnectorBalance + /// + /// + /// + /// + /// + /// + /// + public static long GetAmountToPayFromReturn(long fromConnectorBalance, decimal fromConnectorWeight, + long toConnectorBalance, decimal toConnectorWeight, long amountToReceive) + { + if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) + throw new InvalidValueException("Connector balance needs to be a positive number."); + + if (amountToReceive <= 0) throw new InvalidValueException("Amount needs to be a positive number."); + + decimal bf = fromConnectorBalance; + var wf = fromConnectorWeight; + decimal bt = toConnectorBalance; + var wt = toConnectorWeight; + decimal a = amountToReceive; + if (wf == wt) + try { // if both weights are the same, the formula can be reduced - return (long) (bt / (bf + a) * a); + return (long)(bf / (bt - a) * a); } - - decimal x = bf / (bf + a); - decimal y = wf / wt; - return (long) (bt * (Decimal.One - Exp(y * Ln(x)))); - } - - /// - /// Get amount of token to pay: - /// amountToPay = ((toConnectorBalance / (toConnectorBalance - amountToReceive)) ^(toConnectorWeight/fromConnectorWeight) - 1)*fromConnectorBalance - /// - /// - /// - /// - /// - /// - /// - public static long GetAmountToPayFromReturn(long fromConnectorBalance, decimal fromConnectorWeight, - long toConnectorBalance, decimal toConnectorWeight, long amountToReceive) - { - if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) + catch { - throw new InvalidValueException("Connector balance needs to be a positive number."); + throw new AssertionException("Insufficient account balance to deposit"); } - if (amountToReceive <= 0) - { - throw new InvalidValueException("Amount needs to be a positive number."); - } + var x = bt / (bt - a); + var y = wt / wf; + return (long)(bf * (Exp(y * Ln(x)) - decimal.One)); + } - decimal bf = fromConnectorBalance; - decimal wf = fromConnectorWeight; - decimal bt = toConnectorBalance; - decimal wt = toConnectorWeight; - decimal a = amountToReceive; - if (wf == wt) - { - try - { - // if both weights are the same, the formula can be reduced - return (long) (bf / (bt - a) * a); - } - catch - { - throw new AssertionException("Insufficient account balance to deposit"); - } - } + #region Exponential Helpers - decimal x = bt / (bt - a); - decimal y = wt / wf; - return (long) (bf * (Exp(y * Ln(x)) - Decimal.One)); - } + private const int _LOOPS = 20; // Max = 20 - #region Exponential Helpers + private static readonly ReadOnlyCollection Fact; - private const int _LOOPS = 20; // Max = 20 + // http://www.daimi.au.dk/~ivan/FastExpproject.pdf + // Left to Right Binary Exponentiation + public static decimal Pow(decimal x, uint y) + { + if (y == 1) + return x; - private static readonly ReadOnlyCollection Fact; + var A = 1m; + var e = new BitArray(y.ToBytes(false)); + var t = e.Count; - // http://www.daimi.au.dk/~ivan/FastExpproject.pdf - // Left to Right Binary Exponentiation - public static decimal Pow(decimal x, uint y) + for (var i = t - 1; i >= 0; --i) { - if (y == 1) - return x; - - decimal A = 1m; - BitArray e = new BitArray(y.ToBytes(false)); - int t = e.Count; - - for (int i = t - 1; i >= 0; --i) - { - A *= A; - if (e[i] == true) - { - A *= x; - } - } - - return A; + A *= A; + if (e[i]) A *= x; } - // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal - // natural logarithm series - private static decimal Ln(decimal a) - { - /* - ln(a) = log(1-x) = - x - x^2/2 - x^3/3 - ... (where |x| < 1) - x: a = 1-x => x = 1-a = 1 - 1.004 = -.004 - */ - decimal x = 1 - a; - if (Math.Abs(x) >= 1) - throw new InvalidValueException("must be 0 < a < 2"); - - decimal result = 0; - uint iteration = _LOOPS; - while (iteration > 0) - { - result -= Pow(x, iteration) / iteration; - iteration--; - } + return A; + } - return result; + // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal + // natural logarithm series + private static decimal Ln(decimal a) + { + /* + ln(a) = log(1-x) = - x - x^2/2 - x^3/3 - ... (where |x| < 1) + x: a = 1-x => x = 1-a = 1 - 1.004 = -.004 + */ + var x = 1 - a; + if (Math.Abs(x) >= 1) + throw new InvalidValueException("must be 0 < a < 2"); + + decimal result = 0; + uint iteration = _LOOPS; + while (iteration > 0) + { + result -= Pow(x, iteration) / iteration; + iteration--; } + return result; + } - // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal - // power series - private static decimal Exp(decimal y) - { - /* - exp(y) = 1 + y + y^2/2 + x^3/3! + y^4/4! + y^5/5! + ... - */ - int iteration = _LOOPS; - decimal result = 1; - while (iteration > 0) - { - //uint fatorial = Factorial(iteration); - var fatorial = Fact[iteration - 1]; - result += (Pow(y, (uint) iteration) / fatorial); - iteration--; - } + // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal + // power series + private static decimal Exp(decimal y) + { + /* + exp(y) = 1 + y + y^2/2 + x^3/3! + y^4/4! + y^5/5! + ... + */ - return result; + var iteration = _LOOPS; + decimal result = 1; + while (iteration > 0) + { + //uint fatorial = Factorial(iteration); + var fatorial = Fact[iteration - 1]; + result += Pow(y, (uint)iteration) / fatorial; + iteration--; } - #endregion Exponential Helpers + return result; } + + #endregion Exponential Helpers } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/InvalidValueException.cs b/contract/AElf.Contracts.TokenConverter/InvalidValueException.cs index b2d8597001..bd18d566d7 100644 --- a/contract/AElf.Contracts.TokenConverter/InvalidValueException.cs +++ b/contract/AElf.Contracts.TokenConverter/InvalidValueException.cs @@ -1,11 +1,10 @@ using AElf.Sdk.CSharp; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class InvalidValueException : BaseAElfException { - public class InvalidValueException : BaseAElfException + public InvalidValueException(string message) : base(message) { - public InvalidValueException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/TokenConvert_Views.cs b/contract/AElf.Contracts.TokenConverter/TokenConvert_Views.cs index 940c9bf26a..4026c4249d 100644 --- a/contract/AElf.Contracts.TokenConverter/TokenConvert_Views.cs +++ b/contract/AElf.Contracts.TokenConverter/TokenConvert_Views.cs @@ -1,112 +1,109 @@ -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContract { - public partial class TokenConverterContract + public override StringValue GetFeeRate(Empty input) { - public override StringValue GetFeeRate(Empty input) + return new StringValue { - return new StringValue() - { - Value = State.FeeRate.Value - }; - } + Value = State.FeeRate.Value + }; + } - public override AuthorityInfo GetControllerForManageConnector(Empty input) - { - if (State.ConnectorController.Value == null) - return GetDefaultConnectorController(); - return State.ConnectorController.Value; - } + public override AuthorityInfo GetControllerForManageConnector(Empty input) + { + if (State.ConnectorController.Value == null) + return GetDefaultConnectorController(); + return State.ConnectorController.Value; + } - public override TokenSymbol GetBaseTokenSymbol(Empty input) + public override TokenSymbol GetBaseTokenSymbol(Empty input) + { + return new TokenSymbol { - return new TokenSymbol() - { - Symbol = State.BaseTokenSymbol.Value - }; - } + Symbol = State.BaseTokenSymbol.Value + }; + } - /// - /// Query the connector details. - /// - /// - /// - public override PairConnector GetPairConnector(TokenSymbol input) - { - var targetConnector = State.Connectors[input.Symbol]; - Connector relatedConnector = null; - if (targetConnector != null) - relatedConnector = State.Connectors[targetConnector.RelatedSymbol]; - if (targetConnector != null && targetConnector.IsDepositAccount) - return new PairConnector - { - ResourceConnector = relatedConnector, - DepositConnector = targetConnector - }; + /// + /// Query the connector details. + /// + /// + /// + public override PairConnector GetPairConnector(TokenSymbol input) + { + var targetConnector = State.Connectors[input.Symbol]; + Connector relatedConnector = null; + if (targetConnector != null) + relatedConnector = State.Connectors[targetConnector.RelatedSymbol]; + if (targetConnector != null && targetConnector.IsDepositAccount) return new PairConnector { - ResourceConnector = targetConnector, - DepositConnector = relatedConnector + ResourceConnector = relatedConnector, + DepositConnector = targetConnector }; - } - - public override DepositInfo GetNeededDeposit(ToBeConnectedTokenInfo input) + return new PairConnector { - var toConnector = State.Connectors[input.TokenSymbol]; - Assert(toConnector != null && !toConnector.IsDepositAccount, "[GetNeededDeposit]Can't find to connector."); - var fromConnector = State.Connectors[toConnector.RelatedSymbol]; - Assert(fromConnector != null, "[GetNeededDeposit]Can't find from connector."); - var tokenInfo = State.TokenContract.GetTokenInfo.Call( - new GetTokenInfoInput - { - Symbol = input.TokenSymbol, - }); - var balance = State.TokenContract.GetBalance.Call( - new GetBalanceInput - { - Owner = Context.Self, - Symbol = input.TokenSymbol - }).Balance; - var amountOutOfTokenConvert = tokenInfo.TotalSupply - balance - input.AmountToTokenConvert; - long needDeposit = 0; - if (amountOutOfTokenConvert > 0) - { - var fb = fromConnector.VirtualBalance; - var tb = toConnector.IsVirtualBalanceEnabled - ? toConnector.VirtualBalance.Add(tokenInfo.TotalSupply) - : tokenInfo.TotalSupply; - needDeposit = - BancorHelper.GetAmountToPayFromReturn(fb, GetWeight(fromConnector), - tb, GetWeight(toConnector), amountOutOfTokenConvert); - } + ResourceConnector = targetConnector, + DepositConnector = relatedConnector + }; + } - return new DepositInfo + public override DepositInfo GetNeededDeposit(ToBeConnectedTokenInfo input) + { + var toConnector = State.Connectors[input.TokenSymbol]; + Assert(toConnector != null && !toConnector.IsDepositAccount, "[GetNeededDeposit]Can't find to connector."); + var fromConnector = State.Connectors[toConnector.RelatedSymbol]; + Assert(fromConnector != null, "[GetNeededDeposit]Can't find from connector."); + var tokenInfo = State.TokenContract.GetTokenInfo.Call( + new GetTokenInfoInput { - NeedAmount = needDeposit, - AmountOutOfTokenConvert = amountOutOfTokenConvert - }; + Symbol = input.TokenSymbol + }); + var balance = State.TokenContract.GetBalance.Call( + new GetBalanceInput + { + Owner = Context.Self, + Symbol = input.TokenSymbol + }).Balance; + var amountOutOfTokenConvert = tokenInfo.TotalSupply - balance - input.AmountToTokenConvert; + long needDeposit = 0; + if (amountOutOfTokenConvert > 0) + { + var fb = fromConnector.VirtualBalance; + var tb = toConnector.IsVirtualBalanceEnabled + ? toConnector.VirtualBalance.Add(tokenInfo.TotalSupply) + : tokenInfo.TotalSupply; + needDeposit = + BancorHelper.GetAmountToPayFromReturn(fb, GetWeight(fromConnector), + tb, GetWeight(toConnector), amountOutOfTokenConvert); } - public override Int64Value GetDepositConnectorBalance(StringValue symbolInput) + return new DepositInfo { - var connector = State.Connectors[symbolInput.Value]; - Assert(connector != null && !connector.IsDepositAccount, "token symbol is invalid"); - var ntSymbol = connector.RelatedSymbol; - return new Int64Value - { - Value = State.Connectors[ntSymbol].VirtualBalance + State.DepositBalance[ntSymbol] - }; - } + NeedAmount = needDeposit, + AmountOutOfTokenConvert = amountOutOfTokenConvert + }; + } - public override BoolValue IsSymbolAbleToSell(StringValue input) + public override Int64Value GetDepositConnectorBalance(StringValue symbolInput) + { + var connector = State.Connectors[symbolInput.Value]; + Assert(connector != null && !connector.IsDepositAccount, "token symbol is invalid"); + var ntSymbol = connector.RelatedSymbol; + return new Int64Value { - var depositConnector = GetPairConnector(new TokenSymbol {Symbol = input.Value}).DepositConnector; - return new BoolValue {Value = depositConnector != null && depositConnector.IsPurchaseEnabled}; - } + Value = State.Connectors[ntSymbol].VirtualBalance + State.DepositBalance[ntSymbol] + }; + } + + public override BoolValue IsSymbolAbleToSell(StringValue input) + { + var depositConnector = GetPairConnector(new TokenSymbol { Symbol = input.Value }).DepositConnector; + return new BoolValue { Value = depositConnector != null && depositConnector.IsPurchaseEnabled }; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/TokenConverterContract.cs b/contract/AElf.Contracts.TokenConverter/TokenConverterContract.cs index 335daa9e68..1a7aaf80d2 100644 --- a/contract/AElf.Contracts.TokenConverter/TokenConverterContract.cs +++ b/contract/AElf.Contracts.TokenConverter/TokenConverterContract.cs @@ -1,417 +1,390 @@ using System; using System.Globalization; using System.Linq; -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; using AElf.Sdk.CSharp; using AElf.Standards.ACS10; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContract : TokenConverterContractImplContainer.TokenConverterContractImplBase { - public partial class TokenConverterContract : TokenConverterContractImplContainer.TokenConverterContractImplBase - { - private const string NtTokenPrefix = "nt"; + private const string NtTokenPrefix = "nt"; - #region Actions + #region Actions - /// - /// Initialize the contract information. - /// - /// - /// - public override Empty Initialize(InitializeInput input) + /// + /// Initialize the contract information. + /// + /// + /// + public override Empty Initialize(InitializeInput input) + { + Assert(IsValidBaseSymbol(input.BaseTokenSymbol), $"Base token symbol is invalid. {input.BaseTokenSymbol}"); + Assert(State.TokenContract.Value == null, "Already initialized."); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.BaseTokenSymbol.Value = !string.IsNullOrEmpty(input.BaseTokenSymbol) + ? input.BaseTokenSymbol + : Context.Variables.NativeSymbol; + var feeRate = AssertedDecimal(input.FeeRate); + Assert(IsBetweenZeroAndOne(feeRate), "Fee rate has to be a decimal between 0 and 1."); + State.FeeRate.Value = feeRate.ToString(CultureInfo.InvariantCulture); + foreach (var connector in input.Connectors) { - Assert(IsValidBaseSymbol(input.BaseTokenSymbol), $"Base token symbol is invalid. {input.BaseTokenSymbol}"); - Assert(State.TokenContract.Value == null, "Already initialized."); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.BaseTokenSymbol.Value = !string.IsNullOrEmpty(input.BaseTokenSymbol) - ? input.BaseTokenSymbol - : Context.Variables.NativeSymbol; - var feeRate = AssertedDecimal(input.FeeRate); - Assert(IsBetweenZeroAndOne(feeRate), "Fee rate has to be a decimal between 0 and 1."); - State.FeeRate.Value = feeRate.ToString(CultureInfo.InvariantCulture); - foreach (var connector in input.Connectors) + if (connector.IsDepositAccount) { - if (connector.IsDepositAccount) - { - Assert(!string.IsNullOrEmpty(connector.Symbol), "Invalid connector symbol."); - AssertValidConnectorWeight(connector); - } - else - { - Assert(IsValidSymbol(connector.Symbol), "Invalid symbol."); - AssertValidConnectorWeight(connector); - } - - State.Connectors[connector.Symbol] = connector; + Assert(!string.IsNullOrEmpty(connector.Symbol), "Invalid connector symbol."); + AssertValidConnectorWeight(connector); } - - return new Empty(); - } - - public override Empty UpdateConnector(Connector input) - { - AssertPerformedByConnectorController(); - Assert(!string.IsNullOrEmpty(input.Symbol), "input symbol can not be empty'"); - var targetConnector = State.Connectors[input.Symbol]; - Assert(targetConnector != null, "Can not find target connector."); - Assert(!targetConnector.IsPurchaseEnabled, "connector can not be updated because it has been activated"); - if (!string.IsNullOrEmpty(input.Weight)) + else { - var weight = AssertedDecimal(input.Weight); - Assert(IsBetweenZeroAndOne(weight), "Connector Shares has to be a decimal between 0 and 1."); - targetConnector.Weight = input.Weight.ToString(CultureInfo.InvariantCulture); + Assert(IsValidSymbol(connector.Symbol), "Invalid symbol."); + AssertValidConnectorWeight(connector); } - if (targetConnector.IsDepositAccount && input.VirtualBalance > 0) - targetConnector.VirtualBalance = input.VirtualBalance; - State.Connectors[input.Symbol] = targetConnector; - return new Empty(); + State.Connectors[connector.Symbol] = connector; } + return new Empty(); + } - public override Empty AddPairConnector(PairConnectorParam input) + public override Empty UpdateConnector(Connector input) + { + AssertPerformedByConnectorController(); + Assert(!string.IsNullOrEmpty(input.Symbol), "input symbol can not be empty'"); + var targetConnector = State.Connectors[input.Symbol]; + Assert(targetConnector != null, "Can not find target connector."); + Assert(!targetConnector.IsPurchaseEnabled, "connector can not be updated because it has been activated"); + if (!string.IsNullOrEmpty(input.Weight)) { - AssertPerformedByConnectorController(); - Assert(!string.IsNullOrEmpty(input.ResourceConnectorSymbol), - "resource token symbol should not be empty"); - var nativeConnectorSymbol = NtTokenPrefix.Append(input.ResourceConnectorSymbol); - Assert(State.Connectors[input.ResourceConnectorSymbol] == null, - "resource token symbol has existed"); - var resourceConnector = new Connector - { - Symbol = input.ResourceConnectorSymbol, - IsPurchaseEnabled = false, - RelatedSymbol = nativeConnectorSymbol, - Weight = input.ResourceWeight - }; - Assert(IsValidSymbol(resourceConnector.Symbol), "Invalid symbol."); - AssertValidConnectorWeight(resourceConnector); - var nativeTokenToResourceConnector = new Connector - { - Symbol = nativeConnectorSymbol, - VirtualBalance = input.NativeVirtualBalance, - IsVirtualBalanceEnabled = true, - IsPurchaseEnabled = false, - RelatedSymbol = input.ResourceConnectorSymbol, - Weight = input.NativeWeight, - IsDepositAccount = true - }; - AssertValidConnectorWeight(nativeTokenToResourceConnector); - State.Connectors[resourceConnector.Symbol] = resourceConnector; - State.Connectors[nativeTokenToResourceConnector.Symbol] = nativeTokenToResourceConnector; - return new Empty(); + var weight = AssertedDecimal(input.Weight); + Assert(IsBetweenZeroAndOne(weight), "Connector Shares has to be a decimal between 0 and 1."); + targetConnector.Weight = input.Weight.ToString(CultureInfo.InvariantCulture); } - public override Empty Buy(BuyInput input) - { - var toConnector = State.Connectors[input.Symbol]; - Assert(toConnector != null, "[Buy]Can't find to connector."); - Assert(toConnector.IsPurchaseEnabled, "can't purchase"); - Assert(!string.IsNullOrEmpty(toConnector.RelatedSymbol), "can't find related symbol'"); - var fromConnector = State.Connectors[toConnector.RelatedSymbol]; - Assert(fromConnector != null, "[Buy]Can't find from connector."); - var amountToPay = BancorHelper.GetAmountToPayFromReturn( - GetSelfBalance(fromConnector), GetWeight(fromConnector), - GetSelfBalance(toConnector), GetWeight(toConnector), - input.Amount); - var fee = Convert.ToInt64(amountToPay * GetFeeRate()); - - var amountToPayPlusFee = amountToPay.Add(fee); - Assert(input.PayLimit == 0 || amountToPayPlusFee <= input.PayLimit, "Price not good."); - - // Pay fee - if (fee > 0) - { - HandleFee(fee); - } + if (targetConnector.IsDepositAccount && input.VirtualBalance > 0) + targetConnector.VirtualBalance = input.VirtualBalance; + State.Connectors[input.Symbol] = targetConnector; + return new Empty(); + } - // Transfer base token - State.TokenContract.TransferFrom.Send( - new TransferFromInput() - { - Symbol = State.BaseTokenSymbol.Value, - From = Context.Sender, - To = Context.Self, - Amount = amountToPay, - }); - State.DepositBalance[fromConnector.Symbol] = State.DepositBalance[fromConnector.Symbol].Add(amountToPay); - // Transfer bought token - State.TokenContract.Transfer.Send( - new TransferInput - { - Symbol = input.Symbol, - To = Context.Sender, - Amount = input.Amount - }); - Context.Fire(new TokenBought + public override Empty AddPairConnector(PairConnectorParam input) + { + AssertPerformedByConnectorController(); + Assert(!string.IsNullOrEmpty(input.ResourceConnectorSymbol), + "resource token symbol should not be empty"); + var nativeConnectorSymbol = NtTokenPrefix.Append(input.ResourceConnectorSymbol); + Assert(State.Connectors[input.ResourceConnectorSymbol] == null, + "resource token symbol has existed"); + var resourceConnector = new Connector + { + Symbol = input.ResourceConnectorSymbol, + IsPurchaseEnabled = false, + RelatedSymbol = nativeConnectorSymbol, + Weight = input.ResourceWeight + }; + Assert(IsValidSymbol(resourceConnector.Symbol), "Invalid symbol."); + AssertValidConnectorWeight(resourceConnector); + var nativeTokenToResourceConnector = new Connector + { + Symbol = nativeConnectorSymbol, + VirtualBalance = input.NativeVirtualBalance, + IsVirtualBalanceEnabled = true, + IsPurchaseEnabled = false, + RelatedSymbol = input.ResourceConnectorSymbol, + Weight = input.NativeWeight, + IsDepositAccount = true + }; + AssertValidConnectorWeight(nativeTokenToResourceConnector); + State.Connectors[resourceConnector.Symbol] = resourceConnector; + State.Connectors[nativeTokenToResourceConnector.Symbol] = nativeTokenToResourceConnector; + return new Empty(); + } + + public override Empty Buy(BuyInput input) + { + var toConnector = State.Connectors[input.Symbol]; + Assert(toConnector != null, "[Buy]Can't find to connector."); + Assert(toConnector.IsPurchaseEnabled, "can't purchase"); + Assert(!string.IsNullOrEmpty(toConnector.RelatedSymbol), "can't find related symbol'"); + var fromConnector = State.Connectors[toConnector.RelatedSymbol]; + Assert(fromConnector != null, "[Buy]Can't find from connector."); + var amountToPay = BancorHelper.GetAmountToPayFromReturn( + GetSelfBalance(fromConnector), GetWeight(fromConnector), + GetSelfBalance(toConnector), GetWeight(toConnector), + input.Amount); + var fee = Convert.ToInt64(amountToPay * GetFeeRate()); + + var amountToPayPlusFee = amountToPay.Add(fee); + Assert(input.PayLimit == 0 || amountToPayPlusFee <= input.PayLimit, "Price not good."); + + // Pay fee + if (fee > 0) HandleFee(fee); + + // Transfer base token + State.TokenContract.TransferFrom.Send( + new TransferFromInput + { + Symbol = State.BaseTokenSymbol.Value, + From = Context.Sender, + To = Context.Self, + Amount = amountToPay + }); + State.DepositBalance[fromConnector.Symbol] = State.DepositBalance[fromConnector.Symbol].Add(amountToPay); + // Transfer bought token + State.TokenContract.Transfer.Send( + new TransferInput { Symbol = input.Symbol, - BoughtAmount = input.Amount, - BaseAmount = amountToPay, - FeeAmount = fee + To = Context.Sender, + Amount = input.Amount }); - return new Empty(); - } - public override Empty Sell(SellInput input) + Context.Fire(new TokenBought { - var fromConnector = State.Connectors[input.Symbol]; - Assert(fromConnector != null, "[Sell]Can't find from connector."); - Assert(fromConnector.IsPurchaseEnabled, "can't purchase"); - var toConnector = State.Connectors[fromConnector.RelatedSymbol]; - Assert(toConnector != null, "[Sell]Can't find to connector."); - var amountToReceive = BancorHelper.GetReturnFromPaid( - GetSelfBalance(fromConnector), GetWeight(fromConnector), - GetSelfBalance(toConnector), GetWeight(toConnector), - input.Amount - ); - - var fee = Convert.ToInt64(amountToReceive * GetFeeRate()); - - if (Context.Sender == Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName)) - { - fee = 0; - } - - var amountToReceiveLessFee = amountToReceive.Sub(fee); - Assert(input.ReceiveLimit == 0 || amountToReceiveLessFee >= input.ReceiveLimit, "Price not good."); + Symbol = input.Symbol, + BoughtAmount = input.Amount, + BaseAmount = amountToPay, + FeeAmount = fee + }); + return new Empty(); + } - // Pay fee - if (fee > 0) + public override Empty Sell(SellInput input) + { + var fromConnector = State.Connectors[input.Symbol]; + Assert(fromConnector != null, "[Sell]Can't find from connector."); + Assert(fromConnector.IsPurchaseEnabled, "can't purchase"); + var toConnector = State.Connectors[fromConnector.RelatedSymbol]; + Assert(toConnector != null, "[Sell]Can't find to connector."); + var amountToReceive = BancorHelper.GetReturnFromPaid( + GetSelfBalance(fromConnector), GetWeight(fromConnector), + GetSelfBalance(toConnector), GetWeight(toConnector), + input.Amount + ); + + var fee = Convert.ToInt64(amountToReceive * GetFeeRate()); + + if (Context.Sender == + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName)) fee = 0; + + var amountToReceiveLessFee = amountToReceive.Sub(fee); + Assert(input.ReceiveLimit == 0 || amountToReceiveLessFee >= input.ReceiveLimit, "Price not good."); + + // Pay fee + if (fee > 0) HandleFee(fee); + + // Transfer base token + State.TokenContract.Transfer.Send( + new TransferInput { - HandleFee(fee); - } - - // Transfer base token - State.TokenContract.Transfer.Send( - new TransferInput - { - Symbol = State.BaseTokenSymbol.Value, - To = Context.Sender, - Amount = amountToReceive - }); - State.DepositBalance[toConnector.Symbol] = - State.DepositBalance[toConnector.Symbol].Sub(amountToReceive); - // Transfer sold token - State.TokenContract.TransferFrom.Send( - new TransferFromInput - { - Symbol = input.Symbol, - From = Context.Sender, - To = Context.Self, - Amount = input.Amount - }); - Context.Fire(new TokenSold + Symbol = State.BaseTokenSymbol.Value, + To = Context.Sender, + Amount = amountToReceive + }); + State.DepositBalance[toConnector.Symbol] = + State.DepositBalance[toConnector.Symbol].Sub(amountToReceive); + // Transfer sold token + State.TokenContract.TransferFrom.Send( + new TransferFromInput { Symbol = input.Symbol, - SoldAmount = input.Amount, - BaseAmount = amountToReceive, - FeeAmount = fee + From = Context.Sender, + To = Context.Self, + Amount = input.Amount }); - return new Empty(); - } - - private void HandleFee(long fee) + Context.Fire(new TokenSold { - var donateFee = fee.Div(2); - var burnFee = fee.Sub(donateFee); + Symbol = input.Symbol, + SoldAmount = input.Amount, + BaseAmount = amountToReceive, + FeeAmount = fee + }); + return new Empty(); + } - // Donate 0.5% fees to Treasury - State.TokenContract.TransferFrom.Send( - new TransferFromInput - { - Symbol = State.BaseTokenSymbol.Value, - From = Context.Sender, - To = Context.Self, - Amount = donateFee - }); - if (State.DividendPoolContract.Value == null) - State.DividendPoolContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); - State.TokenContract.Approve.Send(new ApproveInput + private void HandleFee(long fee) + { + var donateFee = fee.Div(2); + var burnFee = fee.Sub(donateFee); + + // Donate 0.5% fees to Treasury + State.TokenContract.TransferFrom.Send( + new TransferFromInput { Symbol = State.BaseTokenSymbol.Value, - Spender = State.DividendPoolContract.Value, + From = Context.Sender, + To = Context.Self, Amount = donateFee }); - State.DividendPoolContract.Donate.Send(new DonateInput + if (State.DividendPoolContract.Value == null) + State.DividendPoolContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName); + State.TokenContract.Approve.Send(new ApproveInput + { + Symbol = State.BaseTokenSymbol.Value, + Spender = State.DividendPoolContract.Value, + Amount = donateFee + }); + State.DividendPoolContract.Donate.Send(new DonateInput + { + Symbol = State.BaseTokenSymbol.Value, + Amount = donateFee + }); + + // Transfer to self contract then burn + State.TokenContract.TransferFrom.Send( + new TransferFromInput + { + Symbol = State.BaseTokenSymbol.Value, + From = Context.Sender, + To = Context.Self, + Amount = burnFee + }); + State.TokenContract.Burn.Send( + new BurnInput { Symbol = State.BaseTokenSymbol.Value, - Amount = donateFee + Amount = burnFee }); + } + + public override Empty SetFeeRate(StringValue input) + { + AssertPerformedByConnectorController(); + var feeRate = AssertedDecimal(input.Value); + Assert(IsBetweenZeroAndOne(feeRate), "Fee rate has to be a decimal between 0 and 1."); + State.FeeRate.Value = feeRate.ToString(CultureInfo.InvariantCulture); + return new Empty(); + } - // Transfer to self contract then burn + public override Empty EnableConnector(ToBeConnectedTokenInfo input) + { + var fromConnector = State.Connectors[input.TokenSymbol]; + Assert(fromConnector != null && !fromConnector.IsDepositAccount, + "[EnableConnector]Can't find from connector."); + var toConnector = State.Connectors[fromConnector.RelatedSymbol]; + Assert(toConnector != null, "[EnableConnector]Can't find to connector."); + var needDeposit = GetNeededDeposit(input); + if (needDeposit.NeedAmount > 0) State.TokenContract.TransferFrom.Send( new TransferFromInput { Symbol = State.BaseTokenSymbol.Value, From = Context.Sender, To = Context.Self, - Amount = burnFee + Amount = needDeposit.NeedAmount }); - State.TokenContract.Burn.Send( - new BurnInput + + if (input.AmountToTokenConvert > 0) + State.TokenContract.TransferFrom.Send( + new TransferFromInput { - Symbol = State.BaseTokenSymbol.Value, - Amount = burnFee + Symbol = input.TokenSymbol, + From = Context.Sender, + To = Context.Self, + Amount = input.AmountToTokenConvert }); - } - - public override Empty SetFeeRate(StringValue input) - { - AssertPerformedByConnectorController(); - var feeRate = AssertedDecimal(input.Value); - Assert(IsBetweenZeroAndOne(feeRate), "Fee rate has to be a decimal between 0 and 1."); - State.FeeRate.Value = feeRate.ToString(CultureInfo.InvariantCulture); - return new Empty(); - } - - public override Empty EnableConnector(ToBeConnectedTokenInfo input) - { - var fromConnector = State.Connectors[input.TokenSymbol]; - Assert(fromConnector != null && !fromConnector.IsDepositAccount, - "[EnableConnector]Can't find from connector."); - var toConnector = State.Connectors[fromConnector.RelatedSymbol]; - Assert(toConnector != null, "[EnableConnector]Can't find to connector."); - var needDeposit = GetNeededDeposit(input); - if (needDeposit.NeedAmount > 0) - { - State.TokenContract.TransferFrom.Send( - new TransferFromInput - { - Symbol = State.BaseTokenSymbol.Value, - From = Context.Sender, - To = Context.Self, - Amount = needDeposit.NeedAmount, - }); - } - - if (input.AmountToTokenConvert > 0) - { - State.TokenContract.TransferFrom.Send( - new TransferFromInput - { - Symbol = input.TokenSymbol, - From = Context.Sender, - To = Context.Self, - Amount = input.AmountToTokenConvert - }); - } - - State.DepositBalance[toConnector.Symbol] = needDeposit.NeedAmount; - toConnector.IsPurchaseEnabled = true; - fromConnector.IsPurchaseEnabled = true; - return new Empty(); - } - public override Empty ChangeConnectorController(AuthorityInfo input) - { - AssertPerformedByConnectorController(); - Assert(CheckOrganizationExist(input), "new controller does not exist"); - State.ConnectorController.Value = input; - return new Empty(); - } + State.DepositBalance[toConnector.Symbol] = needDeposit.NeedAmount; + toConnector.IsPurchaseEnabled = true; + fromConnector.IsPurchaseEnabled = true; + return new Empty(); + } - #endregion Actions + public override Empty ChangeConnectorController(AuthorityInfo input) + { + AssertPerformedByConnectorController(); + Assert(CheckOrganizationExist(input), "new controller does not exist"); + State.ConnectorController.Value = input; + return new Empty(); + } - #region Helpers + #endregion Actions - private decimal AssertedDecimal(string number) - { - Assert(decimal.TryParse(number, out var decimalNumber), $@"Invalid decimal ""{number}"""); - return decimalNumber; - } + #region Helpers - private static bool IsBetweenZeroAndOne(decimal number) - { - return number > decimal.Zero && number < decimal.One; - } + private decimal AssertedDecimal(string number) + { + Assert(decimal.TryParse(number, out var decimalNumber), $@"Invalid decimal ""{number}"""); + return decimalNumber; + } - private static bool IsValidSymbol(string symbol) - { - return symbol.Length > 0 && - symbol.All(c => c >= 'A' && c <= 'Z'); - } + private static bool IsBetweenZeroAndOne(decimal number) + { + return number > decimal.Zero && number < decimal.One; + } - private static bool IsValidBaseSymbol(string symbol) - { - return string.IsNullOrEmpty(symbol) || IsValidSymbol(symbol); - } + private static bool IsValidSymbol(string symbol) + { + return symbol.Length > 0 && + symbol.All(c => c >= 'A' && c <= 'Z'); + } - private decimal GetFeeRate() - { - return decimal.Parse(State.FeeRate.Value); - } + private static bool IsValidBaseSymbol(string symbol) + { + return string.IsNullOrEmpty(symbol) || IsValidSymbol(symbol); + } - private long GetSelfBalance(Connector connector) - { - long realBalance; - if (connector.IsDepositAccount) - { - realBalance = State.DepositBalance[connector.Symbol]; - } - else - { - realBalance = State.TokenContract.GetBalance.Call( - new GetBalanceInput() - { - Owner = Context.Self, - Symbol = connector.Symbol - }).Balance; - } + private decimal GetFeeRate() + { + return decimal.Parse(State.FeeRate.Value); + } - if (connector.IsVirtualBalanceEnabled) - { - return connector.VirtualBalance.Add(realBalance); - } + private long GetSelfBalance(Connector connector) + { + long realBalance; + if (connector.IsDepositAccount) + realBalance = State.DepositBalance[connector.Symbol]; + else + realBalance = State.TokenContract.GetBalance.Call( + new GetBalanceInput + { + Owner = Context.Self, + Symbol = connector.Symbol + }).Balance; - return realBalance; - } + if (connector.IsVirtualBalanceEnabled) return connector.VirtualBalance.Add(realBalance); - private decimal GetWeight(Connector connector) - { - return decimal.Parse(connector.Weight); - } + return realBalance; + } - private void AssertPerformedByConnectorController() - { - if (State.ConnectorController.Value == null) - { - State.ConnectorController.Value = GetDefaultConnectorController(); - } + private decimal GetWeight(Connector connector) + { + return decimal.Parse(connector.Weight); + } - Assert(Context.Sender == State.ConnectorController.Value.OwnerAddress, - "Only manager can perform this action."); - } + private void AssertPerformedByConnectorController() + { + if (State.ConnectorController.Value == null) State.ConnectorController.Value = GetDefaultConnectorController(); - private AuthorityInfo GetDefaultConnectorController() - { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } + Assert(Context.Sender == State.ConnectorController.Value.OwnerAddress, + "Only manager can perform this action."); + } - return new AuthorityInfo - { - ContractAddress = State.ParliamentContract.Value, - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) - }; - } + private AuthorityInfo GetDefaultConnectorController() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private void AssertValidConnectorWeight(Connector connector) + return new AuthorityInfo { - var weight = AssertedDecimal(connector.Weight); - Assert(IsBetweenZeroAndOne(weight), "Connector Shares has to be a decimal between 0 and 1."); - connector.Weight = weight.ToString(CultureInfo.InvariantCulture); - } + ContractAddress = State.ParliamentContract.Value, + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) + }; + } - #endregion + private void AssertValidConnectorWeight(Connector connector) + { + var weight = AssertedDecimal(connector.Weight); + Assert(IsBetweenZeroAndOne(weight), "Connector Shares has to be a decimal between 0 and 1."); + connector.Weight = weight.ToString(CultureInfo.InvariantCulture); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/TokenConverterContractState.cs b/contract/AElf.Contracts.TokenConverter/TokenConverterContractState.cs index 59ef9af88c..a7fb234520 100644 --- a/contract/AElf.Contracts.TokenConverter/TokenConverterContractState.cs +++ b/contract/AElf.Contracts.TokenConverter/TokenConverterContractState.cs @@ -1,24 +1,22 @@ -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Standards.ACS10; -using AElf.Types; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class TokenConverterContractState : ContractState { - public class TokenConverterContractState : ContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } + internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } - public StringState BaseTokenSymbol { get; set; } - public StringState FeeRate { get; set; } - public MappedState Connectors { get; set; } - public MappedState TransactionFees { get; set; } - public MappedState DepositBalance { get; set; } - public SingletonState ConnectorController { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public StringState BaseTokenSymbol { get; set; } + public StringState FeeRate { get; set; } + public MappedState Connectors { get; set; } + public MappedState TransactionFees { get; set; } + public MappedState DepositBalance { get; set; } + public SingletonState ConnectorController { get; set; } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenConverter/TokenConverterContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.TokenConverter/TokenConverterContract_ACS1_TransactionFeeProvider.cs index b4e1ddfd32..6fb9a69acc 100644 --- a/contract/AElf.Contracts.TokenConverter/TokenConverterContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.TokenConverter/TokenConverterContract_ACS1_TransactionFeeProvider.cs @@ -1,99 +1,90 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContract { - public partial class TokenConverterContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenHolder/AElf.Contracts.TokenHolder.csproj b/contract/AElf.Contracts.TokenHolder/AElf.Contracts.TokenHolder.csproj index 8f656a8270..1d8fbf296f 100644 --- a/contract/AElf.Contracts.TokenHolder/AElf.Contracts.TokenHolder.csproj +++ b/contract/AElf.Contracts.TokenHolder/AElf.Contracts.TokenHolder.csproj @@ -1,11 +1,12 @@ - + net6.0 AElf.Contracts.TokenHolder true - TokenHolder is a contract that assists dApp developers to manage profit schemes for token - holders. + TokenHolder is a contract that assists dApp developers to manage profit schemes for token + holders. + true diff --git a/contract/AElf.Contracts.TokenHolder/ContractsReferences.cs b/contract/AElf.Contracts.TokenHolder/ContractsReferences.cs index 092c9c2972..ef2ca1d470 100644 --- a/contract/AElf.Contracts.TokenHolder/ContractsReferences.cs +++ b/contract/AElf.Contracts.TokenHolder/ContractsReferences.cs @@ -2,12 +2,11 @@ using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderContractState { - public partial class TokenHolderContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenHolder/TokenHolderContract.cs b/contract/AElf.Contracts.TokenHolder/TokenHolderContract.cs index e86ba15b68..e2a60ab703 100644 --- a/contract/AElf.Contracts.TokenHolder/TokenHolderContract.cs +++ b/contract/AElf.Contracts.TokenHolder/TokenHolderContract.cs @@ -7,308 +7,294 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderContract : TokenHolderContractImplContainer.TokenHolderContractImplBase { - public partial class TokenHolderContract : TokenHolderContractImplContainer.TokenHolderContractImplBase + public override Empty CreateScheme(CreateTokenHolderProfitSchemeInput input) { - public override Empty CreateScheme(CreateTokenHolderProfitSchemeInput input) - { - if (State.ProfitContract.Value == null) - { - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - } + if (State.ProfitContract.Value == null) + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - State.ProfitContract.CreateScheme.Send(new CreateSchemeInput - { - Manager = Context.Sender, - IsReleaseAllBalanceEveryTimeByDefault = true, - CanRemoveBeneficiaryDirectly = true - }); + State.ProfitContract.CreateScheme.Send(new CreateSchemeInput + { + Manager = Context.Sender, + IsReleaseAllBalanceEveryTimeByDefault = true, + CanRemoveBeneficiaryDirectly = true + }); - State.TokenHolderProfitSchemes[Context.Sender] = new TokenHolderProfitScheme - { - Symbol = input.Symbol, - MinimumLockMinutes = input.MinimumLockMinutes, - AutoDistributeThreshold = {input.AutoDistributeThreshold} - }; + State.TokenHolderProfitSchemes[Context.Sender] = new TokenHolderProfitScheme + { + Symbol = input.Symbol, + MinimumLockMinutes = input.MinimumLockMinutes, + AutoDistributeThreshold = { input.AutoDistributeThreshold } + }; - return new Empty(); - } + return new Empty(); + } - public override Empty AddBeneficiary(AddTokenHolderBeneficiaryInput input) + public override Empty AddBeneficiary(AddTokenHolderBeneficiaryInput input) + { + var scheme = GetValidScheme(Context.Sender); + var detail = State.ProfitContract.GetProfitDetails.Call(new GetProfitDetailsInput { - var scheme = GetValidScheme(Context.Sender); - var detail = State.ProfitContract.GetProfitDetails.Call(new GetProfitDetailsInput + SchemeId = scheme.SchemeId, + Beneficiary = input.Beneficiary + }); + var shares = input.Shares; + if (detail.Details.Any()) + { + // Only keep one detail. + + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { SchemeId = scheme.SchemeId, Beneficiary = input.Beneficiary }); - var shares = input.Shares; - if (detail.Details.Any()) - { - // Only keep one detail. + shares.Add(detail.Details.Single().Shares); + } - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = scheme.SchemeId, - Beneficiary = input.Beneficiary - }); - shares.Add(detail.Details.Single().Shares); + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput + { + SchemeId = scheme.SchemeId, + BeneficiaryShare = new BeneficiaryShare + { + Beneficiary = input.Beneficiary, + Shares = shares } + }); + return new Empty(); + } + + public override Empty RemoveBeneficiary(RemoveTokenHolderBeneficiaryInput input) + { + var scheme = GetValidScheme(Context.Sender); + var detail = State.ProfitContract.GetProfitDetails.Call(new GetProfitDetailsInput + { + Beneficiary = input.Beneficiary, + SchemeId = scheme.SchemeId + }).Details.Single(); + var lockedAmount = detail.Shares; + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput + { + SchemeId = scheme.SchemeId, + Beneficiary = input.Beneficiary + }); + if (lockedAmount > input.Amount && + input.Amount != 0) // If input.Amount == 0, means just remove this beneficiary. State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { SchemeId = scheme.SchemeId, BeneficiaryShare = new BeneficiaryShare { Beneficiary = input.Beneficiary, - Shares = shares + Shares = lockedAmount.Sub(input.Amount) } }); - return new Empty(); - } - - public override Empty RemoveBeneficiary(RemoveTokenHolderBeneficiaryInput input) - { - var scheme = GetValidScheme(Context.Sender); - var detail = State.ProfitContract.GetProfitDetails.Call(new GetProfitDetailsInput - { - Beneficiary = input.Beneficiary, - SchemeId = scheme.SchemeId - }).Details.Single(); - var lockedAmount = detail.Shares; - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = scheme.SchemeId, - Beneficiary = input.Beneficiary - }); - if (lockedAmount > input.Amount && - input.Amount != 0) // If input.Amount == 0, means just remove this beneficiary. - { - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = scheme.SchemeId, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = input.Beneficiary, - Shares = lockedAmount.Sub(input.Amount) - } - }); - } + return new Empty(); + } - return new Empty(); - } + public override Empty ContributeProfits(ContributeProfitsInput input) + { + var scheme = GetValidScheme(input.SchemeManager); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - public override Empty ContributeProfits(ContributeProfitsInput input) + State.TokenContract.TransferFrom.Send(new TransferFromInput { - var scheme = GetValidScheme(input.SchemeManager); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = Context.Self, - Symbol = input.Symbol, - Amount = input.Amount - }); + From = Context.Sender, + To = Context.Self, + Symbol = input.Symbol, + Amount = input.Amount + }); - State.TokenContract.Approve.Send(new ApproveInput - { - Spender = State.ProfitContract.Value, - Symbol = input.Symbol, - Amount = input.Amount - }); + State.TokenContract.Approve.Send(new ApproveInput + { + Spender = State.ProfitContract.Value, + Symbol = input.Symbol, + Amount = input.Amount + }); - State.ProfitContract.ContributeProfits.Send(new Profit.ContributeProfitsInput - { - SchemeId = scheme.SchemeId, - Symbol = input.Symbol, - Amount = input.Amount - }); - return new Empty(); - } + State.ProfitContract.ContributeProfits.Send(new Profit.ContributeProfitsInput + { + SchemeId = scheme.SchemeId, + Symbol = input.Symbol, + Amount = input.Amount + }); + return new Empty(); + } - public override Empty DistributeProfits(DistributeProfitsInput input) + public override Empty DistributeProfits(DistributeProfitsInput input) + { + var scheme = GetValidScheme(input.SchemeManager, true); + Assert(Context.Sender == Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName) || + Context.Sender == input.SchemeManager, "No permission to distribute profits."); + var distributeProfitsInput = new Profit.DistributeProfitsInput { - var scheme = GetValidScheme(input.SchemeManager, true); - Assert(Context.Sender == Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName) || - Context.Sender == input.SchemeManager, "No permission to distribute profits."); - var distributeProfitsInput = new Profit.DistributeProfitsInput - { - SchemeId = scheme.SchemeId, - Period = scheme.Period - }; - if (input.AmountsMap != null && input.AmountsMap.Any()) - { - distributeProfitsInput.AmountsMap.Add(input.AmountsMap); - } + SchemeId = scheme.SchemeId, + Period = scheme.Period + }; + if (input.AmountsMap != null && input.AmountsMap.Any()) distributeProfitsInput.AmountsMap.Add(input.AmountsMap); - State.ProfitContract.DistributeProfits.Send(distributeProfitsInput); - scheme.Period = scheme.Period.Add(1); - State.TokenHolderProfitSchemes[input.SchemeManager] = scheme; - return new Empty(); - } + State.ProfitContract.DistributeProfits.Send(distributeProfitsInput); + scheme.Period = scheme.Period.Add(1); + State.TokenHolderProfitSchemes[input.SchemeManager] = scheme; + return new Empty(); + } + + public override Empty RegisterForProfits(RegisterForProfitsInput input) + { + Assert(State.LockIds[input.SchemeManager][Context.Sender] == null, "Already registered."); + var scheme = GetValidScheme(input.SchemeManager); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - public override Empty RegisterForProfits(RegisterForProfitsInput input) + var lockId = Context.GenerateId(Context.Self, + ByteArrayHelper.ConcatArrays(input.SchemeManager.ToByteArray(), Context.Sender.ToByteArray())); + State.TokenContract.Lock.Send(new LockInput + { + LockId = lockId, + Symbol = scheme.Symbol, + Address = Context.Sender, + Amount = input.Amount + }); + State.LockIds[input.SchemeManager][Context.Sender] = lockId; + State.LockTimestamp[lockId] = Context.CurrentBlockTime; + State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { - Assert(State.LockIds[input.SchemeManager][Context.Sender] == null, "Already registered."); - var scheme = GetValidScheme(input.SchemeManager); - if (State.TokenContract.Value == null) + SchemeId = scheme.SchemeId, + BeneficiaryShare = new BeneficiaryShare { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + Beneficiary = Context.Sender, + Shares = input.Amount } + }); - var lockId = Context.GenerateId(Context.Self, - ByteArrayHelper.ConcatArrays(input.SchemeManager.ToByteArray(), Context.Sender.ToByteArray())); - State.TokenContract.Lock.Send(new LockInput - { - LockId = lockId, - Symbol = scheme.Symbol, - Address = Context.Sender, - Amount = input.Amount, - }); - State.LockIds[input.SchemeManager][Context.Sender] = lockId; - State.LockTimestamp[lockId] = Context.CurrentBlockTime; - State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput - { - SchemeId = scheme.SchemeId, - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = Context.Sender, - Shares = input.Amount - } - }); - - // Check auto-distribute threshold. - if (scheme.AutoDistributeThreshold != null && scheme.AutoDistributeThreshold.Any()) + // Check auto-distribute threshold. + if (scheme.AutoDistributeThreshold != null && scheme.AutoDistributeThreshold.Any()) + { + var originScheme = State.ProfitContract.GetScheme.Call(scheme.SchemeId); + var virtualAddress = originScheme.VirtualAddress; + Profit.DistributeProfitsInput distributedInput = null; + foreach (var threshold in scheme.AutoDistributeThreshold) { - var originScheme = State.ProfitContract.GetScheme.Call(scheme.SchemeId); - var virtualAddress = originScheme.VirtualAddress; - Profit.DistributeProfitsInput distributedInput = null; - foreach (var threshold in scheme.AutoDistributeThreshold) + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput { - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput + Owner = virtualAddress, + Symbol = threshold.Key + }).Balance; + if (balance < threshold.Value) continue; + if (distributedInput == null) + distributedInput = new Profit.DistributeProfitsInput { - Owner = virtualAddress, - Symbol = threshold.Key - }).Balance; - if (balance < threshold.Value) continue; - if (distributedInput == null) - distributedInput = new Profit.DistributeProfitsInput - { - SchemeId = scheme.SchemeId, - Period = scheme.Period - }; - distributedInput.AmountsMap[threshold.Key] = 0; - break; - } - - if (distributedInput == null) return new Empty(); - State.ProfitContract.DistributeProfits.Send(distributedInput); - scheme.Period = scheme.Period.Add(1); - State.TokenHolderProfitSchemes[input.SchemeManager] = scheme; + SchemeId = scheme.SchemeId, + Period = scheme.Period + }; + distributedInput.AmountsMap[threshold.Key] = 0; + break; } - return new Empty(); + if (distributedInput == null) return new Empty(); + State.ProfitContract.DistributeProfits.Send(distributedInput); + scheme.Period = scheme.Period.Add(1); + State.TokenHolderProfitSchemes[input.SchemeManager] = scheme; } - public override Empty Withdraw(Address input) - { - var scheme = GetValidScheme(input); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - var lockId = State.LockIds[input][Context.Sender]; - Assert(lockId != null, "Sender didn't register for profits."); - var amount = State.TokenContract.GetLockedAmount.Call(new GetLockedAmountInput - { - Address = Context.Sender, - LockId = lockId, - Symbol = scheme.Symbol - }).Amount; + return new Empty(); + } - Assert(State.LockTimestamp[lockId].AddMinutes(scheme.MinimumLockMinutes) < Context.CurrentBlockTime, - "Cannot withdraw."); + public override Empty Withdraw(Address input) + { + var scheme = GetValidScheme(input); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.TokenContract.Unlock.Send(new UnlockInput - { - Address = Context.Sender, - LockId = lockId, - Amount = amount, - Symbol = scheme.Symbol - }); + var lockId = State.LockIds[input][Context.Sender]; + Assert(lockId != null, "Sender didn't register for profits."); + var amount = State.TokenContract.GetLockedAmount.Call(new GetLockedAmountInput + { + Address = Context.Sender, + LockId = lockId, + Symbol = scheme.Symbol + }).Amount; - State.LockIds[input].Remove(Context.Sender); - State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput - { - SchemeId = scheme.SchemeId, - Beneficiary = Context.Sender - }); - return new Empty(); - } + Assert(State.LockTimestamp[lockId].AddMinutes(scheme.MinimumLockMinutes) < Context.CurrentBlockTime, + "Cannot withdraw."); - public override Empty ClaimProfits(ClaimProfitsInput input) + State.TokenContract.Unlock.Send(new UnlockInput { - var scheme = GetValidScheme(input.SchemeManager); - var beneficiary = input.Beneficiary ?? Context.Sender; - State.ProfitContract.ClaimProfits.Send(new Profit.ClaimProfitsInput - { - SchemeId = scheme.SchemeId, - Beneficiary = beneficiary - }); - return new Empty(); - } + Address = Context.Sender, + LockId = lockId, + Amount = amount, + Symbol = scheme.Symbol + }); - public override TokenHolderProfitScheme GetScheme(Address input) + State.LockIds[input].Remove(Context.Sender); + State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { - return State.TokenHolderProfitSchemes[input]; - } + SchemeId = scheme.SchemeId, + Beneficiary = Context.Sender + }); + return new Empty(); + } - public override ReceivedProfitsMap GetProfitsMap(ClaimProfitsInput input) + public override Empty ClaimProfits(ClaimProfitsInput input) + { + var scheme = GetValidScheme(input.SchemeManager); + var beneficiary = input.Beneficiary ?? Context.Sender; + State.ProfitContract.ClaimProfits.Send(new Profit.ClaimProfitsInput { - var scheme = State.TokenHolderProfitSchemes[input.SchemeManager]; - var profitsMap = State.ProfitContract.GetProfitsMap.Call(new Profit.ClaimProfitsInput - { - SchemeId = scheme.SchemeId, - Beneficiary = input.Beneficiary ?? Context.Sender - }); - return new ReceivedProfitsMap - { - Value = {profitsMap.Value} - }; - } + SchemeId = scheme.SchemeId, + Beneficiary = beneficiary + }); + return new Empty(); + } + + public override TokenHolderProfitScheme GetScheme(Address input) + { + return State.TokenHolderProfitSchemes[input]; + } - private TokenHolderProfitScheme GetValidScheme(Address manager, bool updateSchemePeriod = false) + public override ReceivedProfitsMap GetProfitsMap(ClaimProfitsInput input) + { + var scheme = State.TokenHolderProfitSchemes[input.SchemeManager]; + var profitsMap = State.ProfitContract.GetProfitsMap.Call(new Profit.ClaimProfitsInput { - var scheme = State.TokenHolderProfitSchemes[manager]; - Assert(scheme != null, "Token holder profit scheme not found."); - UpdateTokenHolderProfitScheme(ref scheme, manager, updateSchemePeriod); - return scheme; - } + SchemeId = scheme.SchemeId, + Beneficiary = input.Beneficiary ?? Context.Sender + }); + return new ReceivedProfitsMap + { + Value = { profitsMap.Value } + }; + } + + private TokenHolderProfitScheme GetValidScheme(Address manager, bool updateSchemePeriod = false) + { + var scheme = State.TokenHolderProfitSchemes[manager]; + Assert(scheme != null, "Token holder profit scheme not found."); + UpdateTokenHolderProfitScheme(ref scheme, manager, updateSchemePeriod); + return scheme; + } - private void UpdateTokenHolderProfitScheme(ref TokenHolderProfitScheme scheme, Address manager, - bool updateSchemePeriod) + private void UpdateTokenHolderProfitScheme(ref TokenHolderProfitScheme scheme, Address manager, + bool updateSchemePeriod) + { + if (scheme.SchemeId != null && !updateSchemePeriod) return; + var originSchemeId = State.ProfitContract.GetManagingSchemeIds.Call(new GetManagingSchemeIdsInput { - if (scheme.SchemeId != null && !updateSchemePeriod) return; - var originSchemeId = State.ProfitContract.GetManagingSchemeIds.Call(new GetManagingSchemeIdsInput - { - Manager = manager - }).SchemeIds.FirstOrDefault(); - Assert(originSchemeId != null, "Origin scheme not found."); - var originScheme = State.ProfitContract.GetScheme.Call(originSchemeId); - scheme.SchemeId = originScheme.SchemeId; - scheme.Period = originScheme.CurrentPeriod; - State.TokenHolderProfitSchemes[Context.Sender] = scheme; - } + Manager = manager + }).SchemeIds.FirstOrDefault(); + Assert(originSchemeId != null, "Origin scheme not found."); + var originScheme = State.ProfitContract.GetScheme.Call(originSchemeId); + scheme.SchemeId = originScheme.SchemeId; + scheme.Period = originScheme.CurrentPeriod; + State.TokenHolderProfitSchemes[Context.Sender] = scheme; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenHolder/TokenHolderContractState.cs b/contract/AElf.Contracts.TokenHolder/TokenHolderContractState.cs index bfb97d9a48..187b1d3455 100644 --- a/contract/AElf.Contracts.TokenHolder/TokenHolderContractState.cs +++ b/contract/AElf.Contracts.TokenHolder/TokenHolderContractState.cs @@ -1,21 +1,21 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderContractState : ContractState { - public partial class TokenHolderContractState : ContractState - { - public MappedState TokenHolderProfitSchemes { get; set; } - - /// - /// Contract address (Manager address) -> Beneficiary address -> Lock id. - /// - public MappedState LockIds { get; set; } - public MappedState LockTimestamp { get; set; } - - public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } - } + public MappedState TokenHolderProfitSchemes { get; set; } + + /// + /// Contract address (Manager address) -> Beneficiary address -> Lock id. + /// + public MappedState LockIds { get; set; } + + public MappedState LockTimestamp { get; set; } + + public MappedState TransactionFees { get; set; } + public SingletonState MethodFeeController { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.TokenHolder/TokenHolderContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.TokenHolder/TokenHolderContract_ACS1_TransactionFeeProvider.cs index b1fa7fd5e5..bf89584343 100644 --- a/contract/AElf.Contracts.TokenHolder/TokenHolderContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.TokenHolder/TokenHolderContract_ACS1_TransactionFeeProvider.cs @@ -1,99 +1,90 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderContract { - public partial class TokenHolderContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/AElf.Contracts.Treasury.csproj b/contract/AElf.Contracts.Treasury/AElf.Contracts.Treasury.csproj index b1a9849b4e..e80a82b65b 100644 --- a/contract/AElf.Contracts.Treasury/AElf.Contracts.Treasury.csproj +++ b/contract/AElf.Contracts.Treasury/AElf.Contracts.Treasury.csproj @@ -1,20 +1,21 @@ - + net6.0 AElf.Contracts.Treasury true - Treasury is a contract used to manage the finances of the system (dividend pool for - example). + Treasury is a contract used to manage the finances of the system (dividend pool for + example). + - true + true - true + true @@ -22,7 +23,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs3.proto diff --git a/contract/AElf.Contracts.Treasury/ContractsReferences.cs b/contract/AElf.Contracts.Treasury/ContractsReferences.cs index dac41c1bb4..878fdea71a 100644 --- a/contract/AElf.Contracts.Treasury/ContractsReferences.cs +++ b/contract/AElf.Contracts.Treasury/ContractsReferences.cs @@ -5,16 +5,15 @@ using AElf.Contracts.Profit; using AElf.Contracts.TokenConverter; -namespace AElf.Contracts.Treasury +namespace AElf.Contracts.Treasury; + +// ReSharper disable InconsistentNaming +public partial class TreasuryContractState { - // ReSharper disable InconsistentNaming - public partial class TreasuryContractState - { - internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal AEDPoSContractContainer.AEDPoSContractReferenceState AEDPoSContract { get; set; } - internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } - internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal AEDPoSContractContainer.AEDPoSContractReferenceState AEDPoSContract { get; set; } + internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/TreasuryContract.cs b/contract/AElf.Contracts.Treasury/TreasuryContract.cs index a3e3fdc389..77c2faf01e 100644 --- a/contract/AElf.Contracts.Treasury/TreasuryContract.cs +++ b/contract/AElf.Contracts.Treasury/TreasuryContract.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS10; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Election; using AElf.Contracts.MultiToken; @@ -8,988 +7,924 @@ using AElf.Contracts.TokenConverter; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Treasury +namespace AElf.Contracts.Treasury; + +// ReSharper disable InconsistentNaming +/// +/// The Treasury is the largest profit scheme in AElf main chain. +/// Actually the Treasury is our Dividends Pool. +/// Income of the Treasury is mining rewards +/// (AEDPoS Contract will: +/// 1. transfer ELF tokens to general ledger of Treasury every time we change term (7 days), +/// the amount of ELF should be based on blocks produced during last term. 1,000,000 * 1250000 ELF, +/// then release the Treasury; +/// 2. Release Treasury) +/// 3 sub profit schemes: +/// (Mining Reward for Miners) - 3 +/// (Subsidy for Candidates / Backups) - 1 +/// (Welfare for Electors / Voters / Citizens) - 1 +/// 3 sub profit schemes for Mining Rewards: +/// (Basic Rewards) - 4 +/// (Welcome Rewards) - 1 +/// (Flexible Rewards) - 1 +/// 3 incomes: +/// 1. 20% total supply of elf, from consensus contract +/// 2. tx fees. +/// 3. resource consumption of developer's contracts. +/// +public partial class TreasuryContract : TreasuryContractImplContainer.TreasuryContractImplBase { - // ReSharper disable InconsistentNaming - /// - /// The Treasury is the largest profit scheme in AElf main chain. - /// Actually the Treasury is our Dividends Pool. - /// Income of the Treasury is mining rewards - /// (AEDPoS Contract will: - /// 1. transfer ELF tokens to general ledger of Treasury every time we change term (7 days), - /// the amount of ELF should be based on blocks produced during last term. 1,000,000 * 1250000 ELF, - /// then release the Treasury; - /// 2. Release Treasury) - /// 3 sub profit schemes: - /// (Mining Reward for Miners) - 3 - /// (Subsidy for Candidates / Backups) - 1 - /// (Welfare for Electors / Voters / Citizens) - 1 - /// - /// 3 sub profit schemes for Mining Rewards: - /// (Basic Rewards) - 4 - /// (Welcome Rewards) - 1 - /// (Flexible Rewards) - 1 - /// - /// 3 incomes: - /// 1. 20% total supply of elf, from consensus contract - /// 2. tx fees. - /// 3. resource consumption of developer's contracts. - /// - public partial class TreasuryContract : TreasuryContractImplContainer.TreasuryContractImplBase + public override Empty InitialTreasuryContract(Empty input) { - public override Empty InitialTreasuryContract(Empty input) - { - Assert(!State.Initialized.Value, "Already initialized."); - - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - - // Create profit schemes: `Treasury`, `CitizenWelfare`, `BackupSubsidy`, `MinerReward`, - // `MinerBasicReward`, `WelcomeReward`, `FlexibleReward` - var profitItemNameList = new List - { - "Treasury", "MinerReward", "Subsidy", "Welfare", "Basic Reward", "Flexible Reward", - "Welcome Reward" - }; - for (var i = 0; i < 7; i++) - { - var index = i; - Context.LogDebug(() => profitItemNameList[index]); - State.ProfitContract.CreateScheme.Send(new CreateSchemeInput - { - IsReleaseAllBalanceEveryTimeByDefault = true, - // Distribution of Citizen Welfare will delay one period. - DelayDistributePeriodCount = i == 3 ? 1 : 0, - // Subsidy, Flexible Reward and Welcome Reward can remove beneficiary directly (due to replaceable.) - CanRemoveBeneficiaryDirectly = new List {2, 5, 6}.Contains(i) - }); - } + Assert(!State.Initialized.Value, "Already initialized."); - State.Initialized.Value = true; + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - State.SymbolList.Value = new SymbolList - { - Value = {Context.Variables.NativeSymbol} - }; - - return new Empty(); - } - - public override Empty InitialMiningRewardProfitItem(Empty input) + // Create profit schemes: `Treasury`, `CitizenWelfare`, `BackupSubsidy`, `MinerReward`, + // `MinerBasicReward`, `WelcomeReward`, `FlexibleReward` + var profitItemNameList = new List + { + "Treasury", "MinerReward", "Subsidy", "Welfare", "Basic Reward", "Flexible Reward", + "Welcome Reward" + }; + for (var i = 0; i < 7; i++) { - Assert(State.TreasuryHash.Value == null, "Already initialized."); - var managingSchemeIds = State.ProfitContract.GetManagingSchemeIds.Call(new GetManagingSchemeIdsInput + var index = i; + Context.LogDebug(() => profitItemNameList[index]); + State.ProfitContract.CreateScheme.Send(new CreateSchemeInput { - Manager = Context.Self - }).SchemeIds; + IsReleaseAllBalanceEveryTimeByDefault = true, + // Distribution of Citizen Welfare will delay one period. + DelayDistributePeriodCount = i == 3 ? 1 : 0, + // Subsidy, Flexible Reward and Welcome Reward can remove beneficiary directly (due to replaceable.) + CanRemoveBeneficiaryDirectly = new List { 2, 5, 6 }.Contains(i) + }); + } - Assert(managingSchemeIds.Count == 7, "Incorrect schemes count."); + State.Initialized.Value = true; - State.TreasuryHash.Value = managingSchemeIds[0]; - State.RewardHash.Value = managingSchemeIds[1]; - State.SubsidyHash.Value = managingSchemeIds[2]; - State.WelfareHash.Value = managingSchemeIds[3]; - State.BasicRewardHash.Value = managingSchemeIds[4]; - State.VotesWeightRewardHash.Value = managingSchemeIds[5]; - State.ReElectionRewardHash.Value = managingSchemeIds[6]; + State.SymbolList.Value = new SymbolList + { + Value = { Context.Variables.NativeSymbol } + }; - var electionContractAddress = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - if (electionContractAddress != null) - { - State.ProfitContract.ResetManager.Send(new ResetManagerInput - { - SchemeId = managingSchemeIds[2], - NewManager = electionContractAddress - }); - State.ProfitContract.ResetManager.Send(new ResetManagerInput - { - SchemeId = managingSchemeIds[3], - NewManager = electionContractAddress - }); - } + return new Empty(); + } - BuildTreasury(); + public override Empty InitialMiningRewardProfitItem(Empty input) + { + Assert(State.TreasuryHash.Value == null, "Already initialized."); + var managingSchemeIds = State.ProfitContract.GetManagingSchemeIds.Call(new GetManagingSchemeIdsInput + { + Manager = Context.Self + }).SchemeIds; - var treasuryVirtualAddress = Address.FromPublicKey(State.ProfitContract.Value.Value.Concat( - managingSchemeIds[0].Value.ToByteArray().ComputeHash()).ToArray()); - State.TreasuryVirtualAddress.Value = treasuryVirtualAddress; + Assert(managingSchemeIds.Count == 7, "Incorrect schemes count."); - return new Empty(); - } + State.TreasuryHash.Value = managingSchemeIds[0]; + State.RewardHash.Value = managingSchemeIds[1]; + State.SubsidyHash.Value = managingSchemeIds[2]; + State.WelfareHash.Value = managingSchemeIds[3]; + State.BasicRewardHash.Value = managingSchemeIds[4]; + State.VotesWeightRewardHash.Value = managingSchemeIds[5]; + State.ReElectionRewardHash.Value = managingSchemeIds[6]; - public override Empty Release(ReleaseInput input) + var electionContractAddress = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + if (electionContractAddress != null) { - RequireAEDPoSContractStateSet(); - Assert( - Context.Sender == State.AEDPoSContract.Value, - "Only AElf Consensus Contract can release profits from Treasury."); - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput + State.ProfitContract.ResetManager.Send(new ResetManagerInput { - SchemeId = State.TreasuryHash.Value, - Period = input.PeriodNumber, - AmountsMap = {State.SymbolList.Value.Value.ToDictionary(s => s, s => 0L)} + SchemeId = managingSchemeIds[2], + NewManager = electionContractAddress }); - RequireElectionContractStateSet(); - var previousTermInformation = State.AEDPoSContract.GetPreviousTermInformation.Call(new Int64Value + State.ProfitContract.ResetManager.Send(new ResetManagerInput { - Value = input.PeriodNumber + SchemeId = managingSchemeIds[3], + NewManager = electionContractAddress }); - - var currentMinerList = State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys - .Select(p => p.ToHex()).ToList(); - var maybeNewElectedMiners = new List(); - maybeNewElectedMiners.AddRange(currentMinerList); - maybeNewElectedMiners.AddRange(previousTermInformation.RealTimeMinersInformation.Keys); - var replaceCandidates = State.ReplaceCandidateMap[input.PeriodNumber]; - if (replaceCandidates != null) - { - Context.LogDebug(() => - $"New miners from replace candidate map: {replaceCandidates.Value.Aggregate((l, r) => $"{l}\n{r}")}"); - maybeNewElectedMiners.AddRange(replaceCandidates.Value); - State.ReplaceCandidateMap.Remove(input.PeriodNumber); - } - - maybeNewElectedMiners = maybeNewElectedMiners - .Where(p => State.LatestMinedTerm[p] == 0 && !GetInitialMinerList().Contains(p)).ToList(); - if (maybeNewElectedMiners.Any()) - { - Context.LogDebug(() => $"New elected miners: {maybeNewElectedMiners.Aggregate((l, r) => $"{l}\n{r}")}"); - } - else - { - Context.LogDebug(() => "No new elected miner."); - } - - UpdateStateBeforeDistribution(previousTermInformation, maybeNewElectedMiners); - ReleaseTreasurySubProfitItems(input.PeriodNumber); - UpdateStateAfterDistribution(previousTermInformation, currentMinerList); - return new Empty(); - } - - private List GetInitialMinerList() - { - return State.AEDPoSContract.GetRoundInformation.Call(new Int64Value {Value = 1}).RealTimeMinersInformation - .Keys.ToList(); } - public override Empty Donate(DonateInput input) - { - Assert(input.Amount > 0, "Invalid amount of donating. Amount needs to be greater than 0."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - if (!State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = input.Symbol}).Value) - { - return new Empty(); - } - - if (State.TokenConverterContract.Value == null) - { - State.TokenConverterContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - } + BuildTreasury(); - var isNativeSymbol = input.Symbol == Context.Variables.NativeSymbol; - var canExchangeWithNativeSymbol = - isNativeSymbol || - State.TokenConverterContract.IsSymbolAbleToSell - .Call(new StringValue {Value = input.Symbol}).Value; + var treasuryVirtualAddress = Address.FromPublicKey(State.ProfitContract.Value.Value.Concat( + managingSchemeIds[0].Value.ToByteArray().ComputeHash()).ToArray()); + State.TreasuryVirtualAddress.Value = treasuryVirtualAddress; - if (Context.Sender != Context.Self) - { - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - From = Context.Sender, - To = Context.Self, - Symbol = input.Symbol, - Amount = input.Amount, - Memo = "Donate to treasury.", - }); - } - - var needToConvert = !isNativeSymbol && canExchangeWithNativeSymbol; - if (needToConvert) - { - ConvertToNativeToken(input.Symbol, input.Amount); - } - else - { - State.TokenContract.Approve.Send(new ApproveInput - { - Symbol = input.Symbol, - Amount = input.Amount, - Spender = State.ProfitContract.Value - }); - - State.ProfitContract.ContributeProfits.Send(new ContributeProfitsInput - { - SchemeId = State.TreasuryHash.Value, - Symbol = input.Symbol, - Amount = input.Amount - }); + return new Empty(); + } - var donatesOfCurrentBlock = State.DonatedDividends[Context.CurrentHeight]; - if (donatesOfCurrentBlock != null && Context.Variables.NativeSymbol == input.Symbol && - donatesOfCurrentBlock.Value.ContainsKey(Context.Variables.NativeSymbol)) - { - donatesOfCurrentBlock.Value[Context.Variables.NativeSymbol] = donatesOfCurrentBlock - .Value[Context.Variables.NativeSymbol].Add(input.Amount); - } - else - { - donatesOfCurrentBlock = new Dividends - { - Value = - { - {input.Symbol, input.Amount} - } - }; - } + public override Empty Release(ReleaseInput input) + { + RequireAEDPoSContractStateSet(); + Assert( + Context.Sender == State.AEDPoSContract.Value, + "Only AElf Consensus Contract can release profits from Treasury."); + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput + { + SchemeId = State.TreasuryHash.Value, + Period = input.PeriodNumber, + AmountsMap = { State.SymbolList.Value.Value.ToDictionary(s => s, s => 0L) } + }); + RequireElectionContractStateSet(); + var previousTermInformation = State.AEDPoSContract.GetPreviousTermInformation.Call(new Int64Value + { + Value = input.PeriodNumber + }); + + var currentMinerList = State.AEDPoSContract.GetCurrentMinerList.Call(new Empty()).Pubkeys + .Select(p => p.ToHex()).ToList(); + var maybeNewElectedMiners = new List(); + maybeNewElectedMiners.AddRange(currentMinerList); + maybeNewElectedMiners.AddRange(previousTermInformation.RealTimeMinersInformation.Keys); + var replaceCandidates = State.ReplaceCandidateMap[input.PeriodNumber]; + if (replaceCandidates != null) + { + Context.LogDebug(() => + $"New miners from replace candidate map: {replaceCandidates.Value.Aggregate((l, r) => $"{l}\n{r}")}"); + maybeNewElectedMiners.AddRange(replaceCandidates.Value); + State.ReplaceCandidateMap.Remove(input.PeriodNumber); + } + + maybeNewElectedMiners = maybeNewElectedMiners + .Where(p => State.LatestMinedTerm[p] == 0 && !GetInitialMinerList().Contains(p)).ToList(); + if (maybeNewElectedMiners.Any()) + Context.LogDebug(() => $"New elected miners: {maybeNewElectedMiners.Aggregate((l, r) => $"{l}\n{r}")}"); + else + Context.LogDebug(() => "No new elected miner."); + + UpdateStateBeforeDistribution(previousTermInformation, maybeNewElectedMiners); + ReleaseTreasurySubProfitItems(input.PeriodNumber); + UpdateStateAfterDistribution(previousTermInformation, currentMinerList); + return new Empty(); + } - State.DonatedDividends[Context.CurrentHeight] = donatesOfCurrentBlock; + private List GetInitialMinerList() + { + return State.AEDPoSContract.GetRoundInformation.Call(new Int64Value { Value = 1 }).RealTimeMinersInformation + .Keys.ToList(); + } - Context.Fire(new DonationReceived - { - From = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount, - PoolContract = Context.Self - }); - } + public override Empty Donate(DonateInput input) + { + Assert(input.Amount > 0, "Invalid amount of donating. Amount needs to be greater than 0."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + if (!State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = input.Symbol }).Value) return new Empty(); - } - public override Empty DonateAll(DonateAllInput input) - { - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + if (State.TokenConverterContract.Value == null) + State.TokenConverterContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Symbol = input.Symbol, - Owner = Context.Sender - }).Balance; + var isNativeSymbol = input.Symbol == Context.Variables.NativeSymbol; + var canExchangeWithNativeSymbol = + isNativeSymbol || + State.TokenConverterContract.IsSymbolAbleToSell + .Call(new StringValue { Value = input.Symbol }).Value; - Donate(new DonateInput + if (Context.Sender != Context.Self) + State.TokenContract.TransferFrom.Send(new TransferFromInput { + From = Context.Sender, + To = Context.Self, Symbol = input.Symbol, - Amount = balance + Amount = input.Amount, + Memo = "Donate to treasury." }); - return new Empty(); - } - - public override Empty ChangeTreasuryController(AuthorityInfo input) + var needToConvert = !isNativeSymbol && canExchangeWithNativeSymbol; + if (needToConvert) { - AssertPerformedByTreasuryController(); - Assert(CheckOrganizationExist(input), "Invalid authority input."); - State.TreasuryController.Value = input; - return new Empty(); + ConvertToNativeToken(input.Symbol, input.Amount); } - - public override Empty SetSymbolList(SymbolList input) + else { - AssertPerformedByTreasuryController(); - Assert(input.Value.Contains(Context.Variables.NativeSymbol), "Need to contain native symbol."); - if (State.TokenContract.Value == null) + State.TokenContract.Approve.Send(new ApproveInput { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } + Symbol = input.Symbol, + Amount = input.Amount, + Spender = State.ProfitContract.Value + }); - if (State.TokenConverterContract.Value == null) + State.ProfitContract.ContributeProfits.Send(new ContributeProfitsInput { - State.TokenConverterContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - } + SchemeId = State.TreasuryHash.Value, + Symbol = input.Symbol, + Amount = input.Amount + }); - foreach (var symbol in input.Value.Where(s => s != Context.Variables.NativeSymbol)) - { - var isTreasuryInWhiteList = State.TokenContract.IsInWhiteList.Call(new IsInWhiteListInput + var donatesOfCurrentBlock = State.DonatedDividends[Context.CurrentHeight]; + if (donatesOfCurrentBlock != null && Context.Variables.NativeSymbol == input.Symbol && + donatesOfCurrentBlock.Value.ContainsKey(Context.Variables.NativeSymbol)) + donatesOfCurrentBlock.Value[Context.Variables.NativeSymbol] = donatesOfCurrentBlock + .Value[Context.Variables.NativeSymbol].Add(input.Amount); + else + donatesOfCurrentBlock = new Dividends { - Symbol = symbol, - Address = Context.Self - }).Value; - Assert( - State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value || - isTreasuryInWhiteList, "Symbol need to be profitable."); - Assert(!State.TokenConverterContract.IsSymbolAbleToSell.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} doesn't need to set to symbol list because it would become native token after donation."); - } + Value = + { + { input.Symbol, input.Amount } + } + }; - State.SymbolList.Value = input; - return new Empty(); + State.DonatedDividends[Context.CurrentHeight] = donatesOfCurrentBlock; + + Context.Fire(new DonationReceived + { + From = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount, + PoolContract = Context.Self + }); } - public override Empty SetDividendPoolWeightSetting(DividendPoolWeightSetting input) + return new Empty(); + } + + public override Empty DonateAll(DonateAllInput input) + { + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput { - AssertPerformedByTreasuryController(); - Assert( - input.CitizenWelfareWeight > 0 && input.BackupSubsidyWeight > 0 && - input.MinerRewardWeight > 0, - "invalid input"); - ResetSubSchemeToTreasury(input); - State.DividendPoolWeightSetting.Value = input; - return new Empty(); - } + Symbol = input.Symbol, + Owner = Context.Sender + }).Balance; - public override Empty SetMinerRewardWeightSetting(MinerRewardWeightSetting input) + Donate(new DonateInput { - AssertPerformedByTreasuryController(); - Assert( - input.BasicMinerRewardWeight > 0 && input.WelcomeRewardWeight > 0 && - input.FlexibleRewardWeight > 0, - "invalid input"); - ResetSubSchemeToMinerReward(input); - State.MinerRewardWeightSetting.Value = input; - return new Empty(); - } + Symbol = input.Symbol, + Amount = balance + }); - #region Private methods + return new Empty(); + } - private void ConvertToNativeToken(string symbol, long amount) - { - State.TokenContract.Approve.Send(new ApproveInput - { - Spender = State.TokenConverterContract.Value, - Symbol = symbol, - Amount = amount - }); + public override Empty ChangeTreasuryController(AuthorityInfo input) + { + AssertPerformedByTreasuryController(); + Assert(CheckOrganizationExist(input), "Invalid authority input."); + State.TreasuryController.Value = input; + return new Empty(); + } - State.TokenConverterContract.Sell.Send(new SellInput - { - Symbol = symbol, - Amount = amount - }); + public override Empty SetSymbolList(SymbolList input) + { + AssertPerformedByTreasuryController(); + Assert(input.Value.Contains(Context.Variables.NativeSymbol), "Need to contain native symbol."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - Context.SendInline(Context.Self, nameof(DonateAll), new DonateAllInput - { - Symbol = Context.Variables.NativeSymbol - }); - } + if (State.TokenConverterContract.Value == null) + State.TokenConverterContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - private void BuildTreasury() + foreach (var symbol in input.Value.Where(s => s != Context.Variables.NativeSymbol)) { - if (State.DividendPoolWeightSetting.Value == null) - { - var dividendPoolWeightSetting = GetDefaultDividendPoolWeightSetting(); - ResetSubSchemeToTreasury(dividendPoolWeightSetting); - State.DividendPoolWeightSetting.Value = dividendPoolWeightSetting; - } - - if (State.MinerRewardWeightSetting.Value == null) + var isTreasuryInWhiteList = State.TokenContract.IsInWhiteList.Call(new IsInWhiteListInput { - var minerRewardWeightSetting = GetDefaultMinerRewardWeightSetting(); - ResetSubSchemeToMinerReward(minerRewardWeightSetting); - State.MinerRewardWeightSetting.Value = minerRewardWeightSetting; - } + Symbol = symbol, + Address = Context.Self + }).Value; + Assert( + State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value || + isTreasuryInWhiteList, "Symbol need to be profitable."); + Assert(!State.TokenConverterContract.IsSymbolAbleToSell.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} doesn't need to set to symbol list because it would become native token after donation."); } - private void ReleaseTreasurySubProfitItems(long termNumber) - { - var amountsMap = State.SymbolList.Value.Value.ToDictionary(s => s, s => 0L); - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeId = State.RewardHash.Value, - Period = termNumber, - AmountsMap = {amountsMap} - }); + State.SymbolList.Value = input; + return new Empty(); + } - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeId = State.VotesWeightRewardHash.Value, - Period = termNumber, - AmountsMap = {amountsMap} - }); + public override Empty SetDividendPoolWeightSetting(DividendPoolWeightSetting input) + { + AssertPerformedByTreasuryController(); + Assert( + input.CitizenWelfareWeight > 0 && input.BackupSubsidyWeight > 0 && + input.MinerRewardWeight > 0, + "invalid input"); + ResetSubSchemeToTreasury(input); + State.DividendPoolWeightSetting.Value = input; + return new Empty(); + } - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeId = State.ReElectionRewardHash.Value, - Period = termNumber, - AmountsMap = {amountsMap} - }); + public override Empty SetMinerRewardWeightSetting(MinerRewardWeightSetting input) + { + AssertPerformedByTreasuryController(); + Assert( + input.BasicMinerRewardWeight > 0 && input.WelcomeRewardWeight > 0 && + input.FlexibleRewardWeight > 0, + "invalid input"); + ResetSubSchemeToMinerReward(input); + State.MinerRewardWeightSetting.Value = input; + return new Empty(); + } - State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeId = State.BasicRewardHash.Value, - Period = termNumber, - AmountsMap = {amountsMap} + public override GetWelfareRewardAmountSampleOutput GetWelfareRewardAmountSample( + GetWelfareRewardAmountSampleInput input) + { + const long sampleAmount = 10000; + var welfareHash = State.WelfareHash.Value; + var output = new GetWelfareRewardAmountSampleOutput(); + var welfareScheme = State.ProfitContract.GetScheme.Call(welfareHash); + var releasedInformation = State.ProfitContract.GetDistributedProfitsInfo.Call( + new SchemePeriod + { + SchemeId = welfareHash, + Period = welfareScheme.CurrentPeriod.Sub(1) }); - } + var totalShares = releasedInformation.TotalShares; + if (totalShares == 0) return new GetWelfareRewardAmountSampleOutput(); - private void RequireAEDPoSContractStateSet() + var totalAmount = releasedInformation.AmountsMap; + foreach (var lockTime in input.Value) { - if (State.AEDPoSContract.Value == null) - { - State.AEDPoSContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - } + var shares = GetVotesWeight(sampleAmount, lockTime); + // In case of arithmetic overflow + var decimalAmount = (decimal)totalAmount[Context.Variables.NativeSymbol]; + var decimalShares = (decimal)shares; + var decimalTotalShares = (decimal)totalShares; + var amount = decimalAmount * decimalShares / decimalTotalShares; + output.Value.Add((long)amount); } - private void RequireElectionContractStateSet() + return output; + } + + public override Dividends GetUndistributedDividends(Empty input) + { + return new Dividends { - if (State.ElectionContract.Value == null) + Value = { - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + State.SymbolList.Value.Value.Select(s => State.TokenContract.GetBalance.Call(new GetBalanceInput + { + Owner = State.TreasuryVirtualAddress.Value, + Symbol = s + })).ToDictionary(b => b.Symbol, b => b.Balance) } - } + }; + } - private void UpdateStateBeforeDistribution(Round previousTermInformation, List newElectedMiners) - { - var previousPreviousTermInformation = State.AEDPoSContract.GetPreviousTermInformation.Call(new Int64Value - { - Value = previousTermInformation.TermNumber.Sub(1) - }); + public override Hash GetTreasurySchemeId(Empty input) + { + return State.TreasuryHash.Value ?? Hash.Empty; + } - if (newElectedMiners.Any()) - { - State.HasNewMiner[previousTermInformation.TermNumber.Add(1)] = true; - } + public override AuthorityInfo GetTreasuryController(Empty input) + { + if (State.TreasuryController.Value == null) return GetDefaultTreasuryController(); - Context.LogDebug(() => $"Will update weights after term {previousTermInformation.TermNumber}"); - UpdateBasicMinerRewardWeights(new List {previousPreviousTermInformation, previousTermInformation}); - UpdateWelcomeRewardWeights(previousTermInformation, newElectedMiners); - UpdateFlexibleRewardWeights(previousTermInformation); - } + return State.TreasuryController.Value; + } - private void UpdateStateAfterDistribution(Round previousTermInformation, List currentMinerList) - { - foreach (var miner in currentMinerList) - { - State.LatestMinedTerm[miner] = previousTermInformation.TermNumber; - } - } + public override SymbolList GetSymbolList(Empty input) + { + return State.SymbolList.Value; + } - /// - /// Remove current total shares of Basic Reward, - /// Add new shares for miners of next term. - /// 1 share for each miner. - /// - /// - private void UpdateBasicMinerRewardWeights(IReadOnlyCollection previousTermInformation) + public override MinerRewardWeightProportion GetMinerRewardWeightProportion(Empty input) + { + var weightSetting = State.MinerRewardWeightSetting.Value ?? GetDefaultMinerRewardWeightSetting(); + var weightSum = weightSetting.BasicMinerRewardWeight.Add(weightSetting.WelcomeRewardWeight) + .Add(weightSetting.FlexibleRewardWeight); + var weightProportion = new MinerRewardWeightProportion { - if (previousTermInformation.First().RealTimeMinersInformation != null) - { - State.ProfitContract.RemoveBeneficiaries.Send(new RemoveBeneficiariesInput - { - SchemeId = State.BasicRewardHash.Value, - Beneficiaries = - { - GetAddressesFromCandidatePubkeys(previousTermInformation.First().RealTimeMinersInformation.Keys) - } - }); - } - - var averageProducedBlocksCount = CalculateAverage(previousTermInformation.Last().RealTimeMinersInformation - .Values - .Select(i => i.ProducedBlocks).ToList()); - // Manage weights of `MinerBasicReward` - State.ProfitContract.AddBeneficiaries.Send(new AddBeneficiariesInput + BasicMinerRewardProportionInfo = new SchemeProportionInfo { SchemeId = State.BasicRewardHash.Value, - EndPeriod = previousTermInformation.Last().TermNumber, - BeneficiaryShares = - { - previousTermInformation.Last().RealTimeMinersInformation.Values.Select(i => - { - long shares; - if (State.IsReplacedEvilMiner[i.Pubkey]) - { - // The new miner may have more shares than his actually contributes, but it's ok. - shares = i.ProducedBlocks; - // Clear the state asap. - State.IsReplacedEvilMiner.Remove(i.Pubkey); - } - else - { - shares = CalculateShares(i.ProducedBlocks, averageProducedBlocksCount); - } - - return new BeneficiaryShare - { - Beneficiary = GetProfitsReceiver(i.Pubkey), - Shares = shares - }; - }) - } - }); - } + Proportion = weightSetting.BasicMinerRewardWeight + .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) + }, + WelcomeRewardProportionInfo = new SchemeProportionInfo + { + SchemeId = State.VotesWeightRewardHash.Value, + Proportion = weightSetting.WelcomeRewardWeight + .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) + } + }; + weightProportion.FlexibleRewardProportionInfo = new SchemeProportionInfo + { + SchemeId = State.ReElectionRewardHash.Value, + Proportion = TreasuryContractConstants.OneHundredPercent + .Sub(weightProportion.BasicMinerRewardProportionInfo.Proportion) + .Sub(weightProportion.WelcomeRewardProportionInfo.Proportion) + }; + return weightProportion; + } - /// - /// Just to make sure not using double type. - /// - /// - /// - private long CalculateAverage(List list) + public override DividendPoolWeightProportion GetDividendPoolWeightProportion(Empty input) + { + var weightSetting = State.DividendPoolWeightSetting.Value ?? GetDefaultDividendPoolWeightSetting(); + var weightSum = weightSetting.BackupSubsidyWeight.Add(weightSetting.CitizenWelfareWeight) + .Add(weightSetting.MinerRewardWeight); + var weightProportion = new DividendPoolWeightProportion + { + BackupSubsidyProportionInfo = new SchemeProportionInfo + { + SchemeId = State.SubsidyHash.Value, + Proportion = weightSetting.BackupSubsidyWeight + .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) + }, + CitizenWelfareProportionInfo = new SchemeProportionInfo + { + SchemeId = State.WelfareHash.Value, + Proportion = weightSetting.CitizenWelfareWeight + .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) + } + }; + weightProportion.MinerRewardProportionInfo = new SchemeProportionInfo + { + SchemeId = State.RewardHash.Value, + Proportion = TreasuryContractConstants.OneHundredPercent + .Sub(weightProportion.BackupSubsidyProportionInfo.Proportion) + .Sub(weightProportion.CitizenWelfareProportionInfo.Proportion) + }; + return weightProportion; + } + + private long GetVotesWeight(long votesAmount, long lockTime) + { + RequireElectionContractStateSet(); + var weight = State.ElectionContract.GetCalculateVoteWeight.Call(new VoteInformation { - var sum = list.Sum(); - return sum.Div(list.Count); - } + Amount = votesAmount, + LockTime = lockTime + }); + return weight.Value; + } - private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) + private DividendPoolWeightSetting GetDefaultDividendPoolWeightSetting() + { + return new DividendPoolWeightSetting { - if (producedBlocksCount < averageProducedBlocksCount.Div(2)) - { - // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. - return 0; - } + CitizenWelfareWeight = 15, + BackupSubsidyWeight = 1, + MinerRewardWeight = 4 + }; + } - if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) - { - // If count < (4/5) * average_count, then ratio will be (count / average_count) - return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); - } + private MinerRewardWeightSetting GetDefaultMinerRewardWeightSetting() + { + return new MinerRewardWeightSetting + { + BasicMinerRewardWeight = 2, + WelcomeRewardWeight = 1, + FlexibleRewardWeight = 1 + }; + } - return producedBlocksCount; - } + private void ResetSubSchemeToTreasury(DividendPoolWeightSetting newWeightSetting) + { + var oldWeightSetting = State.DividendPoolWeightSetting.Value ?? new DividendPoolWeightSetting(); + var parentSchemeId = State.TreasuryHash.Value; + // Register or reset `MinerReward` to `Treasury` + ResetWeight(parentSchemeId, State.RewardHash.Value, + oldWeightSetting.MinerRewardWeight, newWeightSetting.MinerRewardWeight); + // Register or reset `BackupSubsidy` to `Treasury` + ResetWeight(parentSchemeId, State.SubsidyHash.Value, + oldWeightSetting.BackupSubsidyWeight, newWeightSetting.BackupSubsidyWeight); + // Register or reset `CitizenWelfare` to `Treasury` + ResetWeight(parentSchemeId, State.WelfareHash.Value, + oldWeightSetting.CitizenWelfareWeight, newWeightSetting.CitizenWelfareWeight); + } - private void UpdateWelcomeRewardWeights(Round previousTermInformation, List newElectedMiners) - { - var previousMinerAddresses = - GetAddressesFromCandidatePubkeys(previousTermInformation.RealTimeMinersInformation.Keys); - var possibleWelcomeBeneficiaries = new RemoveBeneficiariesInput - { - SchemeId = State.VotesWeightRewardHash.Value, - Beneficiaries = {previousMinerAddresses} - }; - State.ProfitContract.RemoveBeneficiaries.Send(possibleWelcomeBeneficiaries); + private void ResetSubSchemeToMinerReward(MinerRewardWeightSetting newWeightSetting) + { + var oldWeightSetting = State.MinerRewardWeightSetting.Value ?? new MinerRewardWeightSetting(); + var parentSchemeId = State.RewardHash.Value; + // Register or reset `MinerBasicReward` to `MinerReward` + ResetWeight(parentSchemeId, State.BasicRewardHash.Value, + oldWeightSetting.BasicMinerRewardWeight, newWeightSetting.BasicMinerRewardWeight); + // Register or reset `WelcomeRewardWeight` to `MinerReward` + ResetWeight(parentSchemeId, State.VotesWeightRewardHash.Value, + oldWeightSetting.WelcomeRewardWeight, newWeightSetting.WelcomeRewardWeight); + // Register or reset `FlexibleRewardWeight` to `MinerReward` + ResetWeight(parentSchemeId, State.ReElectionRewardHash.Value, + oldWeightSetting.FlexibleRewardWeight, newWeightSetting.FlexibleRewardWeight); + } + + private void ResetWeight(Hash parentSchemeId, Hash subSchemeId, int oldWeight, + int newWeight) + { + if (oldWeight == newWeight) + return; + + // old weight equals 0 indicates the subScheme has not been registered + if (oldWeight > 0) State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput { - SchemeId = State.VotesWeightRewardHash.Value, - SubSchemeId = State.BasicRewardHash.Value + SchemeId = parentSchemeId, + SubSchemeId = subSchemeId }); - if (newElectedMiners.Any()) + State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput + { + SchemeId = parentSchemeId, + SubSchemeId = subSchemeId, + SubSchemeShares = newWeight + }); + } + + public override Empty UpdateMiningReward(Int64Value input) + { + Assert(Context.Sender == + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName), + "Only consensus contract can update mining reward."); + State.MiningReward.Value = input.Value; + return new Empty(); + } + + public override Dividends GetDividends(Int64Value input) + { + Assert(Context.CurrentHeight > input.Value, "Cannot query dividends of a future block."); + var dividends = State.DonatedDividends[input.Value]; + + if (dividends != null && dividends.Value.ContainsKey(Context.Variables.NativeSymbol)) + dividends.Value[Context.Variables.NativeSymbol] = + dividends.Value[Context.Variables.NativeSymbol].Add(State.MiningReward.Value); + else + dividends = new Dividends { - Context.LogDebug(() => "Welcome reward will go to new miners."); - var newBeneficiaries = new AddBeneficiariesInput - { - SchemeId = State.VotesWeightRewardHash.Value, - EndPeriod = previousTermInformation.TermNumber.Add(1) - }; - foreach (var minerAddress in newElectedMiners.Select(GetProfitsReceiver)) + Value = { - newBeneficiaries.BeneficiaryShares.Add(new BeneficiaryShare { - Beneficiary = minerAddress, - Shares = 1 - }); + Context.Variables.NativeSymbol, State.MiningReward.Value + } } + }; - if (newBeneficiaries.BeneficiaryShares.Any()) - { - State.ProfitContract.AddBeneficiaries.Send(newBeneficiaries); - } - } - else - { - Context.LogDebug(() => "Welcome reward will go to Basic Reward."); - State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput - { - SchemeId = State.VotesWeightRewardHash.Value, - SubSchemeId = State.BasicRewardHash.Value, - SubSchemeShares = 1 - }); - } - } + return dividends; + } - private void UpdateFlexibleRewardWeights(Round previousTermInformation) - { - State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput - { - SchemeId = State.ReElectionRewardHash.Value, - SubSchemeId = State.WelfareHash.Value - }); - State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput - { - SchemeId = State.ReElectionRewardHash.Value, - SubSchemeId = State.BasicRewardHash.Value - }); - if (State.ProfitContract.GetScheme.Call(State.ReElectionRewardHash.Value).TotalShares > 0) - { - var previousMinerAddresses = - GetAddressesFromCandidatePubkeys(previousTermInformation.RealTimeMinersInformation.Keys); - State.ProfitContract.RemoveBeneficiaries.Send(new RemoveBeneficiariesInput - { - SchemeId = State.ReElectionRewardHash.Value, - Beneficiaries = {previousMinerAddresses} - }); - } + public override Empty RecordMinerReplacement(RecordMinerReplacementInput input) + { + Assert( + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, + "Only AEDPoS Contract can record miner replacement."); - if (State.HasNewMiner[previousTermInformation.TermNumber]) - { - Context.LogDebug(() => "Flexible reward will go to Welfare Reward."); - State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput - { - SchemeId = State.ReElectionRewardHash.Value, - SubSchemeId = State.WelfareHash.Value, - SubSchemeShares = 1 - }); - } - else - { - Context.LogDebug(() => "Flexible reward will go to Basic Reward."); - State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput - { - SchemeId = State.ReElectionRewardHash.Value, - SubSchemeId = State.BasicRewardHash.Value, - SubSchemeShares = 1 - }); - } - } + if (State.ProfitContract.Value == null) + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - private void AssertPerformedByTreasuryController() + if (!input.IsOldPubkeyEvil) { - if (State.TreasuryController.Value == null) - { - State.TreasuryController.Value = GetDefaultTreasuryController(); - } - - Assert(Context.Sender == State.TreasuryController.Value.OwnerAddress, "no permission"); + var latestMinedTerm = State.LatestMinedTerm[input.OldPubkey]; + State.LatestMinedTerm[input.NewPubkey] = latestMinedTerm; + State.LatestMinedTerm.Remove(input.OldPubkey); } - - private AuthorityInfo GetDefaultTreasuryController() + else { - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - return new AuthorityInfo - { - ContractAddress = State.ParliamentContract.Value, - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) - }; + var replaceCandidates = State.ReplaceCandidateMap[input.CurrentTermNumber] ?? new StringList(); + replaceCandidates.Value.Add(input.NewPubkey); + State.ReplaceCandidateMap[input.CurrentTermNumber] = replaceCandidates; } - #endregion + State.IsReplacedEvilMiner[input.NewPubkey] = true; + + return new Empty(); + } + + public override Empty SetProfitsReceiver(SetProfitsReceiverInput input) + { + if (State.ElectionContract.Value == null) + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - public override GetWelfareRewardAmountSampleOutput GetWelfareRewardAmountSample( - GetWelfareRewardAmountSampleInput input) + var admin = State.ElectionContract.GetCandidateAdmin.Call(new StringValue { Value = input.Pubkey }); + Assert(Context.Origin == admin, "No permission."); + State.ProfitsReceiverMap[input.Pubkey] = input.ProfitsReceiverAddress; + State.ElectionContract.SetProfitsReceiver.Send(new Election.SetProfitsReceiverInput { - const long sampleAmount = 10000; - var welfareHash = State.WelfareHash.Value; - var output = new GetWelfareRewardAmountSampleOutput(); - var welfareScheme = State.ProfitContract.GetScheme.Call(welfareHash); - var releasedInformation = State.ProfitContract.GetDistributedProfitsInfo.Call( - new SchemePeriod - { - SchemeId = welfareHash, - Period = welfareScheme.CurrentPeriod.Sub(1) - }); - var totalShares = releasedInformation.TotalShares; - if (totalShares == 0) - { - return new GetWelfareRewardAmountSampleOutput(); - } + CandidateAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)), + ReceiverAddress = input.ProfitsReceiverAddress + }); + return new Empty(); + } - var totalAmount = releasedInformation.AmountsMap; - foreach (var lockTime in input.Value) - { - var shares = GetVotesWeight(sampleAmount, lockTime); - // In case of arithmetic overflow - var decimalAmount = (decimal) totalAmount[Context.Variables.NativeSymbol]; - var decimalShares = (decimal) shares; - var decimalTotalShares = (decimal) totalShares; - var amount = decimalAmount * decimalShares / decimalTotalShares; - output.Value.Add((long) amount); - } + public override Address GetProfitsReceiver(StringValue input) + { + return GetProfitsReceiver(input.Value); + } - return output; - } + private Address GetProfitsReceiver(string pubkey) + { + return State.ProfitsReceiverMap[pubkey] ?? + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(pubkey)); + } - public override Dividends GetUndistributedDividends(Empty input) - { - return new Dividends - { - Value = - { - State.SymbolList.Value.Value.Select(s => State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = State.TreasuryVirtualAddress.Value, - Symbol = s - })).ToDictionary(b => b.Symbol, b => b.Balance) - } - }; - } + private List
GetAddressesFromCandidatePubkeys(ICollection pubkeys) + { + var addresses = pubkeys.Select(k => Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(k))) + .ToList(); + addresses.AddRange(pubkeys.Select(GetProfitsReceiver)); + return addresses; + } - public override Hash GetTreasurySchemeId(Empty input) + #region Private methods + + private void ConvertToNativeToken(string symbol, long amount) + { + State.TokenContract.Approve.Send(new ApproveInput { - return State.TreasuryHash.Value ?? Hash.Empty; - } + Spender = State.TokenConverterContract.Value, + Symbol = symbol, + Amount = amount + }); - public override AuthorityInfo GetTreasuryController(Empty input) + State.TokenConverterContract.Sell.Send(new SellInput { - if (State.TreasuryController.Value == null) - { - return GetDefaultTreasuryController(); - } + Symbol = symbol, + Amount = amount + }); - return State.TreasuryController.Value; - } + Context.SendInline(Context.Self, nameof(DonateAll), new DonateAllInput + { + Symbol = Context.Variables.NativeSymbol + }); + } - public override SymbolList GetSymbolList(Empty input) + private void BuildTreasury() + { + if (State.DividendPoolWeightSetting.Value == null) { - return State.SymbolList.Value; + var dividendPoolWeightSetting = GetDefaultDividendPoolWeightSetting(); + ResetSubSchemeToTreasury(dividendPoolWeightSetting); + State.DividendPoolWeightSetting.Value = dividendPoolWeightSetting; } - public override MinerRewardWeightProportion GetMinerRewardWeightProportion(Empty input) + if (State.MinerRewardWeightSetting.Value == null) { - var weightSetting = State.MinerRewardWeightSetting.Value ?? GetDefaultMinerRewardWeightSetting(); - var weightSum = weightSetting.BasicMinerRewardWeight.Add(weightSetting.WelcomeRewardWeight) - .Add(weightSetting.FlexibleRewardWeight); - var weightProportion = new MinerRewardWeightProportion - { - BasicMinerRewardProportionInfo = new SchemeProportionInfo - { - SchemeId = State.BasicRewardHash.Value, - Proportion = weightSetting.BasicMinerRewardWeight - .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) - }, - WelcomeRewardProportionInfo = new SchemeProportionInfo - { - SchemeId = State.VotesWeightRewardHash.Value, - Proportion = weightSetting.WelcomeRewardWeight - .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) - } - }; - weightProportion.FlexibleRewardProportionInfo = new SchemeProportionInfo - { - SchemeId = State.ReElectionRewardHash.Value, - Proportion = TreasuryContractConstants.OneHundredPercent - .Sub(weightProportion.BasicMinerRewardProportionInfo.Proportion) - .Sub(weightProportion.WelcomeRewardProportionInfo.Proportion) - }; - return weightProportion; + var minerRewardWeightSetting = GetDefaultMinerRewardWeightSetting(); + ResetSubSchemeToMinerReward(minerRewardWeightSetting); + State.MinerRewardWeightSetting.Value = minerRewardWeightSetting; } + } - public override DividendPoolWeightProportion GetDividendPoolWeightProportion(Empty input) + private void ReleaseTreasurySubProfitItems(long termNumber) + { + var amountsMap = State.SymbolList.Value.Value.ToDictionary(s => s, s => 0L); + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - var weightSetting = State.DividendPoolWeightSetting.Value ?? GetDefaultDividendPoolWeightSetting(); - var weightSum = weightSetting.BackupSubsidyWeight.Add(weightSetting.CitizenWelfareWeight) - .Add(weightSetting.MinerRewardWeight); - var weightProportion = new DividendPoolWeightProportion - { - BackupSubsidyProportionInfo = new SchemeProportionInfo - { - SchemeId = State.SubsidyHash.Value, - Proportion = weightSetting.BackupSubsidyWeight - .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) - }, - CitizenWelfareProportionInfo = new SchemeProportionInfo - { - SchemeId = State.WelfareHash.Value, - Proportion = weightSetting.CitizenWelfareWeight - .Mul(TreasuryContractConstants.OneHundredPercent).Div(weightSum) - } - }; - weightProportion.MinerRewardProportionInfo = new SchemeProportionInfo - { - SchemeId = State.RewardHash.Value, - Proportion = TreasuryContractConstants.OneHundredPercent - .Sub(weightProportion.BackupSubsidyProportionInfo.Proportion) - .Sub(weightProportion.CitizenWelfareProportionInfo.Proportion) - }; - return weightProportion; - } + SchemeId = State.RewardHash.Value, + Period = termNumber, + AmountsMap = { amountsMap } + }); - private long GetVotesWeight(long votesAmount, long lockTime) + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - RequireElectionContractStateSet(); - var weight = State.ElectionContract.GetCalculateVoteWeight.Call(new VoteInformation - { - Amount = votesAmount, - LockTime = lockTime - }); - return weight.Value; - } + SchemeId = State.VotesWeightRewardHash.Value, + Period = termNumber, + AmountsMap = { amountsMap } + }); - private DividendPoolWeightSetting GetDefaultDividendPoolWeightSetting() + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - return new DividendPoolWeightSetting - { - CitizenWelfareWeight = 15, - BackupSubsidyWeight = 1, - MinerRewardWeight = 4 - }; - } + SchemeId = State.ReElectionRewardHash.Value, + Period = termNumber, + AmountsMap = { amountsMap } + }); - private MinerRewardWeightSetting GetDefaultMinerRewardWeightSetting() + State.ProfitContract.DistributeProfits.Send(new DistributeProfitsInput { - return new MinerRewardWeightSetting - { - BasicMinerRewardWeight = 2, - WelcomeRewardWeight = 1, - FlexibleRewardWeight = 1 - }; - } + SchemeId = State.BasicRewardHash.Value, + Period = termNumber, + AmountsMap = { amountsMap } + }); + } - private void ResetSubSchemeToTreasury(DividendPoolWeightSetting newWeightSetting) - { - var oldWeightSetting = State.DividendPoolWeightSetting.Value ?? new DividendPoolWeightSetting(); - var parentSchemeId = State.TreasuryHash.Value; - // Register or reset `MinerReward` to `Treasury` - ResetWeight(parentSchemeId, State.RewardHash.Value, - oldWeightSetting.MinerRewardWeight, newWeightSetting.MinerRewardWeight); - // Register or reset `BackupSubsidy` to `Treasury` - ResetWeight(parentSchemeId, State.SubsidyHash.Value, - oldWeightSetting.BackupSubsidyWeight, newWeightSetting.BackupSubsidyWeight); - // Register or reset `CitizenWelfare` to `Treasury` - ResetWeight(parentSchemeId, State.WelfareHash.Value, - oldWeightSetting.CitizenWelfareWeight, newWeightSetting.CitizenWelfareWeight); - } + private void RequireAEDPoSContractStateSet() + { + if (State.AEDPoSContract.Value == null) + State.AEDPoSContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + } - private void ResetSubSchemeToMinerReward(MinerRewardWeightSetting newWeightSetting) - { - var oldWeightSetting = State.MinerRewardWeightSetting.Value ?? new MinerRewardWeightSetting(); - var parentSchemeId = State.RewardHash.Value; - // Register or reset `MinerBasicReward` to `MinerReward` - ResetWeight(parentSchemeId, State.BasicRewardHash.Value, - oldWeightSetting.BasicMinerRewardWeight, newWeightSetting.BasicMinerRewardWeight); - // Register or reset `WelcomeRewardWeight` to `MinerReward` - ResetWeight(parentSchemeId, State.VotesWeightRewardHash.Value, - oldWeightSetting.WelcomeRewardWeight, newWeightSetting.WelcomeRewardWeight); - // Register or reset `FlexibleRewardWeight` to `MinerReward` - ResetWeight(parentSchemeId, State.ReElectionRewardHash.Value, - oldWeightSetting.FlexibleRewardWeight, newWeightSetting.FlexibleRewardWeight); - } + private void RequireElectionContractStateSet() + { + if (State.ElectionContract.Value == null) + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + } - private void ResetWeight(Hash parentSchemeId, Hash subSchemeId, int oldWeight, - int newWeight) + private void UpdateStateBeforeDistribution(Round previousTermInformation, List newElectedMiners) + { + var previousPreviousTermInformation = State.AEDPoSContract.GetPreviousTermInformation.Call(new Int64Value { - if (oldWeight == newWeight) - return; + Value = previousTermInformation.TermNumber.Sub(1) + }); - // old weight equals 0 indicates the subScheme has not been registered - if (oldWeight > 0) - State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput - { - SchemeId = parentSchemeId, - SubSchemeId = subSchemeId - }); + if (newElectedMiners.Any()) State.HasNewMiner[previousTermInformation.TermNumber.Add(1)] = true; - State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput + Context.LogDebug(() => $"Will update weights after term {previousTermInformation.TermNumber}"); + UpdateBasicMinerRewardWeights(new List { previousPreviousTermInformation, previousTermInformation }); + UpdateWelcomeRewardWeights(previousTermInformation, newElectedMiners); + UpdateFlexibleRewardWeights(previousTermInformation); + } + + private void UpdateStateAfterDistribution(Round previousTermInformation, List currentMinerList) + { + foreach (var miner in currentMinerList) State.LatestMinedTerm[miner] = previousTermInformation.TermNumber; + } + + /// + /// Remove current total shares of Basic Reward, + /// Add new shares for miners of next term. + /// 1 share for each miner. + /// + /// + private void UpdateBasicMinerRewardWeights(IReadOnlyCollection previousTermInformation) + { + if (previousTermInformation.First().RealTimeMinersInformation != null) + State.ProfitContract.RemoveBeneficiaries.Send(new RemoveBeneficiariesInput { - SchemeId = parentSchemeId, - SubSchemeId = subSchemeId, - SubSchemeShares = newWeight + SchemeId = State.BasicRewardHash.Value, + Beneficiaries = + { + GetAddressesFromCandidatePubkeys(previousTermInformation.First().RealTimeMinersInformation.Keys) + } }); - } - - public override Empty UpdateMiningReward(Int64Value input) - { - Assert(Context.Sender == - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName), - "Only consensus contract can update mining reward."); - State.MiningReward.Value = input.Value; - return new Empty(); - } - public override Dividends GetDividends(Int64Value input) + var averageProducedBlocksCount = CalculateAverage(previousTermInformation.Last().RealTimeMinersInformation + .Values + .Select(i => i.ProducedBlocks).ToList()); + // Manage weights of `MinerBasicReward` + State.ProfitContract.AddBeneficiaries.Send(new AddBeneficiariesInput { - Assert(Context.CurrentHeight > input.Value, "Cannot query dividends of a future block."); - var dividends = State.DonatedDividends[input.Value]; - - if (dividends != null && dividends.Value.ContainsKey(Context.Variables.NativeSymbol)) - { - dividends.Value[Context.Variables.NativeSymbol] = - dividends.Value[Context.Variables.NativeSymbol].Add(State.MiningReward.Value); - } - else + SchemeId = State.BasicRewardHash.Value, + EndPeriod = previousTermInformation.Last().TermNumber, + BeneficiaryShares = { - dividends = new Dividends + previousTermInformation.Last().RealTimeMinersInformation.Values.Select(i => { - Value = + long shares; + if (State.IsReplacedEvilMiner[i.Pubkey]) { - { - Context.Variables.NativeSymbol, State.MiningReward.Value - } + // The new miner may have more shares than his actually contributes, but it's ok. + shares = i.ProducedBlocks; + // Clear the state asap. + State.IsReplacedEvilMiner.Remove(i.Pubkey); + } + else + { + shares = CalculateShares(i.ProducedBlocks, averageProducedBlocksCount); } - }; - } - return dividends; - } + return new BeneficiaryShare + { + Beneficiary = GetProfitsReceiver(i.Pubkey), + Shares = shares + }; + }) + } + }); + } - public override Empty RecordMinerReplacement(RecordMinerReplacementInput input) - { - Assert( - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName) == Context.Sender, - "Only AEDPoS Contract can record miner replacement."); + /// + /// Just to make sure not using double type. + /// + /// + /// + private long CalculateAverage(List list) + { + var sum = list.Sum(); + return sum.Div(list.Count); + } - if (State.ProfitContract.Value == null) - { - State.ProfitContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); - } + private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) + { + if (producedBlocksCount < averageProducedBlocksCount.Div(2)) + // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. + return 0; - if (!input.IsOldPubkeyEvil) - { - var latestMinedTerm = State.LatestMinedTerm[input.OldPubkey]; - State.LatestMinedTerm[input.NewPubkey] = latestMinedTerm; - State.LatestMinedTerm.Remove(input.OldPubkey); - } - else - { - var replaceCandidates = State.ReplaceCandidateMap[input.CurrentTermNumber] ?? new StringList(); - replaceCandidates.Value.Add(input.NewPubkey); - State.ReplaceCandidateMap[input.CurrentTermNumber] = replaceCandidates; - } + if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) + // If count < (4/5) * average_count, then ratio will be (count / average_count) + return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); - State.IsReplacedEvilMiner[input.NewPubkey] = true; + return producedBlocksCount; + } - return new Empty(); - } + private void UpdateWelcomeRewardWeights(Round previousTermInformation, List newElectedMiners) + { + var previousMinerAddresses = + GetAddressesFromCandidatePubkeys(previousTermInformation.RealTimeMinersInformation.Keys); + var possibleWelcomeBeneficiaries = new RemoveBeneficiariesInput + { + SchemeId = State.VotesWeightRewardHash.Value, + Beneficiaries = { previousMinerAddresses } + }; + State.ProfitContract.RemoveBeneficiaries.Send(possibleWelcomeBeneficiaries); + State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput + { + SchemeId = State.VotesWeightRewardHash.Value, + SubSchemeId = State.BasicRewardHash.Value + }); - public override Empty SetProfitsReceiver(SetProfitsReceiverInput input) + if (newElectedMiners.Any()) { - if (State.ElectionContract.Value == null) + Context.LogDebug(() => "Welcome reward will go to new miners."); + var newBeneficiaries = new AddBeneficiariesInput { - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - } + SchemeId = State.VotesWeightRewardHash.Value, + EndPeriod = previousTermInformation.TermNumber.Add(1) + }; + foreach (var minerAddress in newElectedMiners.Select(GetProfitsReceiver)) + newBeneficiaries.BeneficiaryShares.Add(new BeneficiaryShare + { + Beneficiary = minerAddress, + Shares = 1 + }); - var admin = State.ElectionContract.GetCandidateAdmin.Call(new StringValue {Value = input.Pubkey}); - Assert(Context.Origin == admin, "No permission."); - State.ProfitsReceiverMap[input.Pubkey] = input.ProfitsReceiverAddress; - State.ElectionContract.SetProfitsReceiver.Send(new Election.SetProfitsReceiverInput + if (newBeneficiaries.BeneficiaryShares.Any()) State.ProfitContract.AddBeneficiaries.Send(newBeneficiaries); + } + else + { + Context.LogDebug(() => "Welcome reward will go to Basic Reward."); + State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput { - CandidateAddress = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Pubkey)), - ReceiverAddress = input.ProfitsReceiverAddress + SchemeId = State.VotesWeightRewardHash.Value, + SubSchemeId = State.BasicRewardHash.Value, + SubSchemeShares = 1 }); - return new Empty(); } + } - public override Address GetProfitsReceiver(StringValue input) + private void UpdateFlexibleRewardWeights(Round previousTermInformation) + { + State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput + { + SchemeId = State.ReElectionRewardHash.Value, + SubSchemeId = State.WelfareHash.Value + }); + State.ProfitContract.RemoveSubScheme.Send(new RemoveSubSchemeInput { - return GetProfitsReceiver(input.Value); + SchemeId = State.ReElectionRewardHash.Value, + SubSchemeId = State.BasicRewardHash.Value + }); + if (State.ProfitContract.GetScheme.Call(State.ReElectionRewardHash.Value).TotalShares > 0) + { + var previousMinerAddresses = + GetAddressesFromCandidatePubkeys(previousTermInformation.RealTimeMinersInformation.Keys); + State.ProfitContract.RemoveBeneficiaries.Send(new RemoveBeneficiariesInput + { + SchemeId = State.ReElectionRewardHash.Value, + Beneficiaries = { previousMinerAddresses } + }); } - private Address GetProfitsReceiver(string pubkey) + if (State.HasNewMiner[previousTermInformation.TermNumber]) { - return State.ProfitsReceiverMap[pubkey] ?? - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(pubkey)); + Context.LogDebug(() => "Flexible reward will go to Welfare Reward."); + State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput + { + SchemeId = State.ReElectionRewardHash.Value, + SubSchemeId = State.WelfareHash.Value, + SubSchemeShares = 1 + }); } - - private List
GetAddressesFromCandidatePubkeys(ICollection pubkeys) + else { - var addresses = pubkeys.Select(k => Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(k))) - .ToList(); - addresses.AddRange(pubkeys.Select(GetProfitsReceiver)); - return addresses; + Context.LogDebug(() => "Flexible reward will go to Basic Reward."); + State.ProfitContract.AddSubScheme.Send(new AddSubSchemeInput + { + SchemeId = State.ReElectionRewardHash.Value, + SubSchemeId = State.BasicRewardHash.Value, + SubSchemeShares = 1 + }); } } + + private void AssertPerformedByTreasuryController() + { + if (State.TreasuryController.Value == null) State.TreasuryController.Value = GetDefaultTreasuryController(); + + Assert(Context.Sender == State.TreasuryController.Value.OwnerAddress, "no permission"); + } + + private AuthorityInfo GetDefaultTreasuryController() + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + + return new AuthorityInfo + { + ContractAddress = State.ParliamentContract.Value, + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()) + }; + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/TreasuryContractConstants.cs b/contract/AElf.Contracts.Treasury/TreasuryContractConstants.cs index dbe33815c9..841a65db44 100644 --- a/contract/AElf.Contracts.Treasury/TreasuryContractConstants.cs +++ b/contract/AElf.Contracts.Treasury/TreasuryContractConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Treasury +namespace AElf.Contracts.Treasury; + +public static class TreasuryContractConstants { - public static class TreasuryContractConstants - { - public const int MaximumReElectionRewardShare = 10; - public const int DaySec = 86400; - public const int OneHundredPercent = 100; - } + public const int MaximumReElectionRewardShare = 10; + public const int DaySec = 86400; + public const int OneHundredPercent = 100; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/TreasuryContractState.cs b/contract/AElf.Contracts.Treasury/TreasuryContractState.cs index 874b6eea3c..7a7200d892 100644 --- a/contract/AElf.Contracts.Treasury/TreasuryContractState.cs +++ b/contract/AElf.Contracts.Treasury/TreasuryContractState.cs @@ -1,60 +1,59 @@ -using AElf.Standards.ACS1; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Standards.ACS10; -using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.Treasury +namespace AElf.Contracts.Treasury; + +public partial class TreasuryContractState : ContractState { - public partial class TreasuryContractState : ContractState - { - public SingletonState
TreasuryVirtualAddress { get; set; } + public SingletonState
TreasuryVirtualAddress { get; set; } - public SingletonState Initialized { get; set; } + public SingletonState Initialized { get; set; } - public SingletonState TreasuryHash { get; set; } + public SingletonState TreasuryHash { get; set; } - public SingletonState WelfareHash { get; set; } - public SingletonState SubsidyHash { get; set; } - public SingletonState RewardHash { get; set; } + public SingletonState WelfareHash { get; set; } + public SingletonState SubsidyHash { get; set; } + public SingletonState RewardHash { get; set; } - public SingletonState BasicRewardHash { get; set; } + public SingletonState BasicRewardHash { get; set; } - /// - /// -> Welcome Reward - /// - public SingletonState VotesWeightRewardHash { get; set; } + /// + /// -> Welcome Reward + /// + public SingletonState VotesWeightRewardHash { get; set; } - /// - /// -> Flexible Reward - /// - public SingletonState ReElectionRewardHash { get; set; } + /// + /// -> Flexible Reward + /// + public SingletonState ReElectionRewardHash { get; set; } - public MappedState TransactionFees { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState MethodFeeController { get; set; } - public SingletonState TreasuryController { get; set; } - public SingletonState SymbolList { get; set; } + public SingletonState MethodFeeController { get; set; } + public SingletonState TreasuryController { get; set; } + public SingletonState SymbolList { get; set; } - public SingletonState DividendPoolWeightSetting { get; set; } - public SingletonState MinerRewardWeightSetting { get; set; } + public SingletonState DividendPoolWeightSetting { get; set; } + public SingletonState MinerRewardWeightSetting { get; set; } - public MappedState DonatedDividends { get; set; } + public MappedState DonatedDividends { get; set; } - public SingletonState MiningReward { get; set; } + public SingletonState MiningReward { get; set; } - /// - /// Pubkey -> Latest Mined Term Number. - /// - public MappedState LatestMinedTerm { get; set; } + /// + /// Pubkey -> Latest Mined Term Number. + /// + public MappedState LatestMinedTerm { get; set; } - public MappedState IsReplacedEvilMiner { get; set; } - public MappedState ReplaceCandidateMap { get; set; } + public MappedState IsReplacedEvilMiner { get; set; } + public MappedState ReplaceCandidateMap { get; set; } - public MappedState HasNewMiner { get; set; } + public MappedState HasNewMiner { get; set; } - /// - /// Miner / Backup Pubkey -> Profits Receiver Address - /// - public MappedState ProfitsReceiverMap { get; set; } - } + /// + /// Miner / Backup Pubkey -> Profits Receiver Address + /// + public MappedState ProfitsReceiverMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/TreasuryContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Treasury/TreasuryContract_ACS1_TransactionFeeProvider.cs index 2a7141a3ab..b97ef2ef7e 100644 --- a/contract/AElf.Contracts.Treasury/TreasuryContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Treasury/TreasuryContract_ACS1_TransactionFeeProvider.cs @@ -1,98 +1,90 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Treasury +namespace AElf.Contracts.Treasury; + +public partial class TreasuryContract { - public partial class TreasuryContract + public override Empty SetMethodFee(MethodFees input) { - #region Views + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; - } + return new Empty(); + } - #endregion + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); + State.MethodFeeController.Value = input; + return new Empty(); + } - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + #region Views - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - State.MethodFeeController.Value = input; - return new Empty(); - } + #endregion - #region private methods + #region private methods - private void RequiredMethodFeeControllerSet() - { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } - - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + var defaultAuthority = new AuthorityInfo { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } - - #endregion + State.MethodFeeController.Value = defaultAuthority; + } + + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } + + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; } + + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); + } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/AElf.Contracts.Vote.csproj b/contract/AElf.Contracts.Vote/AElf.Contracts.Vote.csproj index 6182fe10b6..4efe86b949 100644 --- a/contract/AElf.Contracts.Vote/AElf.Contracts.Vote.csproj +++ b/contract/AElf.Contracts.Vote/AElf.Contracts.Vote.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,11 +9,11 @@ - true + true - true + true diff --git a/contract/AElf.Contracts.Vote/ContractsReferences.cs b/contract/AElf.Contracts.Vote/ContractsReferences.cs index 45ec645dd1..fcd1fc4770 100644 --- a/contract/AElf.Contracts.Vote/ContractsReferences.cs +++ b/contract/AElf.Contracts.Vote/ContractsReferences.cs @@ -1,11 +1,10 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteContractState { - public partial class VoteContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/README.md b/contract/AElf.Contracts.Vote/README.md index 73dfaad565..0c318b36e9 100644 --- a/contract/AElf.Contracts.Vote/README.md +++ b/contract/AElf.Contracts.Vote/README.md @@ -1,6 +1,7 @@ # Vote Contract -## Actions +## Actions +
InitialVoteContract @@ -41,25 +42,29 @@ For a `Sponsor` to register / create a voting event. - If `Delegated` is true, it means the sender address of `Vote` transaction must be the address of `Sponsor`. -- If `StartTimestamp` of input value is smaller than current block time, will use current block time as `StartTimestamp`. +- If `StartTimestamp` of input value is smaller than current block time, will use current block time as `StartTimestamp` + . -- Cannot create a voting event with maximum active time but only 1 epoch. This means voter can never with their votes. Also, voters cannot vote to a voting event with maximum active time in its last epoch. +- Cannot create a voting event with maximum active time but only 1 epoch. This means voter can never with their votes. + Also, voters cannot vote to a voting event with maximum active time in its last epoch. -- Anyway, voters can withdraw their votes after a certain days according to the value of `VoteContractConsts.MaxActiveDays`. +- Anyway, voters can withdraw their votes after a certain days according to the value + of `VoteContractConsts.MaxActiveDays`.
Vote - + ### Purpose For a `Voter` to vote for a voting going (a epoch of a voting event). ### Notes -- Basically, a voting behaviour is to update related `VotingResult` and `VotingHistories`, also add a new `VotingRecord`. +- Basically, a voting behaviour is to update related `VotingResult` and `VotingHistories`, also add a new `VotingRecord` + . - `VotingHistories` contains vote histories of all `VotingEvent`s - more precisely - `VotingGoing`s of a voter. @@ -69,8 +74,8 @@ For a `Voter` to vote for a voting going (a epoch of a voting event). - We can get a certain `VotingRecord` by providing transaction id of `Vote` transaction, which actually called `VoteId`. -- This method will only lock token if voting event isn't delegated. Delegated voting event should lock in higher level contract, like `Election Contract`. - +- This method will only lock token if voting event isn't delegated. Delegated voting event should lock in higher level + contract, like `Election Contract`.
@@ -86,11 +91,13 @@ For a `Voter` to withdraw his previous votes. - Will update related `VotingResult` and `VotingRecord`. -- Unlock token logic is same as `Vote` method, delegated voting event should unlock token on +- Unlock token logic is same as `Vote` method, delegated voting event should unlock token on -- Cannot withdraw votes of on-going voting events, it means `EpochNumber` of `VotingRecord` must be less than `CurrentEpoch` of `VotingEvent`. +- Cannot withdraw votes of on-going voting events, it means `EpochNumber` of `VotingRecord` must be less + than `CurrentEpoch` of `VotingEvent`. -- Extra limitation of voters withdrawing their votes should be coded in higher level contract. Like in `Election Contract`, voters need to keep locking their tokens at least for several epoches (terms). +- Extra limitation of voters withdrawing their votes should be coded in higher level contract. Like + in `Election Contract`, voters need to keep locking their tokens at least for several epoches (terms).
@@ -110,7 +117,8 @@ For the `Sponsor` to update epoch number. - After updating, votes of previous epoch is possible withdrawable for voters. -- When `TotalEpoch` of `VotingEvent` is `x`, if the `Sponsor` set `EpochNumber` to `x + 1`, the whole voting event will be regarded as terminated immediately. +- When `TotalEpoch` of `VotingEvent` is `x`, if the `Sponsor` set `EpochNumber` to `x + 1`, the whole voting event will + be regarded as terminated immediately. diff --git a/contract/AElf.Contracts.Vote/ViewMethods.cs b/contract/AElf.Contracts.Vote/ViewMethods.cs index 86c679f627..01ecf062fe 100644 --- a/contract/AElf.Contracts.Vote/ViewMethods.cs +++ b/contract/AElf.Contracts.Vote/ViewMethods.cs @@ -1,61 +1,60 @@ using System.Linq; using AElf.Types; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteContract { - public partial class VoteContract + public override VotingRecords GetVotingRecords(GetVotingRecordsInput input) { - public override VotingRecords GetVotingRecords(GetVotingRecordsInput input) - { - var votingRecords = new VotingRecords(); - votingRecords.Records.AddRange(input.Ids.Select(id => State.VotingRecords[id])); - return votingRecords; - } + var votingRecords = new VotingRecords(); + votingRecords.Records.AddRange(input.Ids.Select(id => State.VotingRecords[id])); + return votingRecords; + } - public override VotedItems GetVotedItems(Address input) - { - return State.VotedItemsMap[input] ?? new VotedItems(); - } + public override VotedItems GetVotedItems(Address input) + { + return State.VotedItemsMap[input] ?? new VotedItems(); + } - public override VotingRecord GetVotingRecord(Hash input) - { - var votingRecord = State.VotingRecords[input]; - Assert(votingRecord != null, "Voting record not found."); - return votingRecord; - } + public override VotingRecord GetVotingRecord(Hash input) + { + var votingRecord = State.VotingRecords[input]; + Assert(votingRecord != null, "Voting record not found."); + return votingRecord; + } - public override VotingItem GetVotingItem(GetVotingItemInput input) - { - var votingEvent = State.VotingItems[input.VotingItemId]; - Assert(votingEvent != null, "Voting item not found."); - return votingEvent; - } + public override VotingItem GetVotingItem(GetVotingItemInput input) + { + var votingEvent = State.VotingItems[input.VotingItemId]; + Assert(votingEvent != null, "Voting item not found."); + return votingEvent; + } - public override VotingResult GetVotingResult(GetVotingResultInput input) - { - var votingResultHash = new VotingResult - { - VotingItemId = input.VotingItemId, - SnapshotNumber = input.SnapshotNumber - }.GetHash(); - return State.VotingResults[votingResultHash]; - } - - public override VotingResult GetLatestVotingResult(Hash input) + public override VotingResult GetVotingResult(GetVotingResultInput input) + { + var votingResultHash = new VotingResult { - var votingItem = AssertVotingItem(input); - var votingResultHash = new VotingResult - { - VotingItemId = input, - SnapshotNumber = votingItem.CurrentSnapshotNumber - }.GetHash(); - return State.VotingResults[votingResultHash]; - } - - public override VotedIds GetVotingIds(GetVotingIdsInput input) + VotingItemId = input.VotingItemId, + SnapshotNumber = input.SnapshotNumber + }.GetHash(); + return State.VotingResults[votingResultHash]; + } + + public override VotingResult GetLatestVotingResult(Hash input) + { + var votingItem = AssertVotingItem(input); + var votingResultHash = new VotingResult { - return State.VotedItemsMap[input.Voter].VotedItemVoteIds.Where(p => p.Key == input.VotingItemId.ToHex()) - .Select(p => p.Value).First(); - } + VotingItemId = input, + SnapshotNumber = votingItem.CurrentSnapshotNumber + }.GetHash(); + return State.VotingResults[votingResultHash]; + } + + public override VotedIds GetVotingIds(GetVotingIdsInput input) + { + return State.VotedItemsMap[input.Voter].VotedItemVoteIds.Where(p => p.Key == input.VotingItemId.ToHex()) + .Select(p => p.Value).First(); } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/VoteContract.cs b/contract/AElf.Contracts.Vote/VoteContract.cs index 0a6daab50c..a0d45e61d0 100644 --- a/contract/AElf.Contracts.Vote/VoteContract.cs +++ b/contract/AElf.Contracts.Vote/VoteContract.cs @@ -1,431 +1,402 @@ using System.Linq; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; -using AElf.Types; using AElf.Sdk.CSharp; +using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +/// +/// Comments and documents see README.md of current project. +/// +public partial class VoteContract : VoteContractImplContainer.VoteContractImplBase { /// - /// Comments and documents see README.md of current project. + /// To register a new voting item while filling up with details. /// - public partial class VoteContract : VoteContractImplContainer.VoteContractImplBase + /// + /// + public override Empty Register(VotingRegisterInput input) { - /// - /// To register a new voting item while filling up with details. - /// - /// - /// - public override Empty Register(VotingRegisterInput input) - { - var votingItemId = AssertValidNewVotingItem(input); + var votingItemId = AssertValidNewVotingItem(input); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - // Accepted currency is in white list means this token symbol supports voting. - var isInWhiteList = State.TokenContract.IsInWhiteList.Call(new IsInWhiteListInput - { - Symbol = input.AcceptedCurrency, - Address = Context.Self - }).Value; - Assert(isInWhiteList, "Claimed accepted token is not available for voting."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - // Initialize voting event. - var votingItem = new VotingItem - { - Sponsor = Context.Sender, - VotingItemId = votingItemId, - AcceptedCurrency = input.AcceptedCurrency, - IsLockToken = input.IsLockToken, - TotalSnapshotNumber = input.TotalSnapshotNumber, - CurrentSnapshotNumber = 1, - CurrentSnapshotStartTimestamp = input.StartTimestamp, - StartTimestamp = input.StartTimestamp, - EndTimestamp = input.EndTimestamp, - RegisterTimestamp = Context.CurrentBlockTime, - Options = {input.Options}, - IsQuadratic = input.IsQuadratic, - TicketCost = input.TicketCost - }; - - State.VotingItems[votingItemId] = votingItem; - - // Initialize first voting going information of registered voting event. - var votingResultHash = GetVotingResultHash(votingItemId, 1); - State.VotingResults[votingResultHash] = new VotingResult - { - VotingItemId = votingItemId, - SnapshotNumber = 1, - SnapshotStartTimestamp = input.StartTimestamp - }; - - Context.Fire(new VotingItemRegistered - { - Sponsor = votingItem.Sponsor, - VotingItemId = votingItemId, - AcceptedCurrency = votingItem.AcceptedCurrency, - IsLockToken = votingItem.IsLockToken, - TotalSnapshotNumber = votingItem.TotalSnapshotNumber, - CurrentSnapshotNumber = votingItem.CurrentSnapshotNumber, - CurrentSnapshotStartTimestamp = votingItem.StartTimestamp, - StartTimestamp = votingItem.StartTimestamp, - EndTimestamp = votingItem.EndTimestamp, - RegisterTimestamp = votingItem.RegisterTimestamp, - IsQuadratic = votingItem.IsQuadratic, - TicketCost = votingItem.TicketCost - }); - - return new Empty(); - } + // Accepted currency is in white list means this token symbol supports voting. + var isInWhiteList = State.TokenContract.IsInWhiteList.Call(new IsInWhiteListInput + { + Symbol = input.AcceptedCurrency, + Address = Context.Self + }).Value; + Assert(isInWhiteList, "Claimed accepted token is not available for voting."); - /// - /// Execute the Vote action,save the VoteRecords and update the VotingResults and the VotedItems - /// Before Voting,the VotingItem's token must be locked,except the votes delegated to a contract. - /// - /// VoteInput - /// - public override Empty Vote(VoteInput input) + // Initialize voting event. + var votingItem = new VotingItem { - var votingItem = AssertValidVoteInput(input); - var amount = 0L; - if (!votingItem.IsQuadratic) - { - amount = input.Amount; - } - else - { - var currentVotesCount = State.QuadraticVotesCountMap[input.VoteId].Add(1); - State.QuadraticVotesCountMap[input.VoteId] = currentVotesCount; - amount = votingItem.TicketCost.Mul(currentVotesCount); - } + Sponsor = Context.Sender, + VotingItemId = votingItemId, + AcceptedCurrency = input.AcceptedCurrency, + IsLockToken = input.IsLockToken, + TotalSnapshotNumber = input.TotalSnapshotNumber, + CurrentSnapshotNumber = 1, + CurrentSnapshotStartTimestamp = input.StartTimestamp, + StartTimestamp = input.StartTimestamp, + EndTimestamp = input.EndTimestamp, + RegisterTimestamp = Context.CurrentBlockTime, + Options = { input.Options }, + IsQuadratic = input.IsQuadratic, + TicketCost = input.TicketCost + }; + + State.VotingItems[votingItemId] = votingItem; + + // Initialize first voting going information of registered voting event. + var votingResultHash = GetVotingResultHash(votingItemId, 1); + State.VotingResults[votingResultHash] = new VotingResult + { + VotingItemId = votingItemId, + SnapshotNumber = 1, + SnapshotStartTimestamp = input.StartTimestamp + }; - var votingRecord = new VotingRecord - { - VotingItemId = input.VotingItemId, - Amount = amount, - SnapshotNumber = votingItem.CurrentSnapshotNumber, - Option = input.Option, - IsWithdrawn = false, - VoteTimestamp = Context.CurrentBlockTime, - Voter = input.Voter, - IsChangeTarget = input.IsChangeTarget - }; - - State.VotingRecords[input.VoteId] = votingRecord; - - UpdateVotingResult(votingItem, input.Option, votingItem.IsQuadratic ? 1 : amount); - UpdateVotedItems(input.VoteId, votingRecord.Voter, votingItem); - - if (votingItem.IsLockToken) - { - // Lock voted token. - State.TokenContract.Lock.Send(new LockInput - { - Address = votingRecord.Voter, - Symbol = votingItem.AcceptedCurrency, - LockId = input.VoteId, - Amount = amount - }); - } - - Context.Fire(new Voted - { - VoteId = input.VoteId, - VotingItemId = votingRecord.VotingItemId, - Voter = votingRecord.Voter, - Amount = votingRecord.Amount, - Option = votingRecord.Option, - SnapshotNumber = votingRecord.SnapshotNumber, - VoteTimestamp = votingRecord.VoteTimestamp - }); + Context.Fire(new VotingItemRegistered + { + Sponsor = votingItem.Sponsor, + VotingItemId = votingItemId, + AcceptedCurrency = votingItem.AcceptedCurrency, + IsLockToken = votingItem.IsLockToken, + TotalSnapshotNumber = votingItem.TotalSnapshotNumber, + CurrentSnapshotNumber = votingItem.CurrentSnapshotNumber, + CurrentSnapshotStartTimestamp = votingItem.StartTimestamp, + StartTimestamp = votingItem.StartTimestamp, + EndTimestamp = votingItem.EndTimestamp, + RegisterTimestamp = votingItem.RegisterTimestamp, + IsQuadratic = votingItem.IsQuadratic, + TicketCost = votingItem.TicketCost + }); + + return new Empty(); + } - return new Empty(); + /// + /// Execute the Vote action,save the VoteRecords and update the VotingResults and the VotedItems + /// Before Voting,the VotingItem's token must be locked,except the votes delegated to a contract. + /// + /// VoteInput + /// + public override Empty Vote(VoteInput input) + { + var votingItem = AssertValidVoteInput(input); + var amount = 0L; + if (!votingItem.IsQuadratic) + { + amount = input.Amount; } - - private void UpdateVotedItems(Hash voteId, Address voter, VotingItem votingItem) + else { - var votedItems = State.VotedItemsMap[voter] ?? new VotedItems(); - var voterItemIndex = votingItem.VotingItemId.ToHex(); - if (votedItems.VotedItemVoteIds.ContainsKey(voterItemIndex)) - { - votedItems.VotedItemVoteIds[voterItemIndex].ActiveVotes.Add(voteId); - } - else - { - votedItems.VotedItemVoteIds[voterItemIndex] = - new VotedIds - { - ActiveVotes = {voteId} - }; - } - - votedItems.VotedItemVoteIds[voterItemIndex].WithdrawnVotes.Remove(voteId); - State.VotedItemsMap[voter] = votedItems; + var currentVotesCount = State.QuadraticVotesCountMap[input.VoteId].Add(1); + State.QuadraticVotesCountMap[input.VoteId] = currentVotesCount; + amount = votingItem.TicketCost.Mul(currentVotesCount); } - /// - /// Update the State.VotingResults.include the VotersCount,VotesAmount and the votes int the results[option] - /// - /// - /// - /// - private void UpdateVotingResult(VotingItem votingItem, string option, long amount) + var votingRecord = new VotingRecord { - // Update VotingResult based on this voting behaviour. - var votingResultHash = GetVotingResultHash(votingItem.VotingItemId, votingItem.CurrentSnapshotNumber); - var votingResult = State.VotingResults[votingResultHash]; - if (!votingResult.Results.ContainsKey(option)) + VotingItemId = input.VotingItemId, + Amount = amount, + SnapshotNumber = votingItem.CurrentSnapshotNumber, + Option = input.Option, + IsWithdrawn = false, + VoteTimestamp = Context.CurrentBlockTime, + Voter = input.Voter, + IsChangeTarget = input.IsChangeTarget + }; + + State.VotingRecords[input.VoteId] = votingRecord; + + UpdateVotingResult(votingItem, input.Option, votingItem.IsQuadratic ? 1 : amount); + UpdateVotedItems(input.VoteId, votingRecord.Voter, votingItem); + + if (votingItem.IsLockToken) + // Lock voted token. + State.TokenContract.Lock.Send(new LockInput { - votingResult.Results.Add(option, 0); - } - - var currentVotes = votingResult.Results[option]; - votingResult.Results[option] = currentVotes.Add(amount); - votingResult.VotersCount = votingResult.VotersCount.Add(1); - votingResult.VotesAmount = votingResult.VotesAmount.Add(amount); - State.VotingResults[votingResultHash] = votingResult; - } + Address = votingRecord.Voter, + Symbol = votingItem.AcceptedCurrency, + LockId = input.VoteId, + Amount = amount + }); - /// - /// Withdraw the Votes. - /// first,mark the related record IsWithdrawn. - /// second,delete the vote form ActiveVotes and add the vote to withdrawnVotes. - /// finally,unlock the token that Locked in the VotingItem - /// - /// - /// - public override Empty Withdraw(WithdrawInput input) + Context.Fire(new Voted { - var votingRecord = State.VotingRecords[input.VoteId]; - if (votingRecord == null) - { - throw new AssertionException("Voting record not found."); - } - var votingItem = State.VotingItems[votingRecord.VotingItemId]; + VoteId = input.VoteId, + VotingItemId = votingRecord.VotingItemId, + Voter = votingRecord.Voter, + Amount = votingRecord.Amount, + Option = votingRecord.Option, + SnapshotNumber = votingRecord.SnapshotNumber, + VoteTimestamp = votingRecord.VoteTimestamp + }); + + return new Empty(); + } - if (votingItem.IsLockToken) - { - Assert(votingRecord.Voter == Context.Sender, "No permission to withdraw votes of others."); - } - else - { - Assert(votingItem.Sponsor == Context.Sender, "No permission to withdraw votes of others."); - } + private void UpdateVotedItems(Hash voteId, Address voter, VotingItem votingItem) + { + var votedItems = State.VotedItemsMap[voter] ?? new VotedItems(); + var voterItemIndex = votingItem.VotingItemId.ToHex(); + if (votedItems.VotedItemVoteIds.ContainsKey(voterItemIndex)) + votedItems.VotedItemVoteIds[voterItemIndex].ActiveVotes.Add(voteId); + else + votedItems.VotedItemVoteIds[voterItemIndex] = + new VotedIds + { + ActiveVotes = { voteId } + }; - // Update VotingRecord. - votingRecord.IsWithdrawn = true; - votingRecord.WithdrawTimestamp = Context.CurrentBlockTime; - State.VotingRecords[input.VoteId] = votingRecord; + votedItems.VotedItemVoteIds[voterItemIndex].WithdrawnVotes.Remove(voteId); + State.VotedItemsMap[voter] = votedItems; + } - var votingResultHash = GetVotingResultHash(votingRecord.VotingItemId, votingRecord.SnapshotNumber); + /// + /// Update the State.VotingResults.include the VotersCount,VotesAmount and the votes int the results[option] + /// + /// + /// + /// + private void UpdateVotingResult(VotingItem votingItem, string option, long amount) + { + // Update VotingResult based on this voting behaviour. + var votingResultHash = GetVotingResultHash(votingItem.VotingItemId, votingItem.CurrentSnapshotNumber); + var votingResult = State.VotingResults[votingResultHash]; + if (!votingResult.Results.ContainsKey(option)) votingResult.Results.Add(option, 0); + + var currentVotes = votingResult.Results[option]; + votingResult.Results[option] = currentVotes.Add(amount); + votingResult.VotersCount = votingResult.VotersCount.Add(1); + votingResult.VotesAmount = votingResult.VotesAmount.Add(amount); + State.VotingResults[votingResultHash] = votingResult; + } - var votedItems = State.VotedItemsMap[votingRecord.Voter]; - votedItems.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].ActiveVotes.Remove(input.VoteId); - votedItems.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].WithdrawnVotes.Add(input.VoteId); - State.VotedItemsMap[votingRecord.Voter] = votedItems; + /// + /// Withdraw the Votes. + /// first,mark the related record IsWithdrawn. + /// second,delete the vote form ActiveVotes and add the vote to withdrawnVotes. + /// finally,unlock the token that Locked in the VotingItem + /// + /// + /// + public override Empty Withdraw(WithdrawInput input) + { + var votingRecord = State.VotingRecords[input.VoteId]; + if (votingRecord == null) throw new AssertionException("Voting record not found."); + var votingItem = State.VotingItems[votingRecord.VotingItemId]; - var votingResult = State.VotingResults[votingResultHash]; - votingResult.Results[votingRecord.Option] = - votingResult.Results[votingRecord.Option].Sub(votingRecord.Amount); - if (!votedItems.VotedItemVoteIds[votingRecord.VotingItemId.ToHex()].ActiveVotes.Any()) - { - votingResult.VotersCount = votingResult.VotersCount.Sub(1); - } + if (votingItem.IsLockToken) + Assert(votingRecord.Voter == Context.Sender, "No permission to withdraw votes of others."); + else + Assert(votingItem.Sponsor == Context.Sender, "No permission to withdraw votes of others."); - votingResult.VotesAmount = votingResult.VotesAmount.Sub(votingRecord.Amount); + // Update VotingRecord. + votingRecord.IsWithdrawn = true; + votingRecord.WithdrawTimestamp = Context.CurrentBlockTime; + State.VotingRecords[input.VoteId] = votingRecord; - State.VotingResults[votingResultHash] = votingResult; + var votingResultHash = GetVotingResultHash(votingRecord.VotingItemId, votingRecord.SnapshotNumber); - if (votingItem.IsLockToken) - { - State.TokenContract.Unlock.Send(new UnlockInput - { - Address = votingRecord.Voter, - Symbol = votingItem.AcceptedCurrency, - Amount = votingRecord.Amount, - LockId = input.VoteId - }); - } - - Context.Fire(new Withdrawn + var votedItems = State.VotedItemsMap[votingRecord.Voter]; + votedItems.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].ActiveVotes.Remove(input.VoteId); + votedItems.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].WithdrawnVotes.Add(input.VoteId); + State.VotedItemsMap[votingRecord.Voter] = votedItems; + + var votingResult = State.VotingResults[votingResultHash]; + votingResult.Results[votingRecord.Option] = + votingResult.Results[votingRecord.Option].Sub(votingRecord.Amount); + if (!votedItems.VotedItemVoteIds[votingRecord.VotingItemId.ToHex()].ActiveVotes.Any()) + votingResult.VotersCount = votingResult.VotersCount.Sub(1); + + votingResult.VotesAmount = votingResult.VotesAmount.Sub(votingRecord.Amount); + + State.VotingResults[votingResultHash] = votingResult; + + if (votingItem.IsLockToken) + State.TokenContract.Unlock.Send(new UnlockInput { - VoteId = input.VoteId + Address = votingRecord.Voter, + Symbol = votingItem.AcceptedCurrency, + Amount = votingRecord.Amount, + LockId = input.VoteId }); - return new Empty(); - } - - public override Empty TakeSnapshot(TakeSnapshotInput input) + Context.Fire(new Withdrawn { - var votingItem = AssertVotingItem(input.VotingItemId); + VoteId = input.VoteId + }); - Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can take snapshot."); + return new Empty(); + } - Assert(votingItem.CurrentSnapshotNumber - 1 < votingItem.TotalSnapshotNumber, - "Current voting item already ended."); + public override Empty TakeSnapshot(TakeSnapshotInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); - // Update previous voting going information. - var previousVotingResultHash = GetVotingResultHash(input.VotingItemId, votingItem.CurrentSnapshotNumber); - var previousVotingResult = State.VotingResults[previousVotingResultHash]; - previousVotingResult.SnapshotEndTimestamp = Context.CurrentBlockTime; - State.VotingResults[previousVotingResultHash] = previousVotingResult; + Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can take snapshot."); - Assert(votingItem.CurrentSnapshotNumber == input.SnapshotNumber, - $"Can only take snapshot of current snapshot number: {votingItem.CurrentSnapshotNumber}, but {input.SnapshotNumber}"); - var nextSnapshotNumber = input.SnapshotNumber.Add(1); - votingItem.CurrentSnapshotNumber = nextSnapshotNumber; - State.VotingItems[votingItem.VotingItemId] = votingItem; + Assert(votingItem.CurrentSnapshotNumber - 1 < votingItem.TotalSnapshotNumber, + "Current voting item already ended."); - // Initial next voting going information. - var currentVotingGoingHash = GetVotingResultHash(input.VotingItemId, nextSnapshotNumber); - State.VotingResults[currentVotingGoingHash] = new VotingResult - { - VotingItemId = input.VotingItemId, - SnapshotNumber = nextSnapshotNumber, - SnapshotStartTimestamp = Context.CurrentBlockTime, - VotersCount = previousVotingResult.VotersCount, - VotesAmount = previousVotingResult.VotesAmount - }; - return new Empty(); - } + // Update previous voting going information. + var previousVotingResultHash = GetVotingResultHash(input.VotingItemId, votingItem.CurrentSnapshotNumber); + var previousVotingResult = State.VotingResults[previousVotingResultHash]; + previousVotingResult.SnapshotEndTimestamp = Context.CurrentBlockTime; + State.VotingResults[previousVotingResultHash] = previousVotingResult; - /// - /// Add a option for corresponding VotingItem. - /// - /// - /// - public override Empty AddOption(AddOptionInput input) - { - var votingItem = AssertVotingItem(input.VotingItemId); - Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); - AssertOption(votingItem, input.Option); - Assert(votingItem.Options.Count < VoteContractConstants.MaximumOptionsCount, - $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); - votingItem.Options.Add(input.Option); - State.VotingItems[votingItem.VotingItemId] = votingItem; - return new Empty(); - } + Assert(votingItem.CurrentSnapshotNumber == input.SnapshotNumber, + $"Can only take snapshot of current snapshot number: {votingItem.CurrentSnapshotNumber}, but {input.SnapshotNumber}"); + var nextSnapshotNumber = input.SnapshotNumber.Add(1); + votingItem.CurrentSnapshotNumber = nextSnapshotNumber; + State.VotingItems[votingItem.VotingItemId] = votingItem; - private void AssertOption(VotingItem votingItem, string option) + // Initial next voting going information. + var currentVotingGoingHash = GetVotingResultHash(input.VotingItemId, nextSnapshotNumber); + State.VotingResults[currentVotingGoingHash] = new VotingResult { - Assert(option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); - Assert(!votingItem.Options.Contains(option), "Option already exists."); - } + VotingItemId = input.VotingItemId, + SnapshotNumber = nextSnapshotNumber, + SnapshotStartTimestamp = Context.CurrentBlockTime, + VotersCount = previousVotingResult.VotersCount, + VotesAmount = previousVotingResult.VotesAmount + }; + return new Empty(); + } - /// - /// Delete a option for corresponding VotingItem - /// - /// - /// - public override Empty RemoveOption(RemoveOptionInput input) - { - var votingItem = AssertVotingItem(input.VotingItemId); - Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); - Assert(input.Option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); - Assert(votingItem.Options.Contains(input.Option), "Option doesn't exist."); - votingItem.Options.Remove(input.Option); - State.VotingItems[votingItem.VotingItemId] = votingItem; - return new Empty(); - } + /// + /// Add a option for corresponding VotingItem. + /// + /// + /// + public override Empty AddOption(AddOptionInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); + Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); + AssertOption(votingItem, input.Option); + Assert(votingItem.Options.Count < VoteContractConstants.MaximumOptionsCount, + $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); + votingItem.Options.Add(input.Option); + State.VotingItems[votingItem.VotingItemId] = votingItem; + return new Empty(); + } - public override Empty AddOptions(AddOptionsInput input) - { - var votingItem = AssertVotingItem(input.VotingItemId); - Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); - foreach (var option in input.Options) - { - AssertOption(votingItem, option); - } - votingItem.Options.AddRange(input.Options); - Assert(votingItem.Options.Count <= VoteContractConstants.MaximumOptionsCount, - $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); - State.VotingItems[votingItem.VotingItemId] = votingItem; - return new Empty(); - } + private void AssertOption(VotingItem votingItem, string option) + { + Assert(option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); + Assert(!votingItem.Options.Contains(option), "Option already exists."); + } - public override Empty RemoveOptions(RemoveOptionsInput input) - { - var votingItem = AssertVotingItem(input.VotingItemId); - Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); - foreach (var option in input.Options) - { - Assert(votingItem.Options.Contains(option), "Option doesn't exist."); - Assert(option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); - votingItem.Options.Remove(option); - } + /// + /// Delete a option for corresponding VotingItem + /// + /// + /// + public override Empty RemoveOption(RemoveOptionInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); + Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); + Assert(input.Option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); + Assert(votingItem.Options.Contains(input.Option), "Option doesn't exist."); + votingItem.Options.Remove(input.Option); + State.VotingItems[votingItem.VotingItemId] = votingItem; + return new Empty(); + } - State.VotingItems[votingItem.VotingItemId] = votingItem; - return new Empty(); - } + public override Empty AddOptions(AddOptionsInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); + Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); + foreach (var option in input.Options) AssertOption(votingItem, option); + votingItem.Options.AddRange(input.Options); + Assert(votingItem.Options.Count <= VoteContractConstants.MaximumOptionsCount, + $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); + State.VotingItems[votingItem.VotingItemId] = votingItem; + return new Empty(); + } - private VotingItem AssertVotingItem(Hash votingItemId) + public override Empty RemoveOptions(RemoveOptionsInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); + Assert(votingItem.Sponsor == Context.Sender, "Only sponsor can update options."); + foreach (var option in input.Options) { - var votingItem = State.VotingItems[votingItemId]; - Assert(votingItem != null, $"Voting item not found. {votingItemId.ToHex()}"); - return votingItem; + Assert(votingItem.Options.Contains(option), "Option doesn't exist."); + Assert(option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); + votingItem.Options.Remove(option); } - /// - /// Initialize the related contracts=>TokenContract; - /// - private Hash AssertValidNewVotingItem(VotingRegisterInput input) - { - // Use input without options and sender's address to calculate voting item id. - var votingItemId = input.GetHash(Context.Sender); + State.VotingItems[votingItem.VotingItemId] = votingItem; + return new Empty(); + } - Assert(State.VotingItems[votingItemId] == null, "Voting item already exists."); + private VotingItem AssertVotingItem(Hash votingItemId) + { + var votingItem = State.VotingItems[votingItemId]; + Assert(votingItem != null, $"Voting item not found. {votingItemId.ToHex()}"); + return votingItem; + } - // total snapshot number can't be 0. At least one epoch is required. - if (input.TotalSnapshotNumber == 0) - { - input.TotalSnapshotNumber = 1; - } + /// + /// Initialize the related contracts=>TokenContract; + /// + private Hash AssertValidNewVotingItem(VotingRegisterInput input) + { + // Use input without options and sender's address to calculate voting item id. + var votingItemId = input.GetHash(Context.Sender); - Assert(input.EndTimestamp > input.StartTimestamp, "Invalid active time."); + Assert(State.VotingItems[votingItemId] == null, "Voting item already exists."); - Context.LogDebug(() => $"Voting item created by {Context.Sender}: {votingItemId.ToHex()}"); + // total snapshot number can't be 0. At least one epoch is required. + if (input.TotalSnapshotNumber == 0) input.TotalSnapshotNumber = 1; - return votingItemId; - } + Assert(input.EndTimestamp > input.StartTimestamp, "Invalid active time."); + + Context.LogDebug(() => $"Voting item created by {Context.Sender}: {votingItemId.ToHex()}"); - private Hash GetVotingResultHash(Hash votingItemId, long snapshotNumber) + return votingItemId; + } + + private Hash GetVotingResultHash(Hash votingItemId, long snapshotNumber) + { + return new VotingResult { - return new VotingResult - { - VotingItemId = votingItemId, - SnapshotNumber = snapshotNumber - }.GetHash(); - } + VotingItemId = votingItemId, + SnapshotNumber = snapshotNumber + }.GetHash(); + } - private VotingItem AssertValidVoteInput(VoteInput input) + private VotingItem AssertValidVoteInput(VoteInput input) + { + var votingItem = AssertVotingItem(input.VotingItemId); + Assert(input.Option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); + Assert(votingItem.Options.Contains(input.Option), $"Option {input.Option} not found."); + Assert(votingItem.CurrentSnapshotNumber <= votingItem.TotalSnapshotNumber, + "Current voting item already ended."); + if (!votingItem.IsLockToken) { - var votingItem = AssertVotingItem(input.VotingItemId); - Assert(input.Option.Length <= VoteContractConstants.OptionLengthLimit, "Invalid input."); - Assert(votingItem.Options.Contains(input.Option), $"Option {input.Option} not found."); - Assert(votingItem.CurrentSnapshotNumber <= votingItem.TotalSnapshotNumber, - "Current voting item already ended."); - if (!votingItem.IsLockToken) - { - Assert(votingItem.Sponsor == Context.Sender, "Sender of delegated voting event must be the Sponsor."); - Assert(input.Voter != null, "Voter cannot be null if voting event is delegated."); - Assert(input.VoteId != null, "Vote Id cannot be null if voting event is delegated."); - } - else - { - var votingResultHash = GetVotingResultHash(votingItem.VotingItemId, votingItem.CurrentSnapshotNumber); - var votingResult = State.VotingResults[votingResultHash]; - // Voter = Transaction Sender - input.Voter = Context.Sender; - // VoteId = Transaction Id; - input.VoteId = Context.GenerateId(Context.Self, votingResult.VotesAmount.ToBytes(false)); - } - - return votingItem; + Assert(votingItem.Sponsor == Context.Sender, "Sender of delegated voting event must be the Sponsor."); + Assert(input.Voter != null, "Voter cannot be null if voting event is delegated."); + Assert(input.VoteId != null, "Vote Id cannot be null if voting event is delegated."); } + else + { + var votingResultHash = GetVotingResultHash(votingItem.VotingItemId, votingItem.CurrentSnapshotNumber); + var votingResult = State.VotingResults[votingResultHash]; + // Voter = Transaction Sender + input.Voter = Context.Sender; + // VoteId = Transaction Id; + input.VoteId = Context.GenerateId(Context.Self, votingResult.VotesAmount.ToBytes(false)); + } + + return votingItem; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/VoteContractConstants.cs b/contract/AElf.Contracts.Vote/VoteContractConstants.cs index f2c8a91ac4..b682a5e283 100644 --- a/contract/AElf.Contracts.Vote/VoteContractConstants.cs +++ b/contract/AElf.Contracts.Vote/VoteContractConstants.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public static class VoteContractConstants { - public static class VoteContractConstants - { - public const int MaximumOptionsCount = 64; - public const int OptionLengthLimit = 1024; - } + public const int MaximumOptionsCount = 64; + public const int OptionLengthLimit = 1024; } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/VoteContractState.cs b/contract/AElf.Contracts.Vote/VoteContractState.cs index ec6635d6d2..082efec653 100644 --- a/contract/AElf.Contracts.Vote/VoteContractState.cs +++ b/contract/AElf.Contracts.Vote/VoteContractState.cs @@ -1,35 +1,34 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteContractState : ContractState { - public partial class VoteContractState : ContractState - { - public MappedState VotingItems { get; set; } - - /// - /// This hash is calculated by: voting_item_id & epoch_number - /// - public MappedState VotingResults { get; set; } - - /// - /// VoteId -> VotingRecord - /// - public MappedState VotingRecords { get; set; } - - /// - /// Voter's Address -> VotedItems - /// - public MappedState VotedItemsMap { get; set; } - - public MappedState TransactionFees { get; set; } - - public SingletonState MethodFeeController { get; set; } - - /// - /// Vote Id -> Votes Count - /// - public MappedState QuadraticVotesCountMap { get; set; } - } + public MappedState VotingItems { get; set; } + + /// + /// This hash is calculated by: voting_item_id & epoch_number + /// + public MappedState VotingResults { get; set; } + + /// + /// VoteId -> VotingRecord + /// + public MappedState VotingRecords { get; set; } + + /// + /// Voter's Address -> VotedItems + /// + public MappedState VotedItemsMap { get; set; } + + public MappedState TransactionFees { get; set; } + + public SingletonState MethodFeeController { get; set; } + + /// + /// Vote Id -> Votes Count + /// + public MappedState QuadraticVotesCountMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/VoteContract_ACS1_TransactionFeeProvider.cs b/contract/AElf.Contracts.Vote/VoteContract_ACS1_TransactionFeeProvider.cs index da48046ff9..1795ecf620 100644 --- a/contract/AElf.Contracts.Vote/VoteContract_ACS1_TransactionFeeProvider.cs +++ b/contract/AElf.Contracts.Vote/VoteContract_ACS1_TransactionFeeProvider.cs @@ -1,123 +1,111 @@ +using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.MultiToken; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteContract { - public partial class VoteContract + public override Empty SetMethodFee(MethodFees input) + { + foreach (var methodFee in input.Fees) AssertValidToken(methodFee.Symbol, methodFee.BasicFee); + RequiredMethodFeeControllerSet(); + + Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); + State.TransactionFees[input.MethodName] = input; + + return new Empty(); + } + + public override Empty ChangeMethodFeeController(AuthorityInfo input) + { + RequiredMethodFeeControllerSet(); + AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); + var organizationExist = CheckOrganizationExist(input); + Assert(organizationExist, "Invalid authority input."); + + State.MethodFeeController.Value = input; + return new Empty(); + } + + #region Views + + public override MethodFees GetMethodFee(StringValue input) { - #region Views + var tokenAmounts = State.TransactionFees[input.Value]; + if (tokenAmounts != null) return tokenAmounts; - public override MethodFees GetMethodFee(StringValue input) + switch (input.Value) { - var tokenAmounts = State.TransactionFees[input.Value]; - if (tokenAmounts != null) - { - return tokenAmounts; - } - - switch (input.Value) - { - case nameof(Register): - return new MethodFees + case nameof(Register): + return new MethodFees + { + Fees = { - Fees = - { - new MethodFee {Symbol = Context.Variables.NativeSymbol, BasicFee = 10_00000000} - } - }; - default: - return new MethodFees + new MethodFee { Symbol = Context.Variables.NativeSymbol, BasicFee = 10_00000000 } + } + }; + default: + return new MethodFees + { + Fees = { - Fees = - { - new MethodFee {Symbol = Context.Variables.NativeSymbol, BasicFee = 1_00000000} - } - }; - } - } - - public override AuthorityInfo GetMethodFeeController(Empty input) - { - RequiredMethodFeeControllerSet(); - return State.MethodFeeController.Value; + new MethodFee { Symbol = Context.Variables.NativeSymbol, BasicFee = 1_00000000 } + } + }; } + } - #endregion - - public override Empty SetMethodFee(MethodFees input) - { - foreach (var methodFee in input.Fees) - { - AssertValidToken(methodFee.Symbol, methodFee.BasicFee); - } - RequiredMethodFeeControllerSet(); - - Assert(Context.Sender == State.MethodFeeController.Value.OwnerAddress, "Unauthorized to set method fee."); - State.TransactionFees[input.MethodName] = input; + public override AuthorityInfo GetMethodFeeController(Empty input) + { + RequiredMethodFeeControllerSet(); + return State.MethodFeeController.Value; + } - return new Empty(); - } - - public override Empty ChangeMethodFeeController(AuthorityInfo input) - { - RequiredMethodFeeControllerSet(); - AssertSenderAddressWith(State.MethodFeeController.Value.OwnerAddress); - var organizationExist = CheckOrganizationExist(input); - Assert(organizationExist, "Invalid authority input."); + #endregion - State.MethodFeeController.Value = input; - return new Empty(); - } + #region private methods - #region private methods + private void RequiredMethodFeeControllerSet() + { + if (State.MethodFeeController.Value != null) return; + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - private void RequiredMethodFeeControllerSet() + var defaultAuthority = new AuthorityInfo { - if (State.MethodFeeController.Value != null) return; - if (State.ParliamentContract.Value == null) - { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - } - - var defaultAuthority = new AuthorityInfo - { - OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), - ContractAddress = State.ParliamentContract.Value - }; - - State.MethodFeeController.Value = defaultAuthority; - } + OwnerAddress = State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty()), + ContractAddress = State.ParliamentContract.Value + }; - private void AssertSenderAddressWith(Address address) - { - Assert(Context.Sender == address, "Unauthorized behavior."); - } + State.MethodFeeController.Value = defaultAuthority; + } - private bool CheckOrganizationExist(AuthorityInfo authorityInfo) - { - return Context.Call(authorityInfo.ContractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), - authorityInfo.OwnerAddress).Value; - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender == address, "Unauthorized behavior."); + } - private void AssertValidToken(string symbol, long amount) - { - Assert(amount >= 0, "Invalid amount."); - if (State.TokenContract.Value == null) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - } - - Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue {Value = symbol}).Value, - $"Token {symbol} cannot set as method fee."); - } + private bool CheckOrganizationExist(AuthorityInfo authorityInfo) + { + return Context.Call(authorityInfo.ContractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractReferenceState.ValidateOrganizationExist), + authorityInfo.OwnerAddress).Value; + } - #endregion + private void AssertValidToken(string symbol, long amount) + { + Assert(amount >= 0, "Invalid amount."); + if (State.TokenContract.Value == null) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + Assert(State.TokenContract.IsTokenAvailableForMethodFee.Call(new StringValue { Value = symbol }).Value, + $"Token {symbol} cannot set as method fee."); } + + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Vote/VoteExtensions.cs b/contract/AElf.Contracts.Vote/VoteExtensions.cs index 3289656f85..020dbee282 100644 --- a/contract/AElf.Contracts.Vote/VoteExtensions.cs +++ b/contract/AElf.Contracts.Vote/VoteExtensions.cs @@ -1,23 +1,22 @@ using AElf.Types; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public static class VoteExtensions { - public static class VoteExtensions + public static Hash GetHash(this VotingRegisterInput votingItemInput, Address sponsorAddress) { - public static Hash GetHash(this VotingRegisterInput votingItemInput, Address sponsorAddress) - { - var input = votingItemInput.Clone(); - input.Options.Clear(); - return HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sponsorAddress)); - } + var input = votingItemInput.Clone(); + input.Options.Clear(); + return HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sponsorAddress)); + } - public static Hash GetHash(this VotingResult votingResult) + public static Hash GetHash(this VotingResult votingResult) + { + return HashHelper.ComputeFrom(new VotingResult { - return HashHelper.ComputeFrom(new VotingResult - { - VotingItemId = votingResult.VotingItemId, - SnapshotNumber = votingResult.SnapshotNumber - }); - } + VotingItemId = votingResult.VotingItemId, + SnapshotNumber = votingResult.SnapshotNumber + }); } } \ No newline at end of file diff --git a/contract/Directory.Build.props b/contract/Directory.Build.props index 5596142d44..aea7cb14d8 100644 --- a/contract/Directory.Build.props +++ b/contract/Directory.Build.props @@ -1,7 +1,7 @@ - + - + \ No newline at end of file diff --git a/src/AElf.Blockchains.BasicBaseChain/AElf.Blockchains.BasicBaseChain.csproj b/src/AElf.Blockchains.BasicBaseChain/AElf.Blockchains.BasicBaseChain.csproj index 04ffa72027..e32d4beb7d 100644 --- a/src/AElf.Blockchains.BasicBaseChain/AElf.Blockchains.BasicBaseChain.csproj +++ b/src/AElf.Blockchains.BasicBaseChain/AElf.Blockchains.BasicBaseChain.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,21 +9,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/AElf.Blockchains.BasicBaseChain/BasicBaseChainAElfModule.cs b/src/AElf.Blockchains.BasicBaseChain/BasicBaseChainAElfModule.cs index c5a30136df..0a83ca154c 100644 --- a/src/AElf.Blockchains.BasicBaseChain/BasicBaseChainAElfModule.cs +++ b/src/AElf.Blockchains.BasicBaseChain/BasicBaseChainAElfModule.cs @@ -32,106 +32,104 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Blockchains.BasicBaseChain +namespace AElf.Blockchains.BasicBaseChain; + +[DependsOn( + typeof(CrossChainAElfModule), + typeof(KernelAElfModule), + typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(OSAElfModule), + typeof(AbpAspNetCoreModule), + typeof(CSharpRuntimeAElfModule), + typeof(CSharpCodeOpsAElfModule), + typeof(GrpcNetworkModule), + typeof(RuntimeSetupAElfModule), + typeof(GrpcCrossChainAElfModule), + typeof(GovernmentSystemAElfModule), + typeof(EconomicSystemAElfModule), + + //web api module + typeof(WebWebAppAElfModule), + typeof(ParallelExecutionModule), + + //plugin + typeof(ExecutionPluginForMethodFeeModule), + typeof(ExecutionPluginForResourceFeeModule), + typeof(ExecutionPluginForCallThresholdModule) +)] +public class BasicBaseChainAElfModule : AElfModule { - [DependsOn( - typeof(CrossChainAElfModule), - typeof(KernelAElfModule), - typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(OSAElfModule), - typeof(AbpAspNetCoreModule), - typeof(CSharpRuntimeAElfModule), - typeof(CSharpCodeOpsAElfModule), - typeof(GrpcNetworkModule), - typeof(RuntimeSetupAElfModule), - typeof(GrpcCrossChainAElfModule), - - typeof(GovernmentSystemAElfModule), - typeof(EconomicSystemAElfModule), - - //web api module - typeof(WebWebAppAElfModule), - typeof(ParallelExecutionModule), - - //plugin - typeof(ExecutionPluginForMethodFeeModule), - typeof(ExecutionPluginForResourceFeeModule), - typeof(ExecutionPluginForCallThresholdModule) - )] - public class BasicBaseChainAElfModule : AElfModule + public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } + + public override void PreConfigureServices(ServiceConfigurationContext context) { - public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } + var configuration = context.Services.GetConfiguration(); + var hostingEnvironment = context.Services.GetHostingEnvironment(); + var contentRootPath = hostingEnvironment.ContentRootPath; + var hostBuilderContext = context.Services.GetSingletonInstanceOrNull(); + + var chainType = configuration.GetValue("ChainType", ChainType.MainChain); + var netType = configuration.GetValue("NetType", NetType.MainNet); + + var newConfig = new ConfigurationBuilder().AddConfiguration(configuration) + .AddJsonFile($"appsettings.{chainType}.{netType}.json") + .AddJsonFile($"appsettings.{hostingEnvironment.EnvironmentName}.json", true) + .SetBasePath(contentRootPath) + .Build(); + + hostBuilderContext.Configuration = newConfig; - public override void PreConfigureServices(ServiceConfigurationContext context) + Configure(newConfig.GetSection("Economic")); + Configure(option => { - var configuration = context.Services.GetConfiguration(); - var hostingEnvironment = context.Services.GetHostingEnvironment(); - var contentRootPath = hostingEnvironment.ContentRootPath; - var hostBuilderContext = context.Services.GetSingletonInstanceOrNull(); - - var chainType = configuration.GetValue("ChainType", ChainType.MainChain); - var netType = configuration.GetValue("NetType", NetType.MainNet); - - var newConfig = new ConfigurationBuilder().AddConfiguration(configuration) - .AddJsonFile($"appsettings.{chainType}.{netType}.json") - .AddJsonFile($"appsettings.{hostingEnvironment.EnvironmentName}.json", true) - .SetBasePath(contentRootPath) - .Build(); - - hostBuilderContext.Configuration = newConfig; - - Configure(newConfig.GetSection("Economic")); - Configure(option => - { - option.ChainId = ChainHelper.ConvertBase58ToChainId(newConfig["ChainId"]); - option.ChainType = chainType; - option.NetType = netType; - }); - - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = - newConfig.GetValue("Economic:Symbol", "ELF"); - options.ContextVariables["SymbolListToPayTxFee"] = - newConfig.GetValue("Economic:SymbolListToPayTxFee", "WRITE,READ,STORAGE,TRAFFIC"); - options.ContextVariables["SymbolListToPayRental"] = - newConfig.GetValue("Economic:SymbolListToPayRental", "CPU,RAM,DISK,NET"); - }); - - Configure(newConfig.GetSection("Contract")); - Configure(options => - { - options.GenesisContractDir = Path.Combine(contentRootPath, "genesis"); - }); - Configure(newConfig.GetSection("WebApp")); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) + option.ChainId = ChainHelper.ConvertBase58ToChainId(newConfig["ChainId"]); + option.ChainType = chainType; + option.NetType = netType; + }); + + Configure(options => + { + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = + newConfig.GetValue("Economic:Symbol", "ELF"); + options.ContextVariables["SymbolListToPayTxFee"] = + newConfig.GetValue("Economic:SymbolListToPayTxFee", "WRITE,READ,STORAGE,TRAFFIC"); + options.ContextVariables["SymbolListToPayRental"] = + newConfig.GetValue("Economic:SymbolListToPayRental", "CPU,RAM,DISK,NET"); + }); + + Configure(newConfig.GetSection("Contract")); + Configure(options => { - var chainOptions = context.ServiceProvider.GetService>().Value; - var dto = new OsBlockchainNodeContextStartDto() - { - ChainId = chainOptions.ChainId, - ZeroSmartContract = typeof(BasicContractZero) - }; + options.GenesisContractDir = Path.Combine(contentRootPath, "genesis"); + }); + Configure(newConfig.GetSection("WebApp")); + } - var dtoProvider = context.ServiceProvider.GetRequiredService(); + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var chainOptions = context.ServiceProvider.GetService>().Value; + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = chainOptions.ChainId, + ZeroSmartContract = typeof(BasicContractZero) + }; - dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); - var contractOptions = context.ServiceProvider.GetService>().Value; - dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; + var dtoProvider = context.ServiceProvider.GetRequiredService(); - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); - } + dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); + var contractOptions = context.ServiceProvider.GetService>().Value; + dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; - public override void OnApplicationShutdown(ApplicationShutdownContext context) - { - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); - } + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.BasicBaseChain/GenesisSmartContractDtoProviderBase.cs b/src/AElf.Blockchains.BasicBaseChain/GenesisSmartContractDtoProviderBase.cs index 463af7c62e..844998a236 100644 --- a/src/AElf.Blockchains.BasicBaseChain/GenesisSmartContractDtoProviderBase.cs +++ b/src/AElf.Blockchains.BasicBaseChain/GenesisSmartContractDtoProviderBase.cs @@ -3,50 +3,46 @@ using AElf.Kernel.SmartContract.Application; using AElf.OS.Node.Application; -namespace AElf.Blockchains.BasicBaseChain +namespace AElf.Blockchains.BasicBaseChain; + +/// +/// Provide dtos for genesis block contract deployment and initialization. +/// +public abstract class GenesisSmartContractDtoProviderBase : IGenesisSmartContractDtoProvider { - /// - /// Provide dtos for genesis block contract deployment and initialization. - /// - public abstract class GenesisSmartContractDtoProviderBase : IGenesisSmartContractDtoProvider - { - protected readonly IContractDeploymentListProvider ContractDeploymentListProvider; - protected readonly IEnumerable ContractInitializationProviders; + protected readonly IContractDeploymentListProvider ContractDeploymentListProvider; + protected readonly IEnumerable ContractInitializationProviders; - protected GenesisSmartContractDtoProviderBase(IContractDeploymentListProvider contractDeploymentListProvider, - IEnumerable contractInitializationProviders) - { - ContractDeploymentListProvider = contractDeploymentListProvider; - ContractInitializationProviders = contractInitializationProviders; - } + protected GenesisSmartContractDtoProviderBase(IContractDeploymentListProvider contractDeploymentListProvider, + IEnumerable contractInitializationProviders) + { + ContractDeploymentListProvider = contractDeploymentListProvider; + ContractInitializationProviders = contractInitializationProviders; + } - // TODO: Currently contract deployment logic are same for ContractTestBase, need to fix sooner or later. - public virtual IEnumerable GetGenesisSmartContractDtos() - { - var contractCodes = GetContractCodes(); - var deploymentList = ContractDeploymentListProvider.GetDeployContractNameList(); - return ContractInitializationProviders - .Where(p => deploymentList.Contains(p.SystemSmartContractName)) - .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) - .Select(p => + // TODO: Currently contract deployment logic are same for ContractTestBase, need to fix sooner or later. + public virtual IEnumerable GetGenesisSmartContractDtos() + { + var contractCodes = GetContractCodes(); + var deploymentList = ContractDeploymentListProvider.GetDeployContractNameList(); + return ContractInitializationProviders + .Where(p => deploymentList.Contains(p.SystemSmartContractName)) + .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) + .Select(p => + { + var code = contractCodes[p.ContractCodeName]; + var methodList = p.GetInitializeMethodList(code); + var genesisSmartContractDto = new GenesisSmartContractDto { - var code = contractCodes[p.ContractCodeName]; - var methodList = p.GetInitializeMethodList(code); - var genesisSmartContractDto = new GenesisSmartContractDto - { - Code = code, - SystemSmartContractName = p.SystemSmartContractName, - ContractInitializationMethodCallList = new List() - }; - foreach (var method in methodList) - { - genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - } + Code = code, + SystemSmartContractName = p.SystemSmartContractName, + ContractInitializationMethodCallList = new List() + }; + foreach (var method in methodList) genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - return genesisSmartContractDto; - }); - } - - protected abstract IReadOnlyDictionary GetContractCodes(); + return genesisSmartContractDto; + }); } + + protected abstract IReadOnlyDictionary GetContractCodes(); } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/AElf.Blockchains.MainChain.csproj b/src/AElf.Blockchains.MainChain/AElf.Blockchains.MainChain.csproj index f152f26a14..4765c5a414 100644 --- a/src/AElf.Blockchains.MainChain/AElf.Blockchains.MainChain.csproj +++ b/src/AElf.Blockchains.MainChain/AElf.Blockchains.MainChain.csproj @@ -7,9 +7,9 @@ Main module for a mainchain node. - - - + + + diff --git a/src/AElf.Blockchains.MainChain/CrossChainContractInitializationDataProvider.cs b/src/AElf.Blockchains.MainChain/CrossChainContractInitializationDataProvider.cs index 5ffe29f3c4..8e370ea2b8 100644 --- a/src/AElf.Blockchains.MainChain/CrossChainContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.MainChain/CrossChainContractInitializationDataProvider.cs @@ -1,17 +1,16 @@ using AElf.CrossChain; using Volo.Abp.DependencyInjection; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +public class CrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider, + ITransientDependency { - public class CrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider, - ITransientDependency + public CrossChainContractInitializationData GetContractInitializationData() { - public CrossChainContractInitializationData GetContractInitializationData() + return new CrossChainContractInitializationData { - return new CrossChainContractInitializationData - { - IsPrivilegePreserved = true - }; - } + IsPrivilegePreserved = true + }; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/MainChainAElfModule.cs b/src/AElf.Blockchains.MainChain/MainChainAElfModule.cs index e82a2ad9bd..29bff312d0 100644 --- a/src/AElf.Blockchains.MainChain/MainChainAElfModule.cs +++ b/src/AElf.Blockchains.MainChain/MainChainAElfModule.cs @@ -1,7 +1,7 @@ using AElf.Blockchains.BasicBaseChain; -using AElf.Kernel.SmartContract.Application; using AElf.Database; using AElf.Kernel.Infrastructure; +using AElf.Kernel.SmartContract.Application; using AElf.Modularity; using AElf.OS.Node.Application; using Microsoft.Extensions.Configuration; @@ -10,37 +10,32 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Modularity; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +[DependsOn( + typeof(BasicBaseChainAElfModule) +)] +public class MainChainAElfModule : AElfModule { - [DependsOn( - typeof(BasicBaseChainAElfModule) - )] - public class MainChainAElfModule : AElfModule + public MainChainAElfModule() + { + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public override void ConfigureServices(ServiceConfigurationContext context) { - public ILogger Logger { get; set; } - - public MainChainAElfModule() - { - Logger = NullLogger.Instance; - } + var services = context.Services; + services.AddTransient(); + services.AddTransient(); - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddTransient(); - services.AddTransient(); + var config = context.Services.GetConfiguration(); - var config = context.Services.GetConfiguration(); + if (config.GetConnectionString("BlockchainDb") == "InMemory") + services.AddKeyValueDbContext(p => p.UseInMemoryDatabase()); - if (config.GetConnectionString("BlockchainDb") == "InMemory") - { - services.AddKeyValueDbContext(p => p.UseInMemoryDatabase()); - } - - if (config.GetConnectionString("StateDb") == "InMemory") - { - services.AddKeyValueDbContext(p => p.UseInMemoryDatabase()); - } - } + if (config.GetConnectionString("StateDb") == "InMemory") + services.AddKeyValueDbContext(p => p.UseInMemoryDatabase()); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/MainChainContractDeploymentListProvider.cs b/src/AElf.Blockchains.MainChain/MainChainContractDeploymentListProvider.cs index e2c87bc266..7fae9b9232 100644 --- a/src/AElf.Blockchains.MainChain/MainChainContractDeploymentListProvider.cs +++ b/src/AElf.Blockchains.MainChain/MainChainContractDeploymentListProvider.cs @@ -9,29 +9,28 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +public class MainChainContractDeploymentListProvider : IContractDeploymentListProvider { - public class MainChainContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - VoteSmartContractAddressNameProvider.Name, - ProfitSmartContractAddressNameProvider.Name, - ElectionSmartContractAddressNameProvider.Name, - TreasurySmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - ConfigurationSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - TokenConverterSmartContractAddressNameProvider.Name, - TokenHolderSmartContractAddressNameProvider.Name, - EconomicSmartContractAddressNameProvider.Name, - }; - } + VoteSmartContractAddressNameProvider.Name, + ProfitSmartContractAddressNameProvider.Name, + ElectionSmartContractAddressNameProvider.Name, + TreasurySmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name, + ConfigurationSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + TokenConverterSmartContractAddressNameProvider.Name, + TokenHolderSmartContractAddressNameProvider.Name, + EconomicSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/MainChainGenesisSmartContractDtoProvider.cs b/src/AElf.Blockchains.MainChain/MainChainGenesisSmartContractDtoProvider.cs index cf335b729e..78826cdd23 100644 --- a/src/AElf.Blockchains.MainChain/MainChainGenesisSmartContractDtoProvider.cs +++ b/src/AElf.Blockchains.MainChain/MainChainGenesisSmartContractDtoProvider.cs @@ -5,27 +5,26 @@ using AElf.Kernel.SmartContract.Application; using Microsoft.Extensions.Options; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +/// +/// Provide dtos for genesis block contract deployment and initialization. +/// +public class MainChainGenesisSmartContractDtoProvider : GenesisSmartContractDtoProviderBase { - /// - /// Provide dtos for genesis block contract deployment and initialization. - /// - public class MainChainGenesisSmartContractDtoProvider : GenesisSmartContractDtoProviderBase - { - private readonly ContractOptions _contractOptions; + private readonly ContractOptions _contractOptions; - public MainChainGenesisSmartContractDtoProvider(IContractDeploymentListProvider contractDeploymentListProvider, - IEnumerable contractInitializationProviders, - IOptionsSnapshot contractOptions) - : base(contractDeploymentListProvider, contractInitializationProviders) - { - _contractOptions = contractOptions.Value; - } + public MainChainGenesisSmartContractDtoProvider(IContractDeploymentListProvider contractDeploymentListProvider, + IEnumerable contractInitializationProviders, + IOptionsSnapshot contractOptions) + : base(contractDeploymentListProvider, contractInitializationProviders) + { + _contractOptions = contractOptions.Value; + } - protected override IReadOnlyDictionary GetContractCodes() - { - return ContractsDeployer.GetContractCodes(_contractOptions - .GenesisContractDir); - } + protected override IReadOnlyDictionary GetContractCodes() + { + return ContractsDeployer.GetContractCodes(_contractOptions + .GenesisContractDir); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/ParliamentContractInitializationDataProvider.cs b/src/AElf.Blockchains.MainChain/ParliamentContractInitializationDataProvider.cs index d0bd49b8d8..e29ad31f02 100644 --- a/src/AElf.Blockchains.MainChain/ParliamentContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.MainChain/ParliamentContractInitializationDataProvider.cs @@ -1,15 +1,13 @@ using AElf.GovernmentSystem; -using AElf.Kernel.Proposal; using Volo.Abp.DependencyInjection; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider, + ITransientDependency { - public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider, - ITransientDependency + public ParliamentContractInitializationData GetContractInitializationData() { - public ParliamentContractInitializationData GetContractInitializationData() - { - return new ParliamentContractInitializationData(); - } + return new ParliamentContractInitializationData(); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.MainChain/TokenContractInitializationDataProvider.cs b/src/AElf.Blockchains.MainChain/TokenContractInitializationDataProvider.cs index d95563df07..6e69a39f91 100644 --- a/src/AElf.Blockchains.MainChain/TokenContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.MainChain/TokenContractInitializationDataProvider.cs @@ -1,12 +1,11 @@ using AElf.Kernel.Token; -namespace AElf.Blockchains.MainChain +namespace AElf.Blockchains.MainChain; + +public class TokenContractInitializationDataProvider : ITokenContractInitializationDataProvider { - public class TokenContractInitializationDataProvider : ITokenContractInitializationDataProvider + public TokenContractInitializationData GetContractInitializationData() { - public TokenContractInitializationData GetContractInitializationData() - { - return null; - } + return null; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/AEDPoSContractInitializationDataProvider.cs b/src/AElf.Blockchains.SideChain/AEDPoSContractInitializationDataProvider.cs index 98fbf05673..72a6044edf 100644 --- a/src/AElf.Blockchains.SideChain/AEDPoSContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.SideChain/AEDPoSContractInitializationDataProvider.cs @@ -6,40 +6,39 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class AEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider, + ITransientDependency { - public class AEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider, - ITransientDependency + private readonly ConsensusOptions _consensusOptions; + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public AEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions, + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; - private readonly ConsensusOptions _consensusOptions; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + _consensusOptions = consensusOptions.Value; + } - public AEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions, - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - _consensusOptions = consensusOptions.Value; - } + public AEDPoSContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public AEDPoSContractInitializationData GetContractInitializationData() + var aedPoSContractInitializationData = new AEDPoSContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - var aedPoSContractInitializationData = new AEDPoSContractInitializationData - { - InitialMinerList = sideChainInitializationData == null - ? _consensusOptions.InitialMinerList - : MinerListWithRoundNumber.Parser - .ParseFrom(sideChainInitializationData.ChainInitializationConsensusInfo.InitialConsensusData) - .MinerList.Pubkeys.Select(p => p.ToHex()).ToList(), - StartTimestamp = sideChainInitializationData?.CreationTimestamp ?? _consensusOptions.StartTimestamp, - PeriodSeconds = _consensusOptions.PeriodSeconds, - MiningInterval = _consensusOptions.MiningInterval, - IsSideChain = true - }; + InitialMinerList = sideChainInitializationData == null + ? _consensusOptions.InitialMinerList + : MinerListWithRoundNumber.Parser + .ParseFrom(sideChainInitializationData.ChainInitializationConsensusInfo.InitialConsensusData) + .MinerList.Pubkeys.Select(p => p.ToHex()).ToList(), + StartTimestamp = sideChainInitializationData?.CreationTimestamp ?? _consensusOptions.StartTimestamp, + PeriodSeconds = _consensusOptions.PeriodSeconds, + MiningInterval = _consensusOptions.MiningInterval, + IsSideChain = true + }; - return aedPoSContractInitializationData; - } + return aedPoSContractInitializationData; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/AElf.Blockchains.SideChain.csproj b/src/AElf.Blockchains.SideChain/AElf.Blockchains.SideChain.csproj index d8bb2ee904..f32797732a 100644 --- a/src/AElf.Blockchains.SideChain/AElf.Blockchains.SideChain.csproj +++ b/src/AElf.Blockchains.SideChain/AElf.Blockchains.SideChain.csproj @@ -8,8 +8,8 @@ 1701;1702 - - + + @@ -105,6 +105,6 @@ - +
diff --git a/src/AElf.Blockchains.SideChain/CrossChainContractInitializationDataProvider.cs b/src/AElf.Blockchains.SideChain/CrossChainContractInitializationDataProvider.cs index c63e061b04..2d534b1fdd 100644 --- a/src/AElf.Blockchains.SideChain/CrossChainContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.SideChain/CrossChainContractInitializationDataProvider.cs @@ -2,29 +2,28 @@ using AElf.CrossChain.Application; using Volo.Abp.Threading; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class CrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider { - public class CrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public CrossChainContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public CrossChainContractInitializationDataProvider( - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public CrossChainContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public CrossChainContractInitializationData GetContractInitializationData() + return new CrossChainContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new CrossChainContractInitializationData - { - ParentChainId = _sideChainInitializationDataProvider.ParentChainId, - CreationHeightOnParentChain = sideChainInitializationData.CreationHeightOnParentChain, - IsPrivilegePreserved = sideChainInitializationData.ChainCreatorPrivilegePreserved - }; - } + ParentChainId = _sideChainInitializationDataProvider.ParentChainId, + CreationHeightOnParentChain = sideChainInitializationData.CreationHeightOnParentChain, + IsPrivilegePreserved = sideChainInitializationData.ChainCreatorPrivilegePreserved + }; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/ParliamentContractInitializationDataProvider.cs b/src/AElf.Blockchains.SideChain/ParliamentContractInitializationDataProvider.cs index dc7af3d2f9..8b154ab2f8 100644 --- a/src/AElf.Blockchains.SideChain/ParliamentContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.SideChain/ParliamentContractInitializationDataProvider.cs @@ -1,29 +1,28 @@ using AElf.CrossChain.Application; using AElf.GovernmentSystem; -using AElf.Kernel.Proposal; using Volo.Abp.Threading; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider { - public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public ParliamentContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public ParliamentContractInitializationDataProvider(ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public ParliamentContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public ParliamentContractInitializationData GetContractInitializationData() + return new ParliamentContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new ParliamentContractInitializationData - { - PrivilegedProposer = sideChainInitializationData.Creator, - ProposerAuthorityRequired = sideChainInitializationData.ChainCreatorPrivilegePreserved - }; - } + PrivilegedProposer = sideChainInitializationData.Creator, + ProposerAuthorityRequired = sideChainInitializationData.ChainCreatorPrivilegePreserved + }; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/Protobuf/MinerListExtension.cs b/src/AElf.Blockchains.SideChain/Protobuf/MinerListExtension.cs index e714039c39..f771a32feb 100644 --- a/src/AElf.Blockchains.SideChain/Protobuf/MinerListExtension.cs +++ b/src/AElf.Blockchains.SideChain/Protobuf/MinerListExtension.cs @@ -4,46 +4,42 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal static class MinerListExtension { - internal static class MinerListExtension + internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in miners.Pubkeys.Distinct() + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in miners.Pubkeys.Distinct() - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/SideChainAElfModule.cs b/src/AElf.Blockchains.SideChain/SideChainAElfModule.cs index fa4e2df41b..956896982a 100644 --- a/src/AElf.Blockchains.SideChain/SideChainAElfModule.cs +++ b/src/AElf.Blockchains.SideChain/SideChainAElfModule.cs @@ -1,6 +1,5 @@ using AElf.Blockchains.BasicBaseChain; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Token; using AElf.Modularity; using AElf.OS.Node.Application; using Microsoft.Extensions.DependencyInjection; @@ -8,24 +7,23 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.Modularity; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +[DependsOn( + typeof(BasicBaseChainAElfModule) +)] +public class SideChainAElfModule : AElfModule { - [DependsOn( - typeof(BasicBaseChainAElfModule) - )] - public class SideChainAElfModule : AElfModule + public SideChainAElfModule() { - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public SideChainAElfModule() - { - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services.AddTransient(); - } + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTransient(); + context.Services.AddTransient(); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/SideChainContractDeploymentListProvider.cs b/src/AElf.Blockchains.SideChain/SideChainContractDeploymentListProvider.cs index fc24d08833..63649c8927 100644 --- a/src/AElf.Blockchains.SideChain/SideChainContractDeploymentListProvider.cs +++ b/src/AElf.Blockchains.SideChain/SideChainContractDeploymentListProvider.cs @@ -9,24 +9,23 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider { - public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - ProfitSmartContractAddressNameProvider.Name, - TokenHolderSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - ConfigurationSmartContractAddressNameProvider.Name - }; - } + ProfitSmartContractAddressNameProvider.Name, + TokenHolderSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name, + ConfigurationSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/SideChainGenesisSmartContractDtoProvider.cs b/src/AElf.Blockchains.SideChain/SideChainGenesisSmartContractDtoProvider.cs index 36855a0a2a..9129de14a5 100644 --- a/src/AElf.Blockchains.SideChain/SideChainGenesisSmartContractDtoProvider.cs +++ b/src/AElf.Blockchains.SideChain/SideChainGenesisSmartContractDtoProvider.cs @@ -1,6 +1,4 @@ using System.Collections.Generic; -using System.Linq; -using AElf.Standards.ACS0; using AElf.Blockchains.BasicBaseChain; using AElf.ContractDeployer; using AElf.CrossChain.Application; @@ -11,43 +9,39 @@ using Microsoft.Extensions.Options; using Volo.Abp.Threading; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class SideChainGenesisSmartContractDtoProvider : GenesisSmartContractDtoProviderBase { - public class SideChainGenesisSmartContractDtoProvider : GenesisSmartContractDtoProviderBase + private readonly ContractOptions _contractOptions; + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public SideChainGenesisSmartContractDtoProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider, + IContractDeploymentListProvider contractDeploymentListProvider, + IEnumerable contractInitializationProviders, + IOptionsSnapshot contractOptions) + : base(contractDeploymentListProvider, contractInitializationProviders) + { + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + _contractOptions = contractOptions.Value; + } + + public ILogger Logger { get; set; } + + public override IEnumerable GetGenesisSmartContractDtos() + { + var chainInitializationData = AsyncHelper.RunSync(async () => + await _sideChainInitializationDataProvider.GetChainInitializationDataAsync()); + + if (chainInitializationData == null) return new List(); + + return base.GetGenesisSmartContractDtos(); + } + + protected override IReadOnlyDictionary GetContractCodes() { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; - private readonly ContractOptions _contractOptions; - - public ILogger Logger { get; set; } - - public SideChainGenesisSmartContractDtoProvider( - ISideChainInitializationDataProvider sideChainInitializationDataProvider, - IContractDeploymentListProvider contractDeploymentListProvider, - IEnumerable contractInitializationProviders, - IOptionsSnapshot contractOptions) - :base(contractDeploymentListProvider, contractInitializationProviders) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - _contractOptions = contractOptions.Value; - } - - public override IEnumerable GetGenesisSmartContractDtos() - { - var chainInitializationData = AsyncHelper.RunSync(async () => - await _sideChainInitializationDataProvider.GetChainInitializationDataAsync()); - - if (chainInitializationData == null) - { - return new List(); - } - - return base.GetGenesisSmartContractDtos(); - } - - protected override IReadOnlyDictionary GetContractCodes() - { - return ContractsDeployer.GetContractCodes(_contractOptions - .GenesisContractDir); - } + return ContractsDeployer.GetContractCodes(_contractOptions + .GenesisContractDir); } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/SideChainInitializationDataProvider.cs b/src/AElf.Blockchains.SideChain/SideChainInitializationDataProvider.cs index 9ae9982474..92ce231828 100644 --- a/src/AElf.Blockchains.SideChain/SideChainInitializationDataProvider.cs +++ b/src/AElf.Blockchains.SideChain/SideChainInitializationDataProvider.cs @@ -1,51 +1,49 @@ using System; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain; using AElf.CrossChain.Application; -using AElf.CrossChain.Communication; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; +using AElf.Standards.ACS7; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider, ISingletonDependency { - public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider, ISingletonDependency + private readonly IBlockchainService _blockchainService; + private readonly IChainInitializationDataPlugin _chainInitializationDataPlugin; + private readonly ChainOptions _chainOptions; + + private ChainInitializationData _chainInitializationData; + + public SideChainInitializationDataProvider(IOptionsSnapshot chainOptions, + IOptionsSnapshot crossChainConfigOptions, + IChainInitializationDataPlugin chainInitializationDataPlugin, IBlockchainService blockchainService) { - private readonly ChainOptions _chainOptions; - private readonly IChainInitializationDataPlugin _chainInitializationDataPlugin; - private readonly IBlockchainService _blockchainService; - - private ChainInitializationData _chainInitializationData; - - public SideChainInitializationDataProvider(IOptionsSnapshot chainOptions, - IOptionsSnapshot crossChainConfigOptions, - IChainInitializationDataPlugin chainInitializationDataPlugin, IBlockchainService blockchainService) - { - _chainOptions = chainOptions.Value; - _chainInitializationDataPlugin = chainInitializationDataPlugin; - _blockchainService = blockchainService; - ParentChainId = ChainHelper.ConvertBase58ToChainId(crossChainConfigOptions.Value.ParentChainId); - } - - public async Task GetChainInitializationDataAsync() - { - if (_chainInitializationData != null) - return _chainInitializationData; - - var chain = await _blockchainService.GetChainAsync(); - if (chain != null) - return null; - - _chainInitializationData = - await _chainInitializationDataPlugin.GetChainInitializationDataAsync(_chainOptions.ChainId); - if (_chainInitializationData == null) - throw new Exception("Initialization data cannot be null for a new side chain."); - + _chainOptions = chainOptions.Value; + _chainInitializationDataPlugin = chainInitializationDataPlugin; + _blockchainService = blockchainService; + ParentChainId = ChainHelper.ConvertBase58ToChainId(crossChainConfigOptions.Value.ParentChainId); + } + + public async Task GetChainInitializationDataAsync() + { + if (_chainInitializationData != null) return _chainInitializationData; - } - public int ParentChainId { get; } + var chain = await _blockchainService.GetChainAsync(); + if (chain != null) + return null; + + _chainInitializationData = + await _chainInitializationDataPlugin.GetChainInitializationDataAsync(_chainOptions.ChainId); + if (_chainInitializationData == null) + throw new Exception("Initialization data cannot be null for a new side chain."); + + return _chainInitializationData; } + + public int ParentChainId { get; } } \ No newline at end of file diff --git a/src/AElf.Blockchains.SideChain/TokenContractInitializationDataProvider.cs b/src/AElf.Blockchains.SideChain/TokenContractInitializationDataProvider.cs index 852648f66a..8c250ec028 100644 --- a/src/AElf.Blockchains.SideChain/TokenContractInitializationDataProvider.cs +++ b/src/AElf.Blockchains.SideChain/TokenContractInitializationDataProvider.cs @@ -5,43 +5,42 @@ using AElf.Types; using Volo.Abp.Threading; -namespace AElf.Blockchains.SideChain +namespace AElf.Blockchains.SideChain; + +public class TokenContractInitializationDataProvider : ITokenContractInitializationDataProvider { - public class TokenContractInitializationDataProvider : ITokenContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public TokenContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public TokenContractInitializationDataProvider( - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public TokenContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public TokenContractInitializationData GetContractInitializationData() + return new TokenContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new TokenContractInitializationData + Creator = sideChainInitializationData.Creator, + ResourceAmount = sideChainInitializationData.ResourceTokenInfo.InitialResourceAmount.ToDictionary( + kv => kv.Key.ToUpper(), + kv => kv.Value), + NativeTokenInfoData = sideChainInitializationData.NativeTokenInfoData, + PrimaryTokenInfoData = sideChainInitializationData.ChainPrimaryTokenInfo?.ChainPrimaryTokenData, + ResourceTokenListData = sideChainInitializationData.ResourceTokenInfo.ResourceTokenListData, + TokenInitialIssueList = + sideChainInitializationData.ChainPrimaryTokenInfo?.SideChainTokenInitialIssueList + .Select(t => new TokenInitialIssue { Address = t.Address, Amount = t.Amount }).ToList(), + RegisteredOtherTokenContractAddresses = new Dictionary { - Creator = sideChainInitializationData.Creator, - ResourceAmount = sideChainInitializationData.ResourceTokenInfo.InitialResourceAmount.ToDictionary( - kv => kv.Key.ToUpper(), - kv => kv.Value), - NativeTokenInfoData = sideChainInitializationData.NativeTokenInfoData, - PrimaryTokenInfoData = sideChainInitializationData.ChainPrimaryTokenInfo?.ChainPrimaryTokenData, - ResourceTokenListData = sideChainInitializationData.ResourceTokenInfo.ResourceTokenListData, - TokenInitialIssueList = - sideChainInitializationData.ChainPrimaryTokenInfo?.SideChainTokenInitialIssueList - .Select(t => new TokenInitialIssue {Address = t.Address, Amount = t.Amount}).ToList(), - RegisteredOtherTokenContractAddresses = new Dictionary { - { - _sideChainInitializationDataProvider.ParentChainId, - sideChainInitializationData.ParentChainTokenContractAddress - } + _sideChainInitializationDataProvider.ParentChainId, + sideChainInitializationData.ParentChainTokenContractAddress } - }; - } + } + }; } } \ 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 1f2554fe37..514b15d639 100644 --- a/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj +++ b/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -8,12 +8,12 @@ - + - - + + diff --git a/src/AElf.CSharp.CodeOps/CSharpCodeOpsAElfModule.cs b/src/AElf.CSharp.CodeOps/CSharpCodeOpsAElfModule.cs index 6b1f1db241..0030830585 100644 --- a/src/AElf.CSharp.CodeOps/CSharpCodeOpsAElfModule.cs +++ b/src/AElf.CSharp.CodeOps/CSharpCodeOpsAElfModule.cs @@ -9,26 +9,25 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +[DependsOn(typeof(CodeCheckAElfModule))] +public class CSharpCodeOpsAElfModule : AElfModule { - [DependsOn(typeof(CodeCheckAElfModule))] - public class CSharpCodeOpsAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - var configuration = context.Services.GetConfiguration(); - Configure(configuration.GetSection("CSharpCodeOps")); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("CSharpCodeOps")); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - } + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/CSharpCodeOpsOptions.cs b/src/AElf.CSharp.CodeOps/CSharpCodeOpsOptions.cs index 86e61bcc0e..797b9a091e 100644 --- a/src/AElf.CSharp.CodeOps/CSharpCodeOpsOptions.cs +++ b/src/AElf.CSharp.CodeOps/CSharpCodeOpsOptions.cs @@ -1,7 +1,6 @@ -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class CSharpCodeOpsOptions { - public class CSharpCodeOpsOptions - { - public int AuditTimeoutDuration { get; set; } = Constants.DefaultAuditTimeoutDuration; - } + public int AuditTimeoutDuration { get; set; } = Constants.DefaultAuditTimeoutDuration; } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/CSharpContractAuditor.cs b/src/AElf.CSharp.CodeOps/CSharpContractAuditor.cs index 964b69eb35..024c258a32 100644 --- a/src/AElf.CSharp.CodeOps/CSharpContractAuditor.cs +++ b/src/AElf.CSharp.CodeOps/CSharpContractAuditor.cs @@ -11,78 +11,66 @@ using Microsoft.Extensions.Options; using Mono.Cecil; +namespace AElf.CSharp.CodeOps; -namespace AElf.CSharp.CodeOps +public class CSharpContractAuditor : IContractAuditor { - public class CSharpContractAuditor : IContractAuditor + private readonly IAcsValidator _acsValidator; + + private readonly IPolicy _policy; + + public CSharpContractAuditor(IPolicy policy, IAcsValidator acsValidator) + { + _policy = policy; + _acsValidator = acsValidator; + } + + public IOptionsMonitor CodeOpsOptionsMonitor { get; set; } + + public int Category { get; } = 0; + + public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) + { + var findings = new List(); + var asm = Assembly.Load(code); + var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); + var cts = new CancellationTokenSource(CodeOpsOptionsMonitor?.CurrentValue.AuditTimeoutDuration ?? + Constants.DefaultAuditTimeoutDuration); + // Run module validators + findings.AddRange(Validate(modDef, cts.Token, isSystemContract)); + + // Run assembly validators (run after module validators since we invoke BindService method below) + findings.AddRange(Validate(asm, cts.Token, isSystemContract)); + + // Run method validators + foreach (var type in modDef.Types) findings.AddRange(ValidateMethodsInType(type, cts.Token, isSystemContract)); + + // Perform ACS validation + if (requiredAcs != null) + findings.AddRange(_acsValidator.Validate(asm, requiredAcs)); + + if (findings.Count > 0) + throw new CSharpCodeCheckException( + $"Contract code did not pass audit. Audit failed for contract: {modDef.Assembly.MainModule.Name}\n" + + string.Join("\n", findings), findings); + } + + private IEnumerable Validate(T t, CancellationToken ct, bool isSystemContract) + { + var validators = _policy.GetValidators().Where(v => !v.SystemContactIgnored || !isSystemContract); + return validators.SelectMany(v => v.Validate(t, ct)); + } + + private IEnumerable ValidateMethodsInType(TypeDefinition type, + CancellationToken ct, bool isSystemContract) { - private readonly IAcsValidator _acsValidator; - - public int Category { get; } = 0; - - public IOptionsMonitor CodeOpsOptionsMonitor { get; set; } - - private readonly IPolicy _policy; - - public CSharpContractAuditor(IPolicy policy, IAcsValidator acsValidator) - { - _policy = policy; - _acsValidator = acsValidator; - } - - public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) - { - var findings = new List(); - var asm = Assembly.Load(code); - var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); - var cts = new CancellationTokenSource(CodeOpsOptionsMonitor?.CurrentValue.AuditTimeoutDuration ?? - Constants.DefaultAuditTimeoutDuration); - // Run module validators - findings.AddRange(Validate(modDef, cts.Token, isSystemContract)); - - // Run assembly validators (run after module validators since we invoke BindService method below) - findings.AddRange(Validate(asm, cts.Token, isSystemContract)); - - // Run method validators - foreach (var type in modDef.Types) - { - findings.AddRange(ValidateMethodsInType(type, cts.Token, isSystemContract)); - } - - // Perform ACS validation - if (requiredAcs != null) - findings.AddRange(_acsValidator.Validate(asm, requiredAcs)); - - if (findings.Count > 0) - { - throw new CSharpCodeCheckException( - $"Contract code did not pass audit. Audit failed for contract: {modDef.Assembly.MainModule.Name}\n" + - string.Join("\n", findings), findings); - } - } - - private IEnumerable Validate(T t, CancellationToken ct, bool isSystemContract) - { - var validators = _policy.GetValidators().Where(v => !v.SystemContactIgnored || !isSystemContract); - return validators.SelectMany(v => v.Validate(t, ct)); - } - - private IEnumerable ValidateMethodsInType(TypeDefinition type, - CancellationToken ct, bool isSystemContract) - { - var findings = new List(); - - foreach (var method in type.Methods) - { - findings.AddRange(Validate(method, ct, isSystemContract)); - } - - foreach (var nestedType in type.NestedTypes) - { - findings.AddRange(ValidateMethodsInType(nestedType, ct, isSystemContract)); - } - - return findings; - } + var findings = new List(); + + foreach (var method in type.Methods) findings.AddRange(Validate(method, ct, isSystemContract)); + + foreach (var nestedType in type.NestedTypes) + findings.AddRange(ValidateMethodsInType(nestedType, ct, isSystemContract)); + + return findings; } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/CSharpContractPatcher.cs b/src/AElf.CSharp.CodeOps/CSharpContractPatcher.cs index 35720073ee..db6f01bcc2 100644 --- a/src/AElf.CSharp.CodeOps/CSharpContractPatcher.cs +++ b/src/AElf.CSharp.CodeOps/CSharpContractPatcher.cs @@ -4,33 +4,32 @@ using AElf.Kernel.CodeCheck.Infrastructure; using Mono.Cecil; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class CSharpContractPatcher : IContractPatcher { - public class CSharpContractPatcher : IContractPatcher + private readonly IPolicy _policy; + + public CSharpContractPatcher(IPolicy policy) { - private readonly IPolicy _policy; + _policy = policy; + } - public CSharpContractPatcher(IPolicy policy) - { - _policy = policy; - } + public byte[] Patch(byte[] code, bool isSystemContract) + { + var assemblyDef = AssemblyDefinition.ReadAssembly(new MemoryStream(code)); + Patch(assemblyDef.MainModule, isSystemContract); + var newCode = new MemoryStream(); + assemblyDef.Write(newCode); + return newCode.ToArray(); + } - public byte[] Patch(byte[] code, bool isSystemContract) - { - var assemblyDef = AssemblyDefinition.ReadAssembly(new MemoryStream(code)); - Patch(assemblyDef.MainModule, isSystemContract); - var newCode = new MemoryStream(); - assemblyDef.Write(newCode); - return newCode.ToArray(); - } + public int Category => 0; - public int Category => 0; - - private void Patch(T t, bool isSystemContract) - { - var patchers = _policy.GetPatchers().Where(p => !p.SystemContactIgnored || !isSystemContract).ToList(); - patchers.ForEach(v => v.Patch(t)); - } + private void Patch(T t, bool isSystemContract) + { + var patchers = _policy.GetPatchers().Where(p => !p.SystemContactIgnored || !isSystemContract).ToList(); + patchers.ForEach(v => v.Patch(t)); } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Constants.cs b/src/AElf.CSharp.CodeOps/Constants.cs index d5ca1d8d8c..8fa9241c9d 100644 --- a/src/AElf.CSharp.CodeOps/Constants.cs +++ b/src/AElf.CSharp.CodeOps/Constants.cs @@ -1,49 +1,48 @@ using System.Collections.Generic; using Mono.Cecil.Cil; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public static class Constants { - public static class Constants - { - public const int DefaultAuditTimeoutDuration = 60000; - public const int MaxInheritanceThreshold = 5; + public const int DefaultAuditTimeoutDuration = 60000; + public const int MaxInheritanceThreshold = 5; - public static readonly HashSet JumpingOpCodes = new HashSet - { - OpCodes.Beq, - OpCodes.Beq_S, - OpCodes.Bge, - OpCodes.Bge_S, - OpCodes.Bge_Un, - OpCodes.Bge_Un_S, - OpCodes.Bgt, - OpCodes.Bgt_S, - OpCodes.Ble, - OpCodes.Ble_S, - OpCodes.Ble_Un, - OpCodes.Blt, - OpCodes.Blt_S, - OpCodes.Bne_Un, - OpCodes.Bne_Un_S, - OpCodes.Br, - OpCodes.Brfalse, - OpCodes.Brfalse_S, - OpCodes.Brtrue, - OpCodes.Brtrue_S, - OpCodes.Br_S - }; + public static readonly HashSet JumpingOpCodes = new() + { + OpCodes.Beq, + OpCodes.Beq_S, + OpCodes.Bge, + OpCodes.Bge_S, + OpCodes.Bge_Un, + OpCodes.Bge_Un_S, + OpCodes.Bgt, + OpCodes.Bgt_S, + OpCodes.Ble, + OpCodes.Ble_S, + OpCodes.Ble_Un, + OpCodes.Blt, + OpCodes.Blt_S, + OpCodes.Bne_Un, + OpCodes.Bne_Un_S, + OpCodes.Br, + OpCodes.Brfalse, + OpCodes.Brfalse_S, + OpCodes.Brtrue, + OpCodes.Brtrue_S, + OpCodes.Br_S + }; - public static readonly HashSet PrimitiveTypes = new HashSet - { - typeof(bool).FullName, - typeof(decimal).FullName, - typeof(short).FullName, - typeof(int).FullName, - typeof(long).FullName, - typeof(ushort).FullName, - typeof(uint).FullName, - typeof(ulong).FullName, - typeof(string).FullName, - }; - } + public static readonly HashSet PrimitiveTypes = new() + { + typeof(bool).FullName, + typeof(decimal).FullName, + typeof(short).FullName, + typeof(int).FullName, + typeof(long).FullName, + typeof(ushort).FullName, + typeof(uint).FullName, + typeof(ulong).FullName, + typeof(string).FullName + }; } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/DescriptorOnlyServiceBinder.cs b/src/AElf.CSharp.CodeOps/DescriptorOnlyServiceBinder.cs index a7953f5bfb..fa0edc0f8e 100644 --- a/src/AElf.CSharp.CodeOps/DescriptorOnlyServiceBinder.cs +++ b/src/AElf.CSharp.CodeOps/DescriptorOnlyServiceBinder.cs @@ -2,27 +2,26 @@ using AElf.CSharp.Core; using Google.Protobuf.Reflection; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class DescriptorOnlyServiceBinder : ServiceBinderBase { - public class DescriptorOnlyServiceBinder : ServiceBinderBase - { - private readonly List _descriptors = new List(); + private readonly List _descriptors = new(); - internal IReadOnlyList GetDescriptors() - { - return _descriptors.AsReadOnly(); - } + internal IReadOnlyList GetDescriptors() + { + return _descriptors.AsReadOnly(); + } - public override void AddMethod( - Method method, - UnaryServerMethod handler) - { - // Do nothing, just an empty implementation to prevent exception, we don't need methods - } + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + // Do nothing, just an empty implementation to prevent exception, we don't need methods + } - public override void AddDescriptor(ServiceDescriptor descriptor) - { - _descriptors.Add(descriptor); - } + public override void AddDescriptor(ServiceDescriptor descriptor) + { + _descriptors.Add(descriptor); } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Exceptions.cs b/src/AElf.CSharp.CodeOps/Exceptions.cs index 68a6efdc3f..6e8303687b 100644 --- a/src/AElf.CSharp.CodeOps/Exceptions.cs +++ b/src/AElf.CSharp.CodeOps/Exceptions.cs @@ -2,45 +2,44 @@ using AElf.CSharp.CodeOps.Validators; using AElf.Kernel.CodeCheck; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class CSharpCodeCheckException : InvalidCodeException { - public class CSharpCodeCheckException : InvalidCodeException + public CSharpCodeCheckException() { - public List Findings { get; } - - public CSharpCodeCheckException() - { - } + } - public CSharpCodeCheckException(string message) : base(message) - { - } + public CSharpCodeCheckException(string message) : base(message) + { + } - public CSharpCodeCheckException(string message, List findings) : base(message) - { - Findings = findings; - } + public CSharpCodeCheckException(string message, List findings) : base(message) + { + Findings = findings; } - - public class ContractAuditTimeoutException : CSharpCodeCheckException + + public List Findings { get; } +} + +public class ContractAuditTimeoutException : CSharpCodeCheckException +{ + public ContractAuditTimeoutException() { - public ContractAuditTimeoutException() - { - } + } - public ContractAuditTimeoutException(string message) : base(message) - { - } + public ContractAuditTimeoutException(string message) : base(message) + { } - - public class MaxInheritanceExceededException : CSharpCodeCheckException +} + +public class MaxInheritanceExceededException : CSharpCodeCheckException +{ + public MaxInheritanceExceededException() { - public MaxInheritanceExceededException() - { - } + } - public MaxInheritanceExceededException(string message) : base(message) - { - } + public MaxInheritanceExceededException(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/ExecutionObserverProxy.cs b/src/AElf.CSharp.CodeOps/ExecutionObserverProxy.cs index 31f9c69c19..d44c8dc107 100644 --- a/src/AElf.CSharp.CodeOps/ExecutionObserverProxy.cs +++ b/src/AElf.CSharp.CodeOps/ExecutionObserverProxy.cs @@ -1,28 +1,27 @@ using System; using AElf.Kernel.SmartContract; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +// Injected into contract, not used directly, kept as a template to compare IL codes +public static class ExecutionObserverProxy { - // Injected into contract, not used directly, kept as a template to compare IL codes - public static class ExecutionObserverProxy - { - [ThreadStatic] private static IExecutionObserver _observer; + [ThreadStatic] private static IExecutionObserver _observer; - public static void SetObserver(IExecutionObserver observer) - { - _observer = observer; - } + public static void SetObserver(IExecutionObserver observer) + { + _observer = observer; + } - public static void BranchCount() - { - if (_observer != null) - _observer.BranchCount(); - } + public static void BranchCount() + { + if (_observer != null) + _observer.BranchCount(); + } - public static void CallCount() - { - if (_observer != null) - _observer.CallCount(); - } + public static void CallCount() + { + if (_observer != null) + _observer.CallCount(); } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Extensions.cs b/src/AElf.CSharp.CodeOps/Extensions.cs index b6129dec48..805f38245e 100644 --- a/src/AElf.CSharp.CodeOps/Extensions.cs +++ b/src/AElf.CSharp.CodeOps/Extensions.cs @@ -2,167 +2,157 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using AElf.Sdk.CSharp; using AElf.Sdk.CSharp.State; using Mono.Cecil; using Mono.Cecil.Cil; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public static class Extensions { - public static class Extensions + public static bool HasSameBody(this MethodDefinition sourceMethod, MethodDefinition targetMethod) { - public static bool HasSameBody(this MethodDefinition sourceMethod, MethodDefinition targetMethod) - { - // Exclude nop opcodes (compile in debug mode adds nop to be able to place breakpoint, ignore those) - var sourceMethodBodyInstructions = sourceMethod.Body.Instructions - .Where(i => i.OpCode != OpCodes.Nop).ToArray(); - var targetMethodBodyInstructions = targetMethod.Body.Instructions - .Where(i => i.OpCode != OpCodes.Nop).ToArray(); - - // Compare method body - return !sourceMethodBodyInstructions.Where((t, i) => - t.ToComparableString() != targetMethodBodyInstructions[i].ToComparableString()).Any(); - } + // Exclude nop opcodes (compile in debug mode adds nop to be able to place breakpoint, ignore those) + var sourceMethodBodyInstructions = sourceMethod.Body.Instructions + .Where(i => i.OpCode != OpCodes.Nop).ToArray(); + var targetMethodBodyInstructions = targetMethod.Body.Instructions + .Where(i => i.OpCode != OpCodes.Nop).ToArray(); + + // Compare method body + return !sourceMethodBodyInstructions.Where((t, i) => + t.ToComparableString() != targetMethodBodyInstructions[i].ToComparableString()).Any(); + } - private static string ToComparableString(this Instruction instruction) - { - string operandStr; - - if (instruction.Operand is FieldDefinition field) - { - operandStr = field.Name; - } - else if (instruction.Operand is Instruction ins) // Is probably branching to another instruction - { - operandStr = ins.OpCode.ToString() + ins.Operand; // May restrict to branching to ret only - } - else - { - operandStr = instruction.Operand?.ToString(); - } + private static string ToComparableString(this Instruction instruction) + { + string operandStr; - return instruction.OpCode + operandStr; - } + if (instruction.Operand is FieldDefinition field) + operandStr = field.Name; + else if (instruction.Operand is Instruction ins) // Is probably branching to another instruction + operandStr = ins.OpCode.ToString() + ins.Operand; // May restrict to branching to ret only + else + operandStr = instruction.Operand?.ToString(); - public static IEnumerable GetResetableStaticFields(this TypeDefinition type) - { - // Get static fields from type - var fields = type.Fields.Where(f => - f.IsPublic && - f.IsStatic && - !(f.IsInitOnly || f.HasConstant) - ).ToList(); + return instruction.OpCode + operandStr; + } - // Get static fields from nested types - fields.AddRange(type.NestedTypes.SelectMany(GetResetableStaticFields)); + public static IEnumerable GetResetableStaticFields(this TypeDefinition type) + { + // Get static fields from type + var fields = type.Fields.Where(f => + f.IsPublic && + f.IsStatic && + !(f.IsInitOnly || f.HasConstant) + ).ToList(); - return fields; - } + // Get static fields from nested types + fields.AddRange(type.NestedTypes.SelectMany(GetResetableStaticFields)); - public static IEnumerable GetAllFields(this TypeDefinition type, Func condition) - { - var fields = type.Fields.Where(condition).ToList(); + return fields; + } - if (type.BaseType is TypeDefinition baseType) - { - fields.AddRange(baseType.GetAllFields(condition)); - } + public static IEnumerable GetAllFields(this TypeDefinition type, + Func condition) + { + var fields = type.Fields.Where(condition).ToList(); - return fields; - } + if (type.BaseType is TypeDefinition baseType) fields.AddRange(baseType.GetAllFields(condition)); + + return fields; + } - private static GenericInstanceType FindGenericInstanceType(TypeDefinition type) + private static GenericInstanceType FindGenericInstanceType(TypeDefinition type) + { + var maxInheritance = Constants.MaxInheritanceThreshold; + while (true) { - var maxInheritance = Constants.MaxInheritanceThreshold; - while (true) + if (maxInheritance-- == 0) + throw new MaxInheritanceExceededException(); + + switch (type.BaseType) { - if (maxInheritance-- == 0) - throw new MaxInheritanceExceededException(); - - switch (type.BaseType) - { - case null: - return null; - case GenericInstanceType genericInstanceType: - return genericInstanceType; - default: - type = type.BaseType.Resolve(); - continue; - } + case null: + return null; + case GenericInstanceType genericInstanceType: + return genericInstanceType; + default: + type = type.BaseType.Resolve(); + continue; } } + } - public static bool IsContractImplementation(this TypeDefinition type) - { - var baseGenericInstanceType = FindGenericInstanceType(type); + public static bool IsContractImplementation(this TypeDefinition type) + { + var baseGenericInstanceType = FindGenericInstanceType(type); - if (baseGenericInstanceType == null) - return false; + if (baseGenericInstanceType == null) + return false; - var elementType = baseGenericInstanceType.ElementType.Resolve(); + var elementType = baseGenericInstanceType.ElementType.Resolve(); - var baseType = GetBaseType(elementType); - - return baseType.Interfaces.Any(i => i.InterfaceType.FullName == typeof(ISmartContract).FullName); - } - - public static bool IsStateImplementation(this TypeDefinition type) - { - return GetBaseType(type).FullName == typeof(StateBase).FullName; - } + var baseType = GetBaseType(elementType); - private static TypeDefinition GetBaseType(this TypeDefinition type) - { - var maxInheritance = Constants.MaxInheritanceThreshold; - while (true) - { - if (maxInheritance-- == 0) - throw new MaxInheritanceExceededException(); + return baseType.Interfaces.Any(i => i.InterfaceType.FullName == typeof(ISmartContract).FullName); + } - if (type.BaseType == null || type.BaseType.FullName == typeof(object).FullName) return type; - type = type.BaseType.Resolve(); - } - } + public static bool IsStateImplementation(this TypeDefinition type) + { + return GetBaseType(type).FullName == typeof(StateBase).FullName; + } - public static bool HasSameParameters(this MethodDefinition sourceMethod, MethodDefinition targetMethod) + private static TypeDefinition GetBaseType(this TypeDefinition type) + { + var maxInheritance = Constants.MaxInheritanceThreshold; + while (true) { - // Don't mind if injected type method has more parameters since we check the body to be the same - return sourceMethod.Parameters.Count == targetMethod.Parameters.Count && - sourceMethod.Parameters.All(sp => - targetMethod.Parameters.SingleOrDefault(tp => - tp.Name == sp.Name && tp.ParameterType.FullName == sp.ParameterType.FullName) != null); - } + if (maxInheritance-- == 0) + throw new MaxInheritanceExceededException(); - public static bool HasSameFields(this TypeDefinition sourceType, TypeDefinition targetType) - { - // Don't mind if injected type has more fields since we check each of the methods' bodies - return sourceType.Fields.Count == targetType.Fields.Count && - sourceType.Fields.All(sp => - targetType.Fields.SingleOrDefault(tp => - tp.Name == sp.Name && tp.FieldType.FullName == sp.FieldType.FullName) != null); + if (type.BaseType == null || type.BaseType.FullName == typeof(object).FullName) return type; + type = type.BaseType.Resolve(); } + } - public static Type FindContractType(this Assembly assembly) - { - var types = assembly.GetTypes(); - return types.SingleOrDefault(t => typeof(ISmartContract).IsAssignableFrom(t) && !t.IsNested); - } - - public static Type FindContractBaseType(this Assembly assembly) - { - var types = assembly.GetTypes(); - return types.SingleOrDefault(t => typeof(ISmartContract).IsAssignableFrom(t) && t.IsNested); - } + public static bool HasSameParameters(this MethodDefinition sourceMethod, MethodDefinition targetMethod) + { + // Don't mind if injected type method has more parameters since we check the body to be the same + return sourceMethod.Parameters.Count == targetMethod.Parameters.Count && + sourceMethod.Parameters.All(sp => + targetMethod.Parameters.SingleOrDefault(tp => + tp.Name == sp.Name && tp.ParameterType.FullName == sp.ParameterType.FullName) != null); + } - public static Type FindContractContainer(this Assembly assembly) - { - var contractBase = FindContractBaseType(assembly); - return contractBase.DeclaringType; - } - - public static Type FindExecutionObserverProxyType(this Assembly assembly) - { - return assembly.GetTypes().SingleOrDefault(t => t.Name == nameof(ExecutionObserverProxy)); - } + public static bool HasSameFields(this TypeDefinition sourceType, TypeDefinition targetType) + { + // Don't mind if injected type has more fields since we check each of the methods' bodies + return sourceType.Fields.Count == targetType.Fields.Count && + sourceType.Fields.All(sp => + targetType.Fields.SingleOrDefault(tp => + tp.Name == sp.Name && tp.FieldType.FullName == sp.FieldType.FullName) != null); + } + + public static Type FindContractType(this Assembly assembly) + { + var types = assembly.GetTypes(); + return types.SingleOrDefault(t => typeof(ISmartContract).IsAssignableFrom(t) && !t.IsNested); + } + + public static Type FindContractBaseType(this Assembly assembly) + { + var types = assembly.GetTypes(); + return types.SingleOrDefault(t => typeof(ISmartContract).IsAssignableFrom(t) && t.IsNested); + } + + public static Type FindContractContainer(this Assembly assembly) + { + var contractBase = FindContractBaseType(assembly); + return contractBase.DeclaringType; + } + + public static Type FindExecutionObserverProxyType(this Assembly assembly) + { + return assembly.GetTypes().SingleOrDefault(t => t.Name == nameof(ExecutionObserverProxy)); } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Instructions/IStateWrittenInstructionInjector.cs b/src/AElf.CSharp.CodeOps/Instructions/IStateWrittenInstructionInjector.cs index 610e9f57f8..bd4e08603f 100644 --- a/src/AElf.CSharp.CodeOps/Instructions/IStateWrittenInstructionInjector.cs +++ b/src/AElf.CSharp.CodeOps/Instructions/IStateWrittenInstructionInjector.cs @@ -9,109 +9,108 @@ using Mono.Cecil.Rocks; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Instructions +namespace AElf.CSharp.CodeOps.Instructions; + +public interface IStateWrittenInstructionInjector { - public interface IStateWrittenInstructionInjector - { - bool IdentifyInstruction(Instruction instruction); + bool IdentifyInstruction(Instruction instruction); - void InjectInstruction(ILProcessor ilProcessor, Instruction originInstruction, - ModuleDefinition moduleDefinition); + void InjectInstruction(ILProcessor ilProcessor, Instruction originInstruction, + ModuleDefinition moduleDefinition); - bool ValidateInstruction(ModuleDefinition moduleDefinition, Instruction instruction); - } + bool ValidateInstruction(ModuleDefinition moduleDefinition, Instruction instruction); +} + +public class StateWrittenInstructionInjector : IStateWrittenInstructionInjector, ITransientDependency +{ + private static readonly ReadOnlyDictionary> MethodCallsIdentifications = + new( + new Dictionary> + { + { typeof(SingletonState).FullName, new HashSet { "set_Value" } }, + { typeof(ReadonlyState).FullName, new HashSet { "set_Value" } }, + { typeof(MappedState).FullName, new HashSet { "set_Item", "Set" } } + }); - public class StateWrittenInstructionInjector : IStateWrittenInstructionInjector, ITransientDependency + private static readonly HashSet PrimitiveTypes = new() { - private static readonly ReadOnlyDictionary> MethodCallsIdentifications = - new ReadOnlyDictionary>( - new Dictionary> - { - {typeof(SingletonState).FullName, new HashSet {"set_Value"}}, - {typeof(ReadonlyState).FullName, new HashSet {"set_Value"}}, - {typeof(MappedState).FullName, new HashSet {"set_Item", "Set"}} - }); - - private static readonly HashSet PrimitiveTypes = new HashSet - { - typeof(int).FullName, typeof(uint).FullName, - typeof(long).FullName, typeof(ulong).FullName, - typeof(bool).FullName - }; + typeof(int).FullName, typeof(uint).FullName, + typeof(long).FullName, typeof(ulong).FullName, + typeof(bool).FullName + }; - public bool IdentifyInstruction(Instruction instruction) - { - if (instruction.OpCode != OpCodes.Callvirt) - return false; - var methodReference = (MethodReference) instruction.Operand; - var declaringType = methodReference.DeclaringType.Resolve(); - if (declaringType == null || !declaringType.HasGenericParameters) - return false; - - var baseTypeFullName = declaringType.BaseType?.FullName; - if (baseTypeFullName == null || - !MethodCallsIdentifications.TryGetValue(baseTypeFullName, out var methodNames) || - !(methodReference.DeclaringType is GenericInstanceType genericType)) - return false; - var argumentType = genericType.GenericArguments.Last().Resolve(); - if (argumentType.IsEnum) - return false; - - var contains = PrimitiveTypes.Contains(argumentType.FullName); - return !contains && methodNames.Contains(methodReference.Name); - } + public bool IdentifyInstruction(Instruction instruction) + { + if (instruction.OpCode != OpCodes.Callvirt) + return false; + var methodReference = (MethodReference)instruction.Operand; + var declaringType = methodReference.DeclaringType.Resolve(); + if (declaringType == null || !declaringType.HasGenericParameters) + return false; + + var baseTypeFullName = declaringType.BaseType?.FullName; + if (baseTypeFullName == null || + !MethodCallsIdentifications.TryGetValue(baseTypeFullName, out var methodNames) || + !(methodReference.DeclaringType is GenericInstanceType genericType)) + return false; + var argumentType = genericType.GenericArguments.Last().Resolve(); + if (argumentType.IsEnum) + return false; + + var contains = PrimitiveTypes.Contains(argumentType.FullName); + return !contains && methodNames.Contains(methodReference.Name); + } - public void InjectInstruction(ILProcessor ilProcessor, Instruction originInstruction, - ModuleDefinition moduleDefinition) - { - ilProcessor.Body.SimplifyMacros(); + public void InjectInstruction(ILProcessor ilProcessor, Instruction originInstruction, + ModuleDefinition moduleDefinition) + { + ilProcessor.Body.SimplifyMacros(); - var localValCount = ilProcessor.Body.Variables.Count; - ilProcessor.Body.Variables.Add(new VariableDefinition(moduleDefinition.ImportReference(typeof(object)))); + var localValCount = ilProcessor.Body.Variables.Count; + ilProcessor.Body.Variables.Add(new VariableDefinition(moduleDefinition.ImportReference(typeof(object)))); - var stocInstruction = - ilProcessor.Create(OpCodes.Stloc_S, ilProcessor.Body.Variables[localValCount]); // pop to local val - ilProcessor.InsertBefore(originInstruction, stocInstruction); + var stocInstruction = + ilProcessor.Create(OpCodes.Stloc_S, ilProcessor.Body.Variables[localValCount]); // pop to local val + ilProcessor.InsertBefore(originInstruction, stocInstruction); - var ldThisInstruction = ilProcessor.Create(OpCodes.Ldarg_0); // this - ilProcessor.InsertAfter(stocInstruction, ldThisInstruction); + var ldThisInstruction = ilProcessor.Create(OpCodes.Ldarg_0); // this + ilProcessor.InsertAfter(stocInstruction, ldThisInstruction); - var getContextInstruction = ilProcessor.Create(OpCodes.Call, - moduleDefinition.ImportReference(typeof(CSharpSmartContractAbstract).GetProperty("Context") - .GetMethod)); // get_Context - ilProcessor.InsertAfter(ldThisInstruction, getContextInstruction); + var getContextInstruction = ilProcessor.Create(OpCodes.Call, + moduleDefinition.ImportReference(typeof(CSharpSmartContractAbstract).GetProperty("Context") + .GetMethod)); // get_Context + ilProcessor.InsertAfter(ldThisInstruction, getContextInstruction); - var ldlocInstruction = - ilProcessor.Create(OpCodes.Ldloc_S, ilProcessor.Body.Variables[localValCount]); // load local val - ilProcessor.InsertAfter(getContextInstruction, ldlocInstruction); + var ldlocInstruction = + ilProcessor.Create(OpCodes.Ldloc_S, ilProcessor.Body.Variables[localValCount]); // load local val + ilProcessor.InsertAfter(getContextInstruction, ldlocInstruction); - var callInstruction = ilProcessor.Create(OpCodes.Callvirt, moduleDefinition.ImportReference( - typeof(CSharpSmartContractContext).GetMethod(nameof(CSharpSmartContractContext.ValidateStateSize)))); - ilProcessor.InsertAfter(ldlocInstruction, callInstruction); + var callInstruction = ilProcessor.Create(OpCodes.Callvirt, moduleDefinition.ImportReference( + typeof(CSharpSmartContractContext).GetMethod(nameof(CSharpSmartContractContext.ValidateStateSize)))); + ilProcessor.InsertAfter(ldlocInstruction, callInstruction); - ilProcessor.Body.OptimizeMacros(); - } + ilProcessor.Body.OptimizeMacros(); + } - public bool ValidateInstruction(ModuleDefinition moduleDefinition, Instruction instruction) + public bool ValidateInstruction(ModuleDefinition moduleDefinition, Instruction instruction) + { + var methodDefinition = moduleDefinition.ImportReference( + typeof(CSharpSmartContractContext).GetMethod(nameof(CSharpSmartContractContext.ValidateStateSize))); + + MethodReference stateSizeLimitInstruction; + try { - var methodDefinition = moduleDefinition.ImportReference( - typeof(CSharpSmartContractContext).GetMethod(nameof(CSharpSmartContractContext.ValidateStateSize))); + stateSizeLimitInstruction = (MethodReference)instruction.Previous?.Operand; + } + catch (InvalidCastException) + { + return false; + } - MethodReference stateSizeLimitInstruction; - try - { - stateSizeLimitInstruction = (MethodReference) instruction.Previous?.Operand; - } - catch (InvalidCastException) - { - return false; - } - - var result = !string.IsNullOrEmpty(stateSizeLimitInstruction?.FullName) && - methodDefinition.FullName == stateSizeLimitInstruction.FullName; + var result = !string.IsNullOrEmpty(stateSizeLimitInstruction?.FullName) && + methodDefinition.FullName == stateSizeLimitInstruction.FullName; - return result; - } + return result; } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Patchers/IPatcher.cs b/src/AElf.CSharp.CodeOps/Patchers/IPatcher.cs index 47d7629501..65723b6b2a 100644 --- a/src/AElf.CSharp.CodeOps/Patchers/IPatcher.cs +++ b/src/AElf.CSharp.CodeOps/Patchers/IPatcher.cs @@ -1,12 +1,11 @@ -namespace AElf.CSharp.CodeOps.Patchers +namespace AElf.CSharp.CodeOps.Patchers; + +public interface IPatcher { - public interface IPatcher - { - bool SystemContactIgnored { get; } - } + bool SystemContactIgnored { get; } +} - public interface IPatcher : IPatcher - { - void Patch(T item); - } +public interface IPatcher : IPatcher +{ + void Patch(T item); } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Patchers/Module/ExecutionObserverInjector.cs b/src/AElf.CSharp.CodeOps/Patchers/Module/ExecutionObserverInjector.cs index 1bd2d1e0d6..dabe13f61f 100644 --- a/src/AElf.CSharp.CodeOps/Patchers/Module/ExecutionObserverInjector.cs +++ b/src/AElf.CSharp.CodeOps/Patchers/Module/ExecutionObserverInjector.cs @@ -1,172 +1,165 @@ using System; -using System.Collections; using System.Linq; using AElf.Kernel.SmartContract; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; -namespace AElf.CSharp.CodeOps.Patchers.Module +namespace AElf.CSharp.CodeOps.Patchers.Module; + +public class ExecutionObserverInjector : IPatcher { - public class ExecutionObserverInjector : IPatcher + public bool SystemContactIgnored => true; + + public void Patch(ModuleDefinition module) { - public bool SystemContactIgnored => true; - - public void Patch(ModuleDefinition module) - { - // Check if already injected, do not double inject - if (module.Types.Select(t => t.Name).Contains(nameof(ExecutionObserverProxy))) - return; - - // ReSharper disable once IdentifierTypo - var nmspace = module.Types.Single(m => m.BaseType is TypeDefinition).Namespace; - - var counterProxy = ConstructCounterProxy(module, nmspace); - - var proxyBranchCountMethod = counterProxy.Methods.Single(m => m.Name == nameof(ExecutionObserverProxy.BranchCount)); - var proxyCallCountMethod = counterProxy.Methods.Single(m => m.Name == nameof(ExecutionObserverProxy.CallCount)); - - // Patch the types - foreach (var typ in module.Types) - { - PatchType(typ, proxyBranchCountMethod, proxyCallCountMethod); - } - - module.Types.Add(counterProxy); - } + // Check if already injected, do not double inject + if (module.Types.Select(t => t.Name).Contains(nameof(ExecutionObserverProxy))) + return; - public static TypeDefinition ConstructCounterProxy(ModuleDefinition module, string nmspace) - { - var observerType = new TypeDefinition( - nmspace, nameof(ExecutionObserverProxy), - TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.Public | TypeAttributes.Class, - module.ImportReference(typeof(object)) - ); - - var observerField = new FieldDefinition( - "_observer", - FieldAttributes.Private | FieldAttributes.Static, - module.ImportReference(typeof(IExecutionObserver) - ) - ); - - // Counter field should be thread static (at least for the test cases) - observerField.CustomAttributes.Add(new CustomAttribute( - module.ImportReference(typeof(ThreadStaticAttribute).GetConstructor(new Type[]{})))); - - observerType.Fields.Add(observerField); - - observerType.Methods.Add(ConstructProxySetObserverMethod(module, observerField)); - observerType.Methods.Add(ConstructProxyBranchCountMethod(module, observerField)); - observerType.Methods.Add(ConstructProxyCallCountMethod(module, observerField)); - - return observerType; - } + // ReSharper disable once IdentifierTypo + var nmspace = module.Types.Single(m => m.BaseType is TypeDefinition).Namespace; - private static MethodDefinition ConstructProxyBranchCountMethod(ModuleDefinition module, FieldReference observerField) - { - var countMethod = new MethodDefinition( - nameof(ExecutionObserverProxy.BranchCount), - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, - module.ImportReference(typeof(void)) - ); - - countMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); - var il = countMethod.Body.GetILProcessor(); - - var ret = il.Create(OpCodes.Ret); - - il.Emit(OpCodes.Ldsfld, observerField); - il.Emit(OpCodes.Brfalse_S, ret); // Do not call if not initialized - il.Emit(OpCodes.Ldsfld, observerField); - il.Emit(OpCodes.Callvirt, module.ImportReference( - typeof(IExecutionObserver).GetMethod(nameof(IExecutionObserver.BranchCount)))); - il.Append(ret); - - return countMethod; - } - - private static MethodDefinition ConstructProxyCallCountMethod(ModuleDefinition module, FieldReference observerField) - { - var countMethod = new MethodDefinition( - nameof(ExecutionObserverProxy.CallCount), - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, - module.ImportReference(typeof(void)) - ); - - countMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); - var il = countMethod.Body.GetILProcessor(); - - var ret = il.Create(OpCodes.Ret); - - il.Emit(OpCodes.Ldsfld, observerField); - il.Emit(OpCodes.Brfalse_S, ret); // Do not call if not initialized - il.Emit(OpCodes.Ldsfld, observerField); - il.Emit(OpCodes.Callvirt, module.ImportReference( - typeof(IExecutionObserver).GetMethod(nameof(IExecutionObserver.CallCount)))); - il.Append(ret); - - return countMethod; - } + var counterProxy = ConstructCounterProxy(module, nmspace); - private static MethodDefinition ConstructProxySetObserverMethod(ModuleDefinition module, FieldReference observerField) - { - var setObserverMethod = new MethodDefinition( - nameof(ExecutionObserverProxy.SetObserver), - MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, - module.ImportReference(typeof(void)) - ); - - setObserverMethod.Parameters.Add(new ParameterDefinition("observer", - ParameterAttributes.In, module.ImportReference(typeof(IExecutionObserver)))); - - var il = setObserverMethod.Body.GetILProcessor(); - - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Stsfld, observerField); - il.Emit(OpCodes.Ret); - - return setObserverMethod; - } + var proxyBranchCountMethod = + counterProxy.Methods.Single(m => m.Name == nameof(ExecutionObserverProxy.BranchCount)); + var proxyCallCountMethod = counterProxy.Methods.Single(m => m.Name == nameof(ExecutionObserverProxy.CallCount)); - private void PatchType(TypeDefinition typ, MethodReference branchCountRef, MethodReference callCountRef) - { - // Patch the methods in the type - foreach (var method in typ.Methods) - { - PatchMethodsWithCounter(method, branchCountRef, callCountRef); - } - - // Patch if there is any nested type within the type - foreach (var nestedType in typ.NestedTypes) - { - PatchType(nestedType, branchCountRef, callCountRef); - } - } + // Patch the types + foreach (var typ in module.Types) PatchType(typ, proxyBranchCountMethod, proxyCallCountMethod); + + module.Types.Add(counterProxy); + } + + public static TypeDefinition ConstructCounterProxy(ModuleDefinition module, string nmspace) + { + var observerType = new TypeDefinition( + nmspace, nameof(ExecutionObserverProxy), + TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.Public | TypeAttributes.Class, + module.ImportReference(typeof(object)) + ); + + var observerField = new FieldDefinition( + "_observer", + FieldAttributes.Private | FieldAttributes.Static, + module.ImportReference(typeof(IExecutionObserver) + ) + ); + + // Counter field should be thread static (at least for the test cases) + observerField.CustomAttributes.Add(new CustomAttribute( + module.ImportReference(typeof(ThreadStaticAttribute).GetConstructor(new Type[] { })))); + + observerType.Fields.Add(observerField); + + observerType.Methods.Add(ConstructProxySetObserverMethod(module, observerField)); + observerType.Methods.Add(ConstructProxyBranchCountMethod(module, observerField)); + observerType.Methods.Add(ConstructProxyCallCountMethod(module, observerField)); + + return observerType; + } + + private static MethodDefinition ConstructProxyBranchCountMethod(ModuleDefinition module, + FieldReference observerField) + { + var countMethod = new MethodDefinition( + nameof(ExecutionObserverProxy.BranchCount), + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, + module.ImportReference(typeof(void)) + ); + + countMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); + var il = countMethod.Body.GetILProcessor(); + + var ret = il.Create(OpCodes.Ret); + + il.Emit(OpCodes.Ldsfld, observerField); + il.Emit(OpCodes.Brfalse_S, ret); // Do not call if not initialized + il.Emit(OpCodes.Ldsfld, observerField); + il.Emit(OpCodes.Callvirt, module.ImportReference( + typeof(IExecutionObserver).GetMethod(nameof(IExecutionObserver.BranchCount)))); + il.Append(ret); + + return countMethod; + } + + private static MethodDefinition ConstructProxyCallCountMethod(ModuleDefinition module, FieldReference observerField) + { + var countMethod = new MethodDefinition( + nameof(ExecutionObserverProxy.CallCount), + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, + module.ImportReference(typeof(void)) + ); + + countMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); + var il = countMethod.Body.GetILProcessor(); + + var ret = il.Create(OpCodes.Ret); + + il.Emit(OpCodes.Ldsfld, observerField); + il.Emit(OpCodes.Brfalse_S, ret); // Do not call if not initialized + il.Emit(OpCodes.Ldsfld, observerField); + il.Emit(OpCodes.Callvirt, module.ImportReference( + typeof(IExecutionObserver).GetMethod(nameof(IExecutionObserver.CallCount)))); + il.Append(ret); + + return countMethod; + } + + private static MethodDefinition ConstructProxySetObserverMethod(ModuleDefinition module, + FieldReference observerField) + { + var setObserverMethod = new MethodDefinition( + nameof(ExecutionObserverProxy.SetObserver), + MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, + module.ImportReference(typeof(void)) + ); + + setObserverMethod.Parameters.Add(new ParameterDefinition("observer", + ParameterAttributes.In, module.ImportReference(typeof(IExecutionObserver)))); + + var il = setObserverMethod.Body.GetILProcessor(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Stsfld, observerField); + il.Emit(OpCodes.Ret); - private void PatchMethodsWithCounter(MethodDefinition method, MethodReference branchCountRef, MethodReference callCountRef) + return setObserverMethod; + } + + private void PatchType(TypeDefinition typ, MethodReference branchCountRef, MethodReference callCountRef) + { + // Patch the methods in the type + foreach (var method in typ.Methods) PatchMethodsWithCounter(method, branchCountRef, callCountRef); + + // Patch if there is any nested type within the type + foreach (var nestedType in typ.NestedTypes) PatchType(nestedType, branchCountRef, callCountRef); + } + + private void PatchMethodsWithCounter(MethodDefinition method, MethodReference branchCountRef, + MethodReference callCountRef) + { + if (!method.HasBody) + return; + + var il = method.Body.GetILProcessor(); + + // Insert before every branching instruction + var branchingInstructions = method.Body.Instructions.Where(i => + Constants.JumpingOpCodes.Contains(i.OpCode)).ToList(); + + il.Body.SimplifyMacros(); + il.InsertBefore(method.Body.Instructions.First(), il.Create(OpCodes.Call, callCountRef)); + foreach (var instruction in branchingInstructions) { - if (!method.HasBody) - return; - - var il = method.Body.GetILProcessor(); - - // Insert before every branching instruction - var branchingInstructions = method.Body.Instructions.Where(i => - Constants.JumpingOpCodes.Contains(i.OpCode)).ToList(); - - il.Body.SimplifyMacros(); - il.InsertBefore(method.Body.Instructions.First(), il.Create(OpCodes.Call, callCountRef)); - foreach (var instruction in branchingInstructions) - { - var targetInstruction = (Instruction) instruction.Operand; - if (targetInstruction.Offset >= instruction.Offset) - continue; - - il.InsertAfter(targetInstruction, il.Create(OpCodes.Call, branchCountRef)); - } - - il.Body.OptimizeMacros(); + var targetInstruction = (Instruction)instruction.Operand; + if (targetInstruction.Offset >= instruction.Offset) + continue; + + il.InsertAfter(targetInstruction, il.Create(OpCodes.Call, branchCountRef)); } + + il.Body.OptimizeMacros(); } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Patchers/Module/MethodCallReplacer.cs b/src/AElf.CSharp.CodeOps/Patchers/Module/MethodCallReplacer.cs index 4ed491b7b5..b691760d44 100644 --- a/src/AElf.CSharp.CodeOps/Patchers/Module/MethodCallReplacer.cs +++ b/src/AElf.CSharp.CodeOps/Patchers/Module/MethodCallReplacer.cs @@ -6,101 +6,91 @@ using Mono.Cecil; using Mono.Cecil.Cil; -namespace AElf.CSharp.CodeOps.Patchers.Module +namespace AElf.CSharp.CodeOps.Patchers.Module; + +public class MethodCallReplacer : IPatcher { - public class MethodCallReplacer : IPatcher + private static readonly string Sdk = "AElf.Sdk.CSharp"; + + private static readonly Dictionary MethodCallsToReplace = new() { - private static readonly string Sdk = "AElf.Sdk.CSharp"; - - private static readonly Dictionary MethodCallsToReplace = new Dictionary - { - {"System.String::Concat", $"{Sdk}.{nameof(AElfString)}"}, - // May add System.String::Format later - }; - - // Replace unchecked math OpCodes with checked OpCodes (overflow throws exception) - private static readonly Dictionary OpCodesToReplace = new Dictionary() - { - {OpCodes.Add, OpCodes.Add_Ovf}, - {OpCodes.Sub, OpCodes.Sub_Ovf}, - {OpCodes.Mul, OpCodes.Mul_Ovf} - }; - - public bool SystemContactIgnored => false; - - public void Patch(ModuleDefinition module) - { - // Get the specific version of the SDK referenced by the contract - var nameRefSdk = module.AssemblyReferences.Single(r => r.Name == Sdk); - - // May cache all versions not to keep reloading for every contract deployment - var refSdk = AssemblyDefinition.ReadAssembly(Assembly.Load(nameRefSdk.FullName).Location); - - // Get the type definitions mapped for target methods from SDK - var sdkTypes = MethodCallsToReplace.Select(kv => kv.Value).Distinct(); - var sdkTypeDefs = sdkTypes - .Select(t => module.ImportReference(refSdk.MainModule.GetType(t)).Resolve()) - .ToDictionary(def => def.FullName); - - // Patch the types - foreach (var typ in module.Types) - { - PatchType(typ, sdkTypeDefs); - } - } + { "System.String::Concat", $"{Sdk}.{nameof(AElfString)}" } + // May add System.String::Format later + }; - private void PatchType(TypeDefinition typ, Dictionary sdkTypeDefs) - { - // Patch the methods in the type - foreach (var method in typ.Methods) - { - PatchMethod(method, sdkTypeDefs); - } - - // Patch if there is any nested type within the type - foreach (var nestedType in typ.NestedTypes) - { - PatchType(nestedType, sdkTypeDefs); - } - } + // Replace unchecked math OpCodes with checked OpCodes (overflow throws exception) + private static readonly Dictionary OpCodesToReplace = new() + { + { OpCodes.Add, OpCodes.Add_Ovf }, + { OpCodes.Sub, OpCodes.Sub_Ovf }, + { OpCodes.Mul, OpCodes.Mul_Ovf } + }; - private void PatchMethod(MethodDefinition method, Dictionary sdkTypeDefs) - { - if (!method.HasBody) - return; - - var ilProcessor = method.Body.GetILProcessor(); - - var methodCallsToReplace = method.Body.Instructions.Where(i => - i.OpCode.Code == Code.Call && MethodCallsToReplace.Any(m => ((MethodReference) i.Operand).FullName.Contains(m.Key))) - .ToList(); - - foreach (var instruction in methodCallsToReplace) - { - var sysMethodRef = (MethodReference) instruction.Operand; - var newMethodRef = method.Module.ImportReference(GetSdkMethodReference(sdkTypeDefs, sysMethodRef)); - - ilProcessor.Replace(instruction, ilProcessor.Create(OpCodes.Call, newMethodRef)); - } - - var opCodesToReplace = method.Body.Instructions.Where(i => OpCodesToReplace.Keys.Contains(i.OpCode)).ToList(); - foreach (var instruction in opCodesToReplace) - { - ilProcessor.Replace(instruction, ilProcessor.Create(OpCodesToReplace[instruction.OpCode])); - } - } + public bool SystemContactIgnored => false; + + public void Patch(ModuleDefinition module) + { + // Get the specific version of the SDK referenced by the contract + var nameRefSdk = module.AssemblyReferences.Single(r => r.Name == Sdk); + + // May cache all versions not to keep reloading for every contract deployment + var refSdk = AssemblyDefinition.ReadAssembly(Assembly.Load(nameRefSdk.FullName).Location); - private MethodReference GetSdkMethodReference(Dictionary sdkTypeDefs, MethodReference methodRef) + // Get the type definitions mapped for target methods from SDK + var sdkTypes = MethodCallsToReplace.Select(kv => kv.Value).Distinct(); + var sdkTypeDefs = sdkTypes + .Select(t => module.ImportReference(refSdk.MainModule.GetType(t)).Resolve()) + .ToDictionary(def => def.FullName); + + // Patch the types + foreach (var typ in module.Types) PatchType(typ, sdkTypeDefs); + } + + private void PatchType(TypeDefinition typ, Dictionary sdkTypeDefs) + { + // Patch the methods in the type + foreach (var method in typ.Methods) PatchMethod(method, sdkTypeDefs); + + // Patch if there is any nested type within the type + foreach (var nestedType in typ.NestedTypes) PatchType(nestedType, sdkTypeDefs); + } + + private void PatchMethod(MethodDefinition method, Dictionary sdkTypeDefs) + { + if (!method.HasBody) + return; + + var ilProcessor = method.Body.GetILProcessor(); + + var methodCallsToReplace = method.Body.Instructions.Where(i => + i.OpCode.Code == Code.Call && + MethodCallsToReplace.Any(m => ((MethodReference)i.Operand).FullName.Contains(m.Key))) + .ToList(); + + foreach (var instruction in methodCallsToReplace) { - // Find the right method that has the same set of parameters and return type - var replaceFrom = MethodCallsToReplace[$"{methodRef.DeclaringType}::{methodRef.Name}"]; - var methodDefinition = sdkTypeDefs[replaceFrom].Methods.Single( - m => m.ReturnType.FullName == methodRef.ReturnType.FullName && // Return type - m.FullName.Split(new [] {"::"}, StringSplitOptions.None)[1] == - methodRef.FullName.Split(new [] {"::"}, StringSplitOptions.None)[1] // Method Name & Parameters - ); - - return methodDefinition; + var sysMethodRef = (MethodReference)instruction.Operand; + var newMethodRef = method.Module.ImportReference(GetSdkMethodReference(sdkTypeDefs, sysMethodRef)); + + ilProcessor.Replace(instruction, ilProcessor.Create(OpCodes.Call, newMethodRef)); } + + var opCodesToReplace = method.Body.Instructions.Where(i => OpCodesToReplace.Keys.Contains(i.OpCode)).ToList(); + foreach (var instruction in opCodesToReplace) + ilProcessor.Replace(instruction, ilProcessor.Create(OpCodesToReplace[instruction.OpCode])); + } + + private MethodReference GetSdkMethodReference(Dictionary sdkTypeDefs, + MethodReference methodRef) + { + // Find the right method that has the same set of parameters and return type + var replaceFrom = MethodCallsToReplace[$"{methodRef.DeclaringType}::{methodRef.Name}"]; + var methodDefinition = sdkTypeDefs[replaceFrom].Methods.Single( + m => m.ReturnType.FullName == methodRef.ReturnType.FullName && // Return type + m.FullName.Split(new[] { "::" }, StringSplitOptions.None)[1] == + methodRef.FullName.Split(new[] { "::" }, StringSplitOptions.None)[1] // Method Name & Parameters + ); + + return methodDefinition; } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Patchers/Module/ResetFieldsMethodInjector.cs b/src/AElf.CSharp.CodeOps/Patchers/Module/ResetFieldsMethodInjector.cs index 6683382957..8ec0e8f210 100644 --- a/src/AElf.CSharp.CodeOps/Patchers/Module/ResetFieldsMethodInjector.cs +++ b/src/AElf.CSharp.CodeOps/Patchers/Module/ResetFieldsMethodInjector.cs @@ -4,150 +4,139 @@ using Mono.Cecil; using Mono.Cecil.Cil; -namespace AElf.CSharp.CodeOps.Patchers.Module +namespace AElf.CSharp.CodeOps.Patchers.Module; + +public class ResetFieldsMethodInjector : IPatcher { - public class ResetFieldsMethodInjector : IPatcher + public bool SystemContactIgnored => false; + + public void Patch(ModuleDefinition module) { - public bool SystemContactIgnored => false; - - public void Patch(ModuleDefinition module) + foreach (var type in module.Types.Where(t => !t.IsContractImplementation())) { - foreach (var type in module.Types.Where(t => !t.IsContractImplementation())) - { - InjectTypeWithResetFields(module, type); - AddCallToNestedClassResetFields(type); - } - - InjectContractWithResetFields(module); + InjectTypeWithResetFields(module, type); + AddCallToNestedClassResetFields(type); } - private bool InjectTypeWithResetFields(ModuleDefinition module, TypeDefinition type) - { - var callToNestedResetNeeded = false; - - // Inject for nested types first - foreach (var nestedType in type.NestedTypes) - { - callToNestedResetNeeded |= InjectTypeWithResetFields(module, nestedType); - } - - // Get static non-initonly, non-constant fields - var fields = type.Fields.Where(f => - f.FieldType.FullName != typeof(FileDescriptor).FullName && - f.IsStatic && - !(f.IsInitOnly || f.HasConstant) - ).ToList(); - - callToNestedResetNeeded |= fields.Any(); - - if (callToNestedResetNeeded) - { - // Inject ResetFields method in type, so that nested calls can be added later - type.Methods.Add(ConstructResetFieldsMethod(module, fields, false)); - } - - return callToNestedResetNeeded; - } + InjectContractWithResetFields(module); + } - private void AddCallToNestedClassResetFields(TypeDefinition type) - { - var parentClassResetMethod = type.Methods.FirstOrDefault(m => m.Name == nameof(ResetFields)); - - if (parentClassResetMethod == null) - return; - - var il = parentClassResetMethod.Body.GetILProcessor(); - - var ret = il.Body.Instructions.Last(); - - // Get reference of the methods to nested types' reset fields methods - var toBeCalledFromParent = type.NestedTypes - .Where(t => t.Methods.Any(m => m.Name == nameof(ResetFields))) - .Select(t => t.Methods.Single(m => m.Name == nameof(ResetFields))); - - foreach (var nestedResetMethod in toBeCalledFromParent) - { - // Add a call to nested class' ResetFields method - il.InsertBefore(ret, il.Create(OpCodes.Call, nestedResetMethod)); - } - - // Do the same for nested types (add call to their nested types' ResetMethod) - foreach (var nestedType in type.NestedTypes) - { - AddCallToNestedClassResetFields(nestedType); - } - } + private bool InjectTypeWithResetFields(ModuleDefinition module, TypeDefinition type) + { + var callToNestedResetNeeded = false; - private void InjectContractWithResetFields(ModuleDefinition module) - { - var contractImplementation = module.Types.Single(t => t.IsContractImplementation()); - - foreach (var nestedType in contractImplementation.NestedTypes) - { - InjectTypeWithResetFields(module, nestedType); - AddCallToNestedClassResetFields(nestedType); - } - - var otherTypes = module.Types.Where(t => !t.IsContractImplementation()).ToList(); - - // Add contract's nested types as well - otherTypes.AddRange(contractImplementation.NestedTypes); - - // Get all fields, including instance fields from the base type of the inherited contract type - var resetFieldsMethod = ConstructResetFieldsMethod(module, - contractImplementation.GetAllFields(f=>!(f.IsInitOnly || f.HasConstant)), true); - - var il = resetFieldsMethod.Body.GetILProcessor(); - - var ret = il.Body.Instructions.Last(); - - // Call other types' reset fields method from contract implementation reset method - foreach (var resetMethodRef in otherTypes.Select(type => - type.Methods.FirstOrDefault(m => - m.Name == nameof(ResetFields))).Where(resetMethodRef => resetMethodRef != null)) - { - il.InsertBefore(ret, il.Create(OpCodes.Call, resetMethodRef)); - } - - contractImplementation.Methods.Add(resetFieldsMethod); - } + // Inject for nested types first + foreach (var nestedType in type.NestedTypes) + callToNestedResetNeeded |= InjectTypeWithResetFields(module, nestedType); - private MethodDefinition ConstructResetFieldsMethod(ModuleDefinition module, IEnumerable fields, bool instanceMethod) - { - var attributes = instanceMethod - ? MethodAttributes.Public | MethodAttributes.HideBySig - : MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static; - - var resetFieldsMethod = new MethodDefinition( - nameof(ResetFields), - attributes, - module.ImportReference(typeof(void)) - ); - - resetFieldsMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); - var il = resetFieldsMethod.Body.GetILProcessor(); - - foreach (var field in fields) - { - if (instanceMethod && !field.IsStatic) - il.Emit(OpCodes.Ldarg_0); // this - LoadDefaultValue(il, field); - il.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field); - } - - il.Emit(OpCodes.Ret); - - return resetFieldsMethod; - } + // Get static non-initonly, non-constant fields + var fields = type.Fields.Where(f => + f.FieldType.FullName != typeof(FileDescriptor).FullName && + f.IsStatic && + !(f.IsInitOnly || f.HasConstant) + ).ToList(); + + callToNestedResetNeeded |= fields.Any(); + + if (callToNestedResetNeeded) + // Inject ResetFields method in type, so that nested calls can be added later + type.Methods.Add(ConstructResetFieldsMethod(module, fields, false)); + + return callToNestedResetNeeded; + } + + private void AddCallToNestedClassResetFields(TypeDefinition type) + { + var parentClassResetMethod = type.Methods.FirstOrDefault(m => m.Name == nameof(ResetFields)); + + if (parentClassResetMethod == null) + return; + + var il = parentClassResetMethod.Body.GetILProcessor(); + + var ret = il.Body.Instructions.Last(); + + // Get reference of the methods to nested types' reset fields methods + var toBeCalledFromParent = type.NestedTypes + .Where(t => t.Methods.Any(m => m.Name == nameof(ResetFields))) + .Select(t => t.Methods.Single(m => m.Name == nameof(ResetFields))); + + foreach (var nestedResetMethod in toBeCalledFromParent) + // Add a call to nested class' ResetFields method + il.InsertBefore(ret, il.Create(OpCodes.Call, nestedResetMethod)); - private static void LoadDefaultValue(ILProcessor il, FieldReference field) + // Do the same for nested types (add call to their nested types' ResetMethod) + foreach (var nestedType in type.NestedTypes) AddCallToNestedClassResetFields(nestedType); + } + + private void InjectContractWithResetFields(ModuleDefinition module) + { + var contractImplementation = module.Types.Single(t => t.IsContractImplementation()); + + foreach (var nestedType in contractImplementation.NestedTypes) { - il.Emit(field.FieldType.IsValueType ? OpCodes.Ldc_I4_0 : OpCodes.Ldnull); + InjectTypeWithResetFields(module, nestedType); + AddCallToNestedClassResetFields(nestedType); } - public static void ResetFields() + var otherTypes = module.Types.Where(t => !t.IsContractImplementation()).ToList(); + + // Add contract's nested types as well + otherTypes.AddRange(contractImplementation.NestedTypes); + + // Get all fields, including instance fields from the base type of the inherited contract type + var resetFieldsMethod = ConstructResetFieldsMethod(module, + contractImplementation.GetAllFields(f => !(f.IsInitOnly || f.HasConstant)), true); + + var il = resetFieldsMethod.Body.GetILProcessor(); + + var ret = il.Body.Instructions.Last(); + + // Call other types' reset fields method from contract implementation reset method + foreach (var resetMethodRef in otherTypes.Select(type => + type.Methods.FirstOrDefault(m => + m.Name == nameof(ResetFields))).Where(resetMethodRef => resetMethodRef != null)) + il.InsertBefore(ret, il.Create(OpCodes.Call, resetMethodRef)); + + contractImplementation.Methods.Add(resetFieldsMethod); + } + + private MethodDefinition ConstructResetFieldsMethod(ModuleDefinition module, IEnumerable fields, + bool instanceMethod) + { + var attributes = instanceMethod + ? MethodAttributes.Public | MethodAttributes.HideBySig + : MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static; + + var resetFieldsMethod = new MethodDefinition( + nameof(ResetFields), + attributes, + module.ImportReference(typeof(void)) + ); + + resetFieldsMethod.Body.Variables.Add(new VariableDefinition(module.ImportReference(typeof(bool)))); + var il = resetFieldsMethod.Body.GetILProcessor(); + + foreach (var field in fields) { - // This method is to use its name only + if (instanceMethod && !field.IsStatic) + il.Emit(OpCodes.Ldarg_0); // this + LoadDefaultValue(il, field); + il.Emit(field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, field); } + + il.Emit(OpCodes.Ret); + + return resetFieldsMethod; + } + + private static void LoadDefaultValue(ILProcessor il, FieldReference field) + { + il.Emit(field.FieldType.IsValueType ? OpCodes.Ldc_I4_0 : OpCodes.Ldnull); + } + + public static void ResetFields() + { + // This method is to use its name only } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Patchers/Module/StateWrittenSizeLimitMethodInjector.cs b/src/AElf.CSharp.CodeOps/Patchers/Module/StateWrittenSizeLimitMethodInjector.cs index 85afece8a7..ee893ac748 100644 --- a/src/AElf.CSharp.CodeOps/Patchers/Module/StateWrittenSizeLimitMethodInjector.cs +++ b/src/AElf.CSharp.CodeOps/Patchers/Module/StateWrittenSizeLimitMethodInjector.cs @@ -2,55 +2,43 @@ using AElf.CSharp.CodeOps.Instructions; using Mono.Cecil; -namespace AElf.CSharp.CodeOps.Patchers.Module +namespace AElf.CSharp.CodeOps.Patchers.Module; + +public class StateWrittenSizeLimitMethodInjector : IPatcher { - public class StateWrittenSizeLimitMethodInjector : IPatcher + private readonly IStateWrittenInstructionInjector _instructionInjector; + + public StateWrittenSizeLimitMethodInjector(IStateWrittenInstructionInjector instructionInjector) + { + _instructionInjector = instructionInjector; + } + + public bool SystemContactIgnored => true; + + public void Patch(ModuleDefinition module) { - private readonly IStateWrittenInstructionInjector _instructionInjector; - - public StateWrittenSizeLimitMethodInjector(IStateWrittenInstructionInjector instructionInjector) - { - _instructionInjector = instructionInjector; - } - - public bool SystemContactIgnored => true; - - public void Patch(ModuleDefinition module) - { - // Patch the types - foreach (var typ in module.Types) - { - PatchType(typ, module); - } - } - - private void PatchType(TypeDefinition typ, ModuleDefinition moduleDefinition) - { - // Patch the methods in the type - foreach (var method in typ.Methods) - { - PatchMethod(moduleDefinition, method); - } - - // Patch if there is any nested type within the type - foreach (var nestedType in typ.NestedTypes) - { - PatchType(nestedType, moduleDefinition); - } - } - - private void PatchMethod(ModuleDefinition moduleDefinition, MethodDefinition methodDefinition) - { - if (!methodDefinition.HasBody) - return; - - var ilProcessor = methodDefinition.Body.GetILProcessor(); - - foreach (var instruction in methodDefinition.Body.Instructions.Where(instruction => - _instructionInjector.IdentifyInstruction(instruction)).ToList()) - { - _instructionInjector.InjectInstruction(ilProcessor, instruction, moduleDefinition); - } - } + // Patch the types + foreach (var typ in module.Types) PatchType(typ, module); + } + + private void PatchType(TypeDefinition typ, ModuleDefinition moduleDefinition) + { + // Patch the methods in the type + foreach (var method in typ.Methods) PatchMethod(moduleDefinition, method); + + // Patch if there is any nested type within the type + foreach (var nestedType in typ.NestedTypes) PatchType(nestedType, moduleDefinition); + } + + private void PatchMethod(ModuleDefinition moduleDefinition, MethodDefinition methodDefinition) + { + if (!methodDefinition.HasBody) + return; + + var ilProcessor = methodDefinition.Body.GetILProcessor(); + + foreach (var instruction in methodDefinition.Body.Instructions.Where(instruction => + _instructionInjector.IdentifyInstruction(instruction)).ToList()) + _instructionInjector.InjectInstruction(ilProcessor, instruction, moduleDefinition); } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Policies/DefaultPolicy.cs b/src/AElf.CSharp.CodeOps/Policies/DefaultPolicy.cs index 14f57bbee0..0a5223285f 100644 --- a/src/AElf.CSharp.CodeOps/Policies/DefaultPolicy.cs +++ b/src/AElf.CSharp.CodeOps/Policies/DefaultPolicy.cs @@ -3,34 +3,33 @@ using AElf.CSharp.CodeOps.Patchers; using AElf.CSharp.CodeOps.Validators; +namespace AElf.CSharp.CodeOps.Policies; -namespace AElf.CSharp.CodeOps.Policies +public interface IPolicy { - public interface IPolicy + List> GetValidators(); + List> GetPatchers(); +} + +public class DefaultPolicy : IPolicy +{ + private readonly List _patchers; + + private readonly List _validators; + + public DefaultPolicy(IEnumerable validators, IEnumerable patchers) { - List> GetValidators(); - List> GetPatchers(); + _validators = validators.ToList(); + _patchers = patchers.ToList(); } - - public class DefaultPolicy : IPolicy - { - public DefaultPolicy(IEnumerable validators, IEnumerable patchers) - { - _validators = validators.ToList(); - _patchers = patchers.ToList(); - } - private readonly List _validators; - private readonly List _patchers; - - public List> GetValidators() - { - return _validators.OfType>().ToList(); - } + public List> GetValidators() + { + return _validators.OfType>().ToList(); + } - public List> GetPatchers() - { - return _patchers.OfType>().ToList(); - } + public List> GetPatchers() + { + return _patchers.OfType>().ToList(); } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Assembly/AcsValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Assembly/AcsValidator.cs index 18b2731365..c319787461 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Assembly/AcsValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Assembly/AcsValidator.cs @@ -4,72 +4,71 @@ using AElf.CSharp.Core; using AElf.Kernel.SmartContract; -namespace AElf.CSharp.CodeOps.Validators.Assembly +namespace AElf.CSharp.CodeOps.Validators.Assembly; + +public interface IAcsValidator { - public interface IAcsValidator - { - IEnumerable Validate(System.Reflection.Assembly assembly, RequiredAcs requiredAcs); - } - - public class AcsValidator : IAcsValidator - { - public IEnumerable Validate(System.Reflection.Assembly assembly, RequiredAcs requiredAcs) - { - if (requiredAcs.AcsList.Count == 0) - return Enumerable.Empty(); // No ACS required + IEnumerable Validate(System.Reflection.Assembly assembly, RequiredAcs requiredAcs); +} - var acsBaseList = GetServiceDescriptorIdentities(GetServerServiceDefinition(assembly)); +public class AcsValidator : IAcsValidator +{ + public IEnumerable Validate(System.Reflection.Assembly assembly, RequiredAcs requiredAcs) + { + if (requiredAcs.AcsList.Count == 0) + return Enumerable.Empty(); // No ACS required - if (requiredAcs.RequireAll) - { - // Contract should have all listed ACS as a base - if (requiredAcs.AcsList.Any(acs => !acsBaseList.Contains(acs))) - return new List - { - new AcsValidationResult( - $"Contract should have all {string.Join(", ", requiredAcs.AcsList)} as base.") - }; - } - else - { - // Contract should have at least one of the listed ACS in the list as a base - if (requiredAcs.AcsList.All(acs => !acsBaseList.Contains(acs))) - return new List - { - new AcsValidationResult( - $"Contract should have at least {string.Join(" or ", requiredAcs.AcsList)} as base.") - }; - } + var acsBaseList = GetServiceDescriptorIdentities(GetServerServiceDefinition(assembly)); - return Enumerable.Empty(); + if (requiredAcs.RequireAll) + { + // Contract should have all listed ACS as a base + if (requiredAcs.AcsList.Any(acs => !acsBaseList.Contains(acs))) + return new List + { + new AcsValidationResult( + $"Contract should have all {string.Join(", ", requiredAcs.AcsList)} as base.") + }; } - - private static ServerServiceDefinition GetServerServiceDefinition(System.Reflection.Assembly assembly) + else { - var methodInfo = assembly.FindContractContainer() - .GetMethod("BindService", new[] {assembly.FindContractBaseType()}); + // Contract should have at least one of the listed ACS in the list as a base + if (requiredAcs.AcsList.All(acs => !acsBaseList.Contains(acs))) + return new List + { + new AcsValidationResult( + $"Contract should have at least {string.Join(" or ", requiredAcs.AcsList)} as base.") + }; + } - var serviceDefinition = methodInfo.Invoke(null, new[] - { - Activator.CreateInstance(assembly.FindContractType()) - }) as ServerServiceDefinition; + return Enumerable.Empty(); + } - return serviceDefinition; - } + private static ServerServiceDefinition GetServerServiceDefinition(System.Reflection.Assembly assembly) + { + var methodInfo = assembly.FindContractContainer() + .GetMethod("BindService", new[] { assembly.FindContractBaseType() }); - private static IEnumerable GetServiceDescriptorIdentities(ServerServiceDefinition serviceDefinition) + var serviceDefinition = methodInfo.Invoke(null, new[] { - var binder = new DescriptorOnlyServiceBinder(); - serviceDefinition.BindService(binder); - return binder.GetDescriptors() - .Select(service => service.File.GetIdentity()); - } + Activator.CreateInstance(assembly.FindContractType()) + }) as ServerServiceDefinition; + + return serviceDefinition; } - public class AcsValidationResult : ValidationResult + private static IEnumerable GetServiceDescriptorIdentities(ServerServiceDefinition serviceDefinition) + { + var binder = new DescriptorOnlyServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetDescriptors() + .Select(service => service.File.GetIdentity()); + } +} + +public class AcsValidationResult : ValidationResult +{ + public AcsValidationResult(string message) : base(message) { - public AcsValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/IValidator.cs b/src/AElf.CSharp.CodeOps/Validators/IValidator.cs index 9a1a9102ce..e5755ee1c9 100644 --- a/src/AElf.CSharp.CodeOps/Validators/IValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/IValidator.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; using System.Threading; -namespace AElf.CSharp.CodeOps.Validators +namespace AElf.CSharp.CodeOps.Validators; + +public interface IValidator { - public interface IValidator - { - bool SystemContactIgnored { get; } - } + bool SystemContactIgnored { get; } +} - public interface IValidator : IValidator - { - IEnumerable Validate(T item, CancellationToken ct); - } +public interface IValidator : IValidator +{ + IEnumerable Validate(T item, CancellationToken ct); } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs index 1bd6d0296e..d879851e21 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs @@ -7,229 +7,227 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class ArrayValidator : IValidator, ITransientDependency { - public class ArrayValidator : IValidator, ITransientDependency + private const long AllowedTotalSize = 40 * 1024; // Byte per array when limiting by total array size + + private static readonly ArrayLimitLookup AllowedTypes = new ArrayLimitLookup() + .LimitByTotalSize(typeof(byte), sizeof(byte)) + .LimitByTotalSize(typeof(short), sizeof(short)) + .LimitByTotalSize(typeof(int), sizeof(int)) + .LimitByTotalSize(typeof(long), sizeof(long)) + .LimitByTotalSize(typeof(ushort), sizeof(ushort)) + .LimitByTotalSize(typeof(uint), sizeof(uint)) + .LimitByTotalSize(typeof(ulong), sizeof(ulong)) + .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 + + // 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 + .LimitByCount("Google.Protobuf.Reflection.FileDescriptor", 10) + .LimitByCount("Google.Protobuf.Reflection.GeneratedClrTypeInfo", 100); + + // When array dimension is 8 or lower, below OpCodes are used, get size from lookup + private static readonly Dictionary PushIntLookup = new() { - private const long AllowedTotalSize = 40 * 1024; // Byte per array when limiting by total array size - - private static readonly ArrayLimitLookup AllowedTypes = new ArrayLimitLookup() - .LimitByTotalSize(typeof(Byte), sizeof(Byte)) - .LimitByTotalSize(typeof(Int16), sizeof(Int16)) - .LimitByTotalSize(typeof(Int32), sizeof(Int32)) - .LimitByTotalSize(typeof(Int64), sizeof(Int64)) - .LimitByTotalSize(typeof(UInt16), sizeof(UInt16)) - .LimitByTotalSize(typeof(UInt32), sizeof(UInt32)) - .LimitByTotalSize(typeof(UInt64), sizeof(UInt64)) - .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 - - // 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 - .LimitByCount("Google.Protobuf.Reflection.FileDescriptor", 10) - .LimitByCount("Google.Protobuf.Reflection.GeneratedClrTypeInfo", 100); - - // When array dimension is 8 or lower, below OpCodes are used, get size from lookup - private static readonly Dictionary PushIntLookup = new Dictionary() - { - {OpCodes.Ldc_I4_0, 0}, - {OpCodes.Ldc_I4_1, 1}, - {OpCodes.Ldc_I4_2, 2}, - {OpCodes.Ldc_I4_3, 3}, - {OpCodes.Ldc_I4_4, 4}, - {OpCodes.Ldc_I4_5, 5}, - {OpCodes.Ldc_I4_6, 6}, - {OpCodes.Ldc_I4_7, 7}, - {OpCodes.Ldc_I4_8, 8}, - }; - - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + { OpCodes.Ldc_I4_0, 0 }, + { OpCodes.Ldc_I4_1, 1 }, + { OpCodes.Ldc_I4_2, 2 }, + { OpCodes.Ldc_I4_3, 3 }, + { OpCodes.Ldc_I4_4, 4 }, + { OpCodes.Ldc_I4_5, 5 }, + { OpCodes.Ldc_I4_6, 6 }, + { OpCodes.Ldc_I4_7, 7 }, + { OpCodes.Ldc_I4_8, 8 } + }; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return Enumerable.Empty(); + + var errors = new List(); + + foreach (var instruction in method.Body.Instructions) { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - - var errors = new List(); - - foreach (var instruction in method.Body.Instructions) - { - if (instruction.OpCode != OpCodes.Newarr) - continue; + if (instruction.OpCode != OpCodes.Newarr) + continue; - var typ = ((TypeReference) instruction.Operand).FullName; + var typ = ((TypeReference)instruction.Operand).FullName; - ArrayValidationResult error = null; - if (AllowedTypes.TryGetLimit(typ, out var limit)) + ArrayValidationResult error = null; + if (AllowedTypes.TryGetLimit(typ, out var limit)) + { + if (TryGetArraySize(instruction, out var arrayDimension)) { - if (TryGetArraySize(instruction, out var arrayDimension)) + if (limit.By == LimitBy.Count) { - if (limit.By == LimitBy.Count) + if (arrayDimension > limit.Count) + error = new ArrayValidationResult( + $"Array size can not be larger than {limit.Count} elements. ({arrayDimension} x {typ})"); + } + else + { + try { - if (arrayDimension > limit.Count) - error = new ArrayValidationResult($"Array size can not be larger than {limit.Count} elements. ({arrayDimension} x {typ})"); + var totalSize = arrayDimension.Mul(limit.ElementSize); + + if (totalSize > AllowedTotalSize) + error = new ArrayValidationResult( + $"Array size can not be larger than {AllowedTotalSize} bytes. ({arrayDimension} x {typ})"); } - else + catch (OverflowException) { - try - { - var totalSize = arrayDimension.Mul(limit.ElementSize); - - if (totalSize > AllowedTotalSize) - error = new ArrayValidationResult($"Array size can not be larger than {AllowedTotalSize} bytes. ({arrayDimension} x {typ})"); - } - catch (OverflowException) - { - error = new ArrayValidationResult($"Array size is too large that causes overflow when estimating memory usage."); - } + error = new ArrayValidationResult( + "Array size is too large that causes overflow when estimating memory usage."); } } - else - { - error = new ArrayValidationResult($"Array size could not be identified for {typ}." + GetIlCodesPartial(instruction)); - } } else { - error = new ArrayValidationResult($"Array of {typ} type is not allowed."); + error = new ArrayValidationResult($"Array size could not be identified for {typ}." + + GetIlCodesPartial(instruction)); } - - if (error != null) - errors.Add(error.WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); + } + else + { + error = new ArrayValidationResult($"Array of {typ} type is not allowed."); } - return errors; + if (error != null) + errors.Add(error.WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, + null)); } - private bool TryGetArraySize(Instruction instruction, out int size) - { - // Look for size declaration before newarr OpCode - var previous = instruction.Previous; - - // Array size should be hardcoded, not from another method or variable - if (previous.OpCode == OpCodes.Ldc_I4 || previous.OpCode == OpCodes.Ldc_I4_S) - { - size = Convert.ToInt32(previous.Operand); - return true; - } + return errors; + } - // If array size is set like ldc.i4.1 etc, get the size from look up - if (PushIntLookup.TryGetValue(previous.OpCode, out size)) - { - return true; - } + public bool SystemContactIgnored => false; - #if DEBUG - // Creating array from an already existing array, only allowed in Debug mode - if (previous.OpCode == OpCodes.Conv_I4 && previous.Previous.OpCode == OpCodes.Ldlen) - { - size = 0; - return true; - } - #endif + private bool TryGetArraySize(Instruction instruction, out int size) + { + // Look for size declaration before newarr OpCode + var previous = instruction.Previous; - size = -1; - return false; + // Array size should be hardcoded, not from another method or variable + if (previous.OpCode == OpCodes.Ldc_I4 || previous.OpCode == OpCodes.Ldc_I4_S) + { + size = Convert.ToInt32(previous.Operand); + return true; } - private string GetIlCodesNext(Instruction instruction, int depth) - { - var code = ""; - var next = instruction.Next; - while (depth-- > 0 && next != null) - { - code += next + "\n"; - next = next.Next; - } + // If array size is set like ldc.i4.1 etc, get the size from look up + if (PushIntLookup.TryGetValue(previous.OpCode, out size)) return true; - return code; +#if DEBUG + // Creating array from an already existing array, only allowed in Debug mode + if (previous.OpCode == OpCodes.Conv_I4 && previous.Previous.OpCode == OpCodes.Ldlen) + { + size = 0; + return true; } +#endif - private string GetIlCodesPrevious(Instruction instruction, int depth) + size = -1; + return false; + } + + private string GetIlCodesNext(Instruction instruction, int depth) + { + var code = ""; + var next = instruction.Next; + while (depth-- > 0 && next != null) { - var code = ""; - var previous = instruction.Previous; - while (depth-- > 0) - { - code += "\n" + previous + code; - previous = previous.Previous; - } - return code; + code += next + "\n"; + next = next.Next; } - private string GetIlCodesPartial(Instruction instruction, int depth = 5) + return code; + } + + private string GetIlCodesPrevious(Instruction instruction, int depth) + { + var code = ""; + var previous = instruction.Previous; + while (depth-- > 0) { - return GetIlCodesPrevious(instruction, depth) + "\n" + - instruction + "\n" + - GetIlCodesNext(instruction, depth); + code += "\n" + previous + code; + previous = previous.Previous; } - private class ArrayLimitLookup - { - private Dictionary _lookup = new Dictionary(); + return code; + } - public ArrayLimitLookup LimitByCount(string type, int count) - { - _lookup.Add(type, new ArrayLimit(LimitBy.Count, count)); - return this; - } - - public ArrayLimitLookup LimitByCount(Type type, int count) - { - return LimitByCount(type.FullName, count); - } + private string GetIlCodesPartial(Instruction instruction, int depth = 5) + { + return GetIlCodesPrevious(instruction, depth) + "\n" + + instruction + "\n" + + GetIlCodesNext(instruction, depth); + } - public ArrayLimitLookup LimitByTotalSize(Type type, int size) - { - _lookup.Add(type.FullName, new ArrayLimit(LimitBy.Size, size)); - return this; - } + private class ArrayLimitLookup + { + private readonly Dictionary _lookup = new(); - public bool TryGetLimit(string type, out ArrayLimit limit) - { - return _lookup.TryGetValue(type, out limit); - } + public ArrayLimitLookup LimitByCount(string type, int count) + { + _lookup.Add(type, new ArrayLimit(LimitBy.Count, count)); + return this; } - private class ArrayLimit + public ArrayLimitLookup LimitByCount(Type type, int count) { - public LimitBy By { get; } - - public int ElementSize { get; } - - public int Count { get; } - - public ArrayLimit(LimitBy by, int num) - { - By = by; - - if (by == LimitBy.Count) - { - Count = num; - } - else - { - ElementSize = num; - } - } + return LimitByCount(type.FullName, count); } - - private enum LimitBy + + public ArrayLimitLookup LimitByTotalSize(Type type, int size) { - Count, - Size + _lookup.Add(type.FullName, new ArrayLimit(LimitBy.Size, size)); + return this; } - public bool SystemContactIgnored => false; + public bool TryGetLimit(string type, out ArrayLimit limit) + { + return _lookup.TryGetValue(type, out limit); + } } - public class ArrayValidationResult : ValidationResult + private class ArrayLimit { - public ArrayValidationResult(string message) : base(message) + public ArrayLimit(LimitBy by, int num) { + By = by; + + if (by == LimitBy.Count) + Count = num; + else + ElementSize = num; } + + public LimitBy By { get; } + + public int ElementSize { get; } + + public int Count { get; } + } + + private enum LimitBy + { + Count, + Size + } +} + +public class ArrayValidationResult : ValidationResult +{ + public ArrayValidationResult(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/DescriptorAccessValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/DescriptorAccessValidator.cs index 196b4df17e..7b5f32daf0 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/DescriptorAccessValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/DescriptorAccessValidator.cs @@ -6,45 +6,42 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class DescriptorAccessValidator : IValidator, ITransientDependency { - public class DescriptorAccessValidator : IValidator, ITransientDependency + public bool SystemContactIgnored => false; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) { - public bool SystemContactIgnored => false; - - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - - // If there is any non-constructor method accessing a FileDescriptor type field to set, - // then this is a problem. FileDescriptor field should only be set in constructor. - // If there is any access to set a FileDescriptor type field from a constructor outside of its declaring class, - // then it is a problem too - var instructions = method.Body.Instructions - .Where(i => i.OpCode == OpCodes.Stsfld && - i.Operand is FieldDefinition field && - field.FieldType.FullName == typeof(FileDescriptor).FullName && - (!method.IsConstructor || field.DeclaringType != method.DeclaringType)).ToArray(); - - if (instructions.Any()) - { - return instructions.Select(i => new DescriptorAccessValidationResult( - "It is not allowed to set FileDescriptor type static field outside of its declaring type's constructor.") - .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); - } + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + if (!method.HasBody) return Enumerable.Empty(); - } + + // If there is any non-constructor method accessing a FileDescriptor type field to set, + // then this is a problem. FileDescriptor field should only be set in constructor. + // If there is any access to set a FileDescriptor type field from a constructor outside of its declaring class, + // then it is a problem too + var instructions = method.Body.Instructions + .Where(i => i.OpCode == OpCodes.Stsfld && + i.Operand is FieldDefinition field && + field.FieldType.FullName == typeof(FileDescriptor).FullName && + (!method.IsConstructor || field.DeclaringType != method.DeclaringType)).ToArray(); + + if (instructions.Any()) + return instructions.Select(i => new DescriptorAccessValidationResult( + "It is not allowed to set FileDescriptor type static field outside of its declaring type's constructor.") + .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); + + return Enumerable.Empty(); } - - public class DescriptorAccessValidationResult : ValidationResult +} + +public class DescriptorAccessValidationResult : ValidationResult +{ + public DescriptorAccessValidationResult(string message) : base(message) { - public DescriptorAccessValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/FloatOpsValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/FloatOpsValidator.cs index 0f24454790..d5ea07cdab 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/FloatOpsValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/FloatOpsValidator.cs @@ -5,56 +5,51 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class FloatOpsValidator : IValidator, ITransientDependency { - public class FloatOpsValidator : IValidator, ITransientDependency + private static readonly HashSet FloatOpCodes = new() { - private static readonly HashSet FloatOpCodes = new HashSet - { - OpCodes.Ldc_R4, - OpCodes.Ldc_R8, - OpCodes.Ldelem_R4, - OpCodes.Ldelem_R8, - OpCodes.Conv_R_Un, - OpCodes.Conv_R4, - OpCodes.Conv_R8, - OpCodes.Ldind_R4, - OpCodes.Ldind_R8, - OpCodes.Stelem_R4, - OpCodes.Stelem_R8, - OpCodes.Stind_R4, - OpCodes.Stind_R8 - }; - - public bool SystemContactIgnored => false; - - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - var errors = new List(); - - foreach (var instruction in method.Body.Instructions) - { - if (FloatOpCodes.Contains(instruction.OpCode)) - { - errors.Add( - new FloatOpsValidationResult($"Method {method.Name} contains {instruction.OpCode} float OpCode.") - .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); - } - } - - return errors; - } + OpCodes.Ldc_R4, + OpCodes.Ldc_R8, + OpCodes.Ldelem_R4, + OpCodes.Ldelem_R8, + OpCodes.Conv_R_Un, + OpCodes.Conv_R4, + OpCodes.Conv_R8, + OpCodes.Ldind_R4, + OpCodes.Ldind_R8, + OpCodes.Stelem_R4, + OpCodes.Stelem_R8, + OpCodes.Stind_R4, + OpCodes.Stind_R8 + }; + + public bool SystemContactIgnored => false; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return Enumerable.Empty(); + var errors = new List(); + + foreach (var instruction in method.Body.Instructions) + if (FloatOpCodes.Contains(instruction.OpCode)) + errors.Add( + new FloatOpsValidationResult($"Method {method.Name} contains {instruction.OpCode} float OpCode.") + .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); + + return errors; } - - public class FloatOpsValidationResult : ValidationResult +} + +public class FloatOpsValidationResult : ValidationResult +{ + public FloatOpsValidationResult(string message) : base(message) { - public FloatOpsValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/GetHashCodeValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/GetHashCodeValidator.cs index 9afb953119..e98e29efad 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/GetHashCodeValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/GetHashCodeValidator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -6,127 +5,122 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class GetHashCodeValidator : IValidator, ITransientDependency { - public class GetHashCodeValidator : IValidator, ITransientDependency + public bool SystemContactIgnored => false; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) { - public bool SystemContactIgnored => false; + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return Enumerable.Empty(); - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + return method.Name == nameof(GetHashCode) ? ValidateGetHashCodeMethod(method) : ValidateRegularMethod(method); + } + + private IEnumerable ValidateRegularMethod(MethodDefinition method) + { + var errors = new List(); + + // Do not allow calls to GetHashCode method from non GetHashCode methods in contract + foreach (var instruction in method.Body.Instructions) { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - - return method.Name == nameof(GetHashCode) ? - ValidateGetHashCodeMethod(method) : ValidateRegularMethod(method); + if (!(instruction.Operand is MethodReference accessedMethod)) continue; + + if (accessedMethod.Name == nameof(GetHashCode)) + errors.Add(new GetHashCodeValidationResult( + "It is not allowed to access GetHashCode method from a non GetHashCode method.") + .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name)); } - - private IEnumerable ValidateRegularMethod(MethodDefinition method) - { - var errors = new List(); - // Do not allow calls to GetHashCode method from non GetHashCode methods in contract - foreach (var instruction in method.Body.Instructions) - { - if (!(instruction.Operand is MethodReference accessedMethod)) continue; - - if (accessedMethod.Name == nameof(GetHashCode)) - { - errors.Add(new GetHashCodeValidationResult( - "It is not allowed to access GetHashCode method from a non GetHashCode method.") - .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name)); - } - } + return errors; + } - return errors; - } + private IEnumerable ValidateGetHashCodeMethod(MethodDefinition method) + { + var errors = new List(); - private IEnumerable ValidateGetHashCodeMethod(MethodDefinition method) + foreach (var instruction in method.Body.Instructions) { - var errors = new List(); - - foreach (var instruction in method.Body.Instructions) + GetHashCodeValidationResult error = null; + + switch (instruction.Operand) { - GetHashCodeValidationResult error = null; - - switch (instruction.Operand) - { - case MethodReference accessedMethod: - var methodDefinition = accessedMethod.Resolve(); - - if (!(IsGetHashCodeCall(methodDefinition) - || IsFieldGetterCall(methodDefinition) - || IsGetLengthCall(methodDefinition) - || IsExecutionObserverCall(methodDefinition) - || IsInequalityOperatorCall(methodDefinition))) - { - error = new GetHashCodeValidationResult( - $"It is not allowed to access {accessedMethod.Name} method within GetHashCode method."); - } - - break; - - case FieldReference accessedField: - if (instruction.OpCode != OpCodes.Ldfld) // Only allow ldfld, do not allow the rest with fields - error = new GetHashCodeValidationResult( - $"It is not allowed to set {accessedField.Name} field within GetHashCode method."); - break; - } - - if (error != null) - { - errors.Add(error.WithInfo(method.Name, - method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name)); - } + case MethodReference accessedMethod: + var methodDefinition = accessedMethod.Resolve(); + + if (!(IsGetHashCodeCall(methodDefinition) + || IsFieldGetterCall(methodDefinition) + || IsGetLengthCall(methodDefinition) + || IsExecutionObserverCall(methodDefinition) + || IsInequalityOperatorCall(methodDefinition))) + error = new GetHashCodeValidationResult( + $"It is not allowed to access {accessedMethod.Name} method within GetHashCode method."); + + break; + + case FieldReference accessedField: + if (instruction.OpCode != OpCodes.Ldfld) // Only allow ldfld, do not allow the rest with fields + error = new GetHashCodeValidationResult( + $"It is not allowed to set {accessedField.Name} field within GetHashCode method."); + break; } - return errors; + if (error != null) + errors.Add(error.WithInfo(method.Name, + method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name)); } - private bool IsInequalityOperatorCall(MethodDefinition method) - { - if (!(method.Name == "op_Inequality" - && method.Parameters.Count == 2 - && method.ReturnType.FullName == typeof(bool).FullName)) - return false; + return errors; + } - // Both input parameters should be of declaring type - return method.Parameters.All(p => p.ParameterType == method.DeclaringType); - } + private bool IsInequalityOperatorCall(MethodDefinition method) + { + if (!(method.Name == "op_Inequality" + && method.Parameters.Count == 2 + && method.ReturnType.FullName == typeof(bool).FullName)) + return false; - private bool IsFieldGetterCall(MethodDefinition method) - { - return method.Name.StartsWith("get_") && !method.HasParameters && method.HasBody; - } + // Both input parameters should be of declaring type + return method.Parameters.All(p => p.ParameterType == method.DeclaringType); + } - private bool IsGetLengthCall(MethodDefinition method) - { - // Allowed for 2 types only - return (method.DeclaringType.FullName == "System.String" || method.DeclaringType.FullName == "Google.Protobuf.ByteString") - && method.Name == "get_Length" && !method.HasParameters && method.ReturnType.FullName == typeof(int).FullName; - } + private bool IsFieldGetterCall(MethodDefinition method) + { + return method.Name.StartsWith("get_") && !method.HasParameters && method.HasBody; + } - private bool IsExecutionObserverCall(MethodDefinition method) - { - return method.DeclaringType.Name == nameof(ExecutionObserverProxy) - && (method.Name == nameof(ExecutionObserverProxy.CallCount) || method.Name == nameof(ExecutionObserverProxy.BranchCount)) - && method.ReturnType.FullName == "System.Void" - && !method.HasParameters; - } + private bool IsGetLengthCall(MethodDefinition method) + { + // Allowed for 2 types only + return (method.DeclaringType.FullName == "System.String" || + method.DeclaringType.FullName == "Google.Protobuf.ByteString") + && method.Name == "get_Length" && !method.HasParameters && + method.ReturnType.FullName == typeof(int).FullName; + } - private bool IsGetHashCodeCall(MethodDefinition method) - { - return method.Name == nameof(GetHashCode) && !method.HasParameters; - } + private bool IsExecutionObserverCall(MethodDefinition method) + { + return method.DeclaringType.Name == nameof(ExecutionObserverProxy) + && (method.Name == nameof(ExecutionObserverProxy.CallCount) || + method.Name == nameof(ExecutionObserverProxy.BranchCount)) + && method.ReturnType.FullName == "System.Void" + && !method.HasParameters; } - - public class GetHashCodeValidationResult : ValidationResult + + private bool IsGetHashCodeCall(MethodDefinition method) + { + return method.Name == nameof(GetHashCode) && !method.HasParameters; + } +} + +public class GetHashCodeValidationResult : ValidationResult +{ + public GetHashCodeValidationResult(string message) : base(message) { - public GetHashCodeValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/MultiDimArrayValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/MultiDimArrayValidator.cs index 0cf99377aa..f083b4ff0a 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/MultiDimArrayValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/MultiDimArrayValidator.cs @@ -5,45 +5,40 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class MultiDimArrayValidator : IValidator, ITransientDependency { - public class MultiDimArrayValidator : IValidator, ITransientDependency + public bool SystemContactIgnored => false; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) { - public bool SystemContactIgnored => false; - - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - - var errors = new List(); - - foreach (var instruction in method.Body.Instructions) + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return Enumerable.Empty(); + + var errors = new List(); + + foreach (var instruction in method.Body.Instructions) + if (instruction.OpCode.Code == Code.Newarr) { - if (instruction.OpCode.Code == Code.Newarr) - { - var typeReference = (TypeReference) instruction.Operand; - - if (typeReference.IsArray) - { - errors.Add( - new MultiDimArrayValidationResult($"{method.Name} contains multi dimension array declaration.") - .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); - } - } + var typeReference = (TypeReference)instruction.Operand; + + if (typeReference.IsArray) + errors.Add( + new MultiDimArrayValidationResult($"{method.Name} contains multi dimension array declaration.") + .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); } - return errors; - } + return errors; } +} - public class MultiDimArrayValidationResult : ValidationResult +public class MultiDimArrayValidationResult : ValidationResult +{ + public MultiDimArrayValidationResult(string message) : base(message) { - public MultiDimArrayValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/UncheckedMathValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/UncheckedMathValidator.cs index 2fe8f91f9a..bab8d37373 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/UncheckedMathValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/UncheckedMathValidator.cs @@ -5,47 +5,46 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class UncheckedMathValidator : IValidator, ITransientDependency { - public class UncheckedMathValidator : IValidator, ITransientDependency + private readonly HashSet _uncheckedOpCodes = new() { - private readonly HashSet _uncheckedOpCodes = new HashSet - { - OpCodes.Add, - OpCodes.Sub, - OpCodes.Mul - }; - - public bool SystemContactIgnored => false; - - public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + OpCodes.Add, + OpCodes.Sub, + OpCodes.Mul + }; + + public bool SystemContactIgnored => false; + + public IEnumerable Validate(MethodDefinition method, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return Enumerable.Empty(); + + var errors = new List(); + + foreach (var instruction in method.Body.Instructions) { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return Enumerable.Empty(); - - var errors = new List(); - - foreach (var instruction in method.Body.Instructions) - { - if (!_uncheckedOpCodes.Contains(instruction.OpCode)) - continue; - - errors.Add( - new UncheckedMathValidationResult( $"{method.Name} contains unsafe OpCode " + instruction.OpCode) - .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); - } - - return errors; + if (!_uncheckedOpCodes.Contains(instruction.OpCode)) + continue; + + errors.Add( + new UncheckedMathValidationResult($"{method.Name} contains unsafe OpCode " + instruction.OpCode) + .WithInfo(method.Name, method.DeclaringType.Namespace, method.DeclaringType.Name, null)); } + + return errors; } - - public class UncheckedMathValidationResult : ValidationResult +} + +public class UncheckedMathValidationResult : ValidationResult +{ + public UncheckedMathValidationResult(string message) : base(message) { - public UncheckedMathValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs index 80ab9d1cea..4950d31d0d 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -12,267 +11,236 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Module +namespace AElf.CSharp.CodeOps.Validators.Module; + +public class ContractStructureValidator : IValidator, ITransientDependency { - public class ContractStructureValidator : IValidator, ITransientDependency + private readonly HashSet _allowedStateTypes = new() + { + typeof(BoolState).FullName, + typeof(Int32State).FullName, + typeof(UInt32State).FullName, + typeof(Int64State).FullName, + typeof(UInt64State).FullName, + typeof(StringState).FullName, + typeof(BytesState).FullName, + + // Complex state types + typeof(ReadonlyState<>).FullName, + typeof(SingletonState<>).FullName, + typeof(MappedState<,>).FullName, + typeof(MappedState<,,>).FullName, + typeof(MappedState<,,,>).FullName, + typeof(MappedState<,,,,>).FullName, + typeof(MethodReference<,>).FullName, + typeof(ProtobufState<>).FullName + }; + + // For example, we need to allow only primitive types in read only collections + private readonly HashSet _allowedStaticFieldInitOnlyTypes = new() + { + typeof(Marshaller<>).FullName, + typeof(Method<,>).FullName, + typeof(MessageParser<>).FullName, + typeof(FieldCodec<>).FullName, + typeof(MapField<,>.Codec).FullName, + typeof(ReadOnlyCollection<>).FullName, + typeof(IReadOnlyDictionary<,>).FullName + }; + + public ContractStructureValidator() { - public ContractStructureValidator() + // Convert full names to Mono.Cecil compatible full names + foreach (var typeName in _allowedStaticFieldInitOnlyTypes.Where(typeName => typeName.Contains("+")).ToList()) { - // Convert full names to Mono.Cecil compatible full names - foreach (var typeName in _allowedStaticFieldInitOnlyTypes.Where(typeName => typeName.Contains("+")).ToList()) - { - _allowedStaticFieldInitOnlyTypes.Remove(typeName); - _allowedStaticFieldInitOnlyTypes.Add(typeName.Replace("+", "/")); - } + _allowedStaticFieldInitOnlyTypes.Remove(typeName); + _allowedStaticFieldInitOnlyTypes.Add(typeName.Replace("+", "/")); } + } - public bool SystemContactIgnored => false; + public bool SystemContactIgnored => false; - public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - var structureError = ValidateStructure(module); + public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); - if (structureError != null) - return new[] { structureError }.ToList(); + var structureError = ValidateStructure(module); - return module.Types.SelectMany(t => ValidateType(t, ct)); - } + if (structureError != null) + return new[] { structureError }.ToList(); - private ValidationResult ValidateStructure(ModuleDefinition module) - { - // There should be only one contract base - var contractBase = module.Types - .SelectMany(t => t.NestedTypes.Where(nt => nt.IsContractImplementation())) - .SingleOrDefault(); - - if (contractBase == null) - { - return new ContractStructureValidationResult("Contract base not found."); - } - - var contractImplementation = module.Types.SingleOrDefault(t => t.IsContractImplementation()); - if (contractImplementation == null) - { - return new ContractStructureValidationResult("Contract implementation not found."); - } - - if (contractImplementation.BaseType != contractBase) - { - return new ContractStructureValidationResult( - $"Contract implementation should inherit from {contractBase.Name} " + - $"but inherited from {contractImplementation.BaseType.Name}"); - } - - var contractState = contractBase.BaseType is GenericInstanceType genericType - ? genericType.GenericArguments.SingleOrDefault() - : null; - - if (contractState == null) - { - return new ContractStructureValidationResult("Contract state not found."); - } - - var currentContractStateBase = ((TypeDefinition) contractState).BaseType.FullName; - var aelfContractStateBase = typeof(ContractState).FullName; - if (currentContractStateBase != aelfContractStateBase) - { - return new ContractStructureValidationResult( - $"Contract state should inherit from {aelfContractStateBase} " + - $"but inherited from {currentContractStateBase}"); - } - - return null; - } + return module.Types.SelectMany(t => ValidateType(t, ct)); + } - private IEnumerable ValidateType(TypeDefinition type, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - var errors = new List(); - - if (type.IsStateImplementation()) - { - return ValidateContractStateType(type); - } - - errors.AddRange(type.IsContractImplementation() ? ValidateContractType(type) : ValidateRegularType(type)); - errors.AddRange(type.NestedTypes.SelectMany(t => ValidateType(t, ct))); - - return errors; - } + private ValidationResult ValidateStructure(ModuleDefinition module) + { + // There should be only one contract base + var contractBase = module.Types + .SelectMany(t => t.NestedTypes.Where(nt => nt.IsContractImplementation())) + .SingleOrDefault(); - private IEnumerable ValidateContractStateType(TypeDefinition type) - { - // Only allow MappedState, ContractReferenceState or MethodReference fields - var badFields = type.Fields.Where(IsBadStateField).ToList(); - - if (badFields.Any()) - { - return badFields.Select(f => - new ContractStructureValidationResult( - $"{f.FieldType.FullName} type is not allowed as a field in contract state.") - .WithInfo(f.Name, type.Namespace, type.Name, f.Name)); - } - - return Enumerable.Empty(); - } + if (contractBase == null) return new ContractStructureValidationResult("Contract base not found."); - private IEnumerable ValidateContractType(TypeDefinition type) - { - // Allow readonly only if the type is primitive type - // Allow constants - // Allow any other types if not readonly or constant (since ResetFields can reset later on) - // Simply, do not allow if the field is readonly and not one of the allowed types - var errors = type.Fields - .Where(f => f.IsInitOnly && !_allowedStaticFieldInitOnlyTypes.Contains(FieldTypeFullName(f))) - .Select(f => - new ContractStructureValidationResult("Only primitive types or whitelisted types are allowed as readonly fields in contract implementation.") + var contractImplementation = module.Types.SingleOrDefault(t => t.IsContractImplementation()); + if (contractImplementation == null) + return new ContractStructureValidationResult("Contract implementation not found."); + + if (contractImplementation.BaseType != contractBase) + return new ContractStructureValidationResult( + $"Contract implementation should inherit from {contractBase.Name} " + + $"but inherited from {contractImplementation.BaseType.Name}"); + + var contractState = contractBase.BaseType is GenericInstanceType genericType + ? genericType.GenericArguments.SingleOrDefault() + : null; + + if (contractState == null) return new ContractStructureValidationResult("Contract state not found."); + + var currentContractStateBase = ((TypeDefinition)contractState).BaseType.FullName; + var aelfContractStateBase = typeof(ContractState).FullName; + if (currentContractStateBase != aelfContractStateBase) + return new ContractStructureValidationResult( + $"Contract state should inherit from {aelfContractStateBase} " + + $"but inherited from {currentContractStateBase}"); + + return null; + } + + private IEnumerable ValidateType(TypeDefinition type, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + var errors = new List(); + + if (type.IsStateImplementation()) return ValidateContractStateType(type); + + errors.AddRange(type.IsContractImplementation() ? ValidateContractType(type) : ValidateRegularType(type)); + errors.AddRange(type.NestedTypes.SelectMany(t => ValidateType(t, ct))); + + return errors; + } + + private IEnumerable ValidateContractStateType(TypeDefinition type) + { + // Only allow MappedState, ContractReferenceState or MethodReference fields + var badFields = type.Fields.Where(IsBadStateField).ToList(); + + if (badFields.Any()) + return badFields.Select(f => + new ContractStructureValidationResult( + $"{f.FieldType.FullName} type is not allowed as a field in contract state.") + .WithInfo(f.Name, type.Namespace, type.Name, f.Name)); + + return Enumerable.Empty(); + } + + private IEnumerable ValidateContractType(TypeDefinition type) + { + // Allow readonly only if the type is primitive type + // Allow constants + // Allow any other types if not readonly or constant (since ResetFields can reset later on) + // Simply, do not allow if the field is readonly and not one of the allowed types + var errors = type.Fields + .Where(f => f.IsInitOnly && !_allowedStaticFieldInitOnlyTypes.Contains(FieldTypeFullName(f))) + .Select(f => + new ContractStructureValidationResult( + "Only primitive types or whitelisted types are allowed as readonly fields in contract implementation.") .WithInfo(f.Name, type.Namespace, type.Name, f.Name)).ToList(); - // Do not allow setting value of any non-constant, non-readonly field in constructor - foreach (var method in type.Methods.Where(m => m.IsConstructor)) - { - foreach (var instruction in method.Body.Instructions - .Where(i => i.OpCode == OpCodes.Stfld || i.OpCode == OpCodes.Stsfld)) - { - if (instruction.Operand is FieldDefinition field && !(field.IsInitOnly || field.HasConstant)) - { - errors.Add(new ContractStructureValidationResult($"Initialization value is not allowed for field {field.Name}.") - .WithInfo(method.Name, type.Namespace, type.Name, field.Name)); - } - } - } - - return errors; - } + // Do not allow setting value of any non-constant, non-readonly field in constructor + foreach (var method in type.Methods.Where(m => m.IsConstructor)) + foreach (var instruction in method.Body.Instructions + .Where(i => i.OpCode == OpCodes.Stfld || i.OpCode == OpCodes.Stsfld)) + if (instruction.Operand is FieldDefinition field && !(field.IsInitOnly || field.HasConstant)) + errors.Add(new ContractStructureValidationResult( + $"Initialization value is not allowed for field {field.Name}.") + .WithInfo(method.Name, type.Namespace, type.Name, field.Name)); - private IEnumerable ValidateRegularType(TypeDefinition type) - { - // Skip if ExecutionObserverThreshold (validated in a separate validator) - if (type.Name == typeof(ExecutionObserverProxy).Name) - return Enumerable.Empty(); + return errors; + } - var staticFields = type.Fields.Where(f => f.IsStatic); - var badFields = staticFields.Where(IsBadField).ToList(); + private IEnumerable ValidateRegularType(TypeDefinition type) + { + // Skip if ExecutionObserverThreshold (validated in a separate validator) + if (type.Name == typeof(ExecutionObserverProxy).Name) + return Enumerable.Empty(); + + var staticFields = type.Fields.Where(f => f.IsStatic); + var badFields = staticFields.Where(IsBadField).ToList(); - var errors = badFields.Select(f => + var errors = badFields.Select(f => new ContractStructureValidationResult( $"{f.FieldType.FullName} type is not allowed to be used as static field in regular types in contract.") .WithInfo(f.Name, type.Namespace, type.Name, f.Name)) - .ToList(); - - foreach (var method in type.Methods.Where(m => m.IsConstructor)) - { - foreach (var instruction in method.Body.Instructions - .Where(i => i.OpCode == OpCodes.Stfld || i.OpCode == OpCodes.Stsfld)) - { - if (instruction.Operand is FieldDefinition field && - field.FieldType.FullName != typeof(FileDescriptor).FullName && // Allow FileDescriptor fields - field.IsStatic && !(field.IsInitOnly || field.HasConstant)) - { - errors.Add(new ContractStructureValidationResult($"Initialization value is not allowed for field {field.Name}.") - .WithInfo(method.Name, type.Namespace, type.Name, field.Name)); - } - } - } - - return errors; - } + .ToList(); + + foreach (var method in type.Methods.Where(m => m.IsConstructor)) + foreach (var instruction in method.Body.Instructions + .Where(i => i.OpCode == OpCodes.Stfld || i.OpCode == OpCodes.Stsfld)) + if (instruction.Operand is FieldDefinition field && + field.FieldType.FullName != typeof(FileDescriptor).FullName && // Allow FileDescriptor fields + field.IsStatic && !(field.IsInitOnly || field.HasConstant)) + errors.Add(new ContractStructureValidationResult( + $"Initialization value is not allowed for field {field.Name}.") + .WithInfo(method.Name, type.Namespace, type.Name, field.Name)); + + return errors; + } - private bool IsBadField(FieldDefinition field) - { - var fieldTypeFullName = FieldTypeFullName(field); - - // If constant, which means it is also primitive, then not a bad field - if (field.HasConstant) - return false; - - // If a field is init only, then only pass allowed types - if (field.IsInitOnly && - (_allowedStaticFieldInitOnlyTypes.Contains(fieldTypeFullName) || - Constants.PrimitiveTypes.Contains(fieldTypeFullName))) - { - // If field type is ReadOnly GenericInstanceType, only primitive types are allowed - // ReadOnlyCollection, ReadOnlyDictionary etc. - if (field.FieldType is GenericInstanceType fieldType && field.FieldType.Name.Contains("ReadOnly")) - { - return fieldType.GenericArguments.Any(a => !Constants.PrimitiveTypes.Contains(a.FullName)); - } - - return false; - } - - // If a type has a field that is same type of itself (Seen in nested classes generated due to Linq) - // Don't allow any instance fields inside the type of the readonly static field - if (fieldTypeFullName == field.DeclaringType.FullName && field.DeclaringType.Fields.All(f => f.IsStatic)) - return false; - - return field.IsInitOnly; - } + private bool IsBadField(FieldDefinition field) + { + var fieldTypeFullName = FieldTypeFullName(field); + + // If constant, which means it is also primitive, then not a bad field + if (field.HasConstant) + return false; - private string FieldTypeFullName(FieldDefinition field) + // If a field is init only, then only pass allowed types + if (field.IsInitOnly && + (_allowedStaticFieldInitOnlyTypes.Contains(fieldTypeFullName) || + Constants.PrimitiveTypes.Contains(fieldTypeFullName))) { - return field.FieldType is GenericInstanceType genericInstance - ? genericInstance.ElementType.FullName // TypeXyz then element type full name will be TypeXyz`1 - : field.FieldType.FullName; + // If field type is ReadOnly GenericInstanceType, only primitive types are allowed + // ReadOnlyCollection, ReadOnlyDictionary etc. + if (field.FieldType is GenericInstanceType fieldType && field.FieldType.Name.Contains("ReadOnly")) + return fieldType.GenericArguments.Any(a => !Constants.PrimitiveTypes.Contains(a.FullName)); + + return false; } - private bool IsBadStateField(FieldDefinition field) - { - if (field.FieldType is GenericInstanceType genericInstanceType) - { - return !_allowedStateTypes.Contains(genericInstanceType.ElementType.FullName); - } + // If a type has a field that is same type of itself (Seen in nested classes generated due to Linq) + // Don't allow any instance fields inside the type of the readonly static field + if (fieldTypeFullName == field.DeclaringType.FullName && field.DeclaringType.Fields.All(f => f.IsStatic)) + return false; - if (_allowedStateTypes.Contains(field.FieldType.FullName)) - return false; + return field.IsInitOnly; + } - // If not ContractReferenceState then it is not allowed - return field.FieldType.Resolve().BaseType.FullName != typeof(ContractReferenceState).FullName; - } - - // For example, we need to allow only primitive types in read only collections - private readonly HashSet _allowedStaticFieldInitOnlyTypes = new HashSet - { - typeof(Marshaller<>).FullName, - typeof(Method<,>).FullName, - typeof(MessageParser<>).FullName, - typeof(FieldCodec<>).FullName, - typeof(MapField<,>.Codec).FullName, - typeof(ReadOnlyCollection<>).FullName, - typeof(IReadOnlyDictionary<,>).FullName - }; - - private readonly HashSet _allowedStateTypes = new HashSet - { - typeof(BoolState).FullName, - typeof(Int32State).FullName, - typeof(UInt32State).FullName, - typeof(Int64State).FullName, - typeof(UInt64State).FullName, - typeof(StringState).FullName, - typeof(BytesState).FullName, - - // Complex state types - typeof(ReadonlyState<>).FullName, - typeof(SingletonState<>).FullName, - typeof(MappedState<,>).FullName, - typeof(MappedState<,,>).FullName, - typeof(MappedState<,,,>).FullName, - typeof(MappedState<,,,,>).FullName, - typeof(MethodReference<,>).FullName, - typeof(ProtobufState<>).FullName, - }; + private string FieldTypeFullName(FieldDefinition field) + { + return field.FieldType is GenericInstanceType genericInstance + ? genericInstance.ElementType.FullName // TypeXyz then element type full name will be TypeXyz`1 + : field.FieldType.FullName; + } + + private bool IsBadStateField(FieldDefinition field) + { + if (field.FieldType is GenericInstanceType genericInstanceType) + return !_allowedStateTypes.Contains(genericInstanceType.ElementType.FullName); + + if (_allowedStateTypes.Contains(field.FieldType.FullName)) + return false; + + // If not ContractReferenceState then it is not allowed + return field.FieldType.Resolve().BaseType.FullName != typeof(ContractReferenceState).FullName; } - - public class ContractStructureValidationResult : ValidationResult +} + +public class ContractStructureValidationResult : ValidationResult +{ + public ContractStructureValidationResult(string message) : base(message) { - public ContractStructureValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Module/InstructionInjectionValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Module/InstructionInjectionValidator.cs index da4690e707..093487e833 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Module/InstructionInjectionValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Module/InstructionInjectionValidator.cs @@ -5,75 +5,65 @@ using Mono.Cecil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class InstructionInjectionValidator : IValidator, ITransientDependency { - public class InstructionInjectionValidator : IValidator, ITransientDependency + private readonly IStateWrittenInstructionInjector _instructionInjector; + + public InstructionInjectionValidator(IStateWrittenInstructionInjector instructionInjector) { - private readonly IStateWrittenInstructionInjector _instructionInjector; + _instructionInjector = instructionInjector; + } - public InstructionInjectionValidator(IStateWrittenInstructionInjector instructionInjector) - { - _instructionInjector = instructionInjector; - } + public bool SystemContactIgnored => true; - public bool SystemContactIgnored => true; + public IEnumerable Validate(ModuleDefinition moduleDefinition, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); - public IEnumerable Validate(ModuleDefinition moduleDefinition, CancellationToken ct) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - var result = new List(); - foreach (var typ in moduleDefinition.Types) - { - result.AddRange(ValidateType(typ, moduleDefinition)); - } - - return result; - } - - private List ValidateType(TypeDefinition type, ModuleDefinition moduleDefinition) - { - var result = new List(); + var result = new List(); + foreach (var typ in moduleDefinition.Types) result.AddRange(ValidateType(typ, moduleDefinition)); - foreach (var method in type.Methods) - { - result.AddRange(ValidateMethod(moduleDefinition, method)); - } + return result; + } - foreach (var nestedType in type.NestedTypes) - { - result.AddRange(ValidateType(nestedType, moduleDefinition)); - } + private List ValidateType(TypeDefinition type, ModuleDefinition moduleDefinition) + { + var result = new List(); - return result; - } - - private List ValidateMethod(ModuleDefinition moduleDefinition, MethodDefinition methodDefinition) - { - var result = new List(); + foreach (var method in type.Methods) result.AddRange(ValidateMethod(moduleDefinition, method)); + + foreach (var nestedType in type.NestedTypes) result.AddRange(ValidateType(nestedType, moduleDefinition)); - if (!methodDefinition.HasBody) - return result; + return result; + } - foreach (var instruction in methodDefinition.Body.Instructions.Where(instruction => - _instructionInjector.IdentifyInstruction(instruction)).ToList()) - { - if (_instructionInjector.ValidateInstruction(moduleDefinition, instruction)) - continue; - result.Add(new MethodCallInjectionValidationResult( - $"{_instructionInjector.GetType()} validation failed.").WithInfo(methodDefinition.Name, - methodDefinition.DeclaringType.Namespace, methodDefinition.DeclaringType.FullName, null)); - } + private List ValidateMethod(ModuleDefinition moduleDefinition, MethodDefinition methodDefinition) + { + var result = new List(); + if (!methodDefinition.HasBody) return result; + + foreach (var instruction in methodDefinition.Body.Instructions.Where(instruction => + _instructionInjector.IdentifyInstruction(instruction)).ToList()) + { + if (_instructionInjector.ValidateInstruction(moduleDefinition, instruction)) + continue; + result.Add(new MethodCallInjectionValidationResult( + $"{_instructionInjector.GetType()} validation failed.").WithInfo(methodDefinition.Name, + methodDefinition.DeclaringType.Namespace, methodDefinition.DeclaringType.FullName, null)); } + + return result; } - - public class MethodCallInjectionValidationResult : ValidationResult +} + +public class MethodCallInjectionValidationResult : ValidationResult +{ + public MethodCallInjectionValidationResult(string message) : base(message) { - public MethodCallInjectionValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Module/ObserverProxyValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Module/ObserverProxyValidator.cs index 37c7e880ef..d32d58fce6 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Module/ObserverProxyValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Module/ObserverProxyValidator.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -7,155 +6,142 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Module +namespace AElf.CSharp.CodeOps.Validators.Module; + +public class ObserverProxyValidator : IValidator, ITransientDependency { - public class ObserverProxyValidator : IValidator, ITransientDependency + private readonly TypeDefinition _counterProxyTypeRef; + private MethodDefinition _injProxyBranchCount; + private MethodDefinition _injProxyCallCount; + private MethodDefinition _injProxySetObserver; + private TypeDefinition _injProxyType; + + public ObserverProxyValidator() { - private readonly TypeDefinition _counterProxyTypeRef; - private TypeDefinition _injProxyType; - private MethodDefinition _injProxySetObserver; - private MethodDefinition _injProxyBranchCount; - private MethodDefinition _injProxyCallCount; + // Module is only used to construct the type + var module = AssemblyDefinition.ReadAssembly(typeof(ExecutionObserverProxy).Assembly.Location).MainModule; + _counterProxyTypeRef = ExecutionObserverInjector.ConstructCounterProxy(module, "AElf.Reference"); + } - public ObserverProxyValidator() - { - // Module is only used to construct the type - var module = AssemblyDefinition.ReadAssembly(typeof(ExecutionObserverProxy).Assembly.Location).MainModule; - _counterProxyTypeRef = ExecutionObserverInjector.ConstructCounterProxy(module, "AElf.Reference"); - } + public bool SystemContactIgnored => true; - public bool SystemContactIgnored => true; + public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) + { + var errors = new List(); - public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) - { - var errors = new List(); - - // Get proxy type reference - _injProxyType = module.Types.SingleOrDefault(t => t.Name == nameof(ExecutionObserverProxy)); - - if (_injProxyType == null) - return new List - { - new ObserverProxyValidationResult("Could not find execution observer proxy in contract.") - }; - - CheckObserverProxyIsNotTampered(errors); - - // Get references for proxy methods - _injProxySetObserver = - _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.SetObserver)); - _injProxyBranchCount = - _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.BranchCount)); - _injProxyCallCount = - _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.CallCount)); - - foreach (var typ in module.Types) - { - CheckCallsFromTypes(errors, typ, ct); - } - - return errors; - } + // Get proxy type reference + _injProxyType = module.Types.SingleOrDefault(t => t.Name == nameof(ExecutionObserverProxy)); - private void CheckObserverProxyIsNotTampered(List errors) - { - if (!_injProxyType.HasSameFields(_counterProxyTypeRef)) + if (_injProxyType == null) + return new List { - errors.Add(new ObserverProxyValidationResult(_injProxyType.Name + " type has different fields.")); - } + new ObserverProxyValidationResult("Could not find execution observer proxy in contract.") + }; - foreach (var refMethod in _counterProxyTypeRef.Methods) - { - var injMethod = _injProxyType.Methods.SingleOrDefault(m => m.Name == refMethod.Name); - - if (injMethod == null) - { - errors.Add(new ObserverProxyValidationResult(refMethod.Name + " is not implemented in observer proxy.")); - } - - if (!injMethod.HasSameBody(refMethod)) - { - var contractMethodBody = string.Join("\n", injMethod?.Body.Instructions.Select(i => i.ToString()).ToArray()); - var referenceMethodBody = string.Join("\n", refMethod?.Body.Instructions.Select(i => i.ToString()).ToArray()); - - errors.Add(new ObserverProxyValidationResult( - $"{refMethod.Name} proxy method body is tampered.\n" + - $"Injected Contract: \n{contractMethodBody}\n\n" + - $"Reference:\n{referenceMethodBody}")); - } - - if (!injMethod.HasSameParameters(refMethod)) - { - errors.Add(new ObserverProxyValidationResult(refMethod.Name + " proxy method accepts different parameters.")); - } - } - - if (_injProxyType.Methods.Count != _counterProxyTypeRef.Methods.Count) - errors.Add(new ObserverProxyValidationResult("Observer type contains unusual number of methods.")); - } + CheckObserverProxyIsNotTampered(errors); + + // Get references for proxy methods + _injProxySetObserver = + _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.SetObserver)); + _injProxyBranchCount = + _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.BranchCount)); + _injProxyCallCount = + _injProxyType.Methods.SingleOrDefault(m => m.Name == nameof(ExecutionObserverProxy.CallCount)); + + foreach (var typ in module.Types) CheckCallsFromTypes(errors, typ, ct); - private void CheckCallsFromTypes(List errors, TypeDefinition typ, CancellationToken ct) + return errors; + } + + private void CheckObserverProxyIsNotTampered(List errors) + { + if (!_injProxyType.HasSameFields(_counterProxyTypeRef)) + errors.Add(new ObserverProxyValidationResult(_injProxyType.Name + " type has different fields.")); + + foreach (var refMethod in _counterProxyTypeRef.Methods) { - if (typ == _injProxyType) // Do not need to validate calls from the injected proxy - return; - - // Patch the methods in the type - foreach (var method in typ.Methods) - { - CheckCallsFromMethods(errors, method, ct); - } + var injMethod = _injProxyType.Methods.SingleOrDefault(m => m.Name == refMethod.Name); + + if (injMethod == null) + errors.Add(new ObserverProxyValidationResult(refMethod.Name + + " is not implemented in observer proxy.")); - // Patch if there is any nested type within the type - foreach (var nestedType in typ.NestedTypes) + if (!injMethod.HasSameBody(refMethod)) { - CheckCallsFromTypes(errors, nestedType, ct); + var contractMethodBody = + string.Join("\n", injMethod?.Body.Instructions.Select(i => i.ToString()).ToArray()); + var referenceMethodBody = + string.Join("\n", refMethod?.Body.Instructions.Select(i => i.ToString()).ToArray()); + + errors.Add(new ObserverProxyValidationResult( + $"{refMethod.Name} proxy method body is tampered.\n" + + $"Injected Contract: \n{contractMethodBody}\n\n" + + $"Reference:\n{referenceMethodBody}")); } + + if (!injMethod.HasSameParameters(refMethod)) + errors.Add(new ObserverProxyValidationResult(refMethod.Name + + " proxy method accepts different parameters.")); } - private void CheckCallsFromMethods(List errors, MethodDefinition method, CancellationToken ct) + if (_injProxyType.Methods.Count != _counterProxyTypeRef.Methods.Count) + errors.Add(new ObserverProxyValidationResult("Observer type contains unusual number of methods.")); + } + + private void CheckCallsFromTypes(List errors, TypeDefinition typ, CancellationToken ct) + { + if (typ == _injProxyType) // Do not need to validate calls from the injected proxy + return; + + // Patch the methods in the type + foreach (var method in typ.Methods) CheckCallsFromMethods(errors, method, ct); + + // Patch if there is any nested type within the type + foreach (var nestedType in typ.NestedTypes) CheckCallsFromTypes(errors, nestedType, ct); + } + + private void CheckCallsFromMethods(List errors, MethodDefinition method, CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + if (!method.HasBody) + return; + + // First instruction should be a call to proxy call count method + var firstInstruction = method.Body.Instructions.First(); + if (!(firstInstruction.OpCode == OpCodes.Call && firstInstruction.Operand == _injProxyCallCount)) + errors.Add(new ObserverProxyValidationResult("Missing execution observer call count call detected. " + + $"[{method.DeclaringType.Name} > {method.Name}]")); + + // Should be a call placed before each branching opcode + foreach (var instruction in method.Body.Instructions) { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - if (!method.HasBody) - return; - - // First instruction should be a call to proxy call count method - var firstInstruction = method.Body.Instructions.First(); - if (!(firstInstruction.OpCode == OpCodes.Call && firstInstruction.Operand == _injProxyCallCount)) - errors.Add(new ObserverProxyValidationResult($"Missing execution observer call count call detected. " + - $"[{method.DeclaringType.Name} > {method.Name}]")); - - // Should be a call placed before each branching opcode - foreach (var instruction in method.Body.Instructions) + if (Constants.JumpingOpCodes.Contains(instruction.OpCode) + && instruction.Operand is Instruction targetInstruction + && targetInstruction.Offset < instruction.Offset) { - if (Constants.JumpingOpCodes.Contains(instruction.OpCode) - && instruction.Operand is Instruction targetInstruction - && targetInstruction.Offset < instruction.Offset) - { - var proxyCallInstruction = targetInstruction.Next; - - if (!(proxyCallInstruction.OpCode == OpCodes.Call && proxyCallInstruction.Operand == _injProxyBranchCount)) - { - errors.Add(new ObserverProxyValidationResult("Missing execution observer branch count call detected. " + - $"[{method.DeclaringType.Name} > {method.Name}]")); - } - } - - // Calling SetObserver method within contract is a breach - if (instruction.OpCode == OpCodes.Call && instruction.Operand == _injProxySetObserver) - { - errors.Add(new ObserverProxyValidationResult($"Proxy initialize call detected from within the contract. " + - $"[{method.DeclaringType.Name} > {method.Name}]")); - } + var proxyCallInstruction = targetInstruction.Next; + + if (!(proxyCallInstruction.OpCode == OpCodes.Call && + proxyCallInstruction.Operand == _injProxyBranchCount)) + errors.Add(new ObserverProxyValidationResult( + "Missing execution observer branch count call detected. " + + $"[{method.DeclaringType.Name} > {method.Name}]")); } + + // Calling SetObserver method within contract is a breach + if (instruction.OpCode == OpCodes.Call && instruction.Operand == _injProxySetObserver) + errors.Add(new ObserverProxyValidationResult( + "Proxy initialize call detected from within the contract. " + + $"[{method.DeclaringType.Name} > {method.Name}]")); } } - - public class ObserverProxyValidationResult : ValidationResult +} + +public class ObserverProxyValidationResult : ValidationResult +{ + public ObserverProxyValidationResult(string message) : base(message) { - public ObserverProxyValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Module/ResetFieldsValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Module/ResetFieldsValidator.cs index 856178869f..5f0999fdd3 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Module/ResetFieldsValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Module/ResetFieldsValidator.cs @@ -7,171 +7,157 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Module +namespace AElf.CSharp.CodeOps.Validators.Module; + +public class ResetFieldsValidator : IValidator, ITransientDependency { - public class ResetFieldsValidator : IValidator, ITransientDependency + public bool SystemContactIgnored => false; + + public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) { - public bool SystemContactIgnored => false; - - public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) - { - var errors = module.Types - .Where(t => t.Name != nameof(ExecutionObserverProxy)) - .SelectMany(t => ValidateResetFieldsMethod(t, t.IsContractImplementation(), ct)) - .ToList(); + var errors = module.Types + .Where(t => t.Name != nameof(ExecutionObserverProxy)) + .SelectMany(t => ValidateResetFieldsMethod(t, t.IsContractImplementation(), ct)) + .ToList(); - return errors; - } + return errors; + } + + private IEnumerable ValidateResetFieldsMethod(TypeDefinition type, bool isContractImplementation, + CancellationToken ct) + { + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); + + var errors = new List(); + + // Validate nested types (Do not consider any nested types as contract implementation) + errors.AddRange(type.NestedTypes.SelectMany(t => + ValidateResetFieldsMethod(t, false, ct))); + + var fieldsToReset = new List(); + + var methodsToCall = type.NestedTypes + .Select(t => t.Methods.SingleOrDefault(m => + m.Name == nameof(ResetFieldsMethodInjector.ResetFields))) + .Where(t => t != null) + .ToList(); - private IEnumerable ValidateResetFieldsMethod(TypeDefinition type, bool isContractImplementation, CancellationToken ct) + var resetFieldsMethod = + type.Methods.SingleOrDefault(m => m.Name == nameof(ResetFieldsMethodInjector.ResetFields)); + + if (isContractImplementation) { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); - - var errors = new List(); - - // Validate nested types (Do not consider any nested types as contract implementation) - errors.AddRange(type.NestedTypes.SelectMany(t => - ValidateResetFieldsMethod(t, false, ct))); - - var fieldsToReset = new List(); - - var methodsToCall = type.NestedTypes + // All fields including static ones and also base class instance fields should be reset + fieldsToReset.AddRange(type.GetAllFields(f => !(f.IsInitOnly || f.HasConstant))); + + // Contract implementation's ResetFields method should be calling all other types' ResetFields methods + methodsToCall.AddRange(type.Module.Types + .Where(t => t != type) .Select(t => t.Methods.SingleOrDefault(m => m.Name == nameof(ResetFieldsMethodInjector.ResetFields))) - .Where(t => t != null) - .ToList(); - - var resetFieldsMethod = type.Methods.SingleOrDefault(m => m.Name == nameof(ResetFieldsMethodInjector.ResetFields)); - - if (isContractImplementation) - { - // All fields including static ones and also base class instance fields should be reset - fieldsToReset.AddRange(type.GetAllFields(f => !(f.IsInitOnly || f.HasConstant))); - - // Contract implementation's ResetFields method should be calling all other types' ResetFields methods - methodsToCall.AddRange(type.Module.Types - .Where(t => t != type) - .Select(t => t.Methods.SingleOrDefault(m => - m.Name == nameof(ResetFieldsMethodInjector.ResetFields))) - .Where(t => t != null)); - - // Ensure contract implementation's ResetFields method is accessible from CSharpSmartContractProxy - if (resetFieldsMethod != null && !resetFieldsMethod.IsPublic) - { - errors.Add(new ResetFieldsValidationResult( - $"ResetFields method of contract implementation is not public.") - .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); - } - } - else - { - fieldsToReset.AddRange(type.Fields - .Where(f => - f.IsStatic && - !(f.IsInitOnly || f.HasConstant) && - f.FieldType.FullName != typeof(FileDescriptor).FullName)); - } - - if (resetFieldsMethod == null) - { - // If there is no ResetFields method but there are fields to clear or methods to call - // then the type is missing ResetFields method - if (fieldsToReset.Count > 0 || methodsToCall.Count > 0) - { - errors.Add(new ResetFieldsValidationResult( - $"{type.Name} type is missing ResetFields method.") - .WithInfo(type.Name, type.Namespace, type.Name, null)); - } - } - else - { - // Validate whether all fields are reset and other ResetFields methods are called - // fieldsToReset and methodsToCall variables are supposed to be cleared inside below method - errors.AddRange(ValidateMethodInstructions(resetFieldsMethod, fieldsToReset, methodsToCall)); - - // If there are remaining fields or methods not reset, then add error for those - if (fieldsToReset.Count > 0) - { - errors.Add(new ResetFieldsValidationResult( - $"ResetFields method is missing reset for certain fields " + - $"{string.Join(", ", fieldsToReset.Select(f => f.Name).ToArray())}") - .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); - } - - if (methodsToCall.Count > 0) - { - errors.Add(new ResetFieldsValidationResult( - $"ResetFields method is missing certain method calls " + - $"{string.Join(", ", methodsToCall.Select(m => m.DeclaringType + "::" + m.Name).ToArray())}") - .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); - } - } - - return errors; + .Where(t => t != null)); + + // Ensure contract implementation's ResetFields method is accessible from CSharpSmartContractProxy + if (resetFieldsMethod != null && !resetFieldsMethod.IsPublic) + errors.Add(new ResetFieldsValidationResult( + "ResetFields method of contract implementation is not public.") + .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); + } + else + { + fieldsToReset.AddRange(type.Fields + .Where(f => + f.IsStatic && + !(f.IsInitOnly || f.HasConstant) && + f.FieldType.FullName != typeof(FileDescriptor).FullName)); } - private IEnumerable ValidateMethodInstructions(MethodDefinition resetFieldsMethod, List fieldsToReset, - List methodsToCall) + if (resetFieldsMethod == null) { - var errors = new List(); - - foreach (var instruction in resetFieldsMethod.Body.Instructions) - { - // Skip first instruction in ResetFields method, this is supposed to be CallCount call - // and validation of this is handled in ObserverProxyValidator - if (instruction.Offset == 0 && - instruction.OpCode == OpCodes.Call && - instruction.Operand is MethodReference methodRef && - methodRef.Name == nameof(ExecutionObserverProxy.CallCount)) - continue; - - // If ret, assume end of the method and exit the loop - if (instruction.OpCode == OpCodes.Ret) - break; - - // Skip if using "this" to set an instance field - if (instruction.OpCode == OpCodes.Ldarg_0) - continue; - - // Skip if loading 0 or null to stack - if (instruction.OpCode == OpCodes.Ldc_I4_0 || instruction.OpCode == OpCodes.Ldnull) // Default value - continue; - - // If setting a field - if ((instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld) && - instruction.Operand is FieldDefinition field) - { - if (fieldsToReset.Remove(field)) - { - continue; - } - } - - // If calling a method - if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodDefinition method) - { - if (methodsToCall.Remove(method)) - { - continue; - } - } - - // If reached here, then something is wrong + // If there is no ResetFields method but there are fields to clear or methods to call + // then the type is missing ResetFields method + if (fieldsToReset.Count > 0 || methodsToCall.Count > 0) errors.Add(new ResetFieldsValidationResult( - $"Unexpected instruction {instruction} found in ResetFields method.") - .WithInfo(resetFieldsMethod.Name, resetFieldsMethod.DeclaringType.Namespace, - resetFieldsMethod.DeclaringType.Name, null)); - } + $"{type.Name} type is missing ResetFields method.") + .WithInfo(type.Name, type.Namespace, type.Name, null)); + } + else + { + // Validate whether all fields are reset and other ResetFields methods are called + // fieldsToReset and methodsToCall variables are supposed to be cleared inside below method + errors.AddRange(ValidateMethodInstructions(resetFieldsMethod, fieldsToReset, methodsToCall)); + + // If there are remaining fields or methods not reset, then add error for those + if (fieldsToReset.Count > 0) + errors.Add(new ResetFieldsValidationResult( + "ResetFields method is missing reset for certain fields " + + $"{string.Join(", ", fieldsToReset.Select(f => f.Name).ToArray())}") + .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); - return errors; + if (methodsToCall.Count > 0) + errors.Add(new ResetFieldsValidationResult( + "ResetFields method is missing certain method calls " + + $"{string.Join(", ", methodsToCall.Select(m => m.DeclaringType + "::" + m.Name).ToArray())}") + .WithInfo(resetFieldsMethod.Name, type.Namespace, type.Name, null)); } + + return errors; } - - public class ResetFieldsValidationResult : ValidationResult + + private IEnumerable ValidateMethodInstructions(MethodDefinition resetFieldsMethod, + List fieldsToReset, + List methodsToCall) { - public ResetFieldsValidationResult(string message) : base(message) + var errors = new List(); + + foreach (var instruction in resetFieldsMethod.Body.Instructions) { + // Skip first instruction in ResetFields method, this is supposed to be CallCount call + // and validation of this is handled in ObserverProxyValidator + if (instruction.Offset == 0 && + instruction.OpCode == OpCodes.Call && + instruction.Operand is MethodReference methodRef && + methodRef.Name == nameof(ExecutionObserverProxy.CallCount)) + continue; + + // If ret, assume end of the method and exit the loop + if (instruction.OpCode == OpCodes.Ret) + break; + + // Skip if using "this" to set an instance field + if (instruction.OpCode == OpCodes.Ldarg_0) + continue; + + // Skip if loading 0 or null to stack + if (instruction.OpCode == OpCodes.Ldc_I4_0 || instruction.OpCode == OpCodes.Ldnull) // Default value + continue; + + // If setting a field + if ((instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld) && + instruction.Operand is FieldDefinition field) + if (fieldsToReset.Remove(field)) + continue; + + // If calling a method + if (instruction.OpCode == OpCodes.Call && instruction.Operand is MethodDefinition method) + if (methodsToCall.Remove(method)) + continue; + + // If reached here, then something is wrong + errors.Add(new ResetFieldsValidationResult( + $"Unexpected instruction {instruction} found in ResetFields method.") + .WithInfo(resetFieldsMethod.Name, resetFieldsMethod.DeclaringType.Namespace, + resetFieldsMethod.DeclaringType.Name, null)); } + + return errors; + } +} + +public class ResetFieldsValidationResult : ValidationResult +{ + public ResetFieldsValidationResult(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/ValidationResult.cs b/src/AElf.CSharp.CodeOps/Validators/ValidationResult.cs index 7617209af1..4086f9ec5b 100644 --- a/src/AElf.CSharp.CodeOps/Validators/ValidationResult.cs +++ b/src/AElf.CSharp.CodeOps/Validators/ValidationResult.cs @@ -1,52 +1,47 @@ -using System; -using System.Dynamic; +namespace AElf.CSharp.CodeOps.Validators; -namespace AElf.CSharp.CodeOps.Validators +public abstract class ValidationResult { - public abstract class ValidationResult + protected ValidationResult(string message) { - public string Message { get; } - - public Info Info { get; private set; } + Message = message; + } - protected ValidationResult(string message) - { - Message = message; - } + public string Message { get; } - public ValidationResult WithInfo(string referencingMethod, string nm, string type, string member) - { - Info = new Info(referencingMethod, nm, type, member); - return this; - } + public Info Info { get; private set; } - public override string ToString() - { - return $"[{GetType().Name}] {Message} " + Info; - } + public ValidationResult WithInfo(string referencingMethod, string nm, string type, string member) + { + Info = new Info(referencingMethod, nm, type, member); + return this; } - - public class Info + + public override string ToString() { - public readonly string ReferencingMethod; - - public readonly string Namespace; - - public readonly string Type; - - public readonly string Member; - - public Info(string referencingMethod, string nm, string type, string member) - { - Namespace = nm; - Type = type; - ReferencingMethod = referencingMethod; - Member = member; - } - - public override string ToString() - { - return $"{ReferencingMethod} > {Namespace} | {Type} | {Member}"; - } + return $"[{GetType().Name}] {Message} " + Info; } } + +public class Info +{ + public readonly string Member; + + public readonly string Namespace; + public readonly string ReferencingMethod; + + public readonly string Type; + + public Info(string referencingMethod, string nm, string type, string member) + { + Namespace = nm; + Type = type; + ReferencingMethod = referencingMethod; + Member = member; + } + + public override string ToString() + { + return $"{ReferencingMethod} > {Namespace} | {Type} | {Member}"; + } +} \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs index 50b7b1116a..331d097d8a 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs @@ -1,13 +1,12 @@ using System; using System.Globalization; -using System.Numerics; -using AElf.Sdk.CSharp; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using AElf.Cryptography.SecretSharing; using AElf.CSharp.Core; using AElf.Kernel.SmartContract; +using AElf.Sdk.CSharp; using AElf.Types; using Volo.Abp.DependencyInjection; @@ -94,7 +93,7 @@ private void WhitelistSystemTypes(Whitelist whitelist) .Type(nameof(Decimal), Permission.Allowed) .Type(nameof(String), Permission.Allowed, member => member .Constructor(Permission.Denied)) - .Type(typeof(Byte[]).Name, Permission.Allowed) + .Type(typeof(byte[]).Name, Permission.Allowed) ); } @@ -135,7 +134,7 @@ private void WhitelistOthers(Whitelist whitelist) .Type(nameof(RuntimeHelpers), Permission.Denied, member => member .Member(nameof(RuntimeHelpers.InitializeArray), Permission.Allowed)) .Type(nameof(DefaultInterpolatedStringHandler), Permission.Allowed) - ) + ) .Namespace("System.Text", Permission.Denied, type => type .Type(nameof(Encoding), Permission.Denied, member => member .Member(nameof(Encoding.UTF8), Permission.Allowed) diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistValidator.cs index 0c4f0c8f2a..9bf4684eb1 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistValidator.cs @@ -5,263 +5,247 @@ using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public class WhitelistValidator : WhitelistValidatorBase, ITransientDependency { - public class WhitelistValidator : WhitelistValidatorBase, ITransientDependency + public WhitelistValidator(IWhitelistProvider whitelistProvider) : base(whitelistProvider) { - public WhitelistValidator(IWhitelistProvider whitelistProvider) : base(whitelistProvider) - { - } + } + + public override bool SystemContactIgnored => true; +} - public override bool SystemContactIgnored => true; +public class SystemContractWhitelistValidator : WhitelistValidatorBase, ITransientDependency +{ + public SystemContractWhitelistValidator(ISystemContractWhitelistProvider whitelistProvider) : base( + whitelistProvider) + { } - - public class SystemContractWhitelistValidator : WhitelistValidatorBase, ITransientDependency + + public override bool SystemContactIgnored => false; +} + +public abstract class WhitelistValidatorBase : IValidator +{ + private readonly IWhitelistProvider _whitelistProvider; + + public WhitelistValidatorBase(IWhitelistProvider whitelistProvider) { - public SystemContractWhitelistValidator(ISystemContractWhitelistProvider whitelistProvider) : base(whitelistProvider) - { - } + _whitelistProvider = whitelistProvider; + } + + public abstract bool SystemContactIgnored { get; } - public override bool SystemContactIgnored => false; + public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) + { + var whiteList = _whitelistProvider.GetWhitelist(); + var results = new List(); + // Validate assembly references + foreach (var asmRef in module.AssemblyReferences) + if (!whiteList.ContainsAssemblyNameReference(asmRef)) + results.Add(new WhitelistValidationResult("Assembly " + asmRef.Name + " is not allowed.")); + + // Validate types in the module + results.AddRange(module.Types.SelectMany(t => Validate(whiteList, t, ct))); + + // Validate nested types + results.AddRange(module.Types + .SelectMany(t => t.NestedTypes) + .SelectMany(t => Validate(whiteList, t, ct))); + + return results; } - - public abstract class WhitelistValidatorBase : IValidator + + private IEnumerable Validate(Whitelist whitelist, TypeDefinition type, CancellationToken ct) { - private readonly IWhitelistProvider _whitelistProvider; + var results = new List(); - public WhitelistValidatorBase(IWhitelistProvider whitelistProvider) + foreach (var method in type.Methods) { - _whitelistProvider = whitelistProvider; - } + if (ct.IsCancellationRequested) + throw new ContractAuditTimeoutException(); - public abstract bool SystemContactIgnored { get; } + if (!method.HasBody) + continue; - public IEnumerable Validate(ModuleDefinition module, CancellationToken ct) - { - var whiteList = _whitelistProvider.GetWhitelist(); - var results = new List(); - // Validate assembly references - foreach (var asmRef in module.AssemblyReferences) - { - if (!whiteList.ContainsAssemblyNameReference(asmRef)) - results.Add(new WhitelistValidationResult("Assembly " + asmRef.Name + " is not allowed.")); - } + foreach (var instruction in method.Body.Instructions) + results.AddRange(Validate(whitelist, method, instruction)); + } - // Validate types in the module - results.AddRange(module.Types.SelectMany(t => Validate(whiteList, t, ct))); + return results; + } - // Validate nested types - results.AddRange(module.Types - .SelectMany(t => t.NestedTypes) - .SelectMany(t => Validate(whiteList, t, ct))); + private IEnumerable Validate(Whitelist whitelist, MethodDefinition method, + Instruction instruction) + { + if (!(instruction.Operand is MemberReference reference)) + return Enumerable.Empty(); + if (reference is MethodReference methodReference) + { + var results = new List(); + results.AddRange(ValidateReference(whitelist, method, methodReference.DeclaringType, + methodReference.Name)); + results.AddRange(ValidateReference(whitelist, method, methodReference.ReturnType)); return results; } - private IEnumerable Validate(Whitelist whitelist, TypeDefinition type, CancellationToken ct) + if (reference is FieldReference fieldReference) { var results = new List(); + results.AddRange( + ValidateReference(whitelist, method, fieldReference.DeclaringType, fieldReference.Name)); + results.AddRange(ValidateReference(whitelist, method, fieldReference.FieldType)); + return results; + } - foreach (var method in type.Methods) - { - if (ct.IsCancellationRequested) - throw new ContractAuditTimeoutException(); + if (reference is TypeReference typeReference) return ValidateReference(whitelist, method, typeReference); - if (!method.HasBody) - continue; + return Enumerable.Empty(); + } - foreach (var instruction in method.Body.Instructions) - { - results.AddRange(Validate(whitelist, method, instruction)); - } - } + private IEnumerable ValidateReference(Whitelist whitelist, MethodDefinition method, + TypeReference type, + string member = null) + { + var results = new List(); + // If the type is a generic parameter, stop going deeper + if (type.IsGenericParameter) return results; - } - private IEnumerable Validate(Whitelist whitelist, MethodDefinition method, - Instruction instruction) - { - if (!(instruction.Operand is MemberReference reference)) - return Enumerable.Empty(); - - if (reference is MethodReference methodReference) - { - var results = new List(); - results.AddRange(ValidateReference(whitelist, method, methodReference.DeclaringType, - methodReference.Name)); - results.AddRange(ValidateReference(whitelist, method, methodReference.ReturnType)); - return results; - } - - if (reference is FieldReference fieldReference) - { - var results = new List(); - results.AddRange( - ValidateReference(whitelist, method, fieldReference.DeclaringType, fieldReference.Name)); - results.AddRange(ValidateReference(whitelist, method, fieldReference.FieldType)); - return results; - } - - if (reference is TypeReference typeReference) - { - return ValidateReference(whitelist, method, typeReference); - } + // If referred type is from a fully trusted assembly, stop going deeper + if (whitelist.CheckAssemblyFullyTrusted(type.Resolve()?.Module.Assembly.Name)) + return results; - return Enumerable.Empty(); + // Dig deeper by calling ValidateReference until reaching base type + if (type.IsByReference) + { + results.AddRange(ValidateReference(whitelist, method, type.GetElementType())); + return results; } - private IEnumerable ValidateReference(Whitelist whitelist, MethodDefinition method, - TypeReference type, - string member = null) + if (type is GenericInstanceType generic) { - var results = new List(); - - // If the type is a generic parameter, stop going deeper - if (type.IsGenericParameter) - return results; - - // If referred type is from a fully trusted assembly, stop going deeper - if (whitelist.CheckAssemblyFullyTrusted(type.Resolve()?.Module.Assembly.Name)) - return results; + results.AddRange(ValidateReference(whitelist, method, generic.ElementType)); - // Dig deeper by calling ValidateReference until reaching base type - if (type.IsByReference) - { - results.AddRange(ValidateReference(whitelist, method, type.GetElementType())); - return results; - } + foreach (var argument in generic.GenericArguments) + results.AddRange(ValidateReference(whitelist, method, argument)); - if (type is GenericInstanceType generic) - { - results.AddRange(ValidateReference(whitelist, method, generic.ElementType)); + return results; + } - foreach (var argument in generic.GenericArguments) - { - results.AddRange(ValidateReference(whitelist, method, argument)); - } + // If the type is an array, then validate the element type of the array + if (type.IsArray) + { + results.AddRange(ValidateReference(whitelist, method, type.GetElementType())); + return results; + } - return results; - } + // Reached the most base type, now we can validate against the whitelist + results.AddRange(ValidateAgainstWhitelist(whitelist, method, type, member)); - // If the type is an array, then validate the element type of the array - if (type.IsArray) - { - results.AddRange(ValidateReference(whitelist, method, type.GetElementType())); - return results; - } + return results; + } - // Reached the most base type, now we can validate against the whitelist - results.AddRange(ValidateAgainstWhitelist(whitelist, method, type, member)); + private IEnumerable ValidateAgainstWhitelist(Whitelist whitelist, MethodDefinition method, + TypeReference type, string member = null) + { + // Allow own defined types + if (type is TypeDefinition) yield break; - return results; - } + // Filter in the whitelist whether there is any rule + var result = Search(whitelist, type, member); - private IEnumerable ValidateAgainstWhitelist(Whitelist whitelist, MethodDefinition method, - TypeReference type, string member = null) + // Return a validation result if search result is negative (any of the denied results) + switch (result) { - // Allow own defined types - if (type is TypeDefinition) - { - yield break; - } - - // Filter in the whitelist whether there is any rule - var result = Search(whitelist, type, member); - - // Return a validation result if search result is negative (any of the denied results) - switch (result) - { - case WhitelistSearchResult.DeniedNamespace: - var ns = string.IsNullOrWhiteSpace(type.Namespace) ? @"""" : type.Namespace; - yield return new WhitelistValidationResult($"{ns} is not allowed.") - .WithInfo(method.Name, type.Namespace, type.Name, member); - break; - - case WhitelistSearchResult.DeniedType: - yield return new WhitelistValidationResult($"{type.Name} in {type.Namespace} is not allowed.") - .WithInfo(method.Name, type.Namespace, type.Name, member); - break; - - case WhitelistSearchResult.DeniedMember: - yield return new WhitelistValidationResult($"{member} in {type.FullName} is not allowed.") - .WithInfo(method.Name, type.Namespace, type.Name, member); - break; - } + case WhitelistSearchResult.DeniedNamespace: + var ns = string.IsNullOrWhiteSpace(type.Namespace) ? @"""" : type.Namespace; + yield return new WhitelistValidationResult($"{ns} is not allowed.") + .WithInfo(method.Name, type.Namespace, type.Name, member); + break; + + case WhitelistSearchResult.DeniedType: + yield return new WhitelistValidationResult($"{type.Name} in {type.Namespace} is not allowed.") + .WithInfo(method.Name, type.Namespace, type.Name, member); + break; + + case WhitelistSearchResult.DeniedMember: + yield return new WhitelistValidationResult($"{member} in {type.FullName} is not allowed.") + .WithInfo(method.Name, type.Namespace, type.Name, member); + break; } + } - private WhitelistSearchResult Search(Whitelist whitelist, TypeReference type, string member = null) - { - var typeNs = GetNameSpace(type); - - // Fail if there is no rule for the namespace - if (!whitelist.TryGetNamespaceRule(typeNs, out var namespaceRule)) - { - // If no exact match for namespace, check for wildcard matching - if (whitelist.ContainsWildcardMatchedNamespaceRule(typeNs)) - return WhitelistSearchResult.Allowed; - - return WhitelistSearchResult.DeniedNamespace; - } - - // Fail if the type is not allowed in the namespace - if (!namespaceRule.Types.TryGetValue(type.Name, out var typeRule) || - typeRule.Permission == Permission.Denied && !typeRule.Members.Any()) - { - return namespaceRule.Permission == Permission.Allowed - ? WhitelistSearchResult.Allowed - : WhitelistSearchResult.DeniedType; - } - - if (typeRule.Permission == Permission.Denied && !typeRule.Members.Any()) - return WhitelistSearchResult.DeniedType; + private WhitelistSearchResult Search(Whitelist whitelist, TypeReference type, string member = null) + { + var typeNs = GetNameSpace(type); - if (member == null) + // Fail if there is no rule for the namespace + if (!whitelist.TryGetNamespaceRule(typeNs, out var namespaceRule)) + { + // If no exact match for namespace, check for wildcard matching + if (whitelist.ContainsWildcardMatchedNamespaceRule(typeNs)) return WhitelistSearchResult.Allowed; - if (!typeRule.Members.TryGetValue(member, out var memberRule)) - { - if (!member.StartsWith("get_") && !member.StartsWith("set_")) - return typeRule.Permission == Permission.Allowed - ? WhitelistSearchResult.Allowed - : WhitelistSearchResult.DeniedMember; - - // Check without the prefix as well - member = member.Split(new[] {'_'}, 2)[1]; - if (!typeRule.Members.TryGetValue(member, out memberRule)) - { - return typeRule.Permission == Permission.Allowed - ? WhitelistSearchResult.Allowed - : WhitelistSearchResult.DeniedMember; - } - } - - return memberRule.Permission == Permission.Allowed - ? WhitelistSearchResult.Allowed - : WhitelistSearchResult.DeniedMember; + return WhitelistSearchResult.DeniedNamespace; } - private string GetNameSpace(TypeReference type) + // Fail if the type is not allowed in the namespace + if (!namespaceRule.Types.TryGetValue(type.Name, out var typeRule) || + (typeRule.Permission == Permission.Denied && !typeRule.Members.Any())) + return namespaceRule.Permission == Permission.Allowed + ? WhitelistSearchResult.Allowed + : WhitelistSearchResult.DeniedType; + + if (typeRule.Permission == Permission.Denied && !typeRule.Members.Any()) + return WhitelistSearchResult.DeniedType; + + if (member == null) + return WhitelistSearchResult.Allowed; + + if (!typeRule.Members.TryGetValue(member, out var memberRule)) { - // Below is needed for nested types that are declared in other types, otherwise namespace is null - return string.IsNullOrEmpty(type.Namespace) && type.DeclaringType != null - ? GetNameSpace(type.DeclaringType) - : type.Namespace; + if (!member.StartsWith("get_") && !member.StartsWith("set_")) + return typeRule.Permission == Permission.Allowed + ? WhitelistSearchResult.Allowed + : WhitelistSearchResult.DeniedMember; + + // Check without the prefix as well + member = member.Split(new[] { '_' }, 2)[1]; + if (!typeRule.Members.TryGetValue(member, out memberRule)) + return typeRule.Permission == Permission.Allowed + ? WhitelistSearchResult.Allowed + : WhitelistSearchResult.DeniedMember; } + + return memberRule.Permission == Permission.Allowed + ? WhitelistSearchResult.Allowed + : WhitelistSearchResult.DeniedMember; } - internal enum WhitelistSearchResult + private string GetNameSpace(TypeReference type) { - Allowed, - DeniedNamespace, - DeniedType, - DeniedMember, + // Below is needed for nested types that are declared in other types, otherwise namespace is null + return string.IsNullOrEmpty(type.Namespace) && type.DeclaringType != null + ? GetNameSpace(type.DeclaringType) + : type.Namespace; } +} + +internal enum WhitelistSearchResult +{ + Allowed, + DeniedNamespace, + DeniedType, + DeniedMember +} - public class WhitelistValidationResult : ValidationResult +public class WhitelistValidationResult : ValidationResult +{ + public WhitelistValidationResult(string message) : base(message) { - public WhitelistValidationResult(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/MemberRule.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/MemberRule.cs index b0ba04a584..c2313fc59b 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/MemberRule.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/MemberRule.cs @@ -1,14 +1,13 @@ -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public class MemberRule { - public class MemberRule + public MemberRule(string name, Permission permission) { - public string Name { get; } - public Permission Permission { get; } - - public MemberRule(string name, Permission permission) - { - Name = name; - Permission = permission; - } + Name = name; + Permission = permission; } + + public string Name { get; } + public Permission Permission { get; } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/NamespaceRule.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/NamespaceRule.cs index 2c5294dd92..2897cb6979 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/NamespaceRule.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/NamespaceRule.cs @@ -1,37 +1,36 @@ using System; using System.Collections.Generic; -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public class NamespaceRule { - public class NamespaceRule + private readonly IDictionary _types = new Dictionary(); + public Permission Permission; + + public NamespaceRule(string name, Permission permission) { - public string Name { get; } - public Permission Permission; + Name = name; + Permission = permission; + } - private readonly IDictionary _types = new Dictionary(); + public string Name { get; } - public IReadOnlyDictionary Types => (IReadOnlyDictionary) _types; + public IReadOnlyDictionary Types => (IReadOnlyDictionary)_types; - public NamespaceRule(string name, Permission permission) - { - Name = name; - Permission = permission; - } + public NamespaceRule Type(Type type, Permission permission, Action typeRules = null) + { + return Type(type.Name, permission, typeRules); + } - public NamespaceRule Type(Type type, Permission permission, Action typeRules = null) - { - return Type(type.Name, permission, typeRules); - } + public NamespaceRule Type(string name, Permission permission, Action typeRules = null) + { + var rule = new TypeRule(name, permission); - public NamespaceRule Type(string name, Permission permission, Action typeRules = null) - { - var rule = new TypeRule(name, permission); + _types[name] = rule; - _types[name] = rule; - - typeRules?.Invoke(rule); + typeRules?.Invoke(rule); - return this; - } + return this; } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Permission.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Permission.cs index 20b6c002e3..8c0bc94019 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Permission.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Permission.cs @@ -1,8 +1,7 @@ -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public enum Permission { - public enum Permission - { - Allowed, - Denied - } + Allowed, + Denied } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Trust.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Trust.cs index af60cda3b9..d977bd6eb1 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Trust.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Trust.cs @@ -1,8 +1,7 @@ -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public enum Trust { - public enum Trust - { - Full, - Partial - } + Full, + Partial } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/TypeRule.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/TypeRule.cs index b06fd546e2..78564f877f 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/TypeRule.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/TypeRule.cs @@ -1,31 +1,30 @@ using System.Collections.Generic; -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public class TypeRule { - public class TypeRule - { - public string Name { get; } - public Permission Permission { get; } + private readonly IDictionary _members = new Dictionary(); - private readonly IDictionary _members = new Dictionary(); + public TypeRule(string name, Permission permission) + { + Name = name; + Permission = permission; + } - public IReadOnlyDictionary Members => (IReadOnlyDictionary) _members; + public string Name { get; } + public Permission Permission { get; } - public TypeRule(string name, Permission permission) - { - Name = name; - Permission = permission; - } + public IReadOnlyDictionary Members => (IReadOnlyDictionary)_members; - public TypeRule Member(string name, Permission permission) - { - _members[name] = new MemberRule(name, permission); - return this; - } + public TypeRule Member(string name, Permission permission) + { + _members[name] = new MemberRule(name, permission); + return this; + } - public TypeRule Constructor(Permission permission) - { - return Member(".ctor", permission); - } + public TypeRule Constructor(Permission permission) + { + return Member(".ctor", permission); } } \ No newline at end of file diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Whitelist.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Whitelist.cs index 708ed872cd..0c7bd6cfde 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/Whitelist.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/Whitelist.cs @@ -3,58 +3,57 @@ using System.Linq; using Mono.Cecil; -namespace AElf.CSharp.CodeOps.Validators.Whitelist +namespace AElf.CSharp.CodeOps.Validators.Whitelist; + +public class Whitelist { - public class Whitelist - { - private readonly IDictionary _assemblies = new Dictionary(); - private readonly IDictionary _namespaces = new Dictionary(); + private readonly IDictionary _assemblies = new Dictionary(); + private readonly IDictionary _namespaces = new Dictionary(); - public IReadOnlyDictionary NameSpaces => - (IReadOnlyDictionary) _namespaces; + public IReadOnlyDictionary NameSpaces => + (IReadOnlyDictionary)_namespaces; - public Whitelist Assembly(System.Reflection.Assembly assembly, Trust trustLevel) - { - _assemblies.Add(assembly.GetName().Name, trustLevel); + public Whitelist Assembly(System.Reflection.Assembly assembly, Trust trustLevel) + { + _assemblies.Add(assembly.GetName().Name, trustLevel); - return this; - } + return this; + } - public Whitelist Namespace(string name, Permission permission, - Action namespaceRules = null) - { - var rule = new NamespaceRule(name, permission); + public Whitelist Namespace(string name, Permission permission, + Action namespaceRules = null) + { + var rule = new NamespaceRule(name, permission); - _namespaces[name] = rule; + _namespaces[name] = rule; - namespaceRules?.Invoke(rule); + namespaceRules?.Invoke(rule); - return this; - } + return this; + } - public bool ContainsAssemblyNameReference(AssemblyNameReference assemblyNameReference) - { - return _assemblies.Keys.Contains(assemblyNameReference.Name); - } + public bool ContainsAssemblyNameReference(AssemblyNameReference assemblyNameReference) + { + return _assemblies.Keys.Contains(assemblyNameReference.Name); + } - public bool CheckAssemblyFullyTrusted(AssemblyNameReference assemblyNameReference) - { - return _assemblies.Any(asm => asm.Key == assemblyNameReference?.Name && asm.Value == Trust.Full); - } + public bool CheckAssemblyFullyTrusted(AssemblyNameReference assemblyNameReference) + { + return _assemblies.Any(asm => asm.Key == assemblyNameReference?.Name && asm.Value == Trust.Full); + } - public bool TryGetNamespaceRule(string typeNamespace, out NamespaceRule namespaceRule) - { - return _namespaces.TryGetValue(typeNamespace, out namespaceRule); - } + public bool TryGetNamespaceRule(string typeNamespace, out NamespaceRule namespaceRule) + { + return _namespaces.TryGetValue(typeNamespace, out namespaceRule); + } - public bool ContainsWildcardMatchedNamespaceRule(string typeNamespace) - { - return _namespaces.Where(ns => ns.Value.Permission == Permission.Allowed - && !ns.Value.Types.Any() - && ns.Key.EndsWith("*")) - .Any(ns => typeNamespace.StartsWith(ns.Key.Replace(".*", "") - .Replace("*", ""))); - } + public bool ContainsWildcardMatchedNamespaceRule(string typeNamespace) + { + return _namespaces.Where(ns => ns.Value.Permission == Permission.Allowed + && !ns.Value.Types.Any() + && ns.Key.EndsWith("*")) + .Any(ns => typeNamespace.StartsWith(ns.Key.Replace(".*", "") + .Replace("*", ""))); } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/AElf.CSharp.Core.csproj b/src/AElf.CSharp.Core/AElf.CSharp.Core.csproj index 8f3a5a8b7a..4fa8489d88 100644 --- a/src/AElf.CSharp.Core/AElf.CSharp.Core.csproj +++ b/src/AElf.CSharp.Core/AElf.CSharp.Core.csproj @@ -1,15 +1,15 @@ - + - net6.0 - AElf.CSharp.Core - true - Base definitions for C# smart contracts. + net6.0 + AElf.CSharp.Core + true + Base definitions for C# smart contracts. - + - + \ No newline at end of file diff --git a/src/AElf.CSharp.Core/ContractStubBase.cs b/src/AElf.CSharp.Core/ContractStubBase.cs index f85b19a840..a1684c52f9 100644 --- a/src/AElf.CSharp.Core/ContractStubBase.cs +++ b/src/AElf.CSharp.Core/ContractStubBase.cs @@ -1,10 +1,9 @@ using System.Diagnostics.CodeAnalysis; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public class ContractStubBase { - public class ContractStubBase - { - [SuppressMessage("ReSharper", "InconsistentNaming")] - public IMethodStubFactory __factory { get; set; } - } + [SuppressMessage("ReSharper", "InconsistentNaming")] + public IMethodStubFactory __factory { get; set; } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Extension/EventExtensions.cs b/src/AElf.CSharp.Core/Extension/EventExtensions.cs index 19dbb23f29..7c60313464 100644 --- a/src/AElf.CSharp.Core/Extension/EventExtensions.cs +++ b/src/AElf.CSharp.Core/Extension/EventExtensions.cs @@ -1,41 +1,34 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.CSharp.Core.Extension +namespace AElf.CSharp.Core.Extension; + +public static class EventExtensions { - public static class EventExtensions + public static LogEvent ToLogEvent(this T eventData, Address self = null) where T : IEvent { - public static LogEvent ToLogEvent(this T eventData, Address self = null) where T : IEvent + var logEvent = new LogEvent { - var logEvent = new LogEvent - { - Address = self, - Name = eventData.Descriptor.Name - }; - - foreach (var indexed in eventData.GetIndexed()) - { - var byteString = indexed.ToByteString(); - if (byteString.Length == 0) - { - continue; - } + Address = self, + Name = eventData.Descriptor.Name + }; - logEvent.Indexed.Add(byteString); - } + foreach (var indexed in eventData.GetIndexed()) + { + var byteString = indexed.ToByteString(); + if (byteString.Length == 0) continue; - logEvent.NonIndexed = eventData.GetNonIndexed().ToByteString(); - return logEvent; + logEvent.Indexed.Add(byteString); } - public static void MergeFrom(this T eventData, LogEvent log) where T : IEvent - { - foreach (var bs in log.Indexed) - { - eventData.MergeFrom(bs); - } + logEvent.NonIndexed = eventData.GetNonIndexed().ToByteString(); + return logEvent; + } - eventData.MergeFrom(log.NonIndexed); - } + public static void MergeFrom(this T eventData, LogEvent log) where T : IEvent + { + foreach (var bs in log.Indexed) eventData.MergeFrom(bs); + + eventData.MergeFrom(log.NonIndexed); } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Extension/TimestampExtensions.cs b/src/AElf.CSharp.Core/Extension/TimestampExtensions.cs index 873dd23640..e2fc52a6a4 100644 --- a/src/AElf.CSharp.Core/Extension/TimestampExtensions.cs +++ b/src/AElf.CSharp.Core/Extension/TimestampExtensions.cs @@ -1,89 +1,88 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.CSharp.Core.Extension +namespace AElf.CSharp.Core.Extension; + +/// +/// Helper methods for dealing with protobuf timestamps. +/// +public static class TimestampExtensions { /// - /// Helper methods for dealing with protobuf timestamps. + /// Adds a given amount of milliseconds to a timestamp. Returns a new instance. /// - public static class TimestampExtensions + /// the timestamp. + /// the amount of milliseconds to add. + /// a new timestamp instance. + public static Timestamp AddMilliseconds(this Timestamp timestamp, long milliseconds) { - /// - /// Adds a given amount of milliseconds to a timestamp. Returns a new instance. - /// - /// the timestamp. - /// the amount of milliseconds to add. - /// a new timestamp instance. - public static Timestamp AddMilliseconds(this Timestamp timestamp, long milliseconds) - { - return timestamp + new Duration - {Seconds = milliseconds / 1000, Nanos = (int) (milliseconds % 1000).Mul(1000000)}; - } + return timestamp + new Duration + { Seconds = milliseconds / 1000, Nanos = (int)(milliseconds % 1000).Mul(1000000) }; + } - /// - /// Adds a given amount of seconds to a timestamp. Returns a new instance. - /// - /// the timestamp. - /// the amount of seconds. - /// a new timestamp instance. - public static Timestamp AddSeconds(this Timestamp timestamp, long seconds) - { - return timestamp + new Duration {Seconds = seconds}; - } + /// + /// Adds a given amount of seconds to a timestamp. Returns a new instance. + /// + /// the timestamp. + /// the amount of seconds. + /// a new timestamp instance. + public static Timestamp AddSeconds(this Timestamp timestamp, long seconds) + { + return timestamp + new Duration { Seconds = seconds }; + } - /// - /// Adds a given amount of minutes to a timestamp. Returns a new instance. - /// - /// the timestamp. - /// the amount of minutes. - /// a new timestamp instance. - public static Timestamp AddMinutes(this Timestamp timestamp, long minutes) - { - return timestamp + new Duration {Seconds = minutes.Mul(60)}; - } + /// + /// Adds a given amount of minutes to a timestamp. Returns a new instance. + /// + /// the timestamp. + /// the amount of minutes. + /// a new timestamp instance. + public static Timestamp AddMinutes(this Timestamp timestamp, long minutes) + { + return timestamp + new Duration { Seconds = minutes.Mul(60) }; + } - /// - /// Adds a given amount of hours to a timestamp. Returns a new instance. - /// - /// the timestamp. - /// the amount of hours. - /// a new timestamp instance. - public static Timestamp AddHours(this Timestamp timestamp, long hours) - { - return timestamp + new Duration {Seconds = hours.Mul(60 * 60)}; - } + /// + /// Adds a given amount of hours to a timestamp. Returns a new instance. + /// + /// the timestamp. + /// the amount of hours. + /// a new timestamp instance. + public static Timestamp AddHours(this Timestamp timestamp, long hours) + { + return timestamp + new Duration { Seconds = hours.Mul(60 * 60) }; + } - /// - /// Adds a given amount of days to a timestamp. Returns a new instance. - /// - /// the timestamp. - /// the amount of days. - /// a new timestamp instance. - public static Timestamp AddDays(this Timestamp timestamp, long days) - { - return timestamp + new Duration {Seconds = days.Mul(24 * 60 * 60)}; - } + /// + /// Adds a given amount of days to a timestamp. Returns a new instance. + /// + /// the timestamp. + /// the amount of days. + /// a new timestamp instance. + public static Timestamp AddDays(this Timestamp timestamp, long days) + { + return timestamp + new Duration { Seconds = days.Mul(24 * 60 * 60) }; + } - /// - /// Converts a protobuf duration to long. - /// - /// the duration to convert. - /// the duration represented with a long. - public static long Milliseconds(this Duration duration) - { - return duration.Seconds > long.MaxValue.Div(1000) - ? long.MaxValue - : duration.Seconds.Mul(1000).Add(duration.Nanos.Div(1000000)); - } + /// + /// Converts a protobuf duration to long. + /// + /// the duration to convert. + /// the duration represented with a long. + public static long Milliseconds(this Duration duration) + { + return duration.Seconds > long.MaxValue.Div(1000) + ? long.MaxValue + : duration.Seconds.Mul(1000).Add(duration.Nanos.Div(1000000)); + } - /// - /// Compares two timestamps and returns the greater one. - /// - /// the first timestamp - /// the second timestamp - /// the greater timestamp. - public static Timestamp Max(Timestamp timestamp1, Timestamp timestamp2) - { - return timestamp1 > timestamp2 ? timestamp1 : timestamp2; - } + /// + /// Compares two timestamps and returns the greater one. + /// + /// the first timestamp + /// the second timestamp + /// the greater timestamp. + public static Timestamp Max(Timestamp timestamp1, Timestamp timestamp2) + { + return timestamp1 > timestamp2 ? timestamp1 : timestamp2; } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/IEvent.cs b/src/AElf.CSharp.Core/IEvent.cs index def2203232..caf88fce5a 100644 --- a/src/AElf.CSharp.Core/IEvent.cs +++ b/src/AElf.CSharp.Core/IEvent.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using Google.Protobuf; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public interface IEvent : IMessage where T : IEvent { - public interface IEvent : IMessage where T : IEvent - { - IEnumerable GetIndexed(); - T GetNonIndexed(); - } + IEnumerable GetIndexed(); + T GetNonIndexed(); } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/IMethodStubFactory.cs b/src/AElf.CSharp.Core/IMethodStubFactory.cs index e8284d71f3..da04bbcb30 100644 --- a/src/AElf.CSharp.Core/IMethodStubFactory.cs +++ b/src/AElf.CSharp.Core/IMethodStubFactory.cs @@ -4,67 +4,66 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public interface IExecutionTask { - public interface IExecutionTask - { - Transaction Transaction { get; } - TransactionResult TransactionResult { get; } - } + Transaction Transaction { get; } + TransactionResult TransactionResult { get; } +} - public interface IExecutionResult : IExecutionTask where TOutput : IMessage - { - TOutput Output { get; } - } +public interface IExecutionResult : IExecutionTask where TOutput : IMessage +{ + TOutput Output { get; } +} - public class ExecutionTask : IExecutionTask - { - public Transaction Transaction { get; set; } - public TransactionResult TransactionResult { get; set; } - } +public class ExecutionTask : IExecutionTask +{ + public Transaction Transaction { get; set; } + public TransactionResult TransactionResult { get; set; } +} - public class ExecutionResult : ExecutionTask, IExecutionResult where TOutput : IMessage - { - public TOutput Output { get; set; } - } +public class ExecutionResult : ExecutionTask, IExecutionResult where TOutput : IMessage +{ + public TOutput Output { get; set; } +} - public interface IMethodStub where TInput : IMessage where TOutput : IMessage - { - Method Method { get; } - Func>> SendAsync { get; } - Func>> SendWithExceptionAsync { get; } - Func> CallAsync { get; } - Func> CallWithExceptionAsync { get; } - Func GetTransaction { get; } - } +public interface IMethodStub where TInput : IMessage where TOutput : IMessage +{ + Method Method { get; } + Func>> SendAsync { get; } + Func>> SendWithExceptionAsync { get; } + Func> CallAsync { get; } + Func> CallWithExceptionAsync { get; } + Func GetTransaction { get; } +} - public sealed class MethodStub : IMethodStub where TInput : IMessage - where TOutput : IMessage +public sealed class MethodStub : IMethodStub where TInput : IMessage + where TOutput : IMessage +{ + public MethodStub(Method method, Func>> sendAsync, + Func> callAsync, Func getTransaction = null, + Func>> sendWithExceptionAsync = null, + Func> callWithExceptionAsync = null) { - public Method Method { get; } - public Func>> SendAsync { get; } - public Func>> SendWithExceptionAsync { get; } - public Func> CallAsync { get; } - public Func> CallWithExceptionAsync { get; } - public Func GetTransaction { get; } - - public MethodStub(Method method, Func>> sendAsync, - Func> callAsync, Func getTransaction = null, - Func>> sendWithExceptionAsync = null, - Func> callWithExceptionAsync = null) - { - Method = method; - SendAsync = sendAsync; - CallAsync = callAsync; - GetTransaction = getTransaction; - SendWithExceptionAsync = sendWithExceptionAsync; - CallWithExceptionAsync = callWithExceptionAsync; - } + Method = method; + SendAsync = sendAsync; + CallAsync = callAsync; + GetTransaction = getTransaction; + SendWithExceptionAsync = sendWithExceptionAsync; + CallWithExceptionAsync = callWithExceptionAsync; } - public interface IMethodStubFactory - { - IMethodStub Create(Method method) - where TInput : IMessage, new() where TOutput : IMessage, new(); - } + public Method Method { get; } + public Func>> SendAsync { get; } + public Func>> SendWithExceptionAsync { get; } + public Func> CallAsync { get; } + public Func> CallWithExceptionAsync { get; } + public Func GetTransaction { get; } +} + +public interface IMethodStubFactory +{ + IMethodStub Create(Method method) + where TInput : IMessage, new() where TOutput : IMessage, new(); } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Marshaller.cs b/src/AElf.CSharp.Core/Marshaller.cs index 03e43a9206..339729dcd0 100644 --- a/src/AElf.CSharp.Core/Marshaller.cs +++ b/src/AElf.CSharp.Core/Marshaller.cs @@ -17,62 +17,55 @@ #endregion using System; +using System.Text; using AElf.CSharp.Core.Utils; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +/// +/// Encapsulates the logic for serializing and deserializing messages. +/// +public class Marshaller { /// - /// Encapsulates the logic for serializing and deserializing messages. + /// Initializes a new marshaller from simple serialize/deserialize functions. /// - public class Marshaller + /// Function that will be used to serialize messages. + /// Function that will be used to deserialize messages. + public Marshaller(Func serializer, Func deserializer) { - readonly Func serializer; - readonly Func deserializer; - /// - /// Initializes a new marshaller from simple serialize/deserialize functions. - /// - /// Function that will be used to serialize messages. - /// Function that will be used to deserialize messages. - public Marshaller(Func serializer, Func deserializer) - { - this.serializer = Preconditions.CheckNotNull(serializer, nameof(serializer)); - this.deserializer = Preconditions.CheckNotNull(deserializer, nameof(deserializer)); - } + this.Serializer = Preconditions.CheckNotNull(serializer, nameof(serializer)); + this.Deserializer = Preconditions.CheckNotNull(deserializer, nameof(deserializer)); + } - /// - /// Gets the serializer function. - /// - public Func Serializer => this.serializer; + /// + /// Gets the serializer function. + /// + public Func Serializer { get; } - /// - /// Gets the deserializer function. - /// - public Func Deserializer => this.deserializer; - } + /// + /// Gets the deserializer function. + /// + public Func Deserializer { get; } +} +/// +/// Utilities for creating marshallers. +/// +public static class Marshallers +{ /// - /// Utilities for creating marshallers. + /// Returns a marshaller for string type. This is useful for testing. /// - public static class Marshallers - { - /// - /// Creates a marshaller from specified serializer and deserializer. - /// - public static Marshaller Create(Func serializer, Func deserializer) - { - return new Marshaller(serializer, deserializer); - } + public static Marshaller StringMarshaller => + new Marshaller(Encoding.UTF8.GetBytes, + Encoding.UTF8.GetString); - /// - /// Returns a marshaller for string type. This is useful for testing. - /// - public static Marshaller StringMarshaller - { - get - { - return new Marshaller(System.Text.Encoding.UTF8.GetBytes, - System.Text.Encoding.UTF8.GetString); - } - } + /// + /// Creates a marshaller from specified serializer and deserializer. + /// + public static Marshaller Create(Func serializer, Func deserializer) + { + return new Marshaller(serializer, deserializer); } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Method.cs b/src/AElf.CSharp.Core/Method.cs index 5ca58424e4..f5bc30b9ad 100644 --- a/src/AElf.CSharp.Core/Method.cs +++ b/src/AElf.CSharp.Core/Method.cs @@ -18,148 +18,106 @@ using AElf.CSharp.Core.Utils; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public enum MethodType { - public enum MethodType - { - /// The method modifies the contrac state. - Action, - /// The method doesn't modify the contract state. - View - } + /// The method modifies the contrac state. + Action, + + /// The method doesn't modify the contract state. + View +} + +/// +/// A non-generic representation of a remote method. +/// +public interface IMethod +{ + /// + /// Gets the type of the method. + /// + MethodType Type { get; } + + /// + /// Gets the name of the service to which this method belongs. + /// + string ServiceName { get; } + + /// + /// Gets the unqualified name of the method. + /// + string Name { get; } /// - /// A non-generic representation of a remote method. + /// Gets the fully qualified name of the method. On the server side, methods are dispatched + /// based on this name. + /// + string FullName { get; } +} + +/// +/// A description of a remote method. +/// +/// Request message type for this method. +/// Response message type for this method. +public class Method : IMethod +{ + /// + /// Initializes a new instance of the Method class. /// - public interface IMethod + /// Type of method. + /// Name of service this method belongs to. + /// Unqualified name of the method. + /// Marshaller used for request messages. + /// Marshaller used for response messages. + public Method(MethodType type, string serviceName, string name, Marshaller requestMarshaller, + Marshaller responseMarshaller) { - /// - /// Gets the type of the method. - /// - MethodType Type { get; } - - /// - /// Gets the name of the service to which this method belongs. - /// - string ServiceName { get; } - - /// - /// Gets the unqualified name of the method. - /// - string Name { get; } - - /// - /// Gets the fully qualified name of the method. On the server side, methods are dispatched - /// based on this name. - /// - string FullName { get; } + this.Type = type; + this.ServiceName = Preconditions.CheckNotNull(serviceName, "serviceName"); + this.Name = Preconditions.CheckNotNull(name, "name"); + this.RequestMarshaller = Preconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); + this.ResponseMarshaller = Preconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); + FullName = GetFullName(serviceName, name); } /// - /// A description of a remote method. + /// Gets the marshaller used for request messages. /// - /// Request message type for this method. - /// Response message type for this method. - public class Method : IMethod + public Marshaller RequestMarshaller { get; } + + /// + /// Gets the marshaller used for response messages. + /// + public Marshaller ResponseMarshaller { get; } + + /// + /// Gets the type of the method. + /// + public MethodType Type { get; } + + /// + /// Gets the name of the service to which this method belongs. + /// + public string ServiceName { get; } + + /// + /// Gets the unqualified name of the method. + /// + public string Name { get; } + + /// + /// Gets the fully qualified name of the method. On the server side, methods are dispatched + /// based on this name. + /// + public string FullName { get; } + + /// + /// Gets full name of the method including the service name. + /// + internal static string GetFullName(string serviceName, string methodName) { - readonly MethodType type; - readonly string serviceName; - readonly string name; - readonly Marshaller requestMarshaller; - readonly Marshaller responseMarshaller; - readonly string fullName; - - /// - /// Initializes a new instance of the Method class. - /// - /// Type of method. - /// Name of service this method belongs to. - /// Unqualified name of the method. - /// Marshaller used for request messages. - /// Marshaller used for response messages. - public Method(MethodType type, string serviceName, string name, Marshaller requestMarshaller, Marshaller responseMarshaller) - { - this.type = type; - this.serviceName = Preconditions.CheckNotNull(serviceName, "serviceName"); - this.name = Preconditions.CheckNotNull(name, "name"); - this.requestMarshaller = Preconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); - this.responseMarshaller = Preconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); - this.fullName = GetFullName(serviceName, name); - } - - /// - /// Gets the type of the method. - /// - public MethodType Type - { - get - { - return this.type; - } - } - - /// - /// Gets the name of the service to which this method belongs. - /// - public string ServiceName - { - get - { - return this.serviceName; - } - } - - /// - /// Gets the unqualified name of the method. - /// - public string Name - { - get - { - return this.name; - } - } - - /// - /// Gets the marshaller used for request messages. - /// - public Marshaller RequestMarshaller - { - get - { - return this.requestMarshaller; - } - } - - /// - /// Gets the marshaller used for response messages. - /// - public Marshaller ResponseMarshaller - { - get - { - return this.responseMarshaller; - } - } - - /// - /// Gets the fully qualified name of the method. On the server side, methods are dispatched - /// based on this name. - /// - public string FullName - { - get - { - return this.fullName; - } - } - - /// - /// Gets full name of the method including the service name. - /// - internal static string GetFullName(string serviceName, string methodName) - { - return "/" + serviceName + "/" + methodName; - } + return "/" + serviceName + "/" + methodName; } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.Core/SafeMath.cs b/src/AElf.CSharp.Core/SafeMath.cs index 073fd46983..ce68fcb480 100644 --- a/src/AElf.CSharp.Core/SafeMath.cs +++ b/src/AElf.CSharp.Core/SafeMath.cs @@ -1,296 +1,282 @@ -using System; -using System.Numerics; +using System.Numerics; using AElf.Types; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +/// +/// Helper methods for safe math operations that explicitly check for overflow. +/// +public static class SafeMath { - /// - /// Helper methods for safe math operations that explicitly check for overflow. - /// - public static class SafeMath - { - #region int + #region int - public static int Mul(this int a, int b) + public static int Mul(this int a, int b) + { + checked { - checked - { - return a * b; - } + return a * b; } + } - public static int Div(this int a, int b) - { - checked - { - return a / b; - } - } + public static int Div(this int a, int b) + { + return a / b; + } - public static int Sub(this int a, int b) + public static int Sub(this int a, int b) + { + checked { - checked - { - return a - b; - } + return a - b; } + } - public static int Add(this int a, int b) + public static int Add(this int a, int b) + { + checked { - checked - { - return a + b; - } + return a + b; } + } - #endregion int + #endregion int - #region uint + #region uint - public static uint Mul(this uint a, uint b) + public static uint Mul(this uint a, uint b) + { + checked { - checked - { - return a * b; - } + return a * b; } + } - public static uint Div(this uint a, uint b) - { - checked - { - return a / b; - } - } + public static uint Div(this uint a, uint b) + { + return a / b; + } - public static uint Sub(this uint a, uint b) + public static uint Sub(this uint a, uint b) + { + checked { - checked - { - return a - b; - } + return a - b; } + } - public static uint Add(this uint a, uint b) + public static uint Add(this uint a, uint b) + { + checked { - checked - { - return a + b; - } + return a + b; } + } - #endregion uint + #endregion uint - #region long + #region long - public static long Mul(this long a, long b) + public static long Mul(this long a, long b) + { + checked { - checked - { - return a * b; - } + return a * b; } + } - public static long Div(this long a, long b) - { - checked - { - return a / b; - } - } + public static long Div(this long a, long b) + { + return a / b; + } - public static long Sub(this long a, long b) + public static long Sub(this long a, long b) + { + checked { - checked - { - return a - b; - } + return a - b; } + } - public static long Add(this long a, long b) + public static long Add(this long a, long b) + { + checked { - checked - { - return a + b; - } + return a + b; } + } - #endregion long + #endregion long - #region ulong + #region ulong - public static ulong Mul(this ulong a, ulong b) + public static ulong Mul(this ulong a, ulong b) + { + checked { - checked - { - return a * b; - } + return a * b; } + } - public static ulong Div(this ulong a, ulong b) - { - checked - { - return a / b; - } - } + public static ulong Div(this ulong a, ulong b) + { + return a / b; + } - public static ulong Sub(this ulong a, ulong b) + public static ulong Sub(this ulong a, ulong b) + { + checked { - checked - { - return a - b; - } + return a - b; } + } - public static ulong Add(this ulong a, ulong b) + public static ulong Add(this ulong a, ulong b) + { + checked { - checked - { - return a + b; - } + return a + b; } + } - #endregion ulong + #endregion ulong - #region BigIntValue + #region BigIntValue - public static BigIntValue Mul(this BigIntValue a, BigIntValue b) + public static BigIntValue Mul(this BigIntValue a, BigIntValue b) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Multiply(a, b).ToString() - }; - } + Value = BigInteger.Multiply(a, b).ToString() + }; + } - public static BigIntValue Div(this BigIntValue a, BigIntValue b) + public static BigIntValue Div(this BigIntValue a, BigIntValue b) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Divide(a, b).ToString() - }; - } + Value = BigInteger.Divide(a, b).ToString() + }; + } - public static BigIntValue Sub(this BigIntValue a, BigIntValue b) + public static BigIntValue Sub(this BigIntValue a, BigIntValue b) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Subtract(a, b).ToString() - }; - } + Value = BigInteger.Subtract(a, b).ToString() + }; + } - public static BigIntValue Add(this BigIntValue a, BigIntValue b) + public static BigIntValue Add(this BigIntValue a, BigIntValue b) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Add(a, b).ToString() - }; - } + Value = BigInteger.Add(a, b).ToString() + }; + } - public static BigIntValue Pow(this BigIntValue a, int exponent) + public static BigIntValue Pow(this BigIntValue a, int exponent) + { + BigInteger bigInt = a; + return new BigIntValue { - BigInteger bigInt = a; - return new BigIntValue - { - Value = BigInteger.Pow(bigInt, exponent).ToString() - }; - } + Value = BigInteger.Pow(bigInt, exponent).ToString() + }; + } - public static BigIntValue Or(this BigIntValue a, BigIntValue b) + public static BigIntValue Or(this BigIntValue a, BigIntValue b) + { + BigInteger aBigInt = a; + BigInteger bBigInt = b; + return new BigIntValue { - BigInteger aBigInt = a; - BigInteger bBigInt = b; - return new BigIntValue - { - Value = (aBigInt | bBigInt).ToString() - }; - } + Value = (aBigInt | bBigInt).ToString() + }; + } - public static BigIntValue Xor(this BigIntValue a, BigIntValue b) + public static BigIntValue Xor(this BigIntValue a, BigIntValue b) + { + BigInteger aBigInt = a; + BigInteger bBigInt = b; + return new BigIntValue { - BigInteger aBigInt = a; - BigInteger bBigInt = b; - return new BigIntValue - { - Value = (aBigInt ^ bBigInt).ToString() - }; - } + Value = (aBigInt ^ bBigInt).ToString() + }; + } - public static BigIntValue And(this BigIntValue a, BigIntValue b) + public static BigIntValue And(this BigIntValue a, BigIntValue b) + { + BigInteger aBigInt = a; + BigInteger bBigInt = b; + return new BigIntValue { - BigInteger aBigInt = a; - BigInteger bBigInt = b; - return new BigIntValue - { - Value = (aBigInt & bBigInt).ToString() - }; - } + Value = (aBigInt & bBigInt).ToString() + }; + } - public static BigIntValue Not(this BigIntValue a) + public static BigIntValue Not(this BigIntValue a) + { + BigInteger bigInt = a; + return new BigIntValue { - BigInteger bigInt = a; - return new BigIntValue - { - Value = (~bigInt).ToString() - }; - } + Value = (~bigInt).ToString() + }; + } - public static BigIntValue Abs(this BigIntValue a) + public static BigIntValue Abs(this BigIntValue a) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Abs(a).ToString() - }; - } + Value = BigInteger.Abs(a).ToString() + }; + } - public static BigIntValue Negate(this BigIntValue a) + public static BigIntValue Negate(this BigIntValue a) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Negate(a).ToString() - }; - } + Value = BigInteger.Negate(a).ToString() + }; + } - public static BigIntValue Remainder(this BigIntValue dividend, BigIntValue divisor) + public static BigIntValue Remainder(this BigIntValue dividend, BigIntValue divisor) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.Remainder(dividend, divisor).ToString() - }; - } + Value = BigInteger.Remainder(dividend, divisor).ToString() + }; + } - /// - /// Divides one BigIntValue value by another, returns the result, and returns the remainder in an output parameter. - /// - /// - /// - /// - /// - public static BigIntValue DivRem(this BigIntValue dividend, BigIntValue divisor, out BigIntValue remainder) + /// + /// Divides one BigIntValue value by another, returns the result, and returns the remainder in an output parameter. + /// + /// + /// + /// + /// + public static BigIntValue DivRem(this BigIntValue dividend, BigIntValue divisor, out BigIntValue remainder) + { + var result = BigInteger.DivRem(dividend, divisor, out var originRemainder).ToString(); + remainder = new BigIntValue { - var result = BigInteger.DivRem(dividend, divisor, out var originRemainder).ToString(); - remainder = new BigIntValue - { - Value = originRemainder.ToString() - }; - return result; - } + Value = originRemainder.ToString() + }; + return result; + } - /// - /// Performs modulus division on a number raised to the power of another number. - /// - /// - /// - /// - /// - public static BigIntValue ModPow(this BigIntValue value, BigIntValue exponent, BigIntValue modulus) + /// + /// Performs modulus division on a number raised to the power of another number. + /// + /// + /// + /// + /// + public static BigIntValue ModPow(this BigIntValue value, BigIntValue exponent, BigIntValue modulus) + { + return new BigIntValue { - return new BigIntValue - { - Value = BigInteger.ModPow(value, exponent, modulus).ToString() - }; - } - - #endregion + Value = BigInteger.ModPow(value, exponent, modulus).ToString() + }; } + + #endregion } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/ServerMethods.cs b/src/AElf.CSharp.Core/ServerMethods.cs index 1f8ea6d0a5..c2804f785a 100644 --- a/src/AElf.CSharp.Core/ServerMethods.cs +++ b/src/AElf.CSharp.Core/ServerMethods.cs @@ -16,14 +16,13 @@ #endregion -namespace AElf.CSharp.Core -{ - /// - /// Handler for a contract method. - /// - /// Request message type for this method. - /// Response message type for this method. - public delegate TResponse UnaryServerMethod(TRequest request) - where TRequest : class - where TResponse : class; -} +namespace AElf.CSharp.Core; + +/// +/// Handler for a contract method. +/// +/// Request message type for this method. +/// Response message type for this method. +public delegate TResponse UnaryServerMethod(TRequest request) + where TRequest : class + where TResponse : class; \ No newline at end of file diff --git a/src/AElf.CSharp.Core/ServerServiceDefinition.cs b/src/AElf.CSharp.Core/ServerServiceDefinition.cs index 53a1ae59c2..37f1f9d42f 100644 --- a/src/AElf.CSharp.Core/ServerServiceDefinition.cs +++ b/src/AElf.CSharp.Core/ServerServiceDefinition.cs @@ -20,103 +20,97 @@ using System.Collections.Generic; using Google.Protobuf.Reflection; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +/// +/// Stores mapping of methods to server call handlers. +/// Normally, the ServerServiceDefinition objects will be created by the BindService factory method +/// that is part of the autogenerated code for a protocol buffers service definition. +/// +public class ServerServiceDefinition { + private readonly IReadOnlyList> addDescriptorActions; + private readonly IReadOnlyList> addMethodActions; + + internal ServerServiceDefinition(List> addMethodActions, + List> addDescriptorActions) + { + this.addMethodActions = addMethodActions.AsReadOnly(); + this.addDescriptorActions = addDescriptorActions.AsReadOnly(); + } + /// - /// Stores mapping of methods to server call handlers. - /// Normally, the ServerServiceDefinition objects will be created by the BindService factory method - /// that is part of the autogenerated code for a protocol buffers service definition. + /// Forwards all the previously stored AddMethod calls to the service binder. /// - public class ServerServiceDefinition + public void BindService(ServiceBinderBase serviceBinder) { - readonly IReadOnlyList> addMethodActions; - readonly IReadOnlyList> addDescriptorActions; + foreach (var addMethodAction in addMethodActions) addMethodAction(serviceBinder); - internal ServerServiceDefinition(List> addMethodActions, List> addDescriptorActions) - { - this.addMethodActions = addMethodActions.AsReadOnly(); - this.addDescriptorActions = addDescriptorActions.AsReadOnly(); - } + foreach (var addDescriptorAction in addDescriptorActions) addDescriptorAction(serviceBinder); + } + + /// + /// Creates a new builder object for ServerServiceDefinition. + /// + /// The builder object. + public static Builder CreateBuilder() + { + return new Builder(); + } + + /// + /// Builder class for . + /// + public class Builder + { + private readonly List> addDescriptorActions = new(); + + // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase + private readonly List> addMethodActions = new(); + + // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before + private readonly Dictionary duplicateDetector = new(); /// - /// Forwards all the previously stored AddMethod calls to the service binder. + /// Creates a new instance of builder. /// - public void BindService(ServiceBinderBase serviceBinder) + public Builder() { - foreach (var addMethodAction in addMethodActions) - { - addMethodAction(serviceBinder); - } - - foreach (var addDescriptorAction in addDescriptorActions) - { - addDescriptorAction(serviceBinder); - } } /// - /// Creates a new builder object for ServerServiceDefinition. + /// Adds a definition for a single request - single response method. /// - /// The builder object. - public static Builder CreateBuilder() + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + /// This builder instance. + public Builder AddMethod( + Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class + { + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add(serviceBinder => serviceBinder.AddMethod(method, handler)); + return this; + } + + public Builder AddDescriptors(IEnumerable descriptors) { - return new Builder(); + foreach (var descriptor in descriptors) + addDescriptorActions.Add(serviceBinder => serviceBinder.AddDescriptor(descriptor)); + return this; } /// - /// Builder class for . + /// Creates an immutable ServerServiceDefinition from this builder. /// - public class Builder + /// The ServerServiceDefinition object. + public ServerServiceDefinition Build() { - // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before - readonly Dictionary duplicateDetector = new Dictionary(); - // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase - readonly List> addMethodActions = new List>(); - readonly List> addDescriptorActions = new List>(); - - /// - /// Creates a new instance of builder. - /// - public Builder() - { - } - - /// - /// Adds a definition for a single request - single response method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - /// This builder instance. - public Builder AddMethod( - Method method, - UnaryServerMethod handler) - where TRequest : class - where TResponse : class - { - duplicateDetector.Add(method.FullName, null); - addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); - return this; - } - - public Builder AddDescriptors(IEnumerable descriptors) - { - foreach (var descriptor in descriptors) - { - addDescriptorActions.Add((serviceBinder) => serviceBinder.AddDescriptor(descriptor)); - } - return this; - } - - /// - /// Creates an immutable ServerServiceDefinition from this builder. - /// - /// The ServerServiceDefinition object. - public ServerServiceDefinition Build() - { - return new ServerServiceDefinition(addMethodActions, addDescriptorActions); - } + return new ServerServiceDefinition(addMethodActions, addDescriptorActions); } } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.Core/ServiceBinderBase.cs b/src/AElf.CSharp.Core/ServiceBinderBase.cs index 5fcf1ad955..4697b148a9 100644 --- a/src/AElf.CSharp.Core/ServiceBinderBase.cs +++ b/src/AElf.CSharp.Core/ServiceBinderBase.cs @@ -19,34 +19,33 @@ using System; using Google.Protobuf.Reflection; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +/// +/// Allows binding server-side method implementations in alternative serving stacks. +/// Instances of this class are usually populated by the BindService method +/// that is part of the autogenerated code for a protocol buffers service definition. +/// +public class ServiceBinderBase { /// - /// Allows binding server-side method implementations in alternative serving stacks. - /// Instances of this class are usually populated by the BindService method - /// that is part of the autogenerated code for a protocol buffers service definition. + /// Adds a definition for a single request - single response method. /// - public class ServiceBinderBase + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class { - /// - /// Adds a definition for a single request - single response method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - public virtual void AddMethod( - Method method, - UnaryServerMethod handler) - where TRequest : class - where TResponse : class - { - throw new NotImplementedException(); - } + throw new NotImplementedException(); + } - public virtual void AddDescriptor(ServiceDescriptor descriptor) - { - throw new NotImplementedException(); - } + public virtual void AddDescriptor(ServiceDescriptor descriptor) + { + throw new NotImplementedException(); } -} +} \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Utils/EncodingHelper.cs b/src/AElf.CSharp.Core/Utils/EncodingHelper.cs index a0e0ab871b..d645006842 100644 --- a/src/AElf.CSharp.Core/Utils/EncodingHelper.cs +++ b/src/AElf.CSharp.Core/Utils/EncodingHelper.cs @@ -1,20 +1,19 @@ using System.Text; -namespace AElf.CSharp.Core.Utils +namespace AElf.CSharp.Core.Utils; + +/// +/// Helper class for serializing strings. +/// +public class EncodingHelper { /// - /// Helper class for serializing strings. + /// Serializes a UTF-8 string to a byte array. /// - public class EncodingHelper + /// the string to serialize. + /// the serialized string. + public static byte[] EncodeUtf8(string str) { - /// - /// Serializes a UTF-8 string to a byte array. - /// - /// the string to serialize. - /// the serialized string. - public static byte[] EncodeUtf8(string str) - { - return Encoding.UTF8.GetBytes(str); - } + return Encoding.UTF8.GetBytes(str); } } \ No newline at end of file diff --git a/src/AElf.CSharp.Core/Utils/Preconditions.cs b/src/AElf.CSharp.Core/Utils/Preconditions.cs index 970162625e..2fa518de73 100644 --- a/src/AElf.CSharp.Core/Utils/Preconditions.cs +++ b/src/AElf.CSharp.Core/Utils/Preconditions.cs @@ -18,35 +18,28 @@ using System; -namespace AElf.CSharp.Core.Utils +namespace AElf.CSharp.Core.Utils; + +public class Preconditions { - public class Preconditions + /// + /// Throws if reference is null. + /// + /// The reference. + public static T CheckNotNull(T reference) { - /// - /// Throws if reference is null. - /// - /// The reference. - public static T CheckNotNull(T reference) - { - if (reference == null) - { - throw new ArgumentNullException(); - } - return reference; - } + if (reference == null) throw new ArgumentNullException(); + return reference; + } - /// - /// Throws if reference is null. - /// - /// The reference. - /// The parameter name. - public static T CheckNotNull(T reference, string paramName) - { - if (reference == null) - { - throw new ArgumentNullException(paramName); - } - return reference; - } + /// + /// Throws if reference is null. + /// + /// The reference. + /// The parameter name. + public static T CheckNotNull(T reference, string paramName) + { + if (reference == null) throw new ArgumentNullException(paramName); + return reference; } } \ No newline at end of file diff --git a/src/AElf.Cluster/AElf.Cluster.csproj b/src/AElf.Cluster/AElf.Cluster.csproj index 8d25172e5a..28d99c4579 100644 --- a/src/AElf.Cluster/AElf.Cluster.csproj +++ b/src/AElf.Cluster/AElf.Cluster.csproj @@ -5,14 +5,14 @@ - + - - - + + + diff --git a/src/AElf.Cluster/Application/BlockchainNodeHostingService.cs b/src/AElf.Cluster/Application/BlockchainNodeHostingService.cs index e156281b97..485b1906e1 100644 --- a/src/AElf.Cluster/Application/BlockchainNodeHostingService.cs +++ b/src/AElf.Cluster/Application/BlockchainNodeHostingService.cs @@ -6,32 +6,31 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Cluster.Application +namespace AElf.Cluster.Application; + +public class BlockchainApplicationStartDto { - public class BlockchainApplicationStartDto - { - public int ChainId { get; set; } - } + public int ChainId { get; set; } +} - public class BlockchainApplicationHostingService +public class BlockchainApplicationHostingService +{ + public async Task StartAsync(BlockchainApplicationStartDto blockchainApplicationStartDto) { - public async Task StartAsync(BlockchainApplicationStartDto blockchainApplicationStartDto) - { - var builder = new WebHostBuilder() - .ConfigureAppConfiguration(config => { config.AddJsonFile("appsettings.json"); }) - .UseKestrel((builderContext, options) => - { - options.Configure(builderContext.Configuration.GetSection("Kestrel")); - }) - .ConfigureLogging(logger => { }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseStartup>() - .ConfigureServices(services => - { - services.Configure(o => - o.ChainId = blockchainApplicationStartDto.ChainId); - }); - await builder.Build().RunAsync(); - } + var builder = new WebHostBuilder() + .ConfigureAppConfiguration(config => { config.AddJsonFile("appsettings.json"); }) + .UseKestrel((builderContext, options) => + { + options.Configure(builderContext.Configuration.GetSection("Kestrel")); + }) + .ConfigureLogging(logger => { }) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup>() + .ConfigureServices(services => + { + services.Configure(o => + o.ChainId = blockchainApplicationStartDto.ChainId); + }); + await builder.Build().RunAsync(); } } \ No newline at end of file diff --git a/src/AElf.Cluster/Application/Startup.cs b/src/AElf.Cluster/Application/Startup.cs index 2febacc171..1f1d293f47 100644 --- a/src/AElf.Cluster/Application/Startup.cs +++ b/src/AElf.Cluster/Application/Startup.cs @@ -5,30 +5,29 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Cluster.Application +namespace AElf.Cluster.Application; + +public class MainBlockchainStartup where T : AbpModule { - public class MainBlockchainStartup where T: AbpModule + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public IServiceProvider ConfigureServices(IServiceCollection services) { - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public IServiceProvider ConfigureServices(IServiceCollection services) - { - services.AddApplication(options => { options.UseAutofac(); }); + services.AddApplication(options => { options.UseAutofac(); }); - return services.BuildAutofacServiceProvider(); - } + return services.BuildAutofacServiceProvider(); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseCors(builder => builder - .AllowAnyOrigin() - .AllowAnyHeader() - .AllowAnyMethod() - .AllowCredentials() - ); + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseCors(builder => builder + .AllowAnyOrigin() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials() + ); - app.InitializeApplication(); - } + app.InitializeApplication(); } } \ No newline at end of file diff --git a/src/AElf.Cluster/ClusterAElfModule.cs b/src/AElf.Cluster/ClusterAElfModule.cs index f0cb0b60a3..a09d10d573 100644 --- a/src/AElf.Cluster/ClusterAElfModule.cs +++ b/src/AElf.Cluster/ClusterAElfModule.cs @@ -1,12 +1,9 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Cluster +namespace AElf.Cluster; + +[DependsOn] +public class ClusterAElfModule : AElfModule { - [DependsOn( - )] - public class ClusterAElfModule : AElfModule - { - - } } \ No newline at end of file diff --git a/src/AElf.ContractDeployer/AElf.ContractDeployer.csproj b/src/AElf.ContractDeployer/AElf.ContractDeployer.csproj index 0d9556223f..0d99f17fc2 100644 --- a/src/AElf.ContractDeployer/AElf.ContractDeployer.csproj +++ b/src/AElf.ContractDeployer/AElf.ContractDeployer.csproj @@ -1,5 +1,5 @@ - + AElf.ContractDeployer @@ -13,22 +13,22 @@ TRACE;UNIT_TEST - + - - - + + + - + - + - - + + diff --git a/src/AElf.ContractDeployer/ContractDeployerModule.cs b/src/AElf.ContractDeployer/ContractDeployerModule.cs index b6a226fa5d..9cbc4baa33 100644 --- a/src/AElf.ContractDeployer/ContractDeployerModule.cs +++ b/src/AElf.ContractDeployer/ContractDeployerModule.cs @@ -2,11 +2,9 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.ContractDeployer -{ - [DependsOn(typeof(CSharpCodeOpsAElfModule))] - public class ContractDeployerModule : AElfModule +namespace AElf.ContractDeployer; - { - } +[DependsOn(typeof(CSharpCodeOpsAElfModule))] +public class ContractDeployerModule : AElfModule +{ } \ No newline at end of file diff --git a/src/AElf.ContractDeployer/ContractsDeployer.cs b/src/AElf.ContractDeployer/ContractsDeployer.cs index 25454b3f83..6c2aec9dd0 100644 --- a/src/AElf.ContractDeployer/ContractsDeployer.cs +++ b/src/AElf.ContractDeployer/ContractsDeployer.cs @@ -3,44 +3,39 @@ using System.Linq; using System.Reflection; -namespace AElf.ContractDeployer +namespace AElf.ContractDeployer; + +public static class ContractsDeployer { - public static class ContractsDeployer + public static IReadOnlyDictionary GetContractCodes(string contractDir = null, + bool isPatched = false) + { + var contractNames = GetContractNames(typeof(T).Assembly).ToList(); + if (contractNames.Count == 0) throw new NoContractDllFoundInManifestException(); + + return contractNames.Select(n => (n, GetCode(n, contractDir, isPatched))) + .ToDictionary(x => x.Item1, x => x.Item2); + } + + private static byte[] GetCode(string dllName, string contractDir, bool isPatched) { - public static IReadOnlyDictionary GetContractCodes(string contractDir = null, bool isPatched = false) - { - var contractNames = GetContractNames(typeof(T).Assembly).ToList(); - if (contractNames.Count == 0) - { - throw new NoContractDllFoundInManifestException(); - } - - return contractNames.Select(n => (n, GetCode(n, contractDir, isPatched))).ToDictionary(x => x.Item1, x => x.Item2); - } - - private static byte[] GetCode(string dllName, string contractDir, bool isPatched) - { - var dllPath = Directory.Exists(contractDir) - ? Path.Combine(contractDir, isPatched ? $"{dllName}.dll.patched" : $"{dllName}.dll") - : Assembly.Load(dllName).Location; - - return File.ReadAllBytes(dllPath); - } - - private static IEnumerable GetContractNames(Assembly assembly) - { - var manifestName = "Contracts.manifest"; - - var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith(manifestName)); - if (resourceName == default) - { - return new string[0]; - } - - using var stream = assembly.GetManifestResourceStream(resourceName); - using var reader = new StreamReader(stream); - var result = reader.ReadToEnd(); - return result.Trim().Split('\n').Select(f => f.Trim()).ToArray(); - } + var dllPath = Directory.Exists(contractDir) + ? Path.Combine(contractDir, isPatched ? $"{dllName}.dll.patched" : $"{dllName}.dll") + : Assembly.Load(dllName).Location; + + return File.ReadAllBytes(dllPath); + } + + private static IEnumerable GetContractNames(Assembly assembly) + { + var manifestName = "Contracts.manifest"; + + var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith(manifestName)); + if (resourceName == default) return new string[0]; + + using var stream = assembly.GetManifestResourceStream(resourceName); + using var reader = new StreamReader(stream); + var result = reader.ReadToEnd(); + return result.Trim().Split('\n').Select(f => f.Trim()).ToArray(); } } \ No newline at end of file diff --git a/src/AElf.ContractDeployer/NoContractDllFoundInManifestException.cs b/src/AElf.ContractDeployer/NoContractDllFoundInManifestException.cs index 5bcaf14c1e..119aa9f936 100644 --- a/src/AElf.ContractDeployer/NoContractDllFoundInManifestException.cs +++ b/src/AElf.ContractDeployer/NoContractDllFoundInManifestException.cs @@ -1,8 +1,7 @@ using System; -namespace AElf.ContractDeployer +namespace AElf.ContractDeployer; + +public class NoContractDllFoundInManifestException : Exception { - public class NoContractDllFoundInManifestException : Exception - { - } } \ No newline at end of file diff --git a/src/AElf.ContractDeployer/Program.cs b/src/AElf.ContractDeployer/Program.cs index fbcc4d7bf9..f9230328a2 100644 --- a/src/AElf.ContractDeployer/Program.cs +++ b/src/AElf.ContractDeployer/Program.cs @@ -7,81 +7,77 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp; -namespace AElf.ContractDeployer +namespace AElf.ContractDeployer; + +internal class Program { - class Program + private static void Main(string[] args) { - class Options - { - [Option('s', "skipaudit", Default = false, HelpText = "Skip performing code check on contract code.")] - public bool SkipAudit { get; set; } - - [Option('w', "overwrite", Default = false, HelpText = "Overwrite contract's DLL instead of saving with .patched extension.")] - public bool Overwrite { get; set; } - - [Option('t', "treatsystem", Default = false, HelpText = "Treat as system contract when patching.")] - public bool IsSystemContract { get; set; } - - [Option('p', "path", Required = true, HelpText = "The path of the contract's DLL.")] - public string ContractDllPath { get; set; } - } - - static void Main(string[] args) + Parser.Default.ParseArguments(args) + .WithParsed(Run) + .WithNotParsed(Error); + } + + private static void Error(IEnumerable errors) + { + Console.WriteLine("error: Problem parsing input parameters to run contract deployer."); + } + + private static void Run(Options o) + { + string saveAsPath; + + if (!File.Exists(o.ContractDllPath)) { - Parser.Default.ParseArguments(args) - .WithParsed(Run) - .WithNotParsed(Error); + Console.WriteLine($"error: Contract DLL cannot be found in specified path {o.ContractDllPath}"); + return; } - private static void Error(IEnumerable errors) + if (o.Overwrite) { - Console.WriteLine("error: Problem parsing input parameters to run contract deployer."); + saveAsPath = o.ContractDllPath; + Console.WriteLine($"[CONTRACT-PATCHER] Overwriting {saveAsPath}"); } - - private static void Run(Options o) + else { - string saveAsPath; + saveAsPath = o.ContractDllPath + ".patched"; + Console.WriteLine($"[CONTRACT-PATCHER] Saving as {saveAsPath}"); + } - if (!File.Exists(o.ContractDllPath)) - { - Console.WriteLine($"error: Contract DLL cannot be found in specified path {o.ContractDllPath}"); - return; - } + using var application = AbpApplicationFactory.Create(); + application.Initialize(); + var contractPatcher = application.ServiceProvider.GetRequiredService(); + var patchedCode = contractPatcher.Patch(File.ReadAllBytes(o.ContractDllPath), o.IsSystemContract); - if (o.Overwrite) + if (!o.SkipAudit) + try { - saveAsPath = o.ContractDllPath; - Console.WriteLine($"[CONTRACT-PATCHER] Overwriting {saveAsPath}"); + var auditor = application.ServiceProvider.GetRequiredService(); + auditor.Audit(patchedCode, null, o.IsSystemContract); } - else + catch (CSharpCodeCheckException ex) { - saveAsPath = o.ContractDllPath + ".patched"; - Console.WriteLine($"[CONTRACT-PATCHER] Saving as {saveAsPath}"); + foreach (var finding in ex.Findings) + // Print error in parsable format so that it can be shown in IDE + Console.WriteLine($"error: {finding}"); } - - using var application = AbpApplicationFactory.Create(); - application.Initialize(); - var contractPatcher = application.ServiceProvider.GetRequiredService(); - var patchedCode = contractPatcher.Patch(File.ReadAllBytes(o.ContractDllPath), o.IsSystemContract); - if (!o.SkipAudit) - { - try - { - var auditor = application.ServiceProvider.GetRequiredService(); - auditor.Audit(patchedCode, null, o.IsSystemContract); - } - catch (CSharpCodeCheckException ex) - { - foreach (var finding in ex.Findings) - { - // Print error in parsable format so that it can be shown in IDE - Console.WriteLine($"error: {finding.ToString()}"); - } - } - } + File.WriteAllBytes(saveAsPath, patchedCode); + } - File.WriteAllBytes(saveAsPath, patchedCode); - } + private class Options + { + [Option('s', "skipaudit", Default = false, HelpText = "Skip performing code check on contract code.")] + public bool SkipAudit { get; set; } + + [Option('w', "overwrite", Default = false, + HelpText = "Overwrite contract's DLL instead of saving with .patched extension.")] + public bool Overwrite { get; set; } + + [Option('t', "treatsystem", Default = false, HelpText = "Treat as system contract when patching.")] + public bool IsSystemContract { get; set; } + + [Option('p', "path", Required = true, HelpText = "The path of the contract's DLL.")] + public string ContractDllPath { get; set; } } -} +} \ No newline at end of file diff --git a/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj b/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj index adadd27409..40a637defe 100644 --- a/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj +++ b/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.ContractTestBase @@ -8,16 +8,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -25,7 +25,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\aedpos_contract.proto @@ -42,10 +42,10 @@ - - - - - + + + + + diff --git a/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationDto.cs b/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationDto.cs index 6bca7db5dc..3397ef2d2b 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationDto.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationDto.cs @@ -1,7 +1,5 @@ -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class ChainInitializationDto : ChainInitializationOptions { - public class ChainInitializationDto : ChainInitializationOptions - { - - } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationOptions.cs b/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationOptions.cs index 5aea860676..968d91c895 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationOptions.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ChainInitializationOptions.cs @@ -1,14 +1,13 @@ using AElf.Types; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class ChainInitializationOptions { - public class ChainInitializationOptions - { - public int ChainId { get; set; } - public string Symbol { get; set; } - public Address ParentChainTokenContractAddress { get; set; } - public int ParentChainId { get; set; } - public long CreationHeightOnParentChain { get; set; } - public bool RegisterParentChainTokenContractAddress { get; set; } = true; - } + public int ChainId { get; set; } + public string Symbol { get; set; } + public Address ParentChainTokenContractAddress { get; set; } + public int ParentChainId { get; set; } + public long CreationHeightOnParentChain { get; set; } + public bool RegisterParentChainTokenContractAddress { get; set; } = true; } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs index 3dea9ba980..765afaa90e 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.CrossChain; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; @@ -16,6 +15,7 @@ using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; @@ -25,122 +25,134 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class ContractTestBase : AbpIntegratedTest where TModule : AbpModule { - public class ContractTestBase : AbpIntegratedTest where TModule: AbpModule + private readonly IContractTestKitFactory _contractTestKitFactory; + private readonly IContractTestService _contractTestService; + + + public ContractTestBase() { - protected Account DefaultAccount => Accounts[0]; - protected IReadOnlyList Accounts => SampleAccount.Accounts; - - protected int InitialCoreDataCenterCount => 5; - - protected Dictionary SystemContractAddresses { get; } = new Dictionary(); - - protected Address BasicContractZeroAddress => - SystemContractAddresses[ZeroSmartContractAddressNameProvider.Name]; - protected Address CrossChainContractAddress => - SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; - protected Address TokenContractAddress => SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; - protected Address ParliamentContractAddress => SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; - protected Address ConsensusContractAddress => SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; - protected Address ReferendumContractAddress => SystemContractAddresses[ReferendumSmartContractAddressNameProvider.Name]; - protected Address TreasuryContractAddress => - SystemContractAddresses[TreasurySmartContractAddressNameProvider.Name]; - protected Address AssociationContractAddress => - SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name]; - protected Address TokenConverterContractAddress => - SystemContractAddresses[TokenConverterSmartContractAddressNameProvider.Name]; - - private readonly IContractTestKitFactory _contractTestKitFactory; - private readonly IContractTestService _contractTestService; - public ISmartContractAddressService ContractAddressService => - Application.ServiceProvider.GetRequiredService(); - - - public ContractTestBase() - { - _contractTestKitFactory = Application.ServiceProvider.GetRequiredService(); - _contractTestService = Application.ServiceProvider.GetRequiredService(); + _contractTestKitFactory = Application.ServiceProvider.GetRequiredService(); + _contractTestService = Application.ServiceProvider.GetRequiredService(); - AsyncHelper.RunSync(InitSystemContractAddressesAsync); - } - - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } - - private async Task InitSystemContractAddressesAsync() + AsyncHelper.RunSync(InitSystemContractAddressesAsync); + } + + protected Account DefaultAccount => Accounts[0]; + protected IReadOnlyList Accounts => SampleAccount.Accounts; + + protected int InitialCoreDataCenterCount => 5; + + protected Dictionary SystemContractAddresses { get; } = new(); + + protected Address BasicContractZeroAddress => + SystemContractAddresses[ZeroSmartContractAddressNameProvider.Name]; + + protected Address CrossChainContractAddress => + SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; + + protected Address TokenContractAddress => SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; + + protected Address ParliamentContractAddress => + SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; + + protected Address ConsensusContractAddress => + SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; + + protected Address ReferendumContractAddress => + SystemContractAddresses[ReferendumSmartContractAddressNameProvider.Name]; + + protected Address TreasuryContractAddress => + SystemContractAddresses[TreasurySmartContractAddressNameProvider.Name]; + + protected Address AssociationContractAddress => + SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name]; + + protected Address TokenConverterContractAddress => + SystemContractAddresses[TokenConverterSmartContractAddressNameProvider.Name]; + + public ISmartContractAddressService ContractAddressService => + Application.ServiceProvider.GetRequiredService(); + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + private async Task InitSystemContractAddressesAsync() + { + var blockchainService = Application.ServiceProvider.GetService(); + var chain = await blockchainService.GetChainAsync(); + var block = await blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); + var transactionResultManager = Application.ServiceProvider.GetService(); + var transactionResults = + await transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); + foreach (var transactionResult in transactionResults) { - var blockchainService = Application.ServiceProvider.GetService(); - var chain = await blockchainService.GetChainAsync(); - var block = await blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); - var transactionResultManager = Application.ServiceProvider.GetService(); - var transactionResults = - await transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); - foreach (var transactionResult in transactionResults) + Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); + var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ContractDeployed)).ToList(); + if (!relatedLogs.Any()) break; + foreach (var relatedLog in relatedLogs) { - Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); - var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ContractDeployed)).ToList(); - if (!relatedLogs.Any()) break; - foreach (var relatedLog in relatedLogs) - { - var eventData = new ContractDeployed(); - eventData.MergeFrom(relatedLog); - SystemContractAddresses[eventData.Name] = eventData.Address; - } + var eventData = new ContractDeployed(); + eventData.MergeFrom(relatedLog); + SystemContractAddresses[eventData.Name] = eventData.Address; } } + } - protected ContractTestKit CreateContractTestKit(ChainInitializationDto dto) where T : AbpModule - { - var application = CreateApplication(dto); - return _contractTestKitFactory.Create(application); - } - - protected T GetTester(Address contractAddress, ECKeyPair senderKey = null) where T : ContractStubBase, new() - { - return _contractTestService.GetTester(contractAddress, senderKey ?? DefaultAccount.KeyPair); - } - - /// - /// Mine a block with given normal txs and system txs. - /// Normal txs will use tx pool while system txs not. - /// - /// - /// - /// - protected async Task MineAsync(List txs, Timestamp blockTime = null) - { - return await _contractTestService.MineAsync(txs, blockTime); - } - - protected async Task ExecuteTransactionWithMiningAsync(Transaction transaction, Timestamp blockTime = null) - { - return await _contractTestService.ExecuteTransactionWithMiningAsync(transaction,blockTime); - } - - private IAbpApplication CreateApplication(ChainInitializationDto dto) where T:AbpModule - { - var application = - AbpApplicationFactory.Create(options => + protected ContractTestKit CreateContractTestKit(ChainInitializationDto dto) where T : AbpModule + { + var application = CreateApplication(dto); + return _contractTestKitFactory.Create(application); + } + + protected T GetTester(Address contractAddress, ECKeyPair senderKey = null) where T : ContractStubBase, new() + { + return _contractTestService.GetTester(contractAddress, senderKey ?? DefaultAccount.KeyPair); + } + + /// + /// Mine a block with given normal txs and system txs. + /// Normal txs will use tx pool while system txs not. + /// + /// + /// + /// + protected async Task MineAsync(List txs, Timestamp blockTime = null) + { + return await _contractTestService.MineAsync(txs, blockTime); + } + + protected async Task ExecuteTransactionWithMiningAsync(Transaction transaction, + Timestamp blockTime = null) + { + return await _contractTestService.ExecuteTransactionWithMiningAsync(transaction, blockTime); + } + + private IAbpApplication CreateApplication(ChainInitializationDto dto) where T : AbpModule + { + var application = + AbpApplicationFactory.Create(options => + { + options.UseAutofac(); + options.Services.Configure(o => { o.ChainId = dto.ChainId; }); + + options.Services.Configure(o => { - options.UseAutofac(); - options.Services.Configure(o => { o.ChainId = dto.ChainId; }); - - options.Services.Configure(o => - { - o.Symbol = dto.Symbol; - o.ChainId = dto.ChainId; - o.ParentChainId = dto.ParentChainId; - o.CreationHeightOnParentChain = dto.CreationHeightOnParentChain; - o.ParentChainTokenContractAddress = dto.ParentChainTokenContractAddress; - o.RegisterParentChainTokenContractAddress = dto.RegisterParentChainTokenContractAddress; - }); + o.Symbol = dto.Symbol; + o.ChainId = dto.ChainId; + o.ParentChainId = dto.ParentChainId; + o.CreationHeightOnParentChain = dto.CreationHeightOnParentChain; + o.ParentChainTokenContractAddress = dto.ParentChainTokenContractAddress; + o.RegisterParentChainTokenContractAddress = dto.RegisterParentChainTokenContractAddress; }); + }); - application.Initialize(); - return application; - } + application.Initialize(); + return application; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestConstants.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestConstants.cs index 84ebfa1b63..bf9b76e305 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestConstants.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestConstants.cs @@ -1,7 +1,6 @@ -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public static class ContractTestConstants { - public static class ContractTestConstants - { - public static readonly Account DefaultAccount = SampleAccount.Accounts[0]; - } + public static readonly Account DefaultAccount = SampleAccount.Accounts[0]; } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestKit.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestKit.cs index b34c5464a1..c7e8416141 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestKit.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestKit.cs @@ -1,20 +1,15 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; -using AElf.Kernel; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Miner; -using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContractExecution.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; @@ -23,80 +18,79 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class ContractTestKit where TModule : AbpModule { - public class ContractTestKit where TModule : AbpModule + private readonly IContractTestService _contractTestService; + private IReadOnlyDictionary _codes; + + protected int InitialCoreDataCenterCount = 5; + + public ContractTestKit(IAbpApplication application) { - private IReadOnlyDictionary _codes; + Application = application; + _contractTestService = Application.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(InitSystemContractAddressesAsync); + } - public IReadOnlyDictionary Codes => _codes ??= ContractsDeployer.GetContractCodes(); + public IReadOnlyDictionary Codes => _codes ??= ContractsDeployer.GetContractCodes(); - protected IAbpApplication Application { get; } - - protected IReadOnlyList Accounts => SampleAccount.Accounts; + protected IAbpApplication Application { get; } - public ISmartContractAddressService ContractAddressService => - Application.ServiceProvider.GetRequiredService(); + protected IReadOnlyList Accounts => SampleAccount.Accounts; - public Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - - public Account DefaultAccount => Accounts[0]; + public ISmartContractAddressService ContractAddressService => + Application.ServiceProvider.GetRequiredService(); - protected int InitialCoreDataCenterCount = 5; + public Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - public Dictionary SystemContractAddresses { get; } = new Dictionary(); - - private readonly IContractTestService _contractTestService; + public Account DefaultAccount => Accounts[0]; - public ContractTestKit(IAbpApplication application) - { - Application = application; - _contractTestService = Application.ServiceProvider.GetRequiredService(); - AsyncHelper.RunSync(InitSystemContractAddressesAsync); - } - - private async Task InitSystemContractAddressesAsync() + public Dictionary SystemContractAddresses { get; } = new(); + + private async Task InitSystemContractAddressesAsync() + { + var blockchainService = Application.ServiceProvider.GetService(); + var chain = await blockchainService.GetChainAsync(); + var block = await blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); + var transactionResultManager = Application.ServiceProvider.GetService(); + var transactionResults = + await transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); + foreach (var transactionResult in transactionResults) { - var blockchainService = Application.ServiceProvider.GetService(); - var chain = await blockchainService.GetChainAsync(); - var block = await blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); - var transactionResultManager = Application.ServiceProvider.GetService(); - var transactionResults = - await transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash()); - foreach (var transactionResult in transactionResults) + Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); + var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ContractDeployed)).ToList(); + if (!relatedLogs.Any()) break; + foreach (var relatedLog in relatedLogs) { - Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); - var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ContractDeployed)).ToList(); - if (!relatedLogs.Any()) break; - foreach (var relatedLog in relatedLogs) - { - var eventData = new ContractDeployed(); - eventData.MergeFrom(relatedLog); - SystemContractAddresses[eventData.Name] = eventData.Address; - } + var eventData = new ContractDeployed(); + eventData.MergeFrom(relatedLog); + SystemContractAddresses[eventData.Name] = eventData.Address; } } + } - public T GetTester(Address contractAddress, ECKeyPair senderKey = null) where T : ContractStubBase, new() - { - return _contractTestService.GetTester(contractAddress, senderKey ?? DefaultAccount.KeyPair); - } - - /// - /// Mine a block with given normal txs and system txs. - /// Normal txs will use tx pool while system txs not. - /// - /// - /// - /// - public async Task MineAsync(List txs, Timestamp blockTime = null) - { - return await _contractTestService.MineAsync(txs, blockTime); - } - - public async Task ExecuteTransactionWithMiningAsync(Transaction transaction, Timestamp blockTime = null) - { - return await _contractTestService.ExecuteTransactionWithMiningAsync(transaction,blockTime); - } + public T GetTester(Address contractAddress, ECKeyPair senderKey = null) where T : ContractStubBase, new() + { + return _contractTestService.GetTester(contractAddress, senderKey ?? DefaultAccount.KeyPair); + } + + /// + /// Mine a block with given normal txs and system txs. + /// Normal txs will use tx pool while system txs not. + /// + /// + /// + /// + public async Task MineAsync(List txs, Timestamp blockTime = null) + { + return await _contractTestService.MineAsync(txs, blockTime); + } + + public async Task ExecuteTransactionWithMiningAsync(Transaction transaction, + Timestamp blockTime = null) + { + return await _contractTestService.ExecuteTransactionWithMiningAsync(transaction, blockTime); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestKitFactory.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestKitFactory.cs index 7101333c23..a2df60f9f3 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestKitFactory.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestKitFactory.cs @@ -1,18 +1,17 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public interface IContractTestKitFactory { - public interface IContractTestKitFactory - { - ContractTestKit Create(IAbpApplication application) where TModule : AbpModule; - } - - public class ContractTestKitFactory : IContractTestKitFactory + ContractTestKit Create(IAbpApplication application) where TModule : AbpModule; +} + +public class ContractTestKitFactory : IContractTestKitFactory +{ + public ContractTestKit Create(IAbpApplication application) where TModule : AbpModule { - public ContractTestKit Create(IAbpApplication application) where TModule : AbpModule - { - return new ContractTestKit(application); - } + return new ContractTestKit(application); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestModule.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestModule.cs index 7665e4b6ce..4071c41c39 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestModule.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestModule.cs @@ -6,7 +6,6 @@ using AElf.Kernel.Account.Infrastructure; using AElf.Kernel.ChainController; using AElf.Kernel.Consensus.Application; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.Infrastructure; using AElf.Kernel.Node; using AElf.Kernel.SmartContract; @@ -17,7 +16,6 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Kernel.SmartContractExecution; using AElf.Kernel.TransactionPool; -using AElf.Kernel.TransactionPool.Infrastructure; using AElf.OS; using AElf.OS.Network.Application; using AElf.OS.Network.Infrastructure; @@ -36,134 +34,133 @@ using Volo.Abp.Threading; using Xunit.Abstractions; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class ContractTestModule : ContractTestModule + where TSelf : ContractTestModule { - public class ContractTestModule : ContractTestModule - where TSelf : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - base.ConfigureServices(context); - } + context.Services.AddAssemblyOf(); + base.ConfigureServices(context); } +} + +[DependsOn( + typeof(AbpEventBusModule), + typeof(AbpTestBaseModule), + typeof(CoreKernelAElfModule), + typeof(KernelAElfModule), + typeof(NodeAElfModule), + typeof(CoreOSAElfModule), + typeof(SmartContractAElfModule), + typeof(SmartContractExecutionAElfModule), + typeof(TransactionPoolAElfModule), + typeof(ChainControllerAElfModule), + typeof(CSharpRuntimeAElfModule))] +public class ContractTestModule : AbpModule +{ + public int ChainId { get; } = ChainHelper.ConvertBase58ToChainId("AELF"); + public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } - [DependsOn( - typeof(AbpEventBusModule), - typeof(AbpTestBaseModule), - typeof(CoreKernelAElfModule), - typeof(KernelAElfModule), - typeof(NodeAElfModule), - typeof(CoreOSAElfModule), - typeof(SmartContractAElfModule), - typeof(SmartContractExecutionAElfModule), - typeof(TransactionPoolAElfModule), - typeof(ChainControllerAElfModule), - typeof(CSharpRuntimeAElfModule))] - public class ContractTestModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC"; - options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; - }); - - Configure(options => - { - if (options.ChainId == 0) options.ChainId = ChainId; - }); - - #region Infra + Configure(options => + { + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC"; + options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; + }); - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - // services.AddTransient(); - // services.AddSingleton(); - // services.AddSingleton(); + Configure(options => + { + if (options.ChainId == 0) options.ChainId = ChainId; + }); - #endregion + #region Infra - #region Logger + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + // services.AddTransient(); + // services.AddSingleton(); + // services.AddSingleton(); - ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); - services.AddSingleton(testOutputHelperAccessor); - services.AddLogging(o => { o.AddXUnit(testOutputHelperAccessor); }); + #endregion - #endregion + #region Logger - #region Mocks + ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); + services.AddSingleton(testOutputHelperAccessor); + services.AddLogging(o => { o.AddXUnit(testOutputHelperAccessor); }); - services.AddSingleton(o => Mock.Of()); - services.AddSingleton(o => Mock.Of()); + #endregion - services.AddSingleton(o => Mock.Of()); + #region Mocks - context.Services.AddTransient(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); - #endregion + services.AddSingleton(o => Mock.Of()); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddSingleton(); - context.Services.Replace(ServiceDescriptor - .Singleton()); - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new UnitTestCSharpSmartContractRunner( - option.Value.SdkDir); - }); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusRequestMiningEventHandler)); - } + context.Services.AddTransient(o => Mock.Of()); - public int ChainId { get; } = ChainHelper.ConvertBase58ToChainId("AELF"); - public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } + #endregion - public override void OnApplicationInitialization(ApplicationInitializationContext context) + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.Replace(ServiceDescriptor + .Singleton()); + context.Services.AddSingleton(provider => { - context.ServiceProvider.GetService() - .SetKeyPair(SampleAccount.Accounts[0].KeyPair); - - var dto = new OsBlockchainNodeContextStartDto - { - ChainId = context.ServiceProvider.GetService>().Value.ChainId, - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, - }; - var dtoProvider = context.ServiceProvider.GetRequiredService(); - dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); - var contractOptions = context.ServiceProvider.GetService>().Value; - dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); - } - - public override void OnApplicationShutdown(ApplicationShutdownContext context) - { - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); - } + var option = provider.GetService>(); + return new UnitTestCSharpSmartContractRunner( + option.Value.SdkDir); + }); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusRequestMiningEventHandler)); } - [DependsOn(typeof(ContractTestModule), - typeof(ExecutionPluginForResourceFeeModule), - typeof(ExecutionPluginForCallThresholdModule), - typeof(ExecutionPluginForMethodFeeModule))] - public class ContractTestWithExecutionPluginModule : AbpModule + public override void OnApplicationInitialization(ApplicationInitializationContext context) { + context.ServiceProvider.GetService() + .SetKeyPair(SampleAccount.Accounts[0].KeyPair); + + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = context.ServiceProvider.GetService>().Value.ChainId, + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory + }; + var dtoProvider = context.ServiceProvider.GetRequiredService(); + dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); + var contractOptions = context.ServiceProvider.GetService>().Value; + dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); } - public class TestOutputHelperAccessor : ITestOutputHelperAccessor + public override void OnApplicationShutdown(ApplicationShutdownContext context) { - public ITestOutputHelper OutputHelper { get; set; } + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); } +} + +[DependsOn(typeof(ContractTestModule), + typeof(ExecutionPluginForResourceFeeModule), + typeof(ExecutionPluginForCallThresholdModule), + typeof(ExecutionPluginForMethodFeeModule))] +public class ContractTestWithExecutionPluginModule : AbpModule +{ +} + +public class TestOutputHelperAccessor : ITestOutputHelperAccessor +{ + public ITestOutputHelper OutputHelper { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestService.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestService.cs index f491e4ece3..03d1961467 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestService.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestService.cs @@ -12,76 +12,75 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public interface IContractTestService +{ + T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); + Task MineAsync(List txs, Timestamp blockTime = null); + Task ExecuteTransactionWithMiningAsync(Transaction transaction, Timestamp blockTime = null); +} + +public class ContractTestService : IContractTestService { - public interface IContractTestService + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IContractTesterFactory _contractTesterFactory; + private readonly IMiningService _miningService; + + public ContractTestService(IContractTesterFactory contractTesterFactory, IBlockchainService blockchainService, + IMiningService miningService, IBlockAttachService blockAttachService) + { + _contractTesterFactory = contractTesterFactory; + _blockchainService = blockchainService; + _miningService = miningService; + _blockAttachService = blockAttachService; + } + + public T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() { - T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); - Task MineAsync(List txs, Timestamp blockTime = null); - Task ExecuteTransactionWithMiningAsync(Transaction transaction, Timestamp blockTime = null); + return _contractTesterFactory.Create(contractAddress, senderKey); + } + /// + /// Mine a block with given normal txs and system txs. + /// Normal txs will use tx pool while system txs not. + /// + /// + /// + /// + public async Task MineAsync(List txs, Timestamp blockTime = null) + { + var preBlock = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + return await MineAsync(txs, blockTime, preBlock.GetHash(), preBlock.Height); } - - public class ContractTestService : IContractTestService + + public async Task ExecuteTransactionWithMiningAsync(Transaction transaction, + Timestamp blockTime = null) { - private readonly IContractTesterFactory _contractTesterFactory; - private readonly IBlockchainService _blockchainService; - private readonly IMiningService _miningService; - private readonly IBlockAttachService _blockAttachService; + var blockExecutedSet = await MineAsync(new List { transaction }, blockTime); + var result = blockExecutedSet.TransactionResultMap[transaction.GetHash()]; - public ContractTestService(IContractTesterFactory contractTesterFactory, IBlockchainService blockchainService, - IMiningService miningService, IBlockAttachService blockAttachService) - { - _contractTesterFactory = contractTesterFactory; - _blockchainService = blockchainService; - _miningService = miningService; - _blockAttachService = blockAttachService; - } + return result; + } - public T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() - { - return _contractTesterFactory.Create(contractAddress, senderKey); - } - - /// - /// Mine a block with given normal txs and system txs. - /// Normal txs will use tx pool while system txs not. - /// - /// - /// - /// - public async Task MineAsync(List txs, Timestamp blockTime = null) - { - var preBlock = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - return await MineAsync(txs, blockTime, preBlock.GetHash(), preBlock.Height); - } - - public async Task ExecuteTransactionWithMiningAsync(Transaction transaction, Timestamp blockTime = null) - { - var blockExecutedSet = await MineAsync(new List {transaction}, blockTime); - var result = blockExecutedSet.TransactionResultMap[transaction.GetHash()]; + private async Task MineAsync(List txs, Timestamp blockTime, Hash preBlockHash, + long preBlockHeight) + { + var blockExecutedSet = await _miningService.MineAsync( + new RequestMiningDto + { + PreviousBlockHash = preBlockHash, PreviousBlockHeight = preBlockHeight, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, txs, blockTime ?? DateTime.UtcNow.ToTimestamp()); - return result; - } - - private async Task MineAsync(List txs, Timestamp blockTime, Hash preBlockHash, - long preBlockHeight) - { - var blockExecutedSet = await _miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = preBlockHash, PreviousBlockHeight = preBlockHeight, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = Int32.MaxValue - }, txs, blockTime ?? DateTime.UtcNow.ToTimestamp()); - - var block = blockExecutedSet.Block; + var block = blockExecutedSet.Block; - await _blockchainService.AddTransactionsAsync(txs); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + await _blockchainService.AddTransactionsAsync(txs); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); - return blockExecutedSet; - } + return blockExecutedSet; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/IBlockTimeProvider.cs b/src/AElf.ContractTestBase/ContractTestKit/IBlockTimeProvider.cs index 6a4ab61864..30da5bc0d3 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/IBlockTimeProvider.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/IBlockTimeProvider.cs @@ -3,36 +3,36 @@ using AElf.Kernel; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +/// +/// Some contract method's result based on the calling time, +/// like GetConsensusCommand method of consensus contract. +/// +public interface IBlockTimeProvider +{ + Timestamp GetBlockTime(); + void SetBlockTime(Timestamp blockTime); + void SetBlockTime(int offsetMilliseconds); +} + +public class BlockTimeProvider : IBlockTimeProvider { - /// - /// Some contract method's result based on the calling time, - /// like GetConsensusCommand method of consensus contract. - /// - public interface IBlockTimeProvider + private Timestamp _blockTime; + + public Timestamp GetBlockTime() { - Timestamp GetBlockTime(); - void SetBlockTime(Timestamp blockTime); - void SetBlockTime(int offsetMilliseconds); + return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime; } - public class BlockTimeProvider : IBlockTimeProvider + public void SetBlockTime(Timestamp blockTime) { - private Timestamp _blockTime; - public Timestamp GetBlockTime() - { - return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime; - } - - public void SetBlockTime(Timestamp blockTime) - { - Debug.WriteLine($"Update block time: {blockTime}"); - _blockTime = blockTime; - } + Debug.WriteLine($"Update block time: {blockTime}"); + _blockTime = blockTime; + } - public void SetBlockTime(int offsetMilliseconds) - { - SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); - } + public void SetBlockTime(int offsetMilliseconds) + { + SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/IContractTesterFactory.cs b/src/AElf.ContractTestBase/ContractTestKit/IContractTesterFactory.cs index 7a2b4eb51a..34f6478398 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/IContractTesterFactory.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/IContractTesterFactory.cs @@ -4,32 +4,31 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public interface IContractTesterFactory +{ + T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); +} + +public class ContractTesterFactory : IContractTesterFactory, ITransientDependency { - public interface IContractTesterFactory + private readonly IServiceProvider _serviceProvider; + + public ContractTesterFactory(IServiceProvider serviceProvider) { - T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); + _serviceProvider = serviceProvider; } - public class ContractTesterFactory : IContractTesterFactory, ITransientDependency + public T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() { - private readonly IServiceProvider _serviceProvider; - - public ContractTesterFactory(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() + return new T { - return new T + __factory = new MethodStubFactory(_serviceProvider) { - __factory = new MethodStubFactory(_serviceProvider) - { - ContractAddress = contractAddress, - KeyPair = senderKey - } - }; - } + ContractAddress = contractAddress, + KeyPair = senderKey + } + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/IRefBlockInfoProvider.cs b/src/AElf.ContractTestBase/ContractTestKit/IRefBlockInfoProvider.cs index 3346d606c1..a1014f82b2 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/IRefBlockInfoProvider.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/IRefBlockInfoProvider.cs @@ -3,40 +3,39 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public sealed class RefBlockInfo { - public sealed class RefBlockInfo + public RefBlockInfo(long height, ByteString prefix) { - public long Height { get; } - public ByteString Prefix { get; } - - public RefBlockInfo(long height, ByteString prefix) - { - Height = height; - Prefix = prefix; - } + Height = height; + Prefix = prefix; } - public interface IRefBlockInfoProvider + public long Height { get; } + public ByteString Prefix { get; } +} + +public interface IRefBlockInfoProvider +{ + RefBlockInfo GetRefBlockInfo(); +} + +public class RefBlockInfoProvider : IRefBlockInfoProvider, ITransientDependency +{ + private readonly IBlockchainService _blockchainService; + + public RefBlockInfoProvider(IBlockchainService blockchainService) { - RefBlockInfo GetRefBlockInfo(); + _blockchainService = blockchainService; } - public class RefBlockInfoProvider : IRefBlockInfoProvider, ITransientDependency + public RefBlockInfo GetRefBlockInfo() { - private readonly IBlockchainService _blockchainService; - - public RefBlockInfoProvider(IBlockchainService blockchainService) - { - _blockchainService = blockchainService; - } - - public RefBlockInfo GetRefBlockInfo() - { - var block = AsyncHelper.RunSync(() => _blockchainService.GetBestChainLastBlockHeaderAsync()); - var height = block.Height; - var prefix = BlockHelper.GetRefBlockPrefix(block.GetHash()); - return new RefBlockInfo(height, prefix); - } + var block = AsyncHelper.RunSync(() => _blockchainService.GetBestChainLastBlockHeaderAsync()); + var height = block.Height; + var prefix = BlockHelper.GetRefBlockPrefix(block.GetHash()); + return new RefBlockInfo(height, prefix); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/IResetBlockTimeProvider.cs b/src/AElf.ContractTestBase/ContractTestKit/IResetBlockTimeProvider.cs index bc633de278..92f7b6ae98 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/IResetBlockTimeProvider.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/IResetBlockTimeProvider.cs @@ -1,14 +1,13 @@ -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public interface IResetBlockTimeProvider { - public interface IResetBlockTimeProvider - { - bool Enabled { get; } - int StepMilliseconds { get; } - } + bool Enabled { get; } + int StepMilliseconds { get; } +} - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => true; - public int StepMilliseconds => 4000; - } +public class ResetBlockTimeProvider : IResetBlockTimeProvider +{ + public bool Enabled => true; + public int StepMilliseconds => 4000; } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/ITestTransactionExecutor.cs b/src/AElf.ContractTestBase/ContractTestKit/ITestTransactionExecutor.cs index c8c78cdfbe..abc2691e56 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ITestTransactionExecutor.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ITestTransactionExecutor.cs @@ -3,13 +3,12 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public interface ITestTransactionExecutor { - public interface ITestTransactionExecutor - { - Task ExecuteAsync(Transaction transaction); - Task ExecuteWithExceptionAsync(Transaction transaction); - Task ReadAsync(Transaction transaction); - Task ReadWithExceptionAsync(Transaction transaction); - } + Task ExecuteAsync(Transaction transaction); + Task ExecuteWithExceptionAsync(Transaction transaction); + Task ReadAsync(Transaction transaction); + Task ReadWithExceptionAsync(Transaction transaction); } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/MethodStubFactory.cs b/src/AElf.ContractTestBase/ContractTestKit/MethodStubFactory.cs index 5d8fe205d1..a541a70914 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/MethodStubFactory.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/MethodStubFactory.cs @@ -4,126 +4,119 @@ using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; -using AElf.Kernel.Blockchain.Application; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class MethodStubFactory : IMethodStubFactory, ITransientDependency { - public class MethodStubFactory : IMethodStubFactory, ITransientDependency + private readonly IBlockTimeProvider _blockTimeProvider; + + private readonly IRefBlockInfoProvider _refBlockInfoProvider; + private readonly IResetBlockTimeProvider _resetBlockTimeProvider; + private readonly ITestTransactionExecutor _testTransactionExecutor; + + public MethodStubFactory(IServiceProvider serviceProvider) { - public ECKeyPair KeyPair { get; set; } = CryptoHelper.GenerateKeyPair(); + _refBlockInfoProvider = serviceProvider.GetRequiredService(); + _testTransactionExecutor = serviceProvider.GetRequiredService(); + _blockTimeProvider = serviceProvider.GetRequiredService(); + _resetBlockTimeProvider = serviceProvider.GetRequiredService(); + } - public Address ContractAddress { get; set; } + public ECKeyPair KeyPair { get; set; } = CryptoHelper.GenerateKeyPair(); - public Address Sender => Address.FromPublicKey(KeyPair.PublicKey); + public Address ContractAddress { get; set; } - private readonly IRefBlockInfoProvider _refBlockInfoProvider; - private readonly ITestTransactionExecutor _testTransactionExecutor; - private readonly IBlockTimeProvider _blockTimeProvider; - private readonly IResetBlockTimeProvider _resetBlockTimeProvider; + public Address Sender => Address.FromPublicKey(KeyPair.PublicKey); - public MethodStubFactory(IServiceProvider serviceProvider) + public IMethodStub Create(Method method) + where TInput : IMessage, new() where TOutput : IMessage, new() + { + Transaction GetTransaction(TInput input) { - _refBlockInfoProvider = serviceProvider.GetRequiredService(); - _testTransactionExecutor = serviceProvider.GetRequiredService(); - _blockTimeProvider = serviceProvider.GetRequiredService(); - _resetBlockTimeProvider = serviceProvider.GetRequiredService(); + var refBlockInfo = _refBlockInfoProvider.GetRefBlockInfo(); + var transaction = GetTransactionWithoutSignature(input, method); + transaction.RefBlockNumber = refBlockInfo.Height; + transaction.RefBlockPrefix = refBlockInfo.Prefix; + + var signature = CryptoHelper.SignWithPrivateKey( + KeyPair.PrivateKey, transaction.GetHash().Value.ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + return transaction; } - public IMethodStub Create(Method method) - where TInput : IMessage, new() where TOutput : IMessage, new() + async Task> SendAsync(TInput input) { - Transaction GetTransaction(TInput input) - { - var refBlockInfo = _refBlockInfoProvider.GetRefBlockInfo(); - var transaction = GetTransactionWithoutSignature(input, method); - transaction.RefBlockNumber = refBlockInfo.Height; - transaction.RefBlockPrefix = refBlockInfo.Prefix; - - var signature = CryptoHelper.SignWithPrivateKey( - KeyPair.PrivateKey, transaction.GetHash().Value.ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - return transaction; - } - - async Task> SendAsync(TInput input) - { - var transaction = GetTransaction(input); - var transactionResult = await _testTransactionExecutor.ExecuteAsync(transaction); - - if (transactionResult == null) - { - return new ExecutionResult {Transaction = transaction}; - } - - ResetBlockTime(); - return new ExecutionResult - { - Transaction = transaction, TransactionResult = transactionResult, - Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) - }; - } - - async Task> SendWithExceptionAsync(TInput input) - { - var transaction = GetTransaction(input); - var transactionResult = await _testTransactionExecutor.ExecuteWithExceptionAsync(transaction); - if (transactionResult == null) - { - return new ExecutionResult {Transaction = transaction}; - } - - ResetBlockTime(); - return new ExecutionResult - { - Transaction = transaction, TransactionResult = transactionResult, - Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) - }; - } - - void ResetBlockTime() - { - if (!_resetBlockTimeProvider.Enabled) return; - var currentBlockTime = _blockTimeProvider.GetBlockTime(); - currentBlockTime.AddMilliseconds(_resetBlockTimeProvider.StepMilliseconds); - _blockTimeProvider.SetBlockTime(currentBlockTime); - } + var transaction = GetTransaction(input); + var transactionResult = await _testTransactionExecutor.ExecuteAsync(transaction); - async Task CallAsync(TInput input) - { - var transaction = GetTransactionWithoutSignature(input, method); - var returnValue = await _testTransactionExecutor.ReadAsync(transaction); - return method.ResponseMarshaller.Deserializer(returnValue.ToByteArray()); - } + if (transactionResult == null) return new ExecutionResult { Transaction = transaction }; - async Task CallWithExceptionAsync(TInput input) + ResetBlockTime(); + return new ExecutionResult { - var transaction = GetTransactionWithoutSignature(input, method); - var returnValue = await _testTransactionExecutor.ReadWithExceptionAsync(transaction); - return new StringValue {Value = returnValue.Value}; - } - - return new MethodStub(method, SendAsync, CallAsync, GetTransaction, SendWithExceptionAsync, - CallWithExceptionAsync); + Transaction = transaction, TransactionResult = transactionResult, + Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) + }; } - private Transaction GetTransactionWithoutSignature(TInput input, - Method method) - where TInput : IMessage, new() where TOutput : IMessage, new() + async Task> SendWithExceptionAsync(TInput input) { - var transaction = new Transaction + var transaction = GetTransaction(input); + var transactionResult = await _testTransactionExecutor.ExecuteWithExceptionAsync(transaction); + if (transactionResult == null) return new ExecutionResult { Transaction = transaction }; + + ResetBlockTime(); + return new ExecutionResult { - From = Sender, - To = ContractAddress, - MethodName = method.Name, - Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + Transaction = transaction, TransactionResult = transactionResult, + Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) }; + } - return transaction; + void ResetBlockTime() + { + if (!_resetBlockTimeProvider.Enabled) return; + var currentBlockTime = _blockTimeProvider.GetBlockTime(); + currentBlockTime.AddMilliseconds(_resetBlockTimeProvider.StepMilliseconds); + _blockTimeProvider.SetBlockTime(currentBlockTime); + } + + async Task CallAsync(TInput input) + { + var transaction = GetTransactionWithoutSignature(input, method); + var returnValue = await _testTransactionExecutor.ReadAsync(transaction); + return method.ResponseMarshaller.Deserializer(returnValue.ToByteArray()); + } + + async Task CallWithExceptionAsync(TInput input) + { + var transaction = GetTransactionWithoutSignature(input, method); + var returnValue = await _testTransactionExecutor.ReadWithExceptionAsync(transaction); + return new StringValue { Value = returnValue.Value }; } + + return new MethodStub(method, SendAsync, CallAsync, GetTransaction, SendWithExceptionAsync, + CallWithExceptionAsync); + } + + private Transaction GetTransactionWithoutSignature(TInput input, + Method method) + where TInput : IMessage, new() where TOutput : IMessage, new() + { + var transaction = new Transaction + { + From = Sender, + To = ContractAddress, + MethodName = method.Name, + Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + }; + + return transaction; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/SampleAccount.cs b/src/AElf.ContractTestBase/ContractTestKit/SampleAccount.cs index b65770e760..4894b469ac 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/SampleAccount.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/SampleAccount.cs @@ -5,167 +5,166 @@ using AElf.Cryptography.ECDSA; using AElf.Types; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public static class SampleAccount { - public static class SampleAccount + public static IReadOnlyList Accounts; + + private static readonly string[] Keys = { - static SampleAccount() - { - Accounts = new ReadOnlyCollection( - Keys.Select(x => - { - var privateKeyHex = x.Split(",").First(); - var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); - var keyPair = CryptoHelper.FromPrivateKey(privateKey); - - return new Account - { - KeyPair = keyPair, - Address = Address.FromPublicKey(keyPair.PublicKey) - }; - }).ToList()); - } + "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", + "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", + "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", + "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", + "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", + "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", + "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", + "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", + "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", + "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", + "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", + "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", + "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", + "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", + "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", + "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", + "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", + "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", + "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", + "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", + "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", + "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", + "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", + "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", + "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", + "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", + "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", + "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", + "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", + "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", + "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", + "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", + "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", + "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", + "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", + "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", + "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", + "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", + "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", + "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", + "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", + "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", + "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", + "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", + "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", + "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", + "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", + "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", + "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", + "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", + "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", + "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", + "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", + "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", + "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", + "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", + "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", + "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", + "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", + "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", + "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", + "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", + "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", + "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", + "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", + "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", + "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", + "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", + "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", + "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", + "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", + "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", + "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", + "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", + "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", + "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", + "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", + "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", + "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", + "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", + "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", + "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", + "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", + "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", + "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", + "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", + "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", + "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", + "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", + "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", + "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", + "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", + "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", + "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", + "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", + "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", + "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", + "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", + "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", + "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1", + "76c4f4792b72678edcc8365a7ee75a3de023939fe3e4efb9c6537d2245a25db3,046ff7146633ee0ce0390f5760cbba2fa49f8fe4360edb0232bcbab34698b652f1749abff316a9ac8968cc135699e9156ee6727cc6f8a39fda4b822c76f077eb8b", + "d4a55450e3c711114ac65beb47f173ee6439e519b337bbd3159bf095a763ab07,0408ce3ef3c8a3a0edbb7035205a5a18c20d0db882ef764c7dcd14469f69f91c17390a657ff2148f137092a81f1ec328b109083279cb2dc4f1343caa7dac916d91", + "21b3b51a420a68267e26454dd07768f587122251f30420d4e6b2623a74cb7dd5,0480e5857aca871d40b776e805d119b416771bb4dc0a0ede9a571a69290e935761fbed8775bb947b3f6bdbfb7fbbaa6df4df04d1e861ca84130a65f23b6be7d9fb", + "bbcc0e97e84724f689d7abb74a7dbc6c85127439563fab4a6f4521d1a3701a03,04cffb78088a74842ec9abb2cbf9f2acb523315063e8244cc446ac586cffa2d79259a4c12e48453366e232b77617cc23fc14545a465bbcd712b12ade942b8aad01", + "3453beed7711c57b5795a682a6b264e7c3bc7af346e0dea3d764b9c7692ae384,0486d856261e92b2c4df266a69a28c2bb9ed8085c3295394bfc31e5abc57f33836a648cb10e308aba5d6cd6bcd76aabea8e33f315e222c0a7da3ae9cfe8cba6d8a", + "11a927387fa0cc7d161911fce0933d1151bddd4cbce51b08e4e9ad4fc192491b,04c6ad3821932c295424e2057460bfba0a3c2a210ebdb9aedce9cceb9b45915ca6a39cfdec326beae96102a932d65467b942088fd94f5ef3a9533859b7020cf540", + "772058f9c0361f79022212c9ae1f9ac9193524a4ae28b528d3454a7bac6dd42a,04ba722aa798e202e6f770eb5e940c7b9a7baff1682348a28a703442136de1c85d1dd8f9e3595c51b7160ab6a815a0d115df5eaddb683eb04d8a34c880fe5c7be5", + "0d0eb1c444546d09daa2f35c3f8332b5302dca12994e1fa5773f443379a539b1,0498e6abfb3e2a983420bd37ca886369d038cef274c9c605f493dd49fa0b2598716b3c16531ae84b0aeb5812215238914be4b33eeda6fd1e95ed5c19cbe5e8a670", + "a20ee6cd67fd1a533db2adbfc2124b2b109b2c43677b6ac34e1fc9969236faa7,04f7d136f4c95df5b7b4d72d196157912130558b03092a00d75fb7aebf2cbeca97343768e176f03f7cbccea616671127a53c08213b7b241bb734e45b89bd040fa9", + "50ac78772610e3700232df06d8ef9f8128007beeed98c21d19e381cf9d8dda4b,04a5665948b004634be699b306752c743578b85656a279e9e821b080d84b285b3779aba3f0cccd38119f6a964fb46369d33e661eb76db9c9f7cc277d319657cec3", + "e5d5fdb153fce928b0873985f166a89f30159fba8e96ac54d816d4db30313558,04414ef776662c95c6ece72ed39fdeaf236e09c1ee735e616ad9dcefb697b086128598a96347ac816ea5b2ef7d7b11365c2b2dbd81785605fca175cb69c9880251", + "44cdbcd03f5c1c1b5d5261f7d31a05eb57ec7714d6d8681579857551fd52f166,0420baae37eeca0594997f70b2a413e625418d6ca0911e2c303529a69f0bb50b02f834e4d021b6ec95dfeb328f96d58624a13ad2bd84bbb51bdb8dde578d50bb44", + "5a1d480438edd2725429a80e44df714e218ee4eec8e9e18a3a29da165ed76091,042817b6070f8b169e7bf7679f556fb4a50ac7c5dd16c92a7b7f792a9ec5f45e68f2ea31b8d48a54b6bb672dd113744d1f683e271d0cf19cc243454a4a97002310", + "2788e96e5cb2bc7072856fdcd55c14ef8915700202661be9a89b29494cb12459,049571146238b03183c1b6a92b54cb2167f5f803cae77dd6b2995ed6717e768d3108432c8dc4901d5a0a247a4102293f7c808c24bf380c26050a0fa91832e95faf", + "7eea650941c6dbd50c5260e7305a276ee5d1e894e982c5ba10416c0b24ac5001,04b1a54cf58c1d77d38d5962b36dfa5f3203bfdd7077ce6900c6aebbe8b73726dda1bb4416f3500617c9dffebe6bbb65197f403cfd7386b1a8ce98dae696b4c074", + "7ffdd97e69a8d3c36c7fee03672c6c6101f3f17220d43964bca8031fb93e9121,04856729deb6b3df719e75a719ed1e56d5c702862ad62c9ef5ec29212484d52612f0c1c0b26768992b2e4fa90e75992b2bc7d938f320b31023859da89f4f91a3dd", + "b1e760d8189963347f30c72a226ce6d07ed012eb4eeb9770bbfcaa0a1ad4f22b,04d6fee8c9b96185b4539eead39ee59219bc9590abe124e426519c6f7a7dcf2720d8cc810f45e8528819e7b353bafcafd4d0fa768c315bdcd823061f32b3cc8112", + "67e27d4ea0155697d637132f6ef075b70f16f7255245607ec6c4a8843e30a23c,049a2daad089c0340b41886c076294df3d369d3324570f4fe02c7411c374fe31841cfcc201676296dc52ca45e06506d6ec5c521b1faffe4193f15c0e76a82585fa", + "02401eacabbf16b0232db781da565108e59bdde0a5537f8ded889ae3aad19cb4,046f6337c7d9024ffb23359fc5ea456bb9c2ac6350aad68a8322a33a6eb71901d4dcf8e59745b83e69a9e04db9fd64ffa14b6aebc57b577d8b77ed44ac47f11a9b", + "a5176b0331dc5543f1ffb60d83b481210dc2d7d815f6844a3f942d5eea53d665,0479e8f6eec41c83a9727046996c6cd7c86635756e2c5add817831e1130a55f18fbbcc6945d072deed8601ccabd2b30ae6cf0f0483036954f4ed9440d1abc191c8", + "1347544be620547c3baeeb6ea8b8ed17667f9d0f78d23725c8cb6b2ab63f50f8,04756b5b0694e5f910ead249de6439081945791afda055cde92d9e288efef9b8561e23fd0a56a5beda264162b86b08f5c0ebdb938dfbaf973e06a1df0316509fa5", + "8769dc54b9e94bd705cec137a956bbe921eb2a97c5b05b6d7af2eb87ec7d391e,04f8b0fc524ad7d468c74961b3640631460e7b00d832e3f6a32343763892fdf03bc6d67e93915e74d7fb7dcd2fff0ad7b4c1262b6fa97811c4a09e9dd7f720efb7", + "72aadf4b72fb13724382e95cb17d39da9834a50f747f0dc27c569ada13f1a988,04eb6a933ac85f142b60a1b27d80bcf9fcda1ec51afc9c2c44c8bb2850d6c5fa85f93d2512e1f23d743c32269d622f0243c69558527f1c25b917179224dea047c4", + "ed606a6c36a5ce73469945001f3c5845f704a00d07195e53d024280f9b8c6a26,044dcd4c72aea835b1fed73506f5fb11ee09ce20c8eb901f518ba94e1df02fb78df368cd07ec98632c89ef1514304a799923817a062505e142015bbbc6b812a71a", + "72bc1525d9f90959e8fd49833d6d130fef0f4acb99651b2d50e62e47328dbbef,04f421d26b81813d1157c922eeca82b5f356c2cf7a6b1f1ff9b86c609942c70ef9f3c28fd21f4cf6ed278f6f4eea55f3d7ddc403dc2c5b93c87558c6c43556e98b", + "99c765d7a4b746f8db7f3570577f3f6c36c6864545ea1adcf09bcb50ce3bef79,0481f288d081c093a7f3a64b1e67abb8b7f76ce585256bdf6a5919551032755d1193ae3926c76da10bcc8de2f6720fca87d3bf8d6e2914fd53e2c03da6397a31d4", + "6ee0da06418ac1f0006cea79c6741eb42ee0c1a125795918b6c883ccfbe1476c,04884491ebb3f43266b40afddd256502e1c5975c3d3cf5f3889e0586236f1b4455ac36e27f7b500803fdc34a71d5696750fbadbc2cc5b0e302751675e5e5122201", + "d1dfaa8e752ca7f6aec619e8726883c6048c635b6109b240307e029bd05efe7a,04c916226209f7256b29c31faf98811094194e1baeba0edbc31340ba79f984452039a626664bf8f17baa0efdab481449966687d77c0b01b71f22903548b0642f44", + "055832877713f9d284421f55b26c60ef6ff4a92eaf2d45422a6b0285dd555d6a,04ae59215cb0424fe66f868b13f807df7dd7c588830ca163ccd91b96c665ba218d8f9ee0b3a4d749946a6530be9c1b78ea267f55187f06162928e657985e7a776d", + "f7c10cc06f0f64b772c453c7cc056c54b00d14353db0521a34c04af8208da4b2,04d7cf0b10a684bc536b473a8512c91f4b172e95dad42ff71268e49f56a6492f2e1f134cf03b702203b4d1b259788e86bb8ac7ba7b9afcc1497a989cf822974d77" + }; - public static IReadOnlyList Accounts; + static SampleAccount() + { + Accounts = new ReadOnlyCollection( + Keys.Select(x => + { + var privateKeyHex = x.Split(",").First(); + var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); + var keyPair = CryptoHelper.FromPrivateKey(privateKey); - private static readonly string[] Keys = - { - "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", - "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", - "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", - "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", - "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", - "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", - "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", - "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", - "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", - "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", - "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", - "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", - "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", - "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", - "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", - "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", - "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", - "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", - "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", - "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", - "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", - "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", - "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", - "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", - "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", - "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", - "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", - "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", - "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", - "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", - "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", - "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", - "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", - "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", - "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", - "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", - "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", - "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", - "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", - "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", - "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", - "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", - "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", - "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", - "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", - "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", - "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", - "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", - "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", - "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", - "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", - "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", - "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", - "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", - "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", - "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", - "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", - "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", - "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", - "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", - "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", - "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", - "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", - "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", - "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", - "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", - "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", - "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", - "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", - "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", - "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", - "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", - "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", - "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", - "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", - "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", - "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", - "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", - "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", - "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", - "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", - "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", - "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", - "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", - "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", - "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", - "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", - "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", - "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", - "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", - "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", - "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", - "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", - "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", - "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", - "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", - "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", - "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", - "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", - "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1", - "76c4f4792b72678edcc8365a7ee75a3de023939fe3e4efb9c6537d2245a25db3,046ff7146633ee0ce0390f5760cbba2fa49f8fe4360edb0232bcbab34698b652f1749abff316a9ac8968cc135699e9156ee6727cc6f8a39fda4b822c76f077eb8b", - "d4a55450e3c711114ac65beb47f173ee6439e519b337bbd3159bf095a763ab07,0408ce3ef3c8a3a0edbb7035205a5a18c20d0db882ef764c7dcd14469f69f91c17390a657ff2148f137092a81f1ec328b109083279cb2dc4f1343caa7dac916d91", - "21b3b51a420a68267e26454dd07768f587122251f30420d4e6b2623a74cb7dd5,0480e5857aca871d40b776e805d119b416771bb4dc0a0ede9a571a69290e935761fbed8775bb947b3f6bdbfb7fbbaa6df4df04d1e861ca84130a65f23b6be7d9fb", - "bbcc0e97e84724f689d7abb74a7dbc6c85127439563fab4a6f4521d1a3701a03,04cffb78088a74842ec9abb2cbf9f2acb523315063e8244cc446ac586cffa2d79259a4c12e48453366e232b77617cc23fc14545a465bbcd712b12ade942b8aad01", - "3453beed7711c57b5795a682a6b264e7c3bc7af346e0dea3d764b9c7692ae384,0486d856261e92b2c4df266a69a28c2bb9ed8085c3295394bfc31e5abc57f33836a648cb10e308aba5d6cd6bcd76aabea8e33f315e222c0a7da3ae9cfe8cba6d8a", - "11a927387fa0cc7d161911fce0933d1151bddd4cbce51b08e4e9ad4fc192491b,04c6ad3821932c295424e2057460bfba0a3c2a210ebdb9aedce9cceb9b45915ca6a39cfdec326beae96102a932d65467b942088fd94f5ef3a9533859b7020cf540", - "772058f9c0361f79022212c9ae1f9ac9193524a4ae28b528d3454a7bac6dd42a,04ba722aa798e202e6f770eb5e940c7b9a7baff1682348a28a703442136de1c85d1dd8f9e3595c51b7160ab6a815a0d115df5eaddb683eb04d8a34c880fe5c7be5", - "0d0eb1c444546d09daa2f35c3f8332b5302dca12994e1fa5773f443379a539b1,0498e6abfb3e2a983420bd37ca886369d038cef274c9c605f493dd49fa0b2598716b3c16531ae84b0aeb5812215238914be4b33eeda6fd1e95ed5c19cbe5e8a670", - "a20ee6cd67fd1a533db2adbfc2124b2b109b2c43677b6ac34e1fc9969236faa7,04f7d136f4c95df5b7b4d72d196157912130558b03092a00d75fb7aebf2cbeca97343768e176f03f7cbccea616671127a53c08213b7b241bb734e45b89bd040fa9", - "50ac78772610e3700232df06d8ef9f8128007beeed98c21d19e381cf9d8dda4b,04a5665948b004634be699b306752c743578b85656a279e9e821b080d84b285b3779aba3f0cccd38119f6a964fb46369d33e661eb76db9c9f7cc277d319657cec3", - "e5d5fdb153fce928b0873985f166a89f30159fba8e96ac54d816d4db30313558,04414ef776662c95c6ece72ed39fdeaf236e09c1ee735e616ad9dcefb697b086128598a96347ac816ea5b2ef7d7b11365c2b2dbd81785605fca175cb69c9880251", - "44cdbcd03f5c1c1b5d5261f7d31a05eb57ec7714d6d8681579857551fd52f166,0420baae37eeca0594997f70b2a413e625418d6ca0911e2c303529a69f0bb50b02f834e4d021b6ec95dfeb328f96d58624a13ad2bd84bbb51bdb8dde578d50bb44", - "5a1d480438edd2725429a80e44df714e218ee4eec8e9e18a3a29da165ed76091,042817b6070f8b169e7bf7679f556fb4a50ac7c5dd16c92a7b7f792a9ec5f45e68f2ea31b8d48a54b6bb672dd113744d1f683e271d0cf19cc243454a4a97002310", - "2788e96e5cb2bc7072856fdcd55c14ef8915700202661be9a89b29494cb12459,049571146238b03183c1b6a92b54cb2167f5f803cae77dd6b2995ed6717e768d3108432c8dc4901d5a0a247a4102293f7c808c24bf380c26050a0fa91832e95faf", - "7eea650941c6dbd50c5260e7305a276ee5d1e894e982c5ba10416c0b24ac5001,04b1a54cf58c1d77d38d5962b36dfa5f3203bfdd7077ce6900c6aebbe8b73726dda1bb4416f3500617c9dffebe6bbb65197f403cfd7386b1a8ce98dae696b4c074", - "7ffdd97e69a8d3c36c7fee03672c6c6101f3f17220d43964bca8031fb93e9121,04856729deb6b3df719e75a719ed1e56d5c702862ad62c9ef5ec29212484d52612f0c1c0b26768992b2e4fa90e75992b2bc7d938f320b31023859da89f4f91a3dd", - "b1e760d8189963347f30c72a226ce6d07ed012eb4eeb9770bbfcaa0a1ad4f22b,04d6fee8c9b96185b4539eead39ee59219bc9590abe124e426519c6f7a7dcf2720d8cc810f45e8528819e7b353bafcafd4d0fa768c315bdcd823061f32b3cc8112", - "67e27d4ea0155697d637132f6ef075b70f16f7255245607ec6c4a8843e30a23c,049a2daad089c0340b41886c076294df3d369d3324570f4fe02c7411c374fe31841cfcc201676296dc52ca45e06506d6ec5c521b1faffe4193f15c0e76a82585fa", - "02401eacabbf16b0232db781da565108e59bdde0a5537f8ded889ae3aad19cb4,046f6337c7d9024ffb23359fc5ea456bb9c2ac6350aad68a8322a33a6eb71901d4dcf8e59745b83e69a9e04db9fd64ffa14b6aebc57b577d8b77ed44ac47f11a9b", - "a5176b0331dc5543f1ffb60d83b481210dc2d7d815f6844a3f942d5eea53d665,0479e8f6eec41c83a9727046996c6cd7c86635756e2c5add817831e1130a55f18fbbcc6945d072deed8601ccabd2b30ae6cf0f0483036954f4ed9440d1abc191c8", - "1347544be620547c3baeeb6ea8b8ed17667f9d0f78d23725c8cb6b2ab63f50f8,04756b5b0694e5f910ead249de6439081945791afda055cde92d9e288efef9b8561e23fd0a56a5beda264162b86b08f5c0ebdb938dfbaf973e06a1df0316509fa5", - "8769dc54b9e94bd705cec137a956bbe921eb2a97c5b05b6d7af2eb87ec7d391e,04f8b0fc524ad7d468c74961b3640631460e7b00d832e3f6a32343763892fdf03bc6d67e93915e74d7fb7dcd2fff0ad7b4c1262b6fa97811c4a09e9dd7f720efb7", - "72aadf4b72fb13724382e95cb17d39da9834a50f747f0dc27c569ada13f1a988,04eb6a933ac85f142b60a1b27d80bcf9fcda1ec51afc9c2c44c8bb2850d6c5fa85f93d2512e1f23d743c32269d622f0243c69558527f1c25b917179224dea047c4", - "ed606a6c36a5ce73469945001f3c5845f704a00d07195e53d024280f9b8c6a26,044dcd4c72aea835b1fed73506f5fb11ee09ce20c8eb901f518ba94e1df02fb78df368cd07ec98632c89ef1514304a799923817a062505e142015bbbc6b812a71a", - "72bc1525d9f90959e8fd49833d6d130fef0f4acb99651b2d50e62e47328dbbef,04f421d26b81813d1157c922eeca82b5f356c2cf7a6b1f1ff9b86c609942c70ef9f3c28fd21f4cf6ed278f6f4eea55f3d7ddc403dc2c5b93c87558c6c43556e98b", - "99c765d7a4b746f8db7f3570577f3f6c36c6864545ea1adcf09bcb50ce3bef79,0481f288d081c093a7f3a64b1e67abb8b7f76ce585256bdf6a5919551032755d1193ae3926c76da10bcc8de2f6720fca87d3bf8d6e2914fd53e2c03da6397a31d4", - "6ee0da06418ac1f0006cea79c6741eb42ee0c1a125795918b6c883ccfbe1476c,04884491ebb3f43266b40afddd256502e1c5975c3d3cf5f3889e0586236f1b4455ac36e27f7b500803fdc34a71d5696750fbadbc2cc5b0e302751675e5e5122201", - "d1dfaa8e752ca7f6aec619e8726883c6048c635b6109b240307e029bd05efe7a,04c916226209f7256b29c31faf98811094194e1baeba0edbc31340ba79f984452039a626664bf8f17baa0efdab481449966687d77c0b01b71f22903548b0642f44", - "055832877713f9d284421f55b26c60ef6ff4a92eaf2d45422a6b0285dd555d6a,04ae59215cb0424fe66f868b13f807df7dd7c588830ca163ccd91b96c665ba218d8f9ee0b3a4d749946a6530be9c1b78ea267f55187f06162928e657985e7a776d", - "f7c10cc06f0f64b772c453c7cc056c54b00d14353db0521a34c04af8208da4b2,04d7cf0b10a684bc536b473a8512c91f4b172e95dad42ff71268e49f56a6492f2e1f134cf03b702203b4d1b259788e86bb8ac7ba7b9afcc1497a989cf822974d77", - }; + return new Account + { + KeyPair = keyPair, + Address = Address.FromPublicKey(keyPair.PublicKey) + }; + }).ToList()); } +} - public class Account - { - public ECKeyPair KeyPair { get; set; } - public Address Address { get; set; } - } +public class Account +{ + public ECKeyPair KeyPair { get; set; } + public Address Address { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/SampleAddress.cs b/src/AElf.ContractTestBase/ContractTestKit/SampleAddress.cs index 9ad3fb5b47..308a361237 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/SampleAddress.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/SampleAddress.cs @@ -3,30 +3,29 @@ using System.Linq; using AElf.Types; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public static class SampleAddress { - public static class SampleAddress - { - public static readonly IReadOnlyList
AddressList; + public static readonly IReadOnlyList
AddressList; - private static readonly string[] Base58Strings = - { - "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", - "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", - "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", - "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", - "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", - "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", - "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", - "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", - "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", - "XgCfhmyzhtYMfcEy9CbY6sjDAtThVwfRFRu66VhXQpjxNtQ6Q" - }; + private static readonly string[] Base58Strings = + { + "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", + "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", + "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", + "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", + "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", + "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", + "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", + "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", + "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", + "XgCfhmyzhtYMfcEy9CbY6sjDAtThVwfRFRu66VhXQpjxNtQ6Q" + }; - static SampleAddress() - { - AddressList = new ReadOnlyCollection
( - Base58Strings.Select(Address.FromBase58).ToList()); - } + static SampleAddress() + { + AddressList = new ReadOnlyCollection
( + Base58Strings.Select(Address.FromBase58).ToList()); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/SmartContractTestConstants.cs b/src/AElf.ContractTestBase/ContractTestKit/SmartContractTestConstants.cs index 5eb2851168..1713307a39 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/SmartContractTestConstants.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/SmartContractTestConstants.cs @@ -1,12 +1,11 @@ using AElf.Kernel; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public static class SmartContractTestConstants { - public static class SmartContractTestConstants - { - /// - /// 30 means use default assembly loader context, for code coverage - /// - public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; - } + /// + /// 30 means use default assembly loader context, for code coverage + /// + public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/TestTransactionExecutor.cs b/src/AElf.ContractTestBase/ContractTestKit/TestTransactionExecutor.cs index 768c008ad1..1ec32d469a 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/TestTransactionExecutor.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/TestTransactionExecutor.cs @@ -12,97 +12,92 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class TestTransactionExecutor : ITestTransactionExecutor { - public class TestTransactionExecutor : ITestTransactionExecutor + private readonly IServiceProvider _serviceProvider; + + public TestTransactionExecutor(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task ExecuteAsync(Transaction transaction) + { + var transactionResult = await ExecuteTransactionAsync(transaction); + if (transactionResult == null || transactionResult.Status != TransactionResultStatus.Mined) + throw new Exception($"Failed to execute {transaction.MethodName}. {transactionResult?.Error}"); + return transactionResult; + } + + public async Task ExecuteWithExceptionAsync(Transaction transaction) { - private readonly IServiceProvider _serviceProvider; - - public TestTransactionExecutor(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public async Task ExecuteAsync(Transaction transaction) - { - var transactionResult = await ExecuteTransactionAsync(transaction); - if (transactionResult == null || transactionResult.Status != TransactionResultStatus.Mined) - throw new Exception($"Failed to execute {transaction.MethodName}. {transactionResult?.Error}"); - return transactionResult; - } - - public async Task ExecuteWithExceptionAsync(Transaction transaction) - { - var transactionResult = await ExecuteTransactionAsync(transaction); - if (transactionResult.Status == TransactionResultStatus.Mined) + var transactionResult = await ExecuteTransactionAsync(transaction); + if (transactionResult.Status == TransactionResultStatus.Mined) + throw new Exception($"Succeed to execute {transaction.MethodName}."); + + return transactionResult; + } + + public async Task ReadAsync(Transaction transaction) + { + var transactionTrace = await ReadTransactionResultAsync(transaction); + if (transactionTrace.ExecutionStatus != ExecutionStatus.Executed) + throw new Exception($"Failed to call {transaction.MethodName}. {transactionTrace.Error}"); + return transactionTrace.ReturnValue; + } + + public async Task ReadWithExceptionAsync(Transaction transaction) + { + var transactionTrace = await ReadTransactionResultAsync(transaction); + if (transactionTrace.ExecutionStatus == ExecutionStatus.Executed) + throw new Exception($"Succeed to call {transaction.MethodName}."); + + return new StringValue { Value = transactionTrace.Error }; + } + + private async Task ExecuteTransactionAsync(Transaction transaction) + { + var blockchainService = _serviceProvider.GetRequiredService(); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var miningService = _serviceProvider.GetRequiredService(); + var blockAttachService = _serviceProvider.GetRequiredService(); + var blockTimeProvider = _serviceProvider.GetRequiredService(); + + var blockExecutedSet = await miningService.MineAsync( + new RequestMiningDto { - throw new Exception($"Succeed to execute {transaction.MethodName}."); - } - - return transactionResult; - } - - private async Task ExecuteTransactionAsync(Transaction transaction) - { - var blockchainService = _serviceProvider.GetRequiredService(); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var miningService = _serviceProvider.GetRequiredService(); - var blockAttachService = _serviceProvider.GetRequiredService(); - var blockTimeProvider = _serviceProvider.GetRequiredService(); - - var blockExecutedSet = await miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = int.MaxValue - }, - new List {transaction}, - blockTimeProvider.GetBlockTime()); - - var block = blockExecutedSet.Block; - - await blockchainService.AddTransactionsAsync(new List {transaction}); - await blockchainService.AddBlockAsync(block); - await blockAttachService.AttachBlockAsync(block); - - return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; - } - - public async Task ReadAsync(Transaction transaction) - { - var transactionTrace = await ReadTransactionResultAsync(transaction); - if (transactionTrace.ExecutionStatus != ExecutionStatus.Executed) - throw new Exception($"Failed to call {transaction.MethodName}. {transactionTrace.Error}"); - return transactionTrace.ReturnValue; - } - - public async Task ReadWithExceptionAsync(Transaction transaction) - { - var transactionTrace = await ReadTransactionResultAsync(transaction); - if (transactionTrace.ExecutionStatus == ExecutionStatus.Executed) + PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, + new List { transaction }, + blockTimeProvider.GetBlockTime()); + + var block = blockExecutedSet.Block; + + await blockchainService.AddTransactionsAsync(new List { transaction }); + await blockchainService.AddBlockAsync(block); + await blockAttachService.AttachBlockAsync(block); + + return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; + } + + private async Task ReadTransactionResultAsync(Transaction transaction) + { + var blockchainService = _serviceProvider.GetRequiredService(); + var transactionReadOnlyExecutionService = + _serviceProvider.GetRequiredService(); + var blockTimeProvider = _serviceProvider.GetRequiredService(); + + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + return await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext { - throw new Exception($"Succeed to call {transaction.MethodName}."); - } - - return new StringValue {Value = transactionTrace.Error}; - } - - private async Task ReadTransactionResultAsync(Transaction transaction) - { - var blockchainService = _serviceProvider.GetRequiredService(); - var transactionReadOnlyExecutionService = - _serviceProvider.GetRequiredService(); - var blockTimeProvider = _serviceProvider.GetRequiredService(); - - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - return await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = preBlock.GetHash(), - BlockHeight = preBlock.Height - }, - transaction, - blockTimeProvider.GetBlockTime()); - } + BlockHash = preBlock.GetHash(), + BlockHeight = preBlock.Height + }, + transaction, + blockTimeProvider.GetBlockTime()); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/UnitTestContractZeroCodeProvider.cs b/src/AElf.ContractTestBase/ContractTestKit/UnitTestContractZeroCodeProvider.cs index 2ca4aa25c6..13b35af07e 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/UnitTestContractZeroCodeProvider.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/UnitTestContractZeroCodeProvider.cs @@ -4,18 +4,17 @@ using AElf.Kernel.SmartContract.Infrastructure; using Microsoft.Extensions.Options; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider { - public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider + public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, + IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) { - public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, - IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) - { - } + } - protected override int GetCategory() - { - return KernelConstants.CodeCoverageRunnerCategory; - } + protected override int GetCategory() + { + return KernelConstants.CodeCoverageRunnerCategory; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/ContractTestKit/UnitTestSmartContractAddressService.cs b/src/AElf.ContractTestBase/ContractTestKit/UnitTestSmartContractAddressService.cs index fa5f78f602..4ea4cf4b8b 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/UnitTestSmartContractAddressService.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/UnitTestSmartContractAddressService.cs @@ -10,39 +10,35 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -namespace AElf.ContractTestBase.ContractTestKit +namespace AElf.ContractTestBase.ContractTestKit; + +public class UnitTestSmartContractAddressService : SmartContractAddressService { - public class UnitTestSmartContractAddressService : SmartContractAddressService + private readonly ConcurrentDictionary _hashToAddressMap = new(); + + public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + ISmartContractAddressProvider smartContractAddressProvider, + IEnumerable smartContractAddressNameProviders, + IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, + transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, + blockchainService) + { + } + + public override async Task> GetSystemContractNameToAddressMappingAsync( + IChainContext chainContext) + { + var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); + var dictionary = new Dictionary(); + foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) + dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); + return new ReadOnlyDictionary(dictionary); + } + + public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) { - private readonly ConcurrentDictionary _hashToAddressMap = - new ConcurrentDictionary(); - - public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - ISmartContractAddressProvider smartContractAddressProvider, - IEnumerable smartContractAddressNameProviders, - IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, - transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, - blockchainService) - { - } - - public override async Task> GetSystemContractNameToAddressMappingAsync( - IChainContext chainContext) - { - var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); - var dictionary = new Dictionary(); - foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) - { - dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); - } - return new ReadOnlyDictionary(dictionary); - } - - public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) - { - _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; - return base.SetSmartContractAddressAsync(blockIndex, contractName, address); - } + _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; + return base.SetSmartContractAddressAsync(blockIndex, contractName, address); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/GenesisSmartContractDtoProvider.cs b/src/AElf.ContractTestBase/GenesisSmartContractDtoProvider.cs index aac8a8f0bd..ce733eb9d2 100644 --- a/src/AElf.ContractTestBase/GenesisSmartContractDtoProvider.cs +++ b/src/AElf.ContractTestBase/GenesisSmartContractDtoProvider.cs @@ -1,50 +1,45 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS0; using AElf.Kernel.SmartContract.Application; using AElf.OS.Node.Application; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class GenesisSmartContractDtoProvider : IGenesisSmartContractDtoProvider { - public class GenesisSmartContractDtoProvider : IGenesisSmartContractDtoProvider - { - private readonly IContractDeploymentListProvider _contractDeploymentListProvider; - private readonly IEnumerable _contractInitializationProviders; - private readonly IContractCodeProvider _contractCodeProvider; + private readonly IContractCodeProvider _contractCodeProvider; + private readonly IContractDeploymentListProvider _contractDeploymentListProvider; + private readonly IEnumerable _contractInitializationProviders; - public GenesisSmartContractDtoProvider(IContractDeploymentListProvider contractDeploymentListProvider, - IEnumerable contractInitializationProviders, - IContractCodeProvider contractCodeProvider) - { - _contractDeploymentListProvider = contractDeploymentListProvider; - _contractInitializationProviders = contractInitializationProviders; - _contractCodeProvider = contractCodeProvider; - } + public GenesisSmartContractDtoProvider(IContractDeploymentListProvider contractDeploymentListProvider, + IEnumerable contractInitializationProviders, + IContractCodeProvider contractCodeProvider) + { + _contractDeploymentListProvider = contractDeploymentListProvider; + _contractInitializationProviders = contractInitializationProviders; + _contractCodeProvider = contractCodeProvider; + } - public IEnumerable GetGenesisSmartContractDtos() - { - var contractCode = _contractCodeProvider.Codes; - var deploymentList = _contractDeploymentListProvider.GetDeployContractNameList(); - return _contractInitializationProviders - .Where(p => deploymentList.Contains(p.SystemSmartContractName)) - .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) - .Select(p => + public IEnumerable GetGenesisSmartContractDtos() + { + var contractCode = _contractCodeProvider.Codes; + var deploymentList = _contractDeploymentListProvider.GetDeployContractNameList(); + return _contractInitializationProviders + .Where(p => deploymentList.Contains(p.SystemSmartContractName)) + .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) + .Select(p => + { + var code = contractCode[p.ContractCodeName]; + var methodList = p.GetInitializeMethodList(code); + var genesisSmartContractDto = new GenesisSmartContractDto { - var code = contractCode[p.ContractCodeName]; - var methodList = p.GetInitializeMethodList(code); - var genesisSmartContractDto = new GenesisSmartContractDto - { - Code = code, - SystemSmartContractName = p.SystemSmartContractName, - ContractInitializationMethodCallList = new List() - }; - foreach (var method in methodList) - { - genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - } + Code = code, + SystemSmartContractName = p.SystemSmartContractName, + ContractInitializationMethodCallList = new List() + }; + foreach (var method in methodList) genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - return genesisSmartContractDto; - }); - } + return genesisSmartContractDto; + }); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/IContractCodeProvider.cs b/src/AElf.ContractTestBase/IContractCodeProvider.cs index 8f3e615da3..1f57dd6739 100644 --- a/src/AElf.ContractTestBase/IContractCodeProvider.cs +++ b/src/AElf.ContractTestBase/IContractCodeProvider.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public interface IContractCodeProvider { - public interface IContractCodeProvider - { - IReadOnlyDictionary Codes { get; set; } - } + IReadOnlyDictionary Codes { get; set; } +} - public class ContractCodeProvider : IContractCodeProvider, ISingletonDependency - { - public IReadOnlyDictionary Codes { get; set; } - } +public class ContractCodeProvider : IContractCodeProvider, ISingletonDependency +{ + public IReadOnlyDictionary Codes { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainAEDPoSContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/MainChainAEDPoSContractInitializationDataProvider.cs index 872745c451..f8c9b3c4a6 100644 --- a/src/AElf.ContractTestBase/MainChainAEDPoSContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/MainChainAEDPoSContractInitializationDataProvider.cs @@ -1,29 +1,27 @@ using AElf.Kernel.Consensus.AEDPoS; using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +// TODO: Same code in src/AElf.Blockchains.MainChain/AEDPoSContractInitializationDataProvider, need to resolve. +public class MainChainAEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider { - // TODO: Same code in src/AElf.Blockchains.MainChain/AEDPoSContractInitializationDataProvider, need to resolve. - public class MainChainAEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider - { - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; - public MainChainAEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions) - { - _consensusOptions = consensusOptions.Value; - } + public MainChainAEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions) + { + _consensusOptions = consensusOptions.Value; + } - public AEDPoSContractInitializationData GetContractInitializationData() + public AEDPoSContractInitializationData GetContractInitializationData() + { + return new AEDPoSContractInitializationData { - return new AEDPoSContractInitializationData - { - MiningInterval = _consensusOptions.MiningInterval, - PeriodSeconds = _consensusOptions.PeriodSeconds, - StartTimestamp = _consensusOptions.StartTimestamp, - InitialMinerList = _consensusOptions.InitialMinerList, - MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval - }; - } + MiningInterval = _consensusOptions.MiningInterval, + PeriodSeconds = _consensusOptions.PeriodSeconds, + StartTimestamp = _consensusOptions.StartTimestamp, + InitialMinerList = _consensusOptions.InitialMinerList, + MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainContractDeploymentListProvider.cs b/src/AElf.ContractTestBase/MainChainContractDeploymentListProvider.cs index 812cb9fd8c..7fbb590dcf 100644 --- a/src/AElf.ContractTestBase/MainChainContractDeploymentListProvider.cs +++ b/src/AElf.ContractTestBase/MainChainContractDeploymentListProvider.cs @@ -9,29 +9,28 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class MainChainContractDeploymentListProvider : IContractDeploymentListProvider { - public class MainChainContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - VoteSmartContractAddressNameProvider.Name, - ProfitSmartContractAddressNameProvider.Name, - ElectionSmartContractAddressNameProvider.Name, - TreasurySmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - ConfigurationSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - TokenConverterSmartContractAddressNameProvider.Name, - TokenHolderSmartContractAddressNameProvider.Name, - EconomicSmartContractAddressNameProvider.Name, - }; - } + VoteSmartContractAddressNameProvider.Name, + ProfitSmartContractAddressNameProvider.Name, + ElectionSmartContractAddressNameProvider.Name, + TreasurySmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name, + ConfigurationSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + TokenConverterSmartContractAddressNameProvider.Name, + TokenHolderSmartContractAddressNameProvider.Name, + EconomicSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainContractTestBase.cs b/src/AElf.ContractTestBase/MainChainContractTestBase.cs index e6b65ee925..420e397882 100644 --- a/src/AElf.ContractTestBase/MainChainContractTestBase.cs +++ b/src/AElf.ContractTestBase/MainChainContractTestBase.cs @@ -1,8 +1,8 @@ -namespace AElf.ContractTestBase +using AElf.ContractTestBase.ContractTestKit; + +namespace AElf.ContractTestBase; + +public class MainChainContractTestBase : ContractTestBase + where T : MainChainContractTestModule { - public class MainChainContractTestBase : ContractTestKit.ContractTestBase - where T : MainChainContractTestModule - { - - } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainContractTestModule.cs b/src/AElf.ContractTestBase/MainChainContractTestModule.cs index 45dc91a324..f0c18b6868 100644 --- a/src/AElf.ContractTestBase/MainChainContractTestModule.cs +++ b/src/AElf.ContractTestBase/MainChainContractTestModule.cs @@ -6,40 +6,38 @@ using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; -using AElf.OS.Node.Application; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +[DependsOn( + typeof(ContractTestModule), + typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(CrossChainCoreModule), + typeof(EconomicSystemAElfModule), + typeof(GovernmentSystemAElfModule) +)] +public class MainChainContractTestModule : AbpModule { - [DependsOn( - typeof(ContractTestModule), - typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(CrossChainCoreModule), - typeof(EconomicSystemAElfModule), - typeof(GovernmentSystemAElfModule) - )] - public class MainChainContractTestModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = new List {SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex()}; - }); + options.MiningInterval = 4000; + options.InitialMinerList = new List { SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex() }; + }); - var services = context.Services; - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - } + var services = context.Services; + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainCrossChainContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/MainChainCrossChainContractInitializationDataProvider.cs index 6a38450d00..62da46c9cb 100644 --- a/src/AElf.ContractTestBase/MainChainCrossChainContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/MainChainCrossChainContractInitializationDataProvider.cs @@ -1,16 +1,14 @@ using AElf.CrossChain; -using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class MainChainCrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider { - public class MainChainCrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider + public CrossChainContractInitializationData GetContractInitializationData() { - public CrossChainContractInitializationData GetContractInitializationData() + return new CrossChainContractInitializationData { - return new CrossChainContractInitializationData - { - IsPrivilegePreserved = true - }; - } + IsPrivilegePreserved = true + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainParliamentContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/MainChainParliamentContractInitializationDataProvider.cs index 6a131647f5..d04462ceac 100644 --- a/src/AElf.ContractTestBase/MainChainParliamentContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/MainChainParliamentContractInitializationDataProvider.cs @@ -1,13 +1,11 @@ using AElf.GovernmentSystem; -using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class MainChainParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider { - public class MainChainParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider + public ParliamentContractInitializationData GetContractInitializationData() { - public ParliamentContractInitializationData GetContractInitializationData() - { - return new ParliamentContractInitializationData(); - } + return new ParliamentContractInitializationData(); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/MainChainTokenContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/MainChainTokenContractInitializationDataProvider.cs index 48b2da6b74..508a590725 100644 --- a/src/AElf.ContractTestBase/MainChainTokenContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/MainChainTokenContractInitializationDataProvider.cs @@ -1,13 +1,11 @@ using AElf.Kernel.Token; -using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class MainChainTokenContractInitializationDataProvider : ITokenContractInitializationDataProvider { - public class MainChainTokenContractInitializationDataProvider : ITokenContractInitializationDataProvider + public TokenContractInitializationData GetContractInitializationData() { - public TokenContractInitializationData GetContractInitializationData() - { - return null; - } + return null; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainAEDPoSContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/SideChainAEDPoSContractInitializationDataProvider.cs index a83381be1f..bac4bd46c8 100644 --- a/src/AElf.ContractTestBase/SideChainAEDPoSContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/SideChainAEDPoSContractInitializationDataProvider.cs @@ -5,39 +5,38 @@ using Microsoft.Extensions.Options; using Volo.Abp.Threading; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainAEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider { - public class SideChainAEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider + private readonly ConsensusOptions _consensusOptions; + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public SideChainAEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions, + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; - private readonly ConsensusOptions _consensusOptions; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + _consensusOptions = consensusOptions.Value; + } - public SideChainAEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions, - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - _consensusOptions = consensusOptions.Value; - } + public AEDPoSContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public AEDPoSContractInitializationData GetContractInitializationData() + var aedPoSContractInitializationData = new AEDPoSContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - var aedPoSContractInitializationData = new AEDPoSContractInitializationData - { - InitialMinerList = sideChainInitializationData == null - ? _consensusOptions.InitialMinerList - : MinerListWithRoundNumber.Parser - .ParseFrom(sideChainInitializationData.ChainInitializationConsensusInfo.InitialConsensusData) - .MinerList.Pubkeys.Select(p => p.ToHex()).ToList(), - StartTimestamp = sideChainInitializationData?.CreationTimestamp ?? _consensusOptions.StartTimestamp, - PeriodSeconds = _consensusOptions.PeriodSeconds, - MiningInterval = _consensusOptions.MiningInterval, - IsSideChain = true - }; + InitialMinerList = sideChainInitializationData == null + ? _consensusOptions.InitialMinerList + : MinerListWithRoundNumber.Parser + .ParseFrom(sideChainInitializationData.ChainInitializationConsensusInfo.InitialConsensusData) + .MinerList.Pubkeys.Select(p => p.ToHex()).ToList(), + StartTimestamp = sideChainInitializationData?.CreationTimestamp ?? _consensusOptions.StartTimestamp, + PeriodSeconds = _consensusOptions.PeriodSeconds, + MiningInterval = _consensusOptions.MiningInterval, + IsSideChain = true + }; - return aedPoSContractInitializationData; - } + return aedPoSContractInitializationData; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainContractDeploymentListProvider.cs b/src/AElf.ContractTestBase/SideChainContractDeploymentListProvider.cs index 600cf697e9..68512185bb 100644 --- a/src/AElf.ContractTestBase/SideChainContractDeploymentListProvider.cs +++ b/src/AElf.ContractTestBase/SideChainContractDeploymentListProvider.cs @@ -9,24 +9,23 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider { - public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - ProfitSmartContractAddressNameProvider.Name, - TokenHolderSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - ConfigurationSmartContractAddressNameProvider.Name - }; - } + ProfitSmartContractAddressNameProvider.Name, + TokenHolderSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name, + ConfigurationSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainContractTestBase.cs b/src/AElf.ContractTestBase/SideChainContractTestBase.cs index fa544c3867..085df922e0 100644 --- a/src/AElf.ContractTestBase/SideChainContractTestBase.cs +++ b/src/AElf.ContractTestBase/SideChainContractTestBase.cs @@ -1,8 +1,8 @@ -namespace AElf.ContractTestBase +using AElf.ContractTestBase.ContractTestKit; + +namespace AElf.ContractTestBase; + +public class SideChainContractTestBase : ContractTestBase + where T : SideChainContractTestModule { - public class SideChainContractTestBase : ContractTestKit.ContractTestBase - where T : SideChainContractTestModule - { - - } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainContractTestModule.cs b/src/AElf.ContractTestBase/SideChainContractTestModule.cs index 27662e5582..9e4a034741 100644 --- a/src/AElf.ContractTestBase/SideChainContractTestModule.cs +++ b/src/AElf.ContractTestBase/SideChainContractTestModule.cs @@ -11,40 +11,39 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +[DependsOn( + typeof(ContractTestModule), + typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(CrossChainCoreModule), + typeof(EconomicSystemAElfModule), + typeof(GovernmentSystemAElfModule) +)] +public class SideChainContractTestModule : AbpModule { - [DependsOn( - typeof(ContractTestModule), - typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(CrossChainCoreModule), - typeof(EconomicSystemAElfModule), - typeof(GovernmentSystemAElfModule) - )] - public class SideChainContractTestModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = new List {SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex()}; - }); - - Configure(options => { options.ParentChainId = "AELF"; }); + options.MiningInterval = 4000; + options.InitialMinerList = new List { SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex() }; + }); + + Configure(options => { options.ParentChainId = "AELF"; }); - var services = context.Services; - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - } + var services = context.Services; + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainCrossChainContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/SideChainCrossChainContractInitializationDataProvider.cs index 22fab94067..37dfe0e09e 100644 --- a/src/AElf.ContractTestBase/SideChainCrossChainContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/SideChainCrossChainContractInitializationDataProvider.cs @@ -2,29 +2,28 @@ using AElf.CrossChain.Application; using Volo.Abp.Threading; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainCrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider { - public class SideChainCrossChainContractInitializationDataProvider : ICrossChainContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public SideChainCrossChainContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public SideChainCrossChainContractInitializationDataProvider( - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public CrossChainContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public CrossChainContractInitializationData GetContractInitializationData() + return new CrossChainContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new CrossChainContractInitializationData - { - ParentChainId = _sideChainInitializationDataProvider.ParentChainId, - CreationHeightOnParentChain = sideChainInitializationData.CreationHeightOnParentChain, - IsPrivilegePreserved = sideChainInitializationData.ChainCreatorPrivilegePreserved - }; - } + ParentChainId = _sideChainInitializationDataProvider.ParentChainId, + CreationHeightOnParentChain = sideChainInitializationData.CreationHeightOnParentChain, + IsPrivilegePreserved = sideChainInitializationData.ChainCreatorPrivilegePreserved + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainInitializationDataProvider.cs b/src/AElf.ContractTestBase/SideChainInitializationDataProvider.cs index 466cae86c7..b7fcae078d 100644 --- a/src/AElf.ContractTestBase/SideChainInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/SideChainInitializationDataProvider.cs @@ -1,62 +1,61 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.ContractTestBase.ContractTestKit; using AElf.CrossChain; using AElf.CrossChain.Application; using AElf.Kernel; +using AElf.Standards.ACS7; using Google.Protobuf; using Microsoft.Extensions.Options; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider { - public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider + public SideChainInitializationDataProvider(IOptionsSnapshot crossChainConfigOptions) { - public SideChainInitializationDataProvider(IOptionsSnapshot crossChainConfigOptions) - { - ParentChainId = ChainHelper.ConvertBase58ToChainId(crossChainConfigOptions.Value.ParentChainId); - } + ParentChainId = ChainHelper.ConvertBase58ToChainId(crossChainConfigOptions.Value.ParentChainId); + } - public async Task GetChainInitializationDataAsync() + public async Task GetChainInitializationDataAsync() + { + // Default Initialization Data + return new ChainInitializationData { - // Default Initialization Data - return new ChainInitializationData + Creator = SampleAccount.Accounts.First().Address, + ChainId = ChainHelper.GetChainId(1), + ChainCreatorPrivilegePreserved = false, + ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo { - Creator = SampleAccount.Accounts.First().Address, - ChainId = ChainHelper.GetChainId(1), - ChainCreatorPrivilegePreserved = false, - ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo + InitialConsensusData = new MinerListWithRoundNumber { - InitialConsensusData = new MinerListWithRoundNumber + MinerList = new MinerList { - MinerList = new MinerList() + Pubkeys = { - Pubkeys = - { - SampleAccount.Accounts.Take(3) - .Select(a => ByteString.CopyFrom(a.KeyPair.PublicKey)) - } + SampleAccount.Accounts.Take(3) + .Select(a => ByteString.CopyFrom(a.KeyPair.PublicKey)) } - }.ToByteString() - }, - CreationHeightOnParentChain = 100, - CreationTimestamp = TimestampHelper.GetUtcNow(), - NativeTokenInfoData = new TokenInfo - { - Symbol = "ELF", - TokenName = "ELF", - Decimals = 8, - TotalSupply = 100_000_000_000_000_000, - Issuer = SampleAccount.Accounts.First().Address, - IssueChainId = ParentChainId, - }.ToByteString(), - ParentChainTokenContractAddress = SampleAddress.AddressList.Last(), - ResourceTokenInfo = new ResourceTokenInfo() - }; - } - - public int ParentChainId { get; } + } + }.ToByteString() + }, + CreationHeightOnParentChain = 100, + CreationTimestamp = TimestampHelper.GetUtcNow(), + NativeTokenInfoData = new TokenInfo + { + Symbol = "ELF", + TokenName = "ELF", + Decimals = 8, + TotalSupply = 100_000_000_000_000_000, + Issuer = SampleAccount.Accounts.First().Address, + IssueChainId = ParentChainId + }.ToByteString(), + ParentChainTokenContractAddress = SampleAddress.AddressList.Last(), + ResourceTokenInfo = new ResourceTokenInfo() + }; } + + public int ParentChainId { get; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainParliamentContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/SideChainParliamentContractInitializationDataProvider.cs index 7834ec569b..6757c82688 100644 --- a/src/AElf.ContractTestBase/SideChainParliamentContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/SideChainParliamentContractInitializationDataProvider.cs @@ -2,27 +2,27 @@ using AElf.GovernmentSystem; using Volo.Abp.Threading; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider { - public class SideChainParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public SideChainParliamentContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public SideChainParliamentContractInitializationDataProvider(ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public ParliamentContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public ParliamentContractInitializationData GetContractInitializationData() + return new ParliamentContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new ParliamentContractInitializationData - { - PrivilegedProposer = sideChainInitializationData.Creator, - ProposerAuthorityRequired = sideChainInitializationData.ChainCreatorPrivilegePreserved - }; - } + PrivilegedProposer = sideChainInitializationData.Creator, + ProposerAuthorityRequired = sideChainInitializationData.ChainCreatorPrivilegePreserved + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestBase/SideChainTokenContractInitializationDataProvider.cs b/src/AElf.ContractTestBase/SideChainTokenContractInitializationDataProvider.cs index 78930d9b21..0e48edcd15 100644 --- a/src/AElf.ContractTestBase/SideChainTokenContractInitializationDataProvider.cs +++ b/src/AElf.ContractTestBase/SideChainTokenContractInitializationDataProvider.cs @@ -5,43 +5,42 @@ using AElf.Types; using Volo.Abp.Threading; -namespace AElf.ContractTestBase +namespace AElf.ContractTestBase; + +public class SideChainTokenContractInitializationDataProvider : ITokenContractInitializationDataProvider { - public class SideChainTokenContractInitializationDataProvider : ITokenContractInitializationDataProvider + private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + + public SideChainTokenContractInitializationDataProvider( + ISideChainInitializationDataProvider sideChainInitializationDataProvider) { - private readonly ISideChainInitializationDataProvider _sideChainInitializationDataProvider; + _sideChainInitializationDataProvider = sideChainInitializationDataProvider; + } - public SideChainTokenContractInitializationDataProvider( - ISideChainInitializationDataProvider sideChainInitializationDataProvider) - { - _sideChainInitializationDataProvider = sideChainInitializationDataProvider; - } + public TokenContractInitializationData GetContractInitializationData() + { + var sideChainInitializationData = + AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - public TokenContractInitializationData GetContractInitializationData() + return new TokenContractInitializationData { - var sideChainInitializationData = - AsyncHelper.RunSync(_sideChainInitializationDataProvider.GetChainInitializationDataAsync); - - return new TokenContractInitializationData + Creator = sideChainInitializationData.Creator, + ResourceAmount = sideChainInitializationData.ResourceTokenInfo.InitialResourceAmount.ToDictionary( + kv => kv.Key.ToUpper(), + kv => kv.Value), + NativeTokenInfoData = sideChainInitializationData.NativeTokenInfoData, + PrimaryTokenInfoData = sideChainInitializationData.ChainPrimaryTokenInfo?.ChainPrimaryTokenData, + ResourceTokenListData = sideChainInitializationData.ResourceTokenInfo.ResourceTokenListData, + TokenInitialIssueList = + sideChainInitializationData.ChainPrimaryTokenInfo?.SideChainTokenInitialIssueList + .Select(t => new TokenInitialIssue { Address = t.Address, Amount = t.Amount }).ToList(), + RegisteredOtherTokenContractAddresses = new Dictionary { - Creator = sideChainInitializationData.Creator, - ResourceAmount = sideChainInitializationData.ResourceTokenInfo.InitialResourceAmount.ToDictionary( - kv => kv.Key.ToUpper(), - kv => kv.Value), - NativeTokenInfoData = sideChainInitializationData.NativeTokenInfoData, - PrimaryTokenInfoData = sideChainInitializationData.ChainPrimaryTokenInfo?.ChainPrimaryTokenData, - ResourceTokenListData = sideChainInitializationData.ResourceTokenInfo.ResourceTokenListData, - TokenInitialIssueList = - sideChainInitializationData.ChainPrimaryTokenInfo?.SideChainTokenInitialIssueList - .Select(t => new TokenInitialIssue {Address = t.Address, Amount = t.Amount}).ToList(), - RegisteredOtherTokenContractAddresses = new Dictionary { - { - _sideChainInitializationDataProvider.ParentChainId, - sideChainInitializationData.ParentChainTokenContractAddress - } + _sideChainInitializationDataProvider.ParentChainId, + sideChainInitializationData.ParentChainTokenContractAddress } - }; - } + } + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionConstants.cs b/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionConstants.cs index 4873da6483..613266e586 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionConstants.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionConstants.cs @@ -1,19 +1,18 @@ -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +// ReSharper disable once InconsistentNaming +public static class AEDPoSExtensionConstants { - // ReSharper disable once InconsistentNaming - public static class AEDPoSExtensionConstants - { - public const int InitialKeyPairCount = 5; - public const int CoreDataCenterKeyPairCount = 17; - public const int ValidationDataCenterKeyPairCount = CoreDataCenterKeyPairCount * 5; + public const int InitialKeyPairCount = 5; + public const int CoreDataCenterKeyPairCount = 17; + public const int ValidationDataCenterKeyPairCount = CoreDataCenterKeyPairCount * 5; - public static readonly int CitizenKeyPairsCount = - SampleAccount.Accounts.Count - InitialKeyPairCount - CoreDataCenterKeyPairCount * 6; + public const int MiningInterval = 4000; + public const int TinyBlocksNumber = 8; + public const int ActualMiningInterval = MiningInterval / TinyBlocksNumber; + public const int PeriodSeconds = 120; + public const int MinerIncreaseInterval = 240; - public const int MiningInterval = 4000; - public const int TinyBlocksNumber = 8; - public const int ActualMiningInterval = MiningInterval / TinyBlocksNumber; - public const int PeriodSeconds = 120; - public const int MinerIncreaseInterval = 240; - } + public static readonly int CitizenKeyPairsCount = + SampleAccount.Accounts.Count - InitialKeyPairCount - CoreDataCenterKeyPairCount * 6; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionTestBase.cs b/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionTestBase.cs index 6541c3a8e0..23b387d996 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionTestBase.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/AEDPoSExtensionTestBase.cs @@ -12,51 +12,50 @@ using Microsoft.Extensions.DependencyInjection; // ReSharper disable InconsistentNaming -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class AEDPoSExtensionTestBase : ContractTestBase { - public class AEDPoSExtensionTestBase : ContractTestBase + private readonly Dictionary _systemContractKeyWords = new() + { + { VoteSmartContractAddressNameProvider.Name, "Vote" }, + { ProfitSmartContractAddressNameProvider.Name, "Profit" }, + { ElectionSmartContractAddressNameProvider.Name, "Election" }, + { ParliamentSmartContractAddressNameProvider.Name, "Parliament" }, + { TokenSmartContractAddressNameProvider.Name, "MultiToken" }, + { TokenConverterSmartContractAddressNameProvider.Name, "TokenConverter" }, + { TreasurySmartContractAddressNameProvider.Name, "Treasury" }, + { ConsensusSmartContractAddressNameProvider.Name, "AEDPoS" }, + { EconomicSmartContractAddressNameProvider.Name, "Economic" }, + { SmartContractConstants.CrossChainContractSystemHashName, "CrossChain" }, + { ReferendumSmartContractAddressNameProvider.Name, "Referendum" }, + { AssociationSmartContractAddressNameProvider.Name, "Association" }, + { TokenHolderSmartContractAddressNameProvider.Name, "TokenHolder" } + }; + + public Dictionary ContractAddresses; + + protected IBlockMiningService BlockMiningService => + Application.ServiceProvider.GetRequiredService(); + + protected ITestDataProvider TestDataProvider => + Application.ServiceProvider.GetRequiredService(); + + protected IBlockchainService BlockchainService => + Application.ServiceProvider.GetRequiredService(); + + protected ITransactionTraceProvider TransactionTraceProvider => + Application.ServiceProvider.GetRequiredService(); + + /// + /// Exception will throw if provided system contract name not contained as a Key of _systemContractKeyWords. + /// + /// + /// + protected async Task> DeploySystemSmartContracts( + IEnumerable systemContractNames) { - private readonly Dictionary _systemContractKeyWords = new Dictionary - { - {VoteSmartContractAddressNameProvider.Name, "Vote"}, - {ProfitSmartContractAddressNameProvider.Name, "Profit"}, - {ElectionSmartContractAddressNameProvider.Name, "Election"}, - {ParliamentSmartContractAddressNameProvider.Name, "Parliament"}, - {TokenSmartContractAddressNameProvider.Name, "MultiToken"}, - {TokenConverterSmartContractAddressNameProvider.Name, "TokenConverter"}, - {TreasurySmartContractAddressNameProvider.Name, "Treasury"}, - {ConsensusSmartContractAddressNameProvider.Name, "AEDPoS"}, - {EconomicSmartContractAddressNameProvider.Name, "Economic"}, - {SmartContractConstants.CrossChainContractSystemHashName, "CrossChain"}, - {ReferendumSmartContractAddressNameProvider.Name, "Referendum"}, - {AssociationSmartContractAddressNameProvider.Name, "Association"}, - {TokenHolderSmartContractAddressNameProvider.Name, "TokenHolder"} - }; - - protected IBlockMiningService BlockMiningService => - Application.ServiceProvider.GetRequiredService(); - - protected ITestDataProvider TestDataProvider => - Application.ServiceProvider.GetRequiredService(); - - protected IBlockchainService BlockchainService => - Application.ServiceProvider.GetRequiredService(); - - protected ITransactionTraceProvider TransactionTraceProvider => - Application.ServiceProvider.GetRequiredService(); - - public Dictionary ContractAddresses; - - /// - /// Exception will throw if provided system contract name not contained as a Key of _systemContractKeyWords. - /// - /// - /// - protected async Task> DeploySystemSmartContracts( - IEnumerable systemContractNames) - { - return await BlockMiningService.DeploySystemContractsAsync(systemContractNames.ToDictionary(n => n, - n => Codes.Single(c => c.Key.Contains(_systemContractKeyWords[n])).Value)); - } + return await BlockMiningService.DeploySystemContractsAsync(systemContractNames.ToDictionary(n => n, + n => Codes.Single(c => c.Key.Contains(_systemContractKeyWords[n])).Value)); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj b/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj index 2986679b78..96b70d61aa 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj +++ b/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj @@ -7,9 +7,9 @@ - - - + + + @@ -17,7 +17,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\acs0.proto @@ -46,10 +46,10 @@ - - + + - + \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningException.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningException.cs index 508ba9bfbb..79356e8c28 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningException.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningException.cs @@ -1,15 +1,14 @@ using System; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class BlockMiningException : Exception { - public class BlockMiningException : Exception + public BlockMiningException(string message) : base(message) + { + } + + public BlockMiningException(string message, Exception e) : base(message, e) { - public BlockMiningException(string message) : base(message) - { - } - - public BlockMiningException(string message, Exception e) : base(message, e) - { - } } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index d877791b91..87cc138f45 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -5,505 +5,446 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS3; using AElf.ContractDeployer; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.Genesis; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -namespace AElf.ContractTestKit.AEDPoSExtension -{ - public class BlockMiningService : IBlockMiningService - { - private readonly ITestDataProvider _testDataProvider; - private readonly IContractTesterFactory _contractTesterFactory; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITransactionResultService _transactionResultService; - - private Round _currentRound; +namespace AElf.ContractTestKit.AEDPoSExtension; - private Address _consensusContractAddress; - private Address _parliamentContractAddress; +public class BlockMiningService : IBlockMiningService +{ + private readonly List _acs3Stubs = new(); - private readonly List _contractStubs = - new List(); + private readonly IChainTypeProvider _chainTypeProvider; - private readonly List _acs3Stubs = - new List(); + private readonly List _contractStubs = new(); - private bool _isSystemContractsDeployed; + private readonly IContractTesterFactory _contractTesterFactory; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITestDataProvider _testDataProvider; + private readonly ITransactionResultService _transactionResultService; - private bool _isSkipped; + private Address _consensusContractAddress; - private readonly IChainTypeProvider _chainTypeProvider; + private Round _currentRound; - public BlockMiningService(IServiceProvider serviceProvider) - { - RegisterAssemblyResolveEvent(); - _contractTesterFactory = serviceProvider.GetRequiredService(); - _smartContractAddressService = serviceProvider.GetRequiredService(); - _testDataProvider = serviceProvider.GetRequiredService(); - _transactionResultService = serviceProvider.GetRequiredService(); - _chainTypeProvider = serviceProvider.GetRequiredService(); - } + private bool _isSkipped; - private static void RegisterAssemblyResolveEvent() - { - var currentDomain = AppDomain.CurrentDomain; - currentDomain.AssemblyResolve += OnAssemblyResolve; - } + private bool _isSystemContractsDeployed; + private Address _parliamentContractAddress; - private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) - { - var folderPath = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); - var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); - if (!File.Exists(assemblyPath)) return null; - var assembly = Assembly.LoadFrom(assemblyPath); - return assembly; - } + public BlockMiningService(IServiceProvider serviceProvider) + { + RegisterAssemblyResolveEvent(); + _contractTesterFactory = serviceProvider.GetRequiredService(); + _smartContractAddressService = serviceProvider.GetRequiredService(); + _testDataProvider = serviceProvider.GetRequiredService(); + _transactionResultService = serviceProvider.GetRequiredService(); + _chainTypeProvider = serviceProvider.GetRequiredService(); + } - /// - /// Only deploy provided contracts as system contract. - /// Should initial each contract after if necessary. - /// - /// - /// - /// - public async Task> DeploySystemContractsAsync(Dictionary nameToCode, - bool deployConsensusContract = true) + /// + /// Only deploy provided contracts as system contract. + /// Should initial each contract after if necessary. + /// + /// + /// + /// + public async Task> DeploySystemContractsAsync(Dictionary nameToCode, + bool deployConsensusContract = true) + { + var map = new Dictionary(); + var zeroContractStub = + _contractTesterFactory.Create( + _smartContractAddressService.GetZeroSmartContractAddress(), + MissionedECKeyPairs.InitialKeyPairs.First()); + if (!nameToCode.Keys.Contains(ConsensusSmartContractAddressNameProvider.Name) && deployConsensusContract) + nameToCode.Add(ConsensusSmartContractAddressNameProvider.Name, + ContractsDeployer.GetContractCodes().First().Value); + + foreach (var (name, code) in nameToCode) { - var map = new Dictionary(); - var zeroContractStub = - _contractTesterFactory.Create( - _smartContractAddressService.GetZeroSmartContractAddress(), - MissionedECKeyPairs.InitialKeyPairs.First()); - if (!nameToCode.Keys.Contains(ConsensusSmartContractAddressNameProvider.Name) && deployConsensusContract) + var address = (await zeroContractStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Name = name, + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(code) + })).Output; + if (address == null) { - nameToCode.Add(ConsensusSmartContractAddressNameProvider.Name, - ContractsDeployer.GetContractCodes().First().Value); + //throw new Exception($"Failed to deploy contract {name}"); } - foreach (var (name, code) in nameToCode) - { - var address = (await zeroContractStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Name = name, - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(code), - })).Output; - if (address == null) - { - //throw new Exception($"Failed to deploy contract {name}"); - } + map.Add(name, address); + if (name == ConsensusSmartContractAddressNameProvider.Name) _consensusContractAddress = address; - map.Add(name, address); - if (name == ConsensusSmartContractAddressNameProvider.Name) - { - _consensusContractAddress = address; - } + if (name == ParliamentSmartContractAddressNameProvider.Name) _parliamentContractAddress = address; + } - if (name == ParliamentSmartContractAddressNameProvider.Name) - { - _parliamentContractAddress = address; - } - } + _isSystemContractsDeployed = true; + var currentBlockTime = TimestampHelper.GetUtcNow().ToDateTime(); + _testDataProvider.SetBlockTime(currentBlockTime.ToTimestamp() + .AddMilliseconds(AEDPoSExtensionConstants.MiningInterval)); - _isSystemContractsDeployed = true; - var currentBlockTime = TimestampHelper.GetUtcNow().ToDateTime(); - _testDataProvider.SetBlockTime(currentBlockTime.ToTimestamp() - .AddMilliseconds(AEDPoSExtensionConstants.MiningInterval)); + InitialContractStubs(); + await InitialConsensus(currentBlockTime); - InitialContractStubs(); - await InitialConsensus(currentBlockTime); + return map; + } - return map; - } + public async Task MineBlockAsync(List transactions = null, bool withException = false) + { + if (!_isSystemContractsDeployed) return; + + if (transactions != null) await _testDataProvider.AddTransactionListAsync(transactions); + + var currentBlockTime = _testDataProvider.GetBlockTime(); - private void InitialContractStubs() { - foreach (var initialKeyPair in MissionedECKeyPairs.InitialKeyPairs.Concat(MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(18))) { - _contractStubs.Add(_contractTesterFactory.Create( - _consensusContractAddress, initialKeyPair)); + var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); + if (currentRound.RoundNumber == 0) + throw new InitializationFailedException("Can't find current round information."); } } - private async Task InitialConsensus(DateTime currentBlockTime) - { - // InitialAElfConsensusContract - { - var executionResult = await _contractStubs.First().InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - MinerIncreaseInterval = AEDPoSExtensionConstants.MinerIncreaseInterval, - PeriodSeconds = AEDPoSExtensionConstants.PeriodSeconds, - IsSideChain = _chainTypeProvider.IsSideChain - }); - if (executionResult.TransactionResult.Status != TransactionResultStatus.Mined) - { - throw new InitializationFailedException("Failed to execute InitialAElfConsensusContract.", - executionResult.TransactionResult.Error); - } - } + var maximumBlocksCount = (await _contractStubs.First().GetMaximumBlocksCount.CallAsync(new Empty())).Value; + var (contractStub, pubkey) = GetProperContractStub(currentBlockTime, maximumBlocksCount); + currentBlockTime = _testDataProvider.GetBlockTime(); - var initialMinerList = new MinerList - { - Pubkeys = {MissionedECKeyPairs.InitialKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }; - _currentRound = - initialMinerList.GenerateFirstRoundOfNewTerm(AEDPoSExtensionConstants.MiningInterval, - currentBlockTime); - _testDataProvider.SetBlockTime(currentBlockTime.ToTimestamp()); - - // FirstRound - { - var executionResult = await _contractStubs.First().FirstRound.SendAsync(_currentRound); - if (executionResult.TransactionResult.Status != TransactionResultStatus.Mined) - { - throw new InitializationFailedException("Failed to execute FirstRound.", - executionResult.TransactionResult.Error); - } - } - _testDataProvider.SetBlockTime(currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) - .ToTimestamp()); + { + var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); + if (currentRound.RoundNumber == 0) + throw new InitializationFailedException("Can't find current round information."); } - public async Task MineBlockAsync(List transactions = null, bool withException = false) + var triggerInformation = await GetConsensusTriggerInfoAsync(contractStub, pubkey); + var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue { - if (!_isSystemContractsDeployed) + Value = triggerInformation.ToByteString() + }); + await MineAsync(contractStub, consensusTransaction.Transactions.First(), withException); + _currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); + Debug.WriteLine($"Update current round information.{_currentRound}"); + if (!_isSkipped) + if (_currentRound.RealTimeMinersInformation.Any(i => i.Value.MissedTimeSlots != 0)) { - return; + var previousRound = await _contractStubs.First().GetPreviousRoundInformation.CallAsync(new Empty()); + throw new BlockMiningException( + $"Someone missed time slot.\n{_currentRound}\n{previousRound}\nCurrent block time: {currentBlockTime}"); } - if (transactions != null) - { - await _testDataProvider.AddTransactionListAsync(transactions); - } + _testDataProvider.SetBlockTime( + consensusTransaction.Transactions.First().MethodName == + nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm) + ? currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) + : currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval)); - var currentBlockTime = _testDataProvider.GetBlockTime(); + await _testDataProvider.ResetAsync(); - { - { - var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); - if (currentRound.RoundNumber == 0) - { - throw new InitializationFailedException("Can't find current round information."); - } - } - } + _isSkipped = false; + } - var maximumBlocksCount = (await _contractStubs.First().GetMaximumBlocksCount.CallAsync(new Empty())).Value; - var (contractStub, pubkey) = GetProperContractStub(currentBlockTime, maximumBlocksCount); - currentBlockTime = _testDataProvider.GetBlockTime(); + public async Task MineBlockToNextRoundAsync() + { + var consensusStub = _contractTesterFactory.Create( + _consensusContractAddress, MissionedECKeyPairs.InitialKeyPairs.First()); + var startRoundNumber = (await consensusStub.GetCurrentRoundNumber.CallAsync(new Empty())).Value; + var currentRoundNumber = startRoundNumber; + while (currentRoundNumber == startRoundNumber) + { + await MineBlockAsync(); + currentRoundNumber = (await consensusStub.GetCurrentRoundNumber.CallAsync(new Empty())).Value; + } - { - var currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); - if (currentRound.RoundNumber == 0) - { - throw new InitializationFailedException("Can't find current round information."); - } - } + return currentRoundNumber; + } - var triggerInformation = await GetConsensusTriggerInfoAsync(contractStub, pubkey); - var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue - { - Value = triggerInformation.ToByteString() - }); - await MineAsync(contractStub, consensusTransaction.Transactions.First(), withException); - _currentRound = await _contractStubs.First().GetCurrentRoundInformation.CallAsync(new Empty()); - Debug.WriteLine($"Update current round information.{_currentRound}"); - if (!_isSkipped) - { - if (_currentRound.RealTimeMinersInformation.Any(i => i.Value.MissedTimeSlots != 0)) - { - var previousRound = await _contractStubs.First().GetPreviousRoundInformation.CallAsync(new Empty()); - throw new BlockMiningException( - $"Someone missed time slot.\n{_currentRound}\n{previousRound}\nCurrent block time: {currentBlockTime}"); - } - } + public async Task MineBlockToNextTermAsync() + { + var consensusStub = _contractTesterFactory.Create( + _consensusContractAddress, MissionedECKeyPairs.InitialKeyPairs.First()); + var startTermNumber = (await consensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; + var currentTermNumber = startTermNumber; + while (currentTermNumber == startTermNumber) + { + await MineBlockAsync(); + currentTermNumber = (await consensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; + } - _testDataProvider.SetBlockTime( - consensusTransaction.Transactions.First().MethodName == - nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm) - ? currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) - : currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval)); + return currentTermNumber; + } - await _testDataProvider.ResetAsync(); + public async Task MineBlockAsync(long targetHeight) + { + var startHeight = await _testDataProvider.GetCurrentBlockHeight(); + if (targetHeight <= startHeight) return; - _isSkipped = false; + var currentHeight = startHeight; + while (currentHeight <= targetHeight) + { + await MineBlockAsync(); + currentHeight = await _testDataProvider.GetCurrentBlockHeight(); } + } - public async Task MineBlockToNextRoundAsync() - { - var consensusStub = _contractTesterFactory.Create( - _consensusContractAddress, MissionedECKeyPairs.InitialKeyPairs.First()); - var startRoundNumber = (await consensusStub.GetCurrentRoundNumber.CallAsync(new Empty())).Value; - var currentRoundNumber = startRoundNumber; - while (currentRoundNumber == startRoundNumber) - { - await MineBlockAsync(); - currentRoundNumber = (await consensusStub.GetCurrentRoundNumber.CallAsync(new Empty())).Value; - } + /// + /// Skip a certain time for missing some blocks deliberately. + /// + /// + public void SkipTime(int seconds) + { + var timestamp = _testDataProvider.GetBlockTime(); + _testDataProvider.SetBlockTime(timestamp.AddSeconds(seconds)); + _isSkipped = true; + } - return currentRoundNumber; - } + private static void RegisterAssemblyResolveEvent() + { + var currentDomain = AppDomain.CurrentDomain; + currentDomain.AssemblyResolve += OnAssemblyResolve; + } - public async Task MineBlockToNextTermAsync() - { - var consensusStub = _contractTesterFactory.Create( - _consensusContractAddress, MissionedECKeyPairs.InitialKeyPairs.First()); - var startTermNumber = (await consensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; - var currentTermNumber = startTermNumber; - while (currentTermNumber == startTermNumber) - { - await MineBlockAsync(); - currentTermNumber = (await consensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; - } + private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + { + var folderPath = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); + var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); + if (!File.Exists(assemblyPath)) return null; + var assembly = Assembly.LoadFrom(assemblyPath); + return assembly; + } - return currentTermNumber; - } + private void InitialContractStubs() + { + foreach (var initialKeyPair in MissionedECKeyPairs.InitialKeyPairs.Concat( + MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(18))) + _contractStubs.Add(_contractTesterFactory.Create( + _consensusContractAddress, initialKeyPair)); + } - public async Task MineBlockAsync(long targetHeight) + private async Task InitialConsensus(DateTime currentBlockTime) + { + // InitialAElfConsensusContract { - var startHeight = await _testDataProvider.GetCurrentBlockHeight(); - if (targetHeight <= startHeight) - { - return; - } - - var currentHeight = startHeight; - while (currentHeight <= targetHeight) - { - await MineBlockAsync(); - currentHeight = await _testDataProvider.GetCurrentBlockHeight(); - } + var executionResult = await _contractStubs.First().InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput + { + MinerIncreaseInterval = AEDPoSExtensionConstants.MinerIncreaseInterval, + PeriodSeconds = AEDPoSExtensionConstants.PeriodSeconds, + IsSideChain = _chainTypeProvider.IsSideChain + }); + if (executionResult.TransactionResult.Status != TransactionResultStatus.Mined) + throw new InitializationFailedException("Failed to execute InitialAElfConsensusContract.", + executionResult.TransactionResult.Error); } - /// - /// Skip a certain time for missing some blocks deliberately. - /// - /// - public void SkipTime(int seconds) + var initialMinerList = new MinerList { - var timestamp = _testDataProvider.GetBlockTime(); - _testDataProvider.SetBlockTime(timestamp.AddSeconds(seconds)); - _isSkipped = true; + Pubkeys = { MissionedECKeyPairs.InitialKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }; + _currentRound = + initialMinerList.GenerateFirstRoundOfNewTerm(AEDPoSExtensionConstants.MiningInterval, + currentBlockTime); + _testDataProvider.SetBlockTime(currentBlockTime.ToTimestamp()); + + // FirstRound + { + var executionResult = await _contractStubs.First().FirstRound.SendAsync(_currentRound); + if (executionResult.TransactionResult.Status != TransactionResultStatus.Mined) + throw new InitializationFailedException("Failed to execute FirstRound.", + executionResult.TransactionResult.Error); } + _testDataProvider.SetBlockTime(currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) + .ToTimestamp()); + } - private async Task MineAsync(AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, - Transaction transaction, bool withException = false) + private async Task MineAsync(AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, + Transaction transaction, bool withException = false) + { + switch (transaction.MethodName) { - switch (transaction.MethodName) - { - case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.UpdateTinyBlockInformation): - if (withException) - { - await contractStub.UpdateTinyBlockInformation.SendWithExceptionAsync( - TinyBlockInput.Parser.ParseFrom(transaction.Params)); - } - else - { - await contractStub.UpdateTinyBlockInformation.SendAsync( - TinyBlockInput.Parser.ParseFrom(transaction.Params)); - } - - break; - case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.UpdateValue): - if (withException) - { - await contractStub.UpdateValue.SendWithExceptionAsync( - UpdateValueInput.Parser.ParseFrom(transaction.Params)); - } - else - { - await contractStub.UpdateValue.SendAsync(UpdateValueInput.Parser.ParseFrom(transaction.Params)); - } - - break; - case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextRound): - if (withException) - { - await contractStub.NextRound.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); - } - else - { - await contractStub.NextRound.SendAsync(Round.Parser.ParseFrom(transaction.Params)); - } - - break; - case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm): - if (withException) - { - await contractStub.NextTerm.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); - } - else - { - await contractStub.NextTerm.SendAsync(Round.Parser.ParseFrom(transaction.Params)); - } - - break; - } + case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.UpdateTinyBlockInformation): + if (withException) + await contractStub.UpdateTinyBlockInformation.SendWithExceptionAsync( + TinyBlockInput.Parser.ParseFrom(transaction.Params)); + else + await contractStub.UpdateTinyBlockInformation.SendAsync( + TinyBlockInput.Parser.ParseFrom(transaction.Params)); + + break; + case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.UpdateValue): + if (withException) + await contractStub.UpdateValue.SendWithExceptionAsync( + UpdateValueInput.Parser.ParseFrom(transaction.Params)); + else + await contractStub.UpdateValue.SendAsync(UpdateValueInput.Parser.ParseFrom(transaction.Params)); + + break; + case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextRound): + if (withException) + await contractStub.NextRound.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); + else + await contractStub.NextRound.SendAsync(Round.Parser.ParseFrom(transaction.Params)); + + break; + case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm): + if (withException) + await contractStub.NextTerm.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); + else + await contractStub.NextTerm.SendAsync(Round.Parser.ParseFrom(transaction.Params)); + + break; } + } - private (AEDPoSContractImplContainer.AEDPoSContractImplStub, BytesValue) GetProperContractStub( - Timestamp currentBlockTime, int maximumBlocksCount) + private (AEDPoSContractImplContainer.AEDPoSContractImplStub, BytesValue) GetProperContractStub( + Timestamp currentBlockTime, int maximumBlocksCount) + { + try { - try - { - if (_currentRound.RoundNumber == 0) - { - throw new BlockMiningException("Invalid round information."); - } + if (_currentRound.RoundNumber == 0) throw new BlockMiningException("Invalid round information."); - var roundStartTime = _currentRound.RealTimeMinersInformation.Single(i => i.Value.Order == 1).Value - .ExpectedMiningTime; + var roundStartTime = _currentRound.RealTimeMinersInformation.Single(i => i.Value.Order == 1).Value + .ExpectedMiningTime; - var roundEndTime = _currentRound.RealTimeMinersInformation - .Single(i => i.Value.Order == _currentRound.RealTimeMinersInformation.Count).Value - .ExpectedMiningTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval); - if (currentBlockTime > roundEndTime) - { - throw new BlockMiningException("Failed to find proper contract stub."); - } + var roundEndTime = _currentRound.RealTimeMinersInformation + .Single(i => i.Value.Order == _currentRound.RealTimeMinersInformation.Count).Value + .ExpectedMiningTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval); + if (currentBlockTime > roundEndTime) throw new BlockMiningException("Failed to find proper contract stub."); - var ebp = _currentRound.RealTimeMinersInformation.Values.FirstOrDefault(i => - i.Pubkey == _currentRound.ExtraBlockProducerOfPreviousRound); - if (ebp != null && _currentRound.RealTimeMinersInformation.Values.All(i => i.OutValue == null) && - currentBlockTime < roundStartTime && ebp.ActualMiningTimes.Count + 1 <= maximumBlocksCount) + var ebp = _currentRound.RealTimeMinersInformation.Values.FirstOrDefault(i => + i.Pubkey == _currentRound.ExtraBlockProducerOfPreviousRound); + if (ebp != null && _currentRound.RealTimeMinersInformation.Values.All(i => i.OutValue == null) && + currentBlockTime < roundStartTime && ebp.ActualMiningTimes.Count + 1 <= maximumBlocksCount) + { + Debug.WriteLine("Tiny block before new round."); + return ProperContractStub(ebp); + } + + foreach (var minerInRound in _currentRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .ToList()) + { + if (minerInRound.ExpectedMiningTime <= currentBlockTime && currentBlockTime < + minerInRound.ExpectedMiningTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) && + (minerInRound.ActualMiningTimes.Count + 1 <= maximumBlocksCount || + (minerInRound.Pubkey == _currentRound.ExtraBlockProducerOfPreviousRound && + minerInRound.ActualMiningTimes.Count + 2 <= maximumBlocksCount * 2))) { - Debug.WriteLine("Tiny block before new round."); - return ProperContractStub(ebp); + Debug.WriteLine("Normal block or tiny block."); + return ProperContractStub(minerInRound); } - foreach (var minerInRound in _currentRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .ToList()) + var minersCount = _currentRound.RealTimeMinersInformation.Count; + if (minerInRound.IsExtraBlockProducer && + _currentRound.RealTimeMinersInformation.Values.Count(m => m.OutValue != null) == minersCount) { - if (minerInRound.ExpectedMiningTime <= currentBlockTime && currentBlockTime < - minerInRound.ExpectedMiningTime.AddMilliseconds(AEDPoSExtensionConstants.MiningInterval) && - (minerInRound.ActualMiningTimes.Count + 1 <= maximumBlocksCount || - minerInRound.Pubkey == _currentRound.ExtraBlockProducerOfPreviousRound && - minerInRound.ActualMiningTimes.Count + 2 <= maximumBlocksCount * 2)) - { - Debug.WriteLine("Normal block or tiny block."); - return ProperContractStub(minerInRound); - } - - var minersCount = _currentRound.RealTimeMinersInformation.Count; - if (minerInRound.IsExtraBlockProducer && - _currentRound.RealTimeMinersInformation.Values.Count(m => m.OutValue != null) == minersCount) - { - Debug.WriteLine("End of current round."); - return ProperContractStub(minerInRound); - } + Debug.WriteLine("End of current round."); + return ProperContractStub(minerInRound); } } - catch (Exception e) - { - throw new BlockMiningException("Failed to find proper contract stub.", e); - } - - _testDataProvider.SetBlockTime(AEDPoSExtensionConstants.ActualMiningInterval); - Debug.WriteLine("Move forward time."); - return GetProperContractStub( - currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval), maximumBlocksCount); } - - private (AEDPoSContractImplContainer.AEDPoSContractImplStub, BytesValue) ProperContractStub( - MinerInRound minerInRound) + catch (Exception e) { - var pubkey = ByteArrayHelper.HexStringToByteArray(minerInRound.Pubkey); - var keyPair = SampleAccount.Accounts.First(a => a.KeyPair.PublicKey.BytesEqual(pubkey)).KeyPair; - _testDataProvider.SetKeyPair(keyPair); - Debug.WriteLine($"Chosen miner: {keyPair.PublicKey.ToHex()}"); - return (_contractTesterFactory.Create( - _consensusContractAddress, keyPair), new BytesValue {Value = ByteString.CopyFrom(pubkey)}); + throw new BlockMiningException("Failed to find proper contract stub.", e); } - private async Task GetConsensusTriggerInfoAsync( - AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, BytesValue pubkey) - { - var command = await contractStub.GetConsensusCommand.CallAsync(pubkey); - var hint = AElfConsensusHint.Parser.ParseFrom(command.Hint); - var triggerInformation = new AElfConsensusTriggerInformation - { - Behaviour = hint.Behaviour, - // It doesn't matter for testing. - InValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), - PreviousInValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), - Pubkey = pubkey.Value - }; - - var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue - { - Value = triggerInformation.ToByteString() - }); - var consensusHeaderInformation = new AElfConsensusHeaderInformation(); - consensusHeaderInformation.MergeFrom(consensusExtraData.Value); - Debug.WriteLine($"Current header information: {consensusHeaderInformation}"); - - // Validate consensus extra data. - { - var validationResult = - await _contractStubs.First().ValidateConsensusBeforeExecution.CallAsync(consensusExtraData); - if (!validationResult.Success) - { - throw new Exception($"Consensus extra data validation failed: {validationResult.Message}"); - } - } + _testDataProvider.SetBlockTime(AEDPoSExtensionConstants.ActualMiningInterval); + Debug.WriteLine("Move forward time."); + return GetProperContractStub( + currentBlockTime.AddMilliseconds(AEDPoSExtensionConstants.ActualMiningInterval), maximumBlocksCount); + } - return triggerInformation; - } + private (AEDPoSContractImplContainer.AEDPoSContractImplStub, BytesValue) ProperContractStub( + MinerInRound minerInRound) + { + var pubkey = ByteArrayHelper.HexStringToByteArray(minerInRound.Pubkey); + var keyPair = SampleAccount.Accounts.First(a => a.KeyPair.PublicKey.BytesEqual(pubkey)).KeyPair; + _testDataProvider.SetKeyPair(keyPair); + Debug.WriteLine($"Chosen miner: {keyPair.PublicKey.ToHex()}"); + return (_contractTesterFactory.Create( + _consensusContractAddress, keyPair), new BytesValue { Value = ByteString.CopyFrom(pubkey) }); } - internal static class MinerListExtension + private async Task GetConsensusTriggerInfoAsync( + AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, BytesValue pubkey) { - internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, - DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var command = await contractStub.GetConsensusCommand.CallAsync(pubkey); + var hint = AElfConsensusHint.Parser.ParseFrom(command.Hint); + var triggerInformation = new AElfConsensusTriggerInformation + { + Behaviour = hint.Behaviour, + // It doesn't matter for testing. + InValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), + PreviousInValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), + Pubkey = pubkey.Value + }; + + var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue { - var sortedMiners = - (from obj in miners.Pubkeys.Distinct() - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); + Value = triggerInformation.ToByteString() + }); + var consensusHeaderInformation = new AElfConsensusHeaderInformation(); + consensusHeaderInformation.MergeFrom(consensusExtraData.Value); + Debug.WriteLine($"Current header information: {consensusHeaderInformation}"); - var round = new Round(); + // Validate consensus extra data. + { + var validationResult = + await _contractStubs.First().ValidateConsensusBeforeExecution.CallAsync(consensusExtraData); + if (!validationResult.Success) + throw new Exception($"Consensus extra data validation failed: {validationResult.Message}"); + } - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); + return triggerInformation; + } +} - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } +internal static class MinerListExtension +{ + internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, + DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = + (from obj in miners.Pubkeys.Distinct() + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval).ToTimestamp(); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; + var round = new Round(); - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } + for (var i = 0; i < sortedMiners.Count; i++) + { + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval).ToTimestamp(); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; - return round; + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactAttribute.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactAttribute.cs index 9c853c8c98..0a04ecdddc 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactAttribute.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactAttribute.cs @@ -2,13 +2,12 @@ using Xunit; using Xunit.Sdk; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +[XunitTestCaseDiscoverer("AElf.ContractTestKit.AEDPoSExtension.ConsensusFactDiscoverer", + "AElf.ContractTestKit.AEDPoSExtension")] +[AttributeUsage(AttributeTargets.Method)] +public class ConsensusFactAttribute : FactAttribute { - [XunitTestCaseDiscoverer("AElf.ContractTestKit.AEDPoSExtension.ConsensusFactDiscoverer", - "AElf.ContractTestKit.AEDPoSExtension")] - [AttributeUsage(AttributeTargets.Method)] - public class ConsensusFactAttribute : FactAttribute - { - public virtual bool IsSideChain { get; set; } - } + public virtual bool IsSideChain { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactDiscoverer.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactDiscoverer.cs index 1693ec43e3..53877d6564 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactDiscoverer.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusFactDiscoverer.cs @@ -2,27 +2,26 @@ using Xunit.Abstractions; using Xunit.Sdk; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class ConsensusFactDiscoverer : FactDiscoverer { - public class ConsensusFactDiscoverer : FactDiscoverer - { - private readonly IChainTypeProvider _chainTypeProvider; - private readonly IMessageSink _diagnosticMessageSink; + private readonly IChainTypeProvider _chainTypeProvider; + private readonly IMessageSink _diagnosticMessageSink; - public ConsensusFactDiscoverer(IMessageSink diagnosticMessageSink, IChainTypeProvider chainTypeProvider) : base( - diagnosticMessageSink) - { - _chainTypeProvider = chainTypeProvider; - _diagnosticMessageSink = diagnosticMessageSink; - } + public ConsensusFactDiscoverer(IMessageSink diagnosticMessageSink, IChainTypeProvider chainTypeProvider) : base( + diagnosticMessageSink) + { + _chainTypeProvider = chainTypeProvider; + _diagnosticMessageSink = diagnosticMessageSink; + } - public override IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, - ITestMethod testMethod, IAttributeInfo factAttribute) - { - var isSideChain = factAttribute.GetNamedArgument("IsSideChain"); - _chainTypeProvider.IsSideChain = isSideChain; - yield return new ConsensusTestCase(_diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), - testMethod, isSideChain); - } + public override IEnumerable Discover(ITestFrameworkDiscoveryOptions discoveryOptions, + ITestMethod testMethod, IAttributeInfo factAttribute) + { + var isSideChain = factAttribute.GetNamedArgument("IsSideChain"); + _chainTypeProvider.IsSideChain = isSideChain; + yield return new ConsensusTestCase(_diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), + testMethod, isSideChain); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusTestCase.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusTestCase.cs index fd1c2388fb..1749429f88 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusTestCase.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ConsensusTestCase.cs @@ -3,39 +3,38 @@ using Xunit.Abstractions; using Xunit.Sdk; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +[Serializable] +public class ConsensusTestCase : XunitTestCase { - [Serializable] - public class ConsensusTestCase : XunitTestCase - { - private bool _isSideChain; + private bool _isSideChain; - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("Called by the de-serializer", true)] - public ConsensusTestCase() - { - } + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Called by the de-serializer", true)] + public ConsensusTestCase() + { + } - public ConsensusTestCase( - IMessageSink diagnosticMessageSink, - TestMethodDisplay testMethodDisplay, - ITestMethod testMethod, - bool isSideChain) - : base(diagnosticMessageSink, testMethodDisplay, TestMethodDisplayOptions.All, testMethod) - { - _isSideChain = isSideChain; - } + public ConsensusTestCase( + IMessageSink diagnosticMessageSink, + TestMethodDisplay testMethodDisplay, + ITestMethod testMethod, + bool isSideChain) + : base(diagnosticMessageSink, testMethodDisplay, TestMethodDisplayOptions.All, testMethod) + { + _isSideChain = isSideChain; + } - public override void Serialize(IXunitSerializationInfo data) - { - base.Serialize(data); - data.AddValue("IsSideChain", _isSideChain); - } + public override void Serialize(IXunitSerializationInfo data) + { + base.Serialize(data); + data.AddValue("IsSideChain", _isSideChain); + } - public override void Deserialize(IXunitSerializationInfo data) - { - base.Deserialize(data); - _isSideChain = data.GetValue("IsSideChain"); - } + public override void Deserialize(IXunitSerializationInfo data) + { + base.Deserialize(data); + _isSideChain = data.GetValue("IsSideChain"); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ContractTestAEDPoSExtensionModule.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ContractTestAEDPoSExtensionModule.cs index 6a7e9bcd2d..4452054c2e 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ContractTestAEDPoSExtensionModule.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ContractTestAEDPoSExtensionModule.cs @@ -7,7 +7,6 @@ using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; -using AElf.Sdk.CSharp; using AElf.Types; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -16,66 +15,65 @@ using Volo.Abp.Modularity; // ReSharper disable InconsistentNaming -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class ContractTestAEDPoSExtensionModule : ContractTestAEDPoSExtensionModule + where TSelf : ContractTestAEDPoSExtensionModule { - public class ContractTestAEDPoSExtensionModule : ContractTestAEDPoSExtensionModule - where TSelf : ContractTestAEDPoSExtensionModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - base.ConfigureServices(context); - } + context.Services.AddAssemblyOf(); + base.ConfigureServices(context); } +} - [DependsOn( - typeof(ContractTestWithExecutionPluginModule) - )] - public class ContractTestAEDPoSExtensionModule : ContractTestModule +[DependsOn( + typeof(ContractTestWithExecutionPluginModule) +)] +public class ContractTestAEDPoSExtensionModule : ContractTestModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services - .AddSingleton(); - context.Services.RemoveAll(); - context.Services.RemoveAll(); - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services + .AddSingleton(); + context.Services.RemoveAll(); + context.Services.RemoveAll(); + context.Services + .AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); - context.Services.RemoveAll(); - context.Services.AddTransient(provider => - { - var mockBridgeContext = - new Mock( - context.Services.GetRequiredServiceLazy().Value, - context.Services.GetRequiredServiceLazy().Value, - context.Services.GetRequiredServiceLazy().Value, - context.Services - .GetRequiredServiceLazy>().Value) - .As(); - mockBridgeContext.CallBase = true; - mockBridgeContext.Setup(c => - c.GetContractAddressByName(It.IsIn(HashHelper.ComputeFrom("AElf.ContractNames.CrossChain") - .ToStorageKey()))) - .Returns(Address.FromPublicKey(SampleAccount.Accounts.Last().KeyPair.PublicKey)); - return mockBridgeContext.Object; - }); + context.Services.RemoveAll(); + context.Services.AddTransient(provider => + { + var mockBridgeContext = + new Mock( + context.Services.GetRequiredServiceLazy().Value, + context.Services.GetRequiredServiceLazy().Value, + context.Services.GetRequiredServiceLazy().Value, + context.Services + .GetRequiredServiceLazy>().Value) + .As(); + mockBridgeContext.CallBase = true; + mockBridgeContext.Setup(c => + c.GetContractAddressByName(It.IsIn(HashHelper.ComputeFrom("AElf.ContractNames.CrossChain") + .ToStorageKey()))) + .Returns(Address.FromPublicKey(SampleAccount.Accounts.Last().KeyPair.PublicKey)); + return mockBridgeContext.Object; + }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/IBlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/IBlockMiningService.cs index 3840273b57..ce0d638874 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/IBlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/IBlockMiningService.cs @@ -2,15 +2,16 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public interface IBlockMiningService { - public interface IBlockMiningService - { - Task> DeploySystemContractsAsync(Dictionary nameToCode, bool deployConsensusContract = true); - Task MineBlockAsync(List transactions = null, bool withException = false); - Task MineBlockToNextRoundAsync(); - Task MineBlockToNextTermAsync(); - Task MineBlockAsync(long targetHeight); - void SkipTime(int seconds); - } + Task> DeploySystemContractsAsync(Dictionary nameToCode, + bool deployConsensusContract = true); + + Task MineBlockAsync(List transactions = null, bool withException = false); + Task MineBlockToNextRoundAsync(); + Task MineBlockToNextTermAsync(); + Task MineBlockAsync(long targetHeight); + void SkipTime(int seconds); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/IChainTypeProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/IChainTypeProvider.cs index 2d4c8d6832..5eb5d7b2fb 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/IChainTypeProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/IChainTypeProvider.cs @@ -1,12 +1,11 @@ -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public interface IChainTypeProvider { - public interface IChainTypeProvider - { - bool IsSideChain { get; set; } - } + bool IsSideChain { get; set; } +} - public class ChainTypeProvider : IChainTypeProvider - { - public bool IsSideChain { get; set; } = false; - } +public class ChainTypeProvider : IChainTypeProvider +{ + public bool IsSideChain { get; set; } = false; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ITestDataProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ITestDataProvider.cs index 7243d55b49..96cd733c19 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ITestDataProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ITestDataProvider.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; using AElf.Kernel.Account.Infrastructure; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public interface ITestDataProvider : IBlockTimeProvider, ITransactionListProvider, + IAElfAsymmetricCipherKeyPairProvider { - public interface ITestDataProvider : IBlockTimeProvider, ITransactionListProvider, - IAElfAsymmetricCipherKeyPairProvider - { - Task GetCurrentBlockHeight(); - } + Task GetCurrentBlockHeight(); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionListProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionListProvider.cs index 02ca45553b..1dd816e829 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionListProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionListProvider.cs @@ -2,12 +2,11 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public interface ITransactionListProvider { - public interface ITransactionListProvider - { - Task AddTransactionListAsync(List transactions); - Task> GetTransactionListAsync(); - Task ResetAsync(); - } + Task AddTransactionListAsync(List transactions); + Task> GetTransactionListAsync(); + Task ResetAsync(); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionTraceProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionTraceProvider.cs index b5fdd40b81..aeb104626a 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionTraceProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ITransactionTraceProvider.cs @@ -1,14 +1,13 @@ using AElf.Kernel; using AElf.Types; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +/// +/// This interface is just for testing, which means we need not consider parallel executing. +/// +public interface ITransactionTraceProvider { - /// - /// This interface is just for testing, which means we need not consider parallel executing. - /// - public interface ITransactionTraceProvider - { - void AddTransactionTrace(TransactionTrace trace); - TransactionTrace GetTransactionTrace(Hash transactionId); - } + void AddTransactionTrace(TransactionTrace trace); + TransactionTrace GetTransactionTrace(Hash transactionId); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/InitializationFailedException.cs b/src/AElf.ContractTestKit.AEDPoSExtension/InitializationFailedException.cs index bee98fbd80..9e1cc3638d 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/InitializationFailedException.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/InitializationFailedException.cs @@ -1,15 +1,14 @@ using System; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class InitializationFailedException : Exception { - public class InitializationFailedException : Exception + public InitializationFailedException(string message) : base(message) { - public InitializationFailedException(string message) : base(message) - { - } + } - public InitializationFailedException(string message, string error) : base($"{message} {error}") - { - } + public InitializationFailedException(string message, string error) : base($"{message} {error}") + { } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/MissionedECKeyPairs.cs b/src/AElf.ContractTestKit.AEDPoSExtension/MissionedECKeyPairs.cs index 7ee4eee5ca..6692e61182 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/MissionedECKeyPairs.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/MissionedECKeyPairs.cs @@ -3,31 +3,30 @@ using System.Linq; using AElf.Cryptography.ECDSA; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +[SuppressMessage("ReSharper", "InconsistentNaming")] +public static class MissionedECKeyPairs { - [SuppressMessage("ReSharper", "InconsistentNaming")] - public static class MissionedECKeyPairs - { - public static readonly IEnumerable InitialKeyPairs = - SampleAccount.Accounts - .Take(AEDPoSExtensionConstants.InitialKeyPairCount).Select(a => a.KeyPair); + public static readonly IEnumerable InitialKeyPairs = + SampleAccount.Accounts + .Take(AEDPoSExtensionConstants.InitialKeyPairCount).Select(a => a.KeyPair); + + public static readonly IEnumerable CoreDataCenterKeyPairs = + SampleAccount.Accounts + .Skip(AEDPoSExtensionConstants.InitialKeyPairCount) + .Take(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount).Select(a => a.KeyPair); - public static readonly IEnumerable CoreDataCenterKeyPairs = - SampleAccount.Accounts - .Skip(AEDPoSExtensionConstants.InitialKeyPairCount) - .Take(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount).Select(a => a.KeyPair); + public static readonly IEnumerable ValidationDataCenterKeyPairs = + SampleAccount.Accounts + .Skip(AEDPoSExtensionConstants.InitialKeyPairCount + + AEDPoSExtensionConstants.CoreDataCenterKeyPairCount) + .Take(AEDPoSExtensionConstants.ValidationDataCenterKeyPairCount).Select(a => a.KeyPair); - public static readonly IEnumerable ValidationDataCenterKeyPairs = - SampleAccount.Accounts - .Skip(AEDPoSExtensionConstants.InitialKeyPairCount + - AEDPoSExtensionConstants.CoreDataCenterKeyPairCount) - .Take(AEDPoSExtensionConstants.ValidationDataCenterKeyPairCount).Select(a => a.KeyPair); - - public static readonly IEnumerable CitizenKeyPairs = - SampleAccount.Accounts - .Skip(AEDPoSExtensionConstants.InitialKeyPairCount + - AEDPoSExtensionConstants.CoreDataCenterKeyPairCount + - AEDPoSExtensionConstants.ValidationDataCenterKeyPairCount) - .Take(AEDPoSExtensionConstants.CitizenKeyPairsCount).Select(a => a.KeyPair); - } + public static readonly IEnumerable CitizenKeyPairs = + SampleAccount.Accounts + .Skip(AEDPoSExtensionConstants.InitialKeyPairCount + + AEDPoSExtensionConstants.CoreDataCenterKeyPairCount + + AEDPoSExtensionConstants.ValidationDataCenterKeyPairCount) + .Take(AEDPoSExtensionConstants.CitizenKeyPairsCount).Select(a => a.KeyPair); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/ProvideTransactionListPostExecutionPlugin.cs b/src/AElf.ContractTestKit.AEDPoSExtension/ProvideTransactionListPostExecutionPlugin.cs index 8a271d1aa3..cfd430ca03 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/ProvideTransactionListPostExecutionPlugin.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/ProvideTransactionListPostExecutionPlugin.cs @@ -7,41 +7,40 @@ using AElf.Types; using Google.Protobuf.Reflection; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class ProvideTransactionListPostExecutionPlugin : IPostExecutionPlugin { - public class ProvideTransactionListPostExecutionPlugin : IPostExecutionPlugin - { - private readonly ITransactionListProvider _transactionListProvider; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionListProvider _transactionListProvider; - public ProvideTransactionListPostExecutionPlugin(ITransactionListProvider transactionListProvider, - ISmartContractAddressService smartContractAddressService) - { - _transactionListProvider = transactionListProvider; - _smartContractAddressService = smartContractAddressService; - } + public ProvideTransactionListPostExecutionPlugin(ITransactionListProvider transactionListProvider, + ISmartContractAddressService smartContractAddressService) + { + _transactionListProvider = transactionListProvider; + _smartContractAddressService = smartContractAddressService; + } - public async Task> GetPostTransactionsAsync( - IReadOnlyList descriptors, - ITransactionContext transactionContext) - { - return transactionContext.Transaction.To == - await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1, - StateCache = transactionContext.StateCache - }, ConsensusSmartContractAddressNameProvider.StringName) && - new List - { - "FirstRound", - "UpdateValue", - "UpdateTinyBlockInformation", - "NextRound", - "NextTerm" - }.Contains(transactionContext.Transaction.MethodName) - ? await _transactionListProvider.GetTransactionListAsync() - : new List(); - } + public async Task> GetPostTransactionsAsync( + IReadOnlyList descriptors, + ITransactionContext transactionContext) + { + return transactionContext.Transaction.To == + await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext + { + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1, + StateCache = transactionContext.StateCache + }, ConsensusSmartContractAddressNameProvider.StringName) && + new List + { + "FirstRound", + "UpdateValue", + "UpdateTinyBlockInformation", + "NextRound", + "NextTerm" + }.Contains(transactionContext.Transaction.MethodName) + ? await _transactionListProvider.GetTransactionListAsync() + : new List(); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/TestDataProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/TestDataProvider.cs index 72c35b121f..a49cdeb8d9 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/TestDataProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/TestDataProvider.cs @@ -6,67 +6,66 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class TestDataProvider : ITestDataProvider { - public class TestDataProvider : ITestDataProvider - { - private readonly IBlockTimeProvider _blockTimeProvider; - private readonly ITransactionListProvider _transactionListProvider; - private readonly IAElfAsymmetricCipherKeyPairProvider _keyPairProvider; - private readonly IBlockchainService _blockchainService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockTimeProvider _blockTimeProvider; + private readonly IAElfAsymmetricCipherKeyPairProvider _keyPairProvider; + private readonly ITransactionListProvider _transactionListProvider; - public TestDataProvider(IBlockTimeProvider blockTimeProvider, ITransactionListProvider transactionListProvider, - IAElfAsymmetricCipherKeyPairProvider keyPairProvider, IBlockchainService blockchainService) - { - _blockTimeProvider = blockTimeProvider; - _transactionListProvider = transactionListProvider; - _keyPairProvider = keyPairProvider; - _blockchainService = blockchainService; - } + public TestDataProvider(IBlockTimeProvider blockTimeProvider, ITransactionListProvider transactionListProvider, + IAElfAsymmetricCipherKeyPairProvider keyPairProvider, IBlockchainService blockchainService) + { + _blockTimeProvider = blockTimeProvider; + _transactionListProvider = transactionListProvider; + _keyPairProvider = keyPairProvider; + _blockchainService = blockchainService; + } - public Timestamp GetBlockTime() - { - return _blockTimeProvider.GetBlockTime(); - } + public Timestamp GetBlockTime() + { + return _blockTimeProvider.GetBlockTime(); + } - public void SetBlockTime(Timestamp blockTime) - { - _blockTimeProvider.SetBlockTime(blockTime); - } + public void SetBlockTime(Timestamp blockTime) + { + _blockTimeProvider.SetBlockTime(blockTime); + } - public void SetBlockTime(int offsetMilliseconds) - { - _blockTimeProvider.SetBlockTime(offsetMilliseconds); - } + public void SetBlockTime(int offsetMilliseconds) + { + _blockTimeProvider.SetBlockTime(offsetMilliseconds); + } - public async Task AddTransactionListAsync(List transactions) - { - await _transactionListProvider.AddTransactionListAsync(transactions); - } + public async Task AddTransactionListAsync(List transactions) + { + await _transactionListProvider.AddTransactionListAsync(transactions); + } - public async Task> GetTransactionListAsync() - { - return await _transactionListProvider.GetTransactionListAsync(); - } + public async Task> GetTransactionListAsync() + { + return await _transactionListProvider.GetTransactionListAsync(); + } - public async Task ResetAsync() - { - await _transactionListProvider.ResetAsync(); - } + public async Task ResetAsync() + { + await _transactionListProvider.ResetAsync(); + } - public void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair) - { - _keyPairProvider.SetKeyPair(ecKeyPair); - } + public void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair) + { + _keyPairProvider.SetKeyPair(ecKeyPair); + } - public IAElfAsymmetricCipherKeyPair GetKeyPair() - { - return _keyPairProvider.GetKeyPair(); - } + public IAElfAsymmetricCipherKeyPair GetKeyPair() + { + return _keyPairProvider.GetKeyPair(); + } - public async Task GetCurrentBlockHeight() - { - return (await _blockchainService.GetChainAsync()).BestChainHeight; - } + public async Task GetCurrentBlockHeight() + { + return (await _blockchainService.GetChainAsync()).BestChainHeight; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionExecutedEventHandler.cs b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionExecutedEventHandler.cs index 851f0169eb..5e67560dff 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionExecutedEventHandler.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionExecutedEventHandler.cs @@ -3,22 +3,21 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class TransactionExecutedEventHandler : ILocalEventHandler, + ITransientDependency { - public class TransactionExecutedEventHandler : ILocalEventHandler, - ITransientDependency - { - private readonly ITransactionTraceProvider _traceProvider; + private readonly ITransactionTraceProvider _traceProvider; - public TransactionExecutedEventHandler(ITransactionTraceProvider traceProvider) - { - _traceProvider = traceProvider; - } + public TransactionExecutedEventHandler(ITransactionTraceProvider traceProvider) + { + _traceProvider = traceProvider; + } - public Task HandleEventAsync(TransactionExecutedEventData eventData) - { - _traceProvider.AddTransactionTrace(eventData.TransactionTrace); - return Task.CompletedTask; - } + public Task HandleEventAsync(TransactionExecutedEventData eventData) + { + _traceProvider.AddTransactionTrace(eventData.TransactionTrace); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionListProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionListProvider.cs index dbd4aa471a..a585a371d2 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionListProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionListProvider.cs @@ -2,28 +2,27 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class TransactionListProvider : ITransactionListProvider { - public class TransactionListProvider : ITransactionListProvider - { - private readonly List _transactionList = new List(); + private readonly List _transactionList = new(); - public Task AddTransactionListAsync(List transactions) - { - _transactionList.AddRange(transactions); - return Task.CompletedTask; - } + public Task AddTransactionListAsync(List transactions) + { + _transactionList.AddRange(transactions); + return Task.CompletedTask; + } - public Task> GetTransactionListAsync() - { - var list = _transactionList; - return Task.FromResult(list); - } + public Task> GetTransactionListAsync() + { + var list = _transactionList; + return Task.FromResult(list); + } - public Task ResetAsync() - { - _transactionList.Clear(); - return Task.CompletedTask; - } + public Task ResetAsync() + { + _transactionList.Clear(); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionTraceProvider.cs b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionTraceProvider.cs index c58ccb6b4c..87eacbf3c9 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/TransactionTraceProvider.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/TransactionTraceProvider.cs @@ -2,20 +2,19 @@ using AElf.Kernel; using AElf.Types; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class TransactionTraceProvider : ITransactionTraceProvider { - public class TransactionTraceProvider : ITransactionTraceProvider - { - private readonly Dictionary _traces = new Dictionary(); + private readonly Dictionary _traces = new(); - public void AddTransactionTrace(TransactionTrace trace) - { - _traces.TryAdd(trace.TransactionId, trace); - } + public void AddTransactionTrace(TransactionTrace trace) + { + _traces.TryAdd(trace.TransactionId, trace); + } - public TransactionTrace GetTransactionTrace(Hash transactionId) - { - return _traces.TryGetValue(transactionId, out var trace) ? trace : null; - } + public TransactionTrace GetTransactionTrace(Hash transactionId) + { + return _traces.TryGetValue(transactionId, out var trace) ? trace : null; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/UnitTestPlainTransactionExecutingService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/UnitTestPlainTransactionExecutingService.cs index 22dd1d175f..ca7ce8e3f6 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/UnitTestPlainTransactionExecutingService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/UnitTestPlainTransactionExecutingService.cs @@ -6,33 +6,33 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContractExecution.Events; -namespace AElf.ContractTestKit.AEDPoSExtension +namespace AElf.ContractTestKit.AEDPoSExtension; + +public class UnitTestPlainTransactionExecutingService : PlainTransactionExecutingService { - public class UnitTestPlainTransactionExecutingService : PlainTransactionExecutingService + public UnitTestPlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService, + IEnumerable postPlugins, IEnumerable prePlugins, + ITransactionContextFactory transactionContextFactory) : base( + smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory) + { + } + + protected override async Task ExecuteOneAsync(SingleTransactionExecutingDto singleTxExecutingDto, + CancellationToken cancellationToken) { - public UnitTestPlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService, - IEnumerable postPlugins, IEnumerable prePlugins, - ITransactionContextFactory transactionContextFactory) : base( - smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory) + TransactionTrace trace = null; + try { + trace = await base.ExecuteOneAsync(singleTxExecutingDto, cancellationToken); } - - protected override async Task ExecuteOneAsync(SingleTransactionExecutingDto singleTxExecutingDto, CancellationToken cancellationToken) + finally { - TransactionTrace trace = null; - try - { - trace = await base.ExecuteOneAsync(singleTxExecutingDto, cancellationToken); - } - finally + await LocalEventBus.PublishAsync(new TransactionExecutedEventData { - await LocalEventBus.PublishAsync(new TransactionExecutedEventData - { - TransactionTrace = trace - }); - } - - return trace; + TransactionTrace = trace + }); } + + return trace; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/AElf.ContractTestKit.csproj b/src/AElf.ContractTestKit/AElf.ContractTestKit.csproj index 1443ef6b75..928732975c 100644 --- a/src/AElf.ContractTestKit/AElf.ContractTestKit.csproj +++ b/src/AElf.ContractTestKit/AElf.ContractTestKit.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.ContractTestKit @@ -13,15 +13,15 @@ - - - - - - - - - + + + + + + + + + @@ -49,10 +49,10 @@ - - - - - + + + + + \ No newline at end of file diff --git a/src/AElf.ContractTestKit/ContractTestBase.cs b/src/AElf.ContractTestKit/ContractTestBase.cs index 5f97822261..21c26e6aff 100644 --- a/src/AElf.ContractTestKit/ContractTestBase.cs +++ b/src/AElf.ContractTestKit/ContractTestBase.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.Genesis; using AElf.Cryptography.ECDSA; @@ -11,6 +10,7 @@ using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using MartinCostello.Logging.XUnit; @@ -21,109 +21,106 @@ using Xunit; using Xunit.Abstractions; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class ContractTestBase : ContractTestBase { - public class ContractTestBase : ContractTestBase - { - } +} + +public class ContractTestBase : AbpIntegratedTest + where TModule : ContractTestModule +{ + private IReadOnlyDictionary _codes; - public class ContractTestBase : AbpIntegratedTest - where TModule : ContractTestModule + public ContractTestBase() { - private IReadOnlyDictionary _codes; + var blockchainService = Application.ServiceProvider.GetService(); + var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); + var block = AsyncHelper.RunSync(() => blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash)); + var transactionResultManager = Application.ServiceProvider.GetService(); + var transactionResults = AsyncHelper.RunSync(() => + transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash())); + foreach (var transactionResult in transactionResults) + Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); + } - public IReadOnlyDictionary Codes => _codes ??= ContractsDeployer.GetContractCodes(); + public IReadOnlyDictionary Codes => _codes ??= ContractsDeployer.GetContractCodes(); - protected IReadOnlyList Accounts => SampleAccount.Accounts; + protected IReadOnlyList Accounts => SampleAccount.Accounts; - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } + protected ISmartContractAddressService ContractAddressService => + Application.ServiceProvider.GetRequiredService(); - protected void SetTestOutputHelper(ITestOutputHelper testOutputHelper) - { - GetRequiredService().OutputHelper = testOutputHelper; - } + protected Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - protected ISmartContractAddressService ContractAddressService => - Application.ServiceProvider.GetRequiredService(); + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } - protected Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected void SetTestOutputHelper(ITestOutputHelper testOutputHelper) + { + GetRequiredService().OutputHelper = testOutputHelper; + } - public ContractTestBase() - { - var blockchainService = Application.ServiceProvider.GetService(); - var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); - var block = AsyncHelper.RunSync(()=>blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash)); - var transactionResultManager = Application.ServiceProvider.GetService(); - var transactionResults = AsyncHelper.RunSync(() => - transactionResultManager.GetTransactionResultsAsync(block.Body.TransactionIds, block.GetHash())); - foreach (var transactionResult in transactionResults) - { - Assert.True(transactionResult.Status == TransactionResultStatus.Mined, transactionResult.Error); - } - } - - protected async Task
DeployContractAsync(int category, byte[] code, Hash name, ECKeyPair senderKey) + protected async Task
DeployContractAsync(int category, byte[] code, Hash name, ECKeyPair senderKey) + { + var zeroStub = + GetTester(ContractZeroAddress, senderKey); + var res = await zeroStub.DeploySmartContract.SendAsync(new ContractDeploymentInput { - var zeroStub = GetTester(ContractZeroAddress, senderKey); - var res = await zeroStub.DeploySmartContract.SendAsync(new ContractDeploymentInput() - { - Category = category, - Code = ByteString.CopyFrom(code) - }); - return res.Output; - } - - protected async Task
DeploySystemSmartContract(int category, byte[] code, Hash name, - ECKeyPair senderKey) + Category = category, + Code = ByteString.CopyFrom(code) + }); + return res.Output; + } + + protected async Task
DeploySystemSmartContract(int category, byte[] code, Hash name, + ECKeyPair senderKey) + { + var zeroStub = + GetTester(ContractZeroAddress, senderKey); + var res = await zeroStub.DeploySystemSmartContract.SendAsync(new SystemContractDeploymentInput { - var zeroStub = GetTester(ContractZeroAddress, senderKey); - var res = await zeroStub.DeploySystemSmartContract.SendAsync(new SystemContractDeploymentInput - { - Category = category, - Code = ByteString.CopyFrom(code), - Name = name, - TransactionMethodCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList() - }); - if (res.TransactionResult == null || res.TransactionResult.Status != TransactionResultStatus.Mined) - { - throw new Exception($"DeploySystemSmartContract failed: {res.TransactionResult}"); - } - - var address = await zeroStub.GetContractAddressByName.CallAsync(name); - await ContractAddressService.SetSmartContractAddressAsync(new BlockIndex - { - BlockHash = res.TransactionResult.BlockHash, - BlockHeight = res.TransactionResult.BlockNumber - }, name.ToStorageKey(), address); - - return res.Output; - } - - protected T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() + Category = category, + Code = ByteString.CopyFrom(code), + Name = name, + TransactionMethodCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList() + }); + if (res.TransactionResult == null || res.TransactionResult.Status != TransactionResultStatus.Mined) + throw new Exception($"DeploySystemSmartContract failed: {res.TransactionResult}"); + + var address = await zeroStub.GetContractAddressByName.CallAsync(name); + await ContractAddressService.SetSmartContractAddressAsync(new BlockIndex { - var factory = Application.ServiceProvider.GetRequiredService(); - return factory.Create(contractAddress, senderKey); - } + BlockHash = res.TransactionResult.BlockHash, + BlockHeight = res.TransactionResult.BlockNumber + }, name.ToStorageKey(), address); - protected IReadOnlyDictionary GetPatchedCodes(string dir) - { - return ContractsDeployer.GetContractCodes(dir, true); - } - - // byte[] ReadPatchedContractCode(Type contractType) - // { - // return ReadCode(ContractPatchedDllDir + contractType.Module + ".patched"); - // } - // - // byte[] ReadCode(string path) - // { - // return File.Exists(path) - // ? File.ReadAllBytes(path) - // : throw new FileNotFoundException("Contract DLL cannot be found. " + path); - // } + return res.Output; } + + protected T GetTester(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() + { + var factory = Application.ServiceProvider.GetRequiredService(); + return factory.Create(contractAddress, senderKey); + } + + protected IReadOnlyDictionary GetPatchedCodes(string dir) + { + return ContractsDeployer.GetContractCodes(dir, true); + } + + // byte[] ReadPatchedContractCode(Type contractType) + // { + // return ReadCode(ContractPatchedDllDir + contractType.Module + ".patched"); + // } + // + // byte[] ReadCode(string path) + // { + // return File.Exists(path) + // ? File.ReadAllBytes(path) + // : throw new FileNotFoundException("Contract DLL cannot be found. " + path); + // } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/ContractTestModule.cs b/src/AElf.ContractTestKit/ContractTestModule.cs index 76b2a8a5f3..af9838bfef 100644 --- a/src/AElf.ContractTestKit/ContractTestModule.cs +++ b/src/AElf.ContractTestKit/ContractTestModule.cs @@ -7,7 +7,6 @@ using AElf.Kernel.ChainController; using AElf.Kernel.ChainController.Application; using AElf.Kernel.Consensus.Application; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.Infrastructure; using AElf.Kernel.Node; using AElf.Kernel.Proposal; @@ -39,146 +38,145 @@ using Volo.Abp.Threading; using Xunit.Abstractions; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class ContractTestModule : ContractTestModule + where TSelf : ContractTestModule { - public class ContractTestModule : ContractTestModule - where TSelf : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - base.ConfigureServices(context); - } + context.Services.AddAssemblyOf(); + base.ConfigureServices(context); } +} + +[DependsOn( + typeof(AbpEventBusModule), + typeof(AbpTestBaseModule), + typeof(CoreKernelAElfModule), + typeof(KernelAElfModule), + typeof(NodeAElfModule), + typeof(CoreOSAElfModule), + typeof(SmartContractAElfModule), + typeof(SmartContractExecutionAElfModule), + typeof(TransactionPoolAElfModule), + typeof(ChainControllerAElfModule), + typeof(TokenKernelAElfModule), + typeof(CSharpRuntimeAElfModule))] +public class ContractTestModule : AbpModule +{ + public int ChainId { get; } = 500; + public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } - [DependsOn( - typeof(AbpEventBusModule), - typeof(AbpTestBaseModule), - typeof(CoreKernelAElfModule), - typeof(KernelAElfModule), - typeof(NodeAElfModule), - typeof(CoreOSAElfModule), - typeof(SmartContractAElfModule), - typeof(SmartContractExecutionAElfModule), - typeof(TransactionPoolAElfModule), - typeof(ChainControllerAElfModule), - typeof(TokenKernelAElfModule), - typeof(CSharpRuntimeAElfModule))] - public class ContractTestModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC"; - options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; - }); + Configure(options => + { + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC"; + options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; + }); - Configure(options => options.ChainId = ChainId); + Configure(options => options.ChainId = ChainId); - #region Infra + #region Infra - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - services.AddTransient(); - services.AddSingleton(); - services.AddSingleton(); + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + services.AddTransient(); + services.AddSingleton(); + services.AddSingleton(); - #endregion + #endregion - #region Logger + #region Logger - ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); - services.AddSingleton(testOutputHelperAccessor); - services.AddLogging(o => { o.AddXUnit(testOutputHelperAccessor); }); + ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); + services.AddSingleton(testOutputHelperAccessor); + services.AddLogging(o => { o.AddXUnit(testOutputHelperAccessor); }); - #endregion + #endregion - #region Mocks + #region Mocks - services.AddSingleton(o => Mock.Of()); - services.AddSingleton(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); - services.AddSingleton(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); - // When testing contract and packaging transactions, no need to generate and schedule real consensus stuff. + // When testing contract and packaging transactions, no need to generate and schedule real consensus stuff. // context.Services.AddSingleton(o => Mock.Of()); // context.Services.AddSingleton(o => Mock.Of()); - context.Services.AddTransient(o => Mock.Of()); - - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(s => - s.GetGenesisSmartContractDtos()) - .Returns(new List()); - return mockService.Object; - }); - - #endregion - - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.Replace(ServiceDescriptor - .Singleton()); - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new UnitTestCSharpSmartContractRunner( - option.Value.SdkDir); - }); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services - .AddSingleton(); - } - - public int ChainId { get; } = 500; - public OsBlockchainNodeContext OsBlockchainNodeContext { get; set; } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) + context.Services.AddTransient(o => Mock.Of()); + + context.Services.AddTransient(o => { - context.ServiceProvider.GetService() - .SetKeyPair(SampleAccount.Accounts[0].KeyPair); - - var dto = new OsBlockchainNodeContextStartDto - { - ChainId = context.ServiceProvider.GetService>().Value.ChainId, - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, - }; - var dtoProvider = context.ServiceProvider.GetRequiredService(); - dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); - var contractOptions = context.ServiceProvider.GetService>().Value; - dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); - } - - public override void OnApplicationShutdown(ApplicationShutdownContext context) + var mockService = new Mock(); + mockService.Setup(s => + s.GetGenesisSmartContractDtos()) + .Returns(new List()); + return mockService.Object; + }); + + #endregion + + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.Replace(ServiceDescriptor + .Singleton()); + context.Services.AddSingleton(provider => { - var osService = context.ServiceProvider.GetService(); - var that = this; - AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); - } + var option = provider.GetService>(); + return new UnitTestCSharpSmartContractRunner( + option.Value.SdkDir); + }); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services + .AddSingleton(); } - [DependsOn(typeof(ContractTestModule), - typeof(ExecutionPluginForResourceFeeModule), - typeof(ExecutionPluginForCallThresholdModule), - typeof(ExecutionPluginForMethodFeeModule))] - public class ContractTestWithExecutionPluginModule : AbpModule + public override void OnApplicationInitialization(ApplicationInitializationContext context) { + context.ServiceProvider.GetService() + .SetKeyPair(SampleAccount.Accounts[0].KeyPair); + + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = context.ServiceProvider.GetService>().Value.ChainId, + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory + }; + var dtoProvider = context.ServiceProvider.GetRequiredService(); + dto.InitializationSmartContracts = dtoProvider.GetGenesisSmartContractDtos().ToList(); + var contractOptions = context.ServiceProvider.GetService>().Value; + dto.ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired; + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(async () => { that.OsBlockchainNodeContext = await osService.StartAsync(dto); }); } - public class TestOutputHelperAccessor : ITestOutputHelperAccessor + public override void OnApplicationShutdown(ApplicationShutdownContext context) { - public ITestOutputHelper OutputHelper { get; set; } + var osService = context.ServiceProvider.GetService(); + var that = this; + AsyncHelper.RunSync(() => osService.StopAsync(that.OsBlockchainNodeContext)); } +} + +[DependsOn(typeof(ContractTestModule), + typeof(ExecutionPluginForResourceFeeModule), + typeof(ExecutionPluginForCallThresholdModule), + typeof(ExecutionPluginForMethodFeeModule))] +public class ContractTestWithExecutionPluginModule : AbpModule +{ +} + +public class TestOutputHelperAccessor : ITestOutputHelperAccessor +{ + public ITestOutputHelper OutputHelper { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/Extensions/AllCalculateFeeCoefficientsExtensions.cs b/src/AElf.ContractTestKit/Extensions/AllCalculateFeeCoefficientsExtensions.cs index 36fb31bc98..3a172f9b29 100644 --- a/src/AElf.ContractTestKit/Extensions/AllCalculateFeeCoefficientsExtensions.cs +++ b/src/AElf.ContractTestKit/Extensions/AllCalculateFeeCoefficientsExtensions.cs @@ -3,18 +3,17 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.FeeCalculation.Infrastructure; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +/// +/// TODO: Dup this code here to resolve refs conflicts. Remove after figuring out how to de-couple refs. +/// +internal static class AllCalculateFeeCoefficientsExtensions { - /// - /// TODO: Dup this code here to resolve refs conflicts. Remove after figuring out how to de-couple refs. - /// - internal static class AllCalculateFeeCoefficientsExtensions + public static Dictionary ToCalculateFunctionDictionary( + this AllCalculateFeeCoefficients allCalculateFeeCoefficients) { - public static Dictionary ToCalculateFunctionDictionary( - this AllCalculateFeeCoefficients allCalculateFeeCoefficients) - { - return allCalculateFeeCoefficients.Value.ToDictionary(c => ((FeeTypeEnum) c.FeeTokenType).ToString().ToUpper(), - c => c.ToCalculateFunction()); - } + return allCalculateFeeCoefficients.Value.ToDictionary(c => ((FeeTypeEnum)c.FeeTokenType).ToString().ToUpper(), + c => c.ToCalculateFunction()); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/Extensions/CalculateFeeCoefficientsExtensions.cs b/src/AElf.ContractTestKit/Extensions/CalculateFeeCoefficientsExtensions.cs index cbe28c2151..dfe8fc6a63 100644 --- a/src/AElf.ContractTestKit/Extensions/CalculateFeeCoefficientsExtensions.cs +++ b/src/AElf.ContractTestKit/Extensions/CalculateFeeCoefficientsExtensions.cs @@ -3,77 +3,71 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.FeeCalculation.Infrastructure; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +/// +/// TODO: Dup this code here to resolve refs conflicts. Remove after figuring out how to de-couple refs. +/// +internal static class CalculateFeeCoefficientsExtensions { - /// - /// TODO: Dup this code here to resolve refs conflicts. Remove after figuring out how to de-couple refs. - /// - internal static class CalculateFeeCoefficientsExtensions + private const decimal Precision = 100000000; + + public static CalculateFunction ToCalculateFunction( + this CalculateFeeCoefficients calculateFeeCoefficients) { - public static CalculateFunction ToCalculateFunction( - this CalculateFeeCoefficients calculateFeeCoefficients) - { - var pieceCalculateFunction = new CalculateFunction(calculateFeeCoefficients.FeeTokenType); - foreach (var pieceCoefficients in calculateFeeCoefficients.PieceCoefficientsList.Where(pc => - (pc.Value.Count - 1) % 3 == 0)) - { - pieceCalculateFunction.AddFunction(pieceCoefficients.Value.ToArray(), - GetFunction(pieceCoefficients.Value.ToArray())); - } + var pieceCalculateFunction = new CalculateFunction(calculateFeeCoefficients.FeeTokenType); + foreach (var pieceCoefficients in calculateFeeCoefficients.PieceCoefficientsList.Where(pc => + (pc.Value.Count - 1) % 3 == 0)) + pieceCalculateFunction.AddFunction(pieceCoefficients.Value.ToArray(), + GetFunction(pieceCoefficients.Value.ToArray())); - return pieceCalculateFunction; - } + return pieceCalculateFunction; + } - private const decimal Precision = 100000000; + private static Func GetFunction(int[] parameters) + { + return count => GetExponentialFunc(count, parameters); + } + + // eg. 2x^2 + 3x + 1 -> (2,2,1, 1,3,1, 0,1,1) + private static long GetExponentialFunc(int count, params int[] parameters) + { + long cost = 0; - private static Func GetFunction(int[] parameters) + // Skip parameters[0] which is meant to be piece upper bound. + var currentIndex = 1; + while (currentIndex < parameters.Length) { - return count => GetExponentialFunc(count, parameters); + cost += GetUnitExponentialCalculation(count, parameters[currentIndex], + parameters[currentIndex + 1], + parameters[currentIndex + 2]); + currentIndex += 3; } - // eg. 2x^2 + 3x + 1 -> (2,2,1, 1,3,1, 0,1,1) - private static long GetExponentialFunc(int count, params int[] parameters) - { - long cost = 0; + return cost; + } - // Skip parameters[0] which is meant to be piece upper bound. - var currentIndex = 1; - while (currentIndex < parameters.Length) - { - cost += GetUnitExponentialCalculation(count, parameters[currentIndex], - parameters[currentIndex + 1], - parameters[currentIndex + 2]); - currentIndex += 3; - } + // (A, B, C) -> x^A * (B / C) + private static long GetUnitExponentialCalculation(int count, params int[] parameters) + { + if (parameters[2] == 0) parameters[2] = 1; - return cost; + decimal decimalResult; + var power = parameters[0]; + decimal divisor = parameters[1]; + decimal dividend = parameters[2]; + if (power == 0) + { + // This piece is (B / C) + decimalResult = divisor / dividend; } - - // (A, B, C) -> x^A * (B / C) - private static long GetUnitExponentialCalculation(int count, params int[] parameters) + else { - if (parameters[2] == 0) - { - parameters[2] = 1; - } - - decimal decimalResult; - var power = parameters[0]; - decimal divisor = parameters[1]; - decimal dividend = parameters[2]; - if (power == 0) - { - // This piece is (B / C) - decimalResult = divisor / dividend; - } - else - { - // Calculate x^A at first. - var powerResult = (decimal) Math.Pow(count, power); - decimalResult = powerResult * divisor / dividend; - } - - return (long) (decimalResult * Precision); + // Calculate x^A at first. + var powerResult = (decimal)Math.Pow(count, power); + decimalResult = powerResult * divisor / dividend; } + + return (long)(decimalResult * Precision); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/Extensions/GenesisContractDtoExtensions.cs b/src/AElf.ContractTestKit/Extensions/GenesisContractDtoExtensions.cs index f957928c3b..afb4f39ebe 100644 --- a/src/AElf.ContractTestKit/Extensions/GenesisContractDtoExtensions.cs +++ b/src/AElf.ContractTestKit/Extensions/GenesisContractDtoExtensions.cs @@ -1,18 +1,19 @@ using AElf.Standards.ACS0; using Google.Protobuf; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class GenesisContractDtoExtensions { - public static class GenesisContractDtoExtensions + public static void Add( + this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, + string methodName, + IMessage input) { - public static void Add(this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, string methodName, - IMessage input) + systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall() - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/IBlockTimeProvider.cs b/src/AElf.ContractTestKit/IBlockTimeProvider.cs index d8596f2819..063518f6a4 100644 --- a/src/AElf.ContractTestKit/IBlockTimeProvider.cs +++ b/src/AElf.ContractTestKit/IBlockTimeProvider.cs @@ -3,36 +3,36 @@ using AElf.Kernel; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +/// +/// Some contract method's result based on the calling time, +/// like GetConsensusCommand method of consensus contract. +/// +public interface IBlockTimeProvider +{ + Timestamp GetBlockTime(); + void SetBlockTime(Timestamp blockTime); + void SetBlockTime(int offsetMilliseconds); +} + +public class BlockTimeProvider : IBlockTimeProvider { - /// - /// Some contract method's result based on the calling time, - /// like GetConsensusCommand method of consensus contract. - /// - public interface IBlockTimeProvider + private Timestamp _blockTime; + + public Timestamp GetBlockTime() { - Timestamp GetBlockTime(); - void SetBlockTime(Timestamp blockTime); - void SetBlockTime(int offsetMilliseconds); + return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime; } - public class BlockTimeProvider : IBlockTimeProvider + public void SetBlockTime(Timestamp blockTime) { - private Timestamp _blockTime; - public Timestamp GetBlockTime() - { - return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime; - } - - public void SetBlockTime(Timestamp blockTime) - { - Debug.WriteLine($"Update block time: {blockTime}"); - _blockTime = blockTime; - } + Debug.WriteLine($"Update block time: {blockTime}"); + _blockTime = blockTime; + } - public void SetBlockTime(int offsetMilliseconds) - { - SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); - } + public void SetBlockTime(int offsetMilliseconds) + { + SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/IContractTesterFactory.cs b/src/AElf.ContractTestKit/IContractTesterFactory.cs index 430a09ff58..98d8bb970e 100644 --- a/src/AElf.ContractTestKit/IContractTesterFactory.cs +++ b/src/AElf.ContractTestKit/IContractTesterFactory.cs @@ -4,32 +4,31 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public interface IContractTesterFactory +{ + T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); +} + +public class ContractTesterFactory : IContractTesterFactory, ITransientDependency { - public interface IContractTesterFactory + private readonly IServiceProvider _serviceProvider; + + public ContractTesterFactory(IServiceProvider serviceProvider) { - T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new(); + _serviceProvider = serviceProvider; } - public class ContractTesterFactory : IContractTesterFactory, ITransientDependency + public T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() { - private readonly IServiceProvider _serviceProvider; - - public ContractTesterFactory(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public T Create(Address contractAddress, ECKeyPair senderKey) where T : ContractStubBase, new() + return new T { - return new T + __factory = new MethodStubFactory(_serviceProvider) { - __factory = new MethodStubFactory(_serviceProvider) - { - ContractAddress = contractAddress, - KeyPair = senderKey - } - }; - } + ContractAddress = contractAddress, + KeyPair = senderKey + } + }; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/IRefBlockInfoProvider.cs b/src/AElf.ContractTestKit/IRefBlockInfoProvider.cs index 81d7bca8d1..7fe54a6b0c 100644 --- a/src/AElf.ContractTestKit/IRefBlockInfoProvider.cs +++ b/src/AElf.ContractTestKit/IRefBlockInfoProvider.cs @@ -3,40 +3,39 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public sealed class RefBlockInfo { - public sealed class RefBlockInfo + public RefBlockInfo(long height, ByteString prefix) { - public long Height { get; } - public ByteString Prefix { get; } - - public RefBlockInfo(long height, ByteString prefix) - { - Height = height; - Prefix = prefix; - } + Height = height; + Prefix = prefix; } - public interface IRefBlockInfoProvider + public long Height { get; } + public ByteString Prefix { get; } +} + +public interface IRefBlockInfoProvider +{ + RefBlockInfo GetRefBlockInfo(); +} + +public class RefBlockInfoProvider : IRefBlockInfoProvider, ITransientDependency +{ + private readonly IBlockchainService _blockchainService; + + public RefBlockInfoProvider(IBlockchainService blockchainService) { - RefBlockInfo GetRefBlockInfo(); + _blockchainService = blockchainService; } - public class RefBlockInfoProvider : IRefBlockInfoProvider, ITransientDependency + public RefBlockInfo GetRefBlockInfo() { - private readonly IBlockchainService _blockchainService; - - public RefBlockInfoProvider(IBlockchainService blockchainService) - { - _blockchainService = blockchainService; - } - - public RefBlockInfo GetRefBlockInfo() - { - var block = AsyncHelper.RunSync(() => _blockchainService.GetBestChainLastBlockHeaderAsync()); - var height = block.Height; - var prefix = BlockHelper.GetRefBlockPrefix(block.GetHash()); - return new RefBlockInfo(height, prefix); - } + var block = AsyncHelper.RunSync(() => _blockchainService.GetBestChainLastBlockHeaderAsync()); + var height = block.Height; + var prefix = BlockHelper.GetRefBlockPrefix(block.GetHash()); + return new RefBlockInfo(height, prefix); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/IResetBlockTimeProvider.cs b/src/AElf.ContractTestKit/IResetBlockTimeProvider.cs index 8bc2e56d04..137e075f6a 100644 --- a/src/AElf.ContractTestKit/IResetBlockTimeProvider.cs +++ b/src/AElf.ContractTestKit/IResetBlockTimeProvider.cs @@ -1,14 +1,13 @@ -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public interface IResetBlockTimeProvider { - public interface IResetBlockTimeProvider - { - bool Enabled { get; } - int StepMilliseconds { get; } - } + bool Enabled { get; } + int StepMilliseconds { get; } +} - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => true; - public int StepMilliseconds => 4000; - } +public class ResetBlockTimeProvider : IResetBlockTimeProvider +{ + public bool Enabled => true; + public int StepMilliseconds => 4000; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/ITestTransactionExecutor.cs b/src/AElf.ContractTestKit/ITestTransactionExecutor.cs index e0ca9cc7bd..e1e98393b9 100644 --- a/src/AElf.ContractTestKit/ITestTransactionExecutor.cs +++ b/src/AElf.ContractTestKit/ITestTransactionExecutor.cs @@ -3,13 +3,12 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public interface ITestTransactionExecutor { - public interface ITestTransactionExecutor - { - Task ExecuteAsync(Transaction transaction); - Task ExecuteWithExceptionAsync(Transaction transaction); - Task ReadAsync(Transaction transaction); - Task ReadWithExceptionAsync(Transaction transaction); - } + Task ExecuteAsync(Transaction transaction); + Task ExecuteWithExceptionAsync(Transaction transaction); + Task ReadAsync(Transaction transaction); + Task ReadWithExceptionAsync(Transaction transaction); } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/MethodStubFactory.cs b/src/AElf.ContractTestKit/MethodStubFactory.cs index f209b72891..2504ff14c6 100644 --- a/src/AElf.ContractTestKit/MethodStubFactory.cs +++ b/src/AElf.ContractTestKit/MethodStubFactory.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using AElf.Cryptography; using AElf.Cryptography.ECDSA; -using AElf.Kernel.Blockchain.Application; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Types; @@ -11,119 +10,113 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class MethodStubFactory : IMethodStubFactory, ITransientDependency { - public class MethodStubFactory : IMethodStubFactory, ITransientDependency + private readonly IBlockTimeProvider _blockTimeProvider; + + private readonly IRefBlockInfoProvider _refBlockInfoProvider; + private readonly IResetBlockTimeProvider _resetBlockTimeProvider; + private readonly ITestTransactionExecutor _testTransactionExecutor; + + public MethodStubFactory(IServiceProvider serviceProvider) { - public ECKeyPair KeyPair { get; set; } = CryptoHelper.GenerateKeyPair(); + _refBlockInfoProvider = serviceProvider.GetRequiredService(); + _testTransactionExecutor = serviceProvider.GetRequiredService(); + _blockTimeProvider = serviceProvider.GetRequiredService(); + _resetBlockTimeProvider = serviceProvider.GetRequiredService(); + } - public Address ContractAddress { get; set; } + public ECKeyPair KeyPair { get; set; } = CryptoHelper.GenerateKeyPair(); - public Address Sender => Address.FromPublicKey(KeyPair.PublicKey); + public Address ContractAddress { get; set; } - private readonly IRefBlockInfoProvider _refBlockInfoProvider; - private readonly ITestTransactionExecutor _testTransactionExecutor; - private readonly IBlockTimeProvider _blockTimeProvider; - private readonly IResetBlockTimeProvider _resetBlockTimeProvider; + public Address Sender => Address.FromPublicKey(KeyPair.PublicKey); - public MethodStubFactory(IServiceProvider serviceProvider) + public IMethodStub Create(Method method) + where TInput : IMessage, new() where TOutput : IMessage, new() + { + Transaction GetTransaction(TInput input) { - _refBlockInfoProvider = serviceProvider.GetRequiredService(); - _testTransactionExecutor = serviceProvider.GetRequiredService(); - _blockTimeProvider = serviceProvider.GetRequiredService(); - _resetBlockTimeProvider = serviceProvider.GetRequiredService(); + var refBlockInfo = _refBlockInfoProvider.GetRefBlockInfo(); + var transaction = GetTransactionWithoutSignature(input, method); + transaction.RefBlockNumber = refBlockInfo.Height; + transaction.RefBlockPrefix = refBlockInfo.Prefix; + + var signature = CryptoHelper.SignWithPrivateKey( + KeyPair.PrivateKey, transaction.GetHash().Value.ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + return transaction; } - public IMethodStub Create(Method method) - where TInput : IMessage, new() where TOutput : IMessage, new() + async Task> SendAsync(TInput input) { - Transaction GetTransaction(TInput input) - { - var refBlockInfo = _refBlockInfoProvider.GetRefBlockInfo(); - var transaction = GetTransactionWithoutSignature(input, method); - transaction.RefBlockNumber = refBlockInfo.Height; - transaction.RefBlockPrefix = refBlockInfo.Prefix; - - var signature = CryptoHelper.SignWithPrivateKey( - KeyPair.PrivateKey, transaction.GetHash().Value.ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - return transaction; - } - - async Task> SendAsync(TInput input) - { - var transaction = GetTransaction(input); - var transactionResult = await _testTransactionExecutor.ExecuteAsync(transaction); - - if (transactionResult == null) - { - return new ExecutionResult {Transaction = transaction}; - } - - ResetBlockTime(); - return new ExecutionResult - { - Transaction = transaction, TransactionResult = transactionResult, - Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) - }; - } - - async Task> SendWithExceptionAsync(TInput input) - { - var transaction = GetTransaction(input); - var transactionResult =await _testTransactionExecutor.ExecuteWithExceptionAsync(transaction); - if (transactionResult == null) - { - return new ExecutionResult {Transaction = transaction}; - } - - ResetBlockTime(); - return new ExecutionResult - { - Transaction = transaction, TransactionResult = transactionResult, - Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) - }; - } - - void ResetBlockTime() - { - if (!_resetBlockTimeProvider.Enabled) return; - var currentBlockTime = _blockTimeProvider.GetBlockTime(); - currentBlockTime.AddMilliseconds(_resetBlockTimeProvider.StepMilliseconds); - _blockTimeProvider.SetBlockTime(currentBlockTime); - } + var transaction = GetTransaction(input); + var transactionResult = await _testTransactionExecutor.ExecuteAsync(transaction); - async Task CallAsync(TInput input) - { - var transaction = GetTransactionWithoutSignature(input, method); - var returnValue = await _testTransactionExecutor.ReadAsync(transaction); - return method.ResponseMarshaller.Deserializer(returnValue.ToByteArray()); - } + if (transactionResult == null) return new ExecutionResult { Transaction = transaction }; - async Task CallWithExceptionAsync(TInput input) + ResetBlockTime(); + return new ExecutionResult { - var transaction = GetTransactionWithoutSignature(input, method); - var returnValue = await _testTransactionExecutor.ReadWithExceptionAsync(transaction); - return new StringValue {Value = returnValue.Value}; - } - - return new MethodStub(method, SendAsync, CallAsync, GetTransaction, SendWithExceptionAsync, - CallWithExceptionAsync); + Transaction = transaction, TransactionResult = transactionResult, + Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) + }; } - private Transaction GetTransactionWithoutSignature(TInput input, - Method method) - where TInput : IMessage, new() where TOutput : IMessage, new() + async Task> SendWithExceptionAsync(TInput input) { - var transaction = new Transaction + var transaction = GetTransaction(input); + var transactionResult = await _testTransactionExecutor.ExecuteWithExceptionAsync(transaction); + if (transactionResult == null) return new ExecutionResult { Transaction = transaction }; + + ResetBlockTime(); + return new ExecutionResult { - From = Sender, - To = ContractAddress, - MethodName = method.Name, - Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + Transaction = transaction, TransactionResult = transactionResult, + Output = method.ResponseMarshaller.Deserializer(transactionResult.ReturnValue.ToByteArray()) }; + } - return transaction; + void ResetBlockTime() + { + if (!_resetBlockTimeProvider.Enabled) return; + var currentBlockTime = _blockTimeProvider.GetBlockTime(); + currentBlockTime.AddMilliseconds(_resetBlockTimeProvider.StepMilliseconds); + _blockTimeProvider.SetBlockTime(currentBlockTime); + } + + async Task CallAsync(TInput input) + { + var transaction = GetTransactionWithoutSignature(input, method); + var returnValue = await _testTransactionExecutor.ReadAsync(transaction); + return method.ResponseMarshaller.Deserializer(returnValue.ToByteArray()); + } + + async Task CallWithExceptionAsync(TInput input) + { + var transaction = GetTransactionWithoutSignature(input, method); + var returnValue = await _testTransactionExecutor.ReadWithExceptionAsync(transaction); + return new StringValue { Value = returnValue.Value }; } + + return new MethodStub(method, SendAsync, CallAsync, GetTransaction, SendWithExceptionAsync, + CallWithExceptionAsync); + } + + private Transaction GetTransactionWithoutSignature(TInput input, + Method method) + where TInput : IMessage, new() where TOutput : IMessage, new() + { + var transaction = new Transaction + { + From = Sender, + To = ContractAddress, + MethodName = method.Name, + Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + }; + + return transaction; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/MockCalculateFunctionProvider.cs b/src/AElf.ContractTestKit/MockCalculateFunctionProvider.cs index 9d49e1a6da..22ed9505fd 100644 --- a/src/AElf.ContractTestKit/MockCalculateFunctionProvider.cs +++ b/src/AElf.ContractTestKit/MockCalculateFunctionProvider.cs @@ -6,81 +6,78 @@ using AElf.Kernel.FeeCalculation.Infrastructure; using Volo.Abp.DependencyInjection; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class MockCalculateFunctionProvider : ICalculateFunctionProvider, ISingletonDependency { - public class MockCalculateFunctionProvider : ICalculateFunctionProvider, ISingletonDependency + private readonly Dictionary> _coefficientsDicCache; + + public MockCalculateFunctionProvider() { - private enum FeeTypeEnum + _coefficientsDicCache = new Dictionary>(); + var txCoefficient = new List { - Read = 0, - Storage = 1, - Write = 2, - Traffic = 3, - Tx = 4, - } - - private readonly Dictionary> _coefficientsDicCache; - - public MockCalculateFunctionProvider() + new[] { 1000000, 1, 1, 800, 0, 10000, 100000000 }, + new[] { int.MaxValue, 1, 1, 800, 2, 1, 10000 } + }; + _coefficientsDicCache[(int)FeeTypeEnum.Tx] = txCoefficient; + var readCoefficient = new List { - _coefficientsDicCache = new Dictionary>(); - var txCoefficient = new List - { - new[] {1000000, 1, 1, 800, 0, 10000, 100000000}, - new[] {int.MaxValue, 1, 1, 800, 2, 1, 10000} - }; - _coefficientsDicCache[(int) FeeTypeEnum.Tx] = txCoefficient; - var readCoefficient = new List - { - new[] {10, 1, 1, 8, 0, 1000, 100000000}, new[] {100, 1, 1, 4}, - new[] {int.MaxValue, 2, 25, 16, 1, 1, 4} - }; - _coefficientsDicCache[(int) FeeTypeEnum.Read] = readCoefficient; - var storageCoefficient = new List - { - new[] {1000000, 1, 1, 4, 0, 1000, 100000000}, - new[] {int.MaxValue, 2, 1, 20000, 1, 1, 64} - }; - _coefficientsDicCache[(int) FeeTypeEnum.Storage] = storageCoefficient; - var writeCoefficient = new List - { - new[] {10, 1, 1, 8, 0, 10000, 100000000}, - new[] {100, 1, 1, 4}, - new[] {int.MaxValue, 1, 1, 4, 2, 25, 16} - }; - _coefficientsDicCache[(int) FeeTypeEnum.Write] = writeCoefficient; - var trafficCoefficient = new List - { - new[] {1000000, 1, 1, 64, 0, 10000, 100000000}, - new[] {int.MaxValue, 1, 1, 64, 2, 1, 20000} - }; - _coefficientsDicCache[(int) FeeTypeEnum.Traffic] = trafficCoefficient; - } - - public Task AddCalculateFunctions(IBlockIndex blockIndex, - Dictionary calculateFunctionDictionary) + new[] { 10, 1, 1, 8, 0, 1000, 100000000 }, new[] { 100, 1, 1, 4 }, + new[] { int.MaxValue, 2, 25, 16, 1, 1, 4 } + }; + _coefficientsDicCache[(int)FeeTypeEnum.Read] = readCoefficient; + var storageCoefficient = new List { - return Task.CompletedTask; - } - - public Dictionary GetCalculateFunctions(IChainContext chainContext) + new[] { 1000000, 1, 1, 4, 0, 1000, 100000000 }, + new[] { int.MaxValue, 2, 1, 20000, 1, 1, 64 } + }; + _coefficientsDicCache[(int)FeeTypeEnum.Storage] = storageCoefficient; + var writeCoefficient = new List { - var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); - foreach (var coefficients in _coefficientsDicCache) + new[] { 10, 1, 1, 8, 0, 10000, 100000000 }, + new[] { 100, 1, 1, 4 }, + new[] { int.MaxValue, 1, 1, 4, 2, 25, 16 } + }; + _coefficientsDicCache[(int)FeeTypeEnum.Write] = writeCoefficient; + var trafficCoefficient = new List + { + new[] { 1000000, 1, 1, 64, 0, 10000, 100000000 }, + new[] { int.MaxValue, 1, 1, 64, 2, 1, 20000 } + }; + _coefficientsDicCache[(int)FeeTypeEnum.Traffic] = trafficCoefficient; + } + + public Task AddCalculateFunctions(IBlockIndex blockIndex, + Dictionary calculateFunctionDictionary) + { + return Task.CompletedTask; + } + + public Dictionary GetCalculateFunctions(IChainContext chainContext) + { + var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); + foreach (var coefficients in _coefficientsDicCache) + allCalculateFeeCoefficients.Value.Add(new CalculateFeeCoefficients { - allCalculateFeeCoefficients.Value.Add(new CalculateFeeCoefficients + FeeTokenType = coefficients.Key, + PieceCoefficientsList = { - FeeTokenType = coefficients.Key, - PieceCoefficientsList = + coefficients.Value.Select(v => new CalculateFeePieceCoefficients { - coefficients.Value.Select(v => new CalculateFeePieceCoefficients - { - Value = {v} - }) - } - }); - } - return allCalculateFeeCoefficients.ToCalculateFunctionDictionary(); - } + Value = { v } + }) + } + }); + return allCalculateFeeCoefficients.ToCalculateFunctionDictionary(); + } + + private enum FeeTypeEnum + { + Read = 0, + Storage = 1, + Write = 2, + Traffic = 3, + Tx = 4 } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/SampleAccount.cs b/src/AElf.ContractTestKit/SampleAccount.cs index bcc1df2750..f855c840f6 100644 --- a/src/AElf.ContractTestKit/SampleAccount.cs +++ b/src/AElf.ContractTestKit/SampleAccount.cs @@ -5,167 +5,166 @@ using AElf.Cryptography.ECDSA; using AElf.Types; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class SampleAccount { - public static class SampleAccount + public static IReadOnlyList Accounts; + + private static readonly string[] Keys = { - static SampleAccount() - { - Accounts = new ReadOnlyCollection( - Keys.Select(x => - { - var privateKeyHex = x.Split(",").First(); - var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); - var keyPair = CryptoHelper.FromPrivateKey(privateKey); - - return new Account - { - KeyPair = keyPair, - Address = Address.FromPublicKey(keyPair.PublicKey) - }; - }).ToList()); - } + "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", + "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", + "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", + "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", + "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", + "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", + "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", + "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", + "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", + "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", + "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", + "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", + "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", + "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", + "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", + "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", + "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", + "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", + "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", + "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", + "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", + "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", + "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", + "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", + "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", + "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", + "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", + "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", + "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", + "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", + "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", + "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", + "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", + "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", + "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", + "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", + "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", + "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", + "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", + "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", + "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", + "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", + "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", + "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", + "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", + "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", + "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", + "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", + "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", + "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", + "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", + "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", + "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", + "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", + "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", + "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", + "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", + "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", + "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", + "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", + "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", + "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", + "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", + "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", + "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", + "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", + "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", + "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", + "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", + "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", + "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", + "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", + "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", + "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", + "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", + "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", + "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", + "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", + "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", + "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", + "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", + "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", + "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", + "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", + "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", + "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", + "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", + "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", + "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", + "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", + "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", + "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", + "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", + "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", + "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", + "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", + "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", + "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", + "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", + "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1", + "76c4f4792b72678edcc8365a7ee75a3de023939fe3e4efb9c6537d2245a25db3,046ff7146633ee0ce0390f5760cbba2fa49f8fe4360edb0232bcbab34698b652f1749abff316a9ac8968cc135699e9156ee6727cc6f8a39fda4b822c76f077eb8b", + "d4a55450e3c711114ac65beb47f173ee6439e519b337bbd3159bf095a763ab07,0408ce3ef3c8a3a0edbb7035205a5a18c20d0db882ef764c7dcd14469f69f91c17390a657ff2148f137092a81f1ec328b109083279cb2dc4f1343caa7dac916d91", + "21b3b51a420a68267e26454dd07768f587122251f30420d4e6b2623a74cb7dd5,0480e5857aca871d40b776e805d119b416771bb4dc0a0ede9a571a69290e935761fbed8775bb947b3f6bdbfb7fbbaa6df4df04d1e861ca84130a65f23b6be7d9fb", + "bbcc0e97e84724f689d7abb74a7dbc6c85127439563fab4a6f4521d1a3701a03,04cffb78088a74842ec9abb2cbf9f2acb523315063e8244cc446ac586cffa2d79259a4c12e48453366e232b77617cc23fc14545a465bbcd712b12ade942b8aad01", + "3453beed7711c57b5795a682a6b264e7c3bc7af346e0dea3d764b9c7692ae384,0486d856261e92b2c4df266a69a28c2bb9ed8085c3295394bfc31e5abc57f33836a648cb10e308aba5d6cd6bcd76aabea8e33f315e222c0a7da3ae9cfe8cba6d8a", + "11a927387fa0cc7d161911fce0933d1151bddd4cbce51b08e4e9ad4fc192491b,04c6ad3821932c295424e2057460bfba0a3c2a210ebdb9aedce9cceb9b45915ca6a39cfdec326beae96102a932d65467b942088fd94f5ef3a9533859b7020cf540", + "772058f9c0361f79022212c9ae1f9ac9193524a4ae28b528d3454a7bac6dd42a,04ba722aa798e202e6f770eb5e940c7b9a7baff1682348a28a703442136de1c85d1dd8f9e3595c51b7160ab6a815a0d115df5eaddb683eb04d8a34c880fe5c7be5", + "0d0eb1c444546d09daa2f35c3f8332b5302dca12994e1fa5773f443379a539b1,0498e6abfb3e2a983420bd37ca886369d038cef274c9c605f493dd49fa0b2598716b3c16531ae84b0aeb5812215238914be4b33eeda6fd1e95ed5c19cbe5e8a670", + "a20ee6cd67fd1a533db2adbfc2124b2b109b2c43677b6ac34e1fc9969236faa7,04f7d136f4c95df5b7b4d72d196157912130558b03092a00d75fb7aebf2cbeca97343768e176f03f7cbccea616671127a53c08213b7b241bb734e45b89bd040fa9", + "50ac78772610e3700232df06d8ef9f8128007beeed98c21d19e381cf9d8dda4b,04a5665948b004634be699b306752c743578b85656a279e9e821b080d84b285b3779aba3f0cccd38119f6a964fb46369d33e661eb76db9c9f7cc277d319657cec3", + "e5d5fdb153fce928b0873985f166a89f30159fba8e96ac54d816d4db30313558,04414ef776662c95c6ece72ed39fdeaf236e09c1ee735e616ad9dcefb697b086128598a96347ac816ea5b2ef7d7b11365c2b2dbd81785605fca175cb69c9880251", + "44cdbcd03f5c1c1b5d5261f7d31a05eb57ec7714d6d8681579857551fd52f166,0420baae37eeca0594997f70b2a413e625418d6ca0911e2c303529a69f0bb50b02f834e4d021b6ec95dfeb328f96d58624a13ad2bd84bbb51bdb8dde578d50bb44", + "5a1d480438edd2725429a80e44df714e218ee4eec8e9e18a3a29da165ed76091,042817b6070f8b169e7bf7679f556fb4a50ac7c5dd16c92a7b7f792a9ec5f45e68f2ea31b8d48a54b6bb672dd113744d1f683e271d0cf19cc243454a4a97002310", + "2788e96e5cb2bc7072856fdcd55c14ef8915700202661be9a89b29494cb12459,049571146238b03183c1b6a92b54cb2167f5f803cae77dd6b2995ed6717e768d3108432c8dc4901d5a0a247a4102293f7c808c24bf380c26050a0fa91832e95faf", + "7eea650941c6dbd50c5260e7305a276ee5d1e894e982c5ba10416c0b24ac5001,04b1a54cf58c1d77d38d5962b36dfa5f3203bfdd7077ce6900c6aebbe8b73726dda1bb4416f3500617c9dffebe6bbb65197f403cfd7386b1a8ce98dae696b4c074", + "7ffdd97e69a8d3c36c7fee03672c6c6101f3f17220d43964bca8031fb93e9121,04856729deb6b3df719e75a719ed1e56d5c702862ad62c9ef5ec29212484d52612f0c1c0b26768992b2e4fa90e75992b2bc7d938f320b31023859da89f4f91a3dd", + "b1e760d8189963347f30c72a226ce6d07ed012eb4eeb9770bbfcaa0a1ad4f22b,04d6fee8c9b96185b4539eead39ee59219bc9590abe124e426519c6f7a7dcf2720d8cc810f45e8528819e7b353bafcafd4d0fa768c315bdcd823061f32b3cc8112", + "67e27d4ea0155697d637132f6ef075b70f16f7255245607ec6c4a8843e30a23c,049a2daad089c0340b41886c076294df3d369d3324570f4fe02c7411c374fe31841cfcc201676296dc52ca45e06506d6ec5c521b1faffe4193f15c0e76a82585fa", + "02401eacabbf16b0232db781da565108e59bdde0a5537f8ded889ae3aad19cb4,046f6337c7d9024ffb23359fc5ea456bb9c2ac6350aad68a8322a33a6eb71901d4dcf8e59745b83e69a9e04db9fd64ffa14b6aebc57b577d8b77ed44ac47f11a9b", + "a5176b0331dc5543f1ffb60d83b481210dc2d7d815f6844a3f942d5eea53d665,0479e8f6eec41c83a9727046996c6cd7c86635756e2c5add817831e1130a55f18fbbcc6945d072deed8601ccabd2b30ae6cf0f0483036954f4ed9440d1abc191c8", + "1347544be620547c3baeeb6ea8b8ed17667f9d0f78d23725c8cb6b2ab63f50f8,04756b5b0694e5f910ead249de6439081945791afda055cde92d9e288efef9b8561e23fd0a56a5beda264162b86b08f5c0ebdb938dfbaf973e06a1df0316509fa5", + "8769dc54b9e94bd705cec137a956bbe921eb2a97c5b05b6d7af2eb87ec7d391e,04f8b0fc524ad7d468c74961b3640631460e7b00d832e3f6a32343763892fdf03bc6d67e93915e74d7fb7dcd2fff0ad7b4c1262b6fa97811c4a09e9dd7f720efb7", + "72aadf4b72fb13724382e95cb17d39da9834a50f747f0dc27c569ada13f1a988,04eb6a933ac85f142b60a1b27d80bcf9fcda1ec51afc9c2c44c8bb2850d6c5fa85f93d2512e1f23d743c32269d622f0243c69558527f1c25b917179224dea047c4", + "ed606a6c36a5ce73469945001f3c5845f704a00d07195e53d024280f9b8c6a26,044dcd4c72aea835b1fed73506f5fb11ee09ce20c8eb901f518ba94e1df02fb78df368cd07ec98632c89ef1514304a799923817a062505e142015bbbc6b812a71a", + "72bc1525d9f90959e8fd49833d6d130fef0f4acb99651b2d50e62e47328dbbef,04f421d26b81813d1157c922eeca82b5f356c2cf7a6b1f1ff9b86c609942c70ef9f3c28fd21f4cf6ed278f6f4eea55f3d7ddc403dc2c5b93c87558c6c43556e98b", + "99c765d7a4b746f8db7f3570577f3f6c36c6864545ea1adcf09bcb50ce3bef79,0481f288d081c093a7f3a64b1e67abb8b7f76ce585256bdf6a5919551032755d1193ae3926c76da10bcc8de2f6720fca87d3bf8d6e2914fd53e2c03da6397a31d4", + "6ee0da06418ac1f0006cea79c6741eb42ee0c1a125795918b6c883ccfbe1476c,04884491ebb3f43266b40afddd256502e1c5975c3d3cf5f3889e0586236f1b4455ac36e27f7b500803fdc34a71d5696750fbadbc2cc5b0e302751675e5e5122201", + "d1dfaa8e752ca7f6aec619e8726883c6048c635b6109b240307e029bd05efe7a,04c916226209f7256b29c31faf98811094194e1baeba0edbc31340ba79f984452039a626664bf8f17baa0efdab481449966687d77c0b01b71f22903548b0642f44", + "055832877713f9d284421f55b26c60ef6ff4a92eaf2d45422a6b0285dd555d6a,04ae59215cb0424fe66f868b13f807df7dd7c588830ca163ccd91b96c665ba218d8f9ee0b3a4d749946a6530be9c1b78ea267f55187f06162928e657985e7a776d", + "f7c10cc06f0f64b772c453c7cc056c54b00d14353db0521a34c04af8208da4b2,04d7cf0b10a684bc536b473a8512c91f4b172e95dad42ff71268e49f56a6492f2e1f134cf03b702203b4d1b259788e86bb8ac7ba7b9afcc1497a989cf822974d77" + }; - public static IReadOnlyList Accounts; + static SampleAccount() + { + Accounts = new ReadOnlyCollection( + Keys.Select(x => + { + var privateKeyHex = x.Split(",").First(); + var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); + var keyPair = CryptoHelper.FromPrivateKey(privateKey); - private static readonly string[] Keys = - { - "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", - "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", - "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", - "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", - "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", - "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", - "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", - "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", - "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", - "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", - "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", - "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", - "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", - "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", - "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", - "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", - "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", - "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", - "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", - "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", - "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", - "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", - "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", - "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", - "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", - "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", - "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", - "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", - "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", - "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", - "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", - "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", - "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", - "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", - "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", - "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", - "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", - "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", - "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", - "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", - "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", - "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", - "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", - "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", - "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", - "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", - "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", - "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", - "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", - "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", - "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", - "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", - "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", - "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", - "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", - "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", - "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", - "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", - "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", - "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", - "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", - "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", - "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", - "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", - "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", - "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", - "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", - "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", - "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", - "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", - "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", - "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", - "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", - "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", - "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", - "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", - "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", - "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", - "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", - "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", - "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", - "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", - "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", - "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", - "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", - "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", - "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", - "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", - "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", - "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", - "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", - "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", - "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", - "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", - "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", - "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", - "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", - "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", - "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", - "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1", - "76c4f4792b72678edcc8365a7ee75a3de023939fe3e4efb9c6537d2245a25db3,046ff7146633ee0ce0390f5760cbba2fa49f8fe4360edb0232bcbab34698b652f1749abff316a9ac8968cc135699e9156ee6727cc6f8a39fda4b822c76f077eb8b", - "d4a55450e3c711114ac65beb47f173ee6439e519b337bbd3159bf095a763ab07,0408ce3ef3c8a3a0edbb7035205a5a18c20d0db882ef764c7dcd14469f69f91c17390a657ff2148f137092a81f1ec328b109083279cb2dc4f1343caa7dac916d91", - "21b3b51a420a68267e26454dd07768f587122251f30420d4e6b2623a74cb7dd5,0480e5857aca871d40b776e805d119b416771bb4dc0a0ede9a571a69290e935761fbed8775bb947b3f6bdbfb7fbbaa6df4df04d1e861ca84130a65f23b6be7d9fb", - "bbcc0e97e84724f689d7abb74a7dbc6c85127439563fab4a6f4521d1a3701a03,04cffb78088a74842ec9abb2cbf9f2acb523315063e8244cc446ac586cffa2d79259a4c12e48453366e232b77617cc23fc14545a465bbcd712b12ade942b8aad01", - "3453beed7711c57b5795a682a6b264e7c3bc7af346e0dea3d764b9c7692ae384,0486d856261e92b2c4df266a69a28c2bb9ed8085c3295394bfc31e5abc57f33836a648cb10e308aba5d6cd6bcd76aabea8e33f315e222c0a7da3ae9cfe8cba6d8a", - "11a927387fa0cc7d161911fce0933d1151bddd4cbce51b08e4e9ad4fc192491b,04c6ad3821932c295424e2057460bfba0a3c2a210ebdb9aedce9cceb9b45915ca6a39cfdec326beae96102a932d65467b942088fd94f5ef3a9533859b7020cf540", - "772058f9c0361f79022212c9ae1f9ac9193524a4ae28b528d3454a7bac6dd42a,04ba722aa798e202e6f770eb5e940c7b9a7baff1682348a28a703442136de1c85d1dd8f9e3595c51b7160ab6a815a0d115df5eaddb683eb04d8a34c880fe5c7be5", - "0d0eb1c444546d09daa2f35c3f8332b5302dca12994e1fa5773f443379a539b1,0498e6abfb3e2a983420bd37ca886369d038cef274c9c605f493dd49fa0b2598716b3c16531ae84b0aeb5812215238914be4b33eeda6fd1e95ed5c19cbe5e8a670", - "a20ee6cd67fd1a533db2adbfc2124b2b109b2c43677b6ac34e1fc9969236faa7,04f7d136f4c95df5b7b4d72d196157912130558b03092a00d75fb7aebf2cbeca97343768e176f03f7cbccea616671127a53c08213b7b241bb734e45b89bd040fa9", - "50ac78772610e3700232df06d8ef9f8128007beeed98c21d19e381cf9d8dda4b,04a5665948b004634be699b306752c743578b85656a279e9e821b080d84b285b3779aba3f0cccd38119f6a964fb46369d33e661eb76db9c9f7cc277d319657cec3", - "e5d5fdb153fce928b0873985f166a89f30159fba8e96ac54d816d4db30313558,04414ef776662c95c6ece72ed39fdeaf236e09c1ee735e616ad9dcefb697b086128598a96347ac816ea5b2ef7d7b11365c2b2dbd81785605fca175cb69c9880251", - "44cdbcd03f5c1c1b5d5261f7d31a05eb57ec7714d6d8681579857551fd52f166,0420baae37eeca0594997f70b2a413e625418d6ca0911e2c303529a69f0bb50b02f834e4d021b6ec95dfeb328f96d58624a13ad2bd84bbb51bdb8dde578d50bb44", - "5a1d480438edd2725429a80e44df714e218ee4eec8e9e18a3a29da165ed76091,042817b6070f8b169e7bf7679f556fb4a50ac7c5dd16c92a7b7f792a9ec5f45e68f2ea31b8d48a54b6bb672dd113744d1f683e271d0cf19cc243454a4a97002310", - "2788e96e5cb2bc7072856fdcd55c14ef8915700202661be9a89b29494cb12459,049571146238b03183c1b6a92b54cb2167f5f803cae77dd6b2995ed6717e768d3108432c8dc4901d5a0a247a4102293f7c808c24bf380c26050a0fa91832e95faf", - "7eea650941c6dbd50c5260e7305a276ee5d1e894e982c5ba10416c0b24ac5001,04b1a54cf58c1d77d38d5962b36dfa5f3203bfdd7077ce6900c6aebbe8b73726dda1bb4416f3500617c9dffebe6bbb65197f403cfd7386b1a8ce98dae696b4c074", - "7ffdd97e69a8d3c36c7fee03672c6c6101f3f17220d43964bca8031fb93e9121,04856729deb6b3df719e75a719ed1e56d5c702862ad62c9ef5ec29212484d52612f0c1c0b26768992b2e4fa90e75992b2bc7d938f320b31023859da89f4f91a3dd", - "b1e760d8189963347f30c72a226ce6d07ed012eb4eeb9770bbfcaa0a1ad4f22b,04d6fee8c9b96185b4539eead39ee59219bc9590abe124e426519c6f7a7dcf2720d8cc810f45e8528819e7b353bafcafd4d0fa768c315bdcd823061f32b3cc8112", - "67e27d4ea0155697d637132f6ef075b70f16f7255245607ec6c4a8843e30a23c,049a2daad089c0340b41886c076294df3d369d3324570f4fe02c7411c374fe31841cfcc201676296dc52ca45e06506d6ec5c521b1faffe4193f15c0e76a82585fa", - "02401eacabbf16b0232db781da565108e59bdde0a5537f8ded889ae3aad19cb4,046f6337c7d9024ffb23359fc5ea456bb9c2ac6350aad68a8322a33a6eb71901d4dcf8e59745b83e69a9e04db9fd64ffa14b6aebc57b577d8b77ed44ac47f11a9b", - "a5176b0331dc5543f1ffb60d83b481210dc2d7d815f6844a3f942d5eea53d665,0479e8f6eec41c83a9727046996c6cd7c86635756e2c5add817831e1130a55f18fbbcc6945d072deed8601ccabd2b30ae6cf0f0483036954f4ed9440d1abc191c8", - "1347544be620547c3baeeb6ea8b8ed17667f9d0f78d23725c8cb6b2ab63f50f8,04756b5b0694e5f910ead249de6439081945791afda055cde92d9e288efef9b8561e23fd0a56a5beda264162b86b08f5c0ebdb938dfbaf973e06a1df0316509fa5", - "8769dc54b9e94bd705cec137a956bbe921eb2a97c5b05b6d7af2eb87ec7d391e,04f8b0fc524ad7d468c74961b3640631460e7b00d832e3f6a32343763892fdf03bc6d67e93915e74d7fb7dcd2fff0ad7b4c1262b6fa97811c4a09e9dd7f720efb7", - "72aadf4b72fb13724382e95cb17d39da9834a50f747f0dc27c569ada13f1a988,04eb6a933ac85f142b60a1b27d80bcf9fcda1ec51afc9c2c44c8bb2850d6c5fa85f93d2512e1f23d743c32269d622f0243c69558527f1c25b917179224dea047c4", - "ed606a6c36a5ce73469945001f3c5845f704a00d07195e53d024280f9b8c6a26,044dcd4c72aea835b1fed73506f5fb11ee09ce20c8eb901f518ba94e1df02fb78df368cd07ec98632c89ef1514304a799923817a062505e142015bbbc6b812a71a", - "72bc1525d9f90959e8fd49833d6d130fef0f4acb99651b2d50e62e47328dbbef,04f421d26b81813d1157c922eeca82b5f356c2cf7a6b1f1ff9b86c609942c70ef9f3c28fd21f4cf6ed278f6f4eea55f3d7ddc403dc2c5b93c87558c6c43556e98b", - "99c765d7a4b746f8db7f3570577f3f6c36c6864545ea1adcf09bcb50ce3bef79,0481f288d081c093a7f3a64b1e67abb8b7f76ce585256bdf6a5919551032755d1193ae3926c76da10bcc8de2f6720fca87d3bf8d6e2914fd53e2c03da6397a31d4", - "6ee0da06418ac1f0006cea79c6741eb42ee0c1a125795918b6c883ccfbe1476c,04884491ebb3f43266b40afddd256502e1c5975c3d3cf5f3889e0586236f1b4455ac36e27f7b500803fdc34a71d5696750fbadbc2cc5b0e302751675e5e5122201", - "d1dfaa8e752ca7f6aec619e8726883c6048c635b6109b240307e029bd05efe7a,04c916226209f7256b29c31faf98811094194e1baeba0edbc31340ba79f984452039a626664bf8f17baa0efdab481449966687d77c0b01b71f22903548b0642f44", - "055832877713f9d284421f55b26c60ef6ff4a92eaf2d45422a6b0285dd555d6a,04ae59215cb0424fe66f868b13f807df7dd7c588830ca163ccd91b96c665ba218d8f9ee0b3a4d749946a6530be9c1b78ea267f55187f06162928e657985e7a776d", - "f7c10cc06f0f64b772c453c7cc056c54b00d14353db0521a34c04af8208da4b2,04d7cf0b10a684bc536b473a8512c91f4b172e95dad42ff71268e49f56a6492f2e1f134cf03b702203b4d1b259788e86bb8ac7ba7b9afcc1497a989cf822974d77", - }; + return new Account + { + KeyPair = keyPair, + Address = Address.FromPublicKey(keyPair.PublicKey) + }; + }).ToList()); } +} - public class Account - { - public ECKeyPair KeyPair { get; set; } - public Address Address { get; set; } - } +public class Account +{ + public ECKeyPair KeyPair { get; set; } + public Address Address { get; set; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/SampleAddress.cs b/src/AElf.ContractTestKit/SampleAddress.cs index b044ddc203..9939c521de 100644 --- a/src/AElf.ContractTestKit/SampleAddress.cs +++ b/src/AElf.ContractTestKit/SampleAddress.cs @@ -1,32 +1,31 @@ -using AElf.Types; -using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; +using AElf.Types; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class SampleAddress { - public static class SampleAddress - { - public static readonly IReadOnlyList
AddressList; + public static readonly IReadOnlyList
AddressList; - private static readonly string[] Base58Strings = - { - "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", - "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", - "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", - "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", - "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", - "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", - "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", - "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", - "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", - "XgCfhmyzhtYMfcEy9CbY6sjDAtThVwfRFRu66VhXQpjxNtQ6Q" - }; + private static readonly string[] Base58Strings = + { + "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", + "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", + "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", + "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", + "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", + "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", + "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", + "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", + "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", + "XgCfhmyzhtYMfcEy9CbY6sjDAtThVwfRFRu66VhXQpjxNtQ6Q" + }; - static SampleAddress() - { - AddressList = new ReadOnlyCollection
( - Base58Strings.Select(Address.FromBase58).ToList()); - } + static SampleAddress() + { + AddressList = new ReadOnlyCollection
( + Base58Strings.Select(Address.FromBase58).ToList()); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/SmartContractTestConstants.cs b/src/AElf.ContractTestKit/SmartContractTestConstants.cs index 5e746d2d7d..b209938139 100644 --- a/src/AElf.ContractTestKit/SmartContractTestConstants.cs +++ b/src/AElf.ContractTestKit/SmartContractTestConstants.cs @@ -1,12 +1,11 @@ using AElf.Kernel; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class SmartContractTestConstants { - public static class SmartContractTestConstants - { - /// - /// 30 means use default assembly loader context, for code coverage - /// - public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; - } + /// + /// 30 means use default assembly loader context, for code coverage + /// + public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/TestTransactionExecutor.cs b/src/AElf.ContractTestKit/TestTransactionExecutor.cs index 05a5439170..83680a5ab9 100644 --- a/src/AElf.ContractTestKit/TestTransactionExecutor.cs +++ b/src/AElf.ContractTestKit/TestTransactionExecutor.cs @@ -12,96 +12,91 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class TestTransactionExecutor : ITestTransactionExecutor { - public class TestTransactionExecutor : ITestTransactionExecutor + private readonly IServiceProvider _serviceProvider; + + public TestTransactionExecutor(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public async Task ExecuteAsync(Transaction transaction) + { + var transactionResult = await ExecuteTransactionAsync(transaction); + if (transactionResult == null || transactionResult.Status != TransactionResultStatus.Mined) + throw new Exception($"Failed to execute {transaction.MethodName}. {transactionResult?.Error}"); + return transactionResult; + } + + public async Task ExecuteWithExceptionAsync(Transaction transaction) { - private readonly IServiceProvider _serviceProvider; - - public TestTransactionExecutor(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public async Task ExecuteAsync(Transaction transaction) - { - var transactionResult = await ExecuteTransactionAsync(transaction); - if (transactionResult == null || transactionResult.Status != TransactionResultStatus.Mined) - throw new Exception($"Failed to execute {transaction.MethodName}. {transactionResult?.Error}"); - return transactionResult; - } - - public async Task ExecuteWithExceptionAsync(Transaction transaction) - { - var transactionResult = await ExecuteTransactionAsync(transaction); - if (transactionResult.Status == TransactionResultStatus.Mined) + var transactionResult = await ExecuteTransactionAsync(transaction); + if (transactionResult.Status == TransactionResultStatus.Mined) + throw new Exception($"Succeed to execute {transaction.MethodName}."); + + return transactionResult; + } + + public async Task ReadAsync(Transaction transaction) + { + var transactionTrace = await ReadTransactionResultAsync(transaction); + if (transactionTrace.ExecutionStatus != ExecutionStatus.Executed) + throw new Exception($"Failed to call {transaction.MethodName}. {transactionTrace.Error}"); + return transactionTrace.ReturnValue; + } + + public async Task ReadWithExceptionAsync(Transaction transaction) + { + var transactionTrace = await ReadTransactionResultAsync(transaction); + if (transactionTrace.ExecutionStatus == ExecutionStatus.Executed) + throw new Exception($"Succeed to call {transaction.MethodName}."); + + return new StringValue { Value = transactionTrace.Error }; + } + + private async Task ExecuteTransactionAsync(Transaction transaction) + { + var blockchainService = _serviceProvider.GetRequiredService(); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var miningService = _serviceProvider.GetRequiredService(); + var blockAttachService = _serviceProvider.GetRequiredService(); + var blockTimeProvider = _serviceProvider.GetRequiredService(); + + var transactions = new List { transaction }; + var blockExecutedSet = await miningService.MineAsync( + new RequestMiningDto { - throw new Exception($"Succeed to execute {transaction.MethodName}."); - } - - return transactionResult; - } - - private async Task ExecuteTransactionAsync(Transaction transaction) - { - var blockchainService = _serviceProvider.GetRequiredService(); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var miningService = _serviceProvider.GetRequiredService(); - var blockAttachService = _serviceProvider.GetRequiredService(); - var blockTimeProvider = _serviceProvider.GetRequiredService(); - - var transactions = new List {transaction}; - var blockExecutedSet = await miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = int.MaxValue - }, transactions, blockTimeProvider.GetBlockTime()); - - var block = blockExecutedSet.Block; - - await blockchainService.AddTransactionsAsync(transactions); - await blockchainService.AddBlockAsync(block); - await blockAttachService.AttachBlockAsync(block); - - return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; - } - - public async Task ReadAsync(Transaction transaction) - { - var transactionTrace = await ReadTransactionResultAsync(transaction); - if (transactionTrace.ExecutionStatus != ExecutionStatus.Executed) - throw new Exception($"Failed to call {transaction.MethodName}. {transactionTrace.Error}"); - return transactionTrace.ReturnValue; - } - - public async Task ReadWithExceptionAsync(Transaction transaction) - { - var transactionTrace = await ReadTransactionResultAsync(transaction); - if (transactionTrace.ExecutionStatus == ExecutionStatus.Executed) + PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, transactions, blockTimeProvider.GetBlockTime()); + + var block = blockExecutedSet.Block; + + await blockchainService.AddTransactionsAsync(transactions); + await blockchainService.AddBlockAsync(block); + await blockAttachService.AttachBlockAsync(block); + + return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; + } + + private async Task ReadTransactionResultAsync(Transaction transaction) + { + var blockchainService = _serviceProvider.GetRequiredService(); + var transactionReadOnlyExecutionService = + _serviceProvider.GetRequiredService(); + var blockTimeProvider = _serviceProvider.GetRequiredService(); + + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + return await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext { - throw new Exception($"Succeed to call {transaction.MethodName}."); - } - - return new StringValue {Value = transactionTrace.Error}; - } - - private async Task ReadTransactionResultAsync(Transaction transaction) - { - var blockchainService = _serviceProvider.GetRequiredService(); - var transactionReadOnlyExecutionService = - _serviceProvider.GetRequiredService(); - var blockTimeProvider = _serviceProvider.GetRequiredService(); - - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - return await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = preBlock.GetHash(), - BlockHeight = preBlock.Height - }, - transaction, - blockTimeProvider.GetBlockTime()); - } + BlockHash = preBlock.GetHash(), + BlockHeight = preBlock.Height + }, + transaction, + blockTimeProvider.GetBlockTime()); } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/UnitTestContractZeroCodeProvider.cs b/src/AElf.ContractTestKit/UnitTestContractZeroCodeProvider.cs index 1affce7008..dca0429f44 100644 --- a/src/AElf.ContractTestKit/UnitTestContractZeroCodeProvider.cs +++ b/src/AElf.ContractTestKit/UnitTestContractZeroCodeProvider.cs @@ -4,18 +4,17 @@ using AElf.Kernel.SmartContract.Infrastructure; using Microsoft.Extensions.Options; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider { - public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider + public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, + IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) { - public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, - IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) - { - } + } - protected override int GetCategory() - { - return KernelConstants.CodeCoverageRunnerCategory; - } + protected override int GetCategory() + { + return KernelConstants.CodeCoverageRunnerCategory; } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/UnitTestSmartContractAddressService.cs b/src/AElf.ContractTestKit/UnitTestSmartContractAddressService.cs index c3479f0023..a61b1bffd3 100644 --- a/src/AElf.ContractTestKit/UnitTestSmartContractAddressService.cs +++ b/src/AElf.ContractTestKit/UnitTestSmartContractAddressService.cs @@ -10,39 +10,35 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public class UnitTestSmartContractAddressService : SmartContractAddressService { - public class UnitTestSmartContractAddressService : SmartContractAddressService + private readonly ConcurrentDictionary _hashToAddressMap = new(); + + public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + ISmartContractAddressProvider smartContractAddressProvider, + IEnumerable smartContractAddressNameProviders, + IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, + transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, + blockchainService) + { + } + + public override async Task> GetSystemContractNameToAddressMappingAsync( + IChainContext chainContext) + { + var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); + var dictionary = new Dictionary(); + foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) + dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); + return new ReadOnlyDictionary(dictionary); + } + + public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) { - private readonly ConcurrentDictionary _hashToAddressMap = - new ConcurrentDictionary(); - - public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - ISmartContractAddressProvider smartContractAddressProvider, - IEnumerable smartContractAddressNameProviders, - IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, - transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, - blockchainService) - { - } - - public override async Task> GetSystemContractNameToAddressMappingAsync( - IChainContext chainContext) - { - var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); - var dictionary = new Dictionary(); - foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) - { - dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); - } - return new ReadOnlyDictionary(dictionary); - } - - public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) - { - _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; - return base.SetSmartContractAddressAsync(blockIndex, contractName, address); - } + _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; + return base.SetSmartContractAddressAsync(blockIndex, contractName, address); } } \ No newline at end of file diff --git a/src/AElf.Core/AElf.Core.csproj b/src/AElf.Core/AElf.Core.csproj index 2009e20c42..01ffb3ff04 100644 --- a/src/AElf.Core/AElf.Core.csproj +++ b/src/AElf.Core/AElf.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/src/AElf.Core/AElfDefaultConventionalRegistrar.cs b/src/AElf.Core/AElfDefaultConventionalRegistrar.cs index 9646d060ad..84edee5641 100644 --- a/src/AElf.Core/AElfDefaultConventionalRegistrar.cs +++ b/src/AElf.Core/AElfDefaultConventionalRegistrar.cs @@ -4,36 +4,28 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; -namespace AElf +namespace AElf; + +public class AElfDefaultConventionalRegistrar : DefaultConventionalRegistrar { - public class AElfDefaultConventionalRegistrar : DefaultConventionalRegistrar - { - private readonly List _transientTypeSuffixes = - new() { "Service", "Provider", "Manager", "Store", "Factory" }; + private readonly List _transientTypeSuffixes = + new() { "Service", "Provider", "Manager", "Store", "Factory" }; - protected override ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type) - { - //Get ABP lifetime from ABP interface, ITransientDependency,ISingletonDependency or IScopedDependency - var lifeTime = base.GetServiceLifetimeFromClassHierarchy(type); - if (lifeTime != null) - { - return null; - } + protected override ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type) + { + //Get ABP lifetime from ABP interface, ITransientDependency,ISingletonDependency or IScopedDependency + var lifeTime = base.GetServiceLifetimeFromClassHierarchy(type); + if (lifeTime != null) return null; - //if no lifetime interface was found, try to get class with the same interface, - //HelloService -> IHelloService - //HelloManager -> IHelloManager - var interfaceName = "I" + type.Name; + //if no lifetime interface was found, try to get class with the same interface, + //HelloService -> IHelloService + //HelloManager -> IHelloManager + var interfaceName = "I" + type.Name; - if (type.GetInterfaces().Any(p => p.Name == interfaceName)) - { - if (_transientTypeSuffixes.Any(suffix => type.Name.EndsWith(suffix))) - { - return ServiceLifetime.Transient; - } - } + if (type.GetInterfaces().Any(p => p.Name == interfaceName)) + if (_transientTypeSuffixes.Any(suffix => type.Name.EndsWith(suffix))) + return ServiceLifetime.Transient; - return null; - } + return null; } } \ No newline at end of file diff --git a/src/AElf.Core/CoreAElfModule.cs b/src/AElf.Core/CoreAElfModule.cs index 4969c97ae5..37318a0a9b 100644 --- a/src/AElf.Core/CoreAElfModule.cs +++ b/src/AElf.Core/CoreAElfModule.cs @@ -7,79 +7,78 @@ using Microsoft.Extensions.Options; using Volo.Abp.Modularity; -namespace AElf +namespace AElf; + +public class CoreAElfModule : AElfModule { - public class CoreAElfModule : AElfModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddConventionalRegistrar(new AElfDefaultConventionalRegistrar()); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(typeof(IServiceContainer<>), - typeof(ServiceContainerFactory<>)); - } + context.Services.AddConventionalRegistrar(new AElfDefaultConventionalRegistrar()); } - public static class ServiceProviderExtensions + public override void ConfigureServices(ServiceConfigurationContext context) { - public static IEnumerable GetServices(this IServiceProvider provider, IEnumerable types) - { - return types.Select(type => (T) provider.GetService(type)); - } - - /*public static IEnumerable GetServices(this IServiceProvider provider, params Type[] types) - { - return provider.GetServices((IEnumerable) types); - }*/ + context.Services.AddTransient(typeof(IServiceContainer<>), + typeof(ServiceContainerFactory<>)); } +} - public interface IServiceContainer : IEnumerable +public static class ServiceProviderExtensions +{ + public static IEnumerable GetServices(this IServiceProvider provider, IEnumerable types) { + return types.Select(type => (T)provider.GetService(type)); } + /*public static IEnumerable GetServices(this IServiceProvider provider, params Type[] types) + { + return provider.GetServices((IEnumerable) types); + }*/ +} - public class ServiceContainerFactoryOptions +public interface IServiceContainer : IEnumerable +{ +} + +public class ServiceContainerFactoryOptions +{ + /// + /// if Types is null, it will return all services of T + /// + public List Types { get; set; } +} + +public class ServiceContainerFactory : IServiceContainer +{ + private readonly IEnumerable _services; + + private ServiceContainerFactory() { - /// - /// if Types is null, it will return all services of T - /// - public List Types { get; set; } + _services = Enumerable.Empty(); } - public class ServiceContainerFactory : IServiceContainer + public ServiceContainerFactory(IOptionsSnapshot> options, + IServiceProvider serviceProvider) { - public static ServiceContainerFactory Empty { get; } = new ServiceContainerFactory(); - private readonly IEnumerable _services; - - private ServiceContainerFactory() + if (options.Value.Types == null) { - _services = Enumerable.Empty(); + _services = serviceProvider.GetServices(); + return; } - public ServiceContainerFactory(IOptionsSnapshot> options, - IServiceProvider serviceProvider) - { - if (options.Value.Types == null) - { - _services = serviceProvider.GetServices(); - return; - } + _services = serviceProvider.GetServices(options.Value.Types); + } - _services = serviceProvider.GetServices(options.Value.Types); - } + public static ServiceContainerFactory Empty { get; } = new(); - public IEnumerator GetEnumerator() - { - return _services.GetEnumerator(); - } + public IEnumerator GetEnumerator() + { + return _services.GetEnumerator(); + } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); } } \ No newline at end of file diff --git a/src/AElf.Core/ITaskQueue.cs b/src/AElf.Core/ITaskQueue.cs index 67ff8a0cb7..709ee7209c 100644 --- a/src/AElf.Core/ITaskQueue.cs +++ b/src/AElf.Core/ITaskQueue.cs @@ -1,166 +1,154 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Threading; -namespace AElf +namespace AElf; + +public interface ITaskQueue : IDisposable { - public interface ITaskQueue : IDisposable - { - void Enqueue(Func task); - int Size { get; } + int Size { get; } - int MaxDegreeOfParallelism { get; } + int MaxDegreeOfParallelism { get; } + void Enqueue(Func task); - void Start(int maxDegreeOfParallelism = 1); - } + void Start(int maxDegreeOfParallelism = 1); +} + +public class TaskQueue : ITaskQueue, ITransientDependency +{ + private ActionBlock> _actionBlock; - public class TaskQueue : ITaskQueue, ITransientDependency + public TaskQueue() { - private ActionBlock> _actionBlock; + Logger = NullLogger.Instance; + } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - public int Size => _actionBlock.InputCount; - public int MaxDegreeOfParallelism { get; private set; } = 1; + public int Size => _actionBlock.InputCount; + public int MaxDegreeOfParallelism { get; private set; } = 1; - public void Start(int maxDegreeOfParallelism = 1) - { - if (_actionBlock != null) - throw new InvalidOperationException("already started"); + public void Start(int maxDegreeOfParallelism = 1) + { + if (_actionBlock != null) + throw new InvalidOperationException("already started"); - MaxDegreeOfParallelism = maxDegreeOfParallelism; + MaxDegreeOfParallelism = maxDegreeOfParallelism; - _actionBlock = new ActionBlock>(async func => + _actionBlock = new ActionBlock>(async func => + { + try { - try - { - await func(); - } - catch (Exception ex) - { - Logger.LogException(ex, LogLevel.Warning); - } - }, new ExecutionDataflowBlockOptions() + await func(); + } + catch (Exception ex) { - MaxDegreeOfParallelism = MaxDegreeOfParallelism - }); - } - - public TaskQueue() - { - Logger = NullLogger.Instance; - } - - public void Dispose() - { - _actionBlock.Complete(); - - _actionBlock.Completion.Wait(); - } - - public void Enqueue(Func task) + Logger.LogException(ex, LogLevel.Warning); + } + }, new ExecutionDataflowBlockOptions { - if (!_actionBlock.Post(task)) - throw new InvalidOperationException("unable to enqueue a task"); - } + MaxDegreeOfParallelism = MaxDegreeOfParallelism + }); } - - public interface ITaskQueueManager : IDisposable + public void Dispose() { - ITaskQueue GetQueue(string name = null); - - ITaskQueue CreateQueue(string name, int maxDegreeOfParallelism = 1); + _actionBlock.Complete(); - List GetQueueStatus(); + _actionBlock.Completion.Wait(); } - public static class TaskQueueManagerExtensions + public void Enqueue(Func task) { - public static void Enqueue(this ITaskQueueManager taskQueueManager, Func task, string name = null) - { - var queue = taskQueueManager.GetQueue(name); - queue.Enqueue(task); - } + if (!_actionBlock.Post(task)) + throw new InvalidOperationException("unable to enqueue a task"); } +} + +public interface ITaskQueueManager : IDisposable +{ + ITaskQueue GetQueue(string name = null); + + ITaskQueue CreateQueue(string name, int maxDegreeOfParallelism = 1); + + List GetQueueStatus(); +} - public class TaskQueueManager : ITaskQueueManager, ISingletonDependency +public static class TaskQueueManagerExtensions +{ + public static void Enqueue(this ITaskQueueManager taskQueueManager, Func task, string name = null) { - private readonly IServiceProvider _serviceProvider; + var queue = taskQueueManager.GetQueue(name); + queue.Enqueue(task); + } +} - private readonly ITaskQueue _defaultTaskQueue; +public class TaskQueueManager : ITaskQueueManager, ISingletonDependency +{ + private readonly ITaskQueue _defaultTaskQueue; + private readonly IServiceProvider _serviceProvider; - private readonly ConcurrentDictionary _taskQueues = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _taskQueues = new(); - public TaskQueueManager(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; + public TaskQueueManager(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; - _defaultTaskQueue = _serviceProvider.GetService(); - _defaultTaskQueue.Start(); - } + _defaultTaskQueue = _serviceProvider.GetService(); + _defaultTaskQueue.Start(); + } - public void Dispose() - { - _defaultTaskQueue.Dispose(); - foreach (var taskQueue in _taskQueues.Values) - { - taskQueue.Dispose(); - } - } + public void Dispose() + { + _defaultTaskQueue.Dispose(); + foreach (var taskQueue in _taskQueues.Values) taskQueue.Dispose(); + } - public ITaskQueue GetQueue(string name = null) - { - if (name == null) - return _defaultTaskQueue; + public ITaskQueue GetQueue(string name = null) + { + if (name == null) + return _defaultTaskQueue; - _taskQueues.TryGetValue(name, out var queue); - return queue; - } + _taskQueues.TryGetValue(name, out var queue); + return queue; + } - public ITaskQueue CreateQueue(string name, int maxDegreeOfParallelism) - { - var q = _serviceProvider.GetService(); - q.Start(maxDegreeOfParallelism); + public ITaskQueue CreateQueue(string name, int maxDegreeOfParallelism) + { + var q = _serviceProvider.GetService(); + q.Start(maxDegreeOfParallelism); - if (!_taskQueues.TryAdd(name, q)) - { - throw new InvalidOperationException("queue already created"); - } + if (!_taskQueues.TryAdd(name, q)) throw new InvalidOperationException("queue already created"); - return q; - } + return q; + } - public List GetQueueStatus() + public List GetQueueStatus() + { + var result = new List(); + foreach (var taskQueueName in _taskQueues.Keys) { - var result = new List(); - foreach (var taskQueueName in _taskQueues.Keys) + _taskQueues.TryGetValue(taskQueueName, out var queue); + result.Add(new TaskQueueInfo { - _taskQueues.TryGetValue(taskQueueName, out var queue); - result.Add(new TaskQueueInfo - { - Name = taskQueueName, - Size = queue?.Size ?? 0 - }); - } - - return result; + Name = taskQueueName, + Size = queue?.Size ?? 0 + }); } + + return result; } +} - public class TaskQueueInfo - { - public string Name { get; set; } +public class TaskQueueInfo +{ + public string Name { get; set; } - public int Size { get; set; } - } + public int Size { get; set; } } \ No newline at end of file diff --git a/src/AElf.Core/LoggerExtensions.cs b/src/AElf.Core/LoggerExtensions.cs index d045d4403b..dac56c66c4 100644 --- a/src/AElf.Core/LoggerExtensions.cs +++ b/src/AElf.Core/LoggerExtensions.cs @@ -1,16 +1,14 @@ using System; -using System.Linq.Expressions; using Microsoft.Extensions.Logging; -namespace AElf +namespace AElf; + +public static class LoggerExtensions { - public static class LoggerExtensions + public static void LogTrace(this ILogger logger, Func func) { - public static void LogTrace(this ILogger logger, Func func) - { #if DEBUG - logger.LogTrace(func()); + logger.LogTrace(func()); #endif - } } } \ No newline at end of file diff --git a/src/AElf.Core/Modularity/AElfModule.cs b/src/AElf.Core/Modularity/AElfModule.cs index 72d4859ef4..22f8313aed 100644 --- a/src/AElf.Core/Modularity/AElfModule.cs +++ b/src/AElf.Core/Modularity/AElfModule.cs @@ -1,18 +1,17 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Modularity +namespace AElf.Modularity; + +public abstract class AElfModule : AbpModule { - public abstract class AElfModule : AbpModule - { - } +} - public abstract class AElfModule : AElfModule - where TSelf : AElfModule +public abstract class AElfModule : AElfModule + where TSelf : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - } + context.Services.AddAssemblyOf(); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/AElf.CrossChain.Core.csproj b/src/AElf.CrossChain.Core/AElf.CrossChain.Core.csproj index a9d9f93a1a..310eb85cdb 100644 --- a/src/AElf.CrossChain.Core/AElf.CrossChain.Core.csproj +++ b/src/AElf.CrossChain.Core/AElf.CrossChain.Core.csproj @@ -8,8 +8,9 @@ Core functionality for crosschain operations. - - + + 1701;1702 + diff --git a/src/AElf.CrossChain.Core/Application/CrossChainRequestService.cs b/src/AElf.CrossChain.Core/Application/CrossChainRequestService.cs index 7649336e04..22cc3a5e7f 100644 --- a/src/AElf.CrossChain.Core/Application/CrossChainRequestService.cs +++ b/src/AElf.CrossChain.Core/Application/CrossChainRequestService.cs @@ -1,73 +1,72 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Communication.Application; +using AElf.Standards.ACS7; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public class CrossChainRequestService : ICrossChainRequestService, ITransientDependency { - public class CrossChainRequestService : ICrossChainRequestService, ITransientDependency + private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + private readonly ICrossChainClientService _crossChainClientService; + + public CrossChainRequestService(ICrossChainClientService crossChainClientService, + ICrossChainCacheEntityService crossChainCacheEntityService, + IBlockCacheEntityProducer blockCacheEntityProducer) { - private readonly ICrossChainClientService _crossChainClientService; - private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; - private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + _crossChainClientService = crossChainClientService; + _crossChainCacheEntityService = crossChainCacheEntityService; + _blockCacheEntityProducer = blockCacheEntityProducer; + } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - public CrossChainRequestService(ICrossChainClientService crossChainClientService, - ICrossChainCacheEntityService crossChainCacheEntityService, - IBlockCacheEntityProducer blockCacheEntityProducer) - { - _crossChainClientService = crossChainClientService; - _crossChainCacheEntityService = crossChainCacheEntityService; - _blockCacheEntityProducer = blockCacheEntityProducer; - } + public async Task RequestCrossChainDataFromOtherChainsAsync() + { + var chainIdHeightDict = GetNeededChainIdAndHeightPairs(); - public async Task RequestCrossChainDataFromOtherChainsAsync() + foreach (var chainIdHeightPair in chainIdHeightDict) { - var chainIdHeightDict = GetNeededChainIdAndHeightPairs(); - - foreach (var chainIdHeightPair in chainIdHeightDict) + var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainIdHeightPair.Key); + Logger.LogDebug( + $"Try to request from chain {chainIdBased58}, from height {chainIdHeightPair.Value}"); + try + { + var client = await _crossChainClientService.GetConnectedCrossChainClientAsync(chainIdHeightPair.Key); + if (client != null) + await client.RequestCrossChainDataAsync(chainIdHeightPair.Value, + b => _blockCacheEntityProducer.TryAddBlockCacheEntity(b)); + } + catch (CrossChainRequestException e) { - var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainIdHeightPair.Key); - Logger.LogDebug( - $"Try to request from chain {chainIdBased58}, from height {chainIdHeightPair.Value}"); - try - { - var client = await _crossChainClientService.GetConnectedCrossChainClientAsync(chainIdHeightPair.Key); - if (client != null) - await client.RequestCrossChainDataAsync(chainIdHeightPair.Value, - b => _blockCacheEntityProducer.TryAddBlockCacheEntity(b)); - } - catch (CrossChainRequestException e) - { - Logger.LogWarning(e, $"Request chain {chainIdBased58} failed."); - } + Logger.LogWarning(e, $"Request chain {chainIdBased58} failed."); } } + } - public async Task RequestChainInitializationDataAsync(int chainId) - { - Logger.LogDebug("Request chain initialization data."); - var client = await _crossChainClientService.CreateChainInitializationClientAsync(chainId); - return await client.RequestChainInitializationDataAsync(chainId); - } + public async Task RequestChainInitializationDataAsync(int chainId) + { + Logger.LogDebug("Request chain initialization data."); + var client = await _crossChainClientService.CreateChainInitializationClientAsync(chainId); + return await client.RequestChainInitializationDataAsync(chainId); + } - private Dictionary GetNeededChainIdAndHeightPairs() + private Dictionary GetNeededChainIdAndHeightPairs() + { + var chainIdList = _crossChainCacheEntityService.GetCachedChainIds(); + var dict = new Dictionary(); + foreach (var chainId in chainIdList) { - var chainIdList = _crossChainCacheEntityService.GetCachedChainIds(); - var dict = new Dictionary(); - foreach (var chainId in chainIdList) - { - var neededChainHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); - if (neededChainHeight < AElfConstants.GenesisBlockHeight) - continue; - dict.Add(chainId, neededChainHeight); - } - - return dict; + var neededChainHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); + if (neededChainHeight < AElfConstants.GenesisBlockHeight) + continue; + dict.Add(chainId, neededChainHeight); } + + return dict; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Application/CrossChainResponseService.cs b/src/AElf.CrossChain.Core/Application/CrossChainResponseService.cs index 36c60ec466..4204cde953 100644 --- a/src/AElf.CrossChain.Core/Application/CrossChainResponseService.cs +++ b/src/AElf.CrossChain.Core/Application/CrossChainResponseService.cs @@ -1,143 +1,138 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Indexing.Application; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus.Application; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public class CrossChainResponseService : ICrossChainResponseService, ITransientDependency { - public class CrossChainResponseService : ICrossChainResponseService, ITransientDependency + private readonly IBlockExtraDataService _blockExtraDataService; + private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + + public CrossChainResponseService(IBlockExtraDataService blockExtraDataService, + ICrossChainIndexingDataService crossChainIndexingDataService, + IConsensusExtraDataProvider consensusExtraDataProvider) { - private readonly IBlockExtraDataService _blockExtraDataService; - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; + _blockExtraDataService = blockExtraDataService; + _crossChainIndexingDataService = crossChainIndexingDataService; + _consensusExtraDataProvider = consensusExtraDataProvider; + } - public CrossChainResponseService(IBlockExtraDataService blockExtraDataService, - ICrossChainIndexingDataService crossChainIndexingDataService, - IConsensusExtraDataProvider consensusExtraDataProvider) - { - _blockExtraDataService = blockExtraDataService; - _crossChainIndexingDataService = crossChainIndexingDataService; - _consensusExtraDataProvider = consensusExtraDataProvider; - } + public async Task ResponseSideChainBlockDataAsync(long requestHeight) + { + var block = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(requestHeight); + if (block == null) + return null; - public async Task ResponseSideChainBlockDataAsync(long requestHeight) + return new SideChainBlockData { - var block = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(requestHeight); - if (block == null) - return null; - - return new SideChainBlockData - { - Height = block.Height, - BlockHeaderHash = block.GetHash(), - TransactionStatusMerkleTreeRoot = block.Header.MerkleTreeRootOfTransactionStatus, - ChainId = block.Header.ChainId - }; - } + Height = block.Height, + BlockHeaderHash = block.GetHash(), + TransactionStatusMerkleTreeRoot = block.Header.MerkleTreeRootOfTransactionStatus, + ChainId = block.Header.ChainId + }; + } - public async Task ResponseParentChainBlockDataAsync(long requestHeight, int remoteSideChainId) + public async Task ResponseParentChainBlockDataAsync(long requestHeight, int remoteSideChainId) + { + var block = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(requestHeight); + if (block == null) + return null; + var parentChainBlockData = new ParentChainBlockData { - var block = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(requestHeight); - if (block == null) - return null; - var parentChainBlockData = new ParentChainBlockData - { - Height = block.Height, ChainId = block.Header.ChainId - }; - parentChainBlockData = FillExtraDataInResponse(parentChainBlockData, block.Header); - - if (parentChainBlockData.CrossChainExtraData == null) - { - return parentChainBlockData; - } - - var indexedSideChainBlockDataResult = await GetIndexedSideChainBlockDataResultAsync(block); - var enumerableMerklePath = GetEnumerableMerklePath(indexedSideChainBlockDataResult, remoteSideChainId); - foreach (var kv in enumerableMerklePath) - { - parentChainBlockData.IndexedMerklePath.Add(kv.Key, kv.Value); - } - - return parentChainBlockData; - } + Height = block.Height, ChainId = block.Header.ChainId + }; + parentChainBlockData = FillExtraDataInResponse(parentChainBlockData, block.Header); - public async Task ResponseChainInitializationDataFromParentChainAsync(int chainId) - { - var chainInitializationData = await _crossChainIndexingDataService.GetChainInitializationDataAsync(chainId); - return chainInitializationData; - } + if (parentChainBlockData.CrossChainExtraData == null) return parentChainBlockData; - private ParentChainBlockData FillExtraDataInResponse(ParentChainBlockData parentChainBlockData, - BlockHeader blockHeader) - { - parentChainBlockData.TransactionStatusMerkleTreeRoot = blockHeader.MerkleTreeRootOfTransactionStatus; + var indexedSideChainBlockDataResult = await GetIndexedSideChainBlockDataResultAsync(block); + var enumerableMerklePath = GetEnumerableMerklePath(indexedSideChainBlockDataResult, remoteSideChainId); + foreach (var kv in enumerableMerklePath) parentChainBlockData.IndexedMerklePath.Add(kv.Key, kv.Value); - var crossChainExtraByteString = - GetExtraDataFromHeader(blockHeader, CrossChainConstants.CrossChainExtraDataKey); + return parentChainBlockData; + } - var crossChainExtra = crossChainExtraByteString.IsNullOrEmpty() - ? null - : CrossChainExtraData.Parser.ParseFrom(crossChainExtraByteString); - parentChainBlockData.CrossChainExtraData = crossChainExtra; + public async Task ResponseChainInitializationDataFromParentChainAsync(int chainId) + { + var chainInitializationData = await _crossChainIndexingDataService.GetChainInitializationDataAsync(chainId); + return chainInitializationData; + } - parentChainBlockData.ExtraData.Add(GetExtraDataForExchange(blockHeader, - new[] {_consensusExtraDataProvider.BlockHeaderExtraDataKey})); - return parentChainBlockData; - } + private ParentChainBlockData FillExtraDataInResponse(ParentChainBlockData parentChainBlockData, + BlockHeader blockHeader) + { + parentChainBlockData.TransactionStatusMerkleTreeRoot = blockHeader.MerkleTreeRootOfTransactionStatus; - private async Task> GetIndexedSideChainBlockDataResultAsync(Block block) - { - var indexedSideChainBlockData = - await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync(block.GetHash(), block.Height); - return indexedSideChainBlockData.SideChainBlockDataList.ToList(); - } - - private Dictionary GetEnumerableMerklePath(IList indexedSideChainBlockDataResult, - int sideChainId) - { - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes( - indexedSideChainBlockDataResult.Select(sideChainBlockData => - sideChainBlockData.TransactionStatusMerkleTreeRoot)); - - // This is to tell side chain the merkle path for one side chain block, - // which could be removed with subsequent improvement. - var res = new Dictionary(); - for (var i = 0; i < indexedSideChainBlockDataResult.Count; i++) - { - var info = indexedSideChainBlockDataResult[i]; - if (info.ChainId != sideChainId) - continue; - - var merklePath = binaryMerkleTree.GenerateMerklePath(i); - res.Add(info.Height, merklePath); - } - - return res; - } - - private ByteString GetExtraDataFromHeader(BlockHeader header, string symbol) + var crossChainExtraByteString = + GetExtraDataFromHeader(blockHeader, CrossChainConstants.CrossChainExtraDataKey); + + var crossChainExtra = crossChainExtraByteString.IsNullOrEmpty() + ? null + : CrossChainExtraData.Parser.ParseFrom(crossChainExtraByteString); + parentChainBlockData.CrossChainExtraData = crossChainExtra; + + parentChainBlockData.ExtraData.Add(GetExtraDataForExchange(blockHeader, + new[] { _consensusExtraDataProvider.BlockHeaderExtraDataKey })); + return parentChainBlockData; + } + + private async Task> GetIndexedSideChainBlockDataResultAsync(Block block) + { + var indexedSideChainBlockData = + await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync(block.GetHash(), block.Height); + return indexedSideChainBlockData.SideChainBlockDataList.ToList(); + } + + private Dictionary GetEnumerableMerklePath( + IList indexedSideChainBlockDataResult, + int sideChainId) + { + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes( + indexedSideChainBlockDataResult.Select(sideChainBlockData => + sideChainBlockData.TransactionStatusMerkleTreeRoot)); + + // This is to tell side chain the merkle path for one side chain block, + // which could be removed with subsequent improvement. + var res = new Dictionary(); + for (var i = 0; i < indexedSideChainBlockDataResult.Count; i++) { - return _blockExtraDataService.GetExtraDataFromBlockHeader(symbol, header); + var info = indexedSideChainBlockDataResult[i]; + if (info.ChainId != sideChainId) + continue; + + var merklePath = binaryMerkleTree.GenerateMerklePath(i); + res.Add(info.Height, merklePath); } - - private Dictionary GetExtraDataForExchange(BlockHeader header, IEnumerable symbolsOfExchangedExtraData) + + return res; + } + + private ByteString GetExtraDataFromHeader(BlockHeader header, string symbol) + { + return _blockExtraDataService.GetExtraDataFromBlockHeader(symbol, header); + } + + private Dictionary GetExtraDataForExchange(BlockHeader header, + IEnumerable symbolsOfExchangedExtraData) + { + var res = new Dictionary(); + foreach (var symbol in symbolsOfExchangedExtraData) { - var res = new Dictionary(); - foreach (var symbol in symbolsOfExchangedExtraData) - { - var extraData = GetExtraDataFromHeader(header, symbol); - if (extraData != null) - res.Add(symbol, extraData); - } - - return res; + var extraData = GetExtraDataFromHeader(header, symbol); + if (extraData != null) + res.Add(symbol, extraData); } + + return res; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Application/ICrossChainRequestService.cs b/src/AElf.CrossChain.Core/Application/ICrossChainRequestService.cs index 0e04e31fcd..cfdae17823 100644 --- a/src/AElf.CrossChain.Core/Application/ICrossChainRequestService.cs +++ b/src/AElf.CrossChain.Core/Application/ICrossChainRequestService.cs @@ -1,12 +1,11 @@ using System.Threading.Tasks; using AElf.Standards.ACS7; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public interface ICrossChainRequestService { - public interface ICrossChainRequestService - { - Task RequestCrossChainDataFromOtherChainsAsync(); + Task RequestCrossChainDataFromOtherChainsAsync(); - Task RequestChainInitializationDataAsync(int chainId); - } + Task RequestChainInitializationDataAsync(int chainId); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Application/ICrossChainResponseService.cs b/src/AElf.CrossChain.Core/Application/ICrossChainResponseService.cs index 27113cd0ab..21e2996f1f 100644 --- a/src/AElf.CrossChain.Core/Application/ICrossChainResponseService.cs +++ b/src/AElf.CrossChain.Core/Application/ICrossChainResponseService.cs @@ -1,13 +1,12 @@ using System.Threading.Tasks; using AElf.Standards.ACS7; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public interface ICrossChainResponseService { - public interface ICrossChainResponseService - { - Task ResponseSideChainBlockDataAsync(long requestHeight); - Task ResponseParentChainBlockDataAsync(long requestHeight, int remoteSideChainId); + Task ResponseSideChainBlockDataAsync(long requestHeight); + Task ResponseParentChainBlockDataAsync(long requestHeight, int remoteSideChainId); - Task ResponseChainInitializationDataFromParentChainAsync(int chainId); - } + Task ResponseChainInitializationDataFromParentChainAsync(int chainId); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityConsumer.cs b/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityConsumer.cs index 9876d8d6b9..2abc7703b1 100644 --- a/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityConsumer.cs +++ b/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityConsumer.cs @@ -2,37 +2,31 @@ using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Cache.Application +namespace AElf.CrossChain.Cache.Application; + +public interface IBlockCacheEntityConsumer +{ + T Take(int crossChainId, long height, bool isCacheSizeLimited) where T : IMessage, new(); +} + +public class BlockCacheEntityConsumer : IBlockCacheEntityConsumer, ITransientDependency { - public interface IBlockCacheEntityConsumer + private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; + + public BlockCacheEntityConsumer(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) { - T Take(int crossChainId, long height, bool isCacheSizeLimited) where T : IMessage, new(); + _crossChainCacheEntityProvider = crossChainCacheEntityProvider; } - - public class BlockCacheEntityConsumer : IBlockCacheEntityConsumer, ITransientDependency - { - private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; - - public BlockCacheEntityConsumer(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) - { - _crossChainCacheEntityProvider = crossChainCacheEntityProvider; - } - public T Take(int crossChainId, long height, bool isCacheSizeLimited) where T : IMessage, new() - { - if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(crossChainId, out var chainCacheEntity)) - { - return default(T); - } + public T Take(int crossChainId, long height, bool isCacheSizeLimited) where T : IMessage, new() + { + if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(crossChainId, out var chainCacheEntity)) + return default; - if (!chainCacheEntity.TryTake(height, out var blockCacheEntity, isCacheSizeLimited)) - { - return default(T); - } + if (!chainCacheEntity.TryTake(height, out var blockCacheEntity, isCacheSizeLimited)) return default; - var t = new T(); - t.MergeFrom(blockCacheEntity.ToByteString()); - return t; - } + var t = new T(); + t.MergeFrom(blockCacheEntity.ToByteString()); + return t; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityProducer.cs b/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityProducer.cs index 9dcd6b877f..c5eea55df4 100644 --- a/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityProducer.cs +++ b/src/AElf.CrossChain.Core/Cache/Application/IBlockCacheEntityProducer.cs @@ -3,38 +3,35 @@ using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Cache.Application +namespace AElf.CrossChain.Cache.Application; + +public interface IBlockCacheEntityProducer +{ + bool TryAddBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity); +} + +public class BlockCacheEntityProducer : IBlockCacheEntityProducer, ISingletonDependency { - public interface IBlockCacheEntityProducer + private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; + + public BlockCacheEntityProducer(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) { - bool TryAddBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity); + _crossChainCacheEntityProvider = crossChainCacheEntityProvider; } - - public class BlockCacheEntityProducer : IBlockCacheEntityProducer, ISingletonDependency + + public ILogger Logger { get; set; } + + public bool TryAddBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity) { - private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; - - public ILogger Logger { get; set; } - - public BlockCacheEntityProducer(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) - { - _crossChainCacheEntityProvider = crossChainCacheEntityProvider; - } - - public bool TryAddBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity) - { - if (crossChainBlockEntity == null) - throw new ArgumentNullException(nameof(crossChainBlockEntity)); - if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(crossChainBlockEntity.ChainId, out var chainCacheEntity)) - { - return false; - } - - var res = chainCacheEntity.TryAdd(crossChainBlockEntity); - - Logger.LogDebug( - $"Cached height {crossChainBlockEntity.Height} from chain {ChainHelper.ConvertChainIdToBase58(crossChainBlockEntity.ChainId)}, {res}"); - return res; - } + if (crossChainBlockEntity == null) + throw new ArgumentNullException(nameof(crossChainBlockEntity)); + if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(crossChainBlockEntity.ChainId, + out var chainCacheEntity)) return false; + + var res = chainCacheEntity.TryAdd(crossChainBlockEntity); + + Logger.LogDebug( + $"Cached height {crossChainBlockEntity.Height} from chain {ChainHelper.ConvertChainIdToBase58(crossChainBlockEntity.ChainId)}, {res}"); + return res; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Cache/Application/ICrossChainCacheEntityService.cs b/src/AElf.CrossChain.Core/Cache/Application/ICrossChainCacheEntityService.cs index ff50f1b652..fb9cc1b9c8 100644 --- a/src/AElf.CrossChain.Core/Cache/Application/ICrossChainCacheEntityService.cs +++ b/src/AElf.CrossChain.Core/Cache/Application/ICrossChainCacheEntityService.cs @@ -1,80 +1,75 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Infrastructure; +using AElf.Standards.ACS7; using AElf.Types; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Cache.Application +namespace AElf.CrossChain.Cache.Application; + +public interface ICrossChainCacheEntityService { - public interface ICrossChainCacheEntityService - { - void RegisterNewChain(int chainId, long height); - List GetCachedChainIds(); - long GetTargetHeightForChainCacheEntity(int chainId); + void RegisterNewChain(int chainId, long height); + List GetCachedChainIds(); + long GetTargetHeightForChainCacheEntity(int chainId); - Task UpdateCrossChainCacheAsync(Hash blockHash, long blockHeight, - ChainIdAndHeightDict chainIdAndHeightDict); - } + Task UpdateCrossChainCacheAsync(Hash blockHash, long blockHeight, + ChainIdAndHeightDict chainIdAndHeightDict); +} - internal class CrossChainCacheEntityService : ICrossChainCacheEntityService, ITransientDependency - { - private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; +internal class CrossChainCacheEntityService : ICrossChainCacheEntityService, ITransientDependency +{ + private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; - public ILogger Logger { get; set; } + public CrossChainCacheEntityService(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) + { + _crossChainCacheEntityProvider = crossChainCacheEntityProvider; + } - public CrossChainCacheEntityService(ICrossChainCacheEntityProvider crossChainCacheEntityProvider) - { - _crossChainCacheEntityProvider = crossChainCacheEntityProvider; - } + public ILogger Logger { get; set; } - public void RegisterNewChain(int chainId, long height) - { - if (_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out _)) - return; - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, height + 1); - } + public void RegisterNewChain(int chainId, long height) + { + if (_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out _)) + return; + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, height + 1); + } - public List GetCachedChainIds() - { - return _crossChainCacheEntityProvider.GetCachedChainIds(); - } + public List GetCachedChainIds() + { + return _crossChainCacheEntityProvider.GetCachedChainIds(); + } - public long GetTargetHeightForChainCacheEntity(int chainId) - { - if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var chainCacheEntity)) - { - throw new InvalidOperationException($"ChainCacheEntity of {chainId} not found"); - } + public long GetTargetHeightForChainCacheEntity(int chainId) + { + if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var chainCacheEntity)) + throw new InvalidOperationException($"ChainCacheEntity of {chainId} not found"); - return chainCacheEntity.TargetChainHeight(); - } + return chainCacheEntity.TargetChainHeight(); + } - private void ClearOutOfDateCrossChainCache(int chainId, long height) + public Task UpdateCrossChainCacheAsync(Hash blockHash, long blockHeight, + ChainIdAndHeightDict chainIdAndHeightDict) + { + foreach (var chainIdHeight in chainIdAndHeightDict.IdHeightDict) { - if (_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var chainCacheEntity)) - { - chainCacheEntity.ClearOutOfDateCacheByHeight(height); - } - } + // register new chain + RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value); - public Task UpdateCrossChainCacheAsync(Hash blockHash, long blockHeight, - ChainIdAndHeightDict chainIdAndHeightDict) - { - foreach (var chainIdHeight in chainIdAndHeightDict.IdHeightDict) - { - // register new chain - RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value); + // clear cross chain cache + ClearOutOfDateCrossChainCache(chainIdHeight.Key, chainIdHeight.Value); + Logger.LogDebug( + $"Clear chain {ChainHelper.ConvertChainIdToBase58(chainIdHeight.Key)} cache by height {chainIdHeight.Value}"); + } - // clear cross chain cache - ClearOutOfDateCrossChainCache(chainIdHeight.Key, chainIdHeight.Value); - Logger.LogDebug( - $"Clear chain {ChainHelper.ConvertChainIdToBase58(chainIdHeight.Key)} cache by height {chainIdHeight.Value}"); - } + return Task.CompletedTask; + } - return Task.CompletedTask; - } + private void ClearOutOfDateCrossChainCache(int chainId, long height) + { + if (_crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var chainCacheEntity)) + chainCacheEntity.ClearOutOfDateCacheByHeight(height); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Cache/Infrastructure/IChainCacheEntity.cs b/src/AElf.CrossChain.Core/Cache/Infrastructure/IChainCacheEntity.cs index 2f3ac790a2..4ab4b0f88a 100644 --- a/src/AElf.CrossChain.Core/Cache/Infrastructure/IChainCacheEntity.cs +++ b/src/AElf.CrossChain.Core/Cache/Infrastructure/IChainCacheEntity.cs @@ -1,83 +1,76 @@ using System.Collections.Concurrent; using System.Linq; -namespace AElf.CrossChain.Cache.Infrastructure +namespace AElf.CrossChain.Cache.Infrastructure; + +public interface IChainCacheEntity { - public interface IChainCacheEntity - { - bool TryAdd(ICrossChainBlockEntity crossChainBlockEntity); - long TargetChainHeight(); - bool TryTake(long height, out ICrossChainBlockEntity crossChainBlockEntity, bool isCacheSizeLimited); - void ClearOutOfDateCacheByHeight(long height); - } + bool TryAdd(ICrossChainBlockEntity crossChainBlockEntity); + long TargetChainHeight(); + bool TryTake(long height, out ICrossChainBlockEntity crossChainBlockEntity, bool isCacheSizeLimited); + void ClearOutOfDateCacheByHeight(long height); +} - public class ChainCacheEntity : IChainCacheEntity - { - private readonly ConcurrentDictionary _cache = - new ConcurrentDictionary(); +public class ChainCacheEntity : IChainCacheEntity +{ + private readonly ConcurrentDictionary _cache = new(); - private long _targetHeight; - private readonly int _chainId; + private readonly int _chainId; - public ChainCacheEntity(int chainId, long chainHeight) - { - _chainId = chainId; - _targetHeight = chainHeight; - } + private long _targetHeight; - public long TargetChainHeight() - { - return _cache.Count < CrossChainConstants.ChainCacheEntityCapacity ? _targetHeight : -1; - } + public ChainCacheEntity(int chainId, long chainHeight) + { + _chainId = chainId; + _targetHeight = chainHeight; + } - public bool TryAdd(ICrossChainBlockEntity crossChainBlockEntity) - { - if (crossChainBlockEntity.Height != TargetChainHeight()) - return false; - var res = ValidateBlockCacheEntity(crossChainBlockEntity) && - _cache.TryAdd(crossChainBlockEntity.Height, crossChainBlockEntity); - if (res) - _targetHeight = crossChainBlockEntity.Height + 1; - return res; - } + public long TargetChainHeight() + { + return _cache.Count < CrossChainConstants.ChainCacheEntityCapacity ? _targetHeight : -1; + } - /// - /// Try take element from cached queue. - /// - /// Height of block info needed - /// - /// Use as cache count threshold if true. - /// - public bool TryTake(long height, out ICrossChainBlockEntity crossChainBlockEntity, bool isCacheSizeLimited) - { - // clear outdated data - if (!_cache.TryGetValue(height, out crossChainBlockEntity)) - { - return false; - } + public bool TryAdd(ICrossChainBlockEntity crossChainBlockEntity) + { + if (crossChainBlockEntity.Height != TargetChainHeight()) + return false; + var res = ValidateBlockCacheEntity(crossChainBlockEntity) && + _cache.TryAdd(crossChainBlockEntity.Height, crossChainBlockEntity); + if (res) + _targetHeight = crossChainBlockEntity.Height + 1; + return res; + } + + /// + /// Try take element from cached queue. + /// + /// Height of block info needed + /// + /// + /// Use as cache count + /// threshold if true. + /// + /// + public bool TryTake(long height, out ICrossChainBlockEntity crossChainBlockEntity, bool isCacheSizeLimited) + { + // clear outdated data + if (!_cache.TryGetValue(height, out crossChainBlockEntity)) return false; - var lastQueuedHeight = _targetHeight - 1; - return !isCacheSizeLimited || lastQueuedHeight >= height + CrossChainConstants.DefaultBlockCacheEntityCount; - } + var lastQueuedHeight = _targetHeight - 1; + return !isCacheSizeLimited || lastQueuedHeight >= height + CrossChainConstants.DefaultBlockCacheEntityCount; + } - public void ClearOutOfDateCacheByHeight(long height) - { - foreach (var h in _cache.Keys.Where(k => k <= height)) - { - _cache.TryRemove(h, out _); - } + public void ClearOutOfDateCacheByHeight(long height) + { + foreach (var h in _cache.Keys.Where(k => k <= height)) _cache.TryRemove(h, out _); - if (_cache.Count == 0) - { - _targetHeight = height + 1; - } - } + if (_cache.Count == 0) _targetHeight = height + 1; + } - private bool ValidateBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity) - { - return crossChainBlockEntity.Height >= AElfConstants.GenesisBlockHeight && - crossChainBlockEntity.ChainId == _chainId && - crossChainBlockEntity.TransactionStatusMerkleTreeRoot != null; - } + private bool ValidateBlockCacheEntity(ICrossChainBlockEntity crossChainBlockEntity) + { + return crossChainBlockEntity.Height >= AElfConstants.GenesisBlockHeight && + crossChainBlockEntity.ChainId == _chainId && + crossChainBlockEntity.TransactionStatusMerkleTreeRoot != null; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Cache/Infrastructure/ICrossChainCacheEntityProvider.cs b/src/AElf.CrossChain.Core/Cache/Infrastructure/ICrossChainCacheEntityProvider.cs index 28c5a85788..6566c34f64 100644 --- a/src/AElf.CrossChain.Core/Cache/Infrastructure/ICrossChainCacheEntityProvider.cs +++ b/src/AElf.CrossChain.Core/Cache/Infrastructure/ICrossChainCacheEntityProvider.cs @@ -3,37 +3,35 @@ using System.Linq; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Cache.Infrastructure +namespace AElf.CrossChain.Cache.Infrastructure; + +public interface ICrossChainCacheEntityProvider +{ + int Size { get; } + void AddChainCacheEntity(int remoteChainId, long initialTargetHeight); + List GetCachedChainIds(); + bool TryGetChainCacheEntity(int remoteChainId, out IChainCacheEntity chainCacheEntity); +} + +public class CrossChainCacheEntityProvider : ICrossChainCacheEntityProvider, ISingletonDependency { - public interface ICrossChainCacheEntityProvider + private readonly ConcurrentDictionary _chainCacheEntities = new(); + + public int Size => _chainCacheEntities.Count; + + public List GetCachedChainIds() { - void AddChainCacheEntity(int remoteChainId, long initialTargetHeight); - int Size { get; } - List GetCachedChainIds(); - bool TryGetChainCacheEntity(int remoteChainId, out IChainCacheEntity chainCacheEntity); + return _chainCacheEntities.Keys.ToList(); } - - public class CrossChainCacheEntityProvider : ICrossChainCacheEntityProvider, ISingletonDependency - { - private readonly ConcurrentDictionary _chainCacheEntities = - new ConcurrentDictionary(); - - public int Size => _chainCacheEntities.Count; - - public List GetCachedChainIds() - { - return _chainCacheEntities.Keys.ToList(); - } - public void AddChainCacheEntity(int remoteChainId, long initialTargetHeight) - { - var chainCacheEntity = new ChainCacheEntity(remoteChainId, initialTargetHeight); - _chainCacheEntities.TryAdd(remoteChainId, chainCacheEntity); - } + public void AddChainCacheEntity(int remoteChainId, long initialTargetHeight) + { + var chainCacheEntity = new ChainCacheEntity(remoteChainId, initialTargetHeight); + _chainCacheEntities.TryAdd(remoteChainId, chainCacheEntity); + } - public bool TryGetChainCacheEntity(int remoteChainId, out IChainCacheEntity chainCacheEntity) - { - return _chainCacheEntities.TryGetValue(remoteChainId, out chainCacheEntity); - } + public bool TryGetChainCacheEntity(int remoteChainId, out IChainCacheEntity chainCacheEntity) + { + return _chainCacheEntities.TryGetValue(remoteChainId, out chainCacheEntity); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/Application/CrossChainClientService.cs b/src/AElf.CrossChain.Core/Communication/Application/CrossChainClientService.cs index 213927944c..3e26000182 100644 --- a/src/AElf.CrossChain.Core/Communication/Application/CrossChainClientService.cs +++ b/src/AElf.CrossChain.Core/Communication/Application/CrossChainClientService.cs @@ -3,59 +3,55 @@ using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Communication.Application +namespace AElf.CrossChain.Communication.Application; + +public class CrossChainClientService : ICrossChainClientService, ITransientDependency { - public class CrossChainClientService : ICrossChainClientService, ITransientDependency + private readonly ICrossChainClientProvider _crossChainClientProvider; + + public CrossChainClientService(ICrossChainClientProvider crossChainClientProvider) { - private readonly ICrossChainClientProvider _crossChainClientProvider; + _crossChainClientProvider = crossChainClientProvider; + } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - public CrossChainClientService(ICrossChainClientProvider crossChainClientProvider) - { - _crossChainClientProvider = crossChainClientProvider; - } + public async Task GetConnectedCrossChainClientAsync(int chainId) + { + if (!_crossChainClientProvider.TryGetClient(chainId, out var client)) + return null; + await ConnectAsync(client); + return !client.IsConnected ? null : client; + } - public async Task GetConnectedCrossChainClientAsync(int chainId) - { - if (!_crossChainClientProvider.TryGetClient(chainId, out var client)) - return null; - await ConnectAsync(client); - return !client.IsConnected ? null : client; - } + public Task CreateClientAsync(CrossChainClientCreationContext crossChainClientCreationContext) + { + var client = _crossChainClientProvider.AddOrUpdateClient(crossChainClientCreationContext); + return Task.FromResult(client); + } - public Task CreateClientAsync(CrossChainClientCreationContext crossChainClientCreationContext) + public Task CreateChainInitializationClientAsync(int chainId) + { + var crossChainClientDto = new CrossChainClientCreationContext { - var client = _crossChainClientProvider.AddOrUpdateClient(crossChainClientCreationContext); - return Task.FromResult(client); - } + IsClientToParentChain = true, + LocalChainId = chainId + }; + var client = _crossChainClientProvider.CreateChainInitializationDataClient(crossChainClientDto); + return Task.FromResult(client); + } - public Task CreateChainInitializationClientAsync(int chainId) - { - var crossChainClientDto = new CrossChainClientCreationContext - { - IsClientToParentChain = true, - LocalChainId = chainId - }; - var client = _crossChainClientProvider.CreateChainInitializationDataClient(crossChainClientDto); - return Task.FromResult(client); - } - - public async Task CloseClientsAsync() - { - var clientList = _crossChainClientProvider.GetAllClients(); - foreach (var client in clientList) - { - await client.CloseAsync(); - } - } - - private async Task ConnectAsync(ICrossChainClient client) - { - if (client.IsConnected) - return; - Logger.LogDebug($"Try connect with chain {ChainHelper.ConvertChainIdToBase58(client.RemoteChainId)}"); - await client.ConnectAsync(); - } + public async Task CloseClientsAsync() + { + var clientList = _crossChainClientProvider.GetAllClients(); + foreach (var client in clientList) await client.CloseAsync(); + } + + private async Task ConnectAsync(ICrossChainClient client) + { + if (client.IsConnected) + return; + Logger.LogDebug($"Try connect with chain {ChainHelper.ConvertChainIdToBase58(client.RemoteChainId)}"); + await client.ConnectAsync(); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/Application/ICrossChainClientService.cs b/src/AElf.CrossChain.Core/Communication/Application/ICrossChainClientService.cs index d5d00bc37b..6ce177d9e4 100644 --- a/src/AElf.CrossChain.Core/Communication/Application/ICrossChainClientService.cs +++ b/src/AElf.CrossChain.Core/Communication/Application/ICrossChainClientService.cs @@ -1,15 +1,14 @@ using System.Threading.Tasks; using AElf.CrossChain.Communication.Infrastructure; -namespace AElf.CrossChain.Communication.Application +namespace AElf.CrossChain.Communication.Application; + +public interface ICrossChainClientService { - public interface ICrossChainClientService - { - Task GetConnectedCrossChainClientAsync(int chainId); - Task CreateClientAsync(CrossChainClientCreationContext crossChainClientCreationContext); - - Task CreateChainInitializationClientAsync(int chainId); - - Task CloseClientsAsync(); - } + Task GetConnectedCrossChainClientAsync(int chainId); + Task CreateClientAsync(CrossChainClientCreationContext crossChainClientCreationContext); + + Task CreateChainInitializationClientAsync(int chainId); + + Task CloseClientsAsync(); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/ICrossChainCommunicationPlugin.cs b/src/AElf.CrossChain.Core/Communication/ICrossChainCommunicationPlugin.cs index e976c7a699..a79ed49613 100644 --- a/src/AElf.CrossChain.Core/Communication/ICrossChainCommunicationPlugin.cs +++ b/src/AElf.CrossChain.Core/Communication/ICrossChainCommunicationPlugin.cs @@ -1,12 +1,10 @@ using System.Threading.Tasks; -namespace AElf.CrossChain.Communication -{ - public interface ICrossChainCommunicationPlugin - { - Task StartAsync(int chainId); - Task ShutdownAsync(); +namespace AElf.CrossChain.Communication; - int ChainId { get; } - } +public interface ICrossChainCommunicationPlugin +{ + int ChainId { get; } + Task StartAsync(int chainId); + Task ShutdownAsync(); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/Infrastructure/CrossChainClientCreationContext.cs b/src/AElf.CrossChain.Core/Communication/Infrastructure/CrossChainClientCreationContext.cs index 8b22df4d07..33d3afd675 100644 --- a/src/AElf.CrossChain.Core/Communication/Infrastructure/CrossChainClientCreationContext.cs +++ b/src/AElf.CrossChain.Core/Communication/Infrastructure/CrossChainClientCreationContext.cs @@ -1,12 +1,11 @@ -namespace AElf.CrossChain.Communication.Infrastructure +namespace AElf.CrossChain.Communication.Infrastructure; + +public class CrossChainClientCreationContext { - public class CrossChainClientCreationContext - { - public string RemoteServerHost { get; set; } - public int RemoteServerPort { get; set; } - public int RemoteChainId { get; set; } - public int LocalChainId { get; set; } + public string RemoteServerHost { get; set; } + public int RemoteServerPort { get; set; } + public int RemoteChainId { get; set; } + public int LocalChainId { get; set; } - public bool IsClientToParentChain { get; set; } - } + public bool IsClientToParentChain { get; set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClient.cs b/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClient.cs index 708d81d274..bbda2b9856 100644 --- a/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClient.cs +++ b/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClient.cs @@ -2,19 +2,18 @@ using System.Threading.Tasks; using AElf.Standards.ACS7; -namespace AElf.CrossChain.Communication.Infrastructure +namespace AElf.CrossChain.Communication.Infrastructure; + +public interface ICrossChainClient { - public interface ICrossChainClient - { - int RemoteChainId { get; } - string TargetUriString { get; } - bool IsConnected { get; } + int RemoteChainId { get; } + string TargetUriString { get; } + bool IsConnected { get; } - Task RequestCrossChainDataAsync(long targetHeight, - Func crossChainBlockDataEntityHandler); + Task RequestCrossChainDataAsync(long targetHeight, + Func crossChainBlockDataEntityHandler); - Task RequestChainInitializationDataAsync(int chainId); - Task ConnectAsync(); - Task CloseAsync(); - } + Task RequestChainInitializationDataAsync(int chainId); + Task ConnectAsync(); + Task CloseAsync(); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClientProvider.cs b/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClientProvider.cs index fcdc3976c9..a5af0d051f 100644 --- a/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClientProvider.cs +++ b/src/AElf.CrossChain.Core/Communication/Infrastructure/ICrossChainClientProvider.cs @@ -1,13 +1,14 @@ using System.Collections.Generic; -namespace AElf.CrossChain.Communication.Infrastructure +namespace AElf.CrossChain.Communication.Infrastructure; + +public interface ICrossChainClientProvider { - public interface ICrossChainClientProvider - { - ICrossChainClient AddOrUpdateClient(CrossChainClientCreationContext crossChainClientCreationContext); - bool TryGetClient(int chainId, out ICrossChainClient client); - ICrossChainClient CreateChainInitializationDataClient(CrossChainClientCreationContext crossChainClientCreationContext); - - List GetAllClients(); - } + ICrossChainClient AddOrUpdateClient(CrossChainClientCreationContext crossChainClientCreationContext); + bool TryGetClient(int chainId, out ICrossChainClient client); + + ICrossChainClient CreateChainInitializationDataClient( + CrossChainClientCreationContext crossChainClientCreationContext); + + List GetAllClients(); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/CrossChainConfigOptions.cs b/src/AElf.CrossChain.Core/CrossChainConfigOptions.cs index f749b9c79e..1386e8ba5c 100644 --- a/src/AElf.CrossChain.Core/CrossChainConfigOptions.cs +++ b/src/AElf.CrossChain.Core/CrossChainConfigOptions.cs @@ -1,9 +1,8 @@ -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainConfigOptions { - public class CrossChainConfigOptions - { - public string ParentChainId { get; set; } + public string ParentChainId { get; set; } - public bool CrossChainDataValidationIgnored { get; set; } = true; - } + public bool CrossChainDataValidationIgnored { get; set; } = true; } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/CrossChainConstants.cs b/src/AElf.CrossChain.Core/CrossChainConstants.cs index 424b5029b3..e9aed2c77a 100644 --- a/src/AElf.CrossChain.Core/CrossChainConstants.cs +++ b/src/AElf.CrossChain.Core/CrossChainConstants.cs @@ -1,10 +1,9 @@ -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainConstants { - public class CrossChainConstants - { - public const int ChainCacheEntityCapacity = 1024; - public const int DefaultBlockCacheEntityCount = 256; - public const int LibHeightOffsetForCrossChainIndex = 0; - public const string CrossChainExtraDataKey = "CrossChain"; - } + public const int ChainCacheEntityCapacity = 1024; + public const int DefaultBlockCacheEntityCount = 256; + public const int LibHeightOffsetForCrossChainIndex = 0; + public const string CrossChainExtraDataKey = "CrossChain"; } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/CrossChainContractInitializationProvider.cs b/src/AElf.CrossChain.Core/CrossChainContractInitializationProvider.cs index c4ad1e0d67..b715f26fe4 100644 --- a/src/AElf.CrossChain.Core/CrossChainContractInitializationProvider.cs +++ b/src/AElf.CrossChain.Core/CrossChainContractInitializationProvider.cs @@ -5,36 +5,36 @@ using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class CrossChainContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = CrossChainSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.CrossChain"; + private readonly ICrossChainContractInitializationDataProvider _crossChainContractInitializationDataProvider; - private readonly ICrossChainContractInitializationDataProvider _crossChainContractInitializationDataProvider; + public CrossChainContractInitializationProvider( + ICrossChainContractInitializationDataProvider crossChainContractInitializationDataProvider) + { + _crossChainContractInitializationDataProvider = crossChainContractInitializationDataProvider; + } - public CrossChainContractInitializationProvider( - ICrossChainContractInitializationDataProvider crossChainContractInitializationDataProvider) - { - _crossChainContractInitializationDataProvider = crossChainContractInitializationDataProvider; - } + public Hash SystemSmartContractName { get; } = CrossChainSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.CrossChain"; - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + var initializationData = _crossChainContractInitializationDataProvider.GetContractInitializationData(); + return new List { - var initializationData = _crossChainContractInitializationDataProvider.GetContractInitializationData(); - return new List + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(CrossChainContractImplContainer.CrossChainContractImplStub.Initialize), - Params = new InitializeInput - { - ParentChainId = initializationData.ParentChainId, - CreationHeightOnParentChain = initializationData.CreationHeightOnParentChain, - IsPrivilegePreserved = initializationData.IsPrivilegePreserved - }.ToByteString() - } - }; - } + MethodName = nameof(CrossChainContractImplContainer.CrossChainContractImplStub.Initialize), + Params = new InitializeInput + { + ParentChainId = initializationData.ParentChainId, + CreationHeightOnParentChain = initializationData.CreationHeightOnParentChain, + IsPrivilegePreserved = initializationData.IsPrivilegePreserved + }.ToByteString() + } + }; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/CrossChainCoreModule.cs b/src/AElf.CrossChain.Core/CrossChainCoreModule.cs index f820bbc9d9..b6c8663281 100644 --- a/src/AElf.CrossChain.Core/CrossChainCoreModule.cs +++ b/src/AElf.CrossChain.Core/CrossChainCoreModule.cs @@ -5,19 +5,19 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainCoreModule : AElfModule { - public class CrossChainCoreModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var crossChainConfiguration = context.Services.GetConfiguration() - .GetSection(CrossChainConstants.CrossChainExtraDataKey); - Configure(crossChainConfiguration); + var crossChainConfiguration = context.Services.GetConfiguration() + .GetSection(CrossChainConstants.CrossChainExtraDataKey); + Configure(crossChainConfiguration); - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - } + context.Services + .AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/CrossChainSmartContractAddressNameProvider.cs b/src/AElf.CrossChain.Core/CrossChainSmartContractAddressNameProvider.cs index ad472385f4..31d0b95f48 100644 --- a/src/AElf.CrossChain.Core/CrossChainSmartContractAddressNameProvider.cs +++ b/src/AElf.CrossChain.Core/CrossChainSmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class CrossChainSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.CrossChain"); + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.CrossChain"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Exception/CrossChainRequestException.cs b/src/AElf.CrossChain.Core/Exception/CrossChainRequestException.cs index 40949f3f32..151835f0d4 100644 --- a/src/AElf.CrossChain.Core/Exception/CrossChainRequestException.cs +++ b/src/AElf.CrossChain.Core/Exception/CrossChainRequestException.cs @@ -1,14 +1,15 @@ -namespace AElf.CrossChain +using System; + +namespace AElf.CrossChain; + +public class CrossChainRequestException : Exception { - public class CrossChainRequestException : System.Exception + public CrossChainRequestException(string message) : base(message) { - public CrossChainRequestException(string message) : base(message) - { - } + } - public CrossChainRequestException(string message, System.Exception innerException) : base(message, - innerException) - { - } + public CrossChainRequestException(string message, Exception innerException) : base(message, + innerException) + { } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Extensions/CrossChainDataTypeExtensions.cs b/src/AElf.CrossChain.Core/Extensions/CrossChainDataTypeExtensions.cs index 69d270ea22..6d5afc01da 100644 --- a/src/AElf.CrossChain.Core/Extensions/CrossChainDataTypeExtensions.cs +++ b/src/AElf.CrossChain.Core/Extensions/CrossChainDataTypeExtensions.cs @@ -3,47 +3,47 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public static class CrossChainDataTypeExtensions { - public static class CrossChainDataTypeExtensions + public static bool IsNullOrEmpty(this CrossChainBlockData crossChainBlockData) { - public static bool IsNullOrEmpty(this CrossChainBlockData crossChainBlockData) - { - return crossChainBlockData == null || crossChainBlockData.ParentChainBlockDataList.Count == 0 && - crossChainBlockData.SideChainBlockDataList.Count == 0; - } - - public static ByteString ExtractCrossChainExtraDataFromCrossChainBlockData(this CrossChainBlockData crossChainBlockData) + return crossChainBlockData == null || (crossChainBlockData.ParentChainBlockDataList.Count == 0 && + crossChainBlockData.SideChainBlockDataList.Count == 0); + } + + public static ByteString ExtractCrossChainExtraDataFromCrossChainBlockData( + this CrossChainBlockData crossChainBlockData) + { + if (crossChainBlockData.IsNullOrEmpty() || crossChainBlockData.SideChainBlockDataList.Count == 0) + return ByteString.Empty; + + var indexedSideChainBlockData = new IndexedSideChainBlockData { - if (crossChainBlockData.IsNullOrEmpty() || crossChainBlockData.SideChainBlockDataList.Count == 0) - return ByteString.Empty; + SideChainBlockDataList = { crossChainBlockData.SideChainBlockDataList } + }; + + return indexedSideChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); + } + + public static ByteString ExtractCrossChainExtraDataFromCrossChainBlockData( + this IndexedSideChainBlockData indexedSideChainBlockData) + { + var txRootHashList = indexedSideChainBlockData.SideChainBlockDataList + .Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList(); - var indexedSideChainBlockData = new IndexedSideChainBlockData + var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root; + return new CrossChainExtraData { - SideChainBlockDataList = {crossChainBlockData.SideChainBlockDataList} - }; + TransactionStatusMerkleTreeRoot = calculatedSideChainTransactionsRoot + } + .ToByteString(); + } - return indexedSideChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); - } - public static ByteString ExtractCrossChainExtraDataFromCrossChainBlockData( - this IndexedSideChainBlockData indexedSideChainBlockData) - { - var txRootHashList = indexedSideChainBlockData.SideChainBlockDataList - .Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList(); - - var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root; - return new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = calculatedSideChainTransactionsRoot - } - .ToByteString(); - } - - - public static bool IsNullOrEmpty(this IndexedSideChainBlockData indexedSideChainBlockData) - { - return indexedSideChainBlockData == null || indexedSideChainBlockData.SideChainBlockDataList.Count == 0; - } + public static bool IsNullOrEmpty(this IndexedSideChainBlockData indexedSideChainBlockData) + { + return indexedSideChainBlockData == null || indexedSideChainBlockData.SideChainBlockDataList.Count == 0; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Extensions/LocalLibExtensions.cs b/src/AElf.CrossChain.Core/Extensions/LocalLibExtensions.cs index b5b0a26cf1..a6153d9e58 100644 --- a/src/AElf.CrossChain.Core/Extensions/LocalLibExtensions.cs +++ b/src/AElf.CrossChain.Core/Extensions/LocalLibExtensions.cs @@ -3,33 +3,34 @@ using AElf.Kernel.Blockchain.Application; using AElf.Types; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public static class LocalLibExtensions { - public static class LocalLibExtensions + public static async Task GetIrreversibleBlockByHeightAsync(this IBlockchainService blockchainService, + long height) { - public static async Task GetIrreversibleBlockByHeightAsync(this IBlockchainService blockchainService, long height) - { - var chain = await blockchainService.GetChainAsync(); - if (chain.LastIrreversibleBlockHeight < height + CrossChainConstants.LibHeightOffsetForCrossChainIndex) - return null; - var blockHash = await blockchainService.GetBlockHashByHeightAsync(chain, height, chain.BestChainHash); - return await blockchainService.GetBlockByHashAsync(blockHash); - } - - public static async Task GetLibHashAndHeightAsync(this IBlockchainService blockchainService) - { - var chain = await blockchainService.GetChainAsync(); - return new LastIrreversibleBlockDto - { - BlockHeight = chain.LastIrreversibleBlockHeight, - BlockHash = chain.LastIrreversibleBlockHash - }; - } + var chain = await blockchainService.GetChainAsync(); + if (chain.LastIrreversibleBlockHeight < height + CrossChainConstants.LibHeightOffsetForCrossChainIndex) + return null; + var blockHash = await blockchainService.GetBlockHashByHeightAsync(chain, height, chain.BestChainHash); + return await blockchainService.GetBlockByHashAsync(blockHash); } - public class LastIrreversibleBlockDto + public static async Task GetLibHashAndHeightAsync( + this IBlockchainService blockchainService) { - public Hash BlockHash { get; internal set;} - public long BlockHeight { get; internal set;} + var chain = await blockchainService.GetChainAsync(); + return new LastIrreversibleBlockDto + { + BlockHeight = chain.LastIrreversibleBlockHeight, + BlockHash = chain.LastIrreversibleBlockHash + }; } +} + +public class LastIrreversibleBlockDto +{ + public Hash BlockHash { get; internal set; } + public long BlockHeight { get; internal set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/ICrossChainBlockEntity.cs b/src/AElf.CrossChain.Core/ICrossChainBlockEntity.cs index 0357f8b520..0342dadd0a 100644 --- a/src/AElf.CrossChain.Core/ICrossChainBlockEntity.cs +++ b/src/AElf.CrossChain.Core/ICrossChainBlockEntity.cs @@ -1,12 +1,11 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public interface ICrossChainBlockEntity : IMessage { - public interface ICrossChainBlockEntity : IMessage - { - long Height { get; set; } - int ChainId { get; set; } - Hash TransactionStatusMerkleTreeRoot { get; set; } - } + long Height { get; set; } + int ChainId { get; set; } + Hash TransactionStatusMerkleTreeRoot { get; set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/ICrossChainContractInitializationDataProvider.cs b/src/AElf.CrossChain.Core/ICrossChainContractInitializationDataProvider.cs index df9c85edf3..8102c25095 100644 --- a/src/AElf.CrossChain.Core/ICrossChainContractInitializationDataProvider.cs +++ b/src/AElf.CrossChain.Core/ICrossChainContractInitializationDataProvider.cs @@ -1,18 +1,17 @@ -namespace AElf.CrossChain +namespace AElf.CrossChain; + +/// +/// Add this interface because the initialization logic of Cross Chain Contract +/// are different from Main Chain, Side Chain and test cases. +/// +public interface ICrossChainContractInitializationDataProvider { - /// - /// Add this interface because the initialization logic of Cross Chain Contract - /// are different from Main Chain, Side Chain and test cases. - /// - public interface ICrossChainContractInitializationDataProvider - { - CrossChainContractInitializationData GetContractInitializationData(); - } + CrossChainContractInitializationData GetContractInitializationData(); +} - public class CrossChainContractInitializationData - { - public int ParentChainId { get; set; } - public long CreationHeightOnParentChain { get; set; } - public bool IsPrivilegePreserved { get; set; } - } +public class CrossChainContractInitializationData +{ + public int ParentChainId { get; set; } + public long CreationHeightOnParentChain { get; set; } + public bool IsPrivilegePreserved { get; set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataProposedLogEventProcessor.cs b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataProposedLogEventProcessor.cs index eb3196c8de..d89a4b882d 100644 --- a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataProposedLogEventProcessor.cs +++ b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataProposedLogEventProcessor.cs @@ -1,86 +1,86 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; -using AElf.Contracts.CrossChain; -using AElf.Kernel; -using AElf.Kernel.SmartContract.Application; using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Kernel.Proposal.Application; +using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Indexing.Application +namespace AElf.CrossChain.Indexing.Application; + +public class CrossChainIndexingDataProposedLogEventProcessor : LogEventProcessorBase, + IBlocksExecutionSucceededLogEventProcessor { - public class CrossChainIndexingDataProposedLogEventProcessor : LogEventProcessorBase, IBlocksExecutionSucceededLogEventProcessor - { - public IOptions CrossChainConfigOptions { get; set; } - public ILogger Logger { get; set; } + private readonly ICrossChainIndexingDataValidationService _crossChainIndexingDataValidationService; + private readonly IProposalService _proposalService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ICrossChainIndexingDataValidationService _crossChainIndexingDataValidationService; - private readonly IProposalService _proposalService; + private readonly ISmartContractAddressService _smartContractAddressService; - public CrossChainIndexingDataProposedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ICrossChainIndexingDataValidationService crossChainIndexingDataValidationService, - IProposalService proposalService) - { - _smartContractAddressService = smartContractAddressService; - _crossChainIndexingDataValidationService = crossChainIndexingDataValidationService; - _proposalService = proposalService; - } - - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; + public CrossChainIndexingDataProposedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ICrossChainIndexingDataValidationService crossChainIndexingDataValidationService, + IProposalService proposalService) + { + _smartContractAddressService = smartContractAddressService; + _crossChainIndexingDataValidationService = crossChainIndexingDataValidationService; + _proposalService = proposalService; + } + + public IOptions CrossChainConfigOptions { get; set; } + public ILogger Logger { get; set; } - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, CrossChainSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; - - var interestedEvent = GetInterestedEvent(smartContractAddressDto - .SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; - InterestedEvent = interestedEvent; - + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; - } - public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, CrossChainSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; + + var interestedEvent = GetInterestedEvent(smartContractAddressDto + .SmartContractAddress.Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; + InterestedEvent = interestedEvent; + + return InterestedEvent; + } + + public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + { + foreach (var events in logEventsMap) { - foreach (var events in logEventsMap) + var transactionResult = events.Key; + foreach (var logEvent in events.Value) { - var transactionResult = events.Key; - foreach (var logEvent in events.Value) + if (CrossChainConfigOptions.Value.CrossChainDataValidationIgnored) { - if (CrossChainConfigOptions.Value.CrossChainDataValidationIgnored) - { - Logger.LogTrace("Cross chain data validation disabled."); - return; - } + Logger.LogTrace("Cross chain data validation disabled."); + return; + } - var crossChainIndexingDataProposedEvent = new CrossChainIndexingDataProposedEvent(); - crossChainIndexingDataProposedEvent.MergeFrom(logEvent); - var crossChainBlockData = crossChainIndexingDataProposedEvent.ProposedCrossChainData; - if (crossChainBlockData.IsNullOrEmpty()) - return; - var validationResult = - await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - block.GetHash(), block.Height); - if (validationResult) - { - Logger.LogDebug( - $"Valid cross chain indexing proposal found, block height {block.Height}, block hash {block.GetHash()} "); - var proposalId = crossChainIndexingDataProposedEvent.ProposalId ?? ProposalCreated.Parser - .ParseFrom(transactionResult.Logs - .First(l => l.Name == nameof(ProposalCreated)).NonIndexed) - .ProposalId; - _proposalService.AddNotApprovedProposal(proposalId, block.Height); - } + var crossChainIndexingDataProposedEvent = new CrossChainIndexingDataProposedEvent(); + crossChainIndexingDataProposedEvent.MergeFrom(logEvent); + var crossChainBlockData = crossChainIndexingDataProposedEvent.ProposedCrossChainData; + if (crossChainBlockData.IsNullOrEmpty()) + return; + var validationResult = + await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + block.GetHash(), block.Height); + if (validationResult) + { + Logger.LogDebug( + $"Valid cross chain indexing proposal found, block height {block.Height}, block hash {block.GetHash()} "); + var proposalId = crossChainIndexingDataProposedEvent.ProposalId ?? ProposalCreated.Parser + .ParseFrom(transactionResult.Logs + .First(l => l.Name == nameof(ProposalCreated)).NonIndexed) + .ProposalId; + _proposalService.AddNotApprovedProposal(proposalId, block.Height); } } } diff --git a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataService.cs b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataService.cs index 07587cafdb..2e0bef4b6e 100644 --- a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataService.cs +++ b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataService.cs @@ -1,398 +1,393 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.CrossChain; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Indexing.Infrastructure; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; -namespace AElf.CrossChain.Indexing.Application -{ - internal class CrossChainIndexingDataService : ICrossChainIndexingDataService - { - private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; - private readonly ITransactionInputForBlockMiningDataProvider _transactionInputForBlockMiningDataProvider; - private readonly IIrreversibleBlockStateProvider _irreversibleBlockStateProvider; +namespace AElf.CrossChain.Indexing.Application; - private readonly IContractReaderFactory - _contractReaderFactory; +internal class CrossChainIndexingDataService : ICrossChainIndexingDataService +{ + private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IContractReaderFactory + _contractReaderFactory; - public ILogger Logger { get; set; } + private readonly IIrreversibleBlockStateProvider _irreversibleBlockStateProvider; - private Task
GetCrossChainContractAddressAsync(IChainContext chainContext) - { - return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - CrossChainSmartContractAddressNameProvider.StringName); - } + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionInputForBlockMiningDataProvider _transactionInputForBlockMiningDataProvider; - public CrossChainIndexingDataService(IBlockCacheEntityConsumer blockCacheEntityConsumer, - ITransactionInputForBlockMiningDataProvider transactionInputForBlockMiningDataProvider, - IIrreversibleBlockStateProvider irreversibleBlockStateProvider, - IContractReaderFactory contractReaderFactory, - ISmartContractAddressService smartContractAddressService) - { - _blockCacheEntityConsumer = blockCacheEntityConsumer; - _transactionInputForBlockMiningDataProvider = transactionInputForBlockMiningDataProvider; - _irreversibleBlockStateProvider = irreversibleBlockStateProvider; - _contractReaderFactory = contractReaderFactory; - _smartContractAddressService = smartContractAddressService; - } + public CrossChainIndexingDataService(IBlockCacheEntityConsumer blockCacheEntityConsumer, + ITransactionInputForBlockMiningDataProvider transactionInputForBlockMiningDataProvider, + IIrreversibleBlockStateProvider irreversibleBlockStateProvider, + IContractReaderFactory contractReaderFactory, + ISmartContractAddressService smartContractAddressService) + { + _blockCacheEntityConsumer = blockCacheEntityConsumer; + _transactionInputForBlockMiningDataProvider = transactionInputForBlockMiningDataProvider; + _irreversibleBlockStateProvider = irreversibleBlockStateProvider; + _contractReaderFactory = contractReaderFactory; + _smartContractAddressService = smartContractAddressService; + } + public ILogger Logger { get; set; } - private async Task> GetNonIndexedSideChainBlockDataAsync(Hash blockHash, - long blockHeight, HashSet excludeChainIdList) - { - var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext + public async Task GetIndexedSideChainBlockDataAsync(Hash blockHash, long blockHeight) + { + var indexedSideChainBlockData = await _contractReaderFactory + .Create(new ContractReaderContext { BlockHash = blockHash, - BlockHeight = blockHeight - }); - var sideChainBlockDataList = new List(); - var sideChainIndexingInformationList = await _contractReaderFactory - .Create(new ContractReaderContext + BlockHeight = blockHeight, + ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = crossChainContractAddress + BlockHeight = blockHeight }) - .GetSideChainIndexingInformationList.CallAsync(new Empty()); - foreach (var sideChainIndexingInformation in sideChainIndexingInformationList.IndexingInformationList) - { - var libDto = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); - var sideChainId = sideChainIndexingInformation.ChainId; - if (excludeChainIdList.Contains(sideChainId)) - continue; - var sideChainHeightInLibValue = await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = libDto.BlockHash, - BlockHeight = libDto.BlockHeight, - ContractAddress = crossChainContractAddress - }) - .GetSideChainHeight.CallAsync(new Int32Value {Value = sideChainId}); - - long toBeIndexedCount; - long targetHeight; - var sideChainHeightInLib = sideChainHeightInLibValue?.Value ?? 0; - if (sideChainHeightInLib > 0) - { - targetHeight = sideChainIndexingInformation.IndexedHeight + 1; - toBeIndexedCount = CrossChainConstants.DefaultBlockCacheEntityCount; - Logger.LogDebug( - $"Target height {targetHeight} of side chain " + - $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}."); - } - else if (sideChainIndexingInformation.IndexedHeight > 0) + }) + .GetIndexedSideChainBlockDataByHeight.CallAsync(new Int64Value { Value = blockHeight }); + return indexedSideChainBlockData; + } + + /// + /// This method returns serialization input for cross chain proposing method. + /// + /// + /// + /// + public Task GetCrossChainTransactionInputForNextMiningAsync(Hash blockHash, + long blockHeight) + { + var inputForNextMining = + _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); + return Task.FromResult(inputForNextMining); + } + + public async Task CheckExtraDataIsNeededAsync(Hash blockHash, long blockHeight, Timestamp timestamp) + { + var indexingProposalStatusList = await GetIndexingProposalStatusAsync(blockHash, blockHeight, timestamp); + var toBeReleasedChainIdList = FindToBeReleasedChainIdList(indexingProposalStatusList, timestamp); + return toBeReleasedChainIdList.Count > 0; + } + + public async Task PrepareExtraDataForNextMiningAsync(Hash blockHash, long blockHeight) + { + var utcNow = TimestampHelper.GetUtcNow(); + var indexingProposalStatusList = await GetIndexingProposalStatusAsync(blockHash, blockHeight, utcNow); + + var toBeReleasedChainIdList = FindToBeReleasedChainIdList(indexingProposalStatusList, utcNow); + + if (toBeReleasedChainIdList.Count > 0) + { + // release pending proposal and unable to propose anything if it is ready + _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, + new CrossChainTransactionInput { - toBeIndexedCount = 0; - targetHeight = sideChainIndexingInformation.IndexedHeight + 1; - } - else + PreviousBlockHeight = blockHeight, + MethodName = + nameof(CrossChainContractImplContainer.CrossChainContractImplStub + .ReleaseCrossChainIndexingProposal), + Value = new ReleaseCrossChainIndexingProposalInput { ChainIdList = { toBeReleasedChainIdList } } + .ToByteString() + }); + var toBeReleasedCrossChainBlockData = AggregateToBeReleasedCrossChainData( + toBeReleasedChainIdList.Select(chainId => + indexingProposalStatusList.ChainIndexingProposalStatus[chainId].ProposedCrossChainBlockData)); + return toBeReleasedCrossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); + } + + var pendingChainIdList = FindPendingStatusChainIdList(indexingProposalStatusList, utcNow); + + var crossChainBlockData = + await GetCrossChainBlockDataForNextMining(blockHash, blockHeight, new HashSet(pendingChainIdList)); + + if (!crossChainBlockData.IsNullOrEmpty()) + _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, + new CrossChainTransactionInput { - toBeIndexedCount = 1; - targetHeight = AElfConstants.GenesisBlockHeight; - Logger.LogDebug( - $"Target height {targetHeight} of side chain " + - $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}."); - } + PreviousBlockHeight = blockHeight, + MethodName = + nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing), + Value = crossChainBlockData.ToByteString() + }); + return ByteString.Empty; + } - var sideChainBlockDataFromCache = new List(); + public void UpdateCrossChainDataWithLib(Hash blockHash, long blockHeight) + { + // clear useless cache + _transactionInputForBlockMiningDataProvider.ClearExpiredTransactionInput(blockHeight); + } - var i = 0; - while (i < toBeIndexedCount) + public async Task GetChainInitializationDataAsync(int chainId) + { + var libDto = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); + return await _contractReaderFactory + .Create(new ContractReaderContext + { + BlockHash = libDto.BlockHash, + BlockHeight = libDto.BlockHeight, + ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { - var sideChainBlockData = - _blockCacheEntityConsumer.Take(sideChainIndexingInformation.ChainId, - targetHeight, targetHeight == AElfConstants.GenesisBlockHeight); - if (sideChainBlockData == null || sideChainBlockData.Height != targetHeight) - { - // no more available side chain block info - break; - } - - sideChainBlockDataFromCache.Add(sideChainBlockData); - targetHeight++; - i++; - } - - if (sideChainBlockDataFromCache.Count > 0) + BlockHash = libDto.BlockHash, + BlockHeight = libDto.BlockHeight + }) + }).GetChainInitializationData.CallAsync(new Int32Value + { + Value = chainId + }); + } + + public async Task GetNonIndexedBlockAsync(long height) + { + return await _irreversibleBlockStateProvider.GetNotIndexedIrreversibleBlockByHeightAsync(height); + } + + public async Task GetAllChainIdHeightPairsAtLibAsync() + { + var isReadyToCreateChainCache = + await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); + if (!isReadyToCreateChainCache) + return new ChainIdAndHeightDict(); + var lib = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); + return await _contractReaderFactory + .Create(new ContractReaderContext + { + BlockHash = lib.BlockHash, + BlockHeight = lib.BlockHeight, + ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { - Logger.LogDebug( - $"Got height [{sideChainBlockDataFromCache.First().Height} - {sideChainBlockDataFromCache.Last().Height} ]" + - $" from side chain {ChainHelper.ConvertChainIdToBase58(sideChainIndexingInformation.ChainId)}."); - sideChainBlockDataList.AddRange(sideChainBlockDataFromCache); - } - } + BlockHash = lib.BlockHash, + BlockHeight = lib.BlockHeight + }) + }).GetAllChainsIdAndHeight + .CallAsync(new Empty()); + } - return sideChainBlockDataList; - } + private Task
GetCrossChainContractAddressAsync(IChainContext chainContext) + { + return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + CrossChainSmartContractAddressNameProvider.StringName); + } - private async Task> GetNonIndexedParentChainBlockDataAsync(Hash blockHash, - long blockHeight, HashSet excludeChainIdList) - { - var parentChainBlockDataList = new List(); - var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); - if (!libExists) - return parentChainBlockDataList; - var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext + private async Task> GetNonIndexedSideChainBlockDataAsync(Hash blockHash, + long blockHeight, HashSet excludeChainIdList) + { + var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext + { + BlockHash = blockHash, + BlockHeight = blockHeight + }); + var sideChainBlockDataList = new List(); + var sideChainIndexingInformationList = await _contractReaderFactory + .Create(new ContractReaderContext { BlockHash = blockHash, - BlockHeight = blockHeight - }); - - var returnValue = await _contractReaderFactory.Create(new ContractReaderContext + BlockHeight = blockHeight, + ContractAddress = crossChainContractAddress + }) + .GetSideChainIndexingInformationList.CallAsync(new Empty()); + foreach (var sideChainIndexingInformation in sideChainIndexingInformationList.IndexingInformationList) + { + var libDto = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); + var sideChainId = sideChainIndexingInformation.ChainId; + if (excludeChainIdList.Contains(sideChainId)) + continue; + var sideChainHeightInLibValue = await _contractReaderFactory + .Create(new ContractReaderContext { - BlockHash = blockHash, - BlockHeight = blockHeight, + BlockHash = libDto.BlockHash, + BlockHeight = libDto.BlockHeight, ContractAddress = crossChainContractAddress - }).GetParentChainId - .CallAsync(new Empty()); - var parentChainId = returnValue?.Value ?? 0; - if (parentChainId == 0 || excludeChainIdList.Contains(parentChainId)) + }) + .GetSideChainHeight.CallAsync(new Int32Value { Value = sideChainId }); + + long toBeIndexedCount; + long targetHeight; + var sideChainHeightInLib = sideChainHeightInLibValue?.Value ?? 0; + if (sideChainHeightInLib > 0) { - // no configured parent chain - return parentChainBlockDataList; + targetHeight = sideChainIndexingInformation.IndexedHeight + 1; + toBeIndexedCount = CrossChainConstants.DefaultBlockCacheEntityCount; + Logger.LogDebug( + $"Target height {targetHeight} of side chain " + + $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}."); + } + else if (sideChainIndexingInformation.IndexedHeight > 0) + { + toBeIndexedCount = 0; + targetHeight = sideChainIndexingInformation.IndexedHeight + 1; + } + else + { + toBeIndexedCount = 1; + targetHeight = AElfConstants.GenesisBlockHeight; + Logger.LogDebug( + $"Target height {targetHeight} of side chain " + + $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}."); } - int length = CrossChainConstants.DefaultBlockCacheEntityCount; - var heightInState = (await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = crossChainContractAddress - }).GetParentChainHeight - .CallAsync(new Empty())).Value; - - var targetHeight = heightInState + 1; - Logger.LogDebug($"Target height {targetHeight}"); + var sideChainBlockDataFromCache = new List(); var i = 0; - while (i < length) + while (i < toBeIndexedCount) { - var parentChainBlockData = - _blockCacheEntityConsumer.Take(parentChainId, targetHeight, false); - if (parentChainBlockData == null || parentChainBlockData.Height != targetHeight) - { - // no more available parent chain block info + var sideChainBlockData = + _blockCacheEntityConsumer.Take(sideChainIndexingInformation.ChainId, + targetHeight, targetHeight == AElfConstants.GenesisBlockHeight); + if (sideChainBlockData == null || sideChainBlockData.Height != targetHeight) + // no more available side chain block info break; - } - parentChainBlockDataList.Add(parentChainBlockData); + sideChainBlockDataFromCache.Add(sideChainBlockData); targetHeight++; i++; } - if (parentChainBlockDataList.Count > 0) + if (sideChainBlockDataFromCache.Count > 0) + { Logger.LogDebug( - $"Got height [{parentChainBlockDataList.First().Height} - {parentChainBlockDataList.Last().Height} ]" + - $" from parent chain {ChainHelper.ConvertChainIdToBase58(parentChainId)}."); - return parentChainBlockDataList; - } - - public async Task GetIndexedSideChainBlockDataAsync(Hash blockHash, long blockHeight) - { - var indexedSideChainBlockData = await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }) - }) - .GetIndexedSideChainBlockDataByHeight.CallAsync(new Int64Value {Value = blockHeight}); - return indexedSideChainBlockData; + $"Got height [{sideChainBlockDataFromCache.First().Height} - {sideChainBlockDataFromCache.Last().Height} ]" + + $" from side chain {ChainHelper.ConvertChainIdToBase58(sideChainIndexingInformation.ChainId)}."); + sideChainBlockDataList.AddRange(sideChainBlockDataFromCache); + } } - /// - /// This method returns serialization input for cross chain proposing method. - /// - /// - /// - /// - public Task GetCrossChainTransactionInputForNextMiningAsync(Hash blockHash, - long blockHeight) - { - var inputForNextMining = - _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); - return Task.FromResult(inputForNextMining); - } + return sideChainBlockDataList; + } - public async Task CheckExtraDataIsNeededAsync(Hash blockHash, long blockHeight, Timestamp timestamp) - { - var indexingProposalStatusList = await GetIndexingProposalStatusAsync(blockHash, blockHeight, timestamp); - var toBeReleasedChainIdList = FindToBeReleasedChainIdList(indexingProposalStatusList, timestamp); - return toBeReleasedChainIdList.Count > 0; - } + private async Task> GetNonIndexedParentChainBlockDataAsync(Hash blockHash, + long blockHeight, HashSet excludeChainIdList) + { + var parentChainBlockDataList = new List(); + var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); + if (!libExists) + return parentChainBlockDataList; - public async Task PrepareExtraDataForNextMiningAsync(Hash blockHash, long blockHeight) + var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { - var utcNow = TimestampHelper.GetUtcNow(); - var indexingProposalStatusList = await GetIndexingProposalStatusAsync(blockHash, blockHeight, utcNow); + BlockHash = blockHash, + BlockHeight = blockHeight + }); - var toBeReleasedChainIdList = FindToBeReleasedChainIdList(indexingProposalStatusList, utcNow); + var returnValue = await _contractReaderFactory.Create(new ContractReaderContext + { + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = crossChainContractAddress + }).GetParentChainId + .CallAsync(new Empty()); + var parentChainId = returnValue?.Value ?? 0; + if (parentChainId == 0 || excludeChainIdList.Contains(parentChainId)) + // no configured parent chain + return parentChainBlockDataList; - if (toBeReleasedChainIdList.Count > 0) + var length = CrossChainConstants.DefaultBlockCacheEntityCount; + var heightInState = (await _contractReaderFactory + .Create(new ContractReaderContext { - // release pending proposal and unable to propose anything if it is ready - _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, - new CrossChainTransactionInput - { - PreviousBlockHeight = blockHeight, - MethodName = - nameof(CrossChainContractImplContainer.CrossChainContractImplStub - .ReleaseCrossChainIndexingProposal), - Value = new ReleaseCrossChainIndexingProposalInput {ChainIdList = {toBeReleasedChainIdList}} - .ToByteString() - }); - var toBeReleasedCrossChainBlockData = AggregateToBeReleasedCrossChainData( - toBeReleasedChainIdList.Select(chainId => - indexingProposalStatusList.ChainIndexingProposalStatus[chainId].ProposedCrossChainBlockData)); - return toBeReleasedCrossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); - } - - var pendingChainIdList = FindPendingStatusChainIdList(indexingProposalStatusList, utcNow); - - var crossChainBlockData = - await GetCrossChainBlockDataForNextMining(blockHash, blockHeight, new HashSet(pendingChainIdList)); - - if (!crossChainBlockData.IsNullOrEmpty()) - _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, - new CrossChainTransactionInput - { - PreviousBlockHeight = blockHeight, - MethodName = - nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing), - Value = crossChainBlockData.ToByteString() - }); - return ByteString.Empty; - } + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = crossChainContractAddress + }).GetParentChainHeight + .CallAsync(new Empty())).Value; - public void UpdateCrossChainDataWithLib(Hash blockHash, long blockHeight) - { - // clear useless cache - _transactionInputForBlockMiningDataProvider.ClearExpiredTransactionInput(blockHeight); - } + var targetHeight = heightInState + 1; + Logger.LogDebug($"Target height {targetHeight}"); - public async Task GetChainInitializationDataAsync(int chainId) + var i = 0; + while (i < length) { - var libDto = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); - return await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = libDto.BlockHash, - BlockHeight = libDto.BlockHeight, - ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext - { - BlockHash = libDto.BlockHash, - BlockHeight = libDto.BlockHeight - }) - }).GetChainInitializationData.CallAsync(new Int32Value - { - Value = chainId - }); + var parentChainBlockData = + _blockCacheEntityConsumer.Take(parentChainId, targetHeight, false); + if (parentChainBlockData == null || parentChainBlockData.Height != targetHeight) + // no more available parent chain block info + break; + + parentChainBlockDataList.Add(parentChainBlockData); + targetHeight++; + i++; } - public async Task GetNonIndexedBlockAsync(long height) - { - return await _irreversibleBlockStateProvider.GetNotIndexedIrreversibleBlockByHeightAsync(height); - } + if (parentChainBlockDataList.Count > 0) + Logger.LogDebug( + $"Got height [{parentChainBlockDataList.First().Height} - {parentChainBlockDataList.Last().Height} ]" + + $" from parent chain {ChainHelper.ConvertChainIdToBase58(parentChainId)}."); + return parentChainBlockDataList; + } - public async Task GetAllChainIdHeightPairsAtLibAsync() - { - var isReadyToCreateChainCache = - await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); - if (!isReadyToCreateChainCache) - return new ChainIdAndHeightDict(); - var lib = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync(); - return await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = lib.BlockHash, - BlockHeight = lib.BlockHeight, - ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext - { - BlockHash = lib.BlockHash, - BlockHeight = lib.BlockHeight - }) - }).GetAllChainsIdAndHeight - .CallAsync(new Empty()); - } + private async Task GetCrossChainBlockDataForNextMining(Hash blockHash, + long blockHeight, HashSet excludeChainIdList) + { + var sideChainBlockData = await GetNonIndexedSideChainBlockDataAsync(blockHash, blockHeight, excludeChainIdList); + var parentChainBlockData = + await GetNonIndexedParentChainBlockDataAsync(blockHash, blockHeight, excludeChainIdList); - private async Task GetCrossChainBlockDataForNextMining(Hash blockHash, - long blockHeight, HashSet excludeChainIdList) + var crossChainBlockData = new CrossChainBlockData { - var sideChainBlockData = await GetNonIndexedSideChainBlockDataAsync(blockHash, blockHeight, excludeChainIdList); - var parentChainBlockData = await GetNonIndexedParentChainBlockDataAsync(blockHash, blockHeight, excludeChainIdList); + ParentChainBlockDataList = { parentChainBlockData }, + SideChainBlockDataList = { sideChainBlockData } + }; + return crossChainBlockData; + } - var crossChainBlockData = new CrossChainBlockData + private async Task GetIndexingProposalStatusAsync( + Hash blockHash, long blockHeight, Timestamp timestamp) + { + var pendingProposal = await _contractReaderFactory + .Create(new ContractReaderContext { - ParentChainBlockDataList = {parentChainBlockData}, - SideChainBlockDataList = {sideChainBlockData} - }; - return crossChainBlockData; - } - - private async Task GetIndexingProposalStatusAsync( - Hash blockHash, long blockHeight, Timestamp timestamp) - { - var pendingProposal = await _contractReaderFactory - .Create(new ContractReaderContext + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }), - Timestamp = timestamp - }) - .GetIndexingProposalStatus.CallAsync(new Empty()); - return pendingProposal; - } + BlockHeight = blockHeight + }), + Timestamp = timestamp + }) + .GetIndexingProposalStatus.CallAsync(new Empty()); + return pendingProposal; + } - private List FindPendingStatusChainIdList( - GetIndexingProposalStatusOutput pendingChainIndexingProposalStatusList, Timestamp timestamp) - { - return pendingChainIndexingProposalStatusList.ChainIndexingProposalStatus - .Where(pair => !pair.Value.ToBeReleased && pair.Value.ExpiredTime.AddMilliseconds(500) > timestamp) - .Select(pair => pair.Key).ToList(); - } - - private List FindToBeReleasedChainIdList( - GetIndexingProposalStatusOutput pendingChainIndexingProposalStatusList, Timestamp timestamp) - { - return pendingChainIndexingProposalStatusList.ChainIndexingProposalStatus - .Where(pair => pair.Value.ToBeReleased && pair.Value.ExpiredTime > timestamp).Select(pair => pair.Key) - .ToList(); - } + private List FindPendingStatusChainIdList( + GetIndexingProposalStatusOutput pendingChainIndexingProposalStatusList, Timestamp timestamp) + { + return pendingChainIndexingProposalStatusList.ChainIndexingProposalStatus + .Where(pair => !pair.Value.ToBeReleased && pair.Value.ExpiredTime.AddMilliseconds(500) > timestamp) + .Select(pair => pair.Key).ToList(); + } + + private List FindToBeReleasedChainIdList( + GetIndexingProposalStatusOutput pendingChainIndexingProposalStatusList, Timestamp timestamp) + { + return pendingChainIndexingProposalStatusList.ChainIndexingProposalStatus + .Where(pair => pair.Value.ToBeReleased && pair.Value.ExpiredTime > timestamp).Select(pair => pair.Key) + .ToList(); + } - private CrossChainBlockData AggregateToBeReleasedCrossChainData(IEnumerable toBeIndexedList) + private CrossChainBlockData AggregateToBeReleasedCrossChainData(IEnumerable toBeIndexedList) + { + var res = new CrossChainBlockData(); + toBeIndexedList.Aggregate(res, (cur, element) => { - var res = new CrossChainBlockData(); - toBeIndexedList.Aggregate(res, (cur, element) => - { - cur.ParentChainBlockDataList.Add(element.ParentChainBlockDataList); - cur.SideChainBlockDataList.Add(element.SideChainBlockDataList); - return cur; - }); + cur.ParentChainBlockDataList.Add(element.ParentChainBlockDataList); + cur.SideChainBlockDataList.Add(element.SideChainBlockDataList); + return cur; + }); - return res; - } + return res; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataValidationService.cs b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataValidationService.cs index 91012788e3..737d6041a8 100644 --- a/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataValidationService.cs +++ b/src/AElf.CrossChain.Core/Indexing/Application/CrossChainIndexingDataValidationService.cs @@ -1,174 +1,174 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.CrossChain; using AElf.CrossChain.Cache.Application; using AElf.Kernel; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Indexing.Application +namespace AElf.CrossChain.Indexing.Application; + +internal class CrossChainIndexingDataValidationService : ICrossChainIndexingDataValidationService, + ITransientDependency { - internal class CrossChainIndexingDataValidationService : ICrossChainIndexingDataValidationService, - ITransientDependency - { - public ILogger Logger { get; set; } - private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; + private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly IContractReaderFactory + _contractReaderFactory; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractAddressService _smartContractAddressService; - private Task
GetCrossChainContractAddressAsync(IChainContext chainContext) - { - return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - CrossChainSmartContractAddressNameProvider.StringName); - } + public CrossChainIndexingDataValidationService(IBlockCacheEntityConsumer blockCacheEntityConsumer, + IContractReaderFactory contractReaderFactory, + ISmartContractAddressService smartContractAddressService) + { + _blockCacheEntityConsumer = blockCacheEntityConsumer; + _contractReaderFactory = contractReaderFactory; + _smartContractAddressService = smartContractAddressService; + } - public CrossChainIndexingDataValidationService(IBlockCacheEntityConsumer blockCacheEntityConsumer, - IContractReaderFactory contractReaderFactory, - ISmartContractAddressService smartContractAddressService) - { - _blockCacheEntityConsumer = blockCacheEntityConsumer; - _contractReaderFactory = contractReaderFactory; - _smartContractAddressService = smartContractAddressService; - } + public ILogger Logger { get; set; } - public async Task ValidateCrossChainIndexingDataAsync(CrossChainBlockData crossChainBlockData, - Hash blockHash, long blockHeight) - { - var sideChainBlockDataValidationResult = - await ValidateSideChainBlockDataAsync(crossChainBlockData.SideChainBlockDataList, blockHash, - blockHeight); - if (!sideChainBlockDataValidationResult) - return false; + public async Task ValidateCrossChainIndexingDataAsync(CrossChainBlockData crossChainBlockData, + Hash blockHash, long blockHeight) + { + var sideChainBlockDataValidationResult = + await ValidateSideChainBlockDataAsync(crossChainBlockData.SideChainBlockDataList, blockHash, + blockHeight); + if (!sideChainBlockDataValidationResult) + return false; - var parentChainBlockDataValidationResult = - await ValidateParentChainBlockDataAsync(crossChainBlockData.ParentChainBlockDataList, blockHash, - blockHeight); + var parentChainBlockDataValidationResult = + await ValidateParentChainBlockDataAsync(crossChainBlockData.ParentChainBlockDataList, blockHash, + blockHeight); - return parentChainBlockDataValidationResult; - } + return parentChainBlockDataValidationResult; + } + private Task
GetCrossChainContractAddressAsync(IChainContext chainContext) + { + return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + CrossChainSmartContractAddressNameProvider.StringName); + } - private async Task ValidateSideChainBlockDataAsync( - IEnumerable multiSideChainBlockData, - Hash blockHash, long blockHeight) + + private async Task ValidateSideChainBlockDataAsync( + IEnumerable multiSideChainBlockData, + Hash blockHash, long blockHeight) + { + var sideChainValidatedHeightDict = new Dictionary(); // chain id => validated height + foreach (var sideChainBlockData in multiSideChainBlockData) { - var sideChainValidatedHeightDict = new Dictionary(); // chain id => validated height - foreach (var sideChainBlockData in multiSideChainBlockData) + if (!sideChainValidatedHeightDict.TryGetValue(sideChainBlockData.ChainId, out var validatedHeight)) { - if (!sideChainValidatedHeightDict.TryGetValue(sideChainBlockData.ChainId, out var validatedHeight)) - { - var height = await _contractReaderFactory - .Create(new ContractReaderContext + var height = await _contractReaderFactory + .Create(new ContractReaderContext + { + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }) - }).GetSideChainHeight - .CallAsync( - new Int32Value() - { - Value = sideChainBlockData.ChainId - }); - validatedHeight = height?.Value ?? 0; - } - - var targetHeight = validatedHeight + 1; - - if (targetHeight != sideChainBlockData.Height) - // this should not happen if it is good data. - return false; - - var cachedSideChainBlockData = - _blockCacheEntityConsumer.Take(sideChainBlockData.ChainId, targetHeight, false); - if (cachedSideChainBlockData == null) - { - Logger.LogDebug( - $"Side chain data not found. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}."); - return false; - } - - if (!cachedSideChainBlockData.Equals(sideChainBlockData)) - { - Logger.LogDebug( - $"Incorrect side chain data. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}."); - return false; - } - - sideChainValidatedHeightDict[sideChainBlockData.ChainId] = sideChainBlockData.Height; + BlockHeight = blockHeight + }) + }).GetSideChainHeight + .CallAsync( + new Int32Value + { + Value = sideChainBlockData.ChainId + }); + validatedHeight = height?.Value ?? 0; } - return true; + var targetHeight = validatedHeight + 1; + + if (targetHeight != sideChainBlockData.Height) + // this should not happen if it is good data. + return false; + + var cachedSideChainBlockData = + _blockCacheEntityConsumer.Take(sideChainBlockData.ChainId, targetHeight, false); + if (cachedSideChainBlockData == null) + { + Logger.LogDebug( + $"Side chain data not found. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}."); + return false; + } + + if (!cachedSideChainBlockData.Equals(sideChainBlockData)) + { + Logger.LogDebug( + $"Incorrect side chain data. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}."); + return false; + } + + sideChainValidatedHeightDict[sideChainBlockData.ChainId] = sideChainBlockData.Height; } - private async Task ValidateParentChainBlockDataAsync( - IEnumerable multiParentChainBlockData, - Hash blockHash, long blockHeight) + return true; + } + + private async Task ValidateParentChainBlockDataAsync( + IEnumerable multiParentChainBlockData, + Hash blockHash, long blockHeight) + { + var parentChainBlockDataList = multiParentChainBlockData.ToList(); + if (parentChainBlockDataList.Count == 0) + return true; + var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext { - var parentChainBlockDataList = multiParentChainBlockData.ToList(); - if (parentChainBlockDataList.Count == 0) - return true; - var crossChainContractAddress = await GetCrossChainContractAddressAsync(new ChainContext + BlockHash = blockHash, + BlockHeight = blockHeight + }); + var parentChainId = (await _contractReaderFactory + .Create(new ContractReaderContext { BlockHash = blockHash, - BlockHeight = blockHeight - }); - var parentChainId = (await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = crossChainContractAddress - }).GetParentChainId - .CallAsync(new Empty())).Value; - if (parentChainId == 0) - // no configured parent chain + BlockHeight = blockHeight, + ContractAddress = crossChainContractAddress + }).GetParentChainId + .CallAsync(new Empty())).Value; + if (parentChainId == 0) + // no configured parent chain + return false; + + var length = parentChainBlockDataList.Count; + var i = 0; + var targetHeight = (await _contractReaderFactory.Create(new ContractReaderContext + { + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = crossChainContractAddress + }).GetParentChainHeight + .CallAsync(new Empty())).Value + 1; + while (i < length) + { + var parentChainBlockData = + _blockCacheEntityConsumer.Take(parentChainId, targetHeight, false); + if (parentChainBlockData == null) + { + Logger.LogDebug( + $"Parent chain data not found. Parent chain height: {targetHeight}."); return false; + } - var length = parentChainBlockDataList.Count; - var i = 0; - var targetHeight = (await _contractReaderFactory.Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = crossChainContractAddress - }).GetParentChainHeight - .CallAsync(new Empty())).Value + 1; - while (i < length) + if (!parentChainBlockDataList[i].Equals(parentChainBlockData)) { - var parentChainBlockData = - _blockCacheEntityConsumer.Take(parentChainId, targetHeight, false); - if (parentChainBlockData == null) - { - Logger.LogDebug( - $"Parent chain data not found. Parent chain height: {targetHeight}."); - return false; - } - - if (!parentChainBlockDataList[i].Equals(parentChainBlockData)) - { - Logger.LogDebug( - $"Incorrect parent chain data. Parent chain height: {targetHeight}."); - return false; - } - - targetHeight++; - i++; + Logger.LogDebug( + $"Incorrect parent chain data. Parent chain height: {targetHeight}."); + return false; } - return true; + targetHeight++; + i++; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataService.cs b/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataService.cs index 5fef9d03ec..4ed7bda727 100644 --- a/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataService.cs +++ b/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataService.cs @@ -1,28 +1,27 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Indexing.Infrastructure; using AElf.Kernel; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.CrossChain.Indexing.Application +namespace AElf.CrossChain.Indexing.Application; + +public interface ICrossChainIndexingDataService { - public interface ICrossChainIndexingDataService - { - Task GetIndexedSideChainBlockDataAsync(Hash blockHash, long blockHeight); + Task GetIndexedSideChainBlockDataAsync(Hash blockHash, long blockHeight); - Task GetCrossChainTransactionInputForNextMiningAsync(Hash blockHash, - long blockHeight); + Task GetCrossChainTransactionInputForNextMiningAsync(Hash blockHash, + long blockHeight); - Task CheckExtraDataIsNeededAsync(Hash blockHash, long blockHeight, Timestamp timestamp); + Task CheckExtraDataIsNeededAsync(Hash blockHash, long blockHeight, Timestamp timestamp); - Task PrepareExtraDataForNextMiningAsync(Hash blockHash, long blockHeight); + Task PrepareExtraDataForNextMiningAsync(Hash blockHash, long blockHeight); - // ByteString ExtractCrossChainExtraDataFromCrossChainBlockData(CrossChainBlockData crossChainBlockData); - void UpdateCrossChainDataWithLib(Hash blockHash, long blockHeight); - Task GetAllChainIdHeightPairsAtLibAsync(); - Task GetChainInitializationDataAsync(int chainId); - Task GetNonIndexedBlockAsync(long requestHeight); - } + // ByteString ExtractCrossChainExtraDataFromCrossChainBlockData(CrossChainBlockData crossChainBlockData); + void UpdateCrossChainDataWithLib(Hash blockHash, long blockHeight); + Task GetAllChainIdHeightPairsAtLibAsync(); + Task GetChainInitializationDataAsync(int chainId); + Task GetNonIndexedBlockAsync(long requestHeight); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataValidationService.cs b/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataValidationService.cs index 50c5751cc0..8b51993c5b 100644 --- a/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataValidationService.cs +++ b/src/AElf.CrossChain.Core/Indexing/Application/ICrossChainIndexingDataValidationService.cs @@ -2,11 +2,10 @@ using AElf.Standards.ACS7; using AElf.Types; -namespace AElf.CrossChain.Indexing.Application +namespace AElf.CrossChain.Indexing.Application; + +public interface ICrossChainIndexingDataValidationService { - public interface ICrossChainIndexingDataValidationService - { - Task ValidateCrossChainIndexingDataAsync(CrossChainBlockData crossChainBlockData, Hash blockHash, - long blockHeight); - } + Task ValidateCrossChainIndexingDataAsync(CrossChainBlockData crossChainBlockData, Hash blockHash, + long blockHeight); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Infrastructure/IIrreversibleBlockStateProvider.cs b/src/AElf.CrossChain.Core/Indexing/Infrastructure/IIrreversibleBlockStateProvider.cs index a47f20464d..95f7b7b616 100644 --- a/src/AElf.CrossChain.Core/Indexing/Infrastructure/IIrreversibleBlockStateProvider.cs +++ b/src/AElf.CrossChain.Core/Indexing/Infrastructure/IIrreversibleBlockStateProvider.cs @@ -1,12 +1,11 @@ using System.Threading.Tasks; using AElf.Kernel; -namespace AElf.CrossChain.Indexing.Infrastructure +namespace AElf.CrossChain.Indexing.Infrastructure; + +public interface IIrreversibleBlockStateProvider { - public interface IIrreversibleBlockStateProvider - { - Task GetNotIndexedIrreversibleBlockByHeightAsync(long height); - Task GetLastIrreversibleBlockHashAndHeightAsync(); - Task ValidateIrreversibleBlockExistingAsync(); - } + Task GetNotIndexedIrreversibleBlockByHeightAsync(long height); + Task GetLastIrreversibleBlockHashAndHeightAsync(); + Task ValidateIrreversibleBlockExistingAsync(); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Infrastructure/ITransactionInputForBlockMiningDataProvider.cs b/src/AElf.CrossChain.Core/Indexing/Infrastructure/ITransactionInputForBlockMiningDataProvider.cs index 4994456b07..013c564804 100644 --- a/src/AElf.CrossChain.Core/Indexing/Infrastructure/ITransactionInputForBlockMiningDataProvider.cs +++ b/src/AElf.CrossChain.Core/Indexing/Infrastructure/ITransactionInputForBlockMiningDataProvider.cs @@ -1,21 +1,20 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.CrossChain.Indexing.Infrastructure +namespace AElf.CrossChain.Indexing.Infrastructure; + +public interface ITransactionInputForBlockMiningDataProvider { - public interface ITransactionInputForBlockMiningDataProvider - { - void AddTransactionInputForBlockMining(Hash blockHash, CrossChainTransactionInput crossChainTransactionInput); - - CrossChainTransactionInput GetTransactionInputForBlockMining(Hash blockHash); + void AddTransactionInputForBlockMining(Hash blockHash, CrossChainTransactionInput crossChainTransactionInput); + + CrossChainTransactionInput GetTransactionInputForBlockMining(Hash blockHash); - void ClearExpiredTransactionInput(long blockHeight); - } - - public class CrossChainTransactionInput - { - public long PreviousBlockHeight { get; set; } - public string MethodName { get; set; } - public ByteString Value { get; set; } - } + void ClearExpiredTransactionInput(long blockHeight); +} + +public class CrossChainTransactionInput +{ + public long PreviousBlockHeight { get; set; } + public string MethodName { get; set; } + public ByteString Value { get; set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Infrastructure/IrreversibleBlockStateProvider.cs b/src/AElf.CrossChain.Core/Indexing/Infrastructure/IrreversibleBlockStateProvider.cs index c5eaa3d3e9..39a9d8acfe 100644 --- a/src/AElf.CrossChain.Core/Indexing/Infrastructure/IrreversibleBlockStateProvider.cs +++ b/src/AElf.CrossChain.Core/Indexing/Infrastructure/IrreversibleBlockStateProvider.cs @@ -2,39 +2,38 @@ using AElf.Kernel; using AElf.Kernel.Blockchain.Application; -namespace AElf.CrossChain.Indexing.Infrastructure +namespace AElf.CrossChain.Indexing.Infrastructure; + +public class IrreversibleBlockStateProvider : IIrreversibleBlockStateProvider { - public class IrreversibleBlockStateProvider : IIrreversibleBlockStateProvider + private readonly IBlockchainService _blockchainService; + private bool _irreversibleBlockExists; + + public IrreversibleBlockStateProvider(IBlockchainService blockchainService) { - private readonly IBlockchainService _blockchainService; - private bool _irreversibleBlockExists; + _blockchainService = blockchainService; + } - public IrreversibleBlockStateProvider(IBlockchainService blockchainService) - { - _blockchainService = blockchainService; - } + public async Task GetNotIndexedIrreversibleBlockByHeightAsync(long height) + { + var libExistenceValidationResult = await ValidateIrreversibleBlockExistingAsync(); + if (!libExistenceValidationResult) + return null; + return await _blockchainService.GetIrreversibleBlockByHeightAsync(height); + } - public async Task GetNotIndexedIrreversibleBlockByHeightAsync(long height) - { - var libExistenceValidationResult = await ValidateIrreversibleBlockExistingAsync(); - if (!libExistenceValidationResult) - return null; - return await _blockchainService.GetIrreversibleBlockByHeightAsync(height); - } + public async Task GetLastIrreversibleBlockHashAndHeightAsync() + { + return await _blockchainService.GetLibHashAndHeightAsync(); + } - public async Task GetLastIrreversibleBlockHashAndHeightAsync() - { - return await _blockchainService.GetLibHashAndHeightAsync(); - } - - public async Task ValidateIrreversibleBlockExistingAsync() - { - if (_irreversibleBlockExists) - return true; - var libIdHeight = await GetLastIrreversibleBlockHashAndHeightAsync(); - var lastIrreversibleBlockHeight = libIdHeight.BlockHeight; - _irreversibleBlockExists = lastIrreversibleBlockHeight > AElfConstants.GenesisBlockHeight; - return _irreversibleBlockExists; - } + public async Task ValidateIrreversibleBlockExistingAsync() + { + if (_irreversibleBlockExists) + return true; + var libIdHeight = await GetLastIrreversibleBlockHashAndHeightAsync(); + var lastIrreversibleBlockHeight = libIdHeight.BlockHeight; + _irreversibleBlockExists = lastIrreversibleBlockHeight > AElfConstants.GenesisBlockHeight; + return _irreversibleBlockExists; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Indexing/Infrastructure/TransactionInputForBlockMiningDataProvider.cs b/src/AElf.CrossChain.Core/Indexing/Infrastructure/TransactionInputForBlockMiningDataProvider.cs index 1c261f1ef8..2eacc7b1ac 100644 --- a/src/AElf.CrossChain.Core/Indexing/Infrastructure/TransactionInputForBlockMiningDataProvider.cs +++ b/src/AElf.CrossChain.Core/Indexing/Infrastructure/TransactionInputForBlockMiningDataProvider.cs @@ -3,33 +3,29 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Indexing.Infrastructure +namespace AElf.CrossChain.Indexing.Infrastructure; + +internal class TransactionInputForBlockMiningDataProvider : ITransactionInputForBlockMiningDataProvider, + ISingletonDependency { - internal class TransactionInputForBlockMiningDataProvider : ITransactionInputForBlockMiningDataProvider, ISingletonDependency - { - private readonly Dictionary _indexedCrossChainBlockData = - new Dictionary(); + private readonly Dictionary _indexedCrossChainBlockData = new(); - public void AddTransactionInputForBlockMining(Hash blockHash, CrossChainTransactionInput crossChainTransactionInput) - { - _indexedCrossChainBlockData[blockHash] = crossChainTransactionInput; - } + public void AddTransactionInputForBlockMining(Hash blockHash, CrossChainTransactionInput crossChainTransactionInput) + { + _indexedCrossChainBlockData[blockHash] = crossChainTransactionInput; + } - public CrossChainTransactionInput GetTransactionInputForBlockMining(Hash blockHash) - { - return _indexedCrossChainBlockData.TryGetValue(blockHash, out var crossChainBlockData) - ? crossChainBlockData - : null; - } + public CrossChainTransactionInput GetTransactionInputForBlockMining(Hash blockHash) + { + return _indexedCrossChainBlockData.TryGetValue(blockHash, out var crossChainBlockData) + ? crossChainBlockData + : null; + } - public void ClearExpiredTransactionInput(long blockHeight) - { - var toRemoveList = _indexedCrossChainBlockData.Where(kv => kv.Value.PreviousBlockHeight < blockHeight) - .Select(kv => kv.Key); - foreach (var hash in toRemoveList) - { - _indexedCrossChainBlockData.Remove(hash); - } - } + public void ClearExpiredTransactionInput(long blockHeight) + { + var toRemoveList = _indexedCrossChainBlockData.Where(kv => kv.Value.PreviousBlockHeight < blockHeight) + .Select(kv => kv.Key); + foreach (var hash in toRemoveList) _indexedCrossChainBlockData.Remove(hash); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Core/Protobuf/ProtobufTypes.cs b/src/AElf.CrossChain.Core/Protobuf/ProtobufTypes.cs index 64324a3fa7..2ad8b66533 100644 --- a/src/AElf.CrossChain.Core/Protobuf/ProtobufTypes.cs +++ b/src/AElf.CrossChain.Core/Protobuf/ProtobufTypes.cs @@ -1,12 +1,11 @@ using AElf.CrossChain; -namespace AElf.Standards.ACS7 +namespace AElf.Standards.ACS7; + +public partial class SideChainBlockData : ICrossChainBlockEntity +{ +} + +public partial class ParentChainBlockData : ICrossChainBlockEntity { - public partial class SideChainBlockData : ICrossChainBlockEntity - { - } - - public partial class ParentChainBlockData : ICrossChainBlockEntity - { - } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/AElf.CrossChain.Grpc.csproj b/src/AElf.CrossChain.Grpc/AElf.CrossChain.Grpc.csproj index 1e2c1d2ac8..2c679e0a27 100644 --- a/src/AElf.CrossChain.Grpc/AElf.CrossChain.Grpc.csproj +++ b/src/AElf.CrossChain.Grpc/AElf.CrossChain.Grpc.csproj @@ -9,13 +9,13 @@ - 1701;1702 + 1701;1702 - + .\Protobuf\crosschain_rpc.proto @@ -24,12 +24,13 @@ - + + - + diff --git a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClient.cs b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClient.cs index fa4d77e120..d75999e74e 100644 --- a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClient.cs +++ b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClient.cs @@ -1,207 +1,203 @@ using System; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Communication.Infrastructure; using AElf.Kernel; +using AElf.Standards.ACS7; using Grpc.Core; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcClientInitializationContext { - public class GrpcClientInitializationContext - { - public string UriStr { get; set; } - public int LocalChainId { get; set; } + public string UriStr { get; set; } + public int LocalChainId { get; set; } - public int RemoteChainId { get; set; } - public int DialTimeout { get; set; } - public int ListeningPort { get; set; } - } + public int RemoteChainId { get; set; } + public int DialTimeout { get; set; } + public int ListeningPort { get; set; } +} - public abstract class GrpcCrossChainClient : ICrossChainClient where TData : ICrossChainBlockEntity - where TClient : ClientBase - { - protected Channel Channel; - protected readonly int DialTimeout; - protected TClient GrpcClient; +public abstract class GrpcCrossChainClient : ICrossChainClient where TData : ICrossChainBlockEntity + where TClient : ClientBase +{ + private readonly BasicCrossChainRpc.BasicCrossChainRpcClient _basicGrpcClient; + private readonly int _listeningPort; - private readonly int _localChainId; - private readonly int _listeningPort; - private readonly BasicCrossChainRpc.BasicCrossChainRpcClient _basicGrpcClient; + private readonly int _localChainId; + protected readonly int DialTimeout; + protected Channel Channel; + protected TClient GrpcClient; - public string TargetUriString => Channel.Target; - public bool IsConnected { get; private set; } - public int RemoteChainId { get; } + protected GrpcCrossChainClient(GrpcClientInitializationContext grpcClientInitializationContext) + { + _localChainId = grpcClientInitializationContext.LocalChainId; + RemoteChainId = grpcClientInitializationContext.RemoteChainId; + DialTimeout = grpcClientInitializationContext.DialTimeout; + Channel = CreateChannel(grpcClientInitializationContext.UriStr); + _basicGrpcClient = new BasicCrossChainRpc.BasicCrossChainRpcClient(Channel); + _listeningPort = grpcClientInitializationContext.ListeningPort; + } - protected GrpcCrossChainClient(GrpcClientInitializationContext grpcClientInitializationContext) - { - _localChainId = grpcClientInitializationContext.LocalChainId; - RemoteChainId = grpcClientInitializationContext.RemoteChainId; - DialTimeout = grpcClientInitializationContext.DialTimeout; - Channel = CreateChannel(grpcClientInitializationContext.UriStr); - _basicGrpcClient = new BasicCrossChainRpc.BasicCrossChainRpcClient(Channel); - _listeningPort = grpcClientInitializationContext.ListeningPort; - } + public string TargetUriString => Channel.Target; + public bool IsConnected { get; private set; } + public int RemoteChainId { get; } - /// - /// Create a new channel. - /// - /// - /// - private static Channel CreateChannel(string uriStr) - { - return new Channel(uriStr, ChannelCredentials.Insecure); - } + /// + /// Connect with target chain. + /// + /// + public Task ConnectAsync() + { + return RequestAsync(HandshakeAsync); + } - /// - /// Connect with target chain. - /// - /// - public Task ConnectAsync() - { - return RequestAsync(HandshakeAsync); - } + /// + /// Close client and clear channel. + /// + /// + public async Task CloseAsync() + { + IsConnected = false; + await Channel.ShutdownAsync(); + } - /// - /// Close client and clear channel. - /// - /// - public async Task CloseAsync() + /// + /// Request target chain for cross chain data from target height. + /// + /// + /// + /// + public Task RequestCrossChainDataAsync(long targetHeight, + Func crossChainBlockDataEntityHandler) + { + var requestData = new CrossChainRequest { - IsConnected = false; - await Channel.ShutdownAsync(); - } + ChainId = _localChainId, + NextHeight = targetHeight + }; - /// - /// Request target chain for cross chain data from target height. - /// - /// - /// - /// - public Task RequestCrossChainDataAsync(long targetHeight, - Func crossChainBlockDataEntityHandler) - { - var requestData = new CrossChainRequest - { - ChainId = _localChainId, - NextHeight = targetHeight - }; + return RequestAsync(() => RequestCrossChainDataAsync(requestData, crossChainBlockDataEntityHandler)); + } - return RequestAsync(() => RequestCrossChainDataAsync(requestData, crossChainBlockDataEntityHandler)); - } + public abstract Task RequestChainInitializationDataAsync(int chainId); - /// - /// Asynchronous request method. - /// - /// - /// - private async Task RequestAsync(Func requestFunc) + /// + /// Create a new channel. + /// + /// + /// + private static Channel CreateChannel(string uriStr) + { + return new Channel(uriStr, ChannelCredentials.Insecure); + } + + /// + /// Asynchronous request method. + /// + /// + /// + private async Task RequestAsync(Func requestFunc) + { + try { - try - { - await requestFunc(); - } - catch (RpcException e) - { - IsConnected = false; - throw new GrpcCrossChainRequestException(e.Message, e); - } + await requestFunc(); } - - /// - /// Create options for grpc request. - /// - /// - protected CallOptions CreateOption() + catch (RpcException e) { - return new CallOptions().WithDeadline(TimestampHelper.GetUtcNow().ToDateTime() - .AddMilliseconds(DialTimeout)); + IsConnected = false; + throw new GrpcCrossChainRequestException(e.Message, e); } + } + + /// + /// Create options for grpc request. + /// + /// + protected CallOptions CreateOption() + { + return new CallOptions().WithDeadline(TimestampHelper.GetUtcNow().ToDateTime() + .AddMilliseconds(DialTimeout)); + } - private async Task RequestCrossChainDataAsync(CrossChainRequest crossChainRequest, - Func crossChainBlockDataEntityHandler) + private async Task RequestCrossChainDataAsync(CrossChainRequest crossChainRequest, + Func crossChainBlockDataEntityHandler) + { + using (var serverStream = RequestIndexing(crossChainRequest)) { - using (var serverStream = RequestIndexing(crossChainRequest)) + while (await serverStream.ResponseStream.MoveNext(CancellationToken.None)) { - while (await serverStream.ResponseStream.MoveNext(CancellationToken.None)) - { - var response = serverStream.ResponseStream.Current; + var response = serverStream.ResponseStream.Current; - // requestCrossChain failed or useless response - if (!crossChainBlockDataEntityHandler(response)) - { - break; - } - } + // requestCrossChain failed or useless response + if (!crossChainBlockDataEntityHandler(response)) break; } } + } - private async Task HandshakeAsync() + private async Task HandshakeAsync() + { + var reply = await _basicGrpcClient.CrossChainHandShakeAsync(new HandShake { - var reply = await _basicGrpcClient.CrossChainHandShakeAsync(new HandShake - { - ChainId = _localChainId, - ListeningPort = _listeningPort - }, CreateOption()); - IsConnected = reply != null && reply.Status == HandShakeReply.Types.HandShakeStatus.Success; - } + ChainId = _localChainId, + ListeningPort = _listeningPort + }, CreateOption()); + IsConnected = reply != null && reply.Status == HandShakeReply.Types.HandShakeStatus.Success; + } - public abstract Task RequestChainInitializationDataAsync(int chainId); + protected abstract AsyncServerStreamingCall RequestIndexing(CrossChainRequest crossChainRequest); +} - protected abstract AsyncServerStreamingCall RequestIndexing(CrossChainRequest crossChainRequest); +public class ClientForSideChain : GrpcCrossChainClient +{ + public ClientForSideChain(GrpcClientInitializationContext grpcClientInitializationContext) + : base(grpcClientInitializationContext) + { + GrpcClient = new SideChainRpc.SideChainRpcClient(Channel); } - public class ClientForSideChain : GrpcCrossChainClient + public override Task RequestChainInitializationDataAsync(int chainId) { - public ClientForSideChain(GrpcClientInitializationContext grpcClientInitializationContext) - : base(grpcClientInitializationContext) - { - GrpcClient = new SideChainRpc.SideChainRpcClient(Channel); - } + throw new NotImplementedException(); + } - public override Task RequestChainInitializationDataAsync(int chainId) - { - throw new NotImplementedException(); - } + protected override AsyncServerStreamingCall RequestIndexing( + CrossChainRequest crossChainRequest) + { + return GrpcClient.RequestIndexingFromSideChain(crossChainRequest, CreateOption()); + } +} - protected override AsyncServerStreamingCall RequestIndexing( - CrossChainRequest crossChainRequest) - { - return GrpcClient.RequestIndexingFromSideChain(crossChainRequest, CreateOption()); - } +public class ClientForParentChain : GrpcCrossChainClient +{ + public ClientForParentChain(GrpcClientInitializationContext grpcClientInitializationContext) + : base(grpcClientInitializationContext) + { + GrpcClient = new ParentChainRpc.ParentChainRpcClient(Channel); } - public class ClientForParentChain : GrpcCrossChainClient + protected override AsyncServerStreamingCall RequestIndexing( + CrossChainRequest crossChainRequest) { - public ClientForParentChain(GrpcClientInitializationContext grpcClientInitializationContext) - : base(grpcClientInitializationContext) - { - GrpcClient = new ParentChainRpc.ParentChainRpcClient(Channel); - } + return GrpcClient.RequestIndexingFromParentChain(crossChainRequest, CreateOption()); + } - protected override AsyncServerStreamingCall RequestIndexing( - CrossChainRequest crossChainRequest) + public override async Task RequestChainInitializationDataAsync(int chainId) + { + try { - return GrpcClient.RequestIndexingFromParentChain(crossChainRequest, CreateOption()); + var sideChainInitializationResponse = + await GrpcClient.RequestChainInitializationDataFromParentChainAsync( + new SideChainInitializationRequest + { + ChainId = chainId + }); + return sideChainInitializationResponse; } - - public override async Task RequestChainInitializationDataAsync(int chainId) + catch (RpcException e) { - try - { - var sideChainInitializationResponse = - await GrpcClient.RequestChainInitializationDataFromParentChainAsync( - new SideChainInitializationRequest - { - ChainId = chainId - }); - return sideChainInitializationResponse; - } - catch (RpcException e) - { - throw new GrpcCrossChainRequestException("Request initialization data failed.", e); - } + throw new GrpcCrossChainRequestException("Request initialization data failed.", e); } } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientCreationContext.cs b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientCreationContext.cs index c3c8ae253c..425bddc665 100644 --- a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientCreationContext.cs +++ b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientCreationContext.cs @@ -1,8 +1,7 @@ using AElf.CrossChain.Communication.Infrastructure; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainClientCreationContext : CrossChainClientCreationContext { - public class GrpcCrossChainClientCreationContext : CrossChainClientCreationContext - { - } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientNodePlugin.cs b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientNodePlugin.cs index 46bc9d4f9a..2f319bb515 100644 --- a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientNodePlugin.cs +++ b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientNodePlugin.cs @@ -3,47 +3,46 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Grpc.Client -{ - public class GrpcCrossChainClientNodePlugin : IGrpcClientPlugin - { - private readonly ICrossChainClientService _crossChainClientService; - private readonly CrossChainConfigOptions _crossChainConfigOptions; - public int ChainId { get; private set; } +namespace AElf.CrossChain.Grpc.Client; - public ILogger Logger { get; set; } +public class GrpcCrossChainClientNodePlugin : IGrpcClientPlugin +{ + private readonly ICrossChainClientService _crossChainClientService; + private readonly CrossChainConfigOptions _crossChainConfigOptions; - public GrpcCrossChainClientNodePlugin(IOptionsSnapshot crossChainConfigOption, - ICrossChainClientService crossChainClientService) - { - _crossChainClientService = crossChainClientService; - _crossChainConfigOptions = crossChainConfigOption.Value; - } + public GrpcCrossChainClientNodePlugin(IOptionsSnapshot crossChainConfigOption, + ICrossChainClientService crossChainClientService) + { + _crossChainClientService = crossChainClientService; + _crossChainConfigOptions = crossChainConfigOption.Value; + } - public async Task StartAsync(int chainId) - { - ChainId = chainId; + public ILogger Logger { get; set; } + public int ChainId { get; private set; } - if (string.IsNullOrEmpty(_crossChainConfigOptions.ParentChainId)) - return; - Logger.LogInformation("Starting client to parent chain.."); + public async Task StartAsync(int chainId) + { + ChainId = chainId; - await _crossChainClientService.CreateClientAsync(new GrpcCrossChainClientCreationContext - { - RemoteChainId = ChainHelper.ConvertBase58ToChainId(_crossChainConfigOptions.ParentChainId), - LocalChainId = chainId, - IsClientToParentChain = true - }); - } + if (string.IsNullOrEmpty(_crossChainConfigOptions.ParentChainId)) + return; + Logger.LogInformation("Starting client to parent chain.."); - public async Task ShutdownAsync() + await _crossChainClientService.CreateClientAsync(new GrpcCrossChainClientCreationContext { - await _crossChainClientService.CloseClientsAsync(); - } + RemoteChainId = ChainHelper.ConvertBase58ToChainId(_crossChainConfigOptions.ParentChainId), + LocalChainId = chainId, + IsClientToParentChain = true + }); + } - public async Task CreateClientAsync(GrpcCrossChainClientCreationContext crossChainClientCreationContext) - { - await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); - } + public async Task ShutdownAsync() + { + await _crossChainClientService.CloseClientsAsync(); + } + + public async Task CreateClientAsync(GrpcCrossChainClientCreationContext crossChainClientCreationContext) + { + await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientProvider.cs b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientProvider.cs index d317f886ee..a64709afec 100644 --- a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientProvider.cs +++ b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainClientProvider.cs @@ -7,87 +7,87 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainClientProvider : ICrossChainClientProvider, ISingletonDependency { - public class GrpcCrossChainClientProvider : ICrossChainClientProvider, ISingletonDependency + private readonly ConcurrentDictionary _grpcCrossChainClients = new(); + + private readonly GrpcCrossChainConfigOption _grpcCrossChainConfigOption; + + public GrpcCrossChainClientProvider(IOptionsSnapshot grpcCrossChainConfigOption) { - public ILogger Logger { get; set; } + _grpcCrossChainConfigOption = grpcCrossChainConfigOption.Value; + } - private readonly ConcurrentDictionary _grpcCrossChainClients = - new ConcurrentDictionary(); + public ILogger Logger { get; set; } - private readonly GrpcCrossChainConfigOption _grpcCrossChainConfigOption; + public bool TryGetClient(int chainId, out ICrossChainClient client) + { + return _grpcCrossChainClients.TryGetValue(chainId, out client); + } - public GrpcCrossChainClientProvider(IOptionsSnapshot grpcCrossChainConfigOption) - { - _grpcCrossChainConfigOption = grpcCrossChainConfigOption.Value; - } + public List GetAllClients() + { + return _grpcCrossChainClients.Values.ToList(); + } - #region Create client + private string GetUriStr(string host, int port) + { + return new UriBuilder("http", host, port).Uri.Authority; + } - public ICrossChainClient AddOrUpdateClient(CrossChainClientCreationContext crossChainClientCreationContext) + private ICrossChainClient CreateClient(CrossChainClientCreationContext crossChainClientCreationContext) + { + var clientInitializationContext = new GrpcClientInitializationContext { - var chainId = crossChainClientCreationContext.RemoteChainId; - var uriStr = crossChainClientCreationContext.IsClientToParentChain - ? GetUriStr(_grpcCrossChainConfigOption.ParentChainServerIp, - _grpcCrossChainConfigOption.ParentChainServerPort) - : GetUriStr(crossChainClientCreationContext.RemoteServerHost, crossChainClientCreationContext.RemoteServerPort); - - if (TryGetClient(chainId, out var client) && client.TargetUriString.Equals(uriStr)) - return client; // client already cached - - client = CreateClient(crossChainClientCreationContext); - _grpcCrossChainClients.TryAdd(chainId, client); - Logger.LogTrace("Create client finished."); - return client; - } - - /// - /// Create a new client to another chain. - /// - /// - /// - public ICrossChainClient CreateChainInitializationDataClient(CrossChainClientCreationContext crossChainClientCreationContext) + DialTimeout = _grpcCrossChainConfigOption.ConnectionTimeout, + LocalChainId = crossChainClientCreationContext.LocalChainId, + ListeningPort = _grpcCrossChainConfigOption.ListeningPort, + RemoteChainId = crossChainClientCreationContext.RemoteChainId + }; + if (crossChainClientCreationContext.IsClientToParentChain) { - return CreateClient(crossChainClientCreationContext); + clientInitializationContext.UriStr = GetUriStr(_grpcCrossChainConfigOption.ParentChainServerIp, + _grpcCrossChainConfigOption.ParentChainServerPort); + return new ClientForParentChain(clientInitializationContext); } - #endregion Create client + clientInitializationContext.UriStr = GetUriStr(crossChainClientCreationContext.RemoteServerHost, + crossChainClientCreationContext.RemoteServerPort); + return new ClientForSideChain(clientInitializationContext); + } - public bool TryGetClient(int chainId, out ICrossChainClient client) - { - return _grpcCrossChainClients.TryGetValue(chainId, out client); - } + #region Create client - public List GetAllClients() - { - return _grpcCrossChainClients.Values.ToList(); - } + public ICrossChainClient AddOrUpdateClient(CrossChainClientCreationContext crossChainClientCreationContext) + { + var chainId = crossChainClientCreationContext.RemoteChainId; + var uriStr = crossChainClientCreationContext.IsClientToParentChain + ? GetUriStr(_grpcCrossChainConfigOption.ParentChainServerIp, + _grpcCrossChainConfigOption.ParentChainServerPort) + : GetUriStr(crossChainClientCreationContext.RemoteServerHost, + crossChainClientCreationContext.RemoteServerPort); - private string GetUriStr(string host, int port) - { - return new UriBuilder("http", host, port).Uri.Authority; - } + if (TryGetClient(chainId, out var client) && client.TargetUriString.Equals(uriStr)) + return client; // client already cached - private ICrossChainClient CreateClient(CrossChainClientCreationContext crossChainClientCreationContext) - { - var clientInitializationContext = new GrpcClientInitializationContext - { - DialTimeout = _grpcCrossChainConfigOption.ConnectionTimeout, - LocalChainId = crossChainClientCreationContext.LocalChainId, - ListeningPort = _grpcCrossChainConfigOption.ListeningPort, - RemoteChainId = crossChainClientCreationContext.RemoteChainId - }; - if (crossChainClientCreationContext.IsClientToParentChain) - { - clientInitializationContext.UriStr = GetUriStr(_grpcCrossChainConfigOption.ParentChainServerIp, - _grpcCrossChainConfigOption.ParentChainServerPort); - return new ClientForParentChain(clientInitializationContext); - } - - clientInitializationContext.UriStr = GetUriStr(crossChainClientCreationContext.RemoteServerHost, - crossChainClientCreationContext.RemoteServerPort); - return new ClientForSideChain(clientInitializationContext); - } + client = CreateClient(crossChainClientCreationContext); + _grpcCrossChainClients.TryAdd(chainId, client); + Logger.LogTrace("Create client finished."); + return client; } + + /// + /// Create a new client to another chain. + /// + /// + /// + public ICrossChainClient CreateChainInitializationDataClient( + CrossChainClientCreationContext crossChainClientCreationContext) + { + return CreateClient(crossChainClientCreationContext); + } + + #endregion Create client } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainRequestException.cs b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainRequestException.cs index 2436238806..38b30f739f 100644 --- a/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainRequestException.cs +++ b/src/AElf.CrossChain.Grpc/Client/GrpcCrossChainRequestException.cs @@ -1,16 +1,14 @@ using System; -using AElf.CrossChain.Communication; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainRequestException : CrossChainRequestException { - public class GrpcCrossChainRequestException : CrossChainRequestException + public GrpcCrossChainRequestException(string message) : base(message) { - public GrpcCrossChainRequestException(string message) : base(message) - { - } + } - public GrpcCrossChainRequestException(string message, Exception innerException) : base(message, innerException) - { - } + public GrpcCrossChainRequestException(string message, Exception innerException) : base(message, innerException) + { } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Client/IGrpcCrossChainPlugin.cs b/src/AElf.CrossChain.Grpc/Client/IGrpcCrossChainPlugin.cs index 654741de7e..dd186e5983 100644 --- a/src/AElf.CrossChain.Grpc/Client/IGrpcCrossChainPlugin.cs +++ b/src/AElf.CrossChain.Grpc/Client/IGrpcCrossChainPlugin.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using AElf.CrossChain.Communication; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public interface IGrpcClientPlugin : ICrossChainCommunicationPlugin { - public interface IGrpcClientPlugin : ICrossChainCommunicationPlugin - { - Task CreateClientAsync(GrpcCrossChainClientCreationContext grpcCrossChainClientCreationContext); - } + Task CreateClientAsync(GrpcCrossChainClientCreationContext grpcCrossChainClientCreationContext); } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/GrpcCrossChainAElfModule.cs b/src/AElf.CrossChain.Grpc/GrpcCrossChainAElfModule.cs index acb74039e7..6ad64e9937 100644 --- a/src/AElf.CrossChain.Grpc/GrpcCrossChainAElfModule.cs +++ b/src/AElf.CrossChain.Grpc/GrpcCrossChainAElfModule.cs @@ -5,20 +5,19 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +[DependsOn(typeof(CrossChainCoreModule))] +public class GrpcCrossChainAElfModule : AElfModule { - [DependsOn(typeof(CrossChainCoreModule))] - public class GrpcCrossChainAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - var grpcCrossChainConfiguration = services.GetConfiguration().GetSection("CrossChain"); - Configure(grpcCrossChainConfiguration.GetSection("Grpc")); - } + var services = context.Services; + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + var grpcCrossChainConfiguration = services.GetConfiguration().GetSection("CrossChain"); + Configure(grpcCrossChainConfiguration.GetSection("Grpc")); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/GrpcCrossChainConfigOption.cs b/src/AElf.CrossChain.Grpc/GrpcCrossChainConfigOption.cs index 77b044c974..fe885c27bc 100644 --- a/src/AElf.CrossChain.Grpc/GrpcCrossChainConfigOption.cs +++ b/src/AElf.CrossChain.Grpc/GrpcCrossChainConfigOption.cs @@ -1,15 +1,14 @@ -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public class GrpcCrossChainConfigOption { - public class GrpcCrossChainConfigOption - { - public int ListeningPort { get; set; } - public int ConnectionTimeout { get; set; } = 500; - - #region Parent chain - - public string ParentChainServerIp { get; set; } - public int ParentChainServerPort { get; set; } - - #endregion - } + public int ListeningPort { get; set; } + public int ConnectionTimeout { get; set; } = 500; + + #region Parent chain + + public string ParentChainServerIp { get; set; } + public int ParentChainServerPort { get; set; } + + #endregion } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/GrpcCrossChainConnectionEventHandler.cs b/src/AElf.CrossChain.Grpc/GrpcCrossChainConnectionEventHandler.cs index f9e95c386c..aa32db6713 100644 --- a/src/AElf.CrossChain.Grpc/GrpcCrossChainConnectionEventHandler.cs +++ b/src/AElf.CrossChain.Grpc/GrpcCrossChainConnectionEventHandler.cs @@ -4,28 +4,28 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public class GrpcCrossChainConnectionEventHandler : ILocalEventHandler, ITransientDependency { - public class GrpcCrossChainConnectionEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly IGrpcClientPlugin _grpcClientPlugin; - private readonly ICrossChainCommunicationPlugin _crossChainCommunicationPlugin; + private readonly ICrossChainCommunicationPlugin _crossChainCommunicationPlugin; + private readonly IGrpcClientPlugin _grpcClientPlugin; - public GrpcCrossChainConnectionEventHandler(IGrpcClientPlugin grpcClientPlugin, ICrossChainCommunicationPlugin crossChainCommunicationPlugin) - { - _grpcClientPlugin = grpcClientPlugin; - _crossChainCommunicationPlugin = crossChainCommunicationPlugin; - } + public GrpcCrossChainConnectionEventHandler(IGrpcClientPlugin grpcClientPlugin, + ICrossChainCommunicationPlugin crossChainCommunicationPlugin) + { + _grpcClientPlugin = grpcClientPlugin; + _crossChainCommunicationPlugin = crossChainCommunicationPlugin; + } - public Task HandleEventAsync(NewChainConnectionEvent eventData) + public Task HandleEventAsync(NewChainConnectionEvent eventData) + { + return _grpcClientPlugin.CreateClientAsync(new GrpcCrossChainClientCreationContext { - return _grpcClientPlugin.CreateClientAsync(new GrpcCrossChainClientCreationContext - { - RemoteChainId = eventData.RemoteChainId, - RemoteServerHost = eventData.RemoteServerHost, - RemoteServerPort = eventData.RemoteServerPort, - LocalChainId = _crossChainCommunicationPlugin.ChainId - }); - } + RemoteChainId = eventData.RemoteChainId, + RemoteServerHost = eventData.RemoteServerHost, + RemoteServerPort = eventData.RemoteServerPort, + LocalChainId = _crossChainCommunicationPlugin.ChainId + }); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/GrpcCrossChainConstants.cs b/src/AElf.CrossChain.Grpc/GrpcCrossChainConstants.cs index 9b97233299..4824637e14 100644 --- a/src/AElf.CrossChain.Grpc/GrpcCrossChainConstants.cs +++ b/src/AElf.CrossChain.Grpc/GrpcCrossChainConstants.cs @@ -1,7 +1,6 @@ -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public class GrpcCrossChainConstants { - public class GrpcCrossChainConstants - { - public const int MaximalIndexingCount = 32; - } + public const int MaximalIndexingCount = 32; } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Helper/GrpcUriHelper.cs b/src/AElf.CrossChain.Grpc/Helper/GrpcUriHelper.cs index bffa5cc3f7..5a6feed538 100644 --- a/src/AElf.CrossChain.Grpc/Helper/GrpcUriHelper.cs +++ b/src/AElf.CrossChain.Grpc/Helper/GrpcUriHelper.cs @@ -1,33 +1,32 @@ using System.Net; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public static class GrpcUriHelper { - public static class GrpcUriHelper + /// + /// Tries to parse a grpc URI. format: ipv4:127.0.0.1:8000 " + /// + /// + /// + /// + public static bool TryParsePrefixedEndpoint(string url, out IPEndPoint endPoint) { - /// - /// Tries to parse a grpc URI. format: ipv4:127.0.0.1:8000 " - /// - /// - /// - /// - public static bool TryParsePrefixedEndpoint(string url, out IPEndPoint endPoint) - { - endPoint = null; - - var splitRes = url.Split(':'); - - if (splitRes.Length != 3) - return false; - - if (!IPAddress.TryParse(splitRes[1], out IPAddress parsedAddress)) - return false; - - if (!int.TryParse(splitRes[2], out int parsedPort)) - return false; - - endPoint = new IPEndPoint(parsedAddress, parsedPort); - - return true; - } + endPoint = null; + + var splitRes = url.Split(':'); + + if (splitRes.Length != 3) + return false; + + if (!IPAddress.TryParse(splitRes[1], out var parsedAddress)) + return false; + + if (!int.TryParse(splitRes[2], out var parsedPort)) + return false; + + endPoint = new IPEndPoint(parsedAddress, parsedPort); + + return true; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/NewChainConnectionEvent.cs b/src/AElf.CrossChain.Grpc/NewChainConnectionEvent.cs index 1d837afa15..3a76c49398 100644 --- a/src/AElf.CrossChain.Grpc/NewChainConnectionEvent.cs +++ b/src/AElf.CrossChain.Grpc/NewChainConnectionEvent.cs @@ -1,9 +1,8 @@ -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public sealed class NewChainConnectionEvent { - public sealed class NewChainConnectionEvent - { - public string RemoteServerHost { get; set; } - public int RemoteServerPort { get; set; } - public int RemoteChainId { get; set; } - } + public string RemoteServerHost { get; set; } + public int RemoteServerPort { get; set; } + public int RemoteChainId { get; set; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Server/GrpcBasicServerBase.cs b/src/AElf.CrossChain.Grpc/Server/GrpcBasicServerBase.cs index eec98e10b2..26216aad4c 100644 --- a/src/AElf.CrossChain.Grpc/Server/GrpcBasicServerBase.cs +++ b/src/AElf.CrossChain.Grpc/Server/GrpcBasicServerBase.cs @@ -1,38 +1,38 @@ -using System.Net; using System.Threading.Tasks; using Grpc.Core; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcBasicServerBase : BasicCrossChainRpc.BasicCrossChainRpcBase, ITransientDependency { - public class GrpcBasicServerBase : BasicCrossChainRpc.BasicCrossChainRpcBase, ITransientDependency - { - public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public override Task CrossChainHandShake(HandShake request, ServerCallContext context) - { - Logger.LogDebug($"Received shake from chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}."); + public override Task CrossChainHandShake(HandShake request, ServerCallContext context) + { + Logger.LogDebug("Received shake from chain {ChainId}", ChainHelper.ConvertChainIdToBase58(request.ChainId)); - if (!GrpcUriHelper.TryParsePrefixedEndpoint(context.Peer, out IPEndPoint peerEndpoint)) - return Task.FromResult(new HandShakeReply - {Status = HandShakeReply.Types.HandShakeStatus.InvalidHandshakeRequest}); + if (!GrpcUriHelper.TryParsePrefixedEndpoint(context.Peer, out var peerEndpoint)) + return Task.FromResult(new HandShakeReply + { + Status = HandShakeReply.Types.HandShakeStatus.InvalidHandshakeRequest + }); - _ = PublishCrossChainRequestReceivedEvent(peerEndpoint.Address.ToString(), request.ListeningPort, - request.ChainId); - return Task.FromResult(new HandShakeReply {Status = HandShakeReply.Types.HandShakeStatus.Success}); - } + _ = PublishCrossChainRequestReceivedEvent(peerEndpoint.Address.ToString(), request.ListeningPort, + request.ChainId); + return Task.FromResult(new HandShakeReply { Status = HandShakeReply.Types.HandShakeStatus.Success }); + } - private Task PublishCrossChainRequestReceivedEvent(string host, int port, int chainId) + private Task PublishCrossChainRequestReceivedEvent(string host, int port, int chainId) + { + return LocalEventBus.PublishAsync(new NewChainConnectionEvent { - return LocalEventBus.PublishAsync(new NewChainConnectionEvent - { - RemoteServerHost = host, - RemoteServerPort = port, - RemoteChainId = chainId - }); - } + RemoteServerHost = host, + RemoteServerPort = port, + RemoteChainId = chainId + }); } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServer.cs b/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServer.cs index 8eaf65aa63..d5ddf635d6 100644 --- a/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServer.cs +++ b/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServer.cs @@ -4,56 +4,55 @@ using Microsoft.Extensions.Logging; using Volo.Abp.Threading; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcCrossChainServer : IGrpcCrossChainServer { - public class GrpcCrossChainServer : IGrpcCrossChainServer - { - private global::Grpc.Core.Server _server; - private readonly GrpcParentChainServerBase _grpcParentChainServerBase; - private readonly GrpcSideChainServerBase _grpcSideChainServerBase; - private readonly GrpcBasicServerBase _grpcBasicServerBase; + private readonly GrpcBasicServerBase _grpcBasicServerBase; + private readonly GrpcParentChainServerBase _grpcParentChainServerBase; + private readonly GrpcSideChainServerBase _grpcSideChainServerBase; + private global::Grpc.Core.Server _server; - public GrpcCrossChainServer(GrpcParentChainServerBase grpcParentChainServerBase, - GrpcSideChainServerBase grpcSideChainServerBase, GrpcBasicServerBase grpcBasicServerBase) - { - _grpcParentChainServerBase = grpcParentChainServerBase; - _grpcSideChainServerBase = grpcSideChainServerBase; - _grpcBasicServerBase = grpcBasicServerBase; - } + public GrpcCrossChainServer(GrpcParentChainServerBase grpcParentChainServerBase, + GrpcSideChainServerBase grpcSideChainServerBase, GrpcBasicServerBase grpcBasicServerBase) + { + _grpcParentChainServerBase = grpcParentChainServerBase; + _grpcSideChainServerBase = grpcSideChainServerBase; + _grpcBasicServerBase = grpcBasicServerBase; + } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - public async Task StartAsync(int listeningPort) + public async Task StartAsync(int listeningPort) + { + _server = new global::Grpc.Core.Server { - _server = new global::Grpc.Core.Server + Ports = { - Ports = - { - new ServerPort(IPAddress.Any.ToString(), listeningPort, ServerCredentials.Insecure) - }, - Services = - { - ParentChainRpc.BindService(_grpcParentChainServerBase), - SideChainRpc.BindService(_grpcSideChainServerBase), - BasicCrossChainRpc.BindService(_grpcBasicServerBase) - } - }; - - await Task.Run(() => _server.Start()); - - Logger.LogInformation($"Grpc cross chain server started, listening at {listeningPort}"); - IsStarted = true; - } - - public bool IsStarted { get; private set; } - - public void Dispose() - { - if (_server == null) - return; - AsyncHelper.RunSync(() => _server.ShutdownAsync()); - _server = null; - IsStarted = false; - } + new ServerPort(IPAddress.Any.ToString(), listeningPort, ServerCredentials.Insecure) + }, + Services = + { + ParentChainRpc.BindService(_grpcParentChainServerBase), + SideChainRpc.BindService(_grpcSideChainServerBase), + BasicCrossChainRpc.BindService(_grpcBasicServerBase) + } + }; + + await Task.Run(() => _server.Start()); + + Logger.LogInformation($"Grpc cross chain server started, listening at {listeningPort}"); + IsStarted = true; + } + + public bool IsStarted { get; private set; } + + public void Dispose() + { + if (_server == null) + return; + AsyncHelper.RunSync(() => _server.ShutdownAsync()); + _server = null; + IsStarted = false; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServerNodePlugin.cs b/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServerNodePlugin.cs index 94d4d3ef01..a1c961229d 100644 --- a/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServerNodePlugin.cs +++ b/src/AElf.CrossChain.Grpc/Server/GrpcCrossChainServerNodePlugin.cs @@ -2,34 +2,34 @@ using AElf.CrossChain.Communication; using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcCrossChainServerNodePlugin : ICrossChainCommunicationPlugin { - public class GrpcCrossChainServerNodePlugin : ICrossChainCommunicationPlugin - { - private readonly GrpcCrossChainConfigOption _grpcCrossChainConfigOption; - private readonly IGrpcCrossChainServer _grpcCrossChainServer; - public int ChainId { get; private set; } + private readonly GrpcCrossChainConfigOption _grpcCrossChainConfigOption; + private readonly IGrpcCrossChainServer _grpcCrossChainServer; - public GrpcCrossChainServerNodePlugin(IOptionsSnapshot grpcCrossChainConfigOption, - IGrpcCrossChainServer grpcCrossChainServer) - { - _grpcCrossChainConfigOption = grpcCrossChainConfigOption.Value; - _grpcCrossChainServer = grpcCrossChainServer; - } + public GrpcCrossChainServerNodePlugin(IOptionsSnapshot grpcCrossChainConfigOption, + IGrpcCrossChainServer grpcCrossChainServer) + { + _grpcCrossChainConfigOption = grpcCrossChainConfigOption.Value; + _grpcCrossChainServer = grpcCrossChainServer; + } - public Task StartAsync(int chainId) - { - ChainId = chainId; + public int ChainId { get; private set; } - if (_grpcCrossChainConfigOption.ListeningPort == 0) - return Task.CompletedTask; - return _grpcCrossChainServer.StartAsync(_grpcCrossChainConfigOption.ListeningPort); - } + public Task StartAsync(int chainId) + { + ChainId = chainId; - public Task ShutdownAsync() - { - _grpcCrossChainServer.Dispose(); + if (_grpcCrossChainConfigOption.ListeningPort == 0) return Task.CompletedTask; - } + return _grpcCrossChainServer.StartAsync(_grpcCrossChainConfigOption.ListeningPort); + } + + public Task ShutdownAsync() + { + _grpcCrossChainServer.Dispose(); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Server/GrpcParentChainServerBase.cs b/src/AElf.CrossChain.Grpc/Server/GrpcParentChainServerBase.cs index 0de1d12f88..68d351c2c0 100644 --- a/src/AElf.CrossChain.Grpc/Server/GrpcParentChainServerBase.cs +++ b/src/AElf.CrossChain.Grpc/Server/GrpcParentChainServerBase.cs @@ -1,67 +1,67 @@ using System; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; +using AElf.Standards.ACS7; using Grpc.Core; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcParentChainServerBase : ParentChainRpc.ParentChainRpcBase, ITransientDependency { - public class GrpcParentChainServerBase : ParentChainRpc.ParentChainRpcBase, ITransientDependency + private readonly ICrossChainResponseService _crossChainResponseService; + + public GrpcParentChainServerBase(ICrossChainResponseService crossChainResponseService) { - public ILogger Logger { get; set; } - private readonly ICrossChainResponseService _crossChainResponseService; + _crossChainResponseService = crossChainResponseService; + } - public GrpcParentChainServerBase(ICrossChainResponseService crossChainResponseService) - { - _crossChainResponseService = crossChainResponseService; - } + public ILogger Logger { get; set; } - public override async Task RequestIndexingFromParentChain(CrossChainRequest crossChainRequest, - IServerStreamWriter responseStream, ServerCallContext context) + public override async Task RequestIndexingFromParentChain(CrossChainRequest crossChainRequest, + IServerStreamWriter responseStream, ServerCallContext context) + { + Logger.LogDebug( + $"Parent Chain Server received IndexedInfo message from chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)}."); + var requestedHeight = crossChainRequest.NextHeight; + var remoteChainId = crossChainRequest.ChainId; + while (requestedHeight - crossChainRequest.NextHeight < GrpcCrossChainConstants.MaximalIndexingCount) { - Logger.LogDebug( - $"Parent Chain Server received IndexedInfo message from chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)}."); - var requestedHeight = crossChainRequest.NextHeight; - var remoteChainId = crossChainRequest.ChainId; - while (requestedHeight - crossChainRequest.NextHeight < GrpcCrossChainConstants.MaximalIndexingCount) - { - var parentChainBlockData = - await _crossChainResponseService.ResponseParentChainBlockDataAsync(requestedHeight, remoteChainId); - if (parentChainBlockData == null) - break; + var parentChainBlockData = + await _crossChainResponseService.ResponseParentChainBlockDataAsync(requestedHeight, remoteChainId); + if (parentChainBlockData == null) + break; - if (context.Status.StatusCode != Status.DefaultSuccess.StatusCode) - { - Logger.LogTrace( - $"Disconnected with side chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)} node."); - return; - } + if (context.Status.StatusCode != Status.DefaultSuccess.StatusCode) + { + Logger.LogTrace( + $"Disconnected with side chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)} node."); + return; + } - try - { - await responseStream.WriteAsync(parentChainBlockData); - requestedHeight++; - } - catch (InvalidOperationException) - { - Logger.LogWarning("Failed to write into server side stream."); - return; - } + try + { + await responseStream.WriteAsync(parentChainBlockData); + requestedHeight++; + } + catch (InvalidOperationException) + { + Logger.LogWarning("Failed to write into server side stream."); + return; } } + } - public override async Task RequestChainInitializationDataFromParentChain( - SideChainInitializationRequest request, ServerCallContext context) - { - Logger.LogDebug( - $"Received initialization data request from chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}"); - var sideChainInitializationResponse = - await _crossChainResponseService.ResponseChainInitializationDataFromParentChainAsync(request.ChainId); - Logger.LogDebug( - $"Response initialization data for chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}"); - return sideChainInitializationResponse; - } + public override async Task RequestChainInitializationDataFromParentChain( + SideChainInitializationRequest request, ServerCallContext context) + { + Logger.LogDebug( + $"Received initialization data request from chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}"); + var sideChainInitializationResponse = + await _crossChainResponseService.ResponseChainInitializationDataFromParentChainAsync(request.ChainId); + Logger.LogDebug( + $"Response initialization data for chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}"); + return sideChainInitializationResponse; } } \ No newline at end of file diff --git a/src/AElf.CrossChain.Grpc/Server/GrpcSideChainServerBase.cs b/src/AElf.CrossChain.Grpc/Server/GrpcSideChainServerBase.cs index d5dbfe1c65..e10b4987c5 100644 --- a/src/AElf.CrossChain.Grpc/Server/GrpcSideChainServerBase.cs +++ b/src/AElf.CrossChain.Grpc/Server/GrpcSideChainServerBase.cs @@ -1,43 +1,43 @@ using System; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; +using AElf.Standards.ACS7; using Grpc.Core; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcSideChainServerBase : SideChainRpc.SideChainRpcBase, ITransientDependency { - public class GrpcSideChainServerBase : SideChainRpc.SideChainRpcBase, ITransientDependency + private readonly ICrossChainResponseService _crossChainResponseService; + + public GrpcSideChainServerBase(ICrossChainResponseService crossChainResponseService) { - public ILogger Logger { get; set; } - private readonly ICrossChainResponseService _crossChainResponseService; + _crossChainResponseService = crossChainResponseService; + } - public GrpcSideChainServerBase(ICrossChainResponseService crossChainResponseService) - { - _crossChainResponseService = crossChainResponseService; - } + public ILogger Logger { get; set; } - public override async Task RequestIndexingFromSideChain(CrossChainRequest crossChainRequest, - IServerStreamWriter responseStream, ServerCallContext context) + public override async Task RequestIndexingFromSideChain(CrossChainRequest crossChainRequest, + IServerStreamWriter responseStream, ServerCallContext context) + { + Logger.LogTrace("Side Chain Server received IndexedInfo message."); + var requestedHeight = crossChainRequest.NextHeight; + while (requestedHeight - crossChainRequest.NextHeight < GrpcCrossChainConstants.MaximalIndexingCount) { - Logger.LogTrace("Side Chain Server received IndexedInfo message."); - var requestedHeight = crossChainRequest.NextHeight; - while (requestedHeight - crossChainRequest.NextHeight < GrpcCrossChainConstants.MaximalIndexingCount) + var sideChainBlock = await _crossChainResponseService.ResponseSideChainBlockDataAsync(requestedHeight); + if (sideChainBlock == null) + break; + try + { + await responseStream.WriteAsync(sideChainBlock); + requestedHeight++; + } + catch (InvalidOperationException) { - var sideChainBlock = await _crossChainResponseService.ResponseSideChainBlockDataAsync(requestedHeight); - if (sideChainBlock == null) - break; - try - { - await responseStream.WriteAsync(sideChainBlock); - requestedHeight++; - } - catch (InvalidOperationException) - { - Logger.LogWarning("Failed to write into server side stream."); - return; - } + Logger.LogWarning("Failed to write into server side stream."); + return; } } } diff --git a/src/AElf.CrossChain.Grpc/Server/IGrpcCrossChainServer.cs b/src/AElf.CrossChain.Grpc/Server/IGrpcCrossChainServer.cs index 3db0ec06ee..ccd540331d 100644 --- a/src/AElf.CrossChain.Grpc/Server/IGrpcCrossChainServer.cs +++ b/src/AElf.CrossChain.Grpc/Server/IGrpcCrossChainServer.cs @@ -1,11 +1,10 @@ using System; using System.Threading.Tasks; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public interface IGrpcCrossChainServer : IDisposable { - public interface IGrpcCrossChainServer : IDisposable - { - Task StartAsync(int listeningPort); - bool IsStarted { get; } - } + bool IsStarted { get; } + Task StartAsync(int listeningPort); } \ No newline at end of file diff --git a/src/AElf.CrossChain/AElf.CrossChain.csproj b/src/AElf.CrossChain/AElf.CrossChain.csproj index 9e080069fa..05c4170990 100644 --- a/src/AElf.CrossChain/AElf.CrossChain.csproj +++ b/src/AElf.CrossChain/AElf.CrossChain.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/AElf.CrossChain/Application/CrossChainBlockExtraDataProvider.cs b/src/AElf.CrossChain/Application/CrossChainBlockExtraDataProvider.cs index d58e9aa2a6..ff3d5bd693 100644 --- a/src/AElf.CrossChain/Application/CrossChainBlockExtraDataProvider.cs +++ b/src/AElf.CrossChain/Application/CrossChainBlockExtraDataProvider.cs @@ -4,36 +4,35 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Txn.Application; using Google.Protobuf; -using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +internal class CrossChainBlockExtraDataProvider : IBlockExtraDataProvider { - internal class CrossChainBlockExtraDataProvider : IBlockExtraDataProvider + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + + public CrossChainBlockExtraDataProvider(ICrossChainIndexingDataService crossChainIndexingDataService, + ITransactionPackingOptionProvider transactionPackingOptionProvider) { - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - public string BlockHeaderExtraDataKey => CrossChainConstants.CrossChainExtraDataKey; - - public CrossChainBlockExtraDataProvider(ICrossChainIndexingDataService crossChainIndexingDataService, - ITransactionPackingOptionProvider transactionPackingOptionProvider) - { - _crossChainIndexingDataService = crossChainIndexingDataService; - _transactionPackingOptionProvider = transactionPackingOptionProvider; - } - - public async Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) - { - if (blockHeader.Height == AElfConstants.GenesisBlockHeight) - return ByteString.Empty; - - if (!_transactionPackingOptionProvider.IsTransactionPackable(new ChainContext - {BlockHash = blockHeader.PreviousBlockHash, BlockHeight = blockHeader.Height - 1})) - return ByteString.Empty; - - var bytes = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync( - blockHeader.PreviousBlockHash, blockHeader.Height - 1); - - return bytes; - } + _crossChainIndexingDataService = crossChainIndexingDataService; + _transactionPackingOptionProvider = transactionPackingOptionProvider; + } + + public string BlockHeaderExtraDataKey => CrossChainConstants.CrossChainExtraDataKey; + + public async Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) + { + if (blockHeader.Height == AElfConstants.GenesisBlockHeight) + return ByteString.Empty; + + if (!_transactionPackingOptionProvider.IsTransactionPackable(new ChainContext + { BlockHash = blockHeader.PreviousBlockHash, BlockHeight = blockHeader.Height - 1 })) + return ByteString.Empty; + + var bytes = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync( + blockHeader.PreviousBlockHash, blockHeader.Height - 1); + + return bytes; } } \ No newline at end of file diff --git a/src/AElf.CrossChain/Application/CrossChainService.cs b/src/AElf.CrossChain/Application/CrossChainService.cs index 67034395cc..11eea9ddd7 100644 --- a/src/AElf.CrossChain/Application/CrossChainService.cs +++ b/src/AElf.CrossChain/Application/CrossChainService.cs @@ -5,47 +5,45 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +internal class CrossChainService : ICrossChainService { - internal class CrossChainService : ICrossChainService + private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + + public CrossChainService(ICrossChainCacheEntityService crossChainCacheEntityService, + ICrossChainIndexingDataService crossChainIndexingDataService) + { + _crossChainCacheEntityService = crossChainCacheEntityService; + _crossChainIndexingDataService = crossChainIndexingDataService; + } + + public ILogger Logger { get; set; } + + public IOptions CrossChainConfigOptions { get; set; } + + public async Task FinishInitialSyncAsync() { - private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - public ILogger Logger { get; set; } - - public CrossChainService(ICrossChainCacheEntityService crossChainCacheEntityService, - ICrossChainIndexingDataService crossChainIndexingDataService) - { - _crossChainCacheEntityService = crossChainCacheEntityService; - _crossChainIndexingDataService = crossChainIndexingDataService; - } - - public IOptions CrossChainConfigOptions { get; set; } - - public async Task FinishInitialSyncAsync() - { - CrossChainConfigOptions.Value.CrossChainDataValidationIgnored = false; - var chainIdHeightPairs = - await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); - foreach (var chainIdHeight in chainIdHeightPairs.IdHeightDict) - { - // register new chain - _crossChainCacheEntityService.RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value); - } - } - - public async Task UpdateCrossChainDataWithLibAsync(Hash blockHash, long blockHeight) - { - if (CrossChainConfigOptions.Value.CrossChainDataValidationIgnored - || blockHeight <= AElfConstants.GenesisBlockHeight) - return; - - _crossChainIndexingDataService.UpdateCrossChainDataWithLib(blockHash, blockHeight); - - var chainIdHeightPairs = - await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); - - await _crossChainCacheEntityService.UpdateCrossChainCacheAsync(blockHash, blockHeight, chainIdHeightPairs); - } + CrossChainConfigOptions.Value.CrossChainDataValidationIgnored = false; + var chainIdHeightPairs = + await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); + foreach (var chainIdHeight in chainIdHeightPairs.IdHeightDict) + // register new chain + _crossChainCacheEntityService.RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value); + } + + public async Task UpdateCrossChainDataWithLibAsync(Hash blockHash, long blockHeight) + { + if (CrossChainConfigOptions.Value.CrossChainDataValidationIgnored + || blockHeight <= AElfConstants.GenesisBlockHeight) + return; + + _crossChainIndexingDataService.UpdateCrossChainDataWithLib(blockHash, blockHeight); + + var chainIdHeightPairs = + await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); + + await _crossChainCacheEntityService.UpdateCrossChainCacheAsync(blockHash, blockHeight, chainIdHeightPairs); } } \ No newline at end of file diff --git a/src/AElf.CrossChain/Application/CrossChainTransactionGenerator.cs b/src/AElf.CrossChain/Application/CrossChainTransactionGenerator.cs index 6954271825..9df748a6de 100644 --- a/src/AElf.CrossChain/Application/CrossChainTransactionGenerator.cs +++ b/src/AElf.CrossChain/Application/CrossChainTransactionGenerator.cs @@ -8,85 +8,80 @@ using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.Logging; -using Volo.Abp.Threading; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +internal class CrossChainTransactionGenerator : ISystemTransactionGenerator { - internal class CrossChainTransactionGenerator : ISystemTransactionGenerator - { - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractAddressService _smartContractAddressService; - public ILogger Logger { get; set; } + public CrossChainTransactionGenerator(ICrossChainIndexingDataService crossChainIndexingDataService, + ISmartContractAddressService smartContractAddressService) + { + _crossChainIndexingDataService = crossChainIndexingDataService; + _smartContractAddressService = smartContractAddressService; + } - public CrossChainTransactionGenerator(ICrossChainIndexingDataService crossChainIndexingDataService, - ISmartContractAddressService smartContractAddressService) - { - _crossChainIndexingDataService = crossChainIndexingDataService; - _smartContractAddressService = smartContractAddressService; - } + public ILogger Logger { get; set; } - private async Task> GenerateCrossChainIndexingTransactionAsync(Address from, - long refBlockNumber, - Hash previousBlockHash) - { - var generatedTransactions = new List(); + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + var generatedTransactions = + await GenerateCrossChainIndexingTransactionAsync(from, preBlockHeight, preBlockHash); + return generatedTransactions; + } + + private async Task> GenerateCrossChainIndexingTransactionAsync(Address from, + long refBlockNumber, + Hash previousBlockHash) + { + var generatedTransactions = new List(); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, - refBlockNumber); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, + refBlockNumber); - if (crossChainTransactionInput == null) - { - return generatedTransactions; - } + if (crossChainTransactionInput == null) return generatedTransactions; - generatedTransactions.Add(await GenerateNotSignedTransactionAsync(from, crossChainTransactionInput.MethodName, new BlockIndex + generatedTransactions.Add(await GenerateNotSignedTransactionAsync(from, crossChainTransactionInput.MethodName, + new BlockIndex { BlockHash = previousBlockHash, BlockHeight = refBlockNumber }, crossChainTransactionInput.Value)); - Logger.LogTrace($"Cross chain transaction generated."); - return generatedTransactions; - } - - public async Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, - Hash preBlockHash) - { - var generatedTransactions = - await GenerateCrossChainIndexingTransactionAsync(from, preBlockHeight, preBlockHash); - return generatedTransactions; - } + Logger.LogTrace("Cross chain transaction generated."); + return generatedTransactions; + } - /// - /// Create a txn with provided data. - /// - /// - /// - /// - /// - /// - private async Task GenerateNotSignedTransactionAsync(Address from, string methodName, IBlockIndex blockIndex, ByteString bytes) - { - var address = await _smartContractAddressService.GetAddressByContractNameAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }, CrossChainSmartContractAddressNameProvider.StringName); - return new Transaction + /// + /// Create a txn with provided data. + /// + /// + /// + /// + /// + /// + private async Task GenerateNotSignedTransactionAsync(Address from, string methodName, + IBlockIndex blockIndex, ByteString bytes) + { + var address = await _smartContractAddressService.GetAddressByContractNameAsync( + new ChainContext { - From = from, - To = address, - RefBlockNumber = blockIndex.BlockHeight, - RefBlockPrefix = ByteString.CopyFrom(blockIndex.BlockHash.Value.Take(4).ToArray()), - MethodName = methodName, - Params = bytes, - }; - } - - + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }, CrossChainSmartContractAddressNameProvider.StringName); + return new Transaction + { + From = from, + To = address, + RefBlockNumber = blockIndex.BlockHeight, + RefBlockPrefix = ByteString.CopyFrom(blockIndex.BlockHash.Value.Take(4).ToArray()), + MethodName = methodName, + Params = bytes + }; } } \ No newline at end of file diff --git a/src/AElf.CrossChain/Application/CrossChainValidationProvider.cs b/src/AElf.CrossChain/Application/CrossChainValidationProvider.cs index a731857a21..1c286447f3 100644 --- a/src/AElf.CrossChain/Application/CrossChainValidationProvider.cs +++ b/src/AElf.CrossChain/Application/CrossChainValidationProvider.cs @@ -1,112 +1,111 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Indexing.Application; +using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS7; using Google.Protobuf; using Microsoft.Extensions.Logging; using Volo.Abp.EventBus.Local; -using AElf.CSharp.Core.Extension; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public class CrossChainValidationProvider : IBlockValidationProvider { - public class CrossChainValidationProvider : IBlockValidationProvider + private readonly IBlockExtraDataService _blockExtraDataService; + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + private readonly ICrossChainRequestService _crossChainRequestService; + private readonly ISmartContractAddressService _smartContractAddressService; + + public CrossChainValidationProvider(ICrossChainIndexingDataService crossChainIndexingDataService, + IBlockExtraDataService blockExtraDataService, ISmartContractAddressService smartContractAddressService, + ICrossChainRequestService crossChainRequestService) { - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - private readonly ICrossChainRequestService _crossChainRequestService; - private readonly IBlockExtraDataService _blockExtraDataService; - private readonly ISmartContractAddressService _smartContractAddressService; + _crossChainIndexingDataService = crossChainIndexingDataService; + _blockExtraDataService = blockExtraDataService; + _smartContractAddressService = smartContractAddressService; + _crossChainRequestService = crossChainRequestService; + LocalEventBus = NullLocalEventBus.Instance; + } - public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public CrossChainValidationProvider(ICrossChainIndexingDataService crossChainIndexingDataService, - IBlockExtraDataService blockExtraDataService, ISmartContractAddressService smartContractAddressService, - ICrossChainRequestService crossChainRequestService) - { - _crossChainIndexingDataService = crossChainIndexingDataService; - _blockExtraDataService = blockExtraDataService; - _smartContractAddressService = smartContractAddressService; - _crossChainRequestService = crossChainRequestService; - LocalEventBus = NullLocalEventBus.Instance; - } + public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + var extraData = ExtractCrossChainExtraData(block.Header); + if (!extraData.IsNullOrEmpty()) + return await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(block.Header.PreviousBlockHash, + block.Header.Height - 1, block.Header.Time); + return true; + } - public async Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - var extraData = ExtractCrossChainExtraData(block.Header); - if (!extraData.IsNullOrEmpty()) - return await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(block.Header.PreviousBlockHash, - block.Header.Height - 1, block.Header.Time); - return true; - } + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(true); + } - public Task ValidateBeforeAttachAsync(IBlock block) - { - return Task.FromResult(true); - } + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) + return true; - public async Task ValidateBlockAfterExecuteAsync(IBlock block) + try { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) - return true; - - try + var isSideChainBlockDataIndexed = await TryDiscoverIndexedSideChainBlockDataAsync(block); + Logger.LogDebug($"Try discovery indexed side chain block data: {isSideChainBlockDataIndexed}"); + var extraData = ExtractCrossChainExtraData(block.Header); + var validationResult = true; + if (!isSideChainBlockDataIndexed && !extraData.IsNullOrEmpty()) { - var isSideChainBlockDataIndexed = await TryDiscoverIndexedSideChainBlockDataAsync(block); - Logger.LogDebug($"Try discovery indexed side chain block data: {isSideChainBlockDataIndexed}"); - var extraData = ExtractCrossChainExtraData(block.Header); - var validationResult = true; - if (!isSideChainBlockDataIndexed && !extraData.IsNullOrEmpty()) - { - // cross chain extra data in block header should be null if no side chain block data indexed in contract - validationResult = false; - } - else if (isSideChainBlockDataIndexed) - { - var indexedCrossChainBlockData = - await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync(block.Header.GetHash(), - block.Header.Height); - if (indexedCrossChainBlockData.IsNullOrEmpty() ^ extraData.IsNullOrEmpty()) - validationResult = false; - else if (!indexedCrossChainBlockData.IsNullOrEmpty()) - validationResult = ValidateBlockExtraDataAsync(indexedCrossChainBlockData, extraData); - } - - if (!validationResult) - Logger.LogDebug( - $"Invalid cross chain extra data, block height {block.Header.Height}, hash {block.GetHash()}."); - return validationResult; + // cross chain extra data in block header should be null if no side chain block data indexed in contract + validationResult = false; } - finally + else if (isSideChainBlockDataIndexed) { - _ = _crossChainRequestService.RequestCrossChainDataFromOtherChainsAsync(); + var indexedCrossChainBlockData = + await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync(block.Header.GetHash(), + block.Header.Height); + if (indexedCrossChainBlockData.IsNullOrEmpty() ^ extraData.IsNullOrEmpty()) + validationResult = false; + else if (!indexedCrossChainBlockData.IsNullOrEmpty()) + validationResult = ValidateBlockExtraDataAsync(indexedCrossChainBlockData, extraData); } - } - private bool ValidateBlockExtraDataAsync(IndexedSideChainBlockData indexedSideChainBlockData, ByteString extraData) - { - var expected = indexedSideChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); - return expected.Equals(extraData); + if (!validationResult) + Logger.LogDebug( + $"Invalid cross chain extra data, block height {block.Header.Height}, hash {block.GetHash()}."); + return validationResult; } - - private ByteString ExtractCrossChainExtraData(BlockHeader header) + finally { - var bytes = _blockExtraDataService.GetExtraDataFromBlockHeader( - CrossChainConstants.CrossChainExtraDataKey, header); - return bytes; + _ = _crossChainRequestService.RequestCrossChainDataFromOtherChainsAsync(); } + } - private async Task TryDiscoverIndexedSideChainBlockDataAsync(IBlock block) - { - var crossChainContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Header.Height - }, CrossChainSmartContractAddressNameProvider.StringName); - return new SideChainBlockDataIndexed().ToLogEvent(crossChainContractAddress).GetBloom() - .IsIn(new Bloom(block.Header.Bloom.ToByteArray())); - } + private bool ValidateBlockExtraDataAsync(IndexedSideChainBlockData indexedSideChainBlockData, ByteString extraData) + { + var expected = indexedSideChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData(); + return expected.Equals(extraData); + } + + private ByteString ExtractCrossChainExtraData(BlockHeader header) + { + var bytes = _blockExtraDataService.GetExtraDataFromBlockHeader( + CrossChainConstants.CrossChainExtraDataKey, header); + return bytes; + } + + private async Task TryDiscoverIndexedSideChainBlockDataAsync(IBlock block) + { + var crossChainContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Header.Height + }, CrossChainSmartContractAddressNameProvider.StringName); + return new SideChainBlockDataIndexed().ToLogEvent(crossChainContractAddress).GetBloom() + .IsIn(new Bloom(block.Header.Bloom.ToByteArray())); } } \ No newline at end of file diff --git a/src/AElf.CrossChain/Application/ICrossChainService.cs b/src/AElf.CrossChain/Application/ICrossChainService.cs index c3971d9bab..1e989286dc 100644 --- a/src/AElf.CrossChain/Application/ICrossChainService.cs +++ b/src/AElf.CrossChain/Application/ICrossChainService.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public interface ICrossChainService { - public interface ICrossChainService - { - Task FinishInitialSyncAsync(); - Task UpdateCrossChainDataWithLibAsync(Hash blockHash, long blockHeight); - } + Task FinishInitialSyncAsync(); + Task UpdateCrossChainDataWithLibAsync(Hash blockHash, long blockHeight); } \ No newline at end of file diff --git a/src/AElf.CrossChain/Application/ISideChainInitializationDataProvider.cs b/src/AElf.CrossChain/Application/ISideChainInitializationDataProvider.cs index cf28c909fd..a4a2ecdba3 100644 --- a/src/AElf.CrossChain/Application/ISideChainInitializationDataProvider.cs +++ b/src/AElf.CrossChain/Application/ISideChainInitializationDataProvider.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; using AElf.Standards.ACS7; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public interface ISideChainInitializationDataProvider { - public interface ISideChainInitializationDataProvider - { - Task GetChainInitializationDataAsync(); - int ParentChainId { get; } - } + int ParentChainId { get; } + Task GetChainInitializationDataAsync(); } \ No newline at end of file diff --git a/src/AElf.CrossChain/CrossChainAElfModule.cs b/src/AElf.CrossChain/CrossChainAElfModule.cs index 4b40d790fc..346f6856e8 100644 --- a/src/AElf.CrossChain/CrossChainAElfModule.cs +++ b/src/AElf.CrossChain/CrossChainAElfModule.cs @@ -1,27 +1,24 @@ using AElf.CrossChain.Application; -using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner.Application; using AElf.Kernel.Node; using AElf.Kernel.Node.Infrastructure; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +[DependsOn(typeof(CrossChainCoreModule))] +[DependsOn(typeof(NodeAElfModule))] +public class CrossChainAElfModule : AElfModule { - [DependsOn(typeof(CrossChainCoreModule))] - [DependsOn(typeof(NodeAElfModule))] - public class CrossChainAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.CrossChain/CrossChainModuleEventHandler.cs b/src/AElf.CrossChain/CrossChainModuleEventHandler.cs index be5bdb2825..696bad2219 100644 --- a/src/AElf.CrossChain/CrossChainModuleEventHandler.cs +++ b/src/AElf.CrossChain/CrossChainModuleEventHandler.cs @@ -5,25 +5,25 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +internal class CrossChainModuleEventHandler : ILocalEventHandler, + ILocalEventHandler, ITransientDependency { - internal class CrossChainModuleEventHandler : ILocalEventHandler, ILocalEventHandler, ITransientDependency + private readonly ICrossChainService _crossChainService; + + public CrossChainModuleEventHandler(ICrossChainService crossChainService) { - private readonly ICrossChainService _crossChainService; - - public CrossChainModuleEventHandler(ICrossChainService crossChainService) - { - _crossChainService = crossChainService; - } - - public async Task HandleEventAsync(InitialSyncFinishedEvent eventData) - { - await _crossChainService.FinishInitialSyncAsync(); - } + _crossChainService = crossChainService; + } - public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) - { - await _crossChainService.UpdateCrossChainDataWithLibAsync(eventData.BlockHash, eventData.BlockHeight); - } + public async Task HandleEventAsync(InitialSyncFinishedEvent eventData) + { + await _crossChainService.FinishInitialSyncAsync(); + } + + public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + await _crossChainService.UpdateCrossChainDataWithLibAsync(eventData.BlockHash, eventData.BlockHeight); } } \ No newline at end of file diff --git a/src/AElf.CrossChain/CrossChainPlugin.cs b/src/AElf.CrossChain/CrossChainPlugin.cs index 59984a51d4..9213bd308d 100644 --- a/src/AElf.CrossChain/CrossChainPlugin.cs +++ b/src/AElf.CrossChain/CrossChainPlugin.cs @@ -1,50 +1,44 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; using AElf.CrossChain.Communication; using AElf.Kernel.Node.Infrastructure; +using AElf.Standards.ACS7; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public interface IChainInitializationDataPlugin { - public interface IChainInitializationDataPlugin + Task GetChainInitializationDataAsync(int chainId); +} + +public class CrossChainPlugin : IChainInitializationDataPlugin, INodePlugin +{ + private readonly List _crossChainCommunicationPlugins; + private readonly ICrossChainRequestService _crossChainRequestService; + + public CrossChainPlugin(ICrossChainRequestService crossChainRequestService, + IEnumerable crossChainCommunicationPlugins) { - Task GetChainInitializationDataAsync(int chainId); + _crossChainRequestService = crossChainRequestService; + _crossChainCommunicationPlugins = crossChainCommunicationPlugins.ToList(); } - - public class CrossChainPlugin : IChainInitializationDataPlugin, INodePlugin + + public async Task GetChainInitializationDataAsync(int chainId) + { + var chainInitializationInformation = + await _crossChainRequestService.RequestChainInitializationDataAsync(chainId); + return chainInitializationInformation; + } + + public async Task StartAsync(int chainId) + { + foreach (var plugin in _crossChainCommunicationPlugins) await plugin.StartAsync(chainId); + } + + public async Task ShutdownAsync() { - private readonly ICrossChainRequestService _crossChainRequestService; - private readonly List _crossChainCommunicationPlugins; - - public CrossChainPlugin(ICrossChainRequestService crossChainRequestService, IEnumerable crossChainCommunicationPlugins) - { - _crossChainRequestService = crossChainRequestService; - _crossChainCommunicationPlugins = crossChainCommunicationPlugins.ToList(); - } - - public async Task GetChainInitializationDataAsync(int chainId) - { - var chainInitializationInformation = - await _crossChainRequestService.RequestChainInitializationDataAsync(chainId); - return chainInitializationInformation; - } - - public async Task StartAsync(int chainId) - { - foreach (var plugin in _crossChainCommunicationPlugins) - { - await plugin.StartAsync(chainId); - } - } - - public async Task ShutdownAsync() - { - foreach (var plugin in _crossChainCommunicationPlugins) - { - await plugin.ShutdownAsync(); - } - } + foreach (var plugin in _crossChainCommunicationPlugins) await plugin.ShutdownAsync(); } } \ No newline at end of file diff --git a/src/AElf.Cryptography/AElf.Cryptography.csproj b/src/AElf.Cryptography/AElf.Cryptography.csproj index f5dd72f7c1..0ac287552c 100644 --- a/src/AElf.Cryptography/AElf.Cryptography.csproj +++ b/src/AElf.Cryptography/AElf.Cryptography.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Cryptography @@ -7,12 +7,12 @@ Cryptographic primitives used in AElf. - - - - + + + + - + diff --git a/src/AElf.Cryptography/CryptoHelper.cs b/src/AElf.Cryptography/CryptoHelper.cs index 3b9bd72a8a..91abb3a64d 100644 --- a/src/AElf.Cryptography/CryptoHelper.cs +++ b/src/AElf.Cryptography/CryptoHelper.cs @@ -24,20 +24,18 @@ static CryptoHelper() public static ECKeyPair FromPrivateKey(byte[] privateKey) { if (privateKey == null || privateKey.Length != 32) - { throw new InvalidPrivateKeyException( $"Private key has to have length of 32. Current length is {privateKey?.Length}."); - } try { Lock.AcquireWriterLock(Timeout.Infinite); var secp256K1PubKey = new byte[64]; - if(!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey)) + if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey)) throw new InvalidPrivateKeyException("Create public key failed."); var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; - if(!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey)) + if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey)) throw new PublicKeyOperationException("Serialize public key failed."); return new ECKeyPair(privateKey, pubKey); } @@ -62,10 +60,10 @@ public static ECKeyPair GenerateKeyPair() rnd.GetBytes(privateKey); } while (!Secp256K1.SecretKeyVerify(privateKey)); - if(!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey)) + if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey)) throw new InvalidPrivateKeyException("Create public key failed."); var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; - if(!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey)) + if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey)) throw new PublicKeyOperationException("Serialize public key failed."); return new ECKeyPair(privateKey, pubKey); } @@ -82,11 +80,11 @@ public static byte[] SignWithPrivateKey(byte[] privateKey, byte[] hash) Lock.AcquireWriterLock(Timeout.Infinite); var recSig = new byte[65]; var compactSig = new byte[65]; - if(!Secp256K1.SignRecoverable(recSig, hash, privateKey)) + if (!Secp256K1.SignRecoverable(recSig, hash, privateKey)) throw new SignatureOperationException("Create a recoverable ECDSA signature failed."); - if(!Secp256K1.RecoverableSignatureSerializeCompact(compactSig, out var recoverId, recSig)) + if (!Secp256K1.RecoverableSignatureSerializeCompact(compactSig, out var recoverId, recSig)) throw new SignatureOperationException("Serialize an ECDSA signature failed."); - compactSig[64] = (byte) recoverId; // put recover id at the last slot + compactSig[64] = (byte)recoverId; // put recover id at the last slot return compactSig; } finally @@ -150,10 +148,10 @@ public static byte[] Ecdh(byte[] privateKey, byte[] publicKey) { Lock.AcquireWriterLock(Timeout.Infinite); var usablePublicKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; - if(!Secp256K1.PublicKeyParse(usablePublicKey, publicKey)) + if (!Secp256K1.PublicKeyParse(usablePublicKey, publicKey)) throw new PublicKeyOperationException("Parse public key failed."); var ecdhKey = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; - if(!Secp256K1.Ecdh(ecdhKey, usablePublicKey, privateKey)) + if (!Secp256K1.Ecdh(ecdhKey, usablePublicKey, privateKey)) throw new EcdhOperationException("Compute EC Diffie- secret failed."); return ecdhKey; } diff --git a/src/AElf.Cryptography/ECDSA/ECKeyPair.cs b/src/AElf.Cryptography/ECDSA/ECKeyPair.cs index 7e9a53623b..db31de6a1b 100644 --- a/src/AElf.Cryptography/ECDSA/ECKeyPair.cs +++ b/src/AElf.Cryptography/ECDSA/ECKeyPair.cs @@ -1,16 +1,15 @@ using Secp256k1Net; -namespace AElf.Cryptography.ECDSA +namespace AElf.Cryptography.ECDSA; + +public class ECKeyPair : IAElfAsymmetricCipherKeyPair { - public class ECKeyPair : IAElfAsymmetricCipherKeyPair + internal ECKeyPair(byte[] privateKey, byte[] publicKey) { - public byte[] PrivateKey { get; } - public byte[] PublicKey { get; } - - internal ECKeyPair(byte[] privateKey, byte[] publicKey) - { - PublicKey = publicKey; - PrivateKey = privateKey.LeftPad(Secp256k1.PRIVKEY_LENGTH); - } + PublicKey = publicKey; + PrivateKey = privateKey.LeftPad(Secp256k1.PRIVKEY_LENGTH); } + + public byte[] PrivateKey { get; } + public byte[] PublicKey { get; } } \ No newline at end of file diff --git a/src/AElf.Cryptography/ECDSA/ECParameters.cs b/src/AElf.Cryptography/ECDSA/ECParameters.cs index 64c96d1e80..c90af2893b 100644 --- a/src/AElf.Cryptography/ECDSA/ECParameters.cs +++ b/src/AElf.Cryptography/ECDSA/ECParameters.cs @@ -2,11 +2,10 @@ using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto.Parameters; -namespace AElf.Cryptography.ECDSA +namespace AElf.Cryptography.ECDSA; + +public static class ECParameters { - public static class ECParameters - { - public static readonly X9ECParameters Curve = SecNamedCurves.GetByName("secp256k1"); - public static readonly ECDomainParameters DomainParams = new ECDomainParameters (Curve.Curve, Curve.G, Curve.N, Curve.H); - } + public static readonly X9ECParameters Curve = SecNamedCurves.GetByName("secp256k1"); + public static readonly ECDomainParameters DomainParams = new(Curve.Curve, Curve.G, Curve.N, Curve.H); } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/EcdhOperationException.cs b/src/AElf.Cryptography/Exceptions/EcdhOperationException.cs index ed6be343f6..85cf2e1119 100644 --- a/src/AElf.Cryptography/Exceptions/EcdhOperationException.cs +++ b/src/AElf.Cryptography/Exceptions/EcdhOperationException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class EcdhOperationException : Exception { - public class EcdhOperationException : Exception + public EcdhOperationException(string message) : base(message) { - public EcdhOperationException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/InvalidKeyPairException.cs b/src/AElf.Cryptography/Exceptions/InvalidKeyPairException.cs index 2f463e12d4..0e385968c5 100644 --- a/src/AElf.Cryptography/Exceptions/InvalidKeyPairException.cs +++ b/src/AElf.Cryptography/Exceptions/InvalidKeyPairException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class InvalidKeyPairException : Exception { - public class InvalidKeyPairException : Exception + public InvalidKeyPairException(string message, Exception innerException) : base(message, innerException) { - public InvalidKeyPairException(string message, Exception innerException) : base(message, innerException) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/InvalidPasswordException.cs b/src/AElf.Cryptography/Exceptions/InvalidPasswordException.cs index b977db8885..61301850cd 100644 --- a/src/AElf.Cryptography/Exceptions/InvalidPasswordException.cs +++ b/src/AElf.Cryptography/Exceptions/InvalidPasswordException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class InvalidPasswordException : Exception { - public class InvalidPasswordException : Exception + public InvalidPasswordException(string message, Exception innerException) : base(message, innerException) { - public InvalidPasswordException(string message, Exception innerException) : base(message, innerException) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/InvalidPrivateKeyException.cs b/src/AElf.Cryptography/Exceptions/InvalidPrivateKeyException.cs index 146e1373a7..fd8743ede6 100644 --- a/src/AElf.Cryptography/Exceptions/InvalidPrivateKeyException.cs +++ b/src/AElf.Cryptography/Exceptions/InvalidPrivateKeyException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class InvalidPrivateKeyException : Exception { - public class InvalidPrivateKeyException : Exception + public InvalidPrivateKeyException(string message) : base(message) { - public InvalidPrivateKeyException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/KeyStoreNotFoundException.cs b/src/AElf.Cryptography/Exceptions/KeyStoreNotFoundException.cs index 78454228c6..74a6eb2676 100644 --- a/src/AElf.Cryptography/Exceptions/KeyStoreNotFoundException.cs +++ b/src/AElf.Cryptography/Exceptions/KeyStoreNotFoundException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class KeyStoreNotFoundException : Exception { - public class KeyStoreNotFoundException : Exception + public KeyStoreNotFoundException(string message, Exception innerException) : base(message, innerException) { - public KeyStoreNotFoundException(string message, Exception innerException) : base(message, innerException) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/PublicKeyOperationException.cs b/src/AElf.Cryptography/Exceptions/PublicKeyOperationException.cs index 34650ee05f..4e7b58fcfa 100644 --- a/src/AElf.Cryptography/Exceptions/PublicKeyOperationException.cs +++ b/src/AElf.Cryptography/Exceptions/PublicKeyOperationException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class PublicKeyOperationException : Exception { - public class PublicKeyOperationException : Exception + public PublicKeyOperationException(string message) : base(message) { - public PublicKeyOperationException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/Exceptions/SignatureOperationException.cs b/src/AElf.Cryptography/Exceptions/SignatureOperationException.cs index 537f0b49aa..2b2e309bc7 100644 --- a/src/AElf.Cryptography/Exceptions/SignatureOperationException.cs +++ b/src/AElf.Cryptography/Exceptions/SignatureOperationException.cs @@ -1,11 +1,10 @@ using System; -namespace AElf.Cryptography.Exceptions +namespace AElf.Cryptography.Exceptions; + +public class SignatureOperationException : Exception { - public class SignatureOperationException : Exception + public SignatureOperationException(string message) : base(message) { - public SignatureOperationException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/src/AElf.Cryptography/IAElfAsymmetricCipherKeyPair.cs b/src/AElf.Cryptography/IAElfAsymmetricCipherKeyPair.cs index 6e3f64265c..04f1f8f81d 100644 --- a/src/AElf.Cryptography/IAElfAsymmetricCipherKeyPair.cs +++ b/src/AElf.Cryptography/IAElfAsymmetricCipherKeyPair.cs @@ -1,8 +1,7 @@ -namespace AElf.Cryptography +namespace AElf.Cryptography; + +public interface IAElfAsymmetricCipherKeyPair { - public interface IAElfAsymmetricCipherKeyPair - { - byte[] PrivateKey { get; } - byte[] PublicKey { get; } - } + byte[] PrivateKey { get; } + byte[] PublicKey { get; } } \ No newline at end of file diff --git a/src/AElf.Cryptography/SecretSharing/SecretSharingConsts.cs b/src/AElf.Cryptography/SecretSharing/SecretSharingConsts.cs index 5daad49730..ae8f92a605 100644 --- a/src/AElf.Cryptography/SecretSharing/SecretSharingConsts.cs +++ b/src/AElf.Cryptography/SecretSharing/SecretSharingConsts.cs @@ -1,10 +1,9 @@ using System.Numerics; -namespace AElf.Cryptography.SecretSharing +namespace AElf.Cryptography.SecretSharing; + +public static class SecretSharingConsts { - public static class SecretSharingConsts - { - public static readonly uint MaxBits = 1024; - public static readonly BigInteger FieldPrime = BigInteger.Pow(new BigInteger(2), 1025) - 1; - } + public static readonly uint MaxBits = 1024; + public static readonly BigInteger FieldPrime = BigInteger.Pow(new BigInteger(2), 1025) - 1; } \ No newline at end of file diff --git a/src/AElf.Cryptography/SecretSharing/SecretSharingExtensions.cs b/src/AElf.Cryptography/SecretSharing/SecretSharingExtensions.cs index c2a3ef51b1..762bb3badb 100644 --- a/src/AElf.Cryptography/SecretSharing/SecretSharingExtensions.cs +++ b/src/AElf.Cryptography/SecretSharing/SecretSharingExtensions.cs @@ -2,49 +2,42 @@ using System.Linq; using System.Numerics; using System.Text; -using System.Threading; -namespace AElf.Cryptography.SecretSharing +namespace AElf.Cryptography.SecretSharing; + +public static class SecretSharingExtensions { - public static class SecretSharingExtensions + public static BigInteger ToBigInteger(this byte[] bytes) { + var tempBytes = new byte[bytes.Length + 1]; + Array.Copy(bytes.Reverse().ToArray(), 0, tempBytes, 1, bytes.Length); + return new BigInteger(tempBytes); + } - public static BigInteger ToBigInteger(this byte[] bytes) - { - var tempBytes = new byte[bytes.Length + 1]; - Array.Copy(bytes.Reverse().ToArray(), 0, tempBytes, 1, bytes.Length); - return new BigInteger(tempBytes); - } + public static byte[] ToBytesArray(this BigInteger integer) + { + var tempBytes = integer.ToByteArray().Reverse().ToArray(); + var result = new byte[tempBytes.Length - 1]; + Array.Copy(tempBytes, 0, result, 0, result.Length); - public static byte[] ToBytesArray(this BigInteger integer) - { - var tempBytes = integer.ToByteArray().Reverse().ToArray(); - var result = new byte[tempBytes.Length-1]; - Array.Copy(tempBytes,0,result,0,result.Length); + return result; + } - return result; - } - - public static string ConvertToString(this BigInteger integer) - { - var bytes = integer.ToByteArray(); - var chars = Encoding.UTF8.GetChars(bytes); - var size = 0; - for (; size < chars.Length; ++size) - { - if (chars[size] == '\0') - { - break; - } - } + public static string ConvertToString(this BigInteger integer) + { + var bytes = integer.ToByteArray(); + var chars = Encoding.UTF8.GetChars(bytes); + var size = 0; + for (; size < chars.Length; ++size) + if (chars[size] == '\0') + break; - return new string(chars, 0, size); - } + return new string(chars, 0, size); + } - public static BigInteger Abs(this BigInteger integer) - { - return (integer % SecretSharingConsts.FieldPrime + SecretSharingConsts.FieldPrime) % - SecretSharingConsts.FieldPrime; - } + public static BigInteger Abs(this BigInteger integer) + { + return (integer % SecretSharingConsts.FieldPrime + SecretSharingConsts.FieldPrime) % + SecretSharingConsts.FieldPrime; } } \ No newline at end of file diff --git a/src/AElf.Cryptography/SecretSharing/SecretSharingHelper.cs b/src/AElf.Cryptography/SecretSharing/SecretSharingHelper.cs index 8c06e31318..609b2432de 100644 --- a/src/AElf.Cryptography/SecretSharing/SecretSharingHelper.cs +++ b/src/AElf.Cryptography/SecretSharing/SecretSharingHelper.cs @@ -2,107 +2,105 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using AElf.Types; -namespace AElf.Cryptography.SecretSharing +namespace AElf.Cryptography.SecretSharing; + +/// +/// Implementation of Shamir's Secret Sharing: https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing +/// +public static class SecretSharingHelper { - /// - /// Implementation of Shamir's Secret Sharing: https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing - /// - public static class SecretSharingHelper + public static List EncodeSecret(byte[] secretMessage, int threshold, int totalParts) { - public static List EncodeSecret(byte[] secretMessage, int threshold, int totalParts) + // Polynomial construction. + var coefficients = new BigInteger[threshold]; + // Set p(0) = secret message. + coefficients[0] = secretMessage.ToBigInteger(); + for (var i = 1; i < threshold; i++) { - // Polynomial construction. - var coefficients = new BigInteger[threshold]; - // Set p(0) = secret message. - coefficients[0] = secretMessage.ToBigInteger(); - for (var i = 1; i < threshold; i++) - { - var foo = new byte[32]; - Array.Copy(HashHelper.ComputeFrom(Guid.NewGuid().ToByteArray()).ToArray(), foo, 32); - coefficients[i] = BigInteger.Abs(new BigInteger(foo)); - } - - var result = new List(); - for (var i = 1; i < totalParts + 1; i++) - { - var secretBigInteger = coefficients[0]; - for (var j = 1; j < threshold; j++) - { - secretBigInteger += coefficients[j] * BigInteger.Pow(new BigInteger(i), j); - secretBigInteger %= SecretSharingConsts.FieldPrime; - } - - result.Add(secretBigInteger.ToByteArray()); - } - - return result; + var foo = new byte[32]; + Array.Copy(HashHelper.ComputeFrom(Guid.NewGuid().ToByteArray()).ToArray(), foo, 32); + coefficients[i] = BigInteger.Abs(new BigInteger(foo)); } - // The shared parts must be sent in order. - public static byte[] DecodeSecret(List sharedParts, List orders, int threshold) + var result = new List(); + for (var i = 1; i < totalParts + 1; i++) { - var result = BigInteger.Zero; - - for (var i = 0; i < threshold; i++) + var secretBigInteger = coefficients[0]; + for (var j = 1; j < threshold; j++) { - var numerator = new BigInteger(sharedParts[i]); - var denominator = BigInteger.One; - for (var j = 0; j < threshold; j++) - { - if (i == j) continue; - - (numerator, denominator) = - MultiplyRational(numerator, denominator, orders[j], orders[j] - orders[i]); - } - - result += RationalToWhole(numerator, denominator); - result %= SecretSharingConsts.FieldPrime; + secretBigInteger += coefficients[j] * BigInteger.Pow(new BigInteger(i), j); + secretBigInteger %= SecretSharingConsts.FieldPrime; } - return result.ToBytesArray(); + result.Add(secretBigInteger.ToByteArray()); } - private static BigInteger RationalToWhole(BigInteger numerator, BigInteger denominator) - { - return numerator * Inverse(denominator) % SecretSharingConsts.FieldPrime; - } + return result; + } + + // The shared parts must be sent in order. + public static byte[] DecodeSecret(List sharedParts, List orders, int threshold) + { + var result = BigInteger.Zero; - private static BigInteger GetGreatestCommonDivisor(BigInteger integer1, BigInteger integer2) + for (var i = 0; i < threshold; i++) { - while (true) + var numerator = new BigInteger(sharedParts[i]); + var denominator = BigInteger.One; + for (var j = 0; j < threshold; j++) { - if (integer2 == 0) return integer1; - var integer3 = integer1; - integer1 = integer2; - integer2 = integer3 % integer2; + if (i == j) continue; + + (numerator, denominator) = + MultiplyRational(numerator, denominator, orders[j], orders[j] - orders[i]); } + + result += RationalToWhole(numerator, denominator); + result %= SecretSharingConsts.FieldPrime; } - private static (BigInteger gcd, BigInteger invA, BigInteger invB) GetGreatestCommonDivisor2(BigInteger integer1, - BigInteger integer2) - { - if (integer2 == 0) return (integer1, 1, 0); + return result.ToBytesArray(); + } - var div = BigInteger.DivRem(integer1, integer2, out var rem); - var (g, iA, iB) = GetGreatestCommonDivisor2(integer2, rem); - return (g, iB, iA - iB * div); - } + private static BigInteger RationalToWhole(BigInteger numerator, BigInteger denominator) + { + return numerator * Inverse(denominator) % SecretSharingConsts.FieldPrime; + } - private static BigInteger Inverse(BigInteger integer) + private static BigInteger GetGreatestCommonDivisor(BigInteger integer1, BigInteger integer2) + { + while (true) { - return GetGreatestCommonDivisor2(SecretSharingConsts.FieldPrime, integer).invB.Abs(); + if (integer2 == 0) return integer1; + var integer3 = integer1; + integer1 = integer2; + integer2 = integer3 % integer2; } + } - private static (BigInteger numerator, BigInteger denominator) MultiplyRational( - BigInteger numeratorLhs, BigInteger denominatorLhs, - BigInteger numeratorRhs, BigInteger denominatorRhs) - { - var numerator = numeratorLhs * numeratorRhs % SecretSharingConsts.FieldPrime; - var denominator = denominatorLhs * denominatorRhs % SecretSharingConsts.FieldPrime; - var gcd = GetGreatestCommonDivisor(numerator, denominator); - return (numerator / gcd, denominator / gcd); - } + private static (BigInteger gcd, BigInteger invA, BigInteger invB) GetGreatestCommonDivisor2(BigInteger integer1, + BigInteger integer2) + { + if (integer2 == 0) return (integer1, 1, 0); + + var div = BigInteger.DivRem(integer1, integer2, out var rem); + var (g, iA, iB) = GetGreatestCommonDivisor2(integer2, rem); + return (g, iB, iA - iB * div); + } + + private static BigInteger Inverse(BigInteger integer) + { + return GetGreatestCommonDivisor2(SecretSharingConsts.FieldPrime, integer).invB.Abs(); + } + + private static (BigInteger numerator, BigInteger denominator) MultiplyRational( + BigInteger numeratorLhs, BigInteger denominatorLhs, + BigInteger numeratorRhs, BigInteger denominatorRhs) + { + var numerator = numeratorLhs * numeratorRhs % SecretSharingConsts.FieldPrime; + var denominator = denominatorLhs * denominatorRhs % SecretSharingConsts.FieldPrime; + var gcd = GetGreatestCommonDivisor(numerator, denominator); + return (numerator / gcd, denominator / gcd); } } \ No newline at end of file diff --git a/src/AElf.Database/AElf.Database.csproj b/src/AElf.Database/AElf.Database.csproj index da4f2d9daa..bce730bb49 100644 --- a/src/AElf.Database/AElf.Database.csproj +++ b/src/AElf.Database/AElf.Database.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Database @@ -7,9 +7,9 @@ Types and definitions of the data access layer. - + - + \ No newline at end of file diff --git a/src/AElf.Database/DatabaseAElfModule.cs b/src/AElf.Database/DatabaseAElfModule.cs index 135844ba5b..430d9a5b14 100644 --- a/src/AElf.Database/DatabaseAElfModule.cs +++ b/src/AElf.Database/DatabaseAElfModule.cs @@ -1,15 +1,14 @@ -using System.Dynamic; -using AElf.Modularity; +using AElf.Modularity; +using Volo.Abp.Data; using Volo.Abp.Modularity; -namespace AElf.Database +namespace AElf.Database; + +[DependsOn(typeof(CoreAElfModule), typeof(AbpDataModule))] +public class DatabaseAElfModule : AElfModule { - [DependsOn(typeof(CoreAElfModule),typeof(Volo.Abp.Data.AbpDataModule))] - public class DatabaseAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - } + var services = context.Services; } } \ No newline at end of file diff --git a/src/AElf.Database/DatabaseServiceCollectionExtensions.cs b/src/AElf.Database/DatabaseServiceCollectionExtensions.cs index 10a16f690b..fa5219cd66 100644 --- a/src/AElf.Database/DatabaseServiceCollectionExtensions.cs +++ b/src/AElf.Database/DatabaseServiceCollectionExtensions.cs @@ -3,33 +3,32 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Data; -namespace AElf.Database +namespace AElf.Database; + +public static class DatabaseServiceCollectionExtensions { - public static class DatabaseServiceCollectionExtensions + public static IServiceCollection AddKeyValueDbContext( + this IServiceCollection serviceCollection, + Action> builder = null) + where TKeyValueDbContext : KeyValueDbContext { - public static IServiceCollection AddKeyValueDbContext( - this IServiceCollection serviceCollection, - Action> builder = null) - where TKeyValueDbContext : KeyValueDbContext - { - serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); - serviceCollection.TryAddTransient>(factory => - { - var o = new KeyValueDatabaseOptions(); - var name = ConnectionStringNameAttribute.GetConnStringName(); + serviceCollection.TryAddTransient(factory => + { + var o = new KeyValueDatabaseOptions(); + var name = ConnectionStringNameAttribute.GetConnStringName(); - o.ConnectionString = factory.GetRequiredService().Resolve(name); + o.ConnectionString = factory.GetRequiredService().Resolve(name); - return o; - }); + return o; + }); - var options = new KeyValueDbContextCreationOptions(serviceCollection); + var options = new KeyValueDbContextCreationOptions(serviceCollection); - builder?.Invoke(options); + builder?.Invoke(options); - return serviceCollection; - } + return serviceCollection; } } \ No newline at end of file diff --git a/src/AElf.Database/IKeyValueCollection.cs b/src/AElf.Database/IKeyValueCollection.cs index 53f270af6f..30e98bd2b0 100644 --- a/src/AElf.Database/IKeyValueCollection.cs +++ b/src/AElf.Database/IKeyValueCollection.cs @@ -2,72 +2,72 @@ using System.Linq; using System.Threading.Tasks; -namespace AElf.Database +namespace AElf.Database; + +public interface IKeyValueCollection { - public interface IKeyValueCollection - { - string Name { get; } - Task GetAsync(string key); - Task SetAsync(string key, byte[] value); - Task RemoveAsync(string key); - Task IsExistsAsync(string key); + string Name { get; } + Task GetAsync(string key); + Task SetAsync(string key, byte[] value); + Task RemoveAsync(string key); + Task IsExistsAsync(string key); + + Task SetAllAsync(IDictionary cache); + Task> GetAllAsync(IList keys); + Task RemoveAllAsync(IList keys); +} - Task SetAllAsync(IDictionary cache); - Task> GetAllAsync(IList keys); - Task RemoveAllAsync(IList keys); +public class KeyValueCollection : IKeyValueCollection + where TKeyValueDbContext : KeyValueDbContext +{ + private readonly IKeyValueDatabase _keyValueDatabase; + + public KeyValueCollection(string name, IKeyValueDatabase keyValueDatabase) + { + Name = name; + _keyValueDatabase = keyValueDatabase; } - public class KeyValueCollection : IKeyValueCollection - where TKeyValueDbContext: KeyValueDbContext + public string Name { get; } + + public Task GetAsync(string key) { - private IKeyValueDatabase _keyValueDatabase; - - public KeyValueCollection(string name, IKeyValueDatabase keyValueDatabase) - { - Name = name; - _keyValueDatabase = keyValueDatabase; - } + return _keyValueDatabase.GetAsync(GetKey(key)); + } - public string Name { get; } - public Task GetAsync(string key) - { - return _keyValueDatabase.GetAsync(GetKey(key)); - } + public async Task SetAsync(string key, byte[] value) + { + await _keyValueDatabase.SetAsync(GetKey(key), value); + } - public async Task SetAsync(string key, byte[] value) - { - await _keyValueDatabase.SetAsync(GetKey(key), value); - } + public async Task RemoveAsync(string key) + { + await _keyValueDatabase.RemoveAsync(GetKey(key)); + } - protected virtual string GetKey(string key) - { - return Name + key; - } - - public async Task RemoveAsync(string key) - { - await _keyValueDatabase.RemoveAsync(GetKey(key)); - } + public async Task IsExistsAsync(string key) + { + return await _keyValueDatabase.IsExistsAsync(GetKey(key)); + } - public async Task IsExistsAsync(string key) - { - return await _keyValueDatabase.IsExistsAsync(GetKey(key)); - } + public async Task SetAllAsync(IDictionary cache) + { + var dic = cache.ToDictionary(k => GetKey(k.Key), v => v.Value); + await _keyValueDatabase.SetAllAsync(dic); + } - public async Task SetAllAsync(IDictionary cache) - { - var dic = cache.ToDictionary(k=> GetKey(k.Key),v => v.Value); - await _keyValueDatabase.SetAllAsync(dic); - } + public async Task> GetAllAsync(IList keys) + { + return await _keyValueDatabase.GetAllAsync(keys.Select(GetKey).ToList()); + } - public async Task> GetAllAsync(IList keys) - { - return await _keyValueDatabase.GetAllAsync(keys.Select(GetKey).ToList()); - } + public async Task RemoveAllAsync(IList keys) + { + await _keyValueDatabase.RemoveAllAsync(keys.Select(GetKey).ToList()); + } - public async Task RemoveAllAsync(IList keys) - { - await _keyValueDatabase.RemoveAllAsync(keys.Select(GetKey).ToList()); - } + protected virtual string GetKey(string key) + { + return Name + key; } } \ No newline at end of file diff --git a/src/AElf.Database/IKeyValueDatabase.cs b/src/AElf.Database/IKeyValueDatabase.cs index 9628a2e29c..434cc22d1c 100644 --- a/src/AElf.Database/IKeyValueDatabase.cs +++ b/src/AElf.Database/IKeyValueDatabase.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace AElf.Database +namespace AElf.Database; + +public interface IKeyValueDatabase + where TKeyValueDbContext : KeyValueDbContext { - public interface IKeyValueDatabase - where TKeyValueDbContext: KeyValueDbContext - { - Task GetAsync(string key); - Task SetAsync(string key, byte[] bytes); - Task RemoveAsync(string key); - Task> GetAllAsync(IList keys); - Task SetAllAsync(IDictionary values); - Task RemoveAllAsync(IList keys); - Task IsExistsAsync(string key); - bool IsConnected(); - } + Task GetAsync(string key); + Task SetAsync(string key, byte[] bytes); + Task RemoveAsync(string key); + Task> GetAllAsync(IList keys); + Task SetAllAsync(IDictionary values); + Task RemoveAllAsync(IList keys); + Task IsExistsAsync(string key); + bool IsConnected(); } \ No newline at end of file diff --git a/src/AElf.Database/InMemoryDatabase.cs b/src/AElf.Database/InMemoryDatabase.cs index 7960e310b1..7a0bd222b9 100644 --- a/src/AElf.Database/InMemoryDatabase.cs +++ b/src/AElf.Database/InMemoryDatabase.cs @@ -1,92 +1,90 @@ -using System; -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp; -using Volo.Abp.DependencyInjection; -namespace AElf.Database +namespace AElf.Database; + +public class InMemoryDatabase : IKeyValueDatabase + where TKeyValueDbContext : KeyValueDbContext { - public class InMemoryDatabase : IKeyValueDatabase - where TKeyValueDbContext : KeyValueDbContext + private readonly ConcurrentDictionary _dictionary = new(); + + public Task GetAsync(string key) { - private readonly ConcurrentDictionary _dictionary = new ConcurrentDictionary(); + Check.NotNullOrWhiteSpace(key, nameof(key)); - public Task GetAsync(string key) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); + return _dictionary.TryGetValue(key, out var value) ? Task.FromResult(value) : Task.FromResult(null); + } - return _dictionary.TryGetValue(key, out var value) ? Task.FromResult(value) : Task.FromResult(null); - } + public Task SetAsync(string key, byte[] bytes) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); - public Task SetAsync(string key, byte[] bytes) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); + _dictionary[key] = bytes; + return Task.FromResult(true); + } - _dictionary[key] = bytes; - return Task.FromResult(true); - } + public Task RemoveAsync(string key) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); - public Task RemoveAsync(string key) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); + _dictionary.TryRemove(key, out _); + return Task.FromResult(true); + } - _dictionary.TryRemove(key, out _); - return Task.FromResult(true); - } + public Task> GetAllAsync(IList keys) + { + if (keys.Count == 0) + return null; + + var result = new List(); - public Task> GetAllAsync(IList keys) + foreach (var key in keys) { - if (keys.Count == 0) - return null; - - var result = new List(); - - foreach (var key in keys) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - _dictionary.TryGetValue(key, out var value); - result.Add(value); - } - - return result.Any() ? Task.FromResult(result) : Task.FromResult>(null); + Check.NotNullOrWhiteSpace(key, nameof(key)); + _dictionary.TryGetValue(key, out var value); + result.Add(value); } - public Task SetAllAsync(IDictionary values) + return result.Any() ? Task.FromResult(result) : Task.FromResult>(null); + } + + public Task SetAllAsync(IDictionary values) + { + foreach (var pair in values) { - foreach (var pair in values) - { - Check.NotNullOrWhiteSpace(pair.Key, nameof(pair.Key)); - _dictionary[pair.Key] = pair.Value; - } - return Task.FromResult(true); + Check.NotNullOrWhiteSpace(pair.Key, nameof(pair.Key)); + _dictionary[pair.Key] = pair.Value; } - public Task RemoveAllAsync(IList keys) - { - if (keys.Count == 0) - return Task.CompletedTask; - - foreach (var key in keys) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - _dictionary.TryRemove(key, out _); - } - + return Task.FromResult(true); + } + + public Task RemoveAllAsync(IList keys) + { + if (keys.Count == 0) return Task.CompletedTask; - } - public Task IsExistsAsync(string key) + foreach (var key in keys) { Check.NotNullOrWhiteSpace(key, nameof(key)); - - return Task.FromResult(_dictionary.ContainsKey(key)); + _dictionary.TryRemove(key, out _); } - public bool IsConnected() - { - return true; - } + return Task.CompletedTask; + } + + public Task IsExistsAsync(string key) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); + + return Task.FromResult(_dictionary.ContainsKey(key)); + } + + public bool IsConnected() + { + return true; } } \ No newline at end of file diff --git a/src/AElf.Database/KeyValueDatabaseOptions.cs b/src/AElf.Database/KeyValueDatabaseOptions.cs index 27fcb98c2b..1fcd3be11d 100644 --- a/src/AElf.Database/KeyValueDatabaseOptions.cs +++ b/src/AElf.Database/KeyValueDatabaseOptions.cs @@ -1,8 +1,7 @@ -namespace AElf.Database +namespace AElf.Database; + +public class KeyValueDatabaseOptions + where TKeyValueDbContext : KeyValueDbContext { - public class KeyValueDatabaseOptions - where TKeyValueDbContext : KeyValueDbContext - { - public string ConnectionString { get; set; } - } + public string ConnectionString { get; set; } } \ No newline at end of file diff --git a/src/AElf.Database/KeyValueDbContext.cs b/src/AElf.Database/KeyValueDbContext.cs index ee7f18dca2..22b30b731d 100644 --- a/src/AElf.Database/KeyValueDbContext.cs +++ b/src/AElf.Database/KeyValueDbContext.cs @@ -1,29 +1,24 @@ -using System; using System.Collections.Generic; -namespace AElf.Database +namespace AElf.Database; + +public abstract class KeyValueDbContext + where TKeyValueDbContext : KeyValueDbContext { - public abstract class KeyValueDbContext - where TKeyValueDbContext:KeyValueDbContext - { - protected KeyValueDbContext() - { - _keyValueCollections=new Dictionary(); - } + protected readonly Dictionary _keyValueCollections; - public IKeyValueDatabase Database { get; set; } + protected KeyValueDbContext() + { + _keyValueCollections = new Dictionary(); + } - protected readonly Dictionary _keyValueCollections; - - public IKeyValueCollection Collection(string name) - { - _keyValueCollections.TryGetValue(name, out var collection); - if (collection == null) - { - return _keyValueCollections[name] = new KeyValueCollection(name, Database); - } - return collection; - } + public IKeyValueDatabase Database { get; set; } + public IKeyValueCollection Collection(string name) + { + _keyValueCollections.TryGetValue(name, out var collection); + if (collection == null) + return _keyValueCollections[name] = new KeyValueCollection(name, Database); + return collection; } } \ No newline at end of file diff --git a/src/AElf.Database/KeyValueDbContextCreationOptions.cs b/src/AElf.Database/KeyValueDbContextCreationOptions.cs index 9262680966..4230e6617a 100644 --- a/src/AElf.Database/KeyValueDbContextCreationOptions.cs +++ b/src/AElf.Database/KeyValueDbContextCreationOptions.cs @@ -1,24 +1,23 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Database +namespace AElf.Database; + +public class KeyValueDbContextCreationOptions + where TKeyValueDbContext : KeyValueDbContext { - public class KeyValueDbContextCreationOptions - where TKeyValueDbContext : KeyValueDbContext + public KeyValueDbContextCreationOptions([NotNull] IServiceCollection services) { - public KeyValueDbContextCreationOptions([NotNull] IServiceCollection services) - { - Services = services; - } + Services = services; + } - [NotNull] public IServiceCollection Services { get; } + [NotNull] public IServiceCollection Services { get; } - public KeyValueDbContextCreationOptions UseDatabase() - where TKeyValueDatabase : class, IKeyValueDatabase - { - Services.AddSingleton, TKeyValueDatabase>(); - return this; - } + public KeyValueDbContextCreationOptions UseDatabase() + where TKeyValueDatabase : class, IKeyValueDatabase + { + Services.AddSingleton, TKeyValueDatabase>(); + return this; } } \ No newline at end of file diff --git a/src/AElf.Database/KeyValueDbContextCreationOptionsExtensions.cs b/src/AElf.Database/KeyValueDbContextCreationOptionsExtensions.cs index c8d28ee29c..0ab10234a9 100644 --- a/src/AElf.Database/KeyValueDbContextCreationOptionsExtensions.cs +++ b/src/AElf.Database/KeyValueDbContextCreationOptionsExtensions.cs @@ -1,29 +1,28 @@ -namespace AElf.Database +namespace AElf.Database; + +public static class KeyValueDbContextCreationOptionsExtensions { - public static class KeyValueDbContextCreationOptionsExtensions + public static KeyValueDbContextCreationOptions UseRedisDatabase( + this KeyValueDbContextCreationOptions creationOptions) + where TKeyValueDbContext : KeyValueDbContext { - public static KeyValueDbContextCreationOptions UseRedisDatabase( - this KeyValueDbContextCreationOptions creationOptions) - where TKeyValueDbContext : KeyValueDbContext - { - creationOptions.UseDatabase>(); - return creationOptions; - } - - public static KeyValueDbContextCreationOptions UseSsdbDatabase( - this KeyValueDbContextCreationOptions creationOptions) - where TKeyValueDbContext : KeyValueDbContext - { - creationOptions.UseDatabase>(); - return creationOptions; - } - - public static KeyValueDbContextCreationOptions UseInMemoryDatabase( - this KeyValueDbContextCreationOptions creationOptions) - where TKeyValueDbContext : KeyValueDbContext - { - creationOptions.UseDatabase>(); - return creationOptions; - } + creationOptions.UseDatabase>(); + return creationOptions; + } + + public static KeyValueDbContextCreationOptions UseSsdbDatabase( + this KeyValueDbContextCreationOptions creationOptions) + where TKeyValueDbContext : KeyValueDbContext + { + creationOptions.UseDatabase>(); + return creationOptions; + } + + public static KeyValueDbContextCreationOptions UseInMemoryDatabase( + this KeyValueDbContextCreationOptions creationOptions) + where TKeyValueDbContext : KeyValueDbContext + { + creationOptions.UseDatabase>(); + return creationOptions; } } \ No newline at end of file diff --git a/src/AElf.Database/RedisDatabase.cs b/src/AElf.Database/RedisDatabase.cs index 944e180952..16ed1b9fb4 100644 --- a/src/AElf.Database/RedisDatabase.cs +++ b/src/AElf.Database/RedisDatabase.cs @@ -6,82 +6,72 @@ #pragma warning disable 1998 -namespace AElf.Database +namespace AElf.Database; + +public class RedisDatabase : IKeyValueDatabase + where TKeyValueDbContext : KeyValueDbContext { - public class RedisDatabase : IKeyValueDatabase - where TKeyValueDbContext : KeyValueDbContext + private readonly PooledRedisLite _pooledRedisLite; + + public RedisDatabase(KeyValueDatabaseOptions options) { - private readonly PooledRedisLite _pooledRedisLite; + Check.NotNullOrWhiteSpace(options.ConnectionString, nameof(options.ConnectionString)); + var endpoint = options.ConnectionString.ToRedisEndpoint(); + _pooledRedisLite = new PooledRedisLite(endpoint.Host, endpoint.Port, db: (int)endpoint.Db); + } - public RedisDatabase(KeyValueDatabaseOptions options) - { - Check.NotNullOrWhiteSpace(options.ConnectionString, nameof(options.ConnectionString)); - var endpoint = options.ConnectionString.ToRedisEndpoint(); - _pooledRedisLite = new PooledRedisLite(endpoint.Host, endpoint.Port, db: (int) endpoint.Db); - } + public async Task IsExistsAsync(string key) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); + return _pooledRedisLite.Exists(key); + } - public async Task IsExistsAsync(string key) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - return _pooledRedisLite.Exists(key); - } + public bool IsConnected() + { + return _pooledRedisLite.Ping(); + } - public bool IsConnected() - { - return _pooledRedisLite.Ping(); - } + public async Task GetAsync(string key) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); + return _pooledRedisLite.Get(key); + } - public async Task GetAsync(string key) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - return _pooledRedisLite.Get(key); - } + public async Task SetAsync(string key, byte[] bytes) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); + _pooledRedisLite.Set(key, bytes); + } - public async Task SetAsync(string key, byte[] bytes) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - _pooledRedisLite.Set(key, bytes); - } + public async Task RemoveAsync(string key) + { + Check.NotNullOrWhiteSpace(key, nameof(key)); + _pooledRedisLite.Remove(key); + } - public async Task RemoveAsync(string key) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - _pooledRedisLite.Remove(key); - } + public async Task SetAllAsync(IDictionary values) + { + if (values.Count == 0) + return; + foreach (var key in values.Keys) Check.NotNullOrWhiteSpace(key, nameof(key)); + _pooledRedisLite.SetAll(values); + } - public async Task SetAllAsync(IDictionary values) - { - if (values.Count == 0) - return; - foreach (var key in values.Keys) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - } - _pooledRedisLite.SetAll(values); - } - - public async Task> GetAllAsync(IList keys) - { - if (keys.Count == 0) - return null; - foreach (var key in keys) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - } + public async Task> GetAllAsync(IList keys) + { + if (keys.Count == 0) + return null; + foreach (var key in keys) Check.NotNullOrWhiteSpace(key, nameof(key)); + + return _pooledRedisLite.GetAll(keys.ToArray()).ToList(); + } - return _pooledRedisLite.GetAll(keys.ToArray()).ToList(); - } - - public async Task RemoveAllAsync(IList keys) - { - if (keys.Count == 0) - return; - foreach (var key in keys) - { - Check.NotNullOrWhiteSpace(key, nameof(key)); - } + public async Task RemoveAllAsync(IList keys) + { + if (keys.Count == 0) + return; + foreach (var key in keys) Check.NotNullOrWhiteSpace(key, nameof(key)); - _pooledRedisLite.RemoveAll(keys.ToArray()); - } + _pooledRedisLite.RemoveAll(keys.ToArray()); } } \ No newline at end of file diff --git a/src/AElf.Database/RedisProtocol/PooledRedisLite.cs b/src/AElf.Database/RedisProtocol/PooledRedisLite.cs index 7107faaf9c..8306a3fe68 100644 --- a/src/AElf.Database/RedisProtocol/PooledRedisLite.cs +++ b/src/AElf.Database/RedisProtocol/PooledRedisLite.cs @@ -4,190 +4,187 @@ using System.Text; using System.Threading; -namespace AElf.Database.RedisProtocol -{ - /** +namespace AElf.Database.RedisProtocol; + +/** * Simplified NServiceKit.Redis */ - public class PooledRedisLite - { - private readonly RedisLite[] _writeClients; - private readonly RedisLite[] _readOnlyClients; - - private int PoolSize { get; } - private int Db { get; } - public string Host { get; } - public int Port { get; } - private string Password { get; } - public int? PoolTimeout { get; set; } - public int RecheckPoolAfterMs { get; } = 10; +public class PooledRedisLite +{ + private readonly RedisLite[] _readOnlyClients; + private readonly RedisLite[] _writeClients; + private int _readOnlyClientIndex; - private int _writeClientIndex = 0; - private int _readOnlyClientIndex = 0; + private int _writeClientIndex; - public PooledRedisLite(string host, int port = 6379, string password = null, int db = 0, int poolSize = 20) + public PooledRedisLite(string host, int port = 6379, string password = null, int db = 0, int poolSize = 20) + { + Host = host ?? throw new ArgumentNullException(nameof(host)); + Port = port; + PoolSize = poolSize; + Db = db; + Password = password; + + // Init clients + _writeClients = new RedisLite[PoolSize]; + _readOnlyClients = new RedisLite[PoolSize]; + for (var i = 0; i < poolSize; i++) { - Host = host ?? throw new ArgumentNullException(nameof(host)); - Port = port; - PoolSize = poolSize; - Db = db; - Password = password; - - // Init clients - _writeClients = new RedisLite[PoolSize]; - _readOnlyClients = new RedisLite[PoolSize]; - for (var i = 0; i < poolSize; i++) - { - _writeClients[i] = new RedisLite(host, port, Password, db); - _readOnlyClients[i] = new RedisLite(host, port, Password, db); - } + _writeClients[i] = new RedisLite(host, port, Password, db); + _readOnlyClients[i] = new RedisLite(host, port, Password, db); } + } - public bool Exists(string key) + private int PoolSize { get; } + private int Db { get; } + public string Host { get; } + public int Port { get; } + private string Password { get; } + public int? PoolTimeout { get; set; } + public int RecheckPoolAfterMs { get; } = 10; + + public bool Exists(string key) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - return client.Exists(key) > 0; - } + return client.Exists(key) > 0; } + } - public bool Ping() + public bool Ping() + { + using (var client = GetRedisClient(true)) { - using (var client = GetRedisClient(true)) - { - return client.Ping(); - } + return client.Ping(); } + } - public void Set(string key, string value) + public void Set(string key, string value) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - client.Set(key, Encoding.UTF8.GetBytes(value)); - } + client.Set(key, Encoding.UTF8.GetBytes(value)); } + } - public bool Set(string key, byte[] value) + public bool Set(string key, byte[] value) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - client.Set(key, value); - return true; - } + client.Set(key, value); + return true; } + } - public void SetAll(IDictionary dict) + public void SetAll(IDictionary dict) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - client.MSet(dict.Keys.ToArray().ToMultiByteArray(), dict.Values.ToArray()); - } + client.MSet(dict.Keys.ToArray().ToMultiByteArray(), dict.Values.ToArray()); } + } - public bool Remove(string key) + public bool Remove(string key) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - var success = client.Del(key); - return success == RedisLite.Success; - } + var success = client.Del(key); + return success == RedisLite.Success; } - - public bool RemoveAll(string[] key) + } + + public bool RemoveAll(string[] key) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - var success = client.Del(key); - return success == RedisLite.Success; - } + var success = client.Del(key); + return success == RedisLite.Success; } + } - public byte[] Get(string key) + public byte[] Get(string key) + { + using (var client = GetRedisClient(true)) { - using (var client = GetRedisClient(true)) - { - return client.Get(key); - } + return client.Get(key); } + } - public string GetString(string key) + public string GetString(string key) + { + using (var client = GetRedisClient(true)) { - using (var client = GetRedisClient(true)) - { - return client.Get(key).FromUtf8Bytes(); - } + return client.Get(key).FromUtf8Bytes(); } - - public byte[][] GetAll(string[] keys) + } + + public byte[][] GetAll(string[] keys) + { + using (var client = GetRedisClient()) { - using (var client = GetRedisClient()) - { - return client.MGet(keys.ToMultiByteArray()); - } + return client.MGet(keys.ToMultiByteArray()); } + } - private RedisLite GetRedisClient(bool readOnly = false) - { - var lockObject = readOnly ? _readOnlyClients : _writeClients; + private RedisLite GetRedisClient(bool readOnly = false) + { + var lockObject = readOnly ? _readOnlyClients : _writeClients; - try + try + { + lock (lockObject) { - lock (lockObject) - { - RedisLite inActiveClient; - while ((inActiveClient = GetInActiveRedisClient(readOnly)) == null) + RedisLite inActiveClient; + while ((inActiveClient = GetInActiveRedisClient(readOnly)) == null) + if (PoolTimeout.HasValue) + { + // wait for a connection, cry out if made to wait too long + if (!Monitor.Wait(lockObject, PoolTimeout.Value)) + throw new TimeoutException("Pool timeout error."); + } + else { - if (PoolTimeout.HasValue) - { - // wait for a connection, cry out if made to wait too long - if (!Monitor.Wait(lockObject, PoolTimeout.Value)) - throw new TimeoutException("Pool timeout error."); - } - else - Monitor.Wait(lockObject, RecheckPoolAfterMs); + Monitor.Wait(lockObject, RecheckPoolAfterMs); } - inActiveClient.Active = true; - return inActiveClient; - } - } - catch (Exception ex) - { - throw new RedisException("Got exception while get redis client.", ex); + inActiveClient.Active = true; + return inActiveClient; } } + catch (Exception ex) + { + throw new RedisException("Got exception while get redis client.", ex); + } + } + + private RedisLite GetInActiveRedisClient(bool readOnly = false) + { + var desiredIndex = (readOnly ? _readOnlyClientIndex : _writeClientIndex) % PoolSize; + var clients = readOnly ? _readOnlyClients : _writeClients; - private RedisLite GetInActiveRedisClient(bool readOnly = false) + for (var i = desiredIndex; i < desiredIndex + clients.Length; i++) { - var desiredIndex = (readOnly ? _readOnlyClientIndex : _writeClientIndex) % PoolSize; - var clients = readOnly ? _readOnlyClients : _writeClients; + var index = i % PoolSize; + + if (readOnly) + _readOnlyClientIndex = index + 1; + else + _writeClientIndex = index + 1; - for (var i = desiredIndex; i < desiredIndex + clients.Length; i++) + if (clients[index] != null && !clients[index].Active && !clients[index].HadExceptions) + return clients[index]; + + if (clients[index] == null || clients[index].HadExceptions) { - var index = i % PoolSize; - - if (readOnly) - _readOnlyClientIndex = index + 1; - else - _writeClientIndex = index + 1; - - if (clients[index] != null && !clients[index].Active && !clients[index].HadExceptions) - { - return clients[index]; - } - - if (clients[index] == null || clients[index].HadExceptions) - { - if (clients[index] != null) - clients[index].Dispose(); - var client = new RedisLite(Host, Port, Password, Db); - - clients[index] = client; - return client; - } - } + if (clients[index] != null) + clients[index].Dispose(); + var client = new RedisLite(Host, Port, Password, Db); - return null; + clients[index] = client; + return client; + } } + + return null; } } \ No newline at end of file diff --git a/src/AElf.Database/RedisProtocol/RedisLite.cs b/src/AElf.Database/RedisProtocol/RedisLite.cs index 9e679acda2..3a734b7c9e 100644 --- a/src/AElf.Database/RedisProtocol/RedisLite.cs +++ b/src/AElf.Database/RedisProtocol/RedisLite.cs @@ -8,1037 +8,984 @@ using System.Text; using System.Threading; -namespace AElf.Database.RedisProtocol -{ - /** +namespace AElf.Database.RedisProtocol; + +/** * Simplified NServiceKit.Redis */ - public class RedisLite: IDisposable - { - public const long DefaultDb = 0; - public const int DefaultPort = 6379; - public const string DefaultHost = "localhost"; - public const int DefaultIdleTimeOutSecs = 240; //default on redis is 300 +public class RedisLite : IDisposable +{ + public const long DefaultDb = 0; + public const int DefaultPort = 6379; + public const string DefaultHost = "localhost"; + public const int DefaultIdleTimeOutSecs = 240; //default on redis is 300 - internal const int Success = 1; - internal const int OneGb = 1073741824; - private readonly byte[] endData = new[] {(byte) '\r', (byte) '\n'}; + internal const int Success = 1; + internal const int OneGb = 1073741824; - private int clientPort; - private string lastCommand; - private SocketException lastSocketException; - public bool HadExceptions { get; protected set; } + private readonly IList> _cmdBuffer = new List>(); + private readonly byte[] endData = { (byte)'\r', (byte)'\n' }; + private byte[] _currentBuffer = BufferPool.GetBuffer(); + private int _currentBufferIndex; - protected Socket socket; - protected BufferedStream Bstream; + protected BufferedStream Bstream; - /// - /// Used to manage connection pooling - /// - internal bool Active { get; set; } + private int clientPort; + private string lastCommand; - internal long LastConnectedAtTimestamp; + internal long LastConnectedAtTimestamp; + private SocketException lastSocketException; - public long Id { get; set; } + protected Socket socket; - public string Host { get; private set; } - public int Port { get; private set; } + public RedisLite(string host, int port = 6379) : this(host, port, null) + { + } - /// - /// Gets or sets object key prefix. - /// - public string NamespacePrefix { get; set; } + public RedisLite(string host, int port, string password = null, long db = DefaultDb) + { + Host = host ?? throw new ArgumentNullException(nameof(host)); + Port = port; + SendTimeout = -1; + ReceiveTimeout = -1; + Password = password; + Db = db; + IdleTimeOutSecs = DefaultIdleTimeOutSecs; + } - public int ConnectTimeout { get; set; } - public int RetryTimeout { get; set; } - public int RetryCount { get; set; } - public int SendTimeout { get; set; } - public int ReceiveTimeout { get; set; } - public string Password { get; set; } - public int IdleTimeOutSecs { get; set; } + public bool HadExceptions { get; protected set; } - public RedisLite(string host, int port = 6379): this(host, port, null) - { - } + /// + /// Used to manage connection pooling + /// + internal bool Active { get; set; } - public RedisLite(string host, int port, string password = null, long db = DefaultDb) - { - Host = host ?? throw new ArgumentNullException(nameof(host)); - Port = port; - SendTimeout = -1; - ReceiveTimeout = -1; - Password = password; - Db = db; - IdleTimeOutSecs = DefaultIdleTimeOutSecs; - } + public long Id { get; set; } - private long _db; - public long Db - { - get => _db; - set => _db = value; - } + public string Host { get; } + public int Port { get; } - public bool Ping() - { - return SendExpectCode(Commands.Ping) == "PONG"; - } + /// + /// Gets or sets object key prefix. + /// + public string NamespacePrefix { get; set; } - public void Quit() - { - SendCommand(Commands.Quit); - } + public int ConnectTimeout { get; set; } + public int RetryTimeout { get; set; } + public int RetryCount { get; set; } + public int SendTimeout { get; set; } + public int ReceiveTimeout { get; set; } + public string Password { get; set; } + public int IdleTimeOutSecs { get; set; } - public long Exists(string key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); + public long Db { get; set; } - return SendExpectLong(Commands.Exists, key.ToUtf8Bytes()); - } + private bool IsDisposed { get; set; } - public void Set(string key, byte[] value) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); - value = value ?? new byte[0]; + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - if (value.Length > OneGb) - throw new ArgumentException("value exceeds 1G", nameof(value)); + public bool Ping() + { + return SendExpectCode(Commands.Ping) == "PONG"; + } - SendExpectSuccess(Commands.Set, key.ToUtf8Bytes(), value); - } + public void Quit() + { + SendCommand(Commands.Quit); + } - public void MSet(byte[][] keys, byte[][] values) - { - var keysAndValues = MergeCommandWithKeysAndValues(Commands.MSet, keys, values); + public long Exists(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); - SendExpectSuccess(keysAndValues); - } + return SendExpectLong(Commands.Exists, key.ToUtf8Bytes()); + } - public byte[] Get(string key) - { - return GetBytes(key); - } + public void Set(string key, byte[] value) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + value = value ?? new byte[0]; - public byte[] GetBytes(string key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); + if (value.Length > OneGb) + throw new ArgumentException("value exceeds 1G", nameof(value)); - return SendExpectData(Commands.Get, key.ToUtf8Bytes()); - } + SendExpectSuccess(Commands.Set, key.ToUtf8Bytes(), value); + } - public byte[][] MGet(params byte[][] keys) - { - if (keys == null) - throw new ArgumentNullException(nameof(keys)); - if (keys.Length == 0) - throw new ArgumentException("keys"); + public void MSet(byte[][] keys, byte[][] values) + { + var keysAndValues = MergeCommandWithKeysAndValues(Commands.MSet, keys, values); - var cmdWithArgs = MergeCommandWithArgs(Commands.MGet, keys); + SendExpectSuccess(keysAndValues); + } - return SendExpectMultiData(cmdWithArgs); - } + public byte[] Get(string key) + { + return GetBytes(key); + } - public long Del(string key) - { - if (key == null) - throw new ArgumentNullException(nameof(key)); + public byte[] GetBytes(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); - return SendExpectLong(Commands.Del, key.ToUtf8Bytes()); - } + return SendExpectData(Commands.Get, key.ToUtf8Bytes()); + } - public long Del(params string[] keys) - { - if (keys == null) - throw new ArgumentNullException(nameof(keys)); + public byte[][] MGet(params byte[][] keys) + { + if (keys == null) + throw new ArgumentNullException(nameof(keys)); + if (keys.Length == 0) + throw new ArgumentException("keys"); - var cmdWithArgs = MergeCommandWithArgs(Commands.Del, keys); - return SendExpectLong(cmdWithArgs); - } + var cmdWithArgs = MergeCommandWithArgs(Commands.MGet, keys); - private void Connect() - { - socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) - { - SendTimeout = SendTimeout, - ReceiveTimeout = ReceiveTimeout - }; - try - { - if (ConnectTimeout == 0) - { - socket.Connect(Host, Port); - } - else - { - var connectResult = socket.BeginConnect(Host, Port, null, null); - connectResult.AsyncWaitHandle.WaitOne(ConnectTimeout, true); - } + return SendExpectMultiData(cmdWithArgs); + } - if (!socket.Connected) - { - socket.Close(); - socket = null; - HadExceptions = true; - return; - } + public long Del(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); - Bstream = new BufferedStream(new NetworkStream(socket), 16 * 1024); + return SendExpectLong(Commands.Del, key.ToUtf8Bytes()); + } - if (Password != null) - SendExpectSuccess(Commands.Auth, Password.ToUtf8Bytes()); + public long Del(params string[] keys) + { + if (keys == null) + throw new ArgumentNullException(nameof(keys)); - if (_db != 0) - SendExpectSuccess(Commands.Select, _db.ToUtf8Bytes()); + var cmdWithArgs = MergeCommandWithArgs(Commands.Del, keys); + return SendExpectLong(cmdWithArgs); + } - clientPort = socket.LocalEndPoint is IPEndPoint ipEndpoint ? ipEndpoint.Port : -1; - lastCommand = null; - lastSocketException = null; - LastConnectedAtTimestamp = Stopwatch.GetTimestamp(); + private void Connect() + { + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) + { + SendTimeout = SendTimeout, + ReceiveTimeout = ReceiveTimeout + }; + try + { + if (ConnectTimeout == 0) + { + socket.Connect(Host, Port); } - catch (SocketException ex) + else { - socket?.Close(); - socket = null; + var connectResult = socket.BeginConnect(Host, Port, null, null); + connectResult.AsyncWaitHandle.WaitOne(ConnectTimeout, true); + } + if (!socket.Connected) + { + socket.Close(); + socket = null; HadExceptions = true; - var throwEx = new Exception("could not connect to redis Instance at " + Host + ":" + Port, ex); - Log(throwEx.Message, ex); - throw throwEx; + return; } - } - private bool IsDisposed { get; set; } + Bstream = new BufferedStream(new NetworkStream(socket), 16 * 1024); - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + if (Password != null) + SendExpectSuccess(Commands.Auth, Password.ToUtf8Bytes()); - ~RedisLite() - { - Dispose(false); - } + if (Db != 0) + SendExpectSuccess(Commands.Select, Db.ToUtf8Bytes()); - protected virtual void Dispose(bool disposing) + clientPort = socket.LocalEndPoint is IPEndPoint ipEndpoint ? ipEndpoint.Port : -1; + lastCommand = null; + lastSocketException = null; + LastConnectedAtTimestamp = Stopwatch.GetTimestamp(); + } + catch (SocketException ex) { - Active = false; + socket?.Close(); + socket = null; - if (disposing) - { - //dispose un managed resources - DisposeConnection(); - } + HadExceptions = true; + var throwEx = new Exception("could not connect to redis Instance at " + Host + ":" + Port, ex); + Log(throwEx.Message, ex); + throw throwEx; } + } - private void DisposeConnection() - { - if (IsDisposed) return; - IsDisposed = true; + ~RedisLite() + { + Dispose(false); + } - if (socket == null) return; + protected virtual void Dispose(bool disposing) + { + Active = false; - try - { - Quit(); - } - finally - { - SafeConnectionClose(); - } - } + if (disposing) + //dispose un managed resources + DisposeConnection(); + } - private bool Reconnect() - { - var previousDb = _db; + private void DisposeConnection() + { + if (IsDisposed) return; + IsDisposed = true; + if (socket == null) return; + + try + { + Quit(); + } + finally + { SafeConnectionClose(); - Connect(); //sets db to 0 + } + } - if (previousDb != DefaultDb) Db = previousDb; + private bool Reconnect() + { + var previousDb = Db; - return socket != null; - } + SafeConnectionClose(); + Connect(); //sets db to 0 - private void SafeConnectionClose() - { - try - { - // workaround for a .net http://support.microsoft.com/kb/821625 - Bstream?.Close(); - socket?.Close(); - } - catch - { - } + if (previousDb != DefaultDb) Db = previousDb; - Bstream = null; - socket = null; - } + return socket != null; + } - private string ReadLine() + private void SafeConnectionClose() + { + try + { + // workaround for a .net http://support.microsoft.com/kb/821625 + Bstream?.Close(); + socket?.Close(); + } + catch { - var sb = new StringBuilder(); + } - int c; - while ((c = Bstream.ReadByte()) != -1) - { - if (c == '\r') - continue; - if (c == '\n') - break; - sb.Append((char) c); - } + Bstream = null; + socket = null; + } - return sb.ToString(); - } + private string ReadLine() + { + var sb = new StringBuilder(); - private bool AssertConnectedSocket() + int c; + while ((c = Bstream.ReadByte()) != -1) { - if (LastConnectedAtTimestamp > 0) - { - var now = Stopwatch.GetTimestamp(); - var elapsedSecs = (now - LastConnectedAtTimestamp) / Stopwatch.Frequency; - - if (socket == null || elapsedSecs > IdleTimeOutSecs && !socket.IsConnected()) - { - return Reconnect(); - } + if (c == '\r') + continue; + if (c == '\n') + break; + sb.Append((char)c); + } - LastConnectedAtTimestamp = now; - } + return sb.ToString(); + } - if (socket == null) - { - Connect(); - } + private bool AssertConnectedSocket() + { + if (LastConnectedAtTimestamp > 0) + { + var now = Stopwatch.GetTimestamp(); + var elapsedSecs = (now - LastConnectedAtTimestamp) / Stopwatch.Frequency; - var isConnected = socket != null; + if (socket == null || (elapsedSecs > IdleTimeOutSecs && !socket.IsConnected())) return Reconnect(); - return isConnected; + LastConnectedAtTimestamp = now; } - private bool HandleSocketException(SocketException ex) - { - HadExceptions = true; - Console.WriteLine($"SocketException: {ex}"); + if (socket == null) Connect(); - lastSocketException = ex; + var isConnected = socket != null; - // timeout? - socket.Close(); - socket = null; - - return false; - } + return isConnected; + } - private RedisResponseException CreateResponseError(string error) - { - HadExceptions = true; - var throwEx = new RedisResponseException($"{error}, sPort: {clientPort}, LastCommand: {lastCommand}"); - Log(throwEx.Message); - throw throwEx; - } + private bool HandleSocketException(SocketException ex) + { + HadExceptions = true; + Console.WriteLine($"SocketException: {ex}"); - private RedisException CreateConnectionError() - { - HadExceptions = true; - var throwEx = new RedisException($"Unable to Connect: sPort: {clientPort}", lastSocketException); - Log(throwEx.Message); - throw throwEx; - } + lastSocketException = ex; - private static byte[] GetCmdBytes(char cmdPrefix, int noOfLines) - { - var strLines = noOfLines.ToString(); - var strLinesLength = strLines.Length; + // timeout? + socket.Close(); + socket = null; - var cmdBytes = new byte[1 + strLinesLength + 2]; - cmdBytes[0] = (byte) cmdPrefix; + return false; + } - for (var i = 0; i < strLinesLength; i++) - cmdBytes[i + 1] = (byte) strLines[i]; + private RedisResponseException CreateResponseError(string error) + { + HadExceptions = true; + var throwEx = new RedisResponseException($"{error}, sPort: {clientPort}, LastCommand: {lastCommand}"); + Log(throwEx.Message); + throw throwEx; + } - cmdBytes[1 + strLinesLength] = 0x0D; // \r - cmdBytes[2 + strLinesLength] = 0x0A; // \n + private RedisException CreateConnectionError() + { + HadExceptions = true; + var throwEx = new RedisException($"Unable to Connect: sPort: {clientPort}", lastSocketException); + Log(throwEx.Message); + throw throwEx; + } - return cmdBytes; - } + private static byte[] GetCmdBytes(char cmdPrefix, int noOfLines) + { + var strLines = noOfLines.ToString(); + var strLinesLength = strLines.Length; - /// - /// Command to set multuple binary safe arguments - /// - /// - /// - protected bool SendCommand(params byte[][] cmdWithBinaryArgs) - { - if (!AssertConnectedSocket()) return false; + var cmdBytes = new byte[1 + strLinesLength + 2]; + cmdBytes[0] = (byte)cmdPrefix; - try - { - CmdLog(cmdWithBinaryArgs); + for (var i = 0; i < strLinesLength; i++) + cmdBytes[i + 1] = (byte)strLines[i]; - //Total command lines count - WriteAllToSendBuffer(cmdWithBinaryArgs); + cmdBytes[1 + strLinesLength] = 0x0D; // \r + cmdBytes[2 + strLinesLength] = 0x0A; // \n - FlushSendBuffer(); - } - catch (SocketException ex) - { - _cmdBuffer.Clear(); - return HandleSocketException(ex); - } + return cmdBytes; + } - return true; - } + /// + /// Command to set multuple binary safe arguments + /// + /// + /// + protected bool SendCommand(params byte[][] cmdWithBinaryArgs) + { + if (!AssertConnectedSocket()) return false; - public void WriteAllToSendBuffer(params byte[][] cmdWithBinaryArgs) + try { - WriteToSendBuffer(GetCmdBytes('*', cmdWithBinaryArgs.Length)); + CmdLog(cmdWithBinaryArgs); - foreach (var safeBinaryValue in cmdWithBinaryArgs) - { - WriteToSendBuffer(GetCmdBytes('$', safeBinaryValue.Length)); - WriteToSendBuffer(safeBinaryValue); - WriteToSendBuffer(endData); - } + //Total command lines count + WriteAllToSendBuffer(cmdWithBinaryArgs); + + FlushSendBuffer(); + } + catch (SocketException ex) + { + _cmdBuffer.Clear(); + return HandleSocketException(ex); } - private readonly IList> _cmdBuffer = new List>(); - private byte[] _currentBuffer = BufferPool.GetBuffer(); - private int _currentBufferIndex; + return true; + } - private void WriteToSendBuffer(byte[] cmdBytes) + public void WriteAllToSendBuffer(params byte[][] cmdWithBinaryArgs) + { + WriteToSendBuffer(GetCmdBytes('*', cmdWithBinaryArgs.Length)); + + foreach (var safeBinaryValue in cmdWithBinaryArgs) { - if (CouldAddToCurrentBuffer(cmdBytes)) return; + WriteToSendBuffer(GetCmdBytes('$', safeBinaryValue.Length)); + WriteToSendBuffer(safeBinaryValue); + WriteToSendBuffer(endData); + } + } - PushCurrentBuffer(); + private void WriteToSendBuffer(byte[] cmdBytes) + { + if (CouldAddToCurrentBuffer(cmdBytes)) return; - if (CouldAddToCurrentBuffer(cmdBytes)) return; + PushCurrentBuffer(); - var bytesCopied = 0; - while (bytesCopied < cmdBytes.Length) - { - var copyOfBytes = BufferPool.GetBuffer(); - var bytesToCopy = Math.Min(cmdBytes.Length - bytesCopied, copyOfBytes.Length); - Buffer.BlockCopy(cmdBytes, bytesCopied, copyOfBytes, 0, bytesToCopy); - _cmdBuffer.Add(new ArraySegment(copyOfBytes, 0, bytesToCopy)); - bytesCopied += bytesToCopy; - } - } + if (CouldAddToCurrentBuffer(cmdBytes)) return; - private bool CouldAddToCurrentBuffer(byte[] cmdBytes) + var bytesCopied = 0; + while (bytesCopied < cmdBytes.Length) { - if (cmdBytes.Length + _currentBufferIndex < BufferPool.BufferLength) - { - Buffer.BlockCopy(cmdBytes, 0, _currentBuffer, _currentBufferIndex, cmdBytes.Length); - _currentBufferIndex += cmdBytes.Length; - return true; - } - - return false; + var copyOfBytes = BufferPool.GetBuffer(); + var bytesToCopy = Math.Min(cmdBytes.Length - bytesCopied, copyOfBytes.Length); + Buffer.BlockCopy(cmdBytes, bytesCopied, copyOfBytes, 0, bytesToCopy); + _cmdBuffer.Add(new ArraySegment(copyOfBytes, 0, bytesToCopy)); + bytesCopied += bytesToCopy; } + } - private void PushCurrentBuffer() + private bool CouldAddToCurrentBuffer(byte[] cmdBytes) + { + if (cmdBytes.Length + _currentBufferIndex < BufferPool.BufferLength) { - _cmdBuffer.Add(new ArraySegment(_currentBuffer, 0, _currentBufferIndex)); - _currentBuffer = BufferPool.GetBuffer(); - _currentBufferIndex = 0; + Buffer.BlockCopy(cmdBytes, 0, _currentBuffer, _currentBufferIndex, cmdBytes.Length); + _currentBufferIndex += cmdBytes.Length; + return true; } - private void FlushSendBuffer() - { - if (_currentBufferIndex > 0) - PushCurrentBuffer(); + return false; + } - // Sendling IList Throws 'Message to Large' SocketException in Mono - foreach (var segment in _cmdBuffer) - { - var buffer = segment.Array; - socket.Send(buffer, segment.Offset, segment.Count, SocketFlags.None); - } + private void PushCurrentBuffer() + { + _cmdBuffer.Add(new ArraySegment(_currentBuffer, 0, _currentBufferIndex)); + _currentBuffer = BufferPool.GetBuffer(); + _currentBufferIndex = 0; + } - ResetSendBuffer(); - } + private void FlushSendBuffer() + { + if (_currentBufferIndex > 0) + PushCurrentBuffer(); - /// - /// reset buffer index in send buffer - /// - public void ResetSendBuffer() + // Sendling IList Throws 'Message to Large' SocketException in Mono + foreach (var segment in _cmdBuffer) { - _currentBufferIndex = 0; - for (int i = _cmdBuffer.Count - 1; i >= 0; i--) - { - var buffer = _cmdBuffer[i].Array; - BufferPool.ReleaseBufferToPool(ref buffer); - _cmdBuffer.RemoveAt(i); - } + var buffer = segment.Array; + socket.Send(buffer, segment.Offset, segment.Count, SocketFlags.None); } - private int SafeReadByte() - { - return Bstream.ReadByte(); - } + ResetSendBuffer(); + } - protected void SendExpectSuccess(params byte[][] cmdWithBinaryArgs) + /// + /// reset buffer index in send buffer + /// + public void ResetSendBuffer() + { + _currentBufferIndex = 0; + for (var i = _cmdBuffer.Count - 1; i >= 0; i--) { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); - - ExpectSuccess(); + var buffer = _cmdBuffer[i].Array; + BufferPool.ReleaseBufferToPool(ref buffer); + _cmdBuffer.RemoveAt(i); } + } - protected long SendExpectLong(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + private int SafeReadByte() + { + return Bstream.ReadByte(); + } - return ReadLong(); - } + protected void SendExpectSuccess(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - protected byte[] SendExpectData(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + ExpectSuccess(); + } - return ReadData(); - } + protected long SendExpectLong(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - protected string SendExpectString(params byte[][] cmdWithBinaryArgs) - { - var bytes = SendExpectData(cmdWithBinaryArgs); - return bytes.FromUtf8Bytes(); - } + return ReadLong(); + } - protected double SendExpectDouble(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + protected byte[] SendExpectData(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - return ReadDouble(); - } + return ReadData(); + } - public double ReadDouble() - { - var bytes = ReadData(); - return (bytes == null) ? double.NaN : ParseDouble(bytes); - } + protected string SendExpectString(params byte[][] cmdWithBinaryArgs) + { + var bytes = SendExpectData(cmdWithBinaryArgs); + return bytes.FromUtf8Bytes(); + } - public static double ParseDouble(byte[] doubleBytes) - { - var doubleString = Encoding.UTF8.GetString(doubleBytes); + protected double SendExpectDouble(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - double d; - double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out d); + return ReadDouble(); + } - return d; - } + public double ReadDouble() + { + var bytes = ReadData(); + return bytes == null ? double.NaN : ParseDouble(bytes); + } - protected string SendExpectCode(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + public static double ParseDouble(byte[] doubleBytes) + { + var doubleString = Encoding.UTF8.GetString(doubleBytes); - return ExpectCode(); - } + double d; + double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out d); - protected byte[][] SendExpectMultiData(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + return d; + } - return ReadMultiData(); - } + protected string SendExpectCode(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - protected object[] SendExpectDeeplyNestedMultiData(params byte[][] cmdWithBinaryArgs) - { - if (!SendCommand(cmdWithBinaryArgs)) - throw CreateConnectionError(); + return ExpectCode(); + } - return ReadDeeplyNestedMultiData(); - } + protected byte[][] SendExpectMultiData(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - [Conditional("DEBUG_REDIS")] - protected void Log(string fmt, params object[] args) - { - Console.WriteLine("{0}", string.Format(fmt, args).Trim()); - } + return ReadMultiData(); + } - [Conditional("DEBUG_REDIS")] - protected void CmdLog(byte[][] args) - { - var sb = new StringBuilder(); - foreach (var arg in args) - { - if (sb.Length > 0) - sb.Append(" "); + protected object[] SendExpectDeeplyNestedMultiData(params byte[][] cmdWithBinaryArgs) + { + if (!SendCommand(cmdWithBinaryArgs)) + throw CreateConnectionError(); - sb.Append(arg.FromUtf8Bytes()); - } + return ReadDeeplyNestedMultiData(); + } - lastCommand = sb.ToString(); - if (lastCommand.Length > 100) - { - lastCommand = lastCommand.Substring(0, 100) + "..."; - } + [Conditional("DEBUG_REDIS")] + protected void Log(string fmt, params object[] args) + { + Console.WriteLine("{0}", string.Format(fmt, args).Trim()); + } - Console.WriteLine("S: " + lastCommand); + [Conditional("DEBUG_REDIS")] + protected void CmdLog(byte[][] args) + { + var sb = new StringBuilder(); + foreach (var arg in args) + { + if (sb.Length > 0) + sb.Append(" "); + + sb.Append(arg.FromUtf8Bytes()); } - protected void ExpectSuccess() - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + lastCommand = sb.ToString(); + if (lastCommand.Length > 100) lastCommand = lastCommand.Substring(0, 100) + "..."; - var s = ReadLine(); + Console.WriteLine("S: " + lastCommand); + } - Log((char) c + s); + protected void ExpectSuccess() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - if (c == '-') - throw CreateResponseError(s.StartsWith("ERR") && s.Length >= 4 ? s.Substring(4) : s); - } + var s = ReadLine(); - private void ExpectWord(string word) - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + Log((char)c + s); - var s = ReadLine(); + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") && s.Length >= 4 ? s.Substring(4) : s); + } - Log((char) c + s); + private void ExpectWord(string word) + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - if (c == '-') - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + var s = ReadLine(); - if (s != word) - throw CreateResponseError(string.Format("Expected '{0}' got '{1}'", word, s)); - } + Log((char)c + s); - private string ExpectCode() - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - var s = ReadLine(); + if (s != word) + throw CreateResponseError(string.Format("Expected '{0}' got '{1}'", word, s)); + } - Log((char) c + s); + private string ExpectCode() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - if (c == '-') - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + var s = ReadLine(); - return s; - } + Log((char)c + s); - internal void ExpectOk() - { - ExpectWord("OK"); - } + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - internal void ExpectQueued() - { - ExpectWord("QUEUED"); - } + return s; + } - public long ReadInt() - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + internal void ExpectOk() + { + ExpectWord("OK"); + } - var s = ReadLine(); + internal void ExpectQueued() + { + ExpectWord("QUEUED"); + } - Log("R: {0}", s); + public long ReadInt() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - if (c == '-') - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + var s = ReadLine(); - if (c == ':' || c == '$') //really strange why ZRANK needs the '$' here - { - int i; - if (int.TryParse(s, out i)) - return i; - } + Log("R: {0}", s); - throw CreateResponseError("Unknown reply on integer response: " + c + s); - } + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - public long ReadLong() + if (c == ':' || c == '$') //really strange why ZRANK needs the '$' here { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + int i; + if (int.TryParse(s, out i)) + return i; + } - var s = ReadLine(); + throw CreateResponseError("Unknown reply on integer response: " + c + s); + } - Log("R: {0}", s); + public long ReadLong() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - if (c == '-') - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + var s = ReadLine(); - if (c == ':' || c == '$') //really strange why ZRANK needs the '$' here - { - long i; - if (long.TryParse(s, out i)) - return i; - } + Log("R: {0}", s); - throw CreateResponseError("Unknown reply on integer response: " + c + s); - } + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - private byte[] ReadData() + if (c == ':' || c == '$') //really strange why ZRANK needs the '$' here { - var r = ReadLine(); - return ParseSingleLine(r); + long i; + if (long.TryParse(s, out i)) + return i; } - private byte[] ParseSingleLine(string r) - { - Log("R: {0}", r); - if (r.Length == 0) - throw CreateResponseError("Zero length respose"); + throw CreateResponseError("Unknown reply on integer response: " + c + s); + } - char c = r[0]; - if (c == '-') - throw CreateResponseError(r.StartsWith("-ERR") ? r.Substring(5) : r.Substring(1)); + private byte[] ReadData() + { + var r = ReadLine(); + return ParseSingleLine(r); + } - if (c == '$') - { - if (r == "$-1") - return null; - int count; + private byte[] ParseSingleLine(string r) + { + Log("R: {0}", r); + if (r.Length == 0) + throw CreateResponseError("Zero length respose"); - if (Int32.TryParse(r.Substring(1), out count)) - { - var retbuf = new byte[count]; + var c = r[0]; + if (c == '-') + throw CreateResponseError(r.StartsWith("-ERR") ? r.Substring(5) : r.Substring(1)); - var offset = 0; - while (count > 0) - { - var readCount = Bstream.Read(retbuf, offset, count); - if (readCount <= 0) - throw CreateResponseError("Unexpected end of Stream"); + if (c == '$') + { + if (r == "$-1") + return null; + int count; - offset += readCount; - count -= readCount; - } + if (int.TryParse(r.Substring(1), out count)) + { + var retbuf = new byte[count]; - if (Bstream.ReadByte() != '\r' || Bstream.ReadByte() != '\n') - throw CreateResponseError("Invalid termination"); + var offset = 0; + while (count > 0) + { + var readCount = Bstream.Read(retbuf, offset, count); + if (readCount <= 0) + throw CreateResponseError("Unexpected end of Stream"); - return retbuf; + offset += readCount; + count -= readCount; } - throw CreateResponseError("Invalid length"); - } + if (Bstream.ReadByte() != '\r' || Bstream.ReadByte() != '\n') + throw CreateResponseError("Invalid termination"); - if (c == ':') - { - //match the return value - return r.Substring(1).ToUtf8Bytes(); + return retbuf; } - throw CreateResponseError("Unexpected reply: " + r); + throw CreateResponseError("Invalid length"); } - private byte[][] ReadMultiData() - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + if (c == ':') + //match the return value + return r.Substring(1).ToUtf8Bytes(); - var s = ReadLine(); - Log("R: {0}", s); + throw CreateResponseError("Unexpected reply: " + r); + } - switch (c) - { - // Some commands like BRPOPLPUSH may return Bulk Reply instead of Multi-bulk - case '$': - var t = new byte[2][]; - t[1] = ParseSingleLine(string.Concat(char.ToString((char) c), s)); - return t; - - case '-': - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - - case '*': - int count; - if (int.TryParse(s, out count)) - { - if (count == -1) - { - //redis is in an invalid state - return new byte[0][]; - } - - var result = new byte[count][]; - - for (int i = 0; i < count; i++) - result[i] = ReadData(); - - return result; - } - - break; - } + private byte[][] ReadMultiData() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); - throw CreateResponseError("Unknown reply on multi-request: " + c + s); - } + var s = ReadLine(); + Log("R: {0}", s); - private object[] ReadDeeplyNestedMultiData() + switch (c) { - return (object[]) ReadDeeplyNestedMultiDataItem(); - } + // Some commands like BRPOPLPUSH may return Bulk Reply instead of Multi-bulk + case '$': + var t = new byte[2][]; + t[1] = ParseSingleLine(string.Concat(char.ToString((char)c), s)); + return t; - private object ReadDeeplyNestedMultiDataItem() - { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + case '-': + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - var s = ReadLine(); - Log("R: {0}", s); + case '*': + int count; + if (int.TryParse(s, out count)) + { + if (count == -1) + //redis is in an invalid state + return new byte[0][]; - switch (c) - { - case '$': - return ParseSingleLine(string.Concat(char.ToString((char) c), s)); + var result = new byte[count][]; - case '-': - throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + for (var i = 0; i < count; i++) + result[i] = ReadData(); - case '*': - int count; - if (int.TryParse(s, out count)) - { - var array = new object[count]; - for (int i = 0; i < count; i++) - { - array[i] = ReadDeeplyNestedMultiDataItem(); - } + return result; + } - return array; - } + break; + } - break; + throw CreateResponseError("Unknown reply on multi-request: " + c + s); + } - default: - return s; - } + private object[] ReadDeeplyNestedMultiData() + { + return (object[])ReadDeeplyNestedMultiDataItem(); + } - throw CreateResponseError("Unknown reply on multi-request: " + c + s); - } + private object ReadDeeplyNestedMultiDataItem() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); + + var s = ReadLine(); + Log("R: {0}", s); - internal int ReadMultiDataResultCount() + switch (c) { - int c = SafeReadByte(); - if (c == -1) - throw CreateResponseError("No more data"); + case '$': + return ParseSingleLine(string.Concat(char.ToString((char)c), s)); - var s = ReadLine(); - Log("R: {0}", s); - if (c == '-') + case '-': throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); - if (c == '*') - { + + case '*': int count; if (int.TryParse(s, out count)) { - return count; + var array = new object[count]; + for (var i = 0; i < count; i++) array[i] = ReadDeeplyNestedMultiDataItem(); + + return array; } - } - throw CreateResponseError("Unknown reply on multi-request: " + c + s); - } + break; - private static void AssertListIdAndValue(string listId, byte[] value) - { - if (listId == null) - throw new ArgumentNullException("listId"); - if (value == null) - throw new ArgumentNullException("value"); + default: + return s; } - private static byte[][] MergeCommandWithKeysAndValues(byte[] cmd, byte[][] keys, byte[][] values) - { - var firstParams = new[] {cmd}; - return MergeCommandWithKeysAndValues(firstParams, keys, values); - } + throw CreateResponseError("Unknown reply on multi-request: " + c + s); + } - private static byte[][] MergeCommandWithKeysAndValues(byte[] cmd, byte[] firstArg, byte[][] keys, byte[][] values) + internal int ReadMultiDataResultCount() + { + var c = SafeReadByte(); + if (c == -1) + throw CreateResponseError("No more data"); + + var s = ReadLine(); + Log("R: {0}", s); + if (c == '-') + throw CreateResponseError(s.StartsWith("ERR") ? s.Substring(4) : s); + if (c == '*') { - var firstParams = new[] {cmd, firstArg}; - return MergeCommandWithKeysAndValues(firstParams, keys, values); + int count; + if (int.TryParse(s, out count)) return count; } - private static byte[][] MergeCommandWithKeysAndValues(byte[][] firstParams, - byte[][] keys, byte[][] values) - { - if (keys == null || keys.Length == 0) - throw new ArgumentNullException(nameof(keys)); - if (values == null || values.Length == 0) - throw new ArgumentNullException(nameof(values)); - if (keys.Length != values.Length) - throw new ArgumentException("The number of values must be equal to the number of keys"); + throw CreateResponseError("Unknown reply on multi-request: " + c + s); + } - var keyValueStartIndex = firstParams?.Length ?? 0; + private static void AssertListIdAndValue(string listId, byte[] value) + { + if (listId == null) + throw new ArgumentNullException("listId"); + if (value == null) + throw new ArgumentNullException("value"); + } - var keysAndValuesLength = keys.Length * 2 + keyValueStartIndex; - var keysAndValues = new byte[keysAndValuesLength][]; + private static byte[][] MergeCommandWithKeysAndValues(byte[] cmd, byte[][] keys, byte[][] values) + { + var firstParams = new[] { cmd }; + return MergeCommandWithKeysAndValues(firstParams, keys, values); + } - for (var i = 0; i < keyValueStartIndex; i++) - { - keysAndValues[i] = firstParams[i]; - } + private static byte[][] MergeCommandWithKeysAndValues(byte[] cmd, byte[] firstArg, byte[][] keys, byte[][] values) + { + var firstParams = new[] { cmd, firstArg }; + return MergeCommandWithKeysAndValues(firstParams, keys, values); + } - var j = 0; - for (var i = keyValueStartIndex; i < keysAndValuesLength; i += 2) - { - keysAndValues[i] = keys[j]; - keysAndValues[i + 1] = values[j]; - j++; - } + private static byte[][] MergeCommandWithKeysAndValues(byte[][] firstParams, + byte[][] keys, byte[][] values) + { + if (keys == null || keys.Length == 0) + throw new ArgumentNullException(nameof(keys)); + if (values == null || values.Length == 0) + throw new ArgumentNullException(nameof(values)); + if (keys.Length != values.Length) + throw new ArgumentException("The number of values must be equal to the number of keys"); - return keysAndValues; - } + var keyValueStartIndex = firstParams?.Length ?? 0; - private static byte[][] MergeCommandWithArgs(byte[] cmd, params string[] args) - { - var byteArgs = args.ToMultiByteArray(); - return MergeCommandWithArgs(cmd, byteArgs); - } + var keysAndValuesLength = keys.Length * 2 + keyValueStartIndex; + var keysAndValues = new byte[keysAndValuesLength][]; - private static byte[][] MergeCommandWithArgs(byte[] cmd, params byte[][] args) - { - var mergedBytes = new byte[1 + args.Length][]; - mergedBytes[0] = cmd; - for (var i = 0; i < args.Length; i++) - { - mergedBytes[i + 1] = args[i]; - } + for (var i = 0; i < keyValueStartIndex; i++) keysAndValues[i] = firstParams[i]; - return mergedBytes; + var j = 0; + for (var i = keyValueStartIndex; i < keysAndValuesLength; i += 2) + { + keysAndValues[i] = keys[j]; + keysAndValues[i + 1] = values[j]; + j++; } - private static byte[][] MergeCommandWithArgs(byte[] cmd, byte[] firstArg, params byte[][] args) - { - var mergedBytes = new byte[2 + args.Length][]; - mergedBytes[0] = cmd; - mergedBytes[1] = firstArg; - for (var i = 0; i < args.Length; i++) - { - mergedBytes[i + 2] = args[i]; - } + return keysAndValues; + } - return mergedBytes; - } + private static byte[][] MergeCommandWithArgs(byte[] cmd, params string[] args) + { + var byteArgs = args.ToMultiByteArray(); + return MergeCommandWithArgs(cmd, byteArgs); + } - protected byte[][] ConvertToBytes(string[] keys) - { - var keyBytes = new byte[keys.Length][]; - for (var i = 0; i < keys.Length; i++) - { - var key = keys[i]; - keyBytes[i] = key != null ? key.ToUtf8Bytes() : new byte[0]; - } + private static byte[][] MergeCommandWithArgs(byte[] cmd, params byte[][] args) + { + var mergedBytes = new byte[1 + args.Length][]; + mergedBytes[0] = cmd; + for (var i = 0; i < args.Length; i++) mergedBytes[i + 1] = args[i]; - return keyBytes; - } + return mergedBytes; + } - protected byte[][] MergeAndConvertToBytes(string[] keys, string[] args) - { - if (keys == null) - keys = new string[0]; - if (args == null) - args = new string[0]; - - var keysLength = keys.Length; - var merged = new string[keysLength + args.Length]; - for (var i = 0; i < merged.Length; i++) - { - merged[i] = i < keysLength ? keys[i] : args[i - keysLength]; - } + private static byte[][] MergeCommandWithArgs(byte[] cmd, byte[] firstArg, params byte[][] args) + { + var mergedBytes = new byte[2 + args.Length][]; + mergedBytes[0] = cmd; + mergedBytes[1] = firstArg; + for (var i = 0; i < args.Length; i++) mergedBytes[i + 2] = args[i]; - return ConvertToBytes(merged); - } + return mergedBytes; } - internal class BufferPool + protected byte[][] ConvertToBytes(string[] keys) { - internal static void Flush() + var keyBytes = new byte[keys.Length][]; + for (var i = 0; i < keys.Length; i++) { - for (int i = 0; i < pool.Length; i++) - { - Interlocked.Exchange(ref pool[i], null); // and drop the old value on the floor - } + var key = keys[i]; + keyBytes[i] = key != null ? key.ToUtf8Bytes() : new byte[0]; } - private BufferPool() - { - } + return keyBytes; + } - const int PoolSize = 1000; //1.45MB - internal const int BufferLength = 1450; //MTU size - some headers - private static readonly object[] pool = new object[PoolSize]; + protected byte[][] MergeAndConvertToBytes(string[] keys, string[] args) + { + if (keys == null) + keys = new string[0]; + if (args == null) + args = new string[0]; - internal static byte[] GetBuffer() - { - object tmp; - for (int i = 0; i < pool.Length; i++) - { - if ((tmp = Interlocked.Exchange(ref pool[i], null)) != null) - return (byte[]) tmp; - } + var keysLength = keys.Length; + var merged = new string[keysLength + args.Length]; + for (var i = 0; i < merged.Length; i++) merged[i] = i < keysLength ? keys[i] : args[i - keysLength]; - return new byte[BufferLength]; - } + return ConvertToBytes(merged); + } +} - internal static void ResizeAndFlushLeft(ref byte[] buffer, int toFitAtLeastBytes, int copyFromIndex, int copyBytes) - { - Debug.Assert(buffer != null); - Debug.Assert(toFitAtLeastBytes > buffer.Length); - Debug.Assert(copyFromIndex >= 0); - Debug.Assert(copyBytes >= 0); +internal class BufferPool +{ + private const int PoolSize = 1000; //1.45MB + internal const int BufferLength = 1450; //MTU size - some headers + private static readonly object[] pool = new object[PoolSize]; - // try doubling, else match - int newLength = buffer.Length * 2; - if (newLength < toFitAtLeastBytes) newLength = toFitAtLeastBytes; + private BufferPool() + { + } - var newBuffer = new byte[newLength]; - if (copyBytes > 0) - { - Buffer.BlockCopy(buffer, copyFromIndex, newBuffer, 0, copyBytes); - } + internal static void Flush() + { + for (var i = 0; i < pool.Length; i++) + Interlocked.Exchange(ref pool[i], null); // and drop the old value on the floor + } - if (buffer.Length == BufferLength) - { - ReleaseBufferToPool(ref buffer); - } + internal static byte[] GetBuffer() + { + object tmp; + for (var i = 0; i < pool.Length; i++) + if ((tmp = Interlocked.Exchange(ref pool[i], null)) != null) + return (byte[])tmp; - buffer = newBuffer; - } + return new byte[BufferLength]; + } - internal static void ReleaseBufferToPool(ref byte[] buffer) - { - if (buffer == null) return; - if (buffer.Length == BufferLength) - { - for (int i = 0; i < pool.Length; i++) - { - if (Interlocked.CompareExchange(ref pool[i], buffer, null) == null) - { - break; // found a null; swapped it in - } - } - } + internal static void ResizeAndFlushLeft(ref byte[] buffer, int toFitAtLeastBytes, int copyFromIndex, int copyBytes) + { + Debug.Assert(buffer != null); + Debug.Assert(toFitAtLeastBytes > buffer.Length); + Debug.Assert(copyFromIndex >= 0); + Debug.Assert(copyBytes >= 0); - // if no space, just drop it on the floor - buffer = null; - } + // try doubling, else match + var newLength = buffer.Length * 2; + if (newLength < toFitAtLeastBytes) newLength = toFitAtLeastBytes; + + var newBuffer = new byte[newLength]; + if (copyBytes > 0) Buffer.BlockCopy(buffer, copyFromIndex, newBuffer, 0, copyBytes); + + if (buffer.Length == BufferLength) ReleaseBufferToPool(ref buffer); + + buffer = newBuffer; + } + + internal static void ReleaseBufferToPool(ref byte[] buffer) + { + if (buffer == null) return; + if (buffer.Length == BufferLength) + for (var i = 0; i < pool.Length; i++) + if (Interlocked.CompareExchange(ref pool[i], buffer, null) == null) + break; // found a null; swapped it in + + // if no space, just drop it on the floor + buffer = null; } } \ No newline at end of file diff --git a/src/AElf.Database/RedisProtocol/RedisLiteHelper.cs b/src/AElf.Database/RedisProtocol/RedisLiteHelper.cs index befaf448cf..2f8deb143e 100644 --- a/src/AElf.Database/RedisProtocol/RedisLiteHelper.cs +++ b/src/AElf.Database/RedisProtocol/RedisLiteHelper.cs @@ -6,526 +6,519 @@ using System.Net.Sockets; using System.Text; -namespace AElf.Database.RedisProtocol -{ - /** +namespace AElf.Database.RedisProtocol; + +/** * Simplified NServiceKit.Redis */ - public static class Commands - { - public static readonly byte[] Quit = "QUIT".ToUtf8Bytes(); - public static readonly byte[] Auth = "AUTH".ToUtf8Bytes(); - public static readonly byte[] Exists = "EXISTS".ToUtf8Bytes(); - public static readonly byte[] Del = "DEL".ToUtf8Bytes(); - public static readonly byte[] Select = "SELECT".ToUtf8Bytes(); - public static readonly byte[] Ping = "PING".ToUtf8Bytes(); - - public static readonly byte[] Set = "SET".ToUtf8Bytes(); - public static readonly byte[] Get = "GET".ToUtf8Bytes(); - public static readonly byte[] MGet = "MGET".ToUtf8Bytes(); - public static readonly byte[] MSet = "MSET".ToUtf8Bytes(); +public static class Commands +{ + public static readonly byte[] Quit = "QUIT".ToUtf8Bytes(); + public static readonly byte[] Auth = "AUTH".ToUtf8Bytes(); + public static readonly byte[] Exists = "EXISTS".ToUtf8Bytes(); + public static readonly byte[] Del = "DEL".ToUtf8Bytes(); + public static readonly byte[] Select = "SELECT".ToUtf8Bytes(); + public static readonly byte[] Ping = "PING".ToUtf8Bytes(); + + public static readonly byte[] Set = "SET".ToUtf8Bytes(); + public static readonly byte[] Get = "GET".ToUtf8Bytes(); + public static readonly byte[] MGet = "MGET".ToUtf8Bytes(); + public static readonly byte[] MSet = "MSET".ToUtf8Bytes(); +} + +public static class RedisExtensions +{ + public static readonly string[] EmptyStringArray = new string [0]; + + public static byte[][] ToMultiByteArray(this string[] args) + { + var byteArgs = new byte[args.Length][]; + for (var i = 0; i < args.Length; ++i) + byteArgs[i] = args[i].ToUtf8Bytes(); + return byteArgs; } - public static class RedisExtensions + public static bool IsConnected(this Socket socket) { - public static byte[][] ToMultiByteArray(this string[] args) + try { - var byteArgs = new byte[args.Length][]; - for (var i = 0; i < args.Length; ++i) - byteArgs[i] = args[i].ToUtf8Bytes(); - return byteArgs; + return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); } - - public static bool IsConnected(this Socket socket) + catch (SocketException) { - try - { - return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); - } - catch (SocketException) - { - return false; - } + return false; } + } - public static string FromUtf8Bytes(this byte[] bytes) - { - return bytes == null ? null : Encoding.UTF8.GetString(bytes, 0, bytes.Length); - } + public static string FromUtf8Bytes(this byte[] bytes) + { + return bytes == null ? null : Encoding.UTF8.GetString(bytes, 0, bytes.Length); + } - public static byte[] ToUtf8Bytes(this string value) - { - return Encoding.UTF8.GetBytes(value); - } + public static byte[] ToUtf8Bytes(this string value) + { + return Encoding.UTF8.GetBytes(value); + } - public static byte[] ToUtf8Bytes(this int intVal) - { - return FastToUtf8Bytes(intVal.ToString()); - } + public static byte[] ToUtf8Bytes(this int intVal) + { + return FastToUtf8Bytes(intVal.ToString()); + } - public static byte[] ToUtf8Bytes(this long longVal) - { - return FastToUtf8Bytes(longVal.ToString()); - } + public static byte[] ToUtf8Bytes(this long longVal) + { + return FastToUtf8Bytes(longVal.ToString()); + } - public static byte[] ToUtf8Bytes(this ulong ulongVal) - { - return FastToUtf8Bytes(ulongVal.ToString()); - } + public static byte[] ToUtf8Bytes(this ulong ulongVal) + { + return FastToUtf8Bytes(ulongVal.ToString()); + } - /// - /// Skip the encoding process for 'safe strings' - /// - /// - /// - private static byte[] FastToUtf8Bytes(string strVal) - { - var bytes = new byte[strVal.Length]; - for (var i = 0; i < strVal.Length; i++) - bytes[i] = (byte) strVal[i]; + /// + /// Skip the encoding process for 'safe strings' + /// + /// + /// + private static byte[] FastToUtf8Bytes(string strVal) + { + var bytes = new byte[strVal.Length]; + for (var i = 0; i < strVal.Length; i++) + bytes[i] = (byte)strVal[i]; - return bytes; - } - - public static List ToRedisEndPoints(this IEnumerable hosts) - { - return hosts == null - ? new List() - : hosts.Select(x => ToRedisEndpoint(x)).ToList(); - } + return bytes; + } - - public static string [] SplitOnFirst (this string strVal, char needle) - { - if (strVal == null) return EmptyStringArray; - var pos = strVal.IndexOf (needle); - return pos == -1 - ? new [] { strVal } - : new [] { strVal.Substring (0, pos), strVal.Substring (pos + 1) }; - } + public static List ToRedisEndPoints(this IEnumerable hosts) + { + return hosts == null + ? new List() + : hosts.Select(x => ToRedisEndpoint(x)).ToList(); + } - public static string [] SplitOnFirst (this string strVal, string needle) - { - if (strVal == null) return EmptyStringArray; - var pos = strVal.IndexOf (needle, StringComparison.OrdinalIgnoreCase); - return pos == -1 - ? new [] { strVal } - : new [] { strVal.Substring (0, pos), strVal.Substring (pos + needle.Length) }; - } - public static string [] SplitOnLast (this string strVal, char needle) - { - if (strVal == null) return EmptyStringArray; - var pos = strVal.LastIndexOf (needle); - return pos == -1 - ? new [] { strVal } - : new [] { strVal.Substring (0, pos), strVal.Substring (pos + 1) }; - } + public static string[] SplitOnFirst(this string strVal, char needle) + { + if (strVal == null) return EmptyStringArray; + var pos = strVal.IndexOf(needle); + return pos == -1 + ? new[] { strVal } + : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) }; + } - public static readonly string [] EmptyStringArray = new string [0]; - public static string [] SplitOnLast (this string strVal, string needle) + public static string[] SplitOnFirst(this string strVal, string needle) + { + if (strVal == null) return EmptyStringArray; + var pos = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase); + return pos == -1 + ? new[] { strVal } + : new[] { strVal.Substring(0, pos), strVal.Substring(pos + needle.Length) }; + } + + public static string[] SplitOnLast(this string strVal, char needle) + { + if (strVal == null) return EmptyStringArray; + var pos = strVal.LastIndexOf(needle); + return pos == -1 + ? new[] { strVal } + : new[] { strVal.Substring(0, pos), strVal.Substring(pos + 1) }; + } + + public static string[] SplitOnLast(this string strVal, string needle) + { + if (strVal == null) return EmptyStringArray; + var pos = strVal.LastIndexOf(needle, StringComparison.OrdinalIgnoreCase); + return pos == -1 + ? new[] { strVal } + : new[] { strVal.Substring(0, pos), strVal.Substring(pos + needle.Length) }; + } + + public static RedisEndpoint ToRedisEndpoint(this string connectionString, int? defaultPort = null) + { + if (connectionString == null) + throw new ArgumentNullException("connectionString"); + if (connectionString.StartsWith("redis://")) + connectionString = connectionString.Substring("redis://".Length); + + var domainParts = connectionString.SplitOnLast('@'); + var qsParts = domainParts.Last().SplitOnFirst('?'); + var hostParts = qsParts[0].SplitOnLast(':'); + var useDefaultPort = true; + var port = defaultPort.GetValueOrDefault(RedisConfig.DefaultPort); + if (hostParts.Length > 1) { - if (strVal == null) return EmptyStringArray; - var pos = strVal.LastIndexOf (needle, StringComparison.OrdinalIgnoreCase); - return pos == -1 - ? new [] { strVal } - : new [] { strVal.Substring (0, pos), strVal.Substring (pos + needle.Length) }; + port = int.Parse(hostParts[1]); + useDefaultPort = false; } - - public static RedisEndpoint ToRedisEndpoint(this string connectionString, int? defaultPort = null) + + var endpoint = new RedisEndpoint(hostParts[0], port); + if (domainParts.Length > 1) { - if (connectionString == null) - throw new ArgumentNullException("connectionString"); - if (connectionString.StartsWith("redis://")) - connectionString = connectionString.Substring("redis://".Length); - - var domainParts = connectionString.SplitOnLast('@'); - var qsParts = domainParts.Last().SplitOnFirst('?'); - var hostParts = qsParts[0].SplitOnLast(':'); - var useDefaultPort = true; - var port = defaultPort.GetValueOrDefault(RedisConfig.DefaultPort); - if (hostParts.Length > 1) - { - port = int.Parse(hostParts[1]); - useDefaultPort = false; - } + var authParts = domainParts[0].SplitOnFirst(':'); + if (authParts.Length > 1) + endpoint.Client = authParts[0]; - var endpoint = new RedisEndpoint(hostParts[0], port); - if (domainParts.Length > 1) + endpoint.Password = authParts.Last(); + } + + if (qsParts.Length > 1) + { + var qsParams = qsParts[1].Split('&'); + foreach (var param in qsParams) { - var authParts = domainParts[0].SplitOnFirst(':'); - if (authParts.Length > 1) - endpoint.Client = authParts[0]; + var entry = param.Split('='); + var value = entry.Length > 1 ? WebUtility.UrlDecode(entry[1]) : null; + if (value == null) continue; - endpoint.Password = authParts.Last(); + var name = entry[0].ToLower(); + HandleEndpointByName(endpoint, useDefaultPort, name, value); } + } - if (qsParts.Length > 1) - { - var qsParams = qsParts[1].Split('&'); - foreach (var param in qsParams) - { - var entry = param.Split('='); - var value = entry.Length > 1 ? WebUtility.UrlDecode( entry[1] ) : null; - if (value == null) continue; - - var name = entry[0].ToLower(); - HandleEndpointByName(endpoint, useDefaultPort, name, value); - } - } + return endpoint; + } - return endpoint; - } - - private static void HandleEndpointByName(RedisEndpoint endpoint, bool useDefaultPort, string name, string value) - { - switch (name) - { - case "db": - endpoint.Db = int.Parse(value); - break; - case "ssl": - endpoint.Ssl = bool.Parse(value); - if (useDefaultPort) - endpoint.Port = RedisConfig.DefaultPortSsl; - break; - case "client": - endpoint.Client = value; - break; - case "password": - endpoint.Password = value; - break; - case "namespaceprefix": - endpoint.NamespacePrefix = value; - break; - case "connecttimeout": - endpoint.ConnectTimeout = int.Parse(value); - break; - case "sendtimeout": - endpoint.SendTimeout = int.Parse(value); - break; - case "receivetimeout": - endpoint.ReceiveTimeout = int.Parse(value); - break; - case "retrytimeout": - endpoint.RetryTimeout = int.Parse(value); - break; - case "idletimeout": - case "idletimeoutsecs": - endpoint.IdleTimeOutSecs = int.Parse(value); - break; - } + private static void HandleEndpointByName(RedisEndpoint endpoint, bool useDefaultPort, string name, string value) + { + switch (name) + { + case "db": + endpoint.Db = int.Parse(value); + break; + case "ssl": + endpoint.Ssl = bool.Parse(value); + if (useDefaultPort) + endpoint.Port = RedisConfig.DefaultPortSsl; + break; + case "client": + endpoint.Client = value; + break; + case "password": + endpoint.Password = value; + break; + case "namespaceprefix": + endpoint.NamespacePrefix = value; + break; + case "connecttimeout": + endpoint.ConnectTimeout = int.Parse(value); + break; + case "sendtimeout": + endpoint.SendTimeout = int.Parse(value); + break; + case "receivetimeout": + endpoint.ReceiveTimeout = int.Parse(value); + break; + case "retrytimeout": + endpoint.RetryTimeout = int.Parse(value); + break; + case "idletimeout": + case "idletimeoutsecs": + endpoint.IdleTimeOutSecs = int.Parse(value); + break; } } +} - internal static class RedisExtensionsInternal +internal static class RedisExtensionsInternal +{ + private static readonly NumberFormatInfo DoubleFormatProvider = new() { - public static List ToStringList(this byte[][] multiDataList) - { - if (multiDataList == null) - return new List(); + PositiveInfinitySymbol = "+inf", + NegativeInfinitySymbol = "-inf" + }; - var results = new List(); - foreach (var multiData in multiDataList) - { - results.Add(multiData.FromUtf8Bytes()); - } + public static List ToStringList(this byte[][] multiDataList) + { + if (multiDataList == null) + return new List(); - return results; - } + var results = new List(); + foreach (var multiData in multiDataList) results.Add(multiData.FromUtf8Bytes()); - private static readonly NumberFormatInfo DoubleFormatProvider = new NumberFormatInfo - { - PositiveInfinitySymbol = "+inf", - NegativeInfinitySymbol = "-inf" - }; + return results; + } - public static byte[] ToFastUtf8Bytes(this double value) - { - return FastToUtf8Bytes(value.ToString("R", DoubleFormatProvider)); - } + public static byte[] ToFastUtf8Bytes(this double value) + { + return FastToUtf8Bytes(value.ToString("R", DoubleFormatProvider)); + } - private static byte[] FastToUtf8Bytes(string strVal) - { - var bytes = new byte[strVal.Length]; - for (var i = 0; i < strVal.Length; i++) - bytes[i] = (byte) strVal[i]; + private static byte[] FastToUtf8Bytes(string strVal) + { + var bytes = new byte[strVal.Length]; + for (var i = 0; i < strVal.Length; i++) + bytes[i] = (byte)strVal[i]; - return bytes; - } + return bytes; + } - public static byte[][] PrependByteArray(this byte[][] args, byte[] valueToPrepend) - { - var newArgs = new byte[args.Length + 1][]; - newArgs[0] = valueToPrepend; - var i = 1; - foreach (var arg in args) - newArgs[i++] = arg; + public static byte[][] PrependByteArray(this byte[][] args, byte[] valueToPrepend) + { + var newArgs = new byte[args.Length + 1][]; + newArgs[0] = valueToPrepend; + var i = 1; + foreach (var arg in args) + newArgs[i++] = arg; - return newArgs; - } + return newArgs; + } - public static byte[][] PrependInt(this byte[][] args, int valueToPrepend) - { - return args.PrependByteArray(valueToPrepend.ToUtf8Bytes()); - } + public static byte[][] PrependInt(this byte[][] args, int valueToPrepend) + { + return args.PrependByteArray(valueToPrepend.ToUtf8Bytes()); } +} - public class RedisException : Exception +public class RedisException : Exception +{ + public RedisException(string message) : base(message) { - public RedisException(string message) : base(message) - { - } + } - public RedisException(string message, Exception innerException) : base(message, innerException) - { - } + public RedisException(string message, Exception innerException) : base(message, innerException) + { } +} - public class RedisResponseException : RedisException +public class RedisResponseException : RedisException +{ + public RedisResponseException(string message) : base(message) { - public RedisResponseException(string message) : base(message) - { - } + } - public RedisResponseException(string message, string code) : base(message) - { - Code = code; - } + public RedisResponseException(string message, string code) : base(message) + { + Code = code; + } - public string Code { get; private set; } + public string Code { get; } +} + +public class RedisEndpoint +{ + public RedisEndpoint() + { + Host = RedisConfig.DefaultHost; + Port = RedisConfig.DefaultPort; + Db = RedisConfig.DefaultDb; + + ConnectTimeout = RedisConfig.DefaultConnectTimeout; + SendTimeout = RedisConfig.DefaultSendTimeout; + ReceiveTimeout = RedisConfig.DefaultReceiveTimeout; + RetryTimeout = RedisConfig.DefaultRetryTimeout; + IdleTimeOutSecs = RedisConfig.DefaultIdleTimeOutSecs; } - public class RedisEndpoint + public RedisEndpoint(string host, int port, string password = null, long db = RedisConfig.DefaultDb) + : this() { - public RedisEndpoint() - { - Host = RedisConfig.DefaultHost; - Port = RedisConfig.DefaultPort; - Db = RedisConfig.DefaultDb; - - ConnectTimeout = RedisConfig.DefaultConnectTimeout; - SendTimeout = RedisConfig.DefaultSendTimeout; - ReceiveTimeout = RedisConfig.DefaultReceiveTimeout; - RetryTimeout = RedisConfig.DefaultRetryTimeout; - IdleTimeOutSecs = RedisConfig.DefaultIdleTimeOutSecs; - } + Host = host; + Port = port; + Password = password; + Db = db; + } - public RedisEndpoint(string host, int port, string password = null, long db = RedisConfig.DefaultDb) - : this() - { - this.Host = host; - this.Port = port; - this.Password = password; - this.Db = db; - } + public string Host { get; set; } + public int Port { get; set; } + public bool Ssl { get; set; } + public int ConnectTimeout { get; set; } + public int SendTimeout { get; set; } + public int ReceiveTimeout { get; set; } + public int RetryTimeout { get; set; } + public int IdleTimeOutSecs { get; set; } + public long Db { get; set; } + public string Client { get; set; } + public string Password { get; set; } - public string Host { get; set; } - public int Port { get; set; } - public bool Ssl { get; set; } - public int ConnectTimeout { get; set; } - public int SendTimeout { get; set; } - public int ReceiveTimeout { get; set; } - public int RetryTimeout { get; set; } - public int IdleTimeOutSecs { get; set; } - public long Db { get; set; } - public string Client { get; set; } - public string Password { get; set; } - - public bool RequiresAuth - { - get { return !string.IsNullOrEmpty(Password); } - } + public bool RequiresAuth => !string.IsNullOrEmpty(Password); - public string NamespacePrefix { get; set; } + public string NamespacePrefix { get; set; } - public override string ToString() - { - var sb = new StringBuilder(); - sb.AppendFormat("{0}:{1}", Host, Port); - - var args = new List(); - - if (Client != null) - args.Add("Client=" + Client); - if (Password != null) - args.Add("Password=" + System.Net.WebUtility.UrlEncode(Password)); - if (Db != RedisConfig.DefaultDb) - args.Add("Db=" + Db); - if (Ssl) - args.Add("Ssl=true"); - if (ConnectTimeout != RedisConfig.DefaultConnectTimeout) - args.Add("ConnectTimeout=" + ConnectTimeout); - if (SendTimeout != RedisConfig.DefaultSendTimeout) - args.Add("SendTimeout=" + SendTimeout); - if (ReceiveTimeout != RedisConfig.DefaultReceiveTimeout) - args.Add("ReceiveTimeout=" + ReceiveTimeout); - if (RetryTimeout != RedisConfig.DefaultRetryTimeout) - args.Add("RetryTimeout=" + RetryTimeout); - if (IdleTimeOutSecs != RedisConfig.DefaultIdleTimeOutSecs) - args.Add("IdleTimeOutSecs=" + IdleTimeOutSecs); - if (NamespacePrefix != null) - args.Add("NamespacePrefix=" + System.Net.WebUtility.UrlEncode(NamespacePrefix)); - - if (args.Count > 0) - sb.Append("?").Append(string.Join("&", args)); - - return sb.ToString(); - } + public override string ToString() + { + var sb = new StringBuilder(); + sb.AppendFormat("{0}:{1}", Host, Port); + + var args = new List(); + + if (Client != null) + args.Add("Client=" + Client); + if (Password != null) + args.Add("Password=" + WebUtility.UrlEncode(Password)); + if (Db != RedisConfig.DefaultDb) + args.Add("Db=" + Db); + if (Ssl) + args.Add("Ssl=true"); + if (ConnectTimeout != RedisConfig.DefaultConnectTimeout) + args.Add("ConnectTimeout=" + ConnectTimeout); + if (SendTimeout != RedisConfig.DefaultSendTimeout) + args.Add("SendTimeout=" + SendTimeout); + if (ReceiveTimeout != RedisConfig.DefaultReceiveTimeout) + args.Add("ReceiveTimeout=" + ReceiveTimeout); + if (RetryTimeout != RedisConfig.DefaultRetryTimeout) + args.Add("RetryTimeout=" + RetryTimeout); + if (IdleTimeOutSecs != RedisConfig.DefaultIdleTimeOutSecs) + args.Add("IdleTimeOutSecs=" + IdleTimeOutSecs); + if (NamespacePrefix != null) + args.Add("NamespacePrefix=" + WebUtility.UrlEncode(NamespacePrefix)); + + if (args.Count > 0) + sb.Append("?").Append(string.Join("&", args)); + + return sb.ToString(); + } - protected bool Equals(RedisEndpoint other) - { - return string.Equals(Host, other.Host) - && Port == other.Port - && Ssl.Equals(other.Ssl) - && ConnectTimeout == other.ConnectTimeout - && SendTimeout == other.SendTimeout - && ReceiveTimeout == other.ReceiveTimeout - && RetryTimeout == other.RetryTimeout - && IdleTimeOutSecs == other.IdleTimeOutSecs - && Db == other.Db - && string.Equals(Client, other.Client) - && string.Equals(Password, other.Password) - && string.Equals(NamespacePrefix, other.NamespacePrefix); - } + protected bool Equals(RedisEndpoint other) + { + return string.Equals(Host, other.Host) + && Port == other.Port + && Ssl.Equals(other.Ssl) + && ConnectTimeout == other.ConnectTimeout + && SendTimeout == other.SendTimeout + && ReceiveTimeout == other.ReceiveTimeout + && RetryTimeout == other.RetryTimeout + && IdleTimeOutSecs == other.IdleTimeOutSecs + && Db == other.Db + && string.Equals(Client, other.Client) + && string.Equals(Password, other.Password) + && string.Equals(NamespacePrefix, other.NamespacePrefix); + } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((RedisEndpoint) obj); - } + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((RedisEndpoint)obj); + } - public override int GetHashCode() - { - unchecked - { - var hashCode = (Host != null ? Host.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ Port; - hashCode = (hashCode * 397) ^ Ssl.GetHashCode(); - hashCode = (hashCode * 397) ^ ConnectTimeout; - hashCode = (hashCode * 397) ^ SendTimeout; - hashCode = (hashCode * 397) ^ ReceiveTimeout; - hashCode = (hashCode * 397) ^ RetryTimeout; - hashCode = (hashCode * 397) ^ IdleTimeOutSecs; - hashCode = (hashCode * 397) ^ Db.GetHashCode(); - hashCode = (hashCode * 397) ^ (Client != null ? Client.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (Password != null ? Password.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (NamespacePrefix != null ? NamespacePrefix.GetHashCode() : 0); - return hashCode; - } + public override int GetHashCode() + { + unchecked + { + var hashCode = Host != null ? Host.GetHashCode() : 0; + hashCode = (hashCode * 397) ^ Port; + hashCode = (hashCode * 397) ^ Ssl.GetHashCode(); + hashCode = (hashCode * 397) ^ ConnectTimeout; + hashCode = (hashCode * 397) ^ SendTimeout; + hashCode = (hashCode * 397) ^ ReceiveTimeout; + hashCode = (hashCode * 397) ^ RetryTimeout; + hashCode = (hashCode * 397) ^ IdleTimeOutSecs; + hashCode = (hashCode * 397) ^ Db.GetHashCode(); + hashCode = (hashCode * 397) ^ (Client != null ? Client.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Password != null ? Password.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (NamespacePrefix != null ? NamespacePrefix.GetHashCode() : 0); + return hashCode; } } - - public class RedisConfig - { - //redis-server defaults: - public const long DefaultDb = 0; - public const int DefaultPort = 6379; - public const int DefaultPortSsl = 6380; - public const int DefaultPortSentinel = 26379; - public const string DefaultHost = "localhost"; - - /// - /// The default RedisClient Socket ConnectTimeout (default -1, None) - /// - public static int DefaultConnectTimeout = -1; - - /// - /// The default RedisClient Socket SendTimeout (default -1, None) - /// - public static int DefaultSendTimeout = -1; - - /// - /// The default RedisClient Socket ReceiveTimeout (default -1, None) - /// - public static int DefaultReceiveTimeout = -1; - - /// - /// Default Idle TimeOut before a connection is considered to be stale (default 240 secs) - /// - public static int DefaultIdleTimeOutSecs = 240; - - /// - /// The default RetryTimeout for auto retry of failed operations (default 10,000ms) - /// - public static int DefaultRetryTimeout = 10 * 1000; - - /// - /// Default Max Pool Size for Pooled Redis Client Managers (default none) - /// - public static int? DefaultMaxPoolSize; - - /// - /// The BackOff multiplier failed Auto Retries starts from (default 10ms) - /// - public static int BackOffMultiplier = 10; - - /// - /// The Byte Buffer Size to combine Redis Operations within (1450 bytes) - /// - public static int BufferLength => 1450; - - /// - /// The Byte Buffer Size for Operations to use a byte buffer pool (default 500kb) - /// - public static int BufferPoolMaxSize = 500000; - - /// - /// Whether Connections to Master hosts should be verified they're still master instances (default true) - /// - public static bool VerifyMasterConnections = true; - - /// - /// The ConnectTimeout on clients used to find the next available host (default 200ms) - /// - public static int HostLookupTimeoutMs = 200; - - /// - /// Skip ServerVersion Checks by specifying Min Version number, e.g: 2.8.12 => 2812, 2.9.1 => 2910 - /// - public static int? AssumeServerVersion; - - /// - /// How long to hold deactivated clients for before disposing their connection (default 1 min) - /// Dispose of deactivated Clients immediately with TimeSpan.Zero - /// - public static TimeSpan DeactivatedClientsExpiry = TimeSpan.FromMinutes(1); - - /// - /// Whether Debug Logging should log detailed Redis operations (default false) - /// - public static bool DisableVerboseLogging = false; - - - /// - /// Assert all access using pooled RedisClient instance should be limited to same thread. - /// Captures StackTrace so is very slow, use only for debugging connection issues. - /// - public static bool AssertAccessOnlyOnSameThread = false; - - /// - /// Resets Redis Config and Redis Stats back to default values - /// - public static void Reset() - { +} - DefaultConnectTimeout = -1; - DefaultSendTimeout = -1; - DefaultReceiveTimeout = -1; - DefaultRetryTimeout = 10 * 1000; - DefaultIdleTimeOutSecs = 240; - DefaultMaxPoolSize = null; - BackOffMultiplier = 10; - BufferPoolMaxSize = 500000; - VerifyMasterConnections = true; - HostLookupTimeoutMs = 200; - AssumeServerVersion = null; - DeactivatedClientsExpiry = TimeSpan.FromMinutes(1); - DisableVerboseLogging = false; - AssertAccessOnlyOnSameThread = false; - } +public class RedisConfig +{ + //redis-server defaults: + public const long DefaultDb = 0; + public const int DefaultPort = 6379; + public const int DefaultPortSsl = 6380; + public const int DefaultPortSentinel = 26379; + public const string DefaultHost = "localhost"; + + /// + /// The default RedisClient Socket ConnectTimeout (default -1, None) + /// + public static int DefaultConnectTimeout = -1; + + /// + /// The default RedisClient Socket SendTimeout (default -1, None) + /// + public static int DefaultSendTimeout = -1; + + /// + /// The default RedisClient Socket ReceiveTimeout (default -1, None) + /// + public static int DefaultReceiveTimeout = -1; + + /// + /// Default Idle TimeOut before a connection is considered to be stale (default 240 secs) + /// + public static int DefaultIdleTimeOutSecs = 240; + + /// + /// The default RetryTimeout for auto retry of failed operations (default 10,000ms) + /// + public static int DefaultRetryTimeout = 10 * 1000; + + /// + /// Default Max Pool Size for Pooled Redis Client Managers (default none) + /// + public static int? DefaultMaxPoolSize; + + /// + /// The BackOff multiplier failed Auto Retries starts from (default 10ms) + /// + public static int BackOffMultiplier = 10; + + /// + /// The Byte Buffer Size for Operations to use a byte buffer pool (default 500kb) + /// + public static int BufferPoolMaxSize = 500000; + + /// + /// Whether Connections to Master hosts should be verified they're still master instances (default true) + /// + public static bool VerifyMasterConnections = true; + + /// + /// The ConnectTimeout on clients used to find the next available host (default 200ms) + /// + public static int HostLookupTimeoutMs = 200; + + /// + /// Skip ServerVersion Checks by specifying Min Version number, e.g: 2.8.12 => 2812, 2.9.1 => 2910 + /// + public static int? AssumeServerVersion; + + /// + /// How long to hold deactivated clients for before disposing their connection (default 1 min) + /// Dispose of deactivated Clients immediately with TimeSpan.Zero + /// + public static TimeSpan DeactivatedClientsExpiry = TimeSpan.FromMinutes(1); + + /// + /// Whether Debug Logging should log detailed Redis operations (default false) + /// + public static bool DisableVerboseLogging; + + + /// + /// Assert all access using pooled RedisClient instance should be limited to same thread. + /// Captures StackTrace so is very slow, use only for debugging connection issues. + /// + public static bool AssertAccessOnlyOnSameThread; + + /// + /// The Byte Buffer Size to combine Redis Operations within (1450 bytes) + /// + public static int BufferLength => 1450; + + /// + /// Resets Redis Config and Redis Stats back to default values + /// + public static void Reset() + { + DefaultConnectTimeout = -1; + DefaultSendTimeout = -1; + DefaultReceiveTimeout = -1; + DefaultRetryTimeout = 10 * 1000; + DefaultIdleTimeOutSecs = 240; + DefaultMaxPoolSize = null; + BackOffMultiplier = 10; + BufferPoolMaxSize = 500000; + VerifyMasterConnections = true; + HostLookupTimeoutMs = 200; + AssumeServerVersion = null; + DeactivatedClientsExpiry = TimeSpan.FromMinutes(1); + DisableVerboseLogging = false; + AssertAccessOnlyOnSameThread = false; } } \ No newline at end of file diff --git a/src/AElf.Database/SsdbDatabase.cs b/src/AElf.Database/SsdbDatabase.cs index 6fc9d03a7c..5a60d5d53b 100644 --- a/src/AElf.Database/SsdbDatabase.cs +++ b/src/AElf.Database/SsdbDatabase.cs @@ -1,17 +1,9 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Database.RedisProtocol; -using Microsoft.Extensions.Options; +namespace AElf.Database; -namespace AElf.Database +public class SsdbDatabase : RedisDatabase + where TKeyValueDbContext : KeyValueDbContext { - public class SsdbDatabase : RedisDatabase - where TKeyValueDbContext:KeyValueDbContext + public SsdbDatabase(KeyValueDatabaseOptions options) : base(options) { - public SsdbDatabase(KeyValueDatabaseOptions options) : base(options) - { - } } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/AElf.EconomicSystem.csproj b/src/AElf.EconomicSystem/AElf.EconomicSystem.csproj index 4ac159f520..2ddb7d08d9 100644 --- a/src/AElf.EconomicSystem/AElf.EconomicSystem.csproj +++ b/src/AElf.EconomicSystem/AElf.EconomicSystem.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.EconomicSystem @@ -8,9 +8,9 @@ - - - + + + diff --git a/src/AElf.EconomicSystem/EconomicContractInitializationProvider.cs b/src/AElf.EconomicSystem/EconomicContractInitializationProvider.cs index 99d7023fec..bbe1333563 100644 --- a/src/AElf.EconomicSystem/EconomicContractInitializationProvider.cs +++ b/src/AElf.EconomicSystem/EconomicContractInitializationProvider.cs @@ -10,53 +10,54 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class EconomicContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class EconomicContractInitializationProvider : IContractInitializationProvider, ITransientDependency + private readonly ConsensusOptions _consensusOptions; + private readonly EconomicOptions _economicOptions; + + + public EconomicContractInitializationProvider( + IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) { - private readonly EconomicOptions _economicOptions; - private readonly ConsensusOptions _consensusOptions; - - public Hash SystemSmartContractName { get; } = EconomicSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Economic"; + _consensusOptions = consensusOptions.Value; + _economicOptions = economicOptions.Value; + } + public Hash SystemSmartContractName { get; } = EconomicSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Economic"; - public EconomicContractInitializationProvider( - IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) - { - _consensusOptions = consensusOptions.Value; - _economicOptions = economicOptions.Value; - } - - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + return new List { - return new List + new() + { + MethodName = nameof(EconomicContractContainer.EconomicContractStub.InitialEconomicSystem), + Params = new InitialEconomicSystemInput + { + NativeTokenDecimals = _economicOptions.Decimals, + IsNativeTokenBurnable = _economicOptions.IsBurnable, + NativeTokenSymbol = _economicOptions.Symbol, + NativeTokenName = _economicOptions.TokenName, + NativeTokenTotalSupply = _economicOptions.TotalSupply, + MiningRewardTotalAmount = + Convert.ToInt64(_economicOptions.TotalSupply * _economicOptions.DividendPoolRatio), + TransactionSizeFeeUnitPrice = _economicOptions.TransactionSizeFeeUnitPrice + }.ToByteString() + }, + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(EconomicContractContainer.EconomicContractStub.InitialEconomicSystem), - Params = new InitialEconomicSystemInput - { - NativeTokenDecimals = _economicOptions.Decimals, - IsNativeTokenBurnable = _economicOptions.IsBurnable, - NativeTokenSymbol = _economicOptions.Symbol, - NativeTokenName = _economicOptions.TokenName, - NativeTokenTotalSupply = _economicOptions.TotalSupply, - MiningRewardTotalAmount = - Convert.ToInt64(_economicOptions.TotalSupply * _economicOptions.DividendPoolRatio), - TransactionSizeFeeUnitPrice = _economicOptions.TransactionSizeFeeUnitPrice - }.ToByteString() - }, - new ContractInitializationMethodCall{ - MethodName = nameof(EconomicContractContainer.EconomicContractStub.IssueNativeToken), - Params = new IssueNativeTokenInput - { - Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), - To = Address.FromPublicKey( - ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList.First())), - Memo = "Issue native token" - }.ToByteString() - } - }; - } + MethodName = nameof(EconomicContractContainer.EconomicContractStub.IssueNativeToken), + Params = new IssueNativeTokenInput + { + Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), + To = Address.FromPublicKey( + ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList.First())), + Memo = "Issue native token" + }.ToByteString() + } + }; } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/EconomicSmartContractAddressNameProvider.cs b/src/AElf.EconomicSystem/EconomicSmartContractAddressNameProvider.cs index 3c4e04df84..a3c3ee8081 100644 --- a/src/AElf.EconomicSystem/EconomicSmartContractAddressNameProvider.cs +++ b/src/AElf.EconomicSystem/EconomicSmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class EconomicSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class EconomicSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); + public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/EconomicSystemAElfModule.cs b/src/AElf.EconomicSystem/EconomicSystemAElfModule.cs index f0492fb2d4..8c59b45ea7 100644 --- a/src/AElf.EconomicSystem/EconomicSystemAElfModule.cs +++ b/src/AElf.EconomicSystem/EconomicSystemAElfModule.cs @@ -1,8 +1,7 @@ using AElf.Modularity; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class EconomicSystemAElfModule : AElfModule { - public class EconomicSystemAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/ProfitContractInitializationProvider.cs b/src/AElf.EconomicSystem/ProfitContractInitializationProvider.cs index 1944c1949a..6bce55a413 100644 --- a/src/AElf.EconomicSystem/ProfitContractInitializationProvider.cs +++ b/src/AElf.EconomicSystem/ProfitContractInitializationProvider.cs @@ -1,20 +1,18 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class ProfitContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class ProfitContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName => ProfitSmartContractAddressNameProvider.Name; - public string ContractCodeName => "AElf.Contracts.Profit"; + public Hash SystemSmartContractName => ProfitSmartContractAddressNameProvider.Name; + public string ContractCodeName => "AElf.Contracts.Profit"; - public List GetInitializeMethodList(byte[] contractCode) - { - // Profit Contract doesn't need initial method call list. - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + // Profit Contract doesn't need initial method call list. + return new List(); } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/ProfitSmartContractAddressNameProvider.cs b/src/AElf.EconomicSystem/ProfitSmartContractAddressNameProvider.cs index 44f5ae7ffc..099d6f1b30 100644 --- a/src/AElf.EconomicSystem/ProfitSmartContractAddressNameProvider.cs +++ b/src/AElf.EconomicSystem/ProfitSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class ProfitSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ProfitSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Profit"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Profit"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TokenConverterContractInitializationProvider.cs b/src/AElf.EconomicSystem/TokenConverterContractInitializationProvider.cs index fbe90085b4..4727f08ad0 100644 --- a/src/AElf.EconomicSystem/TokenConverterContractInitializationProvider.cs +++ b/src/AElf.EconomicSystem/TokenConverterContractInitializationProvider.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TokenConverterContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class TokenConverterContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = TokenConverterSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.TokenConverter"; + public Hash SystemSmartContractName { get; } = TokenConverterSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.TokenConverter"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TokenConverterSmartContractAddressNameProvider.cs b/src/AElf.EconomicSystem/TokenConverterSmartContractAddressNameProvider.cs index 6a7a4e6d71..177228c6c8 100644 --- a/src/AElf.EconomicSystem/TokenConverterSmartContractAddressNameProvider.cs +++ b/src/AElf.EconomicSystem/TokenConverterSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TokenConverterSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TokenConverterSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TokenConverter"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TokenConverter"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TokenHolderContractInitializationProvider.cs b/src/AElf.EconomicSystem/TokenHolderContractInitializationProvider.cs index 0881a491d0..95a572684b 100644 --- a/src/AElf.EconomicSystem/TokenHolderContractInitializationProvider.cs +++ b/src/AElf.EconomicSystem/TokenHolderContractInitializationProvider.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TokenHolderContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class TokenHolderContractInitializationProvider : IContractInitializationProvider, ITransientDependency + public Hash SystemSmartContractName { get; } = TokenHolderSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.TokenHolder"; + + public List GetInitializeMethodList(byte[] contractCode) { - public Hash SystemSmartContractName { get; } = TokenHolderSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.TokenHolder"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + return new List(); } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TokenHolderSmartContractAddressNameProvider.cs b/src/AElf.EconomicSystem/TokenHolderSmartContractAddressNameProvider.cs index bf77b4f2c6..c71915934b 100644 --- a/src/AElf.EconomicSystem/TokenHolderSmartContractAddressNameProvider.cs +++ b/src/AElf.EconomicSystem/TokenHolderSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TokenHolderSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TokenHolderSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TreasuryContractInitializationProvider.cs b/src/AElf.EconomicSystem/TreasuryContractInitializationProvider.cs index 946c0c3d72..903edbe8c0 100644 --- a/src/AElf.EconomicSystem/TreasuryContractInitializationProvider.cs +++ b/src/AElf.EconomicSystem/TreasuryContractInitializationProvider.cs @@ -3,29 +3,29 @@ using AElf.Kernel.SmartContract.Application; using AElf.Types; using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TreasuryContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class TreasuryContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = TreasurySmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Treasury"; + public Hash SystemSmartContractName { get; } = TreasurySmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Treasury"; - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + return new List { - return new List + new() + { + MethodName = nameof(TreasuryContractContainer.TreasuryContractStub.InitialTreasuryContract), + Params = ByteString.Empty + }, + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(TreasuryContractContainer.TreasuryContractStub.InitialTreasuryContract), - Params = ByteString.Empty - }, - new ContractInitializationMethodCall{ - MethodName = nameof(TreasuryContractContainer.TreasuryContractStub.InitialMiningRewardProfitItem), - Params = ByteString.Empty - } - }; - } + MethodName = nameof(TreasuryContractContainer.TreasuryContractStub.InitialMiningRewardProfitItem), + Params = ByteString.Empty + } + }; } } \ No newline at end of file diff --git a/src/AElf.EconomicSystem/TreasurySmartContractAddressNameProvider.cs b/src/AElf.EconomicSystem/TreasurySmartContractAddressNameProvider.cs index 0bd92a2316..c6a7cf6653 100644 --- a/src/AElf.EconomicSystem/TreasurySmartContractAddressNameProvider.cs +++ b/src/AElf.EconomicSystem/TreasurySmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.EconomicSystem +namespace AElf.EconomicSystem; + +public class TreasurySmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TreasurySmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Treasury"); + public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Treasury"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/AElf.GovernmentSystem.csproj b/src/AElf.GovernmentSystem/AElf.GovernmentSystem.csproj index 524ee6a591..4122562536 100644 --- a/src/AElf.GovernmentSystem/AElf.GovernmentSystem.csproj +++ b/src/AElf.GovernmentSystem/AElf.GovernmentSystem.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.GovernmentSystem @@ -8,10 +8,10 @@ - - - - + + + + @@ -19,7 +19,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\acs3.proto diff --git a/src/AElf.GovernmentSystem/AssociationContractInitializationProvider.cs b/src/AElf.GovernmentSystem/AssociationContractInitializationProvider.cs index f9da6a98d3..3094a47048 100644 --- a/src/AElf.GovernmentSystem/AssociationContractInitializationProvider.cs +++ b/src/AElf.GovernmentSystem/AssociationContractInitializationProvider.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class AssociationContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class AssociationContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = AssociationSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Association"; + public Hash SystemSmartContractName { get; } = AssociationSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Association"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/AssociationSmartContractAddressNameProvider.cs b/src/AElf.GovernmentSystem/AssociationSmartContractAddressNameProvider.cs index 8b74b9fd73..51248ef737 100644 --- a/src/AElf.GovernmentSystem/AssociationSmartContractAddressNameProvider.cs +++ b/src/AElf.GovernmentSystem/AssociationSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class AssociationSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class AssociationSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Association"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Association"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/ElectionContractInitializationProvider.cs b/src/AElf.GovernmentSystem/ElectionContractInitializationProvider.cs index 488e8e021c..8d52ad10d3 100644 --- a/src/AElf.GovernmentSystem/ElectionContractInitializationProvider.cs +++ b/src/AElf.GovernmentSystem/ElectionContractInitializationProvider.cs @@ -8,40 +8,40 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class ElectionContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class ElectionContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - private readonly EconomicOptions _economicOptions; - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; + private readonly EconomicOptions _economicOptions; - public Hash SystemSmartContractName { get; } = ElectionSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Election"; + public ElectionContractInitializationProvider( + IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) + { + _consensusOptions = consensusOptions.Value; + _economicOptions = economicOptions.Value; + } - public ElectionContractInitializationProvider( - IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) - { - _consensusOptions = consensusOptions.Value; - _economicOptions = economicOptions.Value; - } + public Hash SystemSmartContractName { get; } = ElectionSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Election"; - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + return new List { - return new List + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(ElectionContractContainer.ElectionContractStub.InitialElectionContract), - Params = new InitialElectionContractInput - { - MaximumLockTime = _economicOptions.MaximumLockTime, - MinimumLockTime = _economicOptions.MinimumLockTime, - TimeEachTerm = _consensusOptions.PeriodSeconds, - MinerList = {_consensusOptions.InitialMinerList}, - MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval - }.ToByteString() - } - }; - } + MethodName = nameof(ElectionContractContainer.ElectionContractStub.InitialElectionContract), + Params = new InitialElectionContractInput + { + MaximumLockTime = _economicOptions.MaximumLockTime, + MinimumLockTime = _economicOptions.MinimumLockTime, + TimeEachTerm = _consensusOptions.PeriodSeconds, + MinerList = { _consensusOptions.InitialMinerList }, + MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval + }.ToByteString() + } + }; } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/ElectionSmartContractAddressNameProvider.cs b/src/AElf.GovernmentSystem/ElectionSmartContractAddressNameProvider.cs index 86eb989394..82d10f3487 100644 --- a/src/AElf.GovernmentSystem/ElectionSmartContractAddressNameProvider.cs +++ b/src/AElf.GovernmentSystem/ElectionSmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class ElectionSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ElectionSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Election"); + public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Election"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/GovernmentSystemAElfModule.cs b/src/AElf.GovernmentSystem/GovernmentSystemAElfModule.cs index 3da9ca6453..799d7a795f 100644 --- a/src/AElf.GovernmentSystem/GovernmentSystemAElfModule.cs +++ b/src/AElf.GovernmentSystem/GovernmentSystemAElfModule.cs @@ -1,8 +1,7 @@ using AElf.Modularity; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class GovernmentSystemAElfModule : AElfModule { - public class GovernmentSystemAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/IParliamentContractInitializationDataProvider.cs b/src/AElf.GovernmentSystem/IParliamentContractInitializationDataProvider.cs index 0f367bc158..1ebda05d9a 100644 --- a/src/AElf.GovernmentSystem/IParliamentContractInitializationDataProvider.cs +++ b/src/AElf.GovernmentSystem/IParliamentContractInitializationDataProvider.cs @@ -1,19 +1,18 @@ using AElf.Types; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +/// +/// Add this interface because the initialization logic of Parliament Contract +/// are different from Main Chain, Side Chain and test cases. +/// +public interface IParliamentContractInitializationDataProvider { - /// - /// Add this interface because the initialization logic of Parliament Contract - /// are different from Main Chain, Side Chain and test cases. - /// - public interface IParliamentContractInitializationDataProvider - { - ParliamentContractInitializationData GetContractInitializationData(); - } + ParliamentContractInitializationData GetContractInitializationData(); +} - public class ParliamentContractInitializationData - { - public Address PrivilegedProposer { get; set; } - public bool ProposerAuthorityRequired { get; set; } - } +public class ParliamentContractInitializationData +{ + public Address PrivilegedProposer { get; set; } + public bool ProposerAuthorityRequired { get; set; } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/ParliamentContractInitializationProvider.cs b/src/AElf.GovernmentSystem/ParliamentContractInitializationProvider.cs index ab19427cc8..1aae35c82d 100644 --- a/src/AElf.GovernmentSystem/ParliamentContractInitializationProvider.cs +++ b/src/AElf.GovernmentSystem/ParliamentContractInitializationProvider.cs @@ -6,35 +6,35 @@ using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class ParliamentContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class ParliamentContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = ParliamentSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Parliament"; + private readonly IParliamentContractInitializationDataProvider _parliamentContractInitializationDataProvider; - private readonly IParliamentContractInitializationDataProvider _parliamentContractInitializationDataProvider; + public ParliamentContractInitializationProvider( + IParliamentContractInitializationDataProvider parliamentContractInitializationDataProvider) + { + _parliamentContractInitializationDataProvider = parliamentContractInitializationDataProvider; + } - public ParliamentContractInitializationProvider( - IParliamentContractInitializationDataProvider parliamentContractInitializationDataProvider) - { - _parliamentContractInitializationDataProvider = parliamentContractInitializationDataProvider; - } + public Hash SystemSmartContractName { get; } = ParliamentSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Parliament"; - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + var initializationData = _parliamentContractInitializationDataProvider.GetContractInitializationData(); + return new List { - var initializationData = _parliamentContractInitializationDataProvider.GetContractInitializationData(); - return new List + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(ParliamentContractContainer.ParliamentContractStub.Initialize), - Params = new InitializeInput - { - PrivilegedProposer = initializationData.PrivilegedProposer, - ProposerAuthorityRequired = initializationData.ProposerAuthorityRequired - }.ToByteString() - } - }; - } + MethodName = nameof(ParliamentContractContainer.ParliamentContractStub.Initialize), + Params = new InitializeInput + { + PrivilegedProposer = initializationData.PrivilegedProposer, + ProposerAuthorityRequired = initializationData.ProposerAuthorityRequired + }.ToByteString() + } + }; } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/ReferendumContractInitializationProvider.cs b/src/AElf.GovernmentSystem/ReferendumContractInitializationProvider.cs index a5f22794c2..99e9e7c107 100644 --- a/src/AElf.GovernmentSystem/ReferendumContractInitializationProvider.cs +++ b/src/AElf.GovernmentSystem/ReferendumContractInitializationProvider.cs @@ -3,16 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class ReferendumContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class ReferendumContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = ReferendumSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Referendum"; + public Hash SystemSmartContractName { get; } = ReferendumSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Referendum"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/ReferendumSmartContractAddressNameProvider.cs b/src/AElf.GovernmentSystem/ReferendumSmartContractAddressNameProvider.cs index 5a2b4c9ad3..4761d2913a 100644 --- a/src/AElf.GovernmentSystem/ReferendumSmartContractAddressNameProvider.cs +++ b/src/AElf.GovernmentSystem/ReferendumSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class ReferendumSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ReferendumSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Referendum"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Referendum"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/VoteContractInitializationProvider.cs b/src/AElf.GovernmentSystem/VoteContractInitializationProvider.cs index 64ff65134e..2e9bbf1d49 100644 --- a/src/AElf.GovernmentSystem/VoteContractInitializationProvider.cs +++ b/src/AElf.GovernmentSystem/VoteContractInitializationProvider.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class VoteContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class VoteContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = VoteSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Vote"; + public Hash SystemSmartContractName { get; } = VoteSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Vote"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/src/AElf.GovernmentSystem/VoteSmartContractAddressNameProvider.cs b/src/AElf.GovernmentSystem/VoteSmartContractAddressNameProvider.cs index ae9497d887..4df908bb02 100644 --- a/src/AElf.GovernmentSystem/VoteSmartContractAddressNameProvider.cs +++ b/src/AElf.GovernmentSystem/VoteSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.GovernmentSystem +namespace AElf.GovernmentSystem; + +public class VoteSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class VoteSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.ChainController/AElf.Kernel.ChainController.csproj b/src/AElf.Kernel.ChainController/AElf.Kernel.ChainController.csproj index b589a0c2dd..812b5b0050 100644 --- a/src/AElf.Kernel.ChainController/AElf.Kernel.ChainController.csproj +++ b/src/AElf.Kernel.ChainController/AElf.Kernel.ChainController.csproj @@ -1,12 +1,12 @@ - - - net6.0 - AElf.Kernel.ChainController - true - Module that contains chain creation functionality. - - - - + + + net6.0 + AElf.Kernel.ChainController + true + Module that contains chain creation functionality. + + + + \ No newline at end of file diff --git a/src/AElf.Kernel.ChainController/Application/ChainCreationService.cs b/src/AElf.Kernel.ChainController/Application/ChainCreationService.cs index 6bd40db7ad..edaebf187c 100644 --- a/src/AElf.Kernel.ChainController/Application/ChainCreationService.cs +++ b/src/AElf.Kernel.ChainController/Application/ChainCreationService.cs @@ -10,62 +10,62 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.ChainController.Application +namespace AElf.Kernel.ChainController.Application; + +public class ChainCreationService : IChainCreationService { - public class ChainCreationService : IChainCreationService + private readonly IBlockchainExecutingService _blockchainExecutingService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; + + public ChainCreationService(IBlockchainService blockchainService, IBlockExecutingService blockExecutingService, + IBlockExecutionResultProcessingService blockExecutionResultProcessingService + , IBlockchainExecutingService blockchainExecutingService) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; - private readonly IBlockchainExecutingService _blockchainExecutingService; - public ILogger Logger { get; set; } + _blockchainService = blockchainService; + _blockExecutingService = blockExecutingService; + _blockExecutionResultProcessingService = blockExecutionResultProcessingService; + _blockchainExecutingService = blockchainExecutingService; + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + } - public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public ChainCreationService(IBlockchainService blockchainService, IBlockExecutingService blockExecutingService, - IBlockExecutionResultProcessingService blockExecutionResultProcessingService - , IBlockchainExecutingService blockchainExecutingService) - { - _blockchainService = blockchainService; - _blockExecutingService = blockExecutingService; - _blockExecutionResultProcessingService = blockExecutionResultProcessingService; - _blockchainExecutingService = blockchainExecutingService; - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILocalEventBus LocalEventBus { get; set; } - /// - /// Creates a new chain with the provided genesis transactions and Smart Contract Zero. - /// - /// The new chain async. - /// The new chain id which will be derived from the creator address. - /// The transactions to be executed in the genesis block. - public async Task CreateNewChainAsync(IEnumerable genesisTransactions) + /// + /// Creates a new chain with the provided genesis transactions and Smart Contract Zero. + /// + /// The new chain async. + /// The new chain id which will be derived from the creator address. + /// The transactions to be executed in the genesis block. + public async Task CreateNewChainAsync(IEnumerable genesisTransactions) + { + try { - try + var blockHeader = new BlockHeader { - var blockHeader = new BlockHeader - { - Height = AElfConstants.GenesisBlockHeight, - PreviousBlockHash = Hash.Empty, - Time = new Timestamp {Seconds = 0}, - ChainId = _blockchainService.GetChainId() - }; + Height = AElfConstants.GenesisBlockHeight, + PreviousBlockHash = Hash.Empty, + Time = new Timestamp { Seconds = 0 }, + ChainId = _blockchainService.GetChainId() + }; - var transactions = genesisTransactions.ToList(); + var transactions = genesisTransactions.ToList(); - var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - var chain = await _blockchainService.CreateChainAsync(block.Block, transactions); - var blockExecutionResult = await _blockchainExecutingService.ExecuteBlocksAsync(new[] {block.Block}); - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); + var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + var chain = await _blockchainService.CreateChainAsync(block.Block, transactions); + var blockExecutionResult = await _blockchainExecutingService.ExecuteBlocksAsync(new[] { block.Block }); + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); - return await _blockchainService.GetChainAsync(); - } - catch (Exception e) - { - Logger.LogError(e, "Create new chain failed."); - throw; - } + return await _blockchainService.GetChainAsync(); + } + catch (Exception e) + { + Logger.LogError(e, "Create new chain failed"); + throw; } } } \ No newline at end of file diff --git a/src/AElf.Kernel.ChainController/Application/IChainCreationService.cs b/src/AElf.Kernel.ChainController/Application/IChainCreationService.cs index 7706fd36b1..b6e910a9f3 100644 --- a/src/AElf.Kernel.ChainController/Application/IChainCreationService.cs +++ b/src/AElf.Kernel.ChainController/Application/IChainCreationService.cs @@ -2,13 +2,12 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.ChainController.Application +namespace AElf.Kernel.ChainController.Application; + +/// +/// Create a new chain never existing +/// +public interface IChainCreationService { - /// - /// Create a new chain never existing - /// - public interface IChainCreationService - { - Task CreateNewChainAsync(IEnumerable genesisTransactions); - } + Task CreateNewChainAsync(IEnumerable genesisTransactions); } \ No newline at end of file diff --git a/src/AElf.Kernel.ChainController/ChainControllerAElfModule.cs b/src/AElf.Kernel.ChainController/ChainControllerAElfModule.cs index 8e938fa45e..8d0d9fab98 100644 --- a/src/AElf.Kernel.ChainController/ChainControllerAElfModule.cs +++ b/src/AElf.Kernel.ChainController/ChainControllerAElfModule.cs @@ -2,13 +2,12 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Kernel.ChainController +namespace AElf.Kernel.ChainController; + +[DependsOn(typeof(SmartContractExecutionAElfModule))] +public class ChainControllerAElfModule : AElfModule { - [DependsOn(typeof(SmartContractExecutionAElfModule))] - public class ChainControllerAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/AElf.Kernel.CodeCheck.csproj b/src/AElf.Kernel.CodeCheck/AElf.Kernel.CodeCheck.csproj index 0aba2688e6..7aff66e2a0 100644 --- a/src/AElf.Kernel.CodeCheck/AElf.Kernel.CodeCheck.csproj +++ b/src/AElf.Kernel.CodeCheck/AElf.Kernel.CodeCheck.csproj @@ -9,8 +9,8 @@ - - + + @@ -21,7 +21,7 @@ Protobuf\Proto\acs3.proto - + Protobuf\Proto\code_check.proto diff --git a/src/AElf.Kernel.CodeCheck/Application/CodeCheckService.cs b/src/AElf.Kernel.CodeCheck/Application/CodeCheckService.cs index eda882b826..cbb7c1de48 100644 --- a/src/AElf.Kernel.CodeCheck/Application/CodeCheckService.cs +++ b/src/AElf.Kernel.CodeCheck/Application/CodeCheckService.cs @@ -1,58 +1,52 @@ -using System.Threading.Tasks; using AElf.Kernel.CodeCheck.Infrastructure; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.CodeCheck.Application +namespace AElf.Kernel.CodeCheck.Application; + +public class CodeCheckService : ICodeCheckService, ITransientDependency { - public class CodeCheckService : ICodeCheckService, ITransientDependency - { - private readonly IRequiredAcsProvider _requiredAcsProvider; - private readonly IContractAuditorContainer _contractAuditorContainer; - private readonly CodeCheckOptions _codeCheckOptions; + private readonly CodeCheckOptions _codeCheckOptions; + private readonly IContractAuditorContainer _contractAuditorContainer; + private readonly IRequiredAcsProvider _requiredAcsProvider; - public ILogger Logger { get; set; } + public CodeCheckService(IRequiredAcsProvider requiredAcsProvider, + IContractAuditorContainer contractAuditorContainer, + IOptionsMonitor codeCheckOptionsMonitor) + { + _requiredAcsProvider = requiredAcsProvider; + _contractAuditorContainer = contractAuditorContainer; + _codeCheckOptions = codeCheckOptionsMonitor.CurrentValue; + } + public ILogger Logger { get; set; } - public CodeCheckService(IRequiredAcsProvider requiredAcsProvider, - IContractAuditorContainer contractAuditorContainer, - IOptionsMonitor codeCheckOptionsMonitor) - { - _requiredAcsProvider = requiredAcsProvider; - _contractAuditorContainer = contractAuditorContainer; - _codeCheckOptions = codeCheckOptionsMonitor.CurrentValue; - } + public async Task PerformCodeCheckAsync(byte[] code, Hash blockHash, long blockHeight, int category, + bool isSystemContract) + { + if (!_codeCheckOptions.CodeCheckEnabled) + return true; - public async Task PerformCodeCheckAsync(byte[] code, Hash blockHash, long blockHeight, int category, bool isSystemContract) + var requiredAcs = + await _requiredAcsProvider.GetRequiredAcsInContractsAsync(blockHash, blockHeight); + try { - if (!_codeCheckOptions.CodeCheckEnabled) - return true; - - var requiredAcs = - await _requiredAcsProvider.GetRequiredAcsInContractsAsync(blockHash, blockHeight); - try - { - // Check contract code - Logger.LogTrace("Start code check."); - if (!_contractAuditorContainer.TryGetContractAuditor(category, out var contractAuditor)) - { - Logger.LogWarning($"Unrecognized contract category: {category}"); - return false; - } - - contractAuditor.Audit(code, requiredAcs, isSystemContract); - Logger.LogTrace("Finish code check."); - return true; - } - catch (InvalidCodeException e) + // Check contract code + Logger.LogTrace("Start code check"); + if (!_contractAuditorContainer.TryGetContractAuditor(category, out var contractAuditor)) { - // May do something else to indicate that the contract has an issue - Logger.LogWarning(e.Message); + Logger.LogWarning("Unrecognized contract category: {Category}", category); + return false; } - return false; + contractAuditor.Audit(code, requiredAcs, isSystemContract); + Logger.LogTrace("Finish code check"); + return true; } + catch (InvalidCodeException e) + { + // May do something else to indicate that the contract has an issue + Logger.LogWarning("{ExceptionMessage}", e.Message); + } + + return false; } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Application/CodeCheckValidationProvider.cs b/src/AElf.Kernel.CodeCheck/Application/CodeCheckValidationProvider.cs index 4017b123e5..0d772880e4 100644 --- a/src/AElf.Kernel.CodeCheck/Application/CodeCheckValidationProvider.cs +++ b/src/AElf.Kernel.CodeCheck/Application/CodeCheckValidationProvider.cs @@ -1,79 +1,69 @@ using System.Linq; -using System.Threading.Tasks; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Standards.ACS0; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -namespace AElf.Kernel.CodeCheck.Application +namespace AElf.Kernel.CodeCheck.Application; + +internal class CodeCheckValidationProvider : IBlockValidationProvider { - internal class CodeCheckValidationProvider : IBlockValidationProvider + private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; + private readonly IContractReaderFactory _contractReaderFactory; + private readonly ISmartContractAddressService _smartContractAddressService; + + public CodeCheckValidationProvider(ISmartContractAddressService smartContractAddressService, + IContractReaderFactory contractReaderFactory, + ICheckedCodeHashProvider checkedCodeHashProvider, + IOptionsSnapshot codeCheckOptions) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IContractReaderFactory _contractReaderFactory; - private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; - private readonly CodeCheckOptions _codeCheckOptions; + _smartContractAddressService = smartContractAddressService; + _contractReaderFactory = contractReaderFactory; + _checkedCodeHashProvider = checkedCodeHashProvider; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public CodeCheckValidationProvider(ISmartContractAddressService smartContractAddressService, - IContractReaderFactory contractReaderFactory, - ICheckedCodeHashProvider checkedCodeHashProvider, - IOptionsSnapshot codeCheckOptions) - { - _smartContractAddressService = smartContractAddressService; - _contractReaderFactory = contractReaderFactory; - _checkedCodeHashProvider = checkedCodeHashProvider; - _codeCheckOptions = codeCheckOptions.Value; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(true); + } + + public Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + return Task.FromResult(true); + } - public Task ValidateBeforeAttachAsync(IBlock block) + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) return true; + + var genesisContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); + var deployedBloom = new ContractDeployed().ToLogEvent(genesisContractAddress).GetBloom(); + if (!deployedBloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray()))) return true; + + var blockHash = block.GetHash(); + var codeHashList = await _contractReaderFactory.Create(new ContractReaderContext { - return Task.FromResult(true); - } + BlockHash = blockHash, + BlockHeight = block.Header.Height, + ContractAddress = genesisContractAddress + }).GetContractCodeHashListByDeployingBlockHeight.CallAsync(new Int64Value { Value = block.Header.Height }); - public Task ValidateBlockBeforeExecuteAsync(IBlock block) + if (codeHashList == null || !codeHashList.Value.Any()) { - return Task.FromResult(true); + Logger.LogInformation("CodeHashList is empty."); + return true; } - public async Task ValidateBlockAfterExecuteAsync(IBlock block) + Logger.LogInformation("block hash: {Block}", block); + return codeHashList.Value.All(codeHash => _checkedCodeHashProvider.IsCodeHashExists(new BlockIndex { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) - { - return true; - } - - var genesisContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - var deployedBloom = new ContractDeployed().ToLogEvent(genesisContractAddress).GetBloom(); - if (!deployedBloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray()))) return true; - - var blockHash = block.GetHash(); - var codeHashList = await _contractReaderFactory.Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = block.Header.Height, - ContractAddress = genesisContractAddress - }).GetContractCodeHashListByDeployingBlockHeight.CallAsync(new Int64Value { Value = block.Header.Height }); - - if (codeHashList == null || !codeHashList.Value.Any()) - { - Logger.LogInformation($"CodeHashList is empty."); - return true; - } - - Logger.LogInformation($"block hash: {block}"); - return codeHashList.Value.All(codeHash => _checkedCodeHashProvider.IsCodeHashExists(new BlockIndex - { - BlockHash = blockHash, - BlockHeight = block.Header.Height - }, codeHash)); - } + BlockHash = blockHash, + BlockHeight = block.Header.Height + }, codeHash)); } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Application/ICheckedCodeHashProvider.cs b/src/AElf.Kernel.CodeCheck/Application/ICheckedCodeHashProvider.cs index cbc7792981..ac8ccc666a 100644 --- a/src/AElf.Kernel.CodeCheck/Application/ICheckedCodeHashProvider.cs +++ b/src/AElf.Kernel.CodeCheck/Application/ICheckedCodeHashProvider.cs @@ -1,69 +1,57 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Application; using AElf.Standards.ACS0; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.CodeCheck.Application +namespace AElf.Kernel.CodeCheck.Application; + +public interface ICheckedCodeHashProvider { - public interface ICheckedCodeHashProvider - { - Task AddCodeHashAsync(BlockIndex blockIndex, Hash codeHash); - bool IsCodeHashExists(BlockIndex blockIndex, Hash codeHash); - Task RemoveCodeHashAsync(BlockIndex blockIndex, long libHeight); - } + Task AddCodeHashAsync(BlockIndex blockIndex, Hash codeHash); + bool IsCodeHashExists(BlockIndex blockIndex, Hash codeHash); + Task RemoveCodeHashAsync(BlockIndex blockIndex, long libHeight); +} - internal class CheckedCodeHashProvider : BlockExecutedDataBaseProvider, - ICheckedCodeHashProvider, ISingletonDependency +internal class CheckedCodeHashProvider : BlockExecutedDataBaseProvider, + ICheckedCodeHashProvider, ISingletonDependency +{ + public CheckedCodeHashProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : + base(cachedBlockchainExecutedDataService) { - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public CheckedCodeHashProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : - base(cachedBlockchainExecutedDataService) - { - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task AddCodeHashAsync(BlockIndex blockIndex, Hash codeHash) - { - Logger.LogInformation($"Added code hash: {blockIndex}"); - var codeHashMap = GetBlockExecutedData(blockIndex) ?? new ContractCodeHashMap(); - codeHashMap.TryAdd(blockIndex.BlockHeight, codeHash); - await AddBlockExecutedDataAsync(blockIndex, codeHashMap); - } + public async Task AddCodeHashAsync(BlockIndex blockIndex, Hash codeHash) + { + Logger.LogInformation($"Added code hash: {blockIndex}"); + var codeHashMap = GetBlockExecutedData(blockIndex) ?? new ContractCodeHashMap(); + codeHashMap.TryAdd(blockIndex.BlockHeight, codeHash); + await AddBlockExecutedDataAsync(blockIndex, codeHashMap); + } - public bool IsCodeHashExists(BlockIndex blockIndex, Hash codeHash) - { - var codeHashMap = GetBlockExecutedData(blockIndex); - if (codeHashMap == null) - { - return false; - } + public bool IsCodeHashExists(BlockIndex blockIndex, Hash codeHash) + { + var codeHashMap = GetBlockExecutedData(blockIndex); + if (codeHashMap == null) return false; - var result = codeHashMap.ContainsValue(codeHash); - Logger.LogInformation($"Is {codeHash} exists in height {blockIndex.BlockHeight}: {result}"); - return result; - } + var result = codeHashMap.ContainsValue(codeHash); + Logger.LogInformation($"Is {codeHash} exists in height {blockIndex.BlockHeight}: {result}"); + return result; + } - public async Task RemoveCodeHashAsync(BlockIndex blockIndex, long libHeight) - { - Logger.LogInformation($"Removing code hash list below height {libHeight}"); - var codeHashMap = GetBlockExecutedData(blockIndex); - if (codeHashMap == null) - { - return; - } + public async Task RemoveCodeHashAsync(BlockIndex blockIndex, long libHeight) + { + Logger.LogInformation($"Removing code hash list below height {libHeight}"); + var codeHashMap = GetBlockExecutedData(blockIndex); + if (codeHashMap == null) return; - codeHashMap.RemoveValuesBeforeLibHeight(libHeight); - await AddBlockExecutedDataAsync(blockIndex, codeHashMap); - } + codeHashMap.RemoveValuesBeforeLibHeight(libHeight); + await AddBlockExecutedDataAsync(blockIndex, codeHashMap); + } - protected override string GetBlockExecutedDataName() - { - return nameof(ContractCodeHashMap); - } + protected override string GetBlockExecutedDataName() + { + return nameof(ContractCodeHashMap); } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Application/ICodeCheckService.cs b/src/AElf.Kernel.CodeCheck/Application/ICodeCheckService.cs index abf038669c..10f3e5013b 100644 --- a/src/AElf.Kernel.CodeCheck/Application/ICodeCheckService.cs +++ b/src/AElf.Kernel.CodeCheck/Application/ICodeCheckService.cs @@ -1,10 +1,7 @@ -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.CodeCheck.Application; -namespace AElf.Kernel.CodeCheck.Application +public interface ICodeCheckService { - public interface ICodeCheckService - { - Task PerformCodeCheckAsync(byte[] code, Hash blockHash, long blockHeight, int category, bool isSystemContract); - } + Task PerformCodeCheckAsync(byte[] code, Hash blockHash, long blockHeight, int category, + bool isSystemContract); } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/CodeCheckAElfModule.cs b/src/AElf.Kernel.CodeCheck/CodeCheckAElfModule.cs index 6c6b10179f..8ed8995a70 100644 --- a/src/AElf.Kernel.CodeCheck/CodeCheckAElfModule.cs +++ b/src/AElf.Kernel.CodeCheck/CodeCheckAElfModule.cs @@ -6,17 +6,16 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +public class CodeCheckAElfModule : AElfModule { - public class CodeCheckAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services - .AddSingleton(); - //context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services + .AddSingleton(); + //context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/CodeCheckOptions.cs b/src/AElf.Kernel.CodeCheck/CodeCheckOptions.cs index 395cec0f12..f16005729f 100644 --- a/src/AElf.Kernel.CodeCheck/CodeCheckOptions.cs +++ b/src/AElf.Kernel.CodeCheck/CodeCheckOptions.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +public class CodeCheckOptions { - public class CodeCheckOptions - { - public bool CodeCheckEnabled { get; set; } - } + public bool CodeCheckEnabled { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/CodeCheckRequiredLogEventProcessor.cs b/src/AElf.Kernel.CodeCheck/CodeCheckRequiredLogEventProcessor.cs index bc59e4b7f5..f2f0db5e21 100644 --- a/src/AElf.Kernel.CodeCheck/CodeCheckRequiredLogEventProcessor.cs +++ b/src/AElf.Kernel.CodeCheck/CodeCheckRequiredLogEventProcessor.cs @@ -1,88 +1,82 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using AElf.Types; -using AElf.Standards.ACS0; -using AElf.Standards.ACS3; +using AElf.CSharp.Core.Extension; using AElf.Kernel.CodeCheck.Application; using AElf.Kernel.Proposal.Application; -using AElf.CSharp.Core.Extension; using AElf.Kernel.SmartContract.Application; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +public class CodeCheckRequiredLogEventProcessor : LogEventProcessorBase, IBlocksExecutionSucceededLogEventProcessor { - public class CodeCheckRequiredLogEventProcessor : LogEventProcessorBase, IBlocksExecutionSucceededLogEventProcessor + private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; + private readonly ICodeCheckService _codeCheckService; + private readonly IProposalService _proposalService; + private readonly ISmartContractAddressService _smartContractAddressService; + + public CodeCheckRequiredLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ICodeCheckService codeCheckService, IProposalService proposalService, + ICheckedCodeHashProvider checkedCodeHashProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ICodeCheckService _codeCheckService; - private readonly IProposalService _proposalService; - private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; - public ILogger Logger { get; set; } + _smartContractAddressService = smartContractAddressService; + _codeCheckService = codeCheckService; + _proposalService = proposalService; + _checkedCodeHashProvider = checkedCodeHashProvider; - public CodeCheckRequiredLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ICodeCheckService codeCheckService, IProposalService proposalService, - ICheckedCodeHashProvider checkedCodeHashProvider) - { - _smartContractAddressService = smartContractAddressService; - _codeCheckService = codeCheckService; - _proposalService = proposalService; - _checkedCodeHashProvider = checkedCodeHashProvider; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public override Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return Task.FromResult(InterestedEvent); + public override Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return Task.FromResult(InterestedEvent); - var address = _smartContractAddressService.GetZeroSmartContractAddress(); - if (address == null) return null; + var address = _smartContractAddressService.GetZeroSmartContractAddress(); + if (address == null) return null; - InterestedEvent = GetInterestedEvent(address); + InterestedEvent = GetInterestedEvent(address); - return Task.FromResult(InterestedEvent); - } + return Task.FromResult(InterestedEvent); + } - public override Task ProcessAsync(Block block, Dictionary> logEventsMap) + public override Task ProcessAsync(Block block, Dictionary> logEventsMap) + { + Logger.LogInformation("Start handling CodeCheckRequired log event."); + foreach (var events in logEventsMap) { - Logger.LogInformation("Start handling CodeCheckRequired log event."); - foreach (var events in logEventsMap) - { - var transactionResult = events.Key; - foreach (var logEvent in events.Value) + var transactionResult = events.Key; + foreach (var logEvent in events.Value) + // a new task for time-consuming code check job + Task.Run(async () => { - // a new task for time-consuming code check job - Task.Run(async () => - { - var eventData = new CodeCheckRequired(); - eventData.MergeFrom(logEvent); - var codeCheckResult = await _codeCheckService.PerformCodeCheckAsync( - eventData.Code.ToByteArray(), - transactionResult.BlockHash, transactionResult.BlockNumber, eventData.Category, - eventData.IsSystemContract); - Logger.LogInformation($"Code check result: {codeCheckResult}"); - if (!codeCheckResult) - return; - - var proposalId = ProposalCreated.Parser - .ParseFrom(transactionResult.Logs.First(l => l.Name == nameof(ProposalCreated)).NonIndexed) - .ProposalId; - // Cache proposal id to generate system approval transaction later - _proposalService.AddNotApprovedProposal(proposalId, transactionResult.BlockNumber); + var eventData = new CodeCheckRequired(); + eventData.MergeFrom(logEvent); + var codeCheckResult = await _codeCheckService.PerformCodeCheckAsync( + eventData.Code.ToByteArray(), + transactionResult.BlockHash, transactionResult.BlockNumber, eventData.Category, + eventData.IsSystemContract); + Logger.LogInformation($"Code check result: {codeCheckResult}"); + if (!codeCheckResult) + return; - await _checkedCodeHashProvider.AddCodeHashAsync(new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, HashHelper.ComputeFrom(eventData.Code.ToByteArray())); - }); - } - } + var proposalId = ProposalCreated.Parser + .ParseFrom(transactionResult.Logs.First(l => l.Name == nameof(ProposalCreated)).NonIndexed) + .ProposalId; + // Cache proposal id to generate system approval transaction later + _proposalService.AddNotApprovedProposal(proposalId, transactionResult.BlockNumber); - return Task.CompletedTask; + await _checkedCodeHashProvider.AddCodeHashAsync(new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }, HashHelper.ComputeFrom(eventData.Code.ToByteArray())); + }); } + + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/ContractCodeHashMap.cs b/src/AElf.Kernel.CodeCheck/ContractCodeHashMap.cs index 2de809de98..329f6cca7e 100644 --- a/src/AElf.Kernel.CodeCheck/ContractCodeHashMap.cs +++ b/src/AElf.Kernel.CodeCheck/ContractCodeHashMap.cs @@ -1,38 +1,33 @@ using System.Linq; -using AElf.Types; -namespace AElf.Standards.ACS0 +namespace AElf.Standards.ACS0; + +internal partial class ContractCodeHashMap { - internal partial class ContractCodeHashMap + public void TryAdd(long blockHeight, Hash codeHash) { - public void TryAdd(long blockHeight, Hash codeHash) + if (Value.ContainsKey(blockHeight)) { - if (Value.ContainsKey(blockHeight)) - { - var hashList = Value[blockHeight]; - hashList.Value.Add(codeHash); - Value[blockHeight] = hashList; - } - else - { - Value[blockHeight] = new ContractCodeHashList - { - Value = { codeHash } - }; - } + var hashList = Value[blockHeight]; + hashList.Value.Add(codeHash); + Value[blockHeight] = hashList; } - - public bool ContainsValue(Hash codeHash) - { - return Value.Values.SelectMany(l => l.Value).Contains(codeHash); - } - - public void RemoveValuesBeforeLibHeight(long libHeight) + else { - foreach (var key in Value.Keys.Where(k => k <= libHeight)) + Value[blockHeight] = new ContractCodeHashList { - Value.Remove(key); - } + Value = { codeHash } + }; } } + + public bool ContainsValue(Hash codeHash) + { + return Value.Values.SelectMany(l => l.Value).Contains(codeHash); + } + + public void RemoveValuesBeforeLibHeight(long libHeight) + { + foreach (var key in Value.Keys.Where(k => k <= libHeight)) Value.Remove(key); + } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/ContractDeployedLogEventProcessor.cs b/src/AElf.Kernel.CodeCheck/ContractDeployedLogEventProcessor.cs index 0a937ae3e4..bdfebb82e5 100644 --- a/src/AElf.Kernel.CodeCheck/ContractDeployedLogEventProcessor.cs +++ b/src/AElf.Kernel.CodeCheck/ContractDeployedLogEventProcessor.cs @@ -1,55 +1,51 @@ -using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Kernel.SmartContract.Application; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using AElf.CSharp.Core.Extension; using AElf.Kernel.CodeCheck.Application; +using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +/// +/// Maybe not useful. +/// +public class ContractDeployedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - /// - /// Maybe not useful. - /// - public class ContractDeployedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ContractDeployedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ICheckedCodeHashProvider checkedCodeHashProvider) { - private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; - private readonly ISmartContractAddressService _smartContractAddressService; - public ILogger Logger { get; set; } + _checkedCodeHashProvider = checkedCodeHashProvider; + _smartContractAddressService = smartContractAddressService; - public ContractDeployedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ICheckedCodeHashProvider checkedCodeHashProvider) - { - _checkedCodeHashProvider = checkedCodeHashProvider; - _smartContractAddressService = smartContractAddressService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public override Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return Task.FromResult(InterestedEvent); + public override Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return Task.FromResult(InterestedEvent); - var address = _smartContractAddressService.GetZeroSmartContractAddress(); - if (address == null) return null; + var address = _smartContractAddressService.GetZeroSmartContractAddress(); + if (address == null) return null; - InterestedEvent = GetInterestedEvent(address); + InterestedEvent = GetInterestedEvent(address); - return Task.FromResult(InterestedEvent); - } + return Task.FromResult(InterestedEvent); + } + + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var eventData = new ContractDeployed(); + eventData.MergeFrom(logEvent); - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + await _checkedCodeHashProvider.AddCodeHashAsync(new BlockIndex { - var eventData = new ContractDeployed(); - eventData.MergeFrom(logEvent); - - await _checkedCodeHashProvider.AddCodeHashAsync(new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, eventData.CodeHash); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }, eventData.CodeHash); } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Exception/InvalidCodeException.cs b/src/AElf.Kernel.CodeCheck/Exception/InvalidCodeException.cs index 448b985dd3..b34f8229bc 100644 --- a/src/AElf.Kernel.CodeCheck/Exception/InvalidCodeException.cs +++ b/src/AElf.Kernel.CodeCheck/Exception/InvalidCodeException.cs @@ -1,15 +1,14 @@ using System; -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +public class InvalidCodeException : Exception { - public class InvalidCodeException : Exception + public InvalidCodeException() { - public InvalidCodeException() - { - } + } - public InvalidCodeException(string message) : base(message) - { - } + public InvalidCodeException(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/GlobalUsings.cs b/src/AElf.Kernel.CodeCheck/GlobalUsings.cs new file mode 100644 index 0000000000..96a5be2eb4 --- /dev/null +++ b/src/AElf.Kernel.CodeCheck/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using AElf.Types; +global using System.Threading.Tasks; +global using Volo.Abp.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging.Abstractions; +global using Microsoft.Extensions.Options; \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditor.cs b/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditor.cs index 23ef6dd148..87d4386a91 100644 --- a/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditor.cs +++ b/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditor.cs @@ -1,15 +1,14 @@ using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Infrastructure; -namespace AElf.Kernel.CodeCheck.Infrastructure +namespace AElf.Kernel.CodeCheck.Infrastructure; + +public interface IContractAuditor : ISmartContractCategoryProvider { - public interface IContractAuditor : ISmartContractCategoryProvider - { - void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract); - } + void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract); +} - public interface IContractPatcher : ISmartContractCategoryProvider - { - byte[] Patch(byte[] code, bool isSystemContract); - } +public interface IContractPatcher : ISmartContractCategoryProvider +{ + byte[] Patch(byte[] code, bool isSystemContract); } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditorContainer.cs b/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditorContainer.cs index fb014c6c2a..7a7c4f2271 100644 --- a/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditorContainer.cs +++ b/src/AElf.Kernel.CodeCheck/Infrastructure/IContractAuditorContainer.cs @@ -1,29 +1,24 @@ using System.Collections.Concurrent; using System.Collections.Generic; -namespace AElf.Kernel.CodeCheck.Infrastructure +namespace AElf.Kernel.CodeCheck.Infrastructure; + +public interface IContractAuditorContainer +{ + bool TryGetContractAuditor(int category, out IContractAuditor contractAuditor); +} + +public class ContractAuditorContainer : IContractAuditorContainer { - public interface IContractAuditorContainer + private readonly ConcurrentDictionary _contractAuditors = new(); + + public ContractAuditorContainer(IEnumerable contractAuditors) { - bool TryGetContractAuditor(int category, out IContractAuditor contractAuditor); + foreach (var auditor in contractAuditors) _contractAuditors[auditor.Category] = auditor; } - public class ContractAuditorContainer : IContractAuditorContainer + public bool TryGetContractAuditor(int category, out IContractAuditor contractAuditor) { - private readonly ConcurrentDictionary _contractAuditors = - new ConcurrentDictionary(); - - public ContractAuditorContainer(IEnumerable contractAuditors) - { - foreach (var auditor in contractAuditors) - { - _contractAuditors[auditor.Category] = auditor; - } - } - - public bool TryGetContractAuditor(int category, out IContractAuditor contractAuditor) - { - return _contractAuditors.TryGetValue(category, out contractAuditor); - } + return _contractAuditors.TryGetValue(category, out contractAuditor); } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Infrastructure/IRequiredAcsProvider.cs b/src/AElf.Kernel.CodeCheck/Infrastructure/IRequiredAcsProvider.cs index 7a04fa981f..215e78d12c 100644 --- a/src/AElf.Kernel.CodeCheck/Infrastructure/IRequiredAcsProvider.cs +++ b/src/AElf.Kernel.CodeCheck/Infrastructure/IRequiredAcsProvider.cs @@ -1,11 +1,8 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract; -using AElf.Types; -namespace AElf.Kernel.CodeCheck.Infrastructure +namespace AElf.Kernel.CodeCheck.Infrastructure; + +public interface IRequiredAcsProvider { - public interface IRequiredAcsProvider - { - Task GetRequiredAcsInContractsAsync(Hash blockHash, long blockHeight); - } + Task GetRequiredAcsInContractsAsync(Hash blockHash, long blockHeight); } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/Infrastructure/RequiredAcsProvider.cs b/src/AElf.Kernel.CodeCheck/Infrastructure/RequiredAcsProvider.cs index 46be30c405..29e2268bf8 100644 --- a/src/AElf.Kernel.CodeCheck/Infrastructure/RequiredAcsProvider.cs +++ b/src/AElf.Kernel.CodeCheck/Infrastructure/RequiredAcsProvider.cs @@ -1,42 +1,38 @@ using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Configuration; using AElf.Kernel.SmartContract; -using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.CodeCheck.Infrastructure +namespace AElf.Kernel.CodeCheck.Infrastructure; + +public class RequiredAcsProvider : IRequiredAcsProvider { - public class RequiredAcsProvider : IRequiredAcsProvider - { - private readonly IConfigurationService _configurationService; + private const string RequiredAcsInContractsConfigurationName = "RequiredAcsInContracts"; + private readonly IConfigurationService _configurationService; - public RequiredAcsProvider(IConfigurationService configurationService) - { - _configurationService = configurationService; - } + public RequiredAcsProvider(IConfigurationService configurationService) + { + _configurationService = configurationService; + } - public async Task GetRequiredAcsInContractsAsync(Hash blockHash, long blockHeight) + public async Task GetRequiredAcsInContractsAsync(Hash blockHash, long blockHeight) + { + var chainContext = new ChainContext { - var chainContext = new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }; + BlockHash = blockHash, + BlockHeight = blockHeight + }; - var returned = - await _configurationService.GetConfigurationDataAsync( - RequiredAcsInContractsConfigurationName, chainContext); + var returned = + await _configurationService.GetConfigurationDataAsync( + RequiredAcsInContractsConfigurationName, chainContext); - var requiredAcsInContracts = new RequiredAcsInContracts(); - requiredAcsInContracts.MergeFrom(returned); - return new RequiredAcs - { - AcsList = requiredAcsInContracts.AcsList.ToList(), - RequireAll = requiredAcsInContracts.RequireAll - }; - } - - private const string RequiredAcsInContractsConfigurationName = "RequiredAcsInContracts"; + var requiredAcsInContracts = new RequiredAcsInContracts(); + requiredAcsInContracts.MergeFrom(returned); + return new RequiredAcs + { + AcsList = requiredAcsInContracts.AcsList.ToList(), + RequireAll = requiredAcsInContracts.RequireAll + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.CodeCheck/NewIrreversibleBlockFoundEventHandler.cs b/src/AElf.Kernel.CodeCheck/NewIrreversibleBlockFoundEventHandler.cs index d650dffbae..a421ec0a3d 100644 --- a/src/AElf.Kernel.CodeCheck/NewIrreversibleBlockFoundEventHandler.cs +++ b/src/AElf.Kernel.CodeCheck/NewIrreversibleBlockFoundEventHandler.cs @@ -1,28 +1,25 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.CodeCheck.Application; -using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.CodeCheck +namespace AElf.Kernel.CodeCheck; + +public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler + //, ITransientDependency // Not remove code hash list for now, hash list won't be so much. { - public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler - //, ITransientDependency // Not remove code hash list for now, hash list won't be so much. - { - private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; + private readonly ICheckedCodeHashProvider _checkedCodeHashProvider; - public NewIrreversibleBlockFoundEventHandler(ICheckedCodeHashProvider checkedCodeHashProvider) - { - _checkedCodeHashProvider = checkedCodeHashProvider; - } + public NewIrreversibleBlockFoundEventHandler(ICheckedCodeHashProvider checkedCodeHashProvider) + { + _checkedCodeHashProvider = checkedCodeHashProvider; + } - public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + await _checkedCodeHashProvider.RemoveCodeHashAsync(new BlockIndex { - await _checkedCodeHashProvider.RemoveCodeHashAsync(new BlockIndex - { - BlockHash = eventData.BlockHash, - BlockHeight = eventData.BlockHeight - }, eventData.PreviousIrreversibleBlockHeight); - } + BlockHash = eventData.BlockHash, + BlockHeight = eventData.BlockHeight + }, eventData.PreviousIrreversibleBlockHeight); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/AElf.Kernel.Configuration.csproj b/src/AElf.Kernel.Configuration/AElf.Kernel.Configuration.csproj index bcab2da439..842741825b 100644 --- a/src/AElf.Kernel.Configuration/AElf.Kernel.Configuration.csproj +++ b/src/AElf.Kernel.Configuration/AElf.Kernel.Configuration.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -14,7 +14,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\acs1.proto @@ -25,6 +25,6 @@ - + \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/ConfigurationAElfModule.cs b/src/AElf.Kernel.Configuration/ConfigurationAElfModule.cs index d931be6844..dec1488789 100644 --- a/src/AElf.Kernel.Configuration/ConfigurationAElfModule.cs +++ b/src/AElf.Kernel.Configuration/ConfigurationAElfModule.cs @@ -3,14 +3,13 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.Configuration +namespace AElf.Kernel.Configuration; + +public class ConfigurationAElfModule : AElfModule { - public class ConfigurationAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services - .AddSingleton(); - } + context.Services + .AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/ConfigurationContractInitializationProvider.cs b/src/AElf.Kernel.Configuration/ConfigurationContractInitializationProvider.cs index b5ba6e795a..cf0d39156d 100644 --- a/src/AElf.Kernel.Configuration/ConfigurationContractInitializationProvider.cs +++ b/src/AElf.Kernel.Configuration/ConfigurationContractInitializationProvider.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Configuration +namespace AElf.Kernel.Configuration; + +public class ConfigurationContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class ConfigurationContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = ConfigurationSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.Configuration"; + public Hash SystemSmartContractName { get; } = ConfigurationSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.Configuration"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/ConfigurationSetLogEventProcessor.cs b/src/AElf.Kernel.Configuration/ConfigurationSetLogEventProcessor.cs index d10a87762d..a99fa3ba9d 100644 --- a/src/AElf.Kernel.Configuration/ConfigurationSetLogEventProcessor.cs +++ b/src/AElf.Kernel.Configuration/ConfigurationSetLogEventProcessor.cs @@ -1,54 +1,53 @@ using System.Threading.Tasks; -using AElf.Kernel.SmartContract.Application; -using AElf.Types; using AElf.Contracts.Configuration; using AElf.CSharp.Core.Extension; +using AElf.Kernel.SmartContract.Application; +using AElf.Types; + +namespace AElf.Kernel.Configuration; -namespace AElf.Kernel.Configuration +public class ConfigurationSetLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - public class ConfigurationSetLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly IConfigurationService _configurationService; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ConfigurationSetLogEventProcessor(ISmartContractAddressService smartContractAddressService, + IConfigurationService configurationService) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IConfigurationService _configurationService; - - public ConfigurationSetLogEventProcessor(ISmartContractAddressService smartContractAddressService, - IConfigurationService configurationService) - { - _smartContractAddressService = smartContractAddressService; - _configurationService = configurationService; - } - - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; - - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, ConfigurationSmartContractAddressNameProvider.StringName); - - if (smartContractAddressDto == null) return null; - - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - - if (!smartContractAddressDto.Irreversible) return interestedEvent; - - InterestedEvent = interestedEvent; + _smartContractAddressService = smartContractAddressService; + _configurationService = configurationService; + } + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; - } - - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) - { - var configurationSet = new ConfigurationSet(); - configurationSet.MergeFrom(logEvent); - - await _configurationService.ProcessConfigurationAsync(configurationSet.Key, configurationSet.Value, - new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - } + + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, ConfigurationSmartContractAddressNameProvider.StringName); + + if (smartContractAddressDto == null) return null; + + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + + if (!smartContractAddressDto.Irreversible) return interestedEvent; + + InterestedEvent = interestedEvent; + + return InterestedEvent; + } + + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var configurationSet = new ConfigurationSet(); + configurationSet.MergeFrom(logEvent); + + await _configurationService.ProcessConfigurationAsync(configurationSet.Key, configurationSet.Value, + new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/ConfigurationSmartContractAddressNameProvider.cs b/src/AElf.Kernel.Configuration/ConfigurationSmartContractAddressNameProvider.cs index 77592dc784..79772f9f92 100644 --- a/src/AElf.Kernel.Configuration/ConfigurationSmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.Configuration/ConfigurationSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Configuration +namespace AElf.Kernel.Configuration; + +public class ConfigurationSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ConfigurationSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Configuration"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Configuration"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/IConfigurationProcessor.cs b/src/AElf.Kernel.Configuration/IConfigurationProcessor.cs index 46b0160335..7329ffd7f7 100644 --- a/src/AElf.Kernel.Configuration/IConfigurationProcessor.cs +++ b/src/AElf.Kernel.Configuration/IConfigurationProcessor.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; using Google.Protobuf; -namespace AElf.Kernel.Configuration +namespace AElf.Kernel.Configuration; + +public interface IConfigurationProcessor { - public interface IConfigurationProcessor - { - string ConfigurationName { get; } - Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex); - } + string ConfigurationName { get; } + Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex); } \ No newline at end of file diff --git a/src/AElf.Kernel.Configuration/IConfigurationService.cs b/src/AElf.Kernel.Configuration/IConfigurationService.cs index e9ae1f6620..d5f4c87bad 100644 --- a/src/AElf.Kernel.Configuration/IConfigurationService.cs +++ b/src/AElf.Kernel.Configuration/IConfigurationService.cs @@ -7,51 +7,50 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Configuration +namespace AElf.Kernel.Configuration; + +public interface IConfigurationService +{ + Task ProcessConfigurationAsync(string configurationName, ByteString byteString, BlockIndex blockIndex); + Task GetConfigurationDataAsync(string configurationName, ChainContext chainContext); +} + +internal class ConfigurationService : IConfigurationService, ITransientDependency { - public interface IConfigurationService + private readonly List _configurationProcessors; + private readonly IContractReaderFactory _contractReaderFactory; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ConfigurationService(IEnumerable configurationProcessors, + IContractReaderFactory contractReaderFactory, + ISmartContractAddressService smartContractAddressService) { - Task ProcessConfigurationAsync(string configurationName, ByteString byteString, BlockIndex blockIndex); - Task GetConfigurationDataAsync(string configurationName, ChainContext chainContext); + _contractReaderFactory = contractReaderFactory; + _smartContractAddressService = smartContractAddressService; + _configurationProcessors = configurationProcessors.ToList(); } - internal class ConfigurationService : IConfigurationService, ITransientDependency + public async Task ProcessConfigurationAsync(string configurationName, ByteString byteString, BlockIndex blockIndex) { - private readonly List _configurationProcessors; - private readonly IContractReaderFactory _contractReaderFactory; - private readonly ISmartContractAddressService _smartContractAddressService; - - public ConfigurationService(IEnumerable configurationProcessors, - IContractReaderFactory contractReaderFactory, - ISmartContractAddressService smartContractAddressService) - { - _contractReaderFactory = contractReaderFactory; - _smartContractAddressService = smartContractAddressService; - _configurationProcessors = configurationProcessors.ToList(); - } + var configurationProcessor = + _configurationProcessors.FirstOrDefault(c => c.ConfigurationName == configurationName); + if (configurationProcessor == null) + return; + await configurationProcessor.ProcessConfigurationAsync(byteString, blockIndex); + } - public async Task ProcessConfigurationAsync(string configurationName, ByteString byteString, BlockIndex blockIndex) - { - var configurationProcessor = - _configurationProcessors.FirstOrDefault(c => c.ConfigurationName == configurationName); - if (configurationProcessor == null) - return; - await configurationProcessor.ProcessConfigurationAsync(byteString, blockIndex); - } - - public async Task GetConfigurationDataAsync(string configurationName, ChainContext chainContext) - { - var indexedSideChainBlockData = await _contractReaderFactory - .Create(new ContractReaderContext - { - BlockHash = chainContext.BlockHash, - BlockHeight = chainContext.BlockHeight, - ContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - ConfigurationSmartContractAddressNameProvider.StringName) - }) - .GetConfiguration.CallAsync(new StringValue() {Value = configurationName}); + public async Task GetConfigurationDataAsync(string configurationName, ChainContext chainContext) + { + var indexedSideChainBlockData = await _contractReaderFactory + .Create(new ContractReaderContext + { + BlockHash = chainContext.BlockHash, + BlockHeight = chainContext.BlockHeight, + ContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + ConfigurationSmartContractAddressNameProvider.StringName) + }) + .GetConfiguration.CallAsync(new StringValue { Value = configurationName }); - return indexedSideChainBlockData.Value; - } + return indexedSideChainBlockData.Value; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSAElfModule.cs b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSAElfModule.cs index becd08d28a..d229437d5c 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSAElfModule.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSAElfModule.cs @@ -3,9 +3,7 @@ using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Kernel.Consensus.Application; using AElf.Kernel.Consensus.Scheduler.RxNet; -using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Configuration; @@ -13,62 +11,61 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +[DependsOn( + typeof(RxNetSchedulerAElfModule), + typeof(CoreConsensusAElfModule) +)] +// ReSharper disable once InconsistentNaming +public class AEDPoSAElfModule : AElfModule { - [DependsOn( - typeof(RxNetSchedulerAElfModule), - typeof(CoreConsensusAElfModule) - )] - // ReSharper disable once InconsistentNaming - public class AEDPoSAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - // ITriggerInformationProvider is for generating some necessary information - // to trigger consensus hints from consensus contract. - context.Services.AddSingleton(); + // ITriggerInformationProvider is for generating some necessary information + // to trigger consensus hints from consensus contract. + context.Services.AddSingleton(); - // IConsensusExtraDataExtractor is for extracting consensus data from extra data in Block Header. - context.Services.AddTransient(); + // IConsensusExtraDataExtractor is for extracting consensus data from extra data in Block Header. + context.Services.AddTransient(); - // IBroadcastPrivilegedPubkeyListProvider is just a helper for network module - // to broadcast blocks to nodes of higher priority. - context.Services - .AddSingleton(); + // IBroadcastPrivilegedPubkeyListProvider is just a helper for network module + // to broadcast blocks to nodes of higher priority. + context.Services + .AddSingleton(); - context.Services.AddSingleton(); - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - - // Our purpose is that other modules won't sense which consensus protocol are using, - // thus we read the configuration of ConsensusOption here. - // (ConsensusOption itself can support all kinds of consensus protocol via adding more properties.) - var configuration = context.Services.GetConfiguration(); - Configure(option => - { - var consensusOptions = configuration.GetSection("Consensus"); - consensusOptions.Bind(option); + context.Services + .AddSingleton(); + context.Services + .AddSingleton(); + context.Services + .AddSingleton(); + context.Services.AddSingleton(); - var startTimeStamp = consensusOptions["StartTimestamp"]; - option.StartTimestamp = new Timestamp - { - Seconds = string.IsNullOrEmpty(startTimeStamp) ? 0 : long.Parse(startTimeStamp) - }; + // Our purpose is that other modules won't sense which consensus protocol are using, + // thus we read the configuration of ConsensusOption here. + // (ConsensusOption itself can support all kinds of consensus protocol via adding more properties.) + var configuration = context.Services.GetConfiguration(); + Configure(option => + { + var consensusOptions = configuration.GetSection("Consensus"); + consensusOptions.Bind(option); + + var startTimeStamp = consensusOptions["StartTimestamp"]; + option.StartTimestamp = new Timestamp + { + Seconds = string.IsNullOrEmpty(startTimeStamp) ? 0 : long.Parse(startTimeStamp) + }; - if (option.InitialMinerList == null || option.InitialMinerList.Count == 0 || - string.IsNullOrWhiteSpace(option.InitialMinerList[0])) + if (option.InitialMinerList == null || option.InitialMinerList.Count == 0 || + string.IsNullOrWhiteSpace(option.InitialMinerList[0])) + // If InitialMinerList isn't configured yet, then read AccountService and config current user as single initial miner. + AsyncHelper.RunSync(async () => { - // If InitialMinerList isn't configured yet, then read AccountService and config current user as single initial miner. - AsyncHelper.RunSync(async () => - { - var accountService = context.Services.GetRequiredServiceLazy().Value; - var publicKey = (await accountService.GetPublicKeyAsync()).ToHex(); - option.InitialMinerList = new List {publicKey}; - }); - } - }); - } + var accountService = context.Services.GetRequiredServiceLazy().Value; + var publicKey = (await accountService.GetPublicKeyAsync()).ToHex(); + option.InitialMinerList = new List { publicKey }; + }); + }); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationDataProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationDataProvider.cs index f0f93112eb..cc5d4ff80c 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationDataProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationDataProvider.cs @@ -1,28 +1,27 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +public class AEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider, + ITransientDependency { - public class AEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider, - ITransientDependency - { - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; - public AEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions) - { - _consensusOptions = consensusOptions.Value; - } + public AEDPoSContractInitializationDataProvider(IOptionsSnapshot consensusOptions) + { + _consensusOptions = consensusOptions.Value; + } - public AEDPoSContractInitializationData GetContractInitializationData() + public AEDPoSContractInitializationData GetContractInitializationData() + { + return new AEDPoSContractInitializationData { - return new AEDPoSContractInitializationData - { - MiningInterval = _consensusOptions.MiningInterval, - PeriodSeconds = _consensusOptions.PeriodSeconds, - StartTimestamp = _consensusOptions.StartTimestamp, - InitialMinerList = _consensusOptions.InitialMinerList, - MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval - }; - } + MiningInterval = _consensusOptions.MiningInterval, + PeriodSeconds = _consensusOptions.PeriodSeconds, + StartTimestamp = _consensusOptions.StartTimestamp, + InitialMinerList = _consensusOptions.InitialMinerList, + MinerIncreaseInterval = _consensusOptions.MinerIncreaseInterval + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationProvider.cs index 464f3402d3..38d31a44ac 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/AEDPoSContractInitializationProvider.cs @@ -4,50 +4,51 @@ using AElf.Kernel.SmartContract.Application; using AElf.Types; using Google.Protobuf; -using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public class AEDPoSContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - // ReSharper disable once InconsistentNaming - public class AEDPoSContractInitializationProvider : IContractInitializationProvider, ITransientDependency + private readonly IAEDPoSContractInitializationDataProvider _aedPoSContractInitializationDataProvider; + + public AEDPoSContractInitializationProvider( + IAEDPoSContractInitializationDataProvider aedPoSContractInitializationDataProvider) { - private readonly IAEDPoSContractInitializationDataProvider _aedPoSContractInitializationDataProvider; - public Hash SystemSmartContractName => ConsensusSmartContractAddressNameProvider.Name; - public string ContractCodeName => "AElf.Contracts.Consensus.AEDPoS"; + _aedPoSContractInitializationDataProvider = aedPoSContractInitializationDataProvider; + } - public AEDPoSContractInitializationProvider( - IAEDPoSContractInitializationDataProvider aedPoSContractInitializationDataProvider) - { - _aedPoSContractInitializationDataProvider = aedPoSContractInitializationDataProvider; - } + public Hash SystemSmartContractName => ConsensusSmartContractAddressNameProvider.Name; + public string ContractCodeName => "AElf.Contracts.Consensus.AEDPoS"; - public List GetInitializeMethodList(byte[] contractCode) + public List GetInitializeMethodList(byte[] contractCode) + { + var initializationData = _aedPoSContractInitializationDataProvider.GetContractInitializationData(); + return new List { - var initializationData = _aedPoSContractInitializationDataProvider.GetContractInitializationData(); - return new List + new() { - new ContractInitializationMethodCall{ - MethodName = nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), - Params = new InitialAElfConsensusContractInput - { - PeriodSeconds = initializationData.PeriodSeconds, - MinerIncreaseInterval = initializationData.MinerIncreaseInterval, - IsSideChain = initializationData.IsSideChain - }.ToByteString() - }, - new ContractInitializationMethodCall{ - MethodName = nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), - Params = new MinerList + MethodName = nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), + Params = new InitialAElfConsensusContractInput + { + PeriodSeconds = initializationData.PeriodSeconds, + MinerIncreaseInterval = initializationData.MinerIncreaseInterval, + IsSideChain = initializationData.IsSideChain + }.ToByteString() + }, + new() + { + MethodName = nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), + Params = new MinerList + { + Pubkeys = { - Pubkeys = - { - initializationData.InitialMinerList.Select(ByteStringHelper.FromHexString) - } - }.GenerateFirstRoundOfNewTerm(initializationData.MiningInterval, - initializationData.StartTimestamp.ToDateTime()).ToByteString() - } - }; - } + initializationData.InitialMinerList.Select(ByteStringHelper.FromHexString) + } + }.GenerateFirstRoundOfNewTerm(initializationData.MiningInterval, + initializationData.StartTimestamp.ToDateTime()).ToByteString() + } + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj b/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj index a8e0e6977c..beb55cf877 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj +++ b/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -15,7 +15,7 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBlockTimeProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBlockTimeProvider.cs index 33c066ca2a..6c0abdcdb2 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBlockTimeProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBlockTimeProvider.cs @@ -6,35 +6,32 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public class AEDPoSBlockTimeProvider : IBlockTimeProvider, ISingletonDependency { - public class AEDPoSBlockTimeProvider : IBlockTimeProvider, ISingletonDependency - { - private readonly MemoryCache _blockTimeCache; - private readonly ConsensusOptions _consensusOptions; + private readonly MemoryCache _blockTimeCache; + private readonly ConsensusOptions _consensusOptions; - public AEDPoSBlockTimeProvider(IOptionsSnapshot consensusOptions) + public AEDPoSBlockTimeProvider(IOptionsSnapshot consensusOptions) + { + _consensusOptions = consensusOptions.Value; + _blockTimeCache = new MemoryCache(new MemoryCacheOptions { - _consensusOptions = consensusOptions.Value; - _blockTimeCache = new MemoryCache(new MemoryCacheOptions - { - ExpirationScanFrequency = TimeSpan.FromMilliseconds(_consensusOptions.MiningInterval) - }); - } + ExpirationScanFrequency = TimeSpan.FromMilliseconds(_consensusOptions.MiningInterval) + }); + } - public Timestamp GetBlockTime(Hash blockHash) - { - if (blockHash != null && _blockTimeCache.TryGetValue(blockHash, out var blockTime)) - { - return blockTime as Timestamp; - } + public Timestamp GetBlockTime(Hash blockHash) + { + if (blockHash != null && _blockTimeCache.TryGetValue(blockHash, out var blockTime)) + return blockTime as Timestamp; - return new Timestamp(); - } + return new Timestamp(); + } - public void SetBlockTime(Timestamp blockTime, Hash blockHash) - { - _blockTimeCache.Set(blockHash, blockTime, TimeSpan.FromMilliseconds(_consensusOptions.MiningInterval)); - } + public void SetBlockTime(Timestamp blockTime, Hash blockHash) + { + _blockTimeCache.Set(blockHash, blockTime, TimeSpan.FromMilliseconds(_consensusOptions.MiningInterval)); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBroadcastPrivilegedPubkeyListProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBroadcastPrivilegedPubkeyListProvider.cs index 9e4f63d4b3..7aeaa85d94 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBroadcastPrivilegedPubkeyListProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSBroadcastPrivilegedPubkeyListProvider.cs @@ -8,60 +8,57 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +// ReSharper disable once InconsistentNaming +public class AEDPoSBroadcastPrivilegedPubkeyListProvider : IBroadcastPrivilegedPubkeyListProvider { - // ReSharper disable once InconsistentNaming - public class AEDPoSBroadcastPrivilegedPubkeyListProvider : IBroadcastPrivilegedPubkeyListProvider + private readonly IAccountService _accountService; + private readonly IBlockExtraDataService _blockExtraDataService; + private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; + + public AEDPoSBroadcastPrivilegedPubkeyListProvider(IBlockExtraDataService blockExtraDataService, + IAccountService accountService, IConsensusExtraDataProvider consensusExtraDataProvider) { - private readonly IBlockExtraDataService _blockExtraDataService; - private readonly IAccountService _accountService; - private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; + _blockExtraDataService = blockExtraDataService; + _accountService = accountService; + _consensusExtraDataProvider = consensusExtraDataProvider; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public AEDPoSBroadcastPrivilegedPubkeyListProvider(IBlockExtraDataService blockExtraDataService, - IAccountService accountService, IConsensusExtraDataProvider consensusExtraDataProvider) - { - _blockExtraDataService = blockExtraDataService; - _accountService = accountService; - _consensusExtraDataProvider = consensusExtraDataProvider; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public async Task> GetPubkeyList(BlockHeader blockHeader) + { + var consensusExtraData = + _blockExtraDataService.GetExtraDataFromBlockHeader(_consensusExtraDataProvider.BlockHeaderExtraDataKey, + blockHeader); + if (consensusExtraData == null) return new List(); + var consensusInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(consensusExtraData); + if (consensusInformation.Behaviour == AElfConsensusBehaviour.TinyBlock) + // The orders changed every round, and the orders can be updated during every behaviour of UPDATE_VALUE or NEXT_ROUND, + // so we can skip the update for TINY_BLOCK. + return new List(); - public async Task> GetPubkeyList(BlockHeader blockHeader) + var round = consensusInformation.Round; + var currentPubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); + var minersCount = round.RealTimeMinersInformation.Count; + if (round.RealTimeMinersInformation.Values.Any(m => m.OutValue != null) && + round.RealTimeMinersInformation.ContainsKey(currentPubkey)) { - var consensusExtraData = - _blockExtraDataService.GetExtraDataFromBlockHeader(_consensusExtraDataProvider.BlockHeaderExtraDataKey, - blockHeader); - if (consensusExtraData == null) return new List(); - var consensusInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(consensusExtraData); - if (consensusInformation.Behaviour == AElfConsensusBehaviour.TinyBlock) - { - // The orders changed every round, and the orders can be updated during every behaviour of UPDATE_VALUE or NEXT_ROUND, - // so we can skip the update for TINY_BLOCK. - return new List(); - } - - var round = consensusInformation.Round; - var currentPubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); - var minersCount = round.RealTimeMinersInformation.Count; - if (round.RealTimeMinersInformation.Values.Any(m => m.OutValue != null) && - round.RealTimeMinersInformation.ContainsKey(currentPubkey)) - { - // If any miner mined blocks during current round. - var currentMiner = - round.RealTimeMinersInformation.Values.Single(m => m.Pubkey == currentPubkey); - var currentOrder = currentMiner.Order; - var ebp = round.RealTimeMinersInformation.Values.Single(m => m.IsExtraBlockProducer).Pubkey; - if (currentOrder >= minersCount) return new List {ebp}; - var nextMiners = round.RealTimeMinersInformation.Values.Where(m => m.Order > currentOrder) - .OrderBy(m => m.Order).Select(m => m.Pubkey).ToList(); - nextMiners.AddIfNotContains(ebp); - return nextMiners; - } - - return round.RealTimeMinersInformation.Values.OrderBy(m => m.Order).Select(m => m.Pubkey).ToList(); + // If any miner mined blocks during current round. + var currentMiner = + round.RealTimeMinersInformation.Values.Single(m => m.Pubkey == currentPubkey); + var currentOrder = currentMiner.Order; + var ebp = round.RealTimeMinersInformation.Values.Single(m => m.IsExtraBlockProducer).Pubkey; + if (currentOrder >= minersCount) return new List { ebp }; + var nextMiners = round.RealTimeMinersInformation.Values.Where(m => m.Order > currentOrder) + .OrderBy(m => m.Order).Select(m => m.Pubkey).ToList(); + nextMiners.AddIfNotContains(ebp); + return nextMiners; } + + return round.RealTimeMinersInformation.Values.OrderBy(m => m.Order).Select(m => m.Pubkey).ToList(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSExtraDataExtractor.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSExtraDataExtractor.cs index 371202e715..c923e9f844 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSExtraDataExtractor.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSExtraDataExtractor.cs @@ -3,32 +3,32 @@ using AElf.Kernel.Consensus.Application; using Google.Protobuf; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +// ReSharper disable once InconsistentNaming +public class AEDPoSExtraDataExtractor : IConsensusExtraDataExtractor { - // ReSharper disable once InconsistentNaming - public class AEDPoSExtraDataExtractor : IConsensusExtraDataExtractor - { - private readonly IBlockExtraDataService _blockExtraDataService; - private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; + private readonly IBlockExtraDataService _blockExtraDataService; + private readonly IConsensusExtraDataProvider _consensusExtraDataProvider; - public AEDPoSExtraDataExtractor(IBlockExtraDataService blockExtraDataService, - IConsensusExtraDataProvider consensusExtraDataProvider) - { - _blockExtraDataService = blockExtraDataService; - _consensusExtraDataProvider = consensusExtraDataProvider; - } + public AEDPoSExtraDataExtractor(IBlockExtraDataService blockExtraDataService, + IConsensusExtraDataProvider consensusExtraDataProvider) + { + _blockExtraDataService = blockExtraDataService; + _consensusExtraDataProvider = consensusExtraDataProvider; + } - public ByteString ExtractConsensusExtraData(BlockHeader header) - { - var consensusExtraData = - _blockExtraDataService.GetExtraDataFromBlockHeader(_consensusExtraDataProvider.BlockHeaderExtraDataKey, header); - if (consensusExtraData == null) - return null; + public ByteString ExtractConsensusExtraData(BlockHeader header) + { + var consensusExtraData = + _blockExtraDataService.GetExtraDataFromBlockHeader(_consensusExtraDataProvider.BlockHeaderExtraDataKey, + header); + if (consensusExtraData == null) + return null; - var headerInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(consensusExtraData); + var headerInformation = AElfConsensusHeaderInformation.Parser.ParseFrom(consensusExtraData); - // Validate header information - return headerInformation.SenderPubkey != header.SignerPubkey ? null : consensusExtraData; - } + // Validate header information + return headerInformation.SenderPubkey != header.SignerPubkey ? null : consensusExtraData; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs index b7d2ef91c0..a893dd3eb5 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs @@ -6,30 +6,29 @@ using AElf.Kernel.SmartContract.Application; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +// ReSharper disable once InconsistentNaming +internal class AEDPoSInformationProvider : IAEDPoSInformationProvider { - // ReSharper disable once InconsistentNaming - internal class AEDPoSInformationProvider : IAEDPoSInformationProvider - { - private readonly IContractReaderFactory _contractReaderFactory; - private readonly IConsensusReaderContextService _consensusReaderContextService; + private readonly IConsensusReaderContextService _consensusReaderContextService; + private readonly IContractReaderFactory _contractReaderFactory; - public AEDPoSInformationProvider( - IContractReaderFactory contractReaderFactory, - IConsensusReaderContextService consensusReaderContextService) - { - _contractReaderFactory = contractReaderFactory; - _consensusReaderContextService = consensusReaderContextService; - } + public AEDPoSInformationProvider( + IContractReaderFactory contractReaderFactory, + IConsensusReaderContextService consensusReaderContextService) + { + _contractReaderFactory = contractReaderFactory; + _consensusReaderContextService = consensusReaderContextService; + } - public async Task> GetCurrentMinerList(ChainContext chainContext) - { - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - var minersWithRoundNumber = - await _contractReaderFactory - .Create(contractReaderContext).GetCurrentMinerList.CallAsync(new Empty()); - return minersWithRoundNumber.Pubkeys.Select(k => k.ToHex()); - } + public async Task> GetCurrentMinerList(ChainContext chainContext) + { + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + var minersWithRoundNumber = + await _contractReaderFactory + .Create(contractReaderContext).GetCurrentMinerList.CallAsync(new Empty()); + return minersWithRoundNumber.Pubkeys.Select(k => k.ToHex()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs index bbddb077ad..255d1549f0 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs @@ -1,128 +1,117 @@ -using AElf.Kernel.Account.Application; -using Google.Protobuf; -using Volo.Abp.Threading; using AElf.Contracts.Consensus.AEDPoS; +using AElf.Kernel.Account.Application; using AElf.Kernel.Consensus.Application; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Threading; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +internal class AEDPoSTriggerInformationProvider : ITriggerInformationProvider { - internal class AEDPoSTriggerInformationProvider : ITriggerInformationProvider + private readonly IAccountService _accountService; + private readonly IInValueCache _inValueCache; + private readonly ISecretSharingService _secretSharingService; + + public AEDPoSTriggerInformationProvider(IAccountService accountService, + ISecretSharingService secretSharingService, IInValueCache inValueCache) { - private readonly IAccountService _accountService; - private readonly IInValueCache _inValueCache; - private readonly ISecretSharingService _secretSharingService; + _accountService = accountService; + _secretSharingService = secretSharingService; + _inValueCache = inValueCache; - private ByteString Pubkey => ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)); + Logger = NullLogger.Instance; + } - public ILogger Logger { get; set; } + private ByteString Pubkey => ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)); - public AEDPoSTriggerInformationProvider(IAccountService accountService, - ISecretSharingService secretSharingService, IInValueCache inValueCache) - { - _accountService = accountService; - _secretSharingService = secretSharingService; - _inValueCache = inValueCache; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public BytesValue GetTriggerInformationForConsensusCommand(BytesValue consensusCommandBytes) + { + return new BytesValue { Value = Pubkey }; + } - public BytesValue GetTriggerInformationForConsensusCommand(BytesValue consensusCommandBytes) - { - return new BytesValue {Value = Pubkey}; - } + public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes) + { + if (consensusCommandBytes == null) + return new AElfConsensusTriggerInformation + { + Pubkey = Pubkey, + Behaviour = AElfConsensusBehaviour.UpdateValue + }.ToBytesValue(); + + var command = consensusCommandBytes.ToConsensusCommand(); + var hint = command.Hint.ToAElfConsensusHint(); - public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes) + if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) { - if (consensusCommandBytes == null) + var newInValue = _inValueCache.GetInValue(hint.RoundId); + var previousInValue = _inValueCache.GetInValue(hint.PreviousRoundId); + Logger.LogDebug($"New in value {newInValue} for round of id {hint.RoundId}"); + Logger.LogDebug($"Previous in value {previousInValue} for round of id {hint.PreviousRoundId}"); + var trigger = new AElfConsensusTriggerInformation { - return new AElfConsensusTriggerInformation - { - Pubkey = Pubkey, - Behaviour = AElfConsensusBehaviour.UpdateValue - }.ToBytesValue(); - } + Pubkey = Pubkey, + InValue = newInValue, + PreviousInValue = previousInValue, + Behaviour = hint.Behaviour + }; - var command = consensusCommandBytes.ToConsensusCommand(); - var hint = command.Hint.ToAElfConsensusHint(); + return trigger.ToBytesValue(); + } - if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) - { - var newInValue = _inValueCache.GetInValue(hint.RoundId); - var previousInValue = _inValueCache.GetInValue(hint.PreviousRoundId); - Logger.LogDebug($"New in value {newInValue} for round of id {hint.RoundId}"); - Logger.LogDebug($"Previous in value {previousInValue} for round of id {hint.PreviousRoundId}"); - var trigger = new AElfConsensusTriggerInformation - { - Pubkey = Pubkey, - InValue = newInValue, - PreviousInValue = previousInValue, - Behaviour = hint.Behaviour - }; - - return trigger.ToBytesValue(); - } + return new AElfConsensusTriggerInformation + { + Pubkey = Pubkey, + Behaviour = hint.Behaviour + }.ToBytesValue(); + } + public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes) + { + if (consensusCommandBytes == null) return new AElfConsensusTriggerInformation { Pubkey = Pubkey, - Behaviour = hint.Behaviour + Behaviour = AElfConsensusBehaviour.UpdateValue }.ToBytesValue(); - } - public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes) + var command = consensusCommandBytes.ToConsensusCommand(); + var hint = command.Hint.ToAElfConsensusHint(); + + if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) { - if (consensusCommandBytes == null) + var inValue = _inValueCache.GetInValue(hint.RoundId); + var trigger = new AElfConsensusTriggerInformation { - return new AElfConsensusTriggerInformation - { - Pubkey = Pubkey, - Behaviour = AElfConsensusBehaviour.UpdateValue - }.ToBytesValue(); - } + Pubkey = Pubkey, + InValue = inValue, + PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), + Behaviour = hint.Behaviour + }; - var command = consensusCommandBytes.ToConsensusCommand(); - var hint = command.Hint.ToAElfConsensusHint(); + var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); + foreach (var secretPiece in secretPieces) + trigger.EncryptedPieces.Add(secretPiece.Key, ByteString.CopyFrom(secretPiece.Value)); - if (hint.Behaviour == AElfConsensusBehaviour.UpdateValue) - { - var inValue = _inValueCache.GetInValue(hint.RoundId); - var trigger = new AElfConsensusTriggerInformation - { - Pubkey = Pubkey, - InValue = inValue, - PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), - Behaviour = hint.Behaviour, - }; - - var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); - foreach (var secretPiece in secretPieces) - { - trigger.EncryptedPieces.Add(secretPiece.Key, ByteString.CopyFrom(secretPiece.Value)); - } - - var decryptedPieces = _secretSharingService.GetDecryptedPieces(hint.RoundId); - foreach (var decryptedPiece in decryptedPieces) - { - trigger.DecryptedPieces.Add(decryptedPiece.Key, ByteString.CopyFrom(decryptedPiece.Value)); - } - - var revealedInValues = _secretSharingService.GetRevealedInValues(hint.RoundId); - foreach (var revealedInValue in revealedInValues) - { - trigger.RevealedInValues.Add(revealedInValue.Key, revealedInValue.Value); - } - - return trigger.ToBytesValue(); - } + var decryptedPieces = _secretSharingService.GetDecryptedPieces(hint.RoundId); + foreach (var decryptedPiece in decryptedPieces) + trigger.DecryptedPieces.Add(decryptedPiece.Key, ByteString.CopyFrom(decryptedPiece.Value)); - return new AElfConsensusTriggerInformation - { - Pubkey = Pubkey, - Behaviour = hint.Behaviour - }.ToBytesValue(); + var revealedInValues = _secretSharingService.GetRevealedInValues(hint.RoundId); + foreach (var revealedInValue in revealedInValues) + trigger.RevealedInValues.Add(revealedInValue.Key, revealedInValue.Value); + + return trigger.ToBytesValue(); } + + return new AElfConsensusTriggerInformation + { + Pubkey = Pubkey, + Behaviour = hint.Behaviour + }.ToBytesValue(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/ConsensusValidationFailedEventHandler.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/ConsensusValidationFailedEventHandler.cs index db8c1630cc..924e89dfe1 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/ConsensusValidationFailedEventHandler.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/ConsensusValidationFailedEventHandler.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus.Application; using Microsoft.Extensions.Logging; @@ -7,36 +6,36 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public class ConsensusValidationFailedEventHandler : ILocalEventHandler, + ITransientDependency { - public class ConsensusValidationFailedEventHandler : ILocalEventHandler, - ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly IConsensusService _consensusService; + + public ConsensusValidationFailedEventHandler(IConsensusService consensusService, + IBlockchainService blockchainService) { - private readonly IConsensusService _consensusService; - private readonly IBlockchainService _blockchainService; - public ILogger Logger { get; set; } + _consensusService = consensusService; + _blockchainService = blockchainService; - public ConsensusValidationFailedEventHandler(IConsensusService consensusService, - IBlockchainService blockchainService) - { - _consensusService = consensusService; - _blockchainService = blockchainService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task HandleEventAsync(ConsensusValidationFailedEventData eventData) + public async Task HandleEventAsync(ConsensusValidationFailedEventData eventData) + { + if (eventData.IsReTrigger) { - if (eventData.IsReTrigger) + Logger.LogTrace("Re-trigger consensus because validation failed."); + var chain = await _blockchainService.GetChainAsync(); + await _consensusService.TriggerConsensusAsync(new ChainContext { - Logger.LogTrace($"Re-trigger consensus because validation failed."); - var chain = await _blockchainService.GetChainAsync(); - await _consensusService.TriggerConsensusAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }); } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs index dbd8bd38ae..0eb4d0f7cc 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +// ReSharper disable once InconsistentNaming +public interface IAEDPoSInformationProvider { - // ReSharper disable once InconsistentNaming - public interface IAEDPoSInformationProvider - { - Task> GetCurrentMinerList(ChainContext chainContext); - } + Task> GetCurrentMinerList(ChainContext chainContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IInValueCache.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IInValueCache.cs index 5e974a262b..b156617efc 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IInValueCache.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IInValueCache.cs @@ -3,37 +3,32 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public interface IInValueCache +{ + void AddInValue(long roundId, Hash inValue); + Hash GetInValue(long roundId); +} + +public class InValueCache : IInValueCache, ISingletonDependency { - public interface IInValueCache + private readonly Dictionary _inValues = new(); + + public void AddInValue(long roundId, Hash inValue) { - void AddInValue(long roundId, Hash inValue); - Hash GetInValue(long roundId); + _inValues[roundId] = inValue; } - public class InValueCache : IInValueCache, ISingletonDependency + public Hash GetInValue(long roundId) { - private readonly Dictionary _inValues = new Dictionary(); - - public void AddInValue(long roundId, Hash inValue) - { - _inValues[roundId] = inValue; - } - - public Hash GetInValue(long roundId) - { - // Remove old in values. (Keep 10 in values.) - const int keepInValuesCount = 10; - if (_inValues.Keys.Count > keepInValuesCount) - { - foreach (var id in _inValues.Keys.OrderByDescending(id => id).Skip(keepInValuesCount)) - { - _inValues.Remove(id); - } - } + // Remove old in values. (Keep 10 in values.) + const int keepInValuesCount = 10; + if (_inValues.Keys.Count > keepInValuesCount) + foreach (var id in _inValues.Keys.OrderByDescending(id => id).Skip(keepInValuesCount)) + _inValues.Remove(id); - _inValues.TryGetValue(roundId, out var inValue); - return inValue ?? Hash.Empty; - } + _inValues.TryGetValue(roundId, out var inValue); + return inValue ?? Hash.Empty; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/ISecretSharingService.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/ISecretSharingService.cs index 7d1724c0d9..52e68004a4 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/ISecretSharingService.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/ISecretSharingService.cs @@ -3,13 +3,12 @@ using AElf.Contracts.Consensus.AEDPoS; using AElf.Types; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +internal interface ISecretSharingService { - internal interface ISecretSharingService - { - Task AddSharingInformationAsync(SecretSharingInformation secretSharingInformation); - Dictionary GetEncryptedPieces(long roundId); - Dictionary GetDecryptedPieces(long roundId); - Dictionary GetRevealedInValues(long roundId); - } + Task AddSharingInformationAsync(SecretSharingInformation secretSharingInformation); + Dictionary GetEncryptedPieces(long roundId); + Dictionary GetDecryptedPieces(long roundId); + Dictionary GetRevealedInValues(long roundId); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockFoundLogEventProcessor.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockFoundLogEventProcessor.cs index cea20de7e2..1cd19d9c5e 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockFoundLogEventProcessor.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockFoundLogEventProcessor.cs @@ -1,93 +1,88 @@ using System; using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; +using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Txn.Application; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -using AElf.CSharp.Core.Extension; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public class IrreversibleBlockFoundLogEventProcessor : LogEventProcessorBase, + IBlocksExecutionSucceededLogEventProcessor { - public class IrreversibleBlockFoundLogEventProcessor : LogEventProcessorBase, - IBlocksExecutionSucceededLogEventProcessor - { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITaskQueueManager _taskQueueManager; + private readonly IBlockchainService _blockchainService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITaskQueueManager _taskQueueManager; - public ILogger Logger { get; set; } + public IrreversibleBlockFoundLogEventProcessor(ISmartContractAddressService smartContractAddressService, + IBlockchainService blockchainService, ITaskQueueManager taskQueueManager) + { + _smartContractAddressService = smartContractAddressService; + _blockchainService = blockchainService; + _taskQueueManager = taskQueueManager; - public IrreversibleBlockFoundLogEventProcessor(ISmartContractAddressService smartContractAddressService, - IBlockchainService blockchainService, ITaskQueueManager taskQueueManager) - { - _smartContractAddressService = smartContractAddressService; - _blockchainService = blockchainService; - _taskQueueManager = taskQueueManager; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) return InterestedEvent; - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, ConsensusSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, ConsensusSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; - InterestedEvent = interestedEvent; - return InterestedEvent; - } + InterestedEvent = interestedEvent; + return InterestedEvent; + } - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) - { - var irreversibleBlockFound = new IrreversibleBlockFound(); - irreversibleBlockFound.MergeFrom(logEvent); - await ProcessLogEventAsync(block, irreversibleBlockFound); - } + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var irreversibleBlockFound = new IrreversibleBlockFound(); + irreversibleBlockFound.MergeFrom(logEvent); + await ProcessLogEventAsync(block, irreversibleBlockFound); + } - private async Task ProcessLogEventAsync(Block block, IrreversibleBlockFound irreversibleBlockFound) + private async Task ProcessLogEventAsync(Block block, IrreversibleBlockFound irreversibleBlockFound) + { + try { - try - { - var chain = await _blockchainService.GetChainAsync(); + var chain = await _blockchainService.GetChainAsync(); - if (chain.LastIrreversibleBlockHeight > irreversibleBlockFound.IrreversibleBlockHeight) - return; + if (chain.LastIrreversibleBlockHeight > irreversibleBlockFound.IrreversibleBlockHeight) + return; - var libBlockHash = await _blockchainService.GetBlockHashByHeightAsync(chain, - irreversibleBlockFound.IrreversibleBlockHeight, block.GetHash()); - if (libBlockHash == null) return; + var libBlockHash = await _blockchainService.GetBlockHashByHeightAsync(chain, + irreversibleBlockFound.IrreversibleBlockHeight, block.GetHash()); + if (libBlockHash == null) return; - if (chain.LastIrreversibleBlockHeight == irreversibleBlockFound.IrreversibleBlockHeight) return; + if (chain.LastIrreversibleBlockHeight == irreversibleBlockFound.IrreversibleBlockHeight) return; - var blockIndex = new BlockIndex(libBlockHash, irreversibleBlockFound.IrreversibleBlockHeight); - Logger.LogDebug($"About to set new lib height: {blockIndex.BlockHeight} " + - $"Event: {irreversibleBlockFound} " + - $"BlockIndex: {blockIndex.BlockHash} - {blockIndex.BlockHeight}"); - _taskQueueManager.Enqueue( - async () => - { - var currentChain = await _blockchainService.GetChainAsync(); - if (currentChain.LastIrreversibleBlockHeight < blockIndex.BlockHeight) - { - await _blockchainService.SetIrreversibleBlockAsync(currentChain, blockIndex.BlockHeight, - blockIndex.BlockHash); - } - }, KernelConstants.UpdateChainQueueName); - } - catch (Exception e) - { - Logger.LogError(e, "Failed to resolve IrreversibleBlockFound event."); - throw; - } + var blockIndex = new BlockIndex(libBlockHash, irreversibleBlockFound.IrreversibleBlockHeight); + Logger.LogDebug($"About to set new lib height: {blockIndex.BlockHeight} " + + $"Event: {irreversibleBlockFound} " + + $"BlockIndex: {blockIndex.BlockHash} - {blockIndex.BlockHeight}"); + _taskQueueManager.Enqueue( + async () => + { + var currentChain = await _blockchainService.GetChainAsync(); + if (currentChain.LastIrreversibleBlockHeight < blockIndex.BlockHeight) + await _blockchainService.SetIrreversibleBlockAsync(currentChain, blockIndex.BlockHeight, + blockIndex.BlockHash); + }, KernelConstants.UpdateChainQueueName); + } + catch (Exception e) + { + Logger.LogError(e, "Failed to resolve IrreversibleBlockFound event."); + throw; } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockHeightUnacceptableLogEventProcessor.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockHeightUnacceptableLogEventProcessor.cs index 203a82aca3..5ca2448229 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockHeightUnacceptableLogEventProcessor.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IrreversibleBlockHeightUnacceptableLogEventProcessor.cs @@ -1,67 +1,66 @@ using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; +using AElf.CSharp.Core.Extension; +using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using AElf.CSharp.Core.Extension; -using AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public class IrreversibleBlockHeightUnacceptableLogEventProcessor : LogEventProcessorBase, + IBlockAcceptedLogEventProcessor { - public class IrreversibleBlockHeightUnacceptableLogEventProcessor : LogEventProcessorBase, - IBlockAcceptedLogEventProcessor + private readonly IBlockchainService _blockchainService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITaskQueueManager _taskQueueManager; + + public IrreversibleBlockHeightUnacceptableLogEventProcessor( + ISmartContractAddressService smartContractAddressService, + IBlockchainService blockchainService, ITaskQueueManager taskQueueManager) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainService _blockchainService; - private readonly ITaskQueueManager _taskQueueManager; + _smartContractAddressService = smartContractAddressService; + _blockchainService = blockchainService; + _taskQueueManager = taskQueueManager; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public IrreversibleBlockHeightUnacceptableLogEventProcessor( - ISmartContractAddressService smartContractAddressService, - IBlockchainService blockchainService, ITaskQueueManager taskQueueManager) - { - _smartContractAddressService = smartContractAddressService; - _blockchainService = blockchainService; - _taskQueueManager = taskQueueManager; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return InterestedEvent; + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, ConsensusSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, ConsensusSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress + .Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress - .Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; + InterestedEvent = interestedEvent; + return InterestedEvent; + } - InterestedEvent = interestedEvent; - return InterestedEvent; - } + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var distanceToLib = new IrreversibleBlockHeightUnacceptable(); + distanceToLib.MergeFrom(logEvent); - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + if (distanceToLib.DistanceToIrreversibleBlockHeight > 0) { - var distanceToLib = new IrreversibleBlockHeightUnacceptable(); - distanceToLib.MergeFrom(logEvent); - - if (distanceToLib.DistanceToIrreversibleBlockHeight > 0) - { - Logger.LogDebug($"Distance to lib height: {distanceToLib.DistanceToIrreversibleBlockHeight}"); - Logger.LogDebug("Will rollback to lib height."); - _taskQueueManager.Enqueue( - async () => - { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.ResetChainToLibAsync(chain); - }, KernelConstants.UpdateChainQueueName); - } + Logger.LogDebug($"Distance to lib height: {distanceToLib.DistanceToIrreversibleBlockHeight}"); + Logger.LogDebug("Will rollback to lib height."); + _taskQueueManager.Enqueue( + async () => + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.ResetChainToLibAsync(chain); + }, KernelConstants.UpdateChainQueueName); } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingInformationLogEventProcessor.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingInformationLogEventProcessor.cs index 0700052505..82b162c25d 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingInformationLogEventProcessor.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingInformationLogEventProcessor.cs @@ -1,44 +1,44 @@ using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Kernel.SmartContract.Application; using AElf.CSharp.Core.Extension; +using AElf.Kernel.SmartContract.Application; using AElf.Types; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +internal class SecretSharingInformationLogEventProcessor : LogEventProcessorBase, + IBlocksExecutionSucceededLogEventProcessor { - internal class SecretSharingInformationLogEventProcessor : LogEventProcessorBase, IBlocksExecutionSucceededLogEventProcessor + private readonly ISecretSharingService _secretSharingService; + private readonly ISmartContractAddressService _smartContractAddressService; + + public SecretSharingInformationLogEventProcessor( + ISmartContractAddressService smartContractAddressService, + ISecretSharingService secretSharingService) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ISecretSharingService _secretSharingService; + _smartContractAddressService = smartContractAddressService; + _secretSharingService = secretSharingService; + } - public SecretSharingInformationLogEventProcessor( - ISmartContractAddressService smartContractAddressService, - ISecretSharingService secretSharingService) - { - _smartContractAddressService = smartContractAddressService; - _secretSharingService = secretSharingService; - } + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, ConsensusSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; + + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) return InterestedEvent; - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, ConsensusSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; - - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; - - InterestedEvent = interestedEvent; - return InterestedEvent; - } + InterestedEvent = interestedEvent; + return InterestedEvent; + } - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) - { - var secretSharingInformation = new SecretSharingInformation(); - secretSharingInformation.MergeFrom(logEvent); - await _secretSharingService.AddSharingInformationAsync(secretSharingInformation); - } + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var secretSharingInformation = new SecretSharingInformation(); + secretSharingInformation.MergeFrom(logEvent); + await _secretSharingService.AddSharingInformationAsync(secretSharingInformation); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingService.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingService.cs index a0680550f1..f1fb99d41f 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingService.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/SecretSharingService.cs @@ -11,203 +11,182 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -using AElf.CSharp.Core.Extension; -namespace AElf.Kernel.Consensus.AEDPoS.Application +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +internal class SecretSharingService : ISecretSharingService, ISingletonDependency { - internal class SecretSharingService : ISecretSharingService, ISingletonDependency - { - private readonly Dictionary> _encryptedPieces = - new Dictionary>(); + private readonly IAccountService _accountService; - private readonly Dictionary> _decryptedPieces = - new Dictionary>(); + private readonly Dictionary> _decryptedPieces = new(); - private readonly Dictionary> _revealedInValues = - new Dictionary>(); + private readonly Dictionary> _encryptedPieces = new(); - private readonly IInValueCache _inValueCache; - private readonly IAccountService _accountService; + private readonly IInValueCache _inValueCache; - public ILogger Logger { get; set; } + private readonly Dictionary> _revealedInValues = new(); - public SecretSharingService(IInValueCache inValueCache, IAccountService accountService) - { - _inValueCache = inValueCache; - _accountService = accountService; + public SecretSharingService(IInValueCache inValueCache, IAccountService accountService) + { + _inValueCache = inValueCache; + _accountService = accountService; - Logger = NullLogger.Instance; - } + Logger = NullLogger.Instance; + } - public async Task AddSharingInformationAsync(SecretSharingInformation secretSharingInformation) - { - try - { - var selfPubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); - - if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey)) - { - return; - } - - var newInValue = await GenerateInValueAsync(secretSharingInformation); - Logger.LogDebug( - $"Add in value {newInValue} for round id {secretSharingInformation.CurrentRoundId}"); - _inValueCache.AddInValue(secretSharingInformation.CurrentRoundId, newInValue); - - if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count == 1) - { - return; - } - - await CollectPiecesWithSecretSharingAsync(secretSharingInformation, newInValue, selfPubkey); - RevealPreviousInValues(secretSharingInformation, selfPubkey); - } - catch (Exception e) - { - Logger.LogError(e, "Error in AddSharingInformationAsync."); - } - } + public ILogger Logger { get; set; } - private async Task CollectPiecesWithSecretSharingAsync(SecretSharingInformation secretSharingInformation, - Hash newInValue, string selfPubkey) + public async Task AddSharingInformationAsync(SecretSharingInformation secretSharingInformation) + { + try { - var encryptedPieces = new Dictionary(); - var decryptedPieces = new Dictionary(); - - var minersCount = secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count; - var minimumCount = minersCount.Mul(2).Div(3); - var secretShares = - SecretSharingHelper.EncodeSecret(newInValue.ToByteArray(), minimumCount, minersCount); - - foreach (var pair in secretSharingInformation.PreviousRound.RealTimeMinersInformation - .OrderBy(m => m.Value.Order).ToDictionary(m => m.Key, m => m.Value.Order)) - { - var pubkey = pair.Key; - var order = pair.Value; - - var plainMessage = secretShares[order - 1]; - var receiverPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); - var encryptedPiece = await _accountService.EncryptMessageAsync(receiverPublicKey, plainMessage); - encryptedPieces[pubkey] = encryptedPiece; - if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey) && - secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey].EncryptedPieces - .ContainsKey(pubkey)) - { - secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey] - .EncryptedPieces[pubkey] - = ByteString.CopyFrom(encryptedPiece); - } - else - { - continue; - } - - if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(pubkey)) continue; - - var encryptedShares = - secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].EncryptedPieces; - if (!encryptedShares.Any() || !encryptedShares.ContainsKey(selfPubkey)) continue; - var interestingMessage = encryptedShares[selfPubkey]; - var senderPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); - - var decryptedPiece = - await _accountService.DecryptMessageAsync(senderPublicKey, interestingMessage.ToByteArray()); - decryptedPieces[pubkey] = decryptedPiece; - secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].DecryptedPieces[selfPubkey] - = ByteString.CopyFrom(decryptedPiece); - } - - _encryptedPieces[secretSharingInformation.CurrentRoundId] = encryptedPieces; - _decryptedPieces[secretSharingInformation.CurrentRoundId] = decryptedPieces; - } + var selfPubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); - private void RevealPreviousInValues(SecretSharingInformation secretSharingInformation, string selfPubkey) - { - var round = secretSharingInformation.PreviousRound; - var minersCount = round.RealTimeMinersInformation.Count; - var minimumCount = minersCount.Mul(2).Div(3); - minimumCount = minimumCount == 0 ? 1 : minimumCount; + if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey)) return; - var revealedInValues = new Dictionary(); + var newInValue = await GenerateInValueAsync(secretSharingInformation); + Logger.LogDebug( + $"Add in value {newInValue} for round id {secretSharingInformation.CurrentRoundId}"); + _inValueCache.AddInValue(secretSharingInformation.CurrentRoundId, newInValue); - foreach (var pair in round.RealTimeMinersInformation.OrderBy(m => m.Value.Order)) - { - // Skip himself. - if (pair.Key == selfPubkey) continue; + if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count == 1) return; - var pubkey = pair.Key; - var minerInRound = pair.Value; + await CollectPiecesWithSecretSharingAsync(secretSharingInformation, newInValue, selfPubkey); + RevealPreviousInValues(secretSharingInformation, selfPubkey); + } + catch (Exception e) + { + Logger.LogError(e, "Error in AddSharingInformationAsync."); + } + } - if (minerInRound.EncryptedPieces.Count < minimumCount) continue; - if (minerInRound.DecryptedPieces.Count < minersCount) continue; + public Dictionary GetEncryptedPieces(long roundId) + { + _encryptedPieces.TryGetValue(roundId, out var encryptedPieces); + Logger.LogDebug($"[GetEncryptedPieces]Round id: {roundId}"); + if (encryptedPieces != null) Logger.LogDebug($"Encrypted/Shared {encryptedPieces.Count} pieces."); - // Reveal another miner's in value for target round: + _encryptedPieces.Remove(roundId); + return encryptedPieces ?? new Dictionary(); + } - var orders = minerInRound.DecryptedPieces.Select((t, i) => - round.RealTimeMinersInformation.Values - .First(m => m.Pubkey == - minerInRound.DecryptedPieces.Keys.ToList()[i]).Order) - .ToList(); + public Dictionary GetDecryptedPieces(long roundId) + { + _decryptedPieces.TryGetValue(roundId, out var decryptedPieces); + Logger.LogDebug($"[GetDecryptedPieces]Round id: {roundId}"); + if (decryptedPieces != null) + Logger.LogDebug($"Decrypted {decryptedPieces.Count} pieces for round of id {roundId}"); - var sharedParts = minerInRound.DecryptedPieces.Values.ToList() - .Select(s => s.ToByteArray()).ToList(); + _decryptedPieces.Remove(roundId); + return decryptedPieces ?? new Dictionary(); + } - var revealedInValue = - HashHelper.ComputeFrom(SecretSharingHelper.DecodeSecret(sharedParts, orders, minimumCount)); + public Dictionary GetRevealedInValues(long roundId) + { + _revealedInValues.TryGetValue(roundId, out var revealedInValues); + Logger.LogDebug($"[GetRevealedInValues]Round id: {roundId}"); + if (revealedInValues != null) + Logger.LogDebug($"Revealed {revealedInValues.Count} in values for round of id {roundId}"); - Logger.LogDebug($"Revealed in value of {pubkey} of round {round.RoundNumber}: {revealedInValue}"); + _revealedInValues.Remove(roundId); + return revealedInValues ?? new Dictionary(); + } - revealedInValues[pubkey] = revealedInValue; - } + private async Task CollectPiecesWithSecretSharingAsync(SecretSharingInformation secretSharingInformation, + Hash newInValue, string selfPubkey) + { + var encryptedPieces = new Dictionary(); + var decryptedPieces = new Dictionary(); - _revealedInValues[secretSharingInformation.CurrentRoundId] = revealedInValues; - } + var minersCount = secretSharingInformation.PreviousRound.RealTimeMinersInformation.Count; + var minimumCount = minersCount.Mul(2).Div(3); + var secretShares = + SecretSharingHelper.EncodeSecret(newInValue.ToByteArray(), minimumCount, minersCount); - public Dictionary GetEncryptedPieces(long roundId) + foreach (var pair in secretSharingInformation.PreviousRound.RealTimeMinersInformation + .OrderBy(m => m.Value.Order).ToDictionary(m => m.Key, m => m.Value.Order)) { - _encryptedPieces.TryGetValue(roundId, out var encryptedPieces); - Logger.LogDebug($"[GetEncryptedPieces]Round id: {roundId}"); - if (encryptedPieces != null) - { - Logger.LogDebug($"Encrypted/Shared {encryptedPieces.Count} pieces."); - } - - _encryptedPieces.Remove(roundId); - return encryptedPieces ?? new Dictionary(); + var pubkey = pair.Key; + var order = pair.Value; + + var plainMessage = secretShares[order - 1]; + var receiverPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); + var encryptedPiece = await _accountService.EncryptMessageAsync(receiverPublicKey, plainMessage); + encryptedPieces[pubkey] = encryptedPiece; + if (secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(selfPubkey) && + secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey].EncryptedPieces + .ContainsKey(pubkey)) + secretSharingInformation.PreviousRound.RealTimeMinersInformation[selfPubkey] + .EncryptedPieces[pubkey] + = ByteString.CopyFrom(encryptedPiece); + else + continue; + + if (!secretSharingInformation.PreviousRound.RealTimeMinersInformation.ContainsKey(pubkey)) continue; + + var encryptedShares = + secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].EncryptedPieces; + if (!encryptedShares.Any() || !encryptedShares.ContainsKey(selfPubkey)) continue; + var interestingMessage = encryptedShares[selfPubkey]; + var senderPublicKey = ByteArrayHelper.HexStringToByteArray(pubkey); + + var decryptedPiece = + await _accountService.DecryptMessageAsync(senderPublicKey, interestingMessage.ToByteArray()); + decryptedPieces[pubkey] = decryptedPiece; + secretSharingInformation.PreviousRound.RealTimeMinersInformation[pubkey].DecryptedPieces[selfPubkey] + = ByteString.CopyFrom(decryptedPiece); } - public Dictionary GetDecryptedPieces(long roundId) - { - _decryptedPieces.TryGetValue(roundId, out var decryptedPieces); - Logger.LogDebug($"[GetDecryptedPieces]Round id: {roundId}"); - if (decryptedPieces != null) - { - Logger.LogDebug($"Decrypted {decryptedPieces.Count} pieces for round of id {roundId}"); - } - - _decryptedPieces.Remove(roundId); - return decryptedPieces ?? new Dictionary(); - } + _encryptedPieces[secretSharingInformation.CurrentRoundId] = encryptedPieces; + _decryptedPieces[secretSharingInformation.CurrentRoundId] = decryptedPieces; + } - public Dictionary GetRevealedInValues(long roundId) - { - _revealedInValues.TryGetValue(roundId, out var revealedInValues); - Logger.LogDebug($"[GetRevealedInValues]Round id: {roundId}"); - if (revealedInValues != null) - { - Logger.LogDebug($"Revealed {revealedInValues.Count} in values for round of id {roundId}"); - } - - _revealedInValues.Remove(roundId); - return revealedInValues ?? new Dictionary(); - } + private void RevealPreviousInValues(SecretSharingInformation secretSharingInformation, string selfPubkey) + { + var round = secretSharingInformation.PreviousRound; + var minersCount = round.RealTimeMinersInformation.Count; + var minimumCount = minersCount.Mul(2).Div(3); + minimumCount = minimumCount == 0 ? 1 : minimumCount; + + var revealedInValues = new Dictionary(); - private async Task GenerateInValueAsync(IMessage message) + foreach (var pair in round.RealTimeMinersInformation.OrderBy(m => m.Value.Order)) { - var data = HashHelper.ComputeFrom(message.ToByteArray()); - var bytes = await _accountService.SignAsync(data.ToByteArray()); - return HashHelper.ComputeFrom(bytes); + // Skip himself. + if (pair.Key == selfPubkey) continue; + + var pubkey = pair.Key; + var minerInRound = pair.Value; + + if (minerInRound.EncryptedPieces.Count < minimumCount) continue; + if (minerInRound.DecryptedPieces.Count < minersCount) continue; + + // Reveal another miner's in value for target round: + + var orders = minerInRound.DecryptedPieces.Select((t, i) => + round.RealTimeMinersInformation.Values + .First(m => m.Pubkey == + minerInRound.DecryptedPieces.Keys.ToList()[i]).Order) + .ToList(); + + var sharedParts = minerInRound.DecryptedPieces.Values.ToList() + .Select(s => s.ToByteArray()).ToList(); + + var revealedInValue = + HashHelper.ComputeFrom(SecretSharingHelper.DecodeSecret(sharedParts, orders, minimumCount)); + + Logger.LogDebug($"Revealed in value of {pubkey} of round {round.RoundNumber}: {revealedInValue}"); + + revealedInValues[pubkey] = revealedInValue; } + + _revealedInValues[secretSharingInformation.CurrentRoundId] = revealedInValues; + } + + private async Task GenerateInValueAsync(IMessage message) + { + var data = HashHelper.ComputeFrom(message.ToByteArray()); + var bytes = await _accountService.SignAsync(data.ToByteArray()); + return HashHelper.ComputeFrom(bytes); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AssemblyInfo.cs b/src/AElf.Kernel.Consensus.AEDPoS/AssemblyInfo.cs index 177f4d56ff..3b93feee85 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AssemblyInfo.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/AssemblyInfo.cs @@ -3,4 +3,4 @@ [assembly: InternalsVisibleTo("AElf.Kernel.Tests")] [assembly: InternalsVisibleTo("AElf.Contracts.Consensus.AEDPoS.Tests")] [assembly: InternalsVisibleTo("AElf.Contracts.Economic.TestBase")] -[assembly: InternalsVisibleTo("AElf.Kernel.Consensus.AEDPoS.Tests")] +[assembly: InternalsVisibleTo("AElf.Kernel.Consensus.AEDPoS.Tests")] \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/ConsensusOptions.cs b/src/AElf.Kernel.Consensus.AEDPoS/ConsensusOptions.cs index 24033e252e..c490658dc2 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/ConsensusOptions.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/ConsensusOptions.cs @@ -1,16 +1,14 @@ -using System; using System.Collections.Generic; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +// ReSharper disable once InconsistentNaming +public class ConsensusOptions { - // ReSharper disable once InconsistentNaming - public class ConsensusOptions - { - public List InitialMinerList { get; set; } - public int MiningInterval { get; set; } - public Timestamp StartTimestamp { get; set; } = new Timestamp {Seconds = 0}; - public long PeriodSeconds { get; set; } = 604800; - public long MinerIncreaseInterval { get; set; } = 31536000; - } + public List InitialMinerList { get; set; } + public int MiningInterval { get; set; } + public Timestamp StartTimestamp { get; set; } = new() { Seconds = 0 }; + public long PeriodSeconds { get; set; } = 604800; + public long MinerIncreaseInterval { get; set; } = 31536000; } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/ByteStringExtensions.cs b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/ByteStringExtensions.cs index 118c659f73..bd24e47134 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/ByteStringExtensions.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/ByteStringExtensions.cs @@ -2,15 +2,14 @@ using Google.Protobuf; // ReSharper disable once CheckNamespace -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +public static class ByteStringExtensions { - public static class ByteStringExtensions + internal static AElfConsensusHint ToAElfConsensusHint(this ByteString byteString) { - internal static AElfConsensusHint ToAElfConsensusHint(this ByteString byteString) - { - var hint = new AElfConsensusHint(); - hint.MergeFrom(byteString); - return hint; - } + var hint = new AElfConsensusHint(); + hint.MergeFrom(byteString); + return hint; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/BytesValueExtensions.cs b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/BytesValueExtensions.cs index 1a71f1f9a0..03b74bc126 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/BytesValueExtensions.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/BytesValueExtensions.cs @@ -3,15 +3,14 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +internal static class BytesValueExtensions { - internal static class BytesValueExtensions + internal static ConsensusCommand ToConsensusCommand(this BytesValue bytesValue) { - internal static ConsensusCommand ToConsensusCommand(this BytesValue bytesValue) - { - var consensusCommand = new ConsensusCommand(); - consensusCommand.MergeFrom(bytesValue.Value); - return consensusCommand; - } + var consensusCommand = new ConsensusCommand(); + consensusCommand.MergeFrom(bytesValue.Value); + return consensusCommand; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/MinerListExtensions.cs b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/MinerListExtensions.cs index 28a750ac8e..10c7f8f113 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Extensions/MinerListExtensions.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Extensions/MinerListExtensions.cs @@ -5,46 +5,42 @@ using Google.Protobuf.WellKnownTypes; // ReSharper disable once CheckNamespace -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public static class MinerListExtensions { - public static class MinerListExtensions + internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, + DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - internal static Round GenerateFirstRoundOfNewTerm(this MinerList miners, int miningInterval, - DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in miners.Pubkeys.Distinct() + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in miners.Pubkeys.Distinct() - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval).ToTimestamp(); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval).ToTimestamp(); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/IAEDPoSContractInitializationDataProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/IAEDPoSContractInitializationDataProvider.cs index 360d3a08bb..e046366afa 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/IAEDPoSContractInitializationDataProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/IAEDPoSContractInitializationDataProvider.cs @@ -1,24 +1,23 @@ using System.Collections.Generic; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Consensus.AEDPoS +namespace AElf.Kernel.Consensus.AEDPoS; + +/// +/// Add this interface because the initialization logic of AEDPoS Contract +/// are different from Main Chain, Side Chain and test cases. +/// +public interface IAEDPoSContractInitializationDataProvider { - /// - /// Add this interface because the initialization logic of AEDPoS Contract - /// are different from Main Chain, Side Chain and test cases. - /// - public interface IAEDPoSContractInitializationDataProvider - { - AEDPoSContractInitializationData GetContractInitializationData(); - } + AEDPoSContractInitializationData GetContractInitializationData(); +} - public class AEDPoSContractInitializationData - { - public long PeriodSeconds { get; set; } - public long MinerIncreaseInterval { get; set; } - public List InitialMinerList { get; set; } - public int MiningInterval { get; set; } - public Timestamp StartTimestamp { get; set; } - public bool IsSideChain { get; set; } - } +public class AEDPoSContractInitializationData +{ + public long PeriodSeconds { get; set; } + public long MinerIncreaseInterval { get; set; } + public List InitialMinerList { get; set; } + public int MiningInterval { get; set; } + public Timestamp StartTimestamp { get; set; } + public bool IsSideChain { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/AElf.Kernel.Consensus.Core.csproj b/src/AElf.Kernel.Consensus.Core/AElf.Kernel.Consensus.Core.csproj index 241b7351a0..d24ddf32c1 100644 --- a/src/AElf.Kernel.Consensus.Core/AElf.Kernel.Consensus.Core.csproj +++ b/src/AElf.Kernel.Consensus.Core/AElf.Kernel.Consensus.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Kernel.Consensus @@ -10,7 +10,7 @@ - + diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusBestChainFoundEventHandler.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusBestChainFoundEventHandler.cs index 36e64b0ac3..42971de302 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusBestChainFoundEventHandler.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusBestChainFoundEventHandler.cs @@ -3,34 +3,33 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +/// +/// Trigger consensus to update mining scheduler. +/// +public class ConsensusBestChainFoundEventHandler : ILocalEventHandler, ITransientDependency { + private readonly IConsensusService _consensusService; + + public ConsensusBestChainFoundEventHandler(IConsensusService consensusService) + { + _consensusService = consensusService; + } + /// - /// Trigger consensus to update mining scheduler. + /// Trigger consensus mining process after event BestChainFoundEventData published by EventBus. /// - public class ConsensusBestChainFoundEventHandler : ILocalEventHandler, ITransientDependency + /// + /// + public Task HandleEventAsync(BestChainFoundEventData eventData) { - private readonly IConsensusService _consensusService; - - public ConsensusBestChainFoundEventHandler(IConsensusService consensusService) - { - _consensusService = consensusService; - } - - /// - /// Trigger consensus mining process after event BestChainFoundEventData published by EventBus. - /// - /// - /// - public Task HandleEventAsync(BestChainFoundEventData eventData) + _consensusService.TriggerConsensusAsync(new ChainContext { - _consensusService.TriggerConsensusAsync(new ChainContext - { - BlockHash = eventData.BlockHash, - BlockHeight = eventData.BlockHeight - }); + BlockHash = eventData.BlockHash, + BlockHeight = eventData.BlockHeight + }); - return Task.CompletedTask; - } + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusExtraDataProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusExtraDataProvider.cs index 7905ab61fc..3210fae10b 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusExtraDataProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusExtraDataProvider.cs @@ -3,44 +3,39 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public class ConsensusExtraDataProvider : IConsensusExtraDataProvider { - public class ConsensusExtraDataProvider : IConsensusExtraDataProvider - { - public string BlockHeaderExtraDataKey => ConsensusConstants.ConsensusExtraDataKey; + private readonly IConsensusService _consensusService; - private readonly IConsensusService _consensusService; - public ILogger Logger { get; set; } + /// + /// Add an empty ctor for cases only need BlockHeaderExtraDataKey. + /// + public ConsensusExtraDataProvider() + { + } - /// - /// Add an empty ctor for cases only need BlockHeaderExtraDataKey. - /// - public ConsensusExtraDataProvider() - { + public ConsensusExtraDataProvider(IConsensusService consensusService) + { + _consensusService = consensusService; - } + Logger = NullLogger.Instance; + } - public ConsensusExtraDataProvider(IConsensusService consensusService) - { - _consensusService = consensusService; + public ILogger Logger { get; set; } + public string BlockHeaderExtraDataKey => ConsensusConstants.ConsensusExtraDataKey; - Logger = NullLogger.Instance; - } + public async Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) + { + if (blockHeader.Height == AElfConstants.GenesisBlockHeight) return null; - public async Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) + var consensusInformation = await _consensusService.GetConsensusExtraDataAsync(new ChainContext { - if (blockHeader.Height == AElfConstants.GenesisBlockHeight) - { - return null; - } - - var consensusInformation = await _consensusService.GetConsensusExtraDataAsync(new ChainContext - { - BlockHash = blockHeader.PreviousBlockHash, - BlockHeight = blockHeader.Height - 1 - }); - - return consensusInformation == null ? ByteString.Empty : ByteString.CopyFrom(consensusInformation); - } + BlockHash = blockHeader.PreviousBlockHash, + BlockHeight = blockHeader.Height - 1 + }); + + return consensusInformation == null ? ByteString.Empty : ByteString.CopyFrom(consensusInformation); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs index 8f772f2fa8..680a36dfb5 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS4; using AElf.CSharp.Core.Extension; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS4; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -12,222 +12,222 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +internal class ConsensusService : IConsensusService, ISingletonDependency { - internal class ConsensusService : IConsensusService, ISingletonDependency - { - private ConsensusCommand _consensusCommand; - private readonly IConsensusScheduler _consensusScheduler; + private readonly IBlockTimeProvider _blockTimeProvider; + private readonly IConsensusReaderContextService _consensusReaderContextService; + private readonly IConsensusScheduler _consensusScheduler; + + private readonly IContractReaderFactory + _contractReaderFactory; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly ITriggerInformationProvider _triggerInformationProvider; + private ConsensusCommand _consensusCommand; - private readonly ITriggerInformationProvider _triggerInformationProvider; - private readonly IBlockTimeProvider _blockTimeProvider; - private readonly IConsensusReaderContextService _consensusReaderContextService; - public ILocalEventBus LocalEventBus { get; set; } + private Timestamp _nextMiningTime; - public ILogger Logger { get; set; } + public ConsensusService(IConsensusScheduler consensusScheduler, + IContractReaderFactory contractReaderFactory, + ITriggerInformationProvider triggerInformationProvider, + IBlockTimeProvider blockTimeProvider, IConsensusReaderContextService consensusReaderContextService) + { + _contractReaderFactory = contractReaderFactory; + _triggerInformationProvider = triggerInformationProvider; + _blockTimeProvider = blockTimeProvider; + _consensusReaderContextService = consensusReaderContextService; + _consensusScheduler = consensusScheduler; + + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + } - private Timestamp _nextMiningTime; + public ILocalEventBus LocalEventBus { get; set; } - public ConsensusService(IConsensusScheduler consensusScheduler, - IContractReaderFactory contractReaderFactory, - ITriggerInformationProvider triggerInformationProvider, - IBlockTimeProvider blockTimeProvider, IConsensusReaderContextService consensusReaderContextService) - { - _contractReaderFactory = contractReaderFactory; - _triggerInformationProvider = triggerInformationProvider; - _blockTimeProvider = blockTimeProvider; - _consensusReaderContextService = consensusReaderContextService; - _consensusScheduler = consensusScheduler; - - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILogger Logger { get; set; } - /// - /// Basically update the consensus scheduler with latest consensus command. - /// - /// - /// - public async Task TriggerConsensusAsync(ChainContext chainContext) - { - var now = TimestampHelper.GetUtcNow(); - _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); + /// + /// Basically update the consensus scheduler with latest consensus command. + /// + /// + /// + public async Task TriggerConsensusAsync(ChainContext chainContext) + { + var now = TimestampHelper.GetUtcNow(); + _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); - Logger.LogDebug($"Block time of triggering consensus: {now.ToDateTime():hh:mm:ss.ffffff}."); + Logger.LogDebug($"Block time of triggering consensus: {now.ToDateTime():hh:mm:ss.ffffff}."); - var triggerInformation = - _triggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); + var triggerInformation = + _triggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); - Logger.LogDebug($"Mining triggered, chain context: {chainContext.BlockHeight} - {chainContext.BlockHash}"); + Logger.LogDebug($"Mining triggered, chain context: {chainContext.BlockHeight} - {chainContext.BlockHash}"); - // Upload the consensus command. - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - _consensusCommand = await _contractReaderFactory - .Create(contractReaderContext).GetConsensusCommand - .CallAsync(triggerInformation); + // Upload the consensus command. + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + _consensusCommand = await _contractReaderFactory + .Create(contractReaderContext).GetConsensusCommand + .CallAsync(triggerInformation); - if (_consensusCommand == null) - { - Logger.LogWarning("Consensus command is null."); - return; - } - - Logger.LogDebug($"Updated consensus command: {_consensusCommand}"); - - // Update next mining time, also block time of both getting consensus extra data and txs. - _nextMiningTime = _consensusCommand.ArrangedMiningTime; - var leftMilliseconds = _consensusCommand.ArrangedMiningTime - TimestampHelper.GetUtcNow(); - leftMilliseconds = leftMilliseconds.Seconds > ConsensusConstants.MaximumLeftMillisecondsForNextBlock - ? new Duration {Seconds = ConsensusConstants.MaximumLeftMillisecondsForNextBlock} - : leftMilliseconds; - - // Update consensus scheduler. - var blockMiningEventData = new ConsensusRequestMiningEventData(chainContext.BlockHash, - chainContext.BlockHeight, - _nextMiningTime, - TimestampHelper.DurationFromMilliseconds(_consensusCommand.LimitMillisecondsOfMiningBlock), - _consensusCommand.MiningDueTime); - _consensusScheduler.CancelCurrentEvent(); - _consensusScheduler.NewEvent(leftMilliseconds.Milliseconds(), blockMiningEventData); - - Logger.LogDebug($"Set next mining time to: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}"); + if (_consensusCommand == null) + { + Logger.LogWarning("Consensus command is null."); + return; } - /// - /// Call ACS4 method ValidateConsensusBeforeExecution. - /// - /// - /// - /// - public async Task ValidateConsensusBeforeExecutionAsync(ChainContext chainContext, - byte[] consensusExtraData) - { - var now = TimestampHelper.GetUtcNow(); - _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); + Logger.LogDebug($"Updated consensus command: {_consensusCommand}"); + + // Update next mining time, also block time of both getting consensus extra data and txs. + _nextMiningTime = _consensusCommand.ArrangedMiningTime; + var leftMilliseconds = _consensusCommand.ArrangedMiningTime - TimestampHelper.GetUtcNow(); + leftMilliseconds = leftMilliseconds.Seconds > ConsensusConstants.MaximumLeftMillisecondsForNextBlock + ? new Duration { Seconds = ConsensusConstants.MaximumLeftMillisecondsForNextBlock } + : leftMilliseconds; + + // Update consensus scheduler. + var blockMiningEventData = new ConsensusRequestMiningEventData(chainContext.BlockHash, + chainContext.BlockHeight, + _nextMiningTime, + TimestampHelper.DurationFromMilliseconds(_consensusCommand.LimitMillisecondsOfMiningBlock), + _consensusCommand.MiningDueTime); + _consensusScheduler.CancelCurrentEvent(); + _consensusScheduler.NewEvent(leftMilliseconds.Milliseconds(), blockMiningEventData); + + Logger.LogDebug($"Set next mining time to: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}"); + } - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - var validationResult = await _contractReaderFactory - .Create(contractReaderContext) - .ValidateConsensusBeforeExecution - .CallAsync(new BytesValue {Value = ByteString.CopyFrom(consensusExtraData)}); + /// + /// Call ACS4 method ValidateConsensusBeforeExecution. + /// + /// + /// + /// + public async Task ValidateConsensusBeforeExecutionAsync(ChainContext chainContext, + byte[] consensusExtraData) + { + var now = TimestampHelper.GetUtcNow(); + _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); - if (validationResult == null) - { - Logger.LogDebug("Validation of consensus failed before execution."); - return false; - } + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + var validationResult = await _contractReaderFactory + .Create(contractReaderContext) + .ValidateConsensusBeforeExecution + .CallAsync(new BytesValue { Value = ByteString.CopyFrom(consensusExtraData) }); - if (!validationResult.Success) - { - Logger.LogDebug($"Consensus validating before execution failed: {validationResult.Message}"); - await LocalEventBus.PublishAsync(new ConsensusValidationFailedEventData - { - ValidationResultMessage = validationResult.Message, - IsReTrigger = validationResult.IsReTrigger - }); - } - - return validationResult.Success; + if (validationResult == null) + { + Logger.LogDebug("Validation of consensus failed before execution."); + return false; } - /// - /// Call ACS4 method ValidateConsensusAfterExecution. - /// - /// - /// - /// - public async Task ValidateConsensusAfterExecutionAsync(ChainContext chainContext, - byte[] consensusExtraData) + if (!validationResult.Success) { - var now = TimestampHelper.GetUtcNow(); - _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); + Logger.LogDebug($"Consensus validating before execution failed: {validationResult.Message}"); + await LocalEventBus.PublishAsync(new ConsensusValidationFailedEventData + { + ValidationResultMessage = validationResult.Message, + IsReTrigger = validationResult.IsReTrigger + }); + } - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - var validationResult = await _contractReaderFactory - .Create(contractReaderContext) - .ValidateConsensusAfterExecution - .CallAsync(new BytesValue {Value = ByteString.CopyFrom(consensusExtraData)}); + return validationResult.Success; + } - if (validationResult == null) - { - Logger.LogDebug("Validation of consensus failed after execution."); - return false; - } + /// + /// Call ACS4 method ValidateConsensusAfterExecution. + /// + /// + /// + /// + public async Task ValidateConsensusAfterExecutionAsync(ChainContext chainContext, + byte[] consensusExtraData) + { + var now = TimestampHelper.GetUtcNow(); + _blockTimeProvider.SetBlockTime(now, chainContext.BlockHash); - if (!validationResult.Success) - { - Logger.LogDebug($"Consensus validating after execution failed: {validationResult.Message}"); - await LocalEventBus.PublishAsync(new ConsensusValidationFailedEventData - { - ValidationResultMessage = validationResult.Message, - IsReTrigger = validationResult.IsReTrigger - }); - } - - return validationResult.Success; - } + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + var validationResult = await _contractReaderFactory + .Create(contractReaderContext) + .ValidateConsensusAfterExecution + .CallAsync(new BytesValue { Value = ByteString.CopyFrom(consensusExtraData) }); - /// - /// - /// Get consensus block header extra data. - /// - /// - /// - public async Task GetConsensusExtraDataAsync(ChainContext chainContext) + if (validationResult == null) { - _blockTimeProvider.SetBlockTime(_nextMiningTime, chainContext.BlockHash); - - Logger.LogDebug( - $"Block time of getting consensus extra data: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}."); - - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - var input = _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( - _consensusCommand.ToBytesValue()); - var consensusContractStub = _contractReaderFactory.Create(contractReaderContext); - var output = await consensusContractStub.GetConsensusExtraData.CallAsync(input); - return output.Value.ToByteArray(); + Logger.LogDebug("Validation of consensus failed after execution."); + return false; } - /// - /// Get consensus system tx list. - /// - /// - /// - public async Task> GenerateConsensusTransactionsAsync(ChainContext chainContext) + if (!validationResult.Success) { - _blockTimeProvider.SetBlockTime(_nextMiningTime, chainContext.BlockHash); - - Logger.LogDebug( - $"Block time of getting consensus system txs: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}."); - - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - var generatedTransactions = - (await _contractReaderFactory - .Create(contractReaderContext) - .GenerateConsensusTransactions - .CallAsync(_triggerInformationProvider.GetTriggerInformationForConsensusTransactions( - _consensusCommand.ToBytesValue()))) - .Transactions - .ToList(); - - // Complete these transactions. - foreach (var generatedTransaction in generatedTransactions) + Logger.LogDebug($"Consensus validating after execution failed: {validationResult.Message}"); + await LocalEventBus.PublishAsync(new ConsensusValidationFailedEventData { - generatedTransaction.RefBlockNumber = chainContext.BlockHeight; - generatedTransaction.RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(chainContext.BlockHash); - Logger.LogDebug($"Consensus transaction generated: \n{generatedTransaction.GetHash()}"); - } + ValidationResultMessage = validationResult.Message, + IsReTrigger = validationResult.IsReTrigger + }); + } + + return validationResult.Success; + } + + /// + /// + /// Get consensus block header extra data. + /// + /// + /// + public async Task GetConsensusExtraDataAsync(ChainContext chainContext) + { + _blockTimeProvider.SetBlockTime(_nextMiningTime, chainContext.BlockHash); + + Logger.LogDebug( + $"Block time of getting consensus extra data: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}."); + + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + var input = _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( + _consensusCommand.ToBytesValue()); + var consensusContractStub = _contractReaderFactory.Create(contractReaderContext); + var output = await consensusContractStub.GetConsensusExtraData.CallAsync(input); + return output.Value.ToByteArray(); + } + + /// + /// Get consensus system tx list. + /// + /// + /// + public async Task> GenerateConsensusTransactionsAsync(ChainContext chainContext) + { + _blockTimeProvider.SetBlockTime(_nextMiningTime, chainContext.BlockHash); + + Logger.LogDebug( + $"Block time of getting consensus system txs: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}."); - return generatedTransactions; + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + var generatedTransactions = + (await _contractReaderFactory + .Create(contractReaderContext) + .GenerateConsensusTransactions + .CallAsync(_triggerInformationProvider.GetTriggerInformationForConsensusTransactions( + _consensusCommand.ToBytesValue()))) + .Transactions + .ToList(); + + // Complete these transactions. + foreach (var generatedTransaction in generatedTransactions) + { + generatedTransaction.RefBlockNumber = chainContext.BlockHeight; + generatedTransaction.RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(chainContext.BlockHash); + Logger.LogDebug($"Consensus transaction generated: \n{generatedTransaction.GetHash()}"); } + + return generatedTransactions; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusTransactionGenerator.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusTransactionGenerator.cs index 2f0c761192..2f1821ac87 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusTransactionGenerator.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusTransactionGenerator.cs @@ -3,22 +3,21 @@ using AElf.Kernel.Miner.Application; using AElf.Types; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public class ConsensusTransactionGenerator : ISystemTransactionGenerator { - public class ConsensusTransactionGenerator : ISystemTransactionGenerator - { - private readonly IConsensusService _consensusService; + private readonly IConsensusService _consensusService; - public ConsensusTransactionGenerator(IConsensusService consensusService) - { - _consensusService = consensusService; - } + public ConsensusTransactionGenerator(IConsensusService consensusService) + { + _consensusService = consensusService; + } - public async Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, - Hash preBlockHash) - { - return await _consensusService.GenerateConsensusTransactionsAsync(new ChainContext - {BlockHash = preBlockHash, BlockHeight = preBlockHeight}); - } + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + return await _consensusService.GenerateConsensusTransactionsAsync(new ChainContext + { BlockHash = preBlockHash, BlockHeight = preBlockHeight }); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusValidationProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusValidationProvider.cs index a35b231ed4..77080b5755 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusValidationProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusValidationProvider.cs @@ -6,115 +6,114 @@ using AElf.Kernel.Txn.Application; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public class ConsensusValidationProvider : IBlockValidationProvider { - public class ConsensusValidationProvider : IBlockValidationProvider + private readonly IBlockchainService _blockchainService; + private readonly IConsensusExtraDataExtractor _consensusExtraDataExtractor; + private readonly IConsensusService _consensusService; + private readonly int _systemTransactionCount; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + + public ConsensusValidationProvider(IConsensusService consensusService, + ITransactionPackingOptionProvider transactionPackingOptionProvider, + IBlockchainService blockchainService, + IConsensusExtraDataExtractor consensusExtraDataExtractor, + IEnumerable systemTransactionGenerators) { - private readonly IConsensusService _consensusService; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - private readonly IBlockchainService _blockchainService; - private readonly IConsensusExtraDataExtractor _consensusExtraDataExtractor; - private readonly int _systemTransactionCount; - public ILogger Logger { get; set; } - - public ConsensusValidationProvider(IConsensusService consensusService, - ITransactionPackingOptionProvider transactionPackingOptionProvider, - IBlockchainService blockchainService, - IConsensusExtraDataExtractor consensusExtraDataExtractor, - IEnumerable systemTransactionGenerators) - { - _consensusService = consensusService; - _transactionPackingOptionProvider = transactionPackingOptionProvider; - _blockchainService = blockchainService; - _consensusExtraDataExtractor = consensusExtraDataExtractor; - _systemTransactionCount = systemTransactionGenerators.Count(); + _consensusService = consensusService; + _transactionPackingOptionProvider = transactionPackingOptionProvider; + _blockchainService = blockchainService; + _consensusExtraDataExtractor = consensusExtraDataExtractor; + _systemTransactionCount = systemTransactionGenerators.Count(); + + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public async Task ValidateBeforeAttachAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) + return true; - Logger = NullLogger.Instance; + if (block.Header.ExtraData.Count == 0) + { + Logger.LogDebug($"Block header extra data is empty {block}"); + return false; } - public async Task ValidateBeforeAttachAsync(IBlock block) + var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); + if (consensusExtraData == null || consensusExtraData.IsEmpty) { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) - return true; - - if (block.Header.ExtraData.Count == 0) - { - Logger.LogDebug($"Block header extra data is empty {block}"); - return false; - } - - var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); - if (consensusExtraData == null || consensusExtraData.IsEmpty) - { - Logger.LogDebug($"Invalid consensus extra data {block}"); - return false; - } + Logger.LogDebug($"Invalid consensus extra data {block}"); + return false; + } + return true; + } + + public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) return true; - } - public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); + if (consensusExtraData == null || consensusExtraData.IsEmpty) { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) - return true; - - var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); - if (consensusExtraData == null || consensusExtraData.IsEmpty) - { - Logger.LogDebug($"Invalid consensus extra data {block}"); - return false; - } - - var isValid = await _consensusService.ValidateConsensusBeforeExecutionAsync(new ChainContext - { - BlockHash = block.Header.PreviousBlockHash, - BlockHeight = block.Header.Height - 1 - }, consensusExtraData.ToByteArray()); - if (!isValid) return false; - - return ValidateTransactionCount(block); + Logger.LogDebug($"Invalid consensus extra data {block}"); + return false; } - private bool ValidateTransactionCount(IBlock block) + var isValid = await _consensusService.ValidateConsensusBeforeExecutionAsync(new ChainContext { - var chainContext = new ChainContext - { - BlockHash = block.Header.PreviousBlockHash, - BlockHeight = block.Header.Height - 1 - }; - if (_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) - return true; - - if (block.Body.TransactionsCount > _systemTransactionCount) - { - Logger.LogDebug("Cannot package normal transaction."); - return false; - } + BlockHash = block.Header.PreviousBlockHash, + BlockHeight = block.Header.Height - 1 + }, consensusExtraData.ToByteArray()); + if (!isValid) return false; + return ValidateTransactionCount(block); + } + + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) return true; + + var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); + if (consensusExtraData == null || consensusExtraData.IsEmpty) + { + Logger.LogDebug($"Invalid consensus extra data {block}"); + return false; } - public async Task ValidateBlockAfterExecuteAsync(IBlock block) + var isValid = await _consensusService.ValidateConsensusAfterExecutionAsync(new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Header.Height + }, consensusExtraData.ToByteArray()); + + return isValid; + } + + private bool ValidateTransactionCount(IBlock block) + { + var chainContext = new ChainContext { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) - return true; - - var consensusExtraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(block.Header); - if (consensusExtraData == null || consensusExtraData.IsEmpty) - { - Logger.LogDebug($"Invalid consensus extra data {block}"); - return false; - } - - var isValid = await _consensusService.ValidateConsensusAfterExecutionAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Header.Height - }, consensusExtraData.ToByteArray()); - - return isValid; + BlockHash = block.Header.PreviousBlockHash, + BlockHeight = block.Header.Height - 1 + }; + if (_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) + return true; + + if (block.Body.TransactionsCount > _systemTransactionCount) + { + Logger.LogDebug("Cannot package normal transaction."); + return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IBlockTimeProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/IBlockTimeProvider.cs index 95d686fd6a..07b5786957 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IBlockTimeProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IBlockTimeProvider.cs @@ -2,26 +2,25 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IBlockTimeProvider +{ + Timestamp GetBlockTime(Hash blockHash); + void SetBlockTime(Timestamp blockTime, Hash blockHash); +} + +public class BlockTimeProvider : IBlockTimeProvider, ISingletonDependency { - public interface IBlockTimeProvider + private Timestamp _blockTime; + + public Timestamp GetBlockTime(Hash blockHash) { - Timestamp GetBlockTime(Hash blockHash); - void SetBlockTime(Timestamp blockTime, Hash blockHash); + return _blockTime == default ? TimestampHelper.GetUtcNow() : _blockTime; } - public class BlockTimeProvider : IBlockTimeProvider, ISingletonDependency + public void SetBlockTime(Timestamp blockTime, Hash blockHash) { - private Timestamp _blockTime; - - public Timestamp GetBlockTime(Hash blockHash) - { - return _blockTime == default ? TimestampHelper.GetUtcNow() : _blockTime; - } - - public void SetBlockTime(Timestamp blockTime, Hash blockHash) - { - _blockTime = blockTime; - } + _blockTime = blockTime; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IBroadcastPrivilegedPubkeyListProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/IBroadcastPrivilegedPubkeyListProvider.cs index 3087d40f9d..0494c3130f 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IBroadcastPrivilegedPubkeyListProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IBroadcastPrivilegedPubkeyListProvider.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IBroadcastPrivilegedPubkeyListProvider { - public interface IBroadcastPrivilegedPubkeyListProvider - { - Task> GetPubkeyList(BlockHeader blockHeader); - } + Task> GetPubkeyList(BlockHeader blockHeader); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataExtractor.cs b/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataExtractor.cs index 4be7d2ed3c..35b52e0d7a 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataExtractor.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataExtractor.cs @@ -1,9 +1,8 @@ using Google.Protobuf; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IConsensusExtraDataExtractor { - public interface IConsensusExtraDataExtractor - { - ByteString ExtractConsensusExtraData(BlockHeader header); - } + ByteString ExtractConsensusExtraData(BlockHeader header); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataProvider.cs index 8a01b08d53..b70b079a4e 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IConsensusExtraDataProvider.cs @@ -1,8 +1,7 @@ using AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IConsensusExtraDataProvider : IBlockExtraDataProvider { - public interface IConsensusExtraDataProvider : IBlockExtraDataProvider - { - } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IConsensusReaderContextService.cs b/src/AElf.Kernel.Consensus.Core/Application/IConsensusReaderContextService.cs index e2a946032a..14984c7263 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IConsensusReaderContextService.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IConsensusReaderContextService.cs @@ -3,42 +3,41 @@ using AElf.Kernel.SmartContract.Application; using AElf.Types; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IConsensusReaderContextService +{ + Task GetContractReaderContextAsync(IChainContext chainContext); +} + +public class ConsensusReaderContextService : IConsensusReaderContextService { - public interface IConsensusReaderContextService + private readonly IAccountService _accountService; + private readonly IBlockTimeProvider _blockTimeProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ConsensusReaderContextService(IBlockTimeProvider blockTimeProvider, IAccountService accountService, + ISmartContractAddressService smartContractAddressService) { - Task GetContractReaderContextAsync(IChainContext chainContext); + _blockTimeProvider = blockTimeProvider; + _accountService = accountService; + _smartContractAddressService = smartContractAddressService; } - public class ConsensusReaderContextService : IConsensusReaderContextService + public async Task GetContractReaderContextAsync(IChainContext chainContext) { - private readonly IBlockTimeProvider _blockTimeProvider; - private readonly IAccountService _accountService; - private readonly ISmartContractAddressService _smartContractAddressService; + var timestamp = _blockTimeProvider.GetBlockTime(chainContext.BlockHash); + var sender = Address.FromPublicKey(await _accountService.GetPublicKeyAsync()); + var consensusContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( + chainContext, ConsensusSmartContractAddressNameProvider.StringName); - public ConsensusReaderContextService(IBlockTimeProvider blockTimeProvider, IAccountService accountService, - ISmartContractAddressService smartContractAddressService) + return new ContractReaderContext { - _blockTimeProvider = blockTimeProvider; - _accountService = accountService; - _smartContractAddressService = smartContractAddressService; - } - - public async Task GetContractReaderContextAsync(IChainContext chainContext) - { - var timestamp = _blockTimeProvider.GetBlockTime(chainContext.BlockHash); - var sender = Address.FromPublicKey(await _accountService.GetPublicKeyAsync()); - var consensusContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( - chainContext, ConsensusSmartContractAddressNameProvider.StringName); - - return new ContractReaderContext - { - BlockHash = chainContext.BlockHash, - BlockHeight = chainContext.BlockHeight, - ContractAddress = consensusContractAddress, - Sender = sender, - Timestamp = timestamp - }; - } + BlockHash = chainContext.BlockHash, + BlockHeight = chainContext.BlockHeight, + ContractAddress = consensusContractAddress, + Sender = sender, + Timestamp = timestamp + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IConsensusScheduler.cs b/src/AElf.Kernel.Consensus.Core/Application/IConsensusScheduler.cs index 63c16e3bc0..fe780a001e 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IConsensusScheduler.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IConsensusScheduler.cs @@ -1,17 +1,16 @@ -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IConsensusScheduler { - public interface IConsensusScheduler - { - /// - /// Update scheduler event. - /// - /// - /// - void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData); + /// + /// Update scheduler event. + /// + /// + /// + void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData); - /// - /// Cancel previous event. - /// - void CancelCurrentEvent(); - } + /// + /// Cancel previous event. + /// + void CancelCurrentEvent(); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/IConsensusService.cs b/src/AElf.Kernel.Consensus.Core/Application/IConsensusService.cs index a0b73f0841..d920dea3c7 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/IConsensusService.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/IConsensusService.cs @@ -2,47 +2,46 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public interface IConsensusService { - public interface IConsensusService - { - /// - /// To trigger the consensus scheduler at the starting of current node. - /// - /// - Task TriggerConsensusAsync(ChainContext chainContext); + /// + /// To trigger the consensus scheduler at the starting of current node. + /// + /// + Task TriggerConsensusAsync(ChainContext chainContext); - /// - /// To validate the consensus information extracted from block header extra data. - /// - /// - /// Extract from block header. - /// - Task ValidateConsensusBeforeExecutionAsync(ChainContext chainContext, - byte[] consensusExtraData); + /// + /// To validate the consensus information extracted from block header extra data. + /// + /// + /// Extract from block header. + /// + Task ValidateConsensusBeforeExecutionAsync(ChainContext chainContext, + byte[] consensusExtraData); - /// - /// To validate the consensus information extracted from block header extra data. - /// - /// - /// Extract from block header. - /// - Task ValidateConsensusAfterExecutionAsync(ChainContext chainContext, - byte[] consensusExtraData); + /// + /// To validate the consensus information extracted from block header extra data. + /// + /// + /// Extract from block header. + /// + Task ValidateConsensusAfterExecutionAsync(ChainContext chainContext, + byte[] consensusExtraData); - /// - /// After the execution of consensus transactions, the new consensus - /// information will emerge from consensus contract. - /// The consensus information will used to fill block header extra - /// data of new block. - /// - /// - Task GetConsensusExtraDataAsync(ChainContext chainContext); + /// + /// After the execution of consensus transactions, the new consensus + /// information will emerge from consensus contract. + /// The consensus information will used to fill block header extra + /// data of new block. + /// + /// + Task GetConsensusExtraDataAsync(ChainContext chainContext); - /// - /// Generate consensus transactions from consensus contract. - /// - /// - Task> GenerateConsensusTransactionsAsync(ChainContext chainContext); - } + /// + /// Generate consensus transactions from consensus contract. + /// + /// + Task> GenerateConsensusTransactionsAsync(ChainContext chainContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs index 00b06049b7..26567a68b5 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs @@ -1,12 +1,11 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +// ReSharper disable UnusedParameter.Global +public interface ITriggerInformationProvider { - // ReSharper disable UnusedParameter.Global - public interface ITriggerInformationProvider - { - BytesValue GetTriggerInformationForConsensusCommand(BytesValue consensusCommandBytes); - BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes); - BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes); - } + BytesValue GetTriggerInformationForConsensusCommand(BytesValue consensusCommandBytes); + BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes); + BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/ConsensusConstants.cs b/src/AElf.Kernel.Consensus.Core/ConsensusConstants.cs index 82cf63fea7..4b838b9fac 100644 --- a/src/AElf.Kernel.Consensus.Core/ConsensusConstants.cs +++ b/src/AElf.Kernel.Consensus.Core/ConsensusConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public static class ConsensusConstants { - public static class ConsensusConstants - { - public const long MaximumLeftMillisecondsForNextBlock = 3600_000; + public const long MaximumLeftMillisecondsForNextBlock = 3600_000; - public const string ConsensusExtraDataKey = "Consensus"; - } + public const string ConsensusExtraDataKey = "Consensus"; } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/ConsensusRequestMiningEventData.cs b/src/AElf.Kernel.Consensus.Core/ConsensusRequestMiningEventData.cs index 370281f5b1..6681ba8375 100644 --- a/src/AElf.Kernel.Consensus.Core/ConsensusRequestMiningEventData.cs +++ b/src/AElf.Kernel.Consensus.Core/ConsensusRequestMiningEventData.cs @@ -1,25 +1,23 @@ -using System; -using Google.Protobuf.WellKnownTypes; using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Kernel.Consensus; -namespace AElf.Kernel.Consensus +public class ConsensusRequestMiningEventData { - public class ConsensusRequestMiningEventData + public ConsensusRequestMiningEventData(Hash previousBlockHash, long previousBlockHeight, Timestamp blockTime, + Duration blockExecutionTime, Timestamp miningDueTime) { - public Hash PreviousBlockHash { get; } - public long PreviousBlockHeight { get; } - public Duration BlockExecutionTime { get; } - public Timestamp BlockTime { get; } - public Timestamp MiningDueTime { get; set; } - - public ConsensusRequestMiningEventData(Hash previousBlockHash, long previousBlockHeight, Timestamp blockTime, - Duration blockExecutionTime, Timestamp miningDueTime) - { - PreviousBlockHash = previousBlockHash; - PreviousBlockHeight = previousBlockHeight; - BlockTime = blockTime; - BlockExecutionTime = blockExecutionTime; - MiningDueTime = miningDueTime; - } + PreviousBlockHash = previousBlockHash; + PreviousBlockHeight = previousBlockHeight; + BlockTime = blockTime; + BlockExecutionTime = blockExecutionTime; + MiningDueTime = miningDueTime; } + + public Hash PreviousBlockHash { get; } + public long PreviousBlockHeight { get; } + public Duration BlockExecutionTime { get; } + public Timestamp BlockTime { get; } + public Timestamp MiningDueTime { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/ConsensusSmartContractAddressNameProvider.cs b/src/AElf.Kernel.Consensus.Core/ConsensusSmartContractAddressNameProvider.cs index 9d55ef713f..32c92339a4 100644 --- a/src/AElf.Kernel.Consensus.Core/ConsensusSmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/ConsensusSmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public class ConsensusSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ConsensusSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); + public static Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/ConsensusValidationFailedEventData.cs b/src/AElf.Kernel.Consensus.Core/ConsensusValidationFailedEventData.cs index f06707bfc0..b51c99cd56 100644 --- a/src/AElf.Kernel.Consensus.Core/ConsensusValidationFailedEventData.cs +++ b/src/AElf.Kernel.Consensus.Core/ConsensusValidationFailedEventData.cs @@ -1,8 +1,7 @@ -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public class ConsensusValidationFailedEventData { - public class ConsensusValidationFailedEventData - { - public string ValidationResultMessage { get; set; } - public bool IsReTrigger { get; set; } - } + public string ValidationResultMessage { get; set; } + public bool IsReTrigger { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Core/CoreConsensusAElfModule.cs b/src/AElf.Kernel.Consensus.Core/CoreConsensusAElfModule.cs index c02c544fb9..4535545f26 100644 --- a/src/AElf.Kernel.Consensus.Core/CoreConsensusAElfModule.cs +++ b/src/AElf.Kernel.Consensus.Core/CoreConsensusAElfModule.cs @@ -5,16 +5,15 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public class CoreConsensusAElfModule : AElfModule { - public class CoreConsensusAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddSingleton(); - context.Services.AddTransient(); - } + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.AddTransient(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj index d5a1b3de3b..5eca3a7a60 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj +++ b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/AElf.Kernel.Consensus.Scheduler.FluentScheduler.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,11 +9,11 @@ - + - + diff --git a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerAElfModule.cs b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerAElfModule.cs index 41cc8d6f9e..6cb8f204c1 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerAElfModule.cs +++ b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerAElfModule.cs @@ -3,13 +3,12 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.Consensus.Scheduler.FluentScheduler +namespace AElf.Kernel.Consensus.Scheduler.FluentScheduler; + +public class FluentSchedulerAElfModule : AElfModule { - public class FluentSchedulerAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerScheduler.cs b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerScheduler.cs index 872cbfdab4..8033b8b517 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerScheduler.cs +++ b/src/AElf.Kernel.Consensus.Scheduler.FluentScheduler/FluentSchedulerScheduler.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using AElf.CSharp.Core.Extension; using AElf.Kernel.Consensus.Application; using FluentScheduler; @@ -8,37 +7,33 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Consensus.Scheduler.FluentScheduler +namespace AElf.Kernel.Consensus.Scheduler.FluentScheduler; + +public class FluentSchedulerScheduler : IConsensusScheduler, ISingletonDependency { - public class FluentSchedulerScheduler : IConsensusScheduler, ISingletonDependency + public FluentSchedulerScheduler() + { + LocalEventBus = NullLocalEventBus.Instance; + + Logger = NullLogger.Instance; + } + + public ILocalEventBus LocalEventBus { get; set; } + + public ILogger Logger { get; set; } + + public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) + { + JobManager.UseUtcTime(); + + var registry = new Registry(); + registry.Schedule(() => LocalEventBus.PublishAsync(consensusRequestMiningEventData)) + .ToRunOnceAt(TimestampHelper.GetUtcNow().AddMilliseconds(countingMilliseconds).ToDateTime()); + JobManager.Initialize(registry); + } + + public void CancelCurrentEvent() { - public ILocalEventBus LocalEventBus { get; set; } - - public ILogger Logger { get; set; } - - public FluentSchedulerScheduler() - { - LocalEventBus = NullLocalEventBus.Instance; - - Logger = NullLogger.Instance; - } - - public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) - { - JobManager.UseUtcTime(); - - var registry = new Registry(); - registry.Schedule(() => LocalEventBus.PublishAsync(consensusRequestMiningEventData)) - .ToRunOnceAt(TimestampHelper.GetUtcNow().AddMilliseconds(countingMilliseconds).ToDateTime()); - JobManager.Initialize(registry); - } - - public void CancelCurrentEvent() - { - if (JobManager.RunningSchedules.Any()) - { - JobManager.Stop(); - } - } + if (JobManager.RunningSchedules.Any()) JobManager.Stop(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Scheduler.RxNet/AElf.Kernel.Consensus.Scheduler.RxNet.csproj b/src/AElf.Kernel.Consensus.Scheduler.RxNet/AElf.Kernel.Consensus.Scheduler.RxNet.csproj index a7d4fd1cb3..dfd729dd0c 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.RxNet/AElf.Kernel.Consensus.Scheduler.RxNet.csproj +++ b/src/AElf.Kernel.Consensus.Scheduler.RxNet/AElf.Kernel.Consensus.Scheduler.RxNet.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,11 +9,11 @@ - + - + diff --git a/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetScheduler.cs b/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetScheduler.cs index 9db109b81c..afb10b63d9 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetScheduler.cs +++ b/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetScheduler.cs @@ -7,55 +7,57 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Consensus.Scheduler.RxNet +namespace AElf.Kernel.Consensus.Scheduler.RxNet; + +public class RxNetScheduler : IConsensusScheduler, IObserver, ISingletonDependency { - public class RxNetScheduler : IConsensusScheduler, IObserver, ISingletonDependency - { - private IDisposable _observables; + private IDisposable _observables; - public ILocalEventBus LocalEventBus { get; set; } + public RxNetScheduler() + { + LocalEventBus = NullLocalEventBus.Instance; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public RxNetScheduler() - { - LocalEventBus = NullLocalEventBus.Instance; + public ILocalEventBus LocalEventBus { get; set; } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) - { - _observables = Subscribe(countingMilliseconds, consensusRequestMiningEventData); - } + public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) + { + _observables = Subscribe(countingMilliseconds, consensusRequestMiningEventData); + } - public void CancelCurrentEvent() - { - _observables?.Dispose(); - } + public void CancelCurrentEvent() + { + _observables?.Dispose(); + } - public IDisposable Subscribe(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) - { - Logger.LogDebug($"Will produce block after {countingMilliseconds} ms - " + - $"{TimestampHelper.GetUtcNow().AddMilliseconds(countingMilliseconds).ToDateTime():yyyy-MM-dd HH.mm.ss,fff}"); + public void OnCompleted() + { + } - return Observable.Timer(TimeSpan.FromMilliseconds(countingMilliseconds)) - .Select(_ => consensusRequestMiningEventData).Subscribe(this); - } + public void OnError(Exception error) + { + } - public void OnCompleted() - { - } + // This is the callback. + public void OnNext(ConsensusRequestMiningEventData value) + { + Logger.LogDebug("Published block mining event. Current block height: {PreviousBlockHeight}", + value.PreviousBlockHeight); + LocalEventBus.PublishAsync(value); + } - public void OnError(Exception error) - { - } + public IDisposable Subscribe(long countingMilliseconds, + ConsensusRequestMiningEventData consensusRequestMiningEventData) + { + Logger.LogDebug("Will produce block after {CountingMilliseconds} ms - {Time}", countingMilliseconds, + TimestampHelper.GetUtcNow().AddMilliseconds(countingMilliseconds).ToDateTime() + .ToString("yyyy-MM-dd HH.mm.ss,fff")); - // This is the callback. - public void OnNext(ConsensusRequestMiningEventData value) - { - Logger.LogDebug($"Published block mining event. Current block height: {value.PreviousBlockHeight}"); - LocalEventBus.PublishAsync(value); - } + return Observable.Timer(TimeSpan.FromMilliseconds(countingMilliseconds)) + .Select(_ => consensusRequestMiningEventData).Subscribe(this); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetSchedulerAElfModule.cs b/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetSchedulerAElfModule.cs index 745bda7317..c2b28a0409 100644 --- a/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetSchedulerAElfModule.cs +++ b/src/AElf.Kernel.Consensus.Scheduler.RxNet/RxNetSchedulerAElfModule.cs @@ -3,13 +3,12 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.Consensus.Scheduler.RxNet +namespace AElf.Kernel.Consensus.Scheduler.RxNet; + +public class RxNetSchedulerAElfModule : AElfModule { - public class RxNetSchedulerAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/AElf.Kernel.Core.csproj b/src/AElf.Kernel.Core/AElf.Kernel.Core.csproj index 99ddd91f24..483d11bfc3 100644 --- a/src/AElf.Kernel.Core/AElf.Kernel.Core.csproj +++ b/src/AElf.Kernel.Core/AElf.Kernel.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Kernel @@ -13,13 +13,13 @@ true - - + + - - - - + + + + \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs index 2cc953485b..fa47a8ecc5 100644 --- a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs +++ b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs @@ -1,64 +1,56 @@ -using System.Threading.Tasks; -using AElf.Types; using AElf.Cryptography; -using AElf.Cryptography.ECDSA; using AElf.Kernel.Account.Infrastructure; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Account.Application +namespace AElf.Kernel.Account.Application; + +public interface IAccountService +{ + Task SignAsync(byte[] data); + Task GetPublicKeyAsync(); + Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage); + Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage); +} + +public static class AccountServiceExtensions { - public interface IAccountService + public static async Task
GetAccountAsync(this IAccountService accountService) { - Task SignAsync(byte[] data); - Task GetPublicKeyAsync(); - Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage); - Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage); + return Address.FromPublicKey(await accountService.GetPublicKeyAsync()); } +} - public static class AccountServiceExtensions +/// +/// Really need this service to provide key pairs during dpos consensus testing. +/// +public class AccountService : IAccountService, ISingletonDependency +{ + private readonly IAElfAsymmetricCipherKeyPairProvider _ecKeyPairProvider; + + public AccountService(IAElfAsymmetricCipherKeyPairProvider ecKeyPairProvider) { - public static async Task
GetAccountAsync(this IAccountService accountService) - { - return Address.FromPublicKey(await accountService.GetPublicKeyAsync()); - } + _ecKeyPairProvider = ecKeyPairProvider; } - /// - /// Really need this service to provide key pairs during dpos consensus testing. - /// - public class AccountService : IAccountService, ISingletonDependency + public Task SignAsync(byte[] data) { - private readonly IAElfAsymmetricCipherKeyPairProvider _ecKeyPairProvider; - - public AccountService(IAElfAsymmetricCipherKeyPairProvider ecKeyPairProvider) - { - _ecKeyPairProvider = ecKeyPairProvider; - } - - public Task SignAsync(byte[] data) - { - var signature = CryptoHelper.SignWithPrivateKey(_ecKeyPairProvider.GetKeyPair().PrivateKey, data); - return Task.FromResult(signature); - } - + var signature = CryptoHelper.SignWithPrivateKey(_ecKeyPairProvider.GetKeyPair().PrivateKey, data); + return Task.FromResult(signature); + } - public Task GetPublicKeyAsync() - { - return Task.FromResult(_ecKeyPairProvider.GetKeyPair().PublicKey); - } + public Task GetPublicKeyAsync() + { + return Task.FromResult(_ecKeyPairProvider.GetKeyPair().PublicKey); + } - public Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage) - { - return Task.FromResult(CryptoHelper.EncryptMessage(_ecKeyPairProvider.GetKeyPair().PrivateKey, - receiverPublicKey, - plainMessage)); - } + public Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage) + { + return Task.FromResult(CryptoHelper.EncryptMessage(_ecKeyPairProvider.GetKeyPair().PrivateKey, + receiverPublicKey, plainMessage)); + } - public Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage) - { - return Task.FromResult(CryptoHelper.DecryptMessage(senderPublicKey, - _ecKeyPairProvider.GetKeyPair().PrivateKey, - cipherMessage)); - } + public Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage) + { + return Task.FromResult(CryptoHelper.DecryptMessage(senderPublicKey, + _ecKeyPairProvider.GetKeyPair().PrivateKey, cipherMessage)); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Account/Infrastructure/AElfAsymmetricCipherKeyPairProvider.cs b/src/AElf.Kernel.Core/Account/Infrastructure/AElfAsymmetricCipherKeyPairProvider.cs index afd4c0f7a2..321f0f0d2e 100644 --- a/src/AElf.Kernel.Core/Account/Infrastructure/AElfAsymmetricCipherKeyPairProvider.cs +++ b/src/AElf.Kernel.Core/Account/Infrastructure/AElfAsymmetricCipherKeyPairProvider.cs @@ -1,20 +1,18 @@ using AElf.Cryptography; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Account.Infrastructure +namespace AElf.Kernel.Account.Infrastructure; + +public class AElfAsymmetricCipherKeyPairProvider : IAElfAsymmetricCipherKeyPairProvider, ISingletonDependency { - public class AElfAsymmetricCipherKeyPairProvider : IAElfAsymmetricCipherKeyPairProvider, ISingletonDependency - { - private IAElfAsymmetricCipherKeyPair _keyPair; + private IAElfAsymmetricCipherKeyPair _keyPair; - public void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair) - { - _keyPair = ecKeyPair; - } + public void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair) + { + _keyPair = ecKeyPair; + } - public IAElfAsymmetricCipherKeyPair GetKeyPair() - { - return _keyPair; - } + public IAElfAsymmetricCipherKeyPair GetKeyPair() + { + return _keyPair; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Account/Infrastructure/IAElfAsymmetricCipherKeyPairProvider.cs b/src/AElf.Kernel.Core/Account/Infrastructure/IAElfAsymmetricCipherKeyPairProvider.cs index 070434ac82..750c038a5a 100644 --- a/src/AElf.Kernel.Core/Account/Infrastructure/IAElfAsymmetricCipherKeyPairProvider.cs +++ b/src/AElf.Kernel.Core/Account/Infrastructure/IAElfAsymmetricCipherKeyPairProvider.cs @@ -1,10 +1,9 @@ using AElf.Cryptography; -namespace AElf.Kernel.Account.Infrastructure +namespace AElf.Kernel.Account.Infrastructure; + +public interface IAElfAsymmetricCipherKeyPairProvider { - public interface IAElfAsymmetricCipherKeyPairProvider - { - void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair); - IAElfAsymmetricCipherKeyPair GetKeyPair(); - } + void SetKeyPair(IAElfAsymmetricCipherKeyPair ecKeyPair); + IAElfAsymmetricCipherKeyPair GetKeyPair(); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/BlockExtraDataService.cs b/src/AElf.Kernel.Core/Blockchain/Application/BlockExtraDataService.cs index 9b005fd742..f48a6da6ac 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/BlockExtraDataService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/BlockExtraDataService.cs @@ -1,41 +1,35 @@ -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Google.Protobuf; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public class BlockExtraDataService : IBlockExtraDataService { - public class BlockExtraDataService : IBlockExtraDataService - { - private readonly List _blockExtraDataProviders; + private readonly List _blockExtraDataProviders; - public BlockExtraDataService(IEnumerable blockExtraDataProviders) - { - _blockExtraDataProviders = blockExtraDataProviders.ToList(); - } + public BlockExtraDataService(IEnumerable blockExtraDataProviders) + { + _blockExtraDataProviders = blockExtraDataProviders.ToList(); + } - public async Task FillBlockExtraDataAsync(BlockHeader blockHeader) + public async Task FillBlockExtraDataAsync(BlockHeader blockHeader) + { + foreach (var blockExtraDataProvider in _blockExtraDataProviders) { - foreach (var blockExtraDataProvider in _blockExtraDataProviders) - { - var extraData = await blockExtraDataProvider.GetBlockHeaderExtraDataAsync(blockHeader); - if (extraData != null) - { - // Actually extraData cannot be NULL if it is mining processing, as the index in BlockExtraData is fixed. - // So it can be ByteString.Empty but not NULL. - blockHeader.ExtraData.Add(blockExtraDataProvider.BlockHeaderExtraDataKey, extraData); - } - } + var extraData = await blockExtraDataProvider.GetBlockHeaderExtraDataAsync(blockHeader); + if (extraData != null) + // Actually extraData cannot be NULL if it is mining processing, as the index in BlockExtraData is fixed. + // So it can be ByteString.Empty but not NULL. + blockHeader.ExtraData.Add(blockExtraDataProvider.BlockHeaderExtraDataKey, extraData); } + } - public ByteString GetExtraDataFromBlockHeader(string blockHeaderExtraDataKey, BlockHeader blockHeader) - { - if (blockHeader.Height == AElfConstants.GenesisBlockHeight) - return null; + public ByteString GetExtraDataFromBlockHeader(string blockHeaderExtraDataKey, BlockHeader blockHeader) + { + if (blockHeader.Height == AElfConstants.GenesisBlockHeight) + return null; - return blockHeader.ExtraData.TryGetValue(blockHeaderExtraDataKey, out var extraData) - ? extraData - : null; - } + return blockHeader.ExtraData.TryGetValue(blockHeaderExtraDataKey, out var extraData) + ? extraData + : null; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/BlockGenerationService.cs b/src/AElf.Kernel.Core/Blockchain/Application/BlockGenerationService.cs index 0134bfb225..1c4f87279e 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/BlockGenerationService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/BlockGenerationService.cs @@ -1,39 +1,37 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public class BlockGenerationService : IBlockGenerationService { - public class BlockGenerationService : IBlockGenerationService - { - private readonly IBlockExtraDataService _blockExtraDataService; - private readonly IStaticChainInformationProvider _staticChainInformationProvider; + private readonly IBlockExtraDataService _blockExtraDataService; + private readonly IStaticChainInformationProvider _staticChainInformationProvider; - public BlockGenerationService(IBlockExtraDataService blockExtraDataService, - IStaticChainInformationProvider staticChainInformationProvider) - { - _blockExtraDataService = blockExtraDataService; - _staticChainInformationProvider = staticChainInformationProvider; - } + public BlockGenerationService(IBlockExtraDataService blockExtraDataService, + IStaticChainInformationProvider staticChainInformationProvider) + { + _blockExtraDataService = blockExtraDataService; + _staticChainInformationProvider = staticChainInformationProvider; + } - public async Task GenerateBlockBeforeExecutionAsync(GenerateBlockDto generateBlockDto) + public async Task GenerateBlockBeforeExecutionAsync(GenerateBlockDto generateBlockDto) + { + var block = new Block { - var block = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - ChainId = _staticChainInformationProvider.ChainId, - Height = generateBlockDto.PreviousBlockHeight + 1, - PreviousBlockHash = generateBlockDto.PreviousBlockHash, - Time = generateBlockDto.BlockTime - }, - Body = new BlockBody() - }; + ChainId = _staticChainInformationProvider.ChainId, + Height = generateBlockDto.PreviousBlockHeight + 1, + PreviousBlockHash = generateBlockDto.PreviousBlockHash, + Time = generateBlockDto.BlockTime + }, + Body = new BlockBody() + }; - // get block extra data with _blockExtraDataService including consensus data, cross chain data etc.. - await _blockExtraDataService.FillBlockExtraDataAsync(block.Header); - // calculate and set tx merkle tree root - //block.Complete(currentBlockTime, results); - return block; - } + // get block extra data with _blockExtraDataService including consensus data, cross chain data etc.. + await _blockExtraDataService.FillBlockExtraDataAsync(block.Header); + // calculate and set tx merkle tree root + //block.Complete(currentBlockTime, results); + return block; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/ChainBlockLinkService.cs b/src/AElf.Kernel.Core/Blockchain/Application/ChainBlockLinkService.cs index ee1c5bad0d..10dcc8a1cd 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/ChainBlockLinkService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/ChainBlockLinkService.cs @@ -1,47 +1,42 @@ -using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; -using AElf.Types; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public interface IChainBlockLinkService +{ + List GetCachedChainBlockLinks(); + void CleanCachedChainBlockLinks(long height); + Task> GetNotExecutedChainBlockLinksAsync(Hash chainBranchBlockHash); + Task SetChainBlockLinkExecutionStatusAsync(Hash blockHash, ChainBlockLinkExecutionStatus status); +} + +public class ChainBlockLinkService : IChainBlockLinkService, ITransientDependency { - public interface IChainBlockLinkService + private readonly IChainManager _chainManager; + + public ChainBlockLinkService(IChainManager chainManager) { - List GetCachedChainBlockLinks(); - void CleanCachedChainBlockLinks(long height); - Task> GetNotExecutedChainBlockLinksAsync(Hash chainBranchBlockHash); - Task SetChainBlockLinkExecutionStatusAsync(Hash blockHash, ChainBlockLinkExecutionStatus status); + _chainManager = chainManager; } - public class ChainBlockLinkService : IChainBlockLinkService, ITransientDependency + public List GetCachedChainBlockLinks() { - private readonly IChainManager _chainManager; - - public ChainBlockLinkService(IChainManager chainManager) - { - _chainManager = chainManager; - } - - public List GetCachedChainBlockLinks() - { - return _chainManager.GetCachedChainBlockLinks(); - } - - public void CleanCachedChainBlockLinks(long height) - { - _chainManager.CleanCachedChainBlockLinks(height); - } - - public async Task> GetNotExecutedChainBlockLinksAsync(Hash chainBranchBlockHash) - { - return await _chainManager.GetNotExecutedBlocks(chainBranchBlockHash); - } - - public async Task SetChainBlockLinkExecutionStatusAsync(Hash blockHash, ChainBlockLinkExecutionStatus status) - { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(blockHash); - await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, status); - } + return _chainManager.GetCachedChainBlockLinks(); } -} + + public void CleanCachedChainBlockLinks(long height) + { + _chainManager.CleanCachedChainBlockLinks(height); + } + + public async Task> GetNotExecutedChainBlockLinksAsync(Hash chainBranchBlockHash) + { + return await _chainManager.GetNotExecutedBlocks(chainBranchBlockHash); + } + + public async Task SetChainBlockLinkExecutionStatusAsync(Hash blockHash, ChainBlockLinkExecutionStatus status) + { + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(blockHash); + await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, status); + } +} \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataProvider.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataProvider.cs index 715ce85f00..c86bcf3196 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataProvider.cs @@ -1,17 +1,13 @@ -using System.Threading.Tasks; -using Google.Protobuf; +namespace AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Blockchain.Application +public interface IBlockExtraDataProvider { - public interface IBlockExtraDataProvider - { - /// - /// Get extra data from corresponding services. - /// - /// - /// - Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader); + string BlockHeaderExtraDataKey { get; } - string BlockHeaderExtraDataKey { get; } - } + /// + /// Get extra data from corresponding services. + /// + /// + /// + Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataService.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataService.cs index 95f6dfa03c..8f61cef3a3 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockExtraDataService.cs @@ -1,20 +1,14 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; -using Google.Protobuf; +namespace AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Blockchain.Application +public interface IBlockExtraDataService { - public interface IBlockExtraDataService - { - Task FillBlockExtraDataAsync(BlockHeader blockHeader); + Task FillBlockExtraDataAsync(BlockHeader blockHeader); - /// - /// Get extra data from block header. - /// - /// - /// - /// - ByteString GetExtraDataFromBlockHeader(string blockHeaderExtraDataKey, BlockHeader blockHeader); - } + /// + /// Get extra data from block header. + /// + /// + /// + /// + ByteString GetExtraDataFromBlockHeader(string blockHeaderExtraDataKey, BlockHeader blockHeader); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockGenerationService.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockGenerationService.cs index be9321f5ee..d5b797c16c 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockGenerationService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockGenerationService.cs @@ -1,19 +1,16 @@ -using System.Threading.Tasks; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public class GenerateBlockDto { - public class GenerateBlockDto - { - public Hash PreviousBlockHash { get; set; } - public long PreviousBlockHeight { get; set; } + public Hash PreviousBlockHash { get; set; } + public long PreviousBlockHeight { get; set; } - public Timestamp BlockTime { get; set; } = TimestampHelper.GetUtcNow(); - } + public Timestamp BlockTime { get; set; } = TimestampHelper.GetUtcNow(); +} - public interface IBlockGenerationService - { - Task GenerateBlockBeforeExecutionAsync(GenerateBlockDto generateBlockDto); - } +public interface IBlockGenerationService +{ + Task GenerateBlockBeforeExecutionAsync(GenerateBlockDto generateBlockDto); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationProvider.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationProvider.cs index 0403990698..17e72098c5 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationProvider.cs @@ -1,176 +1,171 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; -using System.Threading.Tasks; -using AElf.Types; -using Microsoft.Extensions.Logging; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public interface IBlockValidationProvider +{ + Task ValidateBeforeAttachAsync(IBlock block); + Task ValidateBlockBeforeExecuteAsync(IBlock block); + Task ValidateBlockAfterExecuteAsync(IBlock block); +} + +[Serializable] +public class BlockValidationException : Exception { - public interface IBlockValidationProvider + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public BlockValidationException() { - Task ValidateBeforeAttachAsync(IBlock block); - Task ValidateBlockBeforeExecuteAsync(IBlock block); - Task ValidateBlockAfterExecuteAsync(IBlock block); } + public BlockValidationException(string message) : base(message) + { + } - [Serializable] - public class BlockValidationException : Exception + public BlockValidationException(string message, Exception inner) : base(message, inner) { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // - - public BlockValidationException() - { - } + } - public BlockValidationException(string message) : base(message) - { - } + protected BlockValidationException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { + } +} + +[Serializable] +public class ValidateNextTimeBlockValidationException : BlockValidationException +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public ValidateNextTimeBlockValidationException() + { + } + + public ValidateNextTimeBlockValidationException(string message) : base(message) + { + } + + public ValidateNextTimeBlockValidationException(string message, Exception inner) : base(message, inner) + { + } + + public ValidateNextTimeBlockValidationException(Hash blockhash) : this( + $"validate next time, block hash = {blockhash.ToHex()}") + { + BlockHash = blockhash; + } + + protected ValidateNextTimeBlockValidationException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { + } + + public Hash BlockHash { get; private set; } +} + +public class BlockValidationProvider : IBlockValidationProvider +{ + private readonly IBlockchainService _blockchainService; + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + + public BlockValidationProvider(IBlockchainService blockchainService, + ITransactionBlockIndexService transactionBlockIndexService) + { + _blockchainService = blockchainService; + _transactionBlockIndexService = transactionBlockIndexService; + } + + public ILogger Logger { get; set; } - public BlockValidationException(string message, Exception inner) : base(message, inner) + public Task ValidateBeforeAttachAsync(IBlock block) + { + if (block?.Header == null || block.Body == null) { + Logger.LogDebug("Block header or body is null"); + return Task.FromResult(false); } - protected BlockValidationException( - SerializationInfo info, - StreamingContext context) : base(info, context) + if (block.Body.TransactionsCount == 0) { + Logger.LogDebug("Block transactions is empty"); + return Task.FromResult(false); } - } - [Serializable] - public class ValidateNextTimeBlockValidationException : BlockValidationException - { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // - - public ValidateNextTimeBlockValidationException() + var hashSet = new HashSet(); + if (block.Body.TransactionIds.Select(item => hashSet.Add(item)).Any(addResult => !addResult)) { + Logger.LogDebug("Block contains duplicates transaction"); + return Task.FromResult(false); } - public ValidateNextTimeBlockValidationException(string message) : base(message) + if (_blockchainService.GetChainId() != block.Header.ChainId) { + Logger.LogDebug("Block chain id mismatch {ChainId}", block.Header.ChainId); + return Task.FromResult(false); } - public ValidateNextTimeBlockValidationException(string message, Exception inner) : base(message, inner) + if (block.Header.Height != AElfConstants.GenesisBlockHeight && !block.VerifySignature()) { + Logger.LogDebug("Block verify signature failed"); + return Task.FromResult(false); } - public ValidateNextTimeBlockValidationException(Hash blockhash) : this( - $"validate next time, block hash = {blockhash.ToHex()}") + if (block.Body.CalculateMerkleTreeRoot() != block.Header.MerkleTreeRootOfTransactions) { - BlockHash = blockhash; + Logger.LogDebug("Block merkle tree root mismatch"); + return Task.FromResult(false); } - protected ValidateNextTimeBlockValidationException( - SerializationInfo info, - StreamingContext context) : base(info, context) + if (block.Header.Height != AElfConstants.GenesisBlockHeight && + block.Header.Time.ToDateTime() - TimestampHelper.GetUtcNow().ToDateTime() > + KernelConstants.AllowedFutureBlockTimeSpan.ToTimeSpan()) { + Logger.LogDebug("Future block received {Block}, {BlockTime}", block, block.Header.Time.ToDateTime()); + return Task.FromResult(false); } - public Hash BlockHash { get; private set; } + return Task.FromResult(true); } - public class BlockValidationProvider : IBlockValidationProvider + public async Task ValidateBlockBeforeExecuteAsync(IBlock block) { - private readonly IBlockchainService _blockchainService; - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - public ILogger Logger { get; set; } + if (block?.Header == null || block.Body == null) + return false; - public BlockValidationProvider(IBlockchainService blockchainService, - ITransactionBlockIndexService transactionBlockIndexService) - { - _blockchainService = blockchainService; - _transactionBlockIndexService = transactionBlockIndexService; - } + if (block.Body.TransactionsCount == 0) + return false; - public Task ValidateBeforeAttachAsync(IBlock block) + // Verify that the transaction has been packaged in the current branch + foreach (var transactionId in block.TransactionIds) { - if (block?.Header == null || block.Body == null) - { - Logger.LogDebug("Block header or body is null."); - return Task.FromResult(false); - } - - if (block.Body.TransactionsCount == 0) - { - Logger.LogDebug("Block transactions is empty"); - return Task.FromResult(false); - } - - var hashSet = new HashSet(); - if (block.Body.TransactionIds.Select(item => hashSet.Add(item)).Any(addResult => !addResult)) - { - Logger.LogDebug("Block contains duplicates transaction"); - return Task.FromResult(false); - } - - if (_blockchainService.GetChainId() != block.Header.ChainId) - { - Logger.LogDebug($"Block chain id mismatch {block.Header.ChainId}"); - return Task.FromResult(false); - } - - if (block.Header.Height != AElfConstants.GenesisBlockHeight && !block.VerifySignature()) - { - Logger.LogDebug("Block verify signature failed."); - return Task.FromResult(false); - } - - if (block.Body.CalculateMerkleTreeRoot() != block.Header.MerkleTreeRootOfTransactions) - { - Logger.LogDebug("Block merkle tree root mismatch."); - return Task.FromResult(false); - } - - if (block.Header.Height != AElfConstants.GenesisBlockHeight && - block.Header.Time.ToDateTime() - TimestampHelper.GetUtcNow().ToDateTime() > - KernelConstants.AllowedFutureBlockTimeSpan.ToTimeSpan()) - { - Logger.LogDebug($"Future block received {block}, {block.Header.Time.ToDateTime()}"); - return Task.FromResult(false); - } - - return Task.FromResult(true); + var blockIndexExists = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(transactionId, + block.Header.PreviousBlockHash); + if (!blockIndexExists) + continue; + Logger.LogDebug("Transaction: {TransactionId} repackaged", transactionId); + return false; } - public async Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - if (block?.Header == null || block.Body == null) - return false; - - if (block.Body.TransactionsCount == 0) - return false; - - // Verify that the transaction has been packaged in the current branch - foreach (var transactionId in block.TransactionIds) - { - var blockIndexExists = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(transactionId, - block.Header.PreviousBlockHash); - if (!blockIndexExists) - continue; - Logger.LogDebug($"Transaction: {transactionId} repackaged."); - return false; - } - - return true; - } + return true; + } - public Task ValidateBlockAfterExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockAfterExecuteAsync(IBlock block) + { + return Task.FromResult(true); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationService.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationService.cs index 19e0a5ba0e..8701940e5d 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockValidationService.cs @@ -1,74 +1,58 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; +namespace AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Blockchain.Application +public interface IBlockValidationService { - public interface IBlockValidationService - { - Task ValidateBlockBeforeAttachAsync(IBlock block); - Task ValidateBlockBeforeExecuteAsync(IBlock block); + Task ValidateBlockBeforeAttachAsync(IBlock block); + Task ValidateBlockBeforeExecuteAsync(IBlock block); - Task ValidateBlockAfterExecuteAsync(IBlock block); - } + Task ValidateBlockAfterExecuteAsync(IBlock block); +} - public class BlockValidationService : IBlockValidationService, ITransientDependency - { - public ILogger Logger { get; set; } +public class BlockValidationService : IBlockValidationService, ITransientDependency +{ + private readonly IEnumerable _blockValidationProviders; - private readonly IEnumerable _blockValidationProviders; + public BlockValidationService(IEnumerable blockValidationProviders) + { + Logger = NullLogger.Instance; + _blockValidationProviders = blockValidationProviders; + } - public BlockValidationService(IEnumerable blockValidationProviders) - { - Logger = NullLogger.Instance; - _blockValidationProviders = blockValidationProviders; - } + public ILogger Logger { get; set; } - public async Task ValidateBlockBeforeAttachAsync(IBlock block) - { - foreach (var provider in _blockValidationProviders) + public async Task ValidateBlockBeforeAttachAsync(IBlock block) + { + foreach (var provider in _blockValidationProviders) + if (!await provider.ValidateBeforeAttachAsync(block)) { - if (!await provider.ValidateBeforeAttachAsync(block)) - { - Logger.LogDebug($"Validate block before attach failed: {provider.GetType().Name}"); - return false; - } + Logger.LogDebug("Validate block before attach failed: {ProviderTypeName}", provider.GetType().Name); + return false; } - return true; - } + return true; + } - public async Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - foreach (var provider in _blockValidationProviders) + public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + foreach (var provider in _blockValidationProviders) + if (!await provider.ValidateBlockBeforeExecuteAsync(block)) { - if (!await provider.ValidateBlockBeforeExecuteAsync(block)) - { - Logger.LogDebug($"Validate block before execution failed: {provider.GetType().Name}"); - return false; - } + Logger.LogDebug("Validate block before execution failed: {ProviderTypeName}", provider.GetType().Name); + return false; } - return true; - } + return true; + } - public async Task ValidateBlockAfterExecuteAsync(IBlock block) - { - foreach (var provider in _blockValidationProviders) + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + foreach (var provider in _blockValidationProviders) + if (!await provider.ValidateBlockAfterExecuteAsync(block)) { - if (!await provider.ValidateBlockAfterExecuteAsync(block)) - { - Logger.LogDebug($"Validate block after execution failed: {provider.GetType().Name}"); - return false; - } + Logger.LogDebug("Validate block after execution failed: {ProviderTypeName}", provider.GetType().Name); + return false; } - return true; - } + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/IBlockchainService.cs b/src/AElf.Kernel.Core/Blockchain/Application/IBlockchainService.cs index 7090c3ac15..0b3046cc2d 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/IBlockchainService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/IBlockchainService.cs @@ -1,439 +1,429 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public interface IBlockchainService +{ + int GetChainId(); + + Task CreateChainAsync(Block block, IEnumerable transactions); + Task AddTransactionsAsync(IEnumerable transactions); + Task> GetTransactionsAsync(IEnumerable transactionIds); + Task HasTransactionAsync(Hash transactionId); + Task AddBlockAsync(Block block); + Task HasBlockAsync(Hash blockId); + Task GetBlockByHashAsync(Hash blockId); + + Task GetBlockHeaderByHashAsync(Hash blockId); + + Task GetChainAsync(); + + Task> GetReversedBlockIndexes(Hash lastBlockHash, int count); + + /// + /// if to chainBranchBlockHash have no enough block hashes, may return less hashes than count + /// for example, chainBranchBlockHash's height is 5, count is 10, firstHash's height is 2, will only return + /// hashes 3, 4, 5 + /// + /// + /// + /// + /// + /// + Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, + Hash chainBranchBlockHash = null); + + Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash); + Task AttachBlockToChainAsync(Chain chain, Block block); + Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash); + Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, Hash irreversibleBlockHash); + Task GetDiscardedBranchAsync(Chain chain); + Task CleanChainBranchAsync(DiscardedBranch discardedBranch); + + Task ResetChainToLibAsync(Chain chain); + Task RemoveLongestBranchAsync(Chain chain); +} + +public static class BlockchainServiceExtensions { - public interface IBlockchainService + public static async Task GetBestChainLastBlockHeaderAsync( + this IBlockchainService blockchainService) { - int GetChainId(); - - Task CreateChainAsync(Block block, IEnumerable transactions); - Task AddTransactionsAsync(IEnumerable transactions); - Task> GetTransactionsAsync(IEnumerable transactionIds); - Task HasTransactionAsync(Hash transactionId); - Task AddBlockAsync(Block block); - Task HasBlockAsync(Hash blockId); - Task GetBlockByHashAsync(Hash blockId); - - Task GetBlockHeaderByHashAsync(Hash blockId); - - Task GetChainAsync(); + var chain = await blockchainService.GetChainAsync(); + return await blockchainService.GetBlockHeaderByHashAsync(chain.BestChainHash); + } - Task> GetReversedBlockIndexes(Hash lastBlockHash, int count); + public static async Task GetBlockByHeightInBestChainBranchAsync( + this IBlockchainService blockchainService, long height) + { + var chain = await blockchainService.GetChainAsync(); + var hash = await blockchainService.GetBlockHashByHeightAsync(chain, height, chain.BestChainHash); - /// - /// if to chainBranchBlockHash have no enough block hashes, may return less hashes than count - /// for example, chainBranchBlockHash's height is 5, count is 10, firstHash's height is 2, will only return - /// hashes 3, 4, 5 - /// - /// - /// - /// - /// - /// - Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, - Hash chainBranchBlockHash = null); + return await blockchainService.GetBlockByHashAsync(hash); + } - Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash); - Task AttachBlockToChainAsync(Chain chain, Block block); - Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash); - Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, Hash irreversibleBlockHash); - Task GetDiscardedBranchAsync(Chain chain); - Task CleanChainBranchAsync(DiscardedBranch discardedBranch); + public static async Task> GetBlocksInBestChainBranchAsync(this IBlockchainService blockchainService, + Hash firstHash, + int count) + { + var chain = await blockchainService.GetChainAsync(); + return await blockchainService.GetBlocksInChainBranchAsync(chain, firstHash, count, chain.BestChainHash); + } - Task ResetChainToLibAsync(Chain chain); - Task RemoveLongestBranchAsync(Chain chain); + public static async Task> GetBlocksInLongestChainBranchAsync( + this IBlockchainService blockchainService, + Hash firstHash, + int count) + { + var chain = await blockchainService.GetChainAsync(); + return await blockchainService.GetBlocksInChainBranchAsync(chain, firstHash, count, chain.LongestChainHash); } - public static class BlockchainServiceExtensions + public static async Task> GetBlocksInChainBranchAsync(this IBlockchainService blockchainService, + Chain chain, + Hash firstHash, + int count, + Hash chainBranch) { - public static async Task GetBestChainLastBlockHeaderAsync( - this IBlockchainService blockchainService) - { - var chain = await blockchainService.GetChainAsync(); - return await blockchainService.GetBlockHeaderByHashAsync(chain.BestChainHash); - } + var blockHashes = await blockchainService.GetBlockHashesAsync( + chain, firstHash, count, chainBranch); + var list = blockHashes + .Select(async blockHash => await blockchainService.GetBlockByHashAsync(blockHash)); - public static async Task GetBlockByHeightInBestChainBranchAsync( - this IBlockchainService blockchainService, long height) - { - var chain = await blockchainService.GetChainAsync(); - var hash = await blockchainService.GetBlockHashByHeightAsync(chain, height, chain.BestChainHash); + return (await Task.WhenAll(list)).ToList(); + } +} - return await blockchainService.GetBlockByHashAsync(hash); - } +public interface ILightBlockchainService : IBlockchainService +{ +} - public static async Task> GetBlocksInBestChainBranchAsync(this IBlockchainService blockchainService, - Hash firstHash, - int count) - { - var chain = await blockchainService.GetChainAsync(); - return await blockchainService.GetBlocksInChainBranchAsync(chain, firstHash, count, chain.BestChainHash); - } +/* +public class LightBlockchainService : ILightBlockchainService +{ + public async Task AddBlockAsync( Block block) + { + throw new System.NotImplementedException(); + } - public static async Task> GetBlocksInLongestChainBranchAsync( - this IBlockchainService blockchainService, - Hash firstHash, - int count) - { - var chain = await blockchainService.GetChainAsync(); - return await blockchainService.GetBlocksInChainBranchAsync(chain, firstHash, count, chain.LongestChainHash); - } + public async Task HasBlockAsync( Hash blockId) + { + throw new System.NotImplementedException(); + } - public static async Task> GetBlocksInChainBranchAsync(this IBlockchainService blockchainService, - Chain chain, - Hash firstHash, - int count, - Hash chainBranch) - { - var blockHashes = await blockchainService.GetBlockHashesAsync( - chain, firstHash, count, chainBranch); - var list = blockHashes - .Select(async blockHash => await blockchainService.GetBlockByHashAsync(blockHash)); + public async Task> AddBlocksAsync( IEnumerable blocks) + { + throw new System.NotImplementedException(); + } - return (await Task.WhenAll(list)).ToList(); - } + public async Task GetBlockByHashAsync( Hash blockId) + { + throw new System.NotImplementedException(); } - public interface ILightBlockchainService : IBlockchainService + public async Task GetChainAsync() { + throw new System.NotImplementedException(); } +}*/ + +public interface IFullBlockchainService : IBlockchainService +{ +} - /* - public class LightBlockchainService : ILightBlockchainService +public class FullBlockchainService : IFullBlockchainService, ITransientDependency +{ + private readonly IBlockManager _blockManager; + private readonly IChainManager _chainManager; + private readonly ITransactionManager _transactionManager; + + public FullBlockchainService(IChainManager chainManager, IBlockManager blockManager, + ITransactionManager transactionManager) { - public async Task AddBlockAsync( Block block) - { - throw new System.NotImplementedException(); - } + Logger = NullLogger.Instance; + _chainManager = chainManager; + _blockManager = blockManager; + _transactionManager = transactionManager; + LocalEventBus = NullLocalEventBus.Instance; + } - public async Task HasBlockAsync( Hash blockId) - { - throw new System.NotImplementedException(); - } + public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public async Task> AddBlocksAsync( IEnumerable blocks) - { - throw new System.NotImplementedException(); - } + public int GetChainId() + { + return _chainManager.GetChainId(); + } - public async Task GetBlockByHashAsync( Hash blockId) - { - throw new System.NotImplementedException(); - } + public async Task CreateChainAsync(Block block, IEnumerable transactions) + { + await AddTransactionsAsync(transactions); + await AddBlockAsync(block); - public async Task GetChainAsync() - { - throw new System.NotImplementedException(); - } - }*/ + return await _chainManager.CreateAsync(block.GetHash()); + } - public interface IFullBlockchainService : IBlockchainService + public async Task> GetTransactionsAsync(IEnumerable transactionIds) { + return await _transactionManager.GetTransactionsAsync(transactionIds.ToList()); } - public class FullBlockchainService : IFullBlockchainService, ITransientDependency + public async Task HasTransactionAsync(Hash transactionId) { - private readonly IChainManager _chainManager; - private readonly IBlockManager _blockManager; - private readonly ITransactionManager _transactionManager; - public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } + return await _transactionManager.HasTransactionAsync(transactionId); + } - public FullBlockchainService(IChainManager chainManager, IBlockManager blockManager, - ITransactionManager transactionManager) - { - Logger = NullLogger.Instance; - _chainManager = chainManager; - _blockManager = blockManager; - _transactionManager = transactionManager; - LocalEventBus = NullLocalEventBus.Instance; - } + public async Task AddBlockAsync(Block block) + { + await _blockManager.AddBlockBodyAsync(block.Header.GetHash(), block.Body); + await _blockManager.AddBlockHeaderAsync(block.Header); + } - public int GetChainId() - { - return _chainManager.GetChainId(); - } + public async Task AddTransactionsAsync(IEnumerable transactions) + { + await _transactionManager.AddTransactionsAsync(transactions.ToList()); + } - public async Task CreateChainAsync(Block block, IEnumerable transactions) - { - await AddTransactionsAsync(transactions); - await AddBlockAsync(block); + public async Task HasBlockAsync(Hash blockId) + { + return await _blockManager.HasBlockAsync(blockId); + } - return await _chainManager.CreateAsync(block.GetHash()); - } + /// + /// Returns the block with the specified height, searching from . If the height + /// is in the irreversible section of the chain, it will get the block from the indexed blocks. + /// + /// the chain to search + /// the height of the block + /// the block from which to start the search. + /// + public async Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash) + { + // 1 2 3 4(lib) 5 6 + // 4 >= height + // return any(1,2,3,4) - public async Task> GetTransactionsAsync(IEnumerable transactionIds) - { - return await _transactionManager.GetTransactionsAsync(transactionIds.ToList()); - } + if (chain.LastIrreversibleBlockHeight >= height) + // search irreversible section of the chain + return (await _chainManager.GetChainBlockIndexAsync(height)).BlockHash; - public async Task HasTransactionAsync(Hash transactionId) - { - return await _transactionManager.HasTransactionAsync(transactionId); - } + // Last irreversible block can make the loops in acceptable size, do not need cache - public async Task AddBlockAsync(Block block) - { - await _blockManager.AddBlockBodyAsync(block.Header.GetHash(), block.Body); - await _blockManager.AddBlockHeaderAsync(block.Header); - } + // 1 2 3 4(lib) 5 6 + // 4 < height + // return any(5,6) - public async Task AddTransactionsAsync(IEnumerable transactions) - { - await _transactionManager.AddTransactionsAsync(transactions.ToList()); - } - public async Task HasBlockAsync(Hash blockId) + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); + if (chainBlockLink.Height < height) { - return await _blockManager.HasBlockAsync(blockId); + Logger.LogWarning( + "Start searching height: {ChainBlockLinkHeight},target height: {Height},cannot get block hash", + chainBlockLink.Height, height); + return null; } - /// - /// Returns the block with the specified height, searching from . If the height - /// is in the irreversible section of the chain, it will get the block from the indexed blocks. - /// - /// the chain to search - /// the height of the block - /// the block from which to start the search. - /// - public async Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash) + while (true) { - // 1 2 3 4(lib) 5 6 - // 4 >= height - // return any(1,2,3,4) - - if (chain.LastIrreversibleBlockHeight >= height) - { - // search irreversible section of the chain - return (await _chainManager.GetChainBlockIndexAsync(height)).BlockHash; - } + if (chainBlockLink.Height == height) + return chainBlockLink.BlockHash; - // Last irreversible block can make the loops in acceptable size, do not need cache + chainBranchBlockHash = chainBlockLink.PreviousBlockHash; + chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); - // 1 2 3 4(lib) 5 6 - // 4 < height - // return any(5,6) - - - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); - if (chainBlockLink.Height < height) - { - Logger.LogWarning( - $"Start searching height: {chainBlockLink.Height},target height: {height},cannot get block hash"); + if (chainBlockLink == null || chainBlockLink.Height <= chain.LastIrreversibleBlockHeight) return null; - } - - while (true) - { - if (chainBlockLink.Height == height) - return chainBlockLink.BlockHash; - - chainBranchBlockHash = chainBlockLink.PreviousBlockHash; - chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); - - if (chainBlockLink == null || chainBlockLink.Height <= chain.LastIrreversibleBlockHeight) - return null; - } } + } - public async Task AttachBlockToChainAsync(Chain chain, Block block) - { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + public async Task AttachBlockToChainAsync(Chain chain, Block block) + { + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - if (chainBlockLink == null) - { - chainBlockLink = new ChainBlockLink - { - Height = block.Header.Height, - BlockHash = block.GetHash(), - PreviousBlockHash = block.Header.PreviousBlockHash - }; - } - else + if (chainBlockLink == null) + { + chainBlockLink = new ChainBlockLink { - chainBlockLink.IsLinked = false; - chainBlockLink.ExecutionStatus = - chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionSuccess - ? ChainBlockLinkExecutionStatus.ExecutionSuccess - : ChainBlockLinkExecutionStatus.ExecutionNone; - } - - var status = await _chainManager.AttachBlockToChainAsync(chain, chainBlockLink); - - return status; + Height = block.Header.Height, + BlockHash = block.GetHash(), + PreviousBlockHash = block.Header.PreviousBlockHash + }; } - - public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) + else { - await _chainManager.SetBestChainAsync(chain, bestChainHeight, bestChainHash); - await LocalEventBus.PublishAsync(new BestChainFoundEventData - { - BlockHash = bestChainHash, - BlockHeight = bestChainHeight - }); + chainBlockLink.IsLinked = false; + chainBlockLink.ExecutionStatus = + chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionSuccess + ? ChainBlockLinkExecutionStatus.ExecutionSuccess + : ChainBlockLinkExecutionStatus.ExecutionNone; } - public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, - Hash irreversibleBlockHash) - { - // Create before IChainManager.SetIrreversibleBlockAsync so that we can correctly get the previous LIB info - var eventDataToPublish = new NewIrreversibleBlockFoundEvent() - { - PreviousIrreversibleBlockHash = chain.LastIrreversibleBlockHash, - PreviousIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight, - BlockHash = irreversibleBlockHash, - BlockHeight = irreversibleBlockHeight - }; + var status = await _chainManager.AttachBlockToChainAsync(chain, chainBlockLink); - var success = await _chainManager.SetIrreversibleBlockAsync(chain, irreversibleBlockHash); - if (!success) - return; - - await LocalEventBus.PublishAsync(eventDataToPublish); - } + return status; + } - public async Task ResetChainToLibAsync(Chain chain) + public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) + { + await _chainManager.SetBestChainAsync(chain, bestChainHeight, bestChainHash); + await LocalEventBus.PublishAsync(new BestChainFoundEventData { - return await _chainManager.ResetChainToLibAsync(chain); - } + BlockHash = bestChainHash, + BlockHeight = bestChainHeight + }); + } - public async Task> GetReversedBlockIndexes(Hash lastBlockHash, int count) + public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, + Hash irreversibleBlockHash) + { + // Create before IChainManager.SetIrreversibleBlockAsync so that we can correctly get the previous LIB info + var eventDataToPublish = new NewIrreversibleBlockFoundEvent { - var hashes = new List(); - if (count <= 0) - return hashes; + PreviousIrreversibleBlockHash = chain.LastIrreversibleBlockHash, + PreviousIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight, + BlockHash = irreversibleBlockHash, + BlockHeight = irreversibleBlockHeight + }; - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(lastBlockHash); - if (chainBlockLink == null || chainBlockLink.PreviousBlockHash == Hash.Empty) - return hashes; + var success = await _chainManager.SetIrreversibleBlockAsync(chain, irreversibleBlockHash); + if (!success) + return; - hashes.Add(new BlockIndex(chainBlockLink.PreviousBlockHash, chainBlockLink.Height - 1)); - for (var i = 0; i < count - 1; i++) - { - chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); - if (chainBlockLink == null || chainBlockLink.PreviousBlockHash == Hash.Empty) - break; + await LocalEventBus.PublishAsync(eventDataToPublish); + } - hashes.Add(new BlockIndex(chainBlockLink.PreviousBlockHash, chainBlockLink.Height - 1)); - } + public async Task ResetChainToLibAsync(Chain chain) + { + return await _chainManager.ResetChainToLibAsync(chain); + } + public async Task> GetReversedBlockIndexes(Hash lastBlockHash, int count) + { + var hashes = new List(); + if (count <= 0) return hashes; - } - public async Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, - Hash chainBranchBlockHash) + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(lastBlockHash); + if (chainBlockLink == null || chainBlockLink.PreviousBlockHash == Hash.Empty) + return hashes; + + hashes.Add(new BlockIndex(chainBlockLink.PreviousBlockHash, chainBlockLink.Height - 1)); + for (var i = 0; i < count - 1; i++) { - var first = await _blockManager.GetBlockHeaderAsync(firstHash); + chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); + if (chainBlockLink == null || chainBlockLink.PreviousBlockHash == Hash.Empty) + break; - if (first == null) - return new List(); + hashes.Add(new BlockIndex(chainBlockLink.PreviousBlockHash, chainBlockLink.Height - 1)); + } + + return hashes; + } + + public async Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, + Hash chainBranchBlockHash) + { + var first = await _blockManager.GetBlockHeaderAsync(firstHash); + + if (first == null) + return new List(); - var height = first.Height + count; + var height = first.Height + count; - var chainBranchBlockHashKey = chainBranchBlockHash.ToStorageKey(); + var chainBranchBlockHashKey = chainBranchBlockHash.ToStorageKey(); - ChainBlockLink chainBlockLink = null; + ChainBlockLink chainBlockLink = null; - if (chain.Branches.ContainsKey(chainBranchBlockHashKey)) + if (chain.Branches.ContainsKey(chainBranchBlockHashKey)) + { + if (height > chain.Branches[chainBranchBlockHashKey]) { - if (height > chain.Branches[chainBranchBlockHashKey]) - { - height = chain.Branches[chainBranchBlockHashKey]; - count = (int) (height - first.Height); - } + height = chain.Branches[chainBranchBlockHashKey]; + count = (int)(height - first.Height); } - else + } + else + { + var branchChainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); + if (height > branchChainBlockLink.Height) { - var branchChainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBranchBlockHash); - if (height > branchChainBlockLink.Height) - { - height = branchChainBlockLink.Height; - chainBlockLink = branchChainBlockLink; - count = (int) (height - first.Height); - } + height = branchChainBlockLink.Height; + chainBlockLink = branchChainBlockLink; + count = (int)(height - first.Height); } + } - var hashes = new List(); + var hashes = new List(); - if (count <= 0) - return hashes; + if (count <= 0) + return hashes; - if (chainBlockLink == null) - { - var last = await GetBlockHashByHeightAsync(chain, height, chainBranchBlockHash); + if (chainBlockLink == null) + { + var last = await GetBlockHashByHeightAsync(chain, height, chainBranchBlockHash); - if (last == null) - throw new InvalidOperationException("not support"); + if (last == null) + throw new InvalidOperationException("not support"); - chainBlockLink = await _chainManager.GetChainBlockLinkAsync(last); - } + chainBlockLink = await _chainManager.GetChainBlockLinkAsync(last); + } + hashes.Add(chainBlockLink.BlockHash); + for (var i = 0; i < count - 1; i++) + { + chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); hashes.Add(chainBlockLink.BlockHash); - for (var i = 0; i < count - 1; i++) - { - chainBlockLink = await _chainManager.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); - hashes.Add(chainBlockLink.BlockHash); - } + } - if (chainBlockLink.PreviousBlockHash != firstHash) - { - throw new Exception("wrong branch"); - } + if (chainBlockLink.PreviousBlockHash != firstHash) throw new Exception("wrong branch"); - hashes.Reverse(); + hashes.Reverse(); - return hashes; - } + return hashes; + } - public async Task GetBlockByHashAsync(Hash blockId) - { - return await _blockManager.GetBlockAsync(blockId); - } + public async Task GetBlockByHashAsync(Hash blockId) + { + return await _blockManager.GetBlockAsync(blockId); + } - public async Task GetBlockHeaderByHashAsync(Hash blockId) - { - return await _blockManager.GetBlockHeaderAsync(blockId); - } + public async Task GetBlockHeaderByHashAsync(Hash blockId) + { + return await _blockManager.GetBlockHeaderAsync(blockId); + } - public async Task GetBlockHeaderByHeightAsync(long height) - { - var index = await _chainManager.GetChainBlockIndexAsync(height); - return await _blockManager.GetBlockHeaderAsync(index.BlockHash); - } + public async Task GetChainAsync() + { + return await _chainManager.GetAsync(); + } - public async Task GetChainAsync() - { - return await _chainManager.GetAsync(); - } + public async Task GetDiscardedBranchAsync(Chain chain) + { + return await _chainManager.GetDiscardedBranchAsync(chain, chain.LastIrreversibleBlockHash, + chain.LastIrreversibleBlockHeight); + } - public async Task GetDiscardedBranchAsync(Chain chain) - { - return await _chainManager.GetDiscardedBranchAsync(chain, chain.LastIrreversibleBlockHash, - chain.LastIrreversibleBlockHeight); - } + public async Task CleanChainBranchAsync(DiscardedBranch discardedBranch) + { + var chain = await GetChainAsync(); + await _chainManager.CleanChainBranchAsync(chain, discardedBranch); + } - public async Task CleanChainBranchAsync(DiscardedBranch discardedBranch) - { - var chain = await GetChainAsync(); - await _chainManager.CleanChainBranchAsync(chain, discardedBranch); - } + public async Task RemoveLongestBranchAsync(Chain chain) + { + await _chainManager.RemoveLongestBranchAsync(chain); + } - public async Task RemoveLongestBranchAsync(Chain chain) - { - await _chainManager.RemoveLongestBranchAsync(chain); - } + public async Task GetBlockHeaderByHeightAsync(long height) + { + var index = await _chainManager.GetChainBlockIndexAsync(height); + return await _blockManager.GetBlockHeaderAsync(index.BlockHash); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/ITransactionBlockIndexService.cs b/src/AElf.Kernel.Core/Blockchain/Application/ITransactionBlockIndexService.cs index 4f934671f1..1db9f5f0d1 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/ITransactionBlockIndexService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/ITransactionBlockIndexService.cs @@ -1,204 +1,193 @@ -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Blockchain.Infrastructure; -using AElf.Types; using Google.Protobuf.Collections; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public interface ITransactionBlockIndexService +{ + Task GetTransactionBlockIndexAsync(Hash txId); + Task AddBlockIndexAsync(IList txIds, BlockIndex blockIndex); + Task ValidateTransactionBlockIndexExistsInBranchAsync(Hash txId, Hash chainBranchBlockHash); + Task LoadTransactionBlockIndexAsync(); + Task UpdateTransactionBlockIndicesByLibHeightAsync(long blockHeight); +} + +public class TransactionBlockIndexService : ITransactionBlockIndexService, ITransientDependency { - public interface ITransactionBlockIndexService + private readonly IBlockchainService _blockchainService; + private readonly ITransactionBlockIndexManager _transactionBlockIndexManager; + private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; + + public TransactionBlockIndexService(IBlockchainService blockchainService, + ITransactionBlockIndexManager transactionBlockIndexManager, + ITransactionBlockIndexProvider transactionBlockIndexProvider) { - Task GetTransactionBlockIndexAsync(Hash txId); - Task AddBlockIndexAsync(IList txIds, BlockIndex blockIndex); - Task ValidateTransactionBlockIndexExistsInBranchAsync(Hash txId, Hash chainBranchBlockHash); - Task LoadTransactionBlockIndexAsync(); - Task UpdateTransactionBlockIndicesByLibHeightAsync(long blockHeight); + _blockchainService = blockchainService; + _transactionBlockIndexManager = transactionBlockIndexManager; + _transactionBlockIndexProvider = transactionBlockIndexProvider; } - public class TransactionBlockIndexService : ITransactionBlockIndexService, ITransientDependency + public async Task GetTransactionBlockIndexAsync(Hash txId) { - private readonly IBlockchainService _blockchainService; - private readonly ITransactionBlockIndexManager _transactionBlockIndexManager; - private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; + var transactionBlockIndex = await GetTransactionBlockIndexByTxIdAsync(txId); - public TransactionBlockIndexService(IBlockchainService blockchainService, - ITransactionBlockIndexManager transactionBlockIndexManager, - ITransactionBlockIndexProvider transactionBlockIndexProvider) - { - _blockchainService = blockchainService; - _transactionBlockIndexManager = transactionBlockIndexManager; - _transactionBlockIndexProvider = transactionBlockIndexProvider; - } - - public async Task GetTransactionBlockIndexAsync(Hash txId) - { - var transactionBlockIndex = await GetTransactionBlockIndexByTxIdAsync(txId); - - if (transactionBlockIndex == null) - return null; + if (transactionBlockIndex == null) + return null; - var chain = await _blockchainService.GetChainAsync(); - var blockIndex = await GetBlockIndexAsync(chain, transactionBlockIndex, chain.BestChainHash); - if (blockIndex != null) - await ClearRedundantBlockIndices(txId, transactionBlockIndex, blockIndex, chain); - return blockIndex; - } + var chain = await _blockchainService.GetChainAsync(); + var blockIndex = await GetBlockIndexAsync(chain, transactionBlockIndex, chain.BestChainHash); + if (blockIndex != null) + await ClearRedundantBlockIndices(txId, transactionBlockIndex, blockIndex, chain); + return blockIndex; + } - public async Task AddBlockIndexAsync(IList txIds, BlockIndex blockIndex) + public async Task AddBlockIndexAsync(IList txIds, BlockIndex blockIndex) + { + var transactionBlockIndexes = new Dictionary(); + foreach (var txId in txIds) { - var transactionBlockIndexes = new Dictionary(); - foreach (var txId in txIds) + var transactionBlockIndex = new TransactionBlockIndex { - var transactionBlockIndex = new TransactionBlockIndex - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }; + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }; - var preTransactionBlockIndex = - await GetTransactionBlockIndexByTxIdAsync(txId); + var preTransactionBlockIndex = + await GetTransactionBlockIndexByTxIdAsync(txId); - if (preTransactionBlockIndex != null) + if (preTransactionBlockIndex != null) + { + if (preTransactionBlockIndex.BlockHash == blockIndex.BlockHash || + preTransactionBlockIndex.PreviousExecutionBlockIndexList.Any(l => + l.BlockHash == blockIndex.BlockHash)) + return; + + var needToReplace = preTransactionBlockIndex.BlockHeight > blockIndex.BlockHeight; + if (needToReplace) { - if (preTransactionBlockIndex.BlockHash == blockIndex.BlockHash || - preTransactionBlockIndex.PreviousExecutionBlockIndexList.Any(l => - l.BlockHash == blockIndex.BlockHash)) - { - return; - } - - var needToReplace = preTransactionBlockIndex.BlockHeight > blockIndex.BlockHeight; - if (needToReplace) - { - transactionBlockIndex.BlockHash = preTransactionBlockIndex.BlockHash; - transactionBlockIndex.BlockHeight = preTransactionBlockIndex.BlockHeight; - } - - transactionBlockIndex.PreviousExecutionBlockIndexList.Add(preTransactionBlockIndex - .PreviousExecutionBlockIndexList); - transactionBlockIndex.PreviousExecutionBlockIndexList.Add(needToReplace - ? blockIndex - : new BlockIndex(preTransactionBlockIndex.BlockHash, preTransactionBlockIndex.BlockHeight)); + transactionBlockIndex.BlockHash = preTransactionBlockIndex.BlockHash; + transactionBlockIndex.BlockHeight = preTransactionBlockIndex.BlockHeight; } - transactionBlockIndexes.Add(txId, transactionBlockIndex); + transactionBlockIndex.PreviousExecutionBlockIndexList.Add(preTransactionBlockIndex + .PreviousExecutionBlockIndexList); + transactionBlockIndex.PreviousExecutionBlockIndexList.Add(needToReplace + ? blockIndex + : new BlockIndex(preTransactionBlockIndex.BlockHash, preTransactionBlockIndex.BlockHeight)); } - await AddTransactionBlockIndicesAsync(transactionBlockIndexes); + transactionBlockIndexes.Add(txId, transactionBlockIndex); } - public async Task ValidateTransactionBlockIndexExistsInBranchAsync(Hash txId, Hash chainBranchBlockHash) - { - if (!_transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex)) - return false; - var chain = await _blockchainService.GetChainAsync(); - return await GetBlockIndexAsync(chain, transactionBlockIndex, - chainBranchBlockHash ?? chain.BestChainHash) != null; - } - - public async Task LoadTransactionBlockIndexAsync() - { - var chain = await _blockchainService.GetChainAsync(); - - if (chain == null) - return; - - var blockHeight = chain.LastIrreversibleBlockHeight; - var blockHash = chain.LastIrreversibleBlockHash; - while (true) - { - if (blockHeight < AElfConstants.GenesisBlockHeight || - blockHeight + KernelConstants.ReferenceBlockValidPeriod <= chain.LastIrreversibleBlockHeight) - break; + await AddTransactionBlockIndicesAsync(transactionBlockIndexes); + } - var block = await _blockchainService.GetBlockByHashAsync(blockHash); - if (block == null) - return; + public async Task ValidateTransactionBlockIndexExistsInBranchAsync(Hash txId, Hash chainBranchBlockHash) + { + if (!_transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex)) + return false; + var chain = await _blockchainService.GetChainAsync(); + return await GetBlockIndexAsync(chain, transactionBlockIndex, + chainBranchBlockHash ?? chain.BestChainHash) != null; + } - foreach (var txId in block.TransactionIds) - { - var txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, txBlockIndex); - } + public async Task LoadTransactionBlockIndexAsync() + { + var chain = await _blockchainService.GetChainAsync(); - blockHash = block.Header.PreviousBlockHash; - blockHeight--; - } - } + if (chain == null) + return; - public Task UpdateTransactionBlockIndicesByLibHeightAsync(long blockHeight) + var blockHeight = chain.LastIrreversibleBlockHeight; + var blockHash = chain.LastIrreversibleBlockHash; + while (true) { - var cleanHeight = blockHeight - KernelConstants.ReferenceBlockValidPeriod; - if (cleanHeight <= 0) - return Task.CompletedTask; - _transactionBlockIndexProvider.CleanByHeight(cleanHeight); - return Task.CompletedTask; - } + if (blockHeight < AElfConstants.GenesisBlockHeight || + blockHeight + KernelConstants.ReferenceBlockValidPeriod <= chain.LastIrreversibleBlockHeight) + break; - private async Task AddTransactionBlockIndicesAsync( - IDictionary transactionBlockIndices) - { - foreach (var index in transactionBlockIndices) + var block = await _blockchainService.GetBlockByHashAsync(blockHash); + if (block == null) + return; + + foreach (var txId in block.TransactionIds) { - _transactionBlockIndexProvider.AddTransactionBlockIndex(index.Key, index.Value); + var txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, txBlockIndex); } - await _transactionBlockIndexManager.SetTransactionBlockIndicesAsync(transactionBlockIndices); + blockHash = block.Header.PreviousBlockHash; + blockHeight--; } + } - private async Task GetTransactionBlockIndexByTxIdAsync(Hash txId) - { - if (_transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex)) - return transactionBlockIndex; + public Task UpdateTransactionBlockIndicesByLibHeightAsync(long blockHeight) + { + var cleanHeight = blockHeight - KernelConstants.ReferenceBlockValidPeriod; + if (cleanHeight <= 0) + return Task.CompletedTask; + _transactionBlockIndexProvider.CleanByHeight(cleanHeight); + return Task.CompletedTask; + } + + private async Task AddTransactionBlockIndicesAsync( + IDictionary transactionBlockIndices) + { + foreach (var index in transactionBlockIndices) + _transactionBlockIndexProvider.AddTransactionBlockIndex(index.Key, index.Value); - transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - if (transactionBlockIndex == null) - return null; - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, transactionBlockIndex); + await _transactionBlockIndexManager.SetTransactionBlockIndicesAsync(transactionBlockIndices); + } + private async Task GetTransactionBlockIndexByTxIdAsync(Hash txId) + { + if (_transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex)) return transactionBlockIndex; - } - private async Task GetBlockIndexAsync(Chain chain, TransactionBlockIndex transactionBlockIndex, - Hash chainBranchBlockHash) - { - var previousBlockIndexList = - transactionBlockIndex.PreviousExecutionBlockIndexList ?? new RepeatedField(); - var lastBlockIndex = new BlockIndex(transactionBlockIndex.BlockHash, transactionBlockIndex.BlockHeight); - var reversedBlockIndexList = previousBlockIndexList.Concat(new[] {lastBlockIndex}).Reverse().ToList(); + transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + if (transactionBlockIndex == null) + return null; + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, transactionBlockIndex); - foreach (var blockIndex in reversedBlockIndexList) - { - var blockHash = - await _blockchainService.GetBlockHashByHeightAsync(chain, blockIndex.BlockHeight, - chainBranchBlockHash); + return transactionBlockIndex; + } - if (blockIndex.BlockHash == blockHash) - // If TransactionBlockIndex exists, then read the result via TransactionBlockIndex - return blockIndex; - } + private async Task GetBlockIndexAsync(Chain chain, TransactionBlockIndex transactionBlockIndex, + Hash chainBranchBlockHash) + { + var previousBlockIndexList = + transactionBlockIndex.PreviousExecutionBlockIndexList ?? new RepeatedField(); + var lastBlockIndex = new BlockIndex(transactionBlockIndex.BlockHash, transactionBlockIndex.BlockHeight); + var reversedBlockIndexList = previousBlockIndexList.Concat(new[] { lastBlockIndex }).Reverse().ToList(); - return null; + foreach (var blockIndex in reversedBlockIndexList) + { + var blockHash = + await _blockchainService.GetBlockHashByHeightAsync(chain, blockIndex.BlockHeight, + chainBranchBlockHash); + + if (blockIndex.BlockHash == blockHash) + // If TransactionBlockIndex exists, then read the result via TransactionBlockIndex + return blockIndex; } - private async Task ClearRedundantBlockIndices(Hash txId, TransactionBlockIndex transactionBlockIndex, - BlockIndex blockIndex, Chain chain) - { - if (blockIndex.BlockHeight > chain.LastIrreversibleBlockHeight - || transactionBlockIndex.PreviousExecutionBlockIndexList.Count == 0) - { - return; - } + return null; + } + + private async Task ClearRedundantBlockIndices(Hash txId, TransactionBlockIndex transactionBlockIndex, + BlockIndex blockIndex, Chain chain) + { + if (blockIndex.BlockHeight > chain.LastIrreversibleBlockHeight + || transactionBlockIndex.PreviousExecutionBlockIndexList.Count == 0) + return; - transactionBlockIndex.BlockHash = blockIndex.BlockHash; - transactionBlockIndex.BlockHeight = blockIndex.BlockHeight; - transactionBlockIndex.PreviousExecutionBlockIndexList.Clear(); + transactionBlockIndex.BlockHash = blockIndex.BlockHash; + transactionBlockIndex.BlockHeight = blockIndex.BlockHeight; + transactionBlockIndex.PreviousExecutionBlockIndexList.Clear(); - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, transactionBlockIndex); - await _transactionBlockIndexManager.SetTransactionBlockIndexAsync(txId, transactionBlockIndex); - } + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, transactionBlockIndex); + await _transactionBlockIndexManager.SetTransactionBlockIndexAsync(txId, transactionBlockIndex); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Application/ITransactionResultService.cs b/src/AElf.Kernel.Core/Blockchain/Application/ITransactionResultService.cs index 07dd4d4fc3..c2d6e0b2de 100644 --- a/src/AElf.Kernel.Core/Blockchain/Application/ITransactionResultService.cs +++ b/src/AElf.Kernel.Core/Blockchain/Application/ITransactionResultService.cs @@ -1,81 +1,70 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; -using AElf.Types; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +public interface ITransactionResultQueryService { - public interface ITransactionResultQueryService - { - Task GetTransactionResultAsync(Hash transactionId); - Task GetTransactionResultAsync(Hash transactionId, Hash blockHash); - } + Task GetTransactionResultAsync(Hash transactionId); + Task GetTransactionResultAsync(Hash transactionId, Hash blockHash); +} - public interface ITransactionResultService : ITransactionResultQueryService - { - Task AddTransactionResultsAsync(IList transactionResult, BlockHeader blockHeader); +public interface ITransactionResultService : ITransactionResultQueryService +{ + Task AddTransactionResultsAsync(IList transactionResult, BlockHeader blockHeader); - Task ProcessTransactionResultAfterExecutionAsync(BlockHeader blockHeader, List transactionIds); - } + Task ProcessTransactionResultAfterExecutionAsync(BlockHeader blockHeader, List transactionIds); +} +public class TransactionResultService : ITransactionResultService, ITransientDependency +{ + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + private readonly ITransactionResultManager _transactionResultManager; - public class TransactionResultService : ITransactionResultService, ITransientDependency + public TransactionResultService(ITransactionResultManager transactionResultManager, + ITransactionBlockIndexService transactionBlockIndexService) { - private readonly ITransactionResultManager _transactionResultManager; - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - private readonly IBlockchainService _blockchainService; - - public TransactionResultService(ITransactionResultManager transactionResultManager, - IBlockchainService blockchainService, ITransactionBlockIndexService transactionBlockIndexService) - { - _transactionResultManager = transactionResultManager; - _blockchainService = blockchainService; - _transactionBlockIndexService = transactionBlockIndexService; - } + _transactionResultManager = transactionResultManager; + _transactionBlockIndexService = transactionBlockIndexService; + } - public async Task AddTransactionResultsAsync(IList transactionResults, - BlockHeader blockHeader) - { - await _transactionResultManager.AddTransactionResultsAsync(transactionResults, - blockHeader.GetDisambiguatingHash()); - } + public async Task AddTransactionResultsAsync(IList transactionResults, + BlockHeader blockHeader) + { + await _transactionResultManager.AddTransactionResultsAsync(transactionResults, + blockHeader.GetDisambiguatingHash()); + } - public async Task GetTransactionResultAsync(Hash transactionId) - { - var transactionBlockIndex = - await _transactionBlockIndexService.GetTransactionBlockIndexAsync(transactionId); + public async Task GetTransactionResultAsync(Hash transactionId) + { + var transactionBlockIndex = + await _transactionBlockIndexService.GetTransactionBlockIndexAsync(transactionId); - if (transactionBlockIndex != null) - return await _transactionResultManager.GetTransactionResultAsync(transactionId, - transactionBlockIndex.BlockHash); + if (transactionBlockIndex != null) + return await _transactionResultManager.GetTransactionResultAsync(transactionId, + transactionBlockIndex.BlockHash); - return null; - } + return null; + } - public async Task GetTransactionResultAsync(Hash transactionId, Hash blockHash) - { - var txResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, blockHash); - return txResult; - } + public async Task GetTransactionResultAsync(Hash transactionId, Hash blockHash) + { + var txResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, blockHash); + return txResult; + } - public async Task ProcessTransactionResultAfterExecutionAsync(BlockHeader blockHeader, - List transactionIds) + public async Task ProcessTransactionResultAfterExecutionAsync(BlockHeader blockHeader, + List transactionIds) + { + var blockIndex = new BlockIndex { - var blockIndex = new BlockIndex - { - BlockHash = blockHeader.GetHash(), - BlockHeight = blockHeader.Height - }; + BlockHash = blockHeader.GetHash(), + BlockHeight = blockHeader.Height + }; - if (transactionIds.Count == 0) - { - // This will only happen during test environment - return; - } + if (transactionIds.Count == 0) + // This will only happen during test environment + return; - await _transactionBlockIndexService.AddBlockIndexAsync(transactionIds, blockIndex); - } + await _transactionBlockIndexService.AddBlockIndexAsync(transactionIds, blockIndex); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/BlockExecutedSet.cs b/src/AElf.Kernel.Core/Blockchain/BlockExecutedSet.cs index 11d8536f9a..59c8abbf8a 100644 --- a/src/AElf.Kernel.Core/Blockchain/BlockExecutedSet.cs +++ b/src/AElf.Kernel.Core/Blockchain/BlockExecutedSet.cs @@ -1,22 +1,18 @@ -using System.Collections.Generic; -using AElf.Types; +namespace AElf.Kernel.Blockchain; -namespace AElf.Kernel.Blockchain +public class BlockExecutedSet { - public class BlockExecutedSet - { - public Block Block { get; set; } - public IDictionary TransactionResultMap { get; set; } + public Block Block { get; set; } + public IDictionary TransactionResultMap { get; set; } - public IDictionary TransactionMap { get; set; } + public IDictionary TransactionMap { get; set; } - public long Height => Block.Height; + public long Height => Block.Height; - public Hash GetHash() - { - return Block.GetHash(); - } + public IEnumerable TransactionIds => Block.TransactionIds; - public IEnumerable TransactionIds => Block.TransactionIds; + public Hash GetHash() + { + return Block.GetHash(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/IBlockManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/IBlockManager.cs index 09d4942feb..0f4796bfb1 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/IBlockManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/IBlockManager.cs @@ -1,90 +1,83 @@ using System; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Blockchain.Domain +namespace AElf.Kernel.Blockchain.Domain; + +public interface IBlockManager +{ + Task AddBlockHeaderAsync(BlockHeader header); + Task AddBlockBodyAsync(Hash blockHash, BlockBody blockBody); + Task GetBlockAsync(Hash blockHash); + Task GetBlockHeaderAsync(Hash blockHash); + Task RemoveBlockAsync(Hash blockHash); + Task HasBlockAsync(Hash blockHash); +} + +public class BlockManager : IBlockManager { - public interface IBlockManager + private readonly IBlockchainStore _blockBodyStore; + private readonly IBlockchainStore _blockHeaderStore; + + public BlockManager(IBlockchainStore blockHeaderStore, IBlockchainStore blockBodyStore) { - Task AddBlockHeaderAsync(BlockHeader header); - Task AddBlockBodyAsync(Hash blockHash, BlockBody blockBody); - Task GetBlockAsync(Hash blockHash); - Task GetBlockHeaderAsync(Hash blockHash); - Task RemoveBlockAsync(Hash blockHash); - Task HasBlockAsync(Hash blockHash); + Logger = NullLogger.Instance; + _blockHeaderStore = blockHeaderStore; + _blockBodyStore = blockBodyStore; } - - public class BlockManager : IBlockManager - { - private readonly IBlockchainStore _blockHeaderStore; - private readonly IBlockchainStore _blockBodyStore; - public ILogger Logger {get;set;} - public BlockManager(IBlockchainStore blockHeaderStore, IBlockchainStore blockBodyStore) - { - Logger = NullLogger.Instance; - _blockHeaderStore = blockHeaderStore; - _blockBodyStore = blockBodyStore; - } - - public async Task AddBlockHeaderAsync(BlockHeader header) - { - await _blockHeaderStore.SetAsync(header.GetHash().ToStorageKey(), header); - } + public ILogger Logger { get; set; } - public async Task AddBlockBodyAsync(Hash blockHash, BlockBody blockBody) - { - await _blockBodyStore.SetAsync(blockHash.Clone().ToStorageKey(), blockBody); - } - - public async Task GetBlockAsync(Hash blockHash) - { - if (blockHash == null) - { - return null; - } + public async Task AddBlockHeaderAsync(BlockHeader header) + { + await _blockHeaderStore.SetAsync(header.GetHash().ToStorageKey(), header); + } - try - { - var header = await GetBlockHeaderAsync(blockHash); - var bb = await GetBlockBodyAsync(blockHash); + public async Task AddBlockBodyAsync(Hash blockHash, BlockBody blockBody) + { + await _blockBodyStore.SetAsync(blockHash.Clone().ToStorageKey(), blockBody); + } - if (header == null || bb == null) - return null; + public async Task GetBlockAsync(Hash blockHash) + { + if (blockHash == null) return null; - return new Block { Header = header, Body = bb }; - } - catch (Exception e) - { - Logger.LogError(e, $"Error while getting block {blockHash.ToHex()}."); + try + { + var header = await GetBlockHeaderAsync(blockHash); + var bb = await GetBlockBodyAsync(blockHash); + + if (header == null || bb == null) return null; - } - } - public async Task GetBlockHeaderAsync(Hash blockHash) - { - return await _blockHeaderStore.GetAsync(blockHash.ToStorageKey()); + return new Block { Header = header, Body = bb }; } - - private async Task GetBlockBodyAsync(Hash bodyHash) + catch (Exception e) { - return await _blockBodyStore.GetAsync(bodyHash.ToStorageKey()); + Logger.LogError(e, "Error while getting block {BlockHash}", blockHash.ToHex()); + return null; } + } - public async Task RemoveBlockAsync(Hash blockHash) - { - var blockKey = blockHash.ToStorageKey(); - await _blockHeaderStore.RemoveAsync(blockKey); - await _blockBodyStore.RemoveAsync(blockKey); - } + public async Task GetBlockHeaderAsync(Hash blockHash) + { + return await _blockHeaderStore.GetAsync(blockHash.ToStorageKey()); + } - public async Task HasBlockAsync(Hash blockHash) - { - return await _blockHeaderStore.IsExistsAsync(blockHash.ToStorageKey()); - } + public async Task RemoveBlockAsync(Hash blockHash) + { + var blockKey = blockHash.ToStorageKey(); + await _blockHeaderStore.RemoveAsync(blockKey); + await _blockBodyStore.RemoveAsync(blockKey); + } + + public async Task HasBlockAsync(Hash blockHash) + { + return await _blockHeaderStore.IsExistsAsync(blockHash.ToStorageKey()); + } + + private async Task GetBlockBodyAsync(Hash bodyHash) + { + return await _blockBodyStore.GetAsync(bodyHash.ToStorageKey()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/IChainManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/IChainManager.cs index ef35aad92f..06bcd4b719 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/IChainManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/IChainManager.cs @@ -1,559 +1,538 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Google.Protobuf; -using Microsoft.Extensions.Logging; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Domain -{ - [Flags] - public enum BlockAttachOperationStatus - { - None = 0, - NewBlockNotLinked = 1 << 1, - NewBlockLinked = 1 << 2, - LongestChainFound = 1 << 3 | NewBlockLinked, - NewBlocksLinked = 1 << 4 | NewBlockLinked - } +namespace AElf.Kernel.Blockchain.Domain; - public interface IChainManager +[Flags] +public enum BlockAttachOperationStatus +{ + None = 0, + NewBlockNotLinked = 1 << 1, + NewBlockLinked = 1 << 2, + LongestChainFound = (1 << 3) | NewBlockLinked, + NewBlocksLinked = (1 << 4) | NewBlockLinked +} + +public interface IChainManager +{ + Task CreateAsync(Hash genesisBlock); + Task GetAsync(); + Task GetChainBlockLinkAsync(Hash blockHash); + List GetCachedChainBlockLinks(); + Task RemoveChainBlockLinkAsync(Hash blockHash); + void CleanCachedChainBlockLinks(long height); + Task GetChainBlockIndexAsync(long blockHeight); + Task AttachBlockToChainAsync(Chain chain, ChainBlockLink chainBlockLink); + Task SetIrreversibleBlockAsync(Chain chain, Hash irreversibleBlockHash); + Task> GetNotExecutedBlocks(Hash blockHash); + Task SetChainBlockLinkExecutionStatusAsync(ChainBlockLink blockLink, ChainBlockLinkExecutionStatus status); + + Task SetChainBlockLinkExecutionStatusesAsync(IList blockLinks, + ChainBlockLinkExecutionStatus status); + + Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash); + int GetChainId(); + Task RemoveLongestBranchAsync(Chain chain); + + Task GetDiscardedBranchAsync(Chain chain, Hash irreversibleBlockHash, + long irreversibleBlockHeight); + + Task CleanChainBranchAsync(Chain chain, DiscardedBranch discardedBranch); + Task ResetChainToLibAsync(Chain chain); +} + +public class ChainManager : IChainManager, ISingletonDependency +{ + private readonly IBlockchainStore _chainBlockIndexes; + private readonly IChainBlockLinkCacheProvider _chainBlockLinkCacheProvider; + private readonly IBlockchainStore _chainBlockLinks; + private readonly IBlockchainStore _chains; + + private readonly IStaticChainInformationProvider _staticChainInformationProvider; + + public ChainManager(IBlockchainStore chains, + IBlockchainStore chainBlockLinks, + IBlockchainStore chainBlockIndexes, + IStaticChainInformationProvider staticChainInformationProvider, + IChainBlockLinkCacheProvider chainBlockLinkCacheProvider) { - Task CreateAsync(Hash genesisBlock); - Task GetAsync(); - Task GetChainBlockLinkAsync(Hash blockHash); - List GetCachedChainBlockLinks(); - Task RemoveChainBlockLinkAsync(Hash blockHash); - void CleanCachedChainBlockLinks(long height); - Task GetChainBlockIndexAsync(long blockHeight); - Task AttachBlockToChainAsync(Chain chain, ChainBlockLink chainBlockLink); - Task SetIrreversibleBlockAsync(Chain chain, Hash irreversibleBlockHash); - Task> GetNotExecutedBlocks(Hash blockHash); - Task SetChainBlockLinkExecutionStatusAsync(ChainBlockLink blockLink, ChainBlockLinkExecutionStatus status); - Task SetChainBlockLinkExecutionStatusesAsync(IList blockLinks, - ChainBlockLinkExecutionStatus status); - Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash); - int GetChainId(); - Task RemoveLongestBranchAsync(Chain chain); - Task GetDiscardedBranchAsync(Chain chain, Hash irreversibleBlockHash, - long irreversibleBlockHeight); - Task CleanChainBranchAsync(Chain chain, DiscardedBranch discardedBranch); - Task ResetChainToLibAsync(Chain chain); + _chains = chains; + _chainBlockLinks = chainBlockLinks; + _chainBlockIndexes = chainBlockIndexes; + _staticChainInformationProvider = staticChainInformationProvider; + _chainBlockLinkCacheProvider = chainBlockLinkCacheProvider; } - public class ChainManager : IChainManager, ISingletonDependency - { - private readonly IBlockchainStore _chains; - private readonly IBlockchainStore _chainBlockLinks; - private readonly IBlockchainStore _chainBlockIndexes; - - private readonly IStaticChainInformationProvider _staticChainInformationProvider; - private readonly IChainBlockLinkCacheProvider _chainBlockLinkCacheProvider; + private int ChainId => _staticChainInformationProvider.ChainId; - private int ChainId => _staticChainInformationProvider.ChainId; + public ILogger Logger { get; set; } - public ILogger Logger { get; set; } + public async Task CreateAsync(Hash genesisBlock) + { + var chain = await _chains.GetAsync(ChainId.ToStorageKey()); + if (chain != null) + throw new InvalidOperationException("chain already exists"); - public ChainManager(IBlockchainStore chains, - IBlockchainStore chainBlockLinks, - IBlockchainStore chainBlockIndexes, - IStaticChainInformationProvider staticChainInformationProvider, - IChainBlockLinkCacheProvider chainBlockLinkCacheProvider) + chain = new Chain { - _chains = chains; - _chainBlockLinks = chainBlockLinks; - _chainBlockIndexes = chainBlockIndexes; - _staticChainInformationProvider = staticChainInformationProvider; - _chainBlockLinkCacheProvider = chainBlockLinkCacheProvider; - } + Id = ChainId, + LongestChainHeight = AElfConstants.GenesisBlockHeight, + LongestChainHash = genesisBlock, + BestChainHeight = AElfConstants.GenesisBlockHeight, + BestChainHash = genesisBlock, + GenesisBlockHash = genesisBlock, + LastIrreversibleBlockHash = genesisBlock, + LastIrreversibleBlockHeight = AElfConstants.GenesisBlockHeight, + Branches = + { + { genesisBlock.ToStorageKey(), AElfConstants.GenesisBlockHeight } + } + }; - public async Task CreateAsync(Hash genesisBlock) + await SetChainBlockLinkAsync(new ChainBlockLink { - var chain = await _chains.GetAsync(ChainId.ToStorageKey()); - if (chain != null) - throw new InvalidOperationException("chain already exists"); + BlockHash = genesisBlock, + Height = AElfConstants.GenesisBlockHeight, + PreviousBlockHash = Hash.Empty, + IsLinked = true, + IsIrreversibleBlock = true + }); - chain = new Chain() - { - Id = ChainId, - LongestChainHeight = AElfConstants.GenesisBlockHeight, - LongestChainHash = genesisBlock, - BestChainHeight = AElfConstants.GenesisBlockHeight, - BestChainHash = genesisBlock, - GenesisBlockHash = genesisBlock, - LastIrreversibleBlockHash = genesisBlock, - LastIrreversibleBlockHeight = AElfConstants.GenesisBlockHeight, - Branches = - { - {genesisBlock.ToStorageKey(), AElfConstants.GenesisBlockHeight} - } - }; + await SetChainBlockIndexAsync(AElfConstants.GenesisBlockHeight, genesisBlock); - await SetChainBlockLinkAsync(new ChainBlockLink() - { - BlockHash = genesisBlock, - Height = AElfConstants.GenesisBlockHeight, - PreviousBlockHash = Hash.Empty, - IsLinked = true, - IsIrreversibleBlock = true - }); + await _chains.SetAsync(ChainId.ToStorageKey(), chain); - await SetChainBlockIndexAsync(AElfConstants.GenesisBlockHeight, genesisBlock); + return chain; + } - await _chains.SetAsync(ChainId.ToStorageKey(), chain); + public async Task GetAsync() + { + var chain = await _chains.GetAsync(ChainId.ToStorageKey()); + return chain; + } - return chain; - } + public async Task GetChainBlockLinkAsync(Hash blockHash) + { + var chainBlockLink = _chainBlockLinkCacheProvider.GetChainBlockLink(blockHash); + if (chainBlockLink != null) return chainBlockLink; + return await GetChainBlockLinkAsync(blockHash.ToStorageKey()); + } - public async Task GetAsync() - { - var chain = await _chains.GetAsync(ChainId.ToStorageKey()); - return chain; - } + public List GetCachedChainBlockLinks() + { + return _chainBlockLinkCacheProvider.GetChainBlockLinks(); + } - public async Task GetChainBlockLinkAsync(Hash blockHash) - { - var chainBlockLink = _chainBlockLinkCacheProvider.GetChainBlockLink(blockHash); - if (chainBlockLink != null) return chainBlockLink; - return await GetChainBlockLinkAsync(blockHash.ToStorageKey()); - } + public async Task RemoveChainBlockLinkAsync(Hash blockHash) + { + await _chainBlockLinks.RemoveAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + + blockHash.ToStorageKey()); + _chainBlockLinkCacheProvider.RemoveChainBlockLink(blockHash); + } - public List GetCachedChainBlockLinks() - { - return _chainBlockLinkCacheProvider.GetChainBlockLinks(); - } - - private async Task GetChainBlockLinkWithCacheAsync(string blockHash) - { - var hash = new Hash {Value = ByteString.FromBase64(blockHash)}; - var chainBlockLink = _chainBlockLinkCacheProvider.GetChainBlockLink(hash); - if (chainBlockLink != null) return chainBlockLink; - return await GetChainBlockLinkAsync(blockHash); - } + public void CleanCachedChainBlockLinks(long height) + { + var chainBlockLinks = _chainBlockLinkCacheProvider.GetChainBlockLinks() + .Where(b => b.Height <= height) + .OrderBy(b => b.Height).ToList(); + foreach (var chainBlockLink in chainBlockLinks) + _chainBlockLinkCacheProvider.RemoveChainBlockLink(chainBlockLink.BlockHash); + } - private async Task GetChainBlockLinkAsync(string blockHash) - { - return await _chainBlockLinks.GetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + blockHash); - } - - private async Task> GetChainBlockLinksAsync(IList blockHashes) - { - var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; - return await _chainBlockLinks.GetAllAsync(blockHashes.Select(h => prefix + h).ToList()); - } + public async Task GetChainBlockIndexAsync(long blockHeight) + { + return await _chainBlockIndexes.GetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + + blockHeight.ToStorageKey()); + } - public async Task SetChainBlockLinkAsync(ChainBlockLink chainBlockLink) - { - await _chainBlockLinks.SetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + chainBlockLink.BlockHash.ToStorageKey(), chainBlockLink); - _chainBlockLinkCacheProvider.SetChainBlockLink(chainBlockLink); - } - - private async Task SetChainBlockLinksAsync(IList chainBlockLinks) - { - var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; - await _chainBlockLinks.SetAllAsync(chainBlockLinks.ToDictionary(l => prefix + l.BlockHash.ToStorageKey(), - l => l)); - foreach (var chainBlockLink in chainBlockLinks) - { - _chainBlockLinkCacheProvider.SetChainBlockLink(chainBlockLink); - } - } + public async Task AttachBlockToChainAsync(Chain chain, ChainBlockLink chainBlockLink) + { + var status = BlockAttachOperationStatus.None; - private async Task SetChainBlockIndexAsync(long blockHeight, Hash blockHash) - { - await _chainBlockIndexes.SetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + blockHeight.ToStorageKey(), - new ChainBlockIndex() {BlockHash = blockHash}); - } - - private async Task SetChainBlockIndexesAsync(IDictionary blockIndexes) - { - var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; - await _chainBlockIndexes.SetAllAsync(blockIndexes.ToDictionary(d => prefix + d.Key.ToStorageKey(), - d => new ChainBlockIndex {BlockHash = d.Value})); - } + var isLinkedToLongestChain = chainBlockLink.PreviousBlockHash == chain.LongestChainHash && + chainBlockLink.Height == chain.LongestChainHeight + 1; - public async Task RemoveChainBlockLinkAsync(Hash blockHash) - { - await _chainBlockLinks.RemoveAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + blockHash.ToStorageKey()); - _chainBlockLinkCacheProvider.RemoveChainBlockLink(blockHash); - } + Logger.LogDebug( + $"Start attach block hash {chainBlockLink.BlockHash}, height {chainBlockLink.Height}"); - public void CleanCachedChainBlockLinks(long height) + while (true) { - var chainBlockLinks = _chainBlockLinkCacheProvider.GetChainBlockLinks() - .Where(b => b.Height <= height) - .OrderBy(b => b.Height).ToList(); - foreach (var chainBlockLink in chainBlockLinks) - { - _chainBlockLinkCacheProvider.RemoveChainBlockLink(chainBlockLink.BlockHash); - } - } + var previousHash = chainBlockLink.PreviousBlockHash.ToStorageKey(); + var blockHash = chainBlockLink.BlockHash.ToStorageKey(); - public async Task GetChainBlockIndexAsync(long blockHeight) - { - return await _chainBlockIndexes.GetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + blockHeight.ToStorageKey()); - } - - public async Task AttachBlockToChainAsync(Chain chain, ChainBlockLink chainBlockLink) - { - BlockAttachOperationStatus status = BlockAttachOperationStatus.None; - - bool isLinkedToLongestChain = chainBlockLink.PreviousBlockHash == chain.LongestChainHash && - chainBlockLink.Height == chain.LongestChainHeight + 1; - - Logger.LogDebug( - $"Start attach block hash {chainBlockLink.BlockHash}, height {chainBlockLink.Height}"); - - while (true) + if (chain.Branches.ContainsKey(previousHash)) { - var previousHash = chainBlockLink.PreviousBlockHash.ToStorageKey(); - var blockHash = chainBlockLink.BlockHash.ToStorageKey(); + chain.Branches[blockHash] = chainBlockLink.Height; + chain.Branches.Remove(previousHash); - if (chain.Branches.ContainsKey(previousHash)) + if ((isLinkedToLongestChain && chainBlockLink.Height > chain.LongestChainHeight) + || chainBlockLink.Height >= chain.LongestChainHeight + 8) { - chain.Branches[blockHash] = chainBlockLink.Height; - chain.Branches.Remove(previousHash); - - if (isLinkedToLongestChain && chainBlockLink.Height > chain.LongestChainHeight - || chainBlockLink.Height >= chain.LongestChainHeight + 8) - { - chain.LongestChainHeight = chainBlockLink.Height; - chain.LongestChainHash = chainBlockLink.BlockHash; - status |= BlockAttachOperationStatus.LongestChainFound; - } + chain.LongestChainHeight = chainBlockLink.Height; + chain.LongestChainHash = chainBlockLink.BlockHash; + status |= BlockAttachOperationStatus.LongestChainFound; + } - if (chainBlockLink.IsLinked) - throw new Exception("chain block link should not be linked"); + if (chainBlockLink.IsLinked) + throw new Exception("chain block link should not be linked"); - chainBlockLink.IsLinked = true; + chainBlockLink.IsLinked = true; - await SetChainBlockLinkAsync(chainBlockLink); + await SetChainBlockLinkAsync(chainBlockLink); - if (!chain.NotLinkedBlocks.ContainsKey(blockHash)) - { - status |= BlockAttachOperationStatus.NewBlockLinked; - break; - } + if (!chain.NotLinkedBlocks.ContainsKey(blockHash)) + { + status |= BlockAttachOperationStatus.NewBlockLinked; + break; + } - chainBlockLink = await GetChainBlockLinkWithCacheAsync(chain.NotLinkedBlocks[blockHash]); + chainBlockLink = await GetChainBlockLinkWithCacheAsync(chain.NotLinkedBlocks[blockHash]); - chain.NotLinkedBlocks.Remove(blockHash); + chain.NotLinkedBlocks.Remove(blockHash); - status |= BlockAttachOperationStatus.NewBlocksLinked; - } - else + status |= BlockAttachOperationStatus.NewBlocksLinked; + } + else + { + //check database to ensure whether it can be a branch + var previousChainBlockLink = await GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); + if (previousChainBlockLink != null && previousChainBlockLink.IsLinked) { - //check database to ensure whether it can be a branch - var previousChainBlockLink = await this.GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); - if (previousChainBlockLink != null && previousChainBlockLink.IsLinked) - { - chain.Branches[previousChainBlockLink.BlockHash.ToStorageKey()] = previousChainBlockLink.Height; - continue; - } + chain.Branches[previousChainBlockLink.BlockHash.ToStorageKey()] = previousChainBlockLink.Height; + continue; + } - chain.NotLinkedBlocks[previousHash] = blockHash; + chain.NotLinkedBlocks[previousHash] = blockHash; - if (status != BlockAttachOperationStatus.None) - throw new Exception("invalid status"); + if (status != BlockAttachOperationStatus.None) + throw new Exception("invalid status"); - status = BlockAttachOperationStatus.NewBlockNotLinked; - await SetChainBlockLinkAsync(chainBlockLink); - break; - } + status = BlockAttachOperationStatus.NewBlockNotLinked; + await SetChainBlockLinkAsync(chainBlockLink); + break; } + } - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - Logger.LogInformation($"Attach {chainBlockLink.BlockHash} to longest chain, status: {status}, " + - $"longest chain height: {chain.LongestChainHeight}, longest chain hash: {chain.LongestChainHash}"); + Logger.LogInformation($"Attach {chainBlockLink.BlockHash} to longest chain, status: {status}, " + + $"longest chain height: {chain.LongestChainHeight}, longest chain hash: {chain.LongestChainHash}"); - return status; - } + return status; + } + + public async Task SetIrreversibleBlockAsync(Chain chain, Hash irreversibleBlockHash) + { + var links = new List(); - public async Task SetIrreversibleBlockAsync(Chain chain, Hash irreversibleBlockHash) + while (true) { - var links = new List(); + var chainBlockLink = await GetChainBlockLinkAsync(irreversibleBlockHash); + if (chainBlockLink == null || !chainBlockLink.IsLinked) + throw new InvalidOperationException( + $"should not set an unlinked block as irreversible block, height: {chainBlockLink?.Height}, hash: {chainBlockLink?.BlockHash}"); + if (chainBlockLink.IsIrreversibleBlock) + break; + chainBlockLink.IsIrreversibleBlock = true; + links.Add(chainBlockLink); + irreversibleBlockHash = chainBlockLink.PreviousBlockHash; + } - while (true) - { - var chainBlockLink = await GetChainBlockLinkAsync(irreversibleBlockHash); - if (chainBlockLink == null || !chainBlockLink.IsLinked) - throw new InvalidOperationException( - $"should not set an unlinked block as irreversible block, height: {chainBlockLink?.Height}, hash: {chainBlockLink?.BlockHash}"); - if (chainBlockLink.IsIrreversibleBlock) - break; - chainBlockLink.IsIrreversibleBlock = true; - links.Add(chainBlockLink); - irreversibleBlockHash = chainBlockLink.PreviousBlockHash; - } + if (links.Count > 0) + { + if (links.Last().Height <= chain.LastIrreversibleBlockHeight) + return false; + await SetChainBlockIndexesAsync(links.ToDictionary(l => l.Height, l => l.BlockHash)); + await SetChainBlockLinksAsync(links); + chain.LastIrreversibleBlockHash = links.First().BlockHash; + chain.LastIrreversibleBlockHeight = links.First().Height; + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - if (links.Count > 0) - { - if (links.Last().Height <= chain.LastIrreversibleBlockHeight) - return false; - await SetChainBlockIndexesAsync(links.ToDictionary(l => l.Height, l => l.BlockHash)); - await SetChainBlockLinksAsync(links); - chain.LastIrreversibleBlockHash = links.First().BlockHash; - chain.LastIrreversibleBlockHeight = links.First().Height; - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - - Logger.LogDebug( - $"Setting chain lib height: {chain.LastIrreversibleBlockHeight}, chain lib hash: {chain.LastIrreversibleBlockHash}"); - - return true; - } + Logger.LogDebug( + $"Setting chain lib height: {chain.LastIrreversibleBlockHeight}, chain lib hash: {chain.LastIrreversibleBlockHash}"); - return false; + return true; } - public async Task> GetNotExecutedBlocks(Hash blockHash) + return false; + } + + public async Task> GetNotExecutedBlocks(Hash blockHash) + { + var output = new List(); + while (true) { - var output = new List(); - while (true) + var chainBlockLink = await GetChainBlockLinkAsync(blockHash); + if (chainBlockLink != null) { - var chainBlockLink = await GetChainBlockLinkAsync(blockHash); - if (chainBlockLink != null) + if (chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionNone) { - if (chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionNone) - { - output.Add(chainBlockLink); - if (chainBlockLink.PreviousBlockHash != null) - blockHash = chainBlockLink.PreviousBlockHash; - continue; - } - else if (chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionFailed) - { - output.Clear(); - } + output.Add(chainBlockLink); + if (chainBlockLink.PreviousBlockHash != null) + blockHash = chainBlockLink.PreviousBlockHash; + continue; } - break; + if (chainBlockLink.ExecutionStatus == ChainBlockLinkExecutionStatus.ExecutionFailed) + { + output.Clear(); + } } - output.Reverse(); - return output; + break; } - public async Task SetChainBlockLinkExecutionStatusAsync(ChainBlockLink blockLink, - ChainBlockLinkExecutionStatus status) + output.Reverse(); + return output; + } + + public async Task SetChainBlockLinkExecutionStatusAsync(ChainBlockLink blockLink, + ChainBlockLinkExecutionStatus status) + { + if (blockLink.ExecutionStatus != ChainBlockLinkExecutionStatus.ExecutionNone || + status == ChainBlockLinkExecutionStatus.ExecutionNone) + throw new InvalidOperationException(); + + blockLink.ExecutionStatus = status; + await SetChainBlockLinkAsync(blockLink); + } + + public async Task SetChainBlockLinkExecutionStatusesAsync(IList blockLinks, + ChainBlockLinkExecutionStatus status) + { + foreach (var blockLink in blockLinks) { if (blockLink.ExecutionStatus != ChainBlockLinkExecutionStatus.ExecutionNone || status == ChainBlockLinkExecutionStatus.ExecutionNone) throw new InvalidOperationException(); blockLink.ExecutionStatus = status; - await SetChainBlockLinkAsync(blockLink); } - - public async Task SetChainBlockLinkExecutionStatusesAsync(IList blockLinks, - ChainBlockLinkExecutionStatus status) - { - foreach (var blockLink in blockLinks) - { - if (blockLink.ExecutionStatus != ChainBlockLinkExecutionStatus.ExecutionNone || - status == ChainBlockLinkExecutionStatus.ExecutionNone) - throw new InvalidOperationException(); - blockLink.ExecutionStatus = status; - } + await SetChainBlockLinksAsync(blockLinks); + } - await SetChainBlockLinksAsync(blockLinks); - } + public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) + { + if (chain.BestChainHeight > bestChainHeight) throw new InvalidOperationException(); - public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) - { - if (chain.BestChainHeight > bestChainHeight) - { - throw new InvalidOperationException(); - } + chain.BestChainHeight = bestChainHeight; + chain.BestChainHash = bestChainHash; - chain.BestChainHeight = bestChainHeight; - chain.BestChainHash = bestChainHash; + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + } - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - } + public int GetChainId() + { + return ChainId; + } - public int GetChainId() - { - return ChainId; - } + public async Task GetDiscardedBranchAsync(Chain chain, Hash irreversibleBlockHash, + long irreversibleBlockHeight) + { + var toCleanBranchKeys = new List(); - public async Task GetDiscardedBranchAsync(Chain chain, Hash irreversibleBlockHash, long irreversibleBlockHeight) + var bestChainKey = chain.BestChainHash.ToStorageKey(); + + foreach (var branch in chain.Branches) { - var toCleanBranchKeys = new List(); + if (branch.Key == bestChainKey) continue; - var bestChainKey = chain.BestChainHash.ToStorageKey(); + var chainBlockLink = await GetChainBlockLinkWithCacheAsync(branch.Key); - foreach (var branch in chain.Branches) + // Remove incorrect branch. + // When an existing block is attached, will generate an incorrect branch. + // and only clean up the branch, not clean the block in the branch. + if (chainBlockLink != null) { - if (branch.Key == bestChainKey) + var chainBlockIndex = await GetChainBlockIndexAsync(chainBlockLink.Height); + if (chainBlockIndex != null && chainBlockIndex.BlockHash == chainBlockLink.BlockHash) { + Logger.LogDebug($"Remove incorrect branch: {branch.Key}"); + toCleanBranchKeys.Add(branch.Key); continue; } + } - var chainBlockLink = await GetChainBlockLinkWithCacheAsync(branch.Key); - - // Remove incorrect branch. - // When an existing block is attached, will generate an incorrect branch. - // and only clean up the branch, not clean the block in the branch. - if (chainBlockLink != null) + var isDiscardedBranch = false; + while (true) + { + if (chainBlockLink == null) { - var chainBlockIndex = await GetChainBlockIndexAsync(chainBlockLink.Height); - if (chainBlockIndex != null && chainBlockIndex.BlockHash == chainBlockLink.BlockHash) - { - Logger.LogDebug($"Remove incorrect branch: {branch.Key}"); - toCleanBranchKeys.Add(branch.Key); - continue; - } + isDiscardedBranch = true; + break; } - var isDiscardedBranch = false; - while (true) + if (chainBlockLink.PreviousBlockHash == irreversibleBlockHash) break; + + // Use the height and hash alternatives to ChainBlockLink.IsIrreversibleBlock to verify, + // because ChainBlockLink can be overwrite + if (chainBlockLink.Height < irreversibleBlockHeight) { - if (chainBlockLink == null) + var chainBlockIndex = await GetChainBlockIndexAsync(chainBlockLink.Height); + if (chainBlockIndex.BlockHash == chainBlockLink.BlockHash) { isDiscardedBranch = true; break; } - - if (chainBlockLink.PreviousBlockHash == irreversibleBlockHash) - { - break; - } - - // Use the height and hash alternatives to ChainBlockLink.IsIrreversibleBlock to verify, - // because ChainBlockLink can be overwrite - if (chainBlockLink.Height < irreversibleBlockHeight) - { - var chainBlockIndex = await GetChainBlockIndexAsync(chainBlockLink.Height); - if (chainBlockIndex.BlockHash == chainBlockLink.BlockHash) - { - isDiscardedBranch = true; - break; - } - } - - chainBlockLink = await GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); } - if (isDiscardedBranch) - { - toCleanBranchKeys.Add(branch.Key); - } + chainBlockLink = await GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); } - var toCleanNotLinkedKeys = await GetNotLinkedKeysAsync(chain, irreversibleBlockHeight); - - return new DiscardedBranch - { - BranchKeys = toCleanBranchKeys, - NotLinkedKeys = toCleanNotLinkedKeys - }; + if (isDiscardedBranch) toCleanBranchKeys.Add(branch.Key); } - private async Task> GetNotLinkedKeysAsync(Chain chain, long irreversibleBlockHeight) + var toCleanNotLinkedKeys = await GetNotLinkedKeysAsync(chain, irreversibleBlockHeight); + + return new DiscardedBranch { - var toCleanNotLinkedKeys = new List(); - foreach (var notLinkedBlock in chain.NotLinkedBlocks) - { - var blockLink = await GetChainBlockLinkWithCacheAsync(notLinkedBlock.Value); - if (blockLink == null) - { - toCleanNotLinkedKeys.Add(notLinkedBlock.Key); - continue; - } + BranchKeys = toCleanBranchKeys, + NotLinkedKeys = toCleanNotLinkedKeys + }; + } - if (blockLink.Height <= irreversibleBlockHeight) - { - toCleanNotLinkedKeys.Add(notLinkedBlock.Key); - } + public async Task CleanChainBranchAsync(Chain chain, DiscardedBranch discardedBranch) + { + var longestChainKey = chain.LongestChainHash.ToStorageKey(); + var bestChainKey = chain.BestChainHash.ToStorageKey(); + foreach (var key in discardedBranch.BranchKeys) + { + if (key == bestChainKey) continue; + + if (key == longestChainKey) + { + chain.LongestChainHash = chain.BestChainHash; + chain.LongestChainHeight = chain.BestChainHeight; } - return toCleanNotLinkedKeys; + chain.Branches.Remove(key); } - public async Task CleanChainBranchAsync(Chain chain, DiscardedBranch discardedBranch) - { - var longestChainKey = chain.LongestChainHash.ToStorageKey(); - var bestChainKey = chain.BestChainHash.ToStorageKey(); - foreach (var key in discardedBranch.BranchKeys) - { - if (key == bestChainKey) - { - continue; - } + foreach (var key in discardedBranch.NotLinkedKeys) chain.NotLinkedBlocks.Remove(key); - if (key == longestChainKey) - { - chain.LongestChainHash = chain.BestChainHash; - chain.LongestChainHeight = chain.BestChainHeight; - } + Logger.LogDebug( + $"Clean chain branch, Branches: [{discardedBranch.BranchKeys.JoinAsString(",")}], NotLinkedBlocks: [{discardedBranch.NotLinkedKeys.JoinAsString(",")}]"); - chain.Branches.Remove(key); - } + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + } - foreach (var key in discardedBranch.NotLinkedKeys) - { - chain.NotLinkedBlocks.Remove(key); - } + public async Task RemoveLongestBranchAsync(Chain chain) + { + chain.Branches.Remove(chain.LongestChainHash.ToStorageKey()); + chain.Branches[chain.BestChainHash.ToStorageKey()] = chain.BestChainHeight; - Logger.LogDebug( - $"Clean chain branch, Branches: [{discardedBranch.BranchKeys.JoinAsString(",")}], NotLinkedBlocks: [{discardedBranch.NotLinkedKeys.JoinAsString(",")}]"); + chain.LongestChainHash = chain.BestChainHash; + chain.LongestChainHeight = chain.BestChainHeight; + Logger.LogInformation( + $"Switch Longest chain to height: {chain.LongestChainHeight}, hash: {chain.LongestChainHash}."); - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - } + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + } - public async Task RemoveLongestBranchAsync(Chain chain) + public async Task ResetChainToLibAsync(Chain chain) + { + var libHash = chain.LastIrreversibleBlockHash; + var libHeight = chain.LastIrreversibleBlockHeight; + + foreach (var branch in chain.Branches) { - chain.Branches.Remove(chain.LongestChainHash.ToStorageKey()); - chain.Branches[chain.BestChainHash.ToStorageKey()] = chain.BestChainHeight; + var hash = Hash.LoadFromBase64(branch.Key); + var chainBlockLink = await GetChainBlockLinkAsync(hash); - chain.LongestChainHash = chain.BestChainHash; - chain.LongestChainHeight = chain.BestChainHeight; - Logger.LogInformation( - $"Switch Longest chain to height: {chain.LongestChainHeight}, hash: {chain.LongestChainHash}."); + while (chainBlockLink != null && chainBlockLink.Height > libHeight) + { + chainBlockLink.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; + chainBlockLink.IsLinked = false; + await SetChainBlockLinkAsync(chainBlockLink); - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + chainBlockLink = await GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); + } } - public async Task ResetChainToLibAsync(Chain chain) - { - var libHash = chain.LastIrreversibleBlockHash; - var libHeight = chain.LastIrreversibleBlockHeight; + chain.Branches.Clear(); + chain.NotLinkedBlocks.Clear(); - foreach (var branch in chain.Branches) - { - var hash = Hash.LoadFromBase64(branch.Key); - var chainBlockLink = await GetChainBlockLinkAsync(hash); + chain.Branches[libHash.ToStorageKey()] = libHeight; - while (chainBlockLink != null && chainBlockLink.Height > libHeight) - { - chainBlockLink.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; - chainBlockLink.IsLinked = false; - await SetChainBlockLinkAsync(chainBlockLink); - - chainBlockLink = await GetChainBlockLinkAsync(chainBlockLink.PreviousBlockHash); - } + chain.BestChainHash = libHash; + chain.BestChainHeight = libHeight; + chain.LongestChainHash = libHash; + chain.LongestChainHeight = libHeight; + + Logger.LogInformation($"Rollback to height {chain.BestChainHeight}, hash {chain.BestChainHash}."); + await _chains.SetAsync(chain.Id.ToStorageKey(), chain); + + return chain; + } + + private async Task GetChainBlockLinkWithCacheAsync(string blockHash) + { + var hash = new Hash { Value = ByteString.FromBase64(blockHash) }; + var chainBlockLink = _chainBlockLinkCacheProvider.GetChainBlockLink(hash); + if (chainBlockLink != null) return chainBlockLink; + return await GetChainBlockLinkAsync(blockHash); + } + + private async Task GetChainBlockLinkAsync(string blockHash) + { + return await _chainBlockLinks.GetAsync(ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + + blockHash); + } + + private async Task> GetChainBlockLinksAsync(IList blockHashes) + { + var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; + return await _chainBlockLinks.GetAllAsync(blockHashes.Select(h => prefix + h).ToList()); + } + + public async Task SetChainBlockLinkAsync(ChainBlockLink chainBlockLink) + { + await _chainBlockLinks.SetAsync( + ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + chainBlockLink.BlockHash.ToStorageKey(), + chainBlockLink); + _chainBlockLinkCacheProvider.SetChainBlockLink(chainBlockLink); + } + + private async Task SetChainBlockLinksAsync(IList chainBlockLinks) + { + var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; + await _chainBlockLinks.SetAllAsync(chainBlockLinks.ToDictionary(l => prefix + l.BlockHash.ToStorageKey(), + l => l)); + foreach (var chainBlockLink in chainBlockLinks) _chainBlockLinkCacheProvider.SetChainBlockLink(chainBlockLink); + } + + private async Task SetChainBlockIndexAsync(long blockHeight, Hash blockHash) + { + await _chainBlockIndexes.SetAsync( + ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator + blockHeight.ToStorageKey(), + new ChainBlockIndex { BlockHash = blockHash }); + } + + private async Task SetChainBlockIndexesAsync(IDictionary blockIndexes) + { + var prefix = ChainId.ToStorageKey() + KernelConstants.StorageKeySeparator; + await _chainBlockIndexes.SetAllAsync(blockIndexes.ToDictionary(d => prefix + d.Key.ToStorageKey(), + d => new ChainBlockIndex { BlockHash = d.Value })); + } + + private async Task> GetNotLinkedKeysAsync(Chain chain, long irreversibleBlockHeight) + { + var toCleanNotLinkedKeys = new List(); + foreach (var notLinkedBlock in chain.NotLinkedBlocks) + { + var blockLink = await GetChainBlockLinkWithCacheAsync(notLinkedBlock.Value); + if (blockLink == null) + { + toCleanNotLinkedKeys.Add(notLinkedBlock.Key); + continue; } - - chain.Branches.Clear(); - chain.NotLinkedBlocks.Clear(); - - chain.Branches[libHash.ToStorageKey()] = libHeight; - - chain.BestChainHash = libHash; - chain.BestChainHeight = libHeight; - chain.LongestChainHash = libHash; - chain.LongestChainHeight = libHeight; - - Logger.LogInformation($"Rollback to height {chain.BestChainHeight}, hash {chain.BestChainHash}."); - await _chains.SetAsync(chain.Id.ToStorageKey(), chain); - return chain; + if (blockLink.Height <= irreversibleBlockHeight) toCleanNotLinkedKeys.Add(notLinkedBlock.Key); } + + return toCleanNotLinkedKeys; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionBlockIndexManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionBlockIndexManager.cs index 43225dbcec..b962c7fe70 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionBlockIndexManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionBlockIndexManager.cs @@ -1,49 +1,45 @@ -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -namespace AElf.Kernel.Blockchain.Domain +namespace AElf.Kernel.Blockchain.Domain; + +public interface ITransactionBlockIndexManager +{ + Task GetTransactionBlockIndexAsync(Hash transactionId); + Task SetTransactionBlockIndexAsync(Hash transactionId, TransactionBlockIndex transactionBlockIndex); + Task SetTransactionBlockIndicesAsync(IDictionary transactionBlockIndexes); + Task RemoveTransactionIndicesAsync(IEnumerable txIds); +} + +public class TransactionBlockIndexManager : ITransactionBlockIndexManager { - public interface ITransactionBlockIndexManager + private readonly IBlockchainStore _transactionBlockIndexes; + + public TransactionBlockIndexManager(IBlockchainStore transactionBlockIndexes) + { + _transactionBlockIndexes = transactionBlockIndexes; + } + + public async Task GetTransactionBlockIndexAsync(Hash transactionId) + { + var transactionBlockIndex = await _transactionBlockIndexes.GetAsync(transactionId.ToStorageKey()); + return transactionBlockIndex; + } + + public async Task SetTransactionBlockIndexAsync(Hash transactionId, TransactionBlockIndex transactionBlockIndex) + { + await _transactionBlockIndexes.SetAsync(transactionId.ToStorageKey(), transactionBlockIndex); + } + + public async Task SetTransactionBlockIndicesAsync(IDictionary transactionBlockIndexes) { - Task GetTransactionBlockIndexAsync(Hash transactionId); - Task SetTransactionBlockIndexAsync(Hash transactionId, TransactionBlockIndex transactionBlockIndex); - Task SetTransactionBlockIndicesAsync(IDictionary transactionBlockIndexes); - Task RemoveTransactionIndicesAsync(IEnumerable txIds); + await _transactionBlockIndexes.SetAllAsync( + transactionBlockIndexes.ToDictionary(t => t.Key.ToStorageKey(), t => t.Value)); } - public class TransactionBlockIndexManager : ITransactionBlockIndexManager + public async Task RemoveTransactionIndicesAsync(IEnumerable txIds) { - private readonly IBlockchainStore _transactionBlockIndexes; - - public TransactionBlockIndexManager(IBlockchainStore transactionBlockIndexes) - { - _transactionBlockIndexes = transactionBlockIndexes; - } - - public async Task GetTransactionBlockIndexAsync(Hash transactionId) - { - var transactionBlockIndex = await _transactionBlockIndexes.GetAsync(transactionId.ToStorageKey()); - return transactionBlockIndex; - } - - public async Task SetTransactionBlockIndexAsync(Hash transactionId, TransactionBlockIndex transactionBlockIndex) - { - await _transactionBlockIndexes.SetAsync(transactionId.ToStorageKey(), transactionBlockIndex); - } - - public async Task SetTransactionBlockIndicesAsync(IDictionary transactionBlockIndexes) - { - await _transactionBlockIndexes.SetAllAsync( - transactionBlockIndexes.ToDictionary(t => t.Key.ToStorageKey(), t => t.Value)); - } - - public async Task RemoveTransactionIndicesAsync(IEnumerable txIds) - { - await _transactionBlockIndexes.RemoveAllAsync(txIds.Select(txId => txId.ToStorageKey()).ToList()); - } + await _transactionBlockIndexes.RemoveAllAsync(txIds.Select(txId => txId.ToStorageKey()).ToList()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionManager.cs index 577cdfa2e2..fe76bc0911 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionManager.cs @@ -1,17 +1,12 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.Blockchain.Domain; -namespace AElf.Kernel.Blockchain.Domain +public interface ITransactionManager { - public interface ITransactionManager - { - Task AddTransactionAsync(Transaction tx); - Task AddTransactionsAsync(IList txs); - Task GetTransactionAsync(Hash txId); - Task> GetTransactionsAsync(IList txIds); - Task RemoveTransactionAsync(Hash txId); - Task RemoveTransactionsAsync(IList txIds); - Task HasTransactionAsync(Hash txId); - } + Task AddTransactionAsync(Transaction tx); + Task AddTransactionsAsync(IList txs); + Task GetTransactionAsync(Hash txId); + Task> GetTransactionsAsync(IList txIds); + Task RemoveTransactionAsync(Hash txId); + Task RemoveTransactionsAsync(IList txIds); + Task HasTransactionAsync(Hash txId); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionResultManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionResultManager.cs index b37b46883f..e2f2176886 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionResultManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/ITransactionResultManager.cs @@ -1,60 +1,60 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Linq; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -namespace AElf.Kernel.Blockchain.Domain +namespace AElf.Kernel.Blockchain.Domain; + +public interface ITransactionResultManager +{ + Task AddTransactionResultAsync(TransactionResult transactionResult, Hash disambiguationHash); + + Task AddTransactionResultsAsync(IList transactionResults, Hash disambiguationHash); + Task GetTransactionResultAsync(Hash txId, Hash disambiguationHash); + Task> GetTransactionResultsAsync(IList txIds, Hash disambiguationHash); + Task HasTransactionResultAsync(Hash transactionId, Hash disambiguationHash); +} + +public class TransactionResultManager : ITransactionResultManager { - public interface ITransactionResultManager + private readonly IBlockchainStore _transactionResultStore; + + public TransactionResultManager(IBlockchainStore transactionResultStore) + { + _transactionResultStore = transactionResultStore; + } + + public async Task AddTransactionResultAsync(TransactionResult transactionResult, Hash disambiguationHash) { - Task AddTransactionResultAsync(TransactionResult transactionResult, Hash disambiguationHash); + await _transactionResultStore.SetAsync( + HashHelper.XorAndCompute(transactionResult.TransactionId, disambiguationHash).ToStorageKey(), + transactionResult); + } + + public async Task AddTransactionResultsAsync(IList transactionResults, + Hash disambiguationHash) + { + await _transactionResultStore.SetAllAsync( + transactionResults.ToDictionary( + t => HashHelper.XorAndCompute(t.TransactionId, disambiguationHash).ToStorageKey(), t => t)); + } - Task AddTransactionResultsAsync(IList transactionResults, Hash disambiguationHash); - Task GetTransactionResultAsync(Hash txId, Hash disambiguationHash); - Task> GetTransactionResultsAsync(IList txIds, Hash disambiguationHash); - Task HasTransactionResultAsync(Hash transactionId, Hash disambiguationHash); + public async Task GetTransactionResultAsync(Hash txId, Hash disambiguationHash) + { + return await _transactionResultStore.GetAsync(HashHelper.XorAndCompute(txId, disambiguationHash) + .ToStorageKey()); + } + + public async Task> GetTransactionResultsAsync(IList txIds, + Hash disambiguationHash) + { + return await _transactionResultStore.GetAllAsync(txIds + .Select(t => HashHelper.XorAndCompute(t, disambiguationHash).ToStorageKey()) + .ToList()); } - public class TransactionResultManager : ITransactionResultManager + public async Task HasTransactionResultAsync(Hash transactionId, Hash disambiguationHash) { - private readonly IBlockchainStore _transactionResultStore; - - public TransactionResultManager(IBlockchainStore transactionResultStore) - { - _transactionResultStore = transactionResultStore; - } - - public async Task AddTransactionResultAsync(TransactionResult transactionResult, Hash disambiguationHash) - { - await _transactionResultStore.SetAsync( - HashHelper.XorAndCompute(transactionResult.TransactionId, disambiguationHash).ToStorageKey(), - transactionResult); - } - - public async Task AddTransactionResultsAsync(IList transactionResults, - Hash disambiguationHash) - { - await _transactionResultStore.SetAllAsync( - transactionResults.ToDictionary(t => HashHelper.XorAndCompute(t.TransactionId, disambiguationHash).ToStorageKey(), t => t)); - } - - public async Task GetTransactionResultAsync(Hash txId, Hash disambiguationHash) - { - return await _transactionResultStore.GetAsync(HashHelper.XorAndCompute(txId, disambiguationHash).ToStorageKey()); - } - - public async Task> GetTransactionResultsAsync(IList txIds, - Hash disambiguationHash) - { - return await _transactionResultStore.GetAllAsync(txIds.Select(t => HashHelper.XorAndCompute(t, disambiguationHash).ToStorageKey()) - .ToList()); - } - - public async Task HasTransactionResultAsync(Hash transactionId, Hash disambiguationHash) - { - return await _transactionResultStore.IsExistsAsync(HashHelper.XorAndCompute(transactionId, disambiguationHash).ToStorageKey()); - } + return await _transactionResultStore.IsExistsAsync(HashHelper.XorAndCompute(transactionId, disambiguationHash) + .ToStorageKey()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Domain/TransactionManager.cs b/src/AElf.Kernel.Core/Blockchain/Domain/TransactionManager.cs index be6174d331..3aa4a0d774 100644 --- a/src/AElf.Kernel.Core/Blockchain/Domain/TransactionManager.cs +++ b/src/AElf.Kernel.Core/Blockchain/Domain/TransactionManager.cs @@ -1,66 +1,61 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Linq; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Blockchain.Domain +namespace AElf.Kernel.Blockchain.Domain; + +public class TransactionManager : ITransactionManager { - public class TransactionManager : ITransactionManager + private readonly IBlockchainStore _transactionStore; + + public TransactionManager(IBlockchainStore transactionStore) { - private readonly IBlockchainStore _transactionStore; - public ILogger Logger { get; set; } + _transactionStore = transactionStore; + Logger = NullLogger.Instance; + } - public TransactionManager(IBlockchainStore transactionStore) - { - _transactionStore = transactionStore; - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task AddTransactionAsync(Transaction tx) - { - var transactionId = tx.GetHash(); - await _transactionStore.SetAsync(GetStringKey(transactionId), tx); - return transactionId; - } - - public async Task AddTransactionsAsync(IList txs) - { - await _transactionStore.SetAllAsync(txs.ToDictionary(t => GetStringKey(t.GetHash()), t => t)); - } + public async Task AddTransactionAsync(Transaction tx) + { + var transactionId = tx.GetHash(); + await _transactionStore.SetAsync(GetStringKey(transactionId), tx); + return transactionId; + } - public async Task GetTransactionAsync(Hash txId) - { - return await _transactionStore.GetAsync(GetStringKey(txId)); - } - - public async Task> GetTransactionsAsync(IList txIds) - { - return await _transactionStore.GetAllAsync(txIds.Select(GetStringKey).ToList()); - } + public async Task AddTransactionsAsync(IList txs) + { + await _transactionStore.SetAllAsync(txs.ToDictionary(t => GetStringKey(t.GetHash()), t => t)); + } - public async Task RemoveTransactionAsync(Hash txId) - { - await _transactionStore.RemoveAsync(GetStringKey(txId)); - } - - public async Task RemoveTransactionsAsync(IList txIds) - { - await _transactionStore.RemoveAllAsync(txIds.Select(GetStringKey).ToList()); - } + public async Task GetTransactionAsync(Hash txId) + { + return await _transactionStore.GetAsync(GetStringKey(txId)); + } + public async Task> GetTransactionsAsync(IList txIds) + { + return await _transactionStore.GetAllAsync(txIds.Select(GetStringKey).ToList()); + } - public async Task HasTransactionAsync(Hash txId) - { - return await _transactionStore.IsExistsAsync(GetStringKey(txId)); - } + public async Task RemoveTransactionAsync(Hash txId) + { + await _transactionStore.RemoveAsync(GetStringKey(txId)); + } + + public async Task RemoveTransactionsAsync(IList txIds) + { + await _transactionStore.RemoveAllAsync(txIds.Select(GetStringKey).ToList()); + } - private string GetStringKey(Hash txId) - { - return txId.ToStorageKey(); - } + + public async Task HasTransactionAsync(Hash txId) + { + return await _transactionStore.IsExistsAsync(GetStringKey(txId)); + } + + private string GetStringKey(Hash txId) + { + return txId.ToStorageKey(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Events/BestChainFoundEventData.cs b/src/AElf.Kernel.Core/Blockchain/Events/BestChainFoundEventData.cs index d9f582bb5e..31df5841ab 100644 --- a/src/AElf.Kernel.Core/Blockchain/Events/BestChainFoundEventData.cs +++ b/src/AElf.Kernel.Core/Blockchain/Events/BestChainFoundEventData.cs @@ -1,10 +1,7 @@ -using AElf.Types; +namespace AElf.Kernel.Blockchain.Events; -namespace AElf.Kernel.Blockchain.Events +public class BestChainFoundEventData { - public class BestChainFoundEventData - { - public Hash BlockHash { get; set; } - public long BlockHeight { get; set; } - } + public Hash BlockHash { get; set; } + public long BlockHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Events/BlockAcceptedEvent.cs b/src/AElf.Kernel.Core/Blockchain/Events/BlockAcceptedEvent.cs index 3ad7e59bbc..ddff545f08 100644 --- a/src/AElf.Kernel.Core/Blockchain/Events/BlockAcceptedEvent.cs +++ b/src/AElf.Kernel.Core/Blockchain/Events/BlockAcceptedEvent.cs @@ -1,9 +1,8 @@ -namespace AElf.Kernel.Blockchain.Events +namespace AElf.Kernel.Blockchain.Events; + +public class BlockAcceptedEvent { - public class BlockAcceptedEvent - { - public BlockExecutedSet BlockExecutedSet { get; set; } + public BlockExecutedSet BlockExecutedSet { get; set; } - public Block Block => BlockExecutedSet.Block; - } + public Block Block => BlockExecutedSet.Block; } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Events/NewIrreversibleBlockFoundEvent.cs b/src/AElf.Kernel.Core/Blockchain/Events/NewIrreversibleBlockFoundEvent.cs index 8eba2146e3..3603395080 100644 --- a/src/AElf.Kernel.Core/Blockchain/Events/NewIrreversibleBlockFoundEvent.cs +++ b/src/AElf.Kernel.Core/Blockchain/Events/NewIrreversibleBlockFoundEvent.cs @@ -1,12 +1,9 @@ -using AElf.Types; +namespace AElf.Kernel.Blockchain.Events; -namespace AElf.Kernel.Blockchain.Events +public class NewIrreversibleBlockFoundEvent { - public class NewIrreversibleBlockFoundEvent - { - public Hash PreviousIrreversibleBlockHash { get; set; } - public long PreviousIrreversibleBlockHeight { get; set; } - public Hash BlockHash { get; set; } - public long BlockHeight { get; set; } - } + public Hash PreviousIrreversibleBlockHash { get; set; } + public long PreviousIrreversibleBlockHeight { get; set; } + public Hash BlockHash { get; set; } + public long BlockHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Infrastructure/ChainBlockLinkCacheProvider.cs b/src/AElf.Kernel.Core/Blockchain/Infrastructure/ChainBlockLinkCacheProvider.cs index f149b4b495..3b16f64b88 100644 --- a/src/AElf.Kernel.Core/Blockchain/Infrastructure/ChainBlockLinkCacheProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Infrastructure/ChainBlockLinkCacheProvider.cs @@ -1,44 +1,39 @@ using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; -using AElf.Types; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Infrastructure +namespace AElf.Kernel.Blockchain.Infrastructure; + +public interface IChainBlockLinkCacheProvider { - public interface IChainBlockLinkCacheProvider + ChainBlockLink GetChainBlockLink(Hash blockHash); + List GetChainBlockLinks(); + void SetChainBlockLink(ChainBlockLink chainBlockLink); + + void RemoveChainBlockLink(Hash blockHash); +} + +public class ChainBlockLinkCacheProvider : IChainBlockLinkCacheProvider, ISingletonDependency +{ + private readonly ConcurrentDictionary _cachedChainBlockLinks = new(); + + public ChainBlockLink GetChainBlockLink(Hash blockHash) { - ChainBlockLink GetChainBlockLink(Hash blockHash); - List GetChainBlockLinks(); - void SetChainBlockLink(ChainBlockLink chainBlockLink); + _cachedChainBlockLinks.TryGetValue(blockHash, out var chainBlockLink); + return chainBlockLink; + } - void RemoveChainBlockLink(Hash blockHash); + public List GetChainBlockLinks() + { + return _cachedChainBlockLinks.Values.ToList(); + } + + public void SetChainBlockLink(ChainBlockLink chainBlockLink) + { + _cachedChainBlockLinks[chainBlockLink.BlockHash] = chainBlockLink; } - public class ChainBlockLinkCacheProvider : IChainBlockLinkCacheProvider, ISingletonDependency + public void RemoveChainBlockLink(Hash blockHash) { - private readonly ConcurrentDictionary _cachedChainBlockLinks = - new ConcurrentDictionary(); - - public ChainBlockLink GetChainBlockLink(Hash blockHash) - { - _cachedChainBlockLinks.TryGetValue(blockHash, out var chainBlockLink); - return chainBlockLink; - } - - public List GetChainBlockLinks() - { - return _cachedChainBlockLinks.Values.ToList(); - } - - public void SetChainBlockLink(ChainBlockLink chainBlockLink) - { - _cachedChainBlockLinks[chainBlockLink.BlockHash] = chainBlockLink; - } - - public void RemoveChainBlockLink(Hash blockHash) - { - _cachedChainBlockLinks.TryRemove(blockHash, out _); - } + _cachedChainBlockLinks.TryRemove(blockHash, out _); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Infrastructure/IBlockchainStore.cs b/src/AElf.Kernel.Core/Blockchain/Infrastructure/IBlockchainStore.cs index 31cf25b8e7..9935b3956a 100644 --- a/src/AElf.Kernel.Core/Blockchain/Infrastructure/IBlockchainStore.cs +++ b/src/AElf.Kernel.Core/Blockchain/Infrastructure/IBlockchainStore.cs @@ -1,19 +1,17 @@ using AElf.Kernel.Infrastructure; -using Google.Protobuf; -namespace AElf.Kernel.Blockchain.Infrastructure +namespace AElf.Kernel.Blockchain.Infrastructure; + +public interface IBlockchainStore : IKeyValueStore + where T : class, IMessage, new() { - public interface IBlockchainStore : IKeyValueStore - where T : class, IMessage, new() - { - } +} - public class BlockchainStore : KeyValueStoreBase, IBlockchainStore - where T : class, IMessage, new() +public class BlockchainStore : KeyValueStoreBase, IBlockchainStore + where T : class, IMessage, new() +{ + public BlockchainStore(BlockchainKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) + : base(keyValueDbContext, prefixProvider) { - public BlockchainStore(BlockchainKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) - : base(keyValueDbContext, prefixProvider) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Infrastructure/IStaticChainInformationProvider.cs b/src/AElf.Kernel.Core/Blockchain/Infrastructure/IStaticChainInformationProvider.cs index 844d2c3088..dc85cbe683 100644 --- a/src/AElf.Kernel.Core/Blockchain/Infrastructure/IStaticChainInformationProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Infrastructure/IStaticChainInformationProvider.cs @@ -1,36 +1,33 @@ -using AElf.Types; using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Infrastructure +namespace AElf.Kernel.Blockchain.Infrastructure; + +public interface IStaticChainInformationProvider { - public interface IStaticChainInformationProvider - { - int ChainId { get; } - Address ZeroSmartContractAddress { get; } - Address GetZeroSmartContractAddress(int chainId); - } + int ChainId { get; } + Address ZeroSmartContractAddress { get; } + Address GetZeroSmartContractAddress(int chainId); +} - public class StaticChainInformationProvider : IStaticChainInformationProvider, ISingletonDependency +public class StaticChainInformationProvider : IStaticChainInformationProvider, ISingletonDependency +{ + public StaticChainInformationProvider(IOptionsSnapshot chainOptions) { - public int ChainId { get; } - public Address ZeroSmartContractAddress { get; } + ChainId = chainOptions.Value.ChainId; + ZeroSmartContractAddress = BuildZeroContractAddress(ChainId); + } - public Address GetZeroSmartContractAddress(int chainId) - { - return BuildZeroContractAddress(chainId); - } + public int ChainId { get; } + public Address ZeroSmartContractAddress { get; } - public StaticChainInformationProvider(IOptionsSnapshot chainOptions) - { - ChainId = chainOptions.Value.ChainId; - ZeroSmartContractAddress = BuildZeroContractAddress(ChainId); - } + public Address GetZeroSmartContractAddress(int chainId) + { + return BuildZeroContractAddress(chainId); + } - private static Address BuildZeroContractAddress(int chainId) - { - var hash = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(chainId), HashHelper.ComputeFrom(0L)); - return Address.FromBytes(hash.ToByteArray()); - } + private static Address BuildZeroContractAddress(int chainId) + { + var hash = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(chainId), HashHelper.ComputeFrom(0L)); + return Address.FromBytes(hash.ToByteArray()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Infrastructure/ITransactionBlockIndexProvider.cs b/src/AElf.Kernel.Core/Blockchain/Infrastructure/ITransactionBlockIndexProvider.cs index a9fd1fe8ba..55c5016aaf 100644 --- a/src/AElf.Kernel.Core/Blockchain/Infrastructure/ITransactionBlockIndexProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Infrastructure/ITransactionBlockIndexProvider.cs @@ -1,11 +1,8 @@ -using AElf.Types; +namespace AElf.Kernel.Blockchain.Infrastructure; -namespace AElf.Kernel.Blockchain.Infrastructure +public interface ITransactionBlockIndexProvider { - public interface ITransactionBlockIndexProvider - { - void AddTransactionBlockIndex(Hash transactionId, TransactionBlockIndex transactionBlockIndex); - bool TryGetTransactionBlockIndex(Hash transactionId, out TransactionBlockIndex transactionBlockIndex); - void CleanByHeight(long blockHeight); - } + void AddTransactionBlockIndex(Hash transactionId, TransactionBlockIndex transactionBlockIndex); + bool TryGetTransactionBlockIndex(Hash transactionId, out TransactionBlockIndex transactionBlockIndex); + void CleanByHeight(long blockHeight); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Blockchain/Infrastructure/TransactionBlockIndexProvider.cs b/src/AElf.Kernel.Core/Blockchain/Infrastructure/TransactionBlockIndexProvider.cs index 3c5c24e063..041e09e209 100644 --- a/src/AElf.Kernel.Core/Blockchain/Infrastructure/TransactionBlockIndexProvider.cs +++ b/src/AElf.Kernel.Core/Blockchain/Infrastructure/TransactionBlockIndexProvider.cs @@ -1,46 +1,40 @@ using System.Collections.Concurrent; using System.Linq; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Blockchain.Infrastructure +namespace AElf.Kernel.Blockchain.Infrastructure; + +public class TransactionBlockIndexProvider : ITransactionBlockIndexProvider, + ISingletonDependency { - public class TransactionBlockIndexProvider : ITransactionBlockIndexProvider, - ISingletonDependency + private readonly ConcurrentDictionary _transactionBlockIndices; + + public TransactionBlockIndexProvider() { - private readonly ConcurrentDictionary _transactionBlockIndices; - - public ILogger Logger { get; set; } - - public TransactionBlockIndexProvider() - { - _transactionBlockIndices = new ConcurrentDictionary(); - Logger = NullLogger.Instance; - } - - public void AddTransactionBlockIndex(Hash transactionId, TransactionBlockIndex transactionBlockIndex) - { - if (transactionBlockIndex == null) - return; - _transactionBlockIndices[transactionId] = transactionBlockIndex; - } - - public bool TryGetTransactionBlockIndex(Hash transactionId, out TransactionBlockIndex transactionBlockIndex) - { - return _transactionBlockIndices.TryGetValue(transactionId, out transactionBlockIndex); - } - - public void CleanByHeight(long blockHeight) - { - foreach (var txId in _transactionBlockIndices.Where(m => m.Value.BlockHeight <= blockHeight) - .Select(mapping => mapping.Key).ToList()) - { - _transactionBlockIndices.TryRemove(txId, out _); - } - - Logger.LogDebug($"Transaction block index count {_transactionBlockIndices.Count} in provider."); - } + _transactionBlockIndices = new ConcurrentDictionary(); + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public void AddTransactionBlockIndex(Hash transactionId, TransactionBlockIndex transactionBlockIndex) + { + if (transactionBlockIndex == null) + return; + _transactionBlockIndices[transactionId] = transactionBlockIndex; + } + + public bool TryGetTransactionBlockIndex(Hash transactionId, out TransactionBlockIndex transactionBlockIndex) + { + return _transactionBlockIndices.TryGetValue(transactionId, out transactionBlockIndex); + } + + public void CleanByHeight(long blockHeight) + { + foreach (var txId in _transactionBlockIndices.Where(m => m.Value.BlockHeight <= blockHeight) + .Select(mapping => mapping.Key).ToList()) + _transactionBlockIndices.TryRemove(txId, out _); + + Logger.LogDebug("Transaction block index count {TransactionBlockIndicesCount} in provider", + _transactionBlockIndices.Count); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/ChainOptions.cs b/src/AElf.Kernel.Core/ChainOptions.cs index 2cd2c20d2a..d85d60f22e 100644 --- a/src/AElf.Kernel.Core/ChainOptions.cs +++ b/src/AElf.Kernel.Core/ChainOptions.cs @@ -1,22 +1,21 @@ -namespace AElf.Kernel +namespace AElf.Kernel; + +public class ChainOptions +{ + public int ChainId { get; set; } + public ChainType ChainType { get; set; } + public NetType NetType { get; set; } +} + +public enum ChainType { - public class ChainOptions - { - public int ChainId { get; set; } - public ChainType ChainType { get; set; } - public NetType NetType { get; set; } - } - - public enum ChainType - { - MainChain, - SideChain - } + MainChain, + SideChain +} - public enum NetType - { - MainNet, - TestNet, - CustomNet - } +public enum NetType +{ + MainNet, + TestNet, + CustomNet } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/CoreKernelAElfModule.cs b/src/AElf.Kernel.Core/CoreKernelAElfModule.cs index 2a02771aaf..86df74b631 100644 --- a/src/AElf.Kernel.Core/CoreKernelAElfModule.cs +++ b/src/AElf.Kernel.Core/CoreKernelAElfModule.cs @@ -6,70 +6,70 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Modularity; -using AElf.Types; -using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(DatabaseAElfModule), + typeof(CoreAElfModule) +)] +public class CoreKernelAElfModule : AElfModule { - [DependsOn(typeof(DatabaseAElfModule), typeof(CoreAElfModule))] - public class CoreKernelAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; + + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddTransient(typeof(IStoreKeyPrefixProvider<>), typeof(StoreKeyPrefixProvider<>)); + services.AddTransient(typeof(IStoreKeyPrefixProvider<>), typeof(StoreKeyPrefixProvider<>)); - services.AddStoreKeyPrefixProvide("bb"); - services.AddStoreKeyPrefixProvide("bh"); - services.AddStoreKeyPrefixProvide("bs"); - services.AddStoreKeyPrefixProvide("ch"); - services.AddStoreKeyPrefixProvide("cl"); - services.AddStoreKeyPrefixProvide("ci"); - services.AddStoreKeyPrefixProvide("cs"); - services.AddStoreKeyPrefixProvide("tx"); - services.AddStoreKeyPrefixProvide("ti"); - services.AddStoreKeyPrefixProvide("tr"); - services.AddStoreKeyPrefixProvide("vs"); - + services.AddStoreKeyPrefixProvide("bb"); + services.AddStoreKeyPrefixProvide("bh"); + services.AddStoreKeyPrefixProvide("bs"); + services.AddStoreKeyPrefixProvide("ch"); + services.AddStoreKeyPrefixProvide("cl"); + services.AddStoreKeyPrefixProvide("ci"); + services.AddStoreKeyPrefixProvide("cs"); + services.AddStoreKeyPrefixProvide("tx"); + services.AddStoreKeyPrefixProvide("ti"); + services.AddStoreKeyPrefixProvide("tr"); + services.AddStoreKeyPrefixProvide("vs"); - services.AddTransient(typeof(IStateStore<>), typeof(StateStore<>)); - services.AddSingleton(typeof(INotModifiedCachedStateStore<>), typeof(NotModifiedCachedStateStore<>)); - services.AddTransient(typeof(IBlockchainStore<>), typeof(BlockchainStore<>)); - services.AddSingleton(typeof(ICachedBlockchainExecutedDataService<>), - typeof(CachedBlockchainExecutedDataService<>)); - services.AddSingleton(typeof(IBlockchainExecutedDataCacheProvider<>), - typeof(BlockchainExecutedDataCacheProvider<>)); - - services.AddKeyValueDbContext(p => p.UseRedisDatabase()); - services.AddKeyValueDbContext(p => p.UseRedisDatabase()); - } - public override void OnPostApplicationInitialization(ApplicationInitializationContext context) - { - var transactionBlockIndexService = - context.ServiceProvider.GetRequiredService(); - AsyncHelper.RunSync(transactionBlockIndexService.LoadTransactionBlockIndexAsync); - } + services.AddTransient(typeof(IStateStore<>), typeof(StateStore<>)); + services.AddSingleton(typeof(INotModifiedCachedStateStore<>), typeof(NotModifiedCachedStateStore<>)); + services.AddTransient(typeof(IBlockchainStore<>), typeof(BlockchainStore<>)); + services.AddSingleton(typeof(ICachedBlockchainExecutedDataService<>), + typeof(CachedBlockchainExecutedDataService<>)); + services.AddSingleton(typeof(IBlockchainExecutedDataCacheProvider<>), + typeof(BlockchainExecutedDataCacheProvider<>)); + + services.AddKeyValueDbContext(p => p.UseRedisDatabase()); + services.AddKeyValueDbContext(p => p.UseRedisDatabase()); } - public static class StoreKeyPrefixProviderServiceCollectionExtensions + public override void OnPostApplicationInitialization(ApplicationInitializationContext context) + { + var transactionBlockIndexService = + context.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(transactionBlockIndexService.LoadTransactionBlockIndexAsync); + } +} + +public static class StoreKeyPrefixProviderServiceCollectionExtensions +{ + public static IServiceCollection AddStoreKeyPrefixProvide( + this IServiceCollection serviceCollection, string prefix) + where T : IMessage, new() { - public static IServiceCollection AddStoreKeyPrefixProvide( - this IServiceCollection serviceCollection, string prefix) - where T : IMessage, new() - { - serviceCollection.AddTransient>(c => - new FastStoreKeyPrefixProvider(prefix)); + serviceCollection.AddTransient>(c => + new FastStoreKeyPrefixProvider(prefix)); - return serviceCollection; - } + return serviceCollection; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Events/TransactionValidationStatusChangedEvent.cs b/src/AElf.Kernel.Core/Events/TransactionValidationStatusChangedEvent.cs index 6f8e188fad..e80915e0ef 100644 --- a/src/AElf.Kernel.Core/Events/TransactionValidationStatusChangedEvent.cs +++ b/src/AElf.Kernel.Core/Events/TransactionValidationStatusChangedEvent.cs @@ -1,11 +1,8 @@ -using AElf.Types; +namespace AElf.Kernel; -namespace AElf.Kernel +public class TransactionValidationStatusChangedEvent { - public class TransactionValidationStatusChangedEvent - { - public Hash TransactionId { get; set; } - public TransactionResultStatus TransactionResultStatus { get; set; } - public string Error { get; set; } - } + public Hash TransactionId { get; set; } + public TransactionResultStatus TransactionResultStatus { get; set; } + public string Error { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/BlockBodyExtensions.cs b/src/AElf.Kernel.Core/Extensions/BlockBodyExtensions.cs index ee097cfa0a..c4d71bc2fa 100644 --- a/src/AElf.Kernel.Core/Extensions/BlockBodyExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/BlockBodyExtensions.cs @@ -1,33 +1,29 @@ -using System.Collections.Generic; -using AElf.Types; +namespace AElf.Kernel; -namespace AElf.Kernel +public static class BlockBodyExtensions { - public static class BlockBodyExtensions + /// + /// Calculate merkle tree root of transaction. + /// + /// + public static Hash CalculateMerkleTreeRoot(this BlockBody blockBody) { - /// - /// Calculate merkle tree root of transaction. - /// - /// - public static Hash CalculateMerkleTreeRoot(this BlockBody blockBody) - { - if (blockBody.TransactionsCount == 0) - return Hash.Empty; - var merkleTreeRoot = BinaryMerkleTree.FromLeafNodes(blockBody.TransactionIds).Root; + if (blockBody.TransactionsCount == 0) + return Hash.Empty; + var merkleTreeRoot = BinaryMerkleTree.FromLeafNodes(blockBody.TransactionIds).Root; - return merkleTreeRoot; - } + return merkleTreeRoot; + } - public static bool AddTransaction(this BlockBody blockBody, Transaction tx) - { - blockBody.TransactionIds.Add(tx.GetHash()); - return true; - } + public static bool AddTransaction(this BlockBody blockBody, Transaction tx) + { + blockBody.TransactionIds.Add(tx.GetHash()); + return true; + } - public static bool AddTransactions(this BlockBody blockBody, IEnumerable txs) - { - blockBody.TransactionIds.Add(txs); - return true; - } + public static bool AddTransactions(this BlockBody blockBody, IEnumerable txs) + { + blockBody.TransactionIds.Add(txs); + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/BlockExtensions.cs b/src/AElf.Kernel.Core/Extensions/BlockExtensions.cs index 5aa39e2f51..eff35d1fc6 100644 --- a/src/AElf.Kernel.Core/Extensions/BlockExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/BlockExtensions.cs @@ -1,35 +1,33 @@ using AElf.Cryptography; -using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class BlockExtensions { - public static class BlockExtensions + /// + /// Add transaction Hash to the block + /// + /// true, if the hash was added, false otherwise. + /// + /// the transactions hash + public static void AddTransaction(this IBlock block, Transaction tx) { - /// - /// Add transaction Hash to the block - /// - /// true, if the hash was added, false otherwise. - /// - /// the transactions hash - public static void AddTransaction(this IBlock block, Transaction tx) - { - block.Body.AddTransaction(tx); - } + block.Body.AddTransaction(tx); + } - public static bool VerifySignature(this IBlock block) - { - if (!block.Header.VerifyFields() || !block.Body.VerifyFields()) - return false; + public static bool VerifySignature(this IBlock block) + { + if (!block.Header.VerifyFields() || !block.Body.VerifyFields()) + return false; - if (block.Header.Signature.IsEmpty) - return false; + if (block.Header.Signature.IsEmpty) + return false; - var recovered = CryptoHelper.RecoverPublicKey(block.Header.Signature.ToByteArray(), - block.GetHash().ToByteArray(), out var publicKey); - if (!recovered) - return false; + var recovered = CryptoHelper.RecoverPublicKey(block.Header.Signature.ToByteArray(), + block.GetHash().ToByteArray(), out var publicKey); + if (!recovered) + return false; - return block.Header.SignerPubkey.ToByteArray().BytesEqual(publicKey); - } + return block.Header.SignerPubkey.ToByteArray().BytesEqual(publicKey); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/BlockHeaderExtensions.cs b/src/AElf.Kernel.Core/Extensions/BlockHeaderExtensions.cs index 957f2f3e44..0435acb6a1 100644 --- a/src/AElf.Kernel.Core/Extensions/BlockHeaderExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/BlockHeaderExtensions.cs @@ -1,22 +1,20 @@ using System; -using AElf.Types; -using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class BlockHeaderExtensions { - public static class BlockHeaderExtensions + public static bool IsMined(this BlockHeader blockHeader) { - public static bool IsMined(this BlockHeader blockHeader) - { - return blockHeader.MerkleTreeRootOfTransactions != null; - } + return blockHeader.MerkleTreeRootOfTransactions != null; + } - public static Hash GetDisambiguatingHash(this BlockHeader blockHeader) - { - if(!blockHeader.IsMined()) - throw new InvalidOperationException("GetDisambiguatingHash: should only get mined block's DisambiguatingHash"); + public static Hash GetDisambiguatingHash(this BlockHeader blockHeader) + { + if (!blockHeader.IsMined()) + throw new InvalidOperationException( + "GetDisambiguatingHash: should only get mined block's DisambiguatingHash"); - return blockHeader.GetHash(); - } + return blockHeader.GetHash(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/BlockStateSetExtension.cs b/src/AElf.Kernel.Core/Extensions/BlockStateSetExtension.cs index ae106eb415..5eab3dc5f0 100644 --- a/src/AElf.Kernel.Core/Extensions/BlockStateSetExtension.cs +++ b/src/AElf.Kernel.Core/Extensions/BlockStateSetExtension.cs @@ -1,37 +1,31 @@ -using Google.Protobuf; +namespace AElf.Kernel; -namespace AElf.Kernel +public static class BlockStateSetExtension { - public static class BlockStateSetExtension + public static bool TryGetState(this BlockStateSet blockStateSet, string key, out ByteString value) { - public static bool TryGetState(this BlockStateSet blockStateSet, string key, out ByteString value) - { - value = null; - if (blockStateSet.Deletes.Contains(key)) - { - return true; - } + value = null; + if (blockStateSet.Deletes.Contains(key)) return true; - if (blockStateSet.Changes.ContainsKey(key)) - { - value = blockStateSet.Changes[key]; - return true; - } - - return false; - } - - public static bool TryGetExecutedCache(this BlockStateSet blockStateSet, string key, out ByteString value) + if (blockStateSet.Changes.ContainsKey(key)) { - value = null; - - if (blockStateSet.BlockExecutedData.ContainsKey(key)) - { - value = blockStateSet.BlockExecutedData[key]; - return true; - } + value = blockStateSet.Changes[key]; + return true; + } + + return false; + } - return false; + public static bool TryGetExecutedCache(this BlockStateSet blockStateSet, string key, out ByteString value) + { + value = null; + + if (blockStateSet.BlockExecutedData.ContainsKey(key)) + { + value = blockStateSet.BlockExecutedData[key]; + return true; } + + return false; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/TransactionExtensions.cs b/src/AElf.Kernel.Core/Extensions/TransactionExtensions.cs index f6803a0a91..4c3e8e3242 100644 --- a/src/AElf.Kernel.Core/Extensions/TransactionExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/TransactionExtensions.cs @@ -1,35 +1,33 @@ using AElf.Cryptography; -using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class TransactionExtensions { - public static class TransactionExtensions + public static long GetExpiryBlockNumber(this Transaction transaction) { - public static long GetExpiryBlockNumber(this Transaction transaction) - { - return transaction.RefBlockNumber + KernelConstants.ReferenceBlockValidPeriod; - } + return transaction.RefBlockNumber + KernelConstants.ReferenceBlockValidPeriod; + } - public static int Size(this Transaction transaction) - { - return transaction.CalculateSize(); - } + public static int Size(this Transaction transaction) + { + return transaction.CalculateSize(); + } - public static bool VerifySignature(this Transaction transaction) - { - if (!transaction.VerifyFields()) - return false; + public static bool VerifySignature(this Transaction transaction) + { + if (!transaction.VerifyFields()) + return false; - var recovered = CryptoHelper.RecoverPublicKey(transaction.Signature.ToByteArray(), - transaction.GetHash().ToByteArray(), out var publicKey); + var recovered = CryptoHelper.RecoverPublicKey(transaction.Signature.ToByteArray(), + transaction.GetHash().ToByteArray(), out var publicKey); - return recovered && Address.FromPublicKey(publicKey) == transaction.From; - } + return recovered && Address.FromPublicKey(publicKey) == transaction.From; + } - public static bool VerifyExpiration(this Transaction transaction, long chainBranchBlockHeight) - { - return transaction.RefBlockNumber <= chainBranchBlockHeight && - transaction.GetExpiryBlockNumber() > chainBranchBlockHeight; - } + public static bool VerifyExpiration(this Transaction transaction, long chainBranchBlockHeight) + { + return transaction.RefBlockNumber <= chainBranchBlockHeight && + transaction.GetExpiryBlockNumber() > chainBranchBlockHeight; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/TransactionResultExtensions.cs b/src/AElf.Kernel.Core/Extensions/TransactionResultExtensions.cs index 488817c51c..76ddc9a451 100644 --- a/src/AElf.Kernel.Core/Extensions/TransactionResultExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/TransactionResultExtensions.cs @@ -1,16 +1,13 @@ using System.Linq; -using AElf.Types; -using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class TransactionResultExtensions { - public static class TransactionResultExtensions + public static void UpdateBloom(this TransactionResult transactionResult) { - public static void UpdateBloom(this TransactionResult transactionResult) - { - var bloom = new Bloom(); - bloom.Combine(transactionResult.Logs.Select(l => l.GetBloom())); - transactionResult.Bloom = ByteString.CopyFrom(bloom.Data); - } + var bloom = new Bloom(); + bloom.Combine(transactionResult.Logs.Select(l => l.GetBloom())); + transactionResult.Bloom = ByteString.CopyFrom(bloom.Data); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Extensions/TransactionTraceExtensions.cs b/src/AElf.Kernel.Core/Extensions/TransactionTraceExtensions.cs index 0534fde9e2..a883547e4c 100644 --- a/src/AElf.Kernel.Core/Extensions/TransactionTraceExtensions.cs +++ b/src/AElf.Kernel.Core/Extensions/TransactionTraceExtensions.cs @@ -1,90 +1,61 @@ -using System.Collections.Generic; using System.Linq; -using AElf.Types; using Google.Protobuf.Collections; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class TransactionTraceExtensions { - public static class TransactionTraceExtensions + public static bool IsSuccessful(this TransactionTrace txTrace) { - public static bool IsSuccessful(this TransactionTrace txTrace) - { - if (txTrace.ExecutionStatus != ExecutionStatus.Executed) - { - return false; - } + if (txTrace.ExecutionStatus != ExecutionStatus.Executed) return false; - if (txTrace.PreTraces.Any(trace => !trace.IsSuccessful())) - { - return false; - } + if (txTrace.PreTraces.Any(trace => !trace.IsSuccessful())) return false; - if (txTrace.InlineTraces.Any(trace => !trace.IsSuccessful())) - { - return false; - } + if (txTrace.InlineTraces.Any(trace => !trace.IsSuccessful())) return false; - if (txTrace.PostTraces.Any(trace => !trace.IsSuccessful())) - { - return false; - } + if (txTrace.PostTraces.Any(trace => !trace.IsSuccessful())) return false; - return true; - } - - public static IEnumerable GetPluginLogs(this TransactionTrace txTrace) - { - var logEvents = new RepeatedField(); - foreach (var preTrace in txTrace.PreTraces) - { - if (preTrace.IsSuccessful()) - logEvents.AddRange(preTrace.FlattenedLogs); - } + return true; + } - foreach (var postTrace in txTrace.PostTraces) - { - if (postTrace.IsSuccessful()) - logEvents.AddRange(postTrace.FlattenedLogs); - } + public static IEnumerable GetPluginLogs(this TransactionTrace txTrace) + { + var logEvents = new RepeatedField(); + foreach (var preTrace in txTrace.PreTraces) + if (preTrace.IsSuccessful()) + logEvents.AddRange(preTrace.FlattenedLogs); - return logEvents; - } + foreach (var postTrace in txTrace.PostTraces) + if (postTrace.IsSuccessful()) + logEvents.AddRange(postTrace.FlattenedLogs); + + return logEvents; + } - public static void SurfaceUpError(this TransactionTrace txTrace) + public static void SurfaceUpError(this TransactionTrace txTrace) + { + foreach (var inline in txTrace.InlineTraces) { - foreach (var inline in txTrace.InlineTraces) + inline.SurfaceUpError(); + if (inline.ExecutionStatus < txTrace.ExecutionStatus) { - inline.SurfaceUpError(); - if (inline.ExecutionStatus < txTrace.ExecutionStatus) - { - txTrace.ExecutionStatus = inline.ExecutionStatus; - txTrace.Error = $"{inline.Error}"; - } + txTrace.ExecutionStatus = inline.ExecutionStatus; + txTrace.Error = $"{inline.Error}"; } + } - if (txTrace.ExecutionStatus == ExecutionStatus.Postfailed) + if (txTrace.ExecutionStatus == ExecutionStatus.Postfailed) + foreach (var trace in txTrace.PostTraces) { - foreach (var trace in txTrace.PostTraces) - { - trace.SurfaceUpError(); - if (!string.IsNullOrEmpty(trace.Error)) - { - txTrace.Error += $"Post-Error: {trace.Error}"; - } - } + trace.SurfaceUpError(); + if (!string.IsNullOrEmpty(trace.Error)) txTrace.Error += $"Post-Error: {trace.Error}"; } - if (txTrace.ExecutionStatus == ExecutionStatus.Prefailed) + if (txTrace.ExecutionStatus == ExecutionStatus.Prefailed) + foreach (var trace in txTrace.PreTraces) { - foreach (var trace in txTrace.PreTraces) - { - trace.SurfaceUpError(); - if (!string.IsNullOrEmpty(trace.Error)) - { - txTrace.Error += $"Pre-Error: {trace.Error}"; - } - } + trace.SurfaceUpError(); + if (!string.IsNullOrEmpty(trace.Error)) txTrace.Error += $"Pre-Error: {trace.Error}"; } - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/GlobalUsings.cs b/src/AElf.Kernel.Core/GlobalUsings.cs new file mode 100644 index 0000000000..e23d867d7d --- /dev/null +++ b/src/AElf.Kernel.Core/GlobalUsings.cs @@ -0,0 +1,7 @@ +global using Google.Protobuf; +global using AElf.Types; +global using System.Threading.Tasks; +global using Volo.Abp.DependencyInjection; +global using System.Collections.Generic; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging.Abstractions; \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Infrastructure/BlockChainKeyValueDbContext.cs b/src/AElf.Kernel.Core/Infrastructure/BlockChainKeyValueDbContext.cs index b26c8bd48d..a0feec0999 100644 --- a/src/AElf.Kernel.Core/Infrastructure/BlockChainKeyValueDbContext.cs +++ b/src/AElf.Kernel.Core/Infrastructure/BlockChainKeyValueDbContext.cs @@ -1,18 +1,14 @@ using AElf.Database; using Volo.Abp.Data; -// ReSharper disable All -namespace AElf.Kernel.Infrastructure +namespace AElf.Kernel.Infrastructure; + +[ConnectionStringName("BlockchainDb")] +public class BlockchainKeyValueDbContext : KeyValueDbContext { - [ConnectionStringName("BlockchainDb")] - public class BlockchainKeyValueDbContext : KeyValueDbContext - { - - } +} - [ConnectionStringName("StateDb")] - public class StateKeyValueDbContext : KeyValueDbContext - { - - } +[ConnectionStringName("StateDb")] +public class StateKeyValueDbContext : KeyValueDbContext +{ } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Infrastructure/IKeyValueStore.cs b/src/AElf.Kernel.Core/Infrastructure/IKeyValueStore.cs index b833e13666..473de42d34 100644 --- a/src/AElf.Kernel.Core/Infrastructure/IKeyValueStore.cs +++ b/src/AElf.Kernel.Core/Infrastructure/IKeyValueStore.cs @@ -1,18 +1,13 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Google.Protobuf; +namespace AElf.Kernel.Infrastructure; -namespace AElf.Kernel.Infrastructure +public interface IKeyValueStore + where T : IMessage { - public interface IKeyValueStore - where T: IMessage - { - Task SetAsync(string key, T value); - Task SetAllAsync(Dictionary pipelineSet); - Task GetAsync(string key); - Task RemoveAsync(string key); - Task IsExistsAsync(string key); - Task> GetAllAsync(List keys); - Task RemoveAllAsync(List keys); - } + Task SetAsync(string key, T value); + Task SetAllAsync(Dictionary pipelineSet); + Task GetAsync(string key); + Task RemoveAsync(string key); + Task IsExistsAsync(string key); + Task> GetAllAsync(List keys); + Task RemoveAllAsync(List keys); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Infrastructure/KeyValueStoreBase.cs b/src/AElf.Kernel.Core/Infrastructure/KeyValueStoreBase.cs index 98b00c38e7..8dfacb300c 100644 --- a/src/AElf.Kernel.Core/Infrastructure/KeyValueStoreBase.cs +++ b/src/AElf.Kernel.Core/Infrastructure/KeyValueStoreBase.cs @@ -1,116 +1,105 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Database; -using Google.Protobuf; -namespace AElf.Kernel.Infrastructure -{ - public interface IStoreKeyPrefixProvider - where T : IMessage, new() - { - string GetStoreKeyPrefix(); - } +namespace AElf.Kernel.Infrastructure; - public class StoreKeyPrefixProvider : IStoreKeyPrefixProvider - where T : IMessage, new() - { - private static readonly string _typeName = typeof(T).Name; +public interface IStoreKeyPrefixProvider + where T : IMessage, new() +{ + string GetStoreKeyPrefix(); +} - public string GetStoreKeyPrefix() - { - return _typeName; - } - } +public class StoreKeyPrefixProvider : IStoreKeyPrefixProvider + where T : IMessage, new() +{ + private static readonly string TypeName = typeof(T).Name; - public class FastStoreKeyPrefixProvider : IStoreKeyPrefixProvider - where T : IMessage, new() + public string GetStoreKeyPrefix() { - private readonly string _prefix; - - public FastStoreKeyPrefixProvider(string prefix) - { - _prefix = prefix; - } - - public string GetStoreKeyPrefix() - { - return _prefix; - } + return TypeName; } +} +public class FastStoreKeyPrefixProvider : IStoreKeyPrefixProvider + where T : IMessage, new() +{ + private readonly string _prefix; - public abstract class KeyValueStoreBase : IKeyValueStore - where TKeyValueDbContext : KeyValueDbContext - where T : class, IMessage, new() + public FastStoreKeyPrefixProvider(string prefix) { - private readonly TKeyValueDbContext _keyValueDbContext; + _prefix = prefix; + } - private readonly IKeyValueCollection _collection; + public string GetStoreKeyPrefix() + { + return _prefix; + } +} - private readonly MessageParser _messageParser; +public abstract class KeyValueStoreBase : IKeyValueStore + where TKeyValueDbContext : KeyValueDbContext + where T : class, IMessage, new() +{ + private readonly IKeyValueCollection _collection; + private readonly MessageParser _messageParser; - public KeyValueStoreBase(TKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) - { - _keyValueDbContext = keyValueDbContext; - // ReSharper disable once VirtualMemberCallInConstructor - _collection = keyValueDbContext.Collection(prefixProvider.GetStoreKeyPrefix()); + public KeyValueStoreBase(TKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) + { + _collection = keyValueDbContext.Collection(prefixProvider.GetStoreKeyPrefix()); - _messageParser = new MessageParser(() => new T()); - } + _messageParser = new MessageParser(() => new T()); + } - public async Task SetAsync(string key, T value) - { - await _collection.SetAsync(key, Serialize(value)); - } + public async Task SetAsync(string key, T value) + { + await _collection.SetAsync(key, Serialize(value)); + } - private static byte[] Serialize(T value) - { - return value?.ToByteArray(); - } + public async Task SetAllAsync(Dictionary pipelineSet) + { + await _collection.SetAllAsync( + pipelineSet.ToDictionary(k => k.Key, v => Serialize(v.Value))); + } - public async Task SetAllAsync(Dictionary pipelineSet) - { - await _collection.SetAllAsync( - pipelineSet.ToDictionary(k => k.Key, v => Serialize(v.Value))); - } + public virtual async Task GetAsync(string key) + { + var result = await _collection.GetAsync(key); - public virtual async Task GetAsync(string key) - { - var result = await _collection.GetAsync(key); + return result == null ? default : Deserialize(result); + } - return result == null ? default(T) : Deserialize(result); - } + public virtual async Task RemoveAsync(string key) + { + await _collection.RemoveAsync(key); + } - private T Deserialize(byte[] result) - { - return _messageParser.ParseFrom(result); - } + public async Task IsExistsAsync(string key) + { + return await _collection.IsExistsAsync(key); + } - public virtual async Task RemoveAsync(string key) - { - await _collection.RemoveAsync(key); - } + public virtual async Task> GetAllAsync(List keys) + { + var result = await _collection.GetAllAsync(keys); - public async Task IsExistsAsync(string key) - { - return await _collection.IsExistsAsync(key); - } + return result == null || result.Count == 0 + ? default + : result.Select(r => r == null ? default : Deserialize(r)).ToList(); + } - public virtual async Task> GetAllAsync(List keys) - { - var result = await _collection.GetAllAsync(keys); + public virtual async Task RemoveAllAsync(List keys) + { + await _collection.RemoveAllAsync(keys); + } - return result == null || result.Count == 0 - ? default - : result.Select(r => r == null ? default : Deserialize(r)).ToList(); - } + private static byte[] Serialize(T value) + { + return value?.ToByteArray(); + } - public virtual async Task RemoveAllAsync(List keys) - { - await _collection.RemoveAllAsync(keys); - } + private T Deserialize(byte[] result) + { + return _messageParser.ParseFrom(result); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Infrastructure/StorageKeyExtensions.cs b/src/AElf.Kernel.Core/Infrastructure/StorageKeyExtensions.cs index b2e92c61d3..2cde606c03 100644 --- a/src/AElf.Kernel.Core/Infrastructure/StorageKeyExtensions.cs +++ b/src/AElf.Kernel.Core/Infrastructure/StorageKeyExtensions.cs @@ -1,36 +1,34 @@ -using AElf.Types; -using Google.Protobuf; +namespace AElf.Kernel.Infrastructure; -namespace AElf.Kernel.Infrastructure +public static class StorageKeyExtensions { - public static class StorageKeyExtensions + public static string ToStorageKey(this long n) { - public static string ToStorageKey(this long n) - { - return n.ToString(); - } - - public static string ToStorageKey(this ulong n) - { - return n.ToString(); - } - public static string ToStorageKey(this int n) - { - return n.ToString(); - } - public static string ToStorageKey(this Hash hash) - { - return hash?.Value.ToBase64(); - } - - public static string ToStorageKey(this ByteString byteString) - { - return byteString?.ToBase64(); - } - - public static string ToStorageKey(this Address byteString) - { - return byteString?.ToBase58(); - } + return n.ToString(); + } + + public static string ToStorageKey(this ulong n) + { + return n.ToString(); + } + + public static string ToStorageKey(this int n) + { + return n.ToString(); + } + + public static string ToStorageKey(this Hash hash) + { + return hash?.Value.ToBase64(); + } + + public static string ToStorageKey(this ByteString byteString) + { + return byteString?.ToBase64(); + } + + public static string ToStorageKey(this Address byteString) + { + return byteString?.ToBase58(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionExtraDataProvider.cs b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionExtraDataProvider.cs index f5b44d6aed..e616c64139 100644 --- a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionExtraDataProvider.cs +++ b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionExtraDataProvider.cs @@ -1,39 +1,36 @@ using AElf.Kernel.Blockchain.Application; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public interface ISystemTransactionExtraDataProvider { - public interface ISystemTransactionExtraDataProvider - { - bool TryGetSystemTransactionCount(BlockHeader blockHeader,out int count); + bool TryGetSystemTransactionCount(BlockHeader blockHeader, out int count); - void SetSystemTransactionCount(int count, BlockHeader blockHeader); - } - - public class SystemTransactionExtraDataProvider : ISystemTransactionExtraDataProvider, ISingletonDependency - { - private const string BlockHeaderExtraDataKey = "SystemTransactionCount"; - private readonly IBlockExtraDataService _blockExtraDataService; + void SetSystemTransactionCount(int count, BlockHeader blockHeader); +} - public SystemTransactionExtraDataProvider(IBlockExtraDataService blockExtraDataService) - { - _blockExtraDataService = blockExtraDataService; - } +public class SystemTransactionExtraDataProvider : ISystemTransactionExtraDataProvider, ISingletonDependency +{ + private const string BlockHeaderExtraDataKey = "SystemTransactionCount"; + private readonly IBlockExtraDataService _blockExtraDataService; - public bool TryGetSystemTransactionCount(BlockHeader blockHeader,out int count) - { - count = 0; - var byteString = _blockExtraDataService.GetExtraDataFromBlockHeader(BlockHeaderExtraDataKey, blockHeader); - if (byteString == null) return false; - count = Int32Value.Parser.ParseFrom(byteString).Value; - return true; - } + public SystemTransactionExtraDataProvider(IBlockExtraDataService blockExtraDataService) + { + _blockExtraDataService = blockExtraDataService; + } - public void SetSystemTransactionCount(int count, BlockHeader blockHeader) - { - blockHeader.ExtraData.Add(BlockHeaderExtraDataKey, new Int32Value {Value = count}.ToByteString()); - } + public bool TryGetSystemTransactionCount(BlockHeader blockHeader, out int count) + { + count = 0; + var byteString = _blockExtraDataService.GetExtraDataFromBlockHeader(BlockHeaderExtraDataKey, blockHeader); + if (byteString == null) return false; + count = Int32Value.Parser.ParseFrom(byteString).Value; + return true; + } + + public void SetSystemTransactionCount(int count, BlockHeader blockHeader) + { + blockHeader.ExtraData.Add(BlockHeaderExtraDataKey, new Int32Value { Value = count }.ToByteString()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerationService.cs b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerationService.cs index 9a647d84b4..9d984e2b55 100644 --- a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerationService.cs +++ b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerationService.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.Miner.Application; -namespace AElf.Kernel.Miner.Application +public interface ISystemTransactionGenerationService { - public interface ISystemTransactionGenerationService - { - Task> GenerateSystemTransactionsAsync(Address @from, long preBlockHeight, Hash preBlockHash); - } + Task> GenerateSystemTransactionsAsync(Address from, long preBlockHeight, Hash preBlockHash); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerator.cs b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerator.cs index 4b8044a6db..d98a0df643 100644 --- a/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerator.cs +++ b/src/AElf.Kernel.Core/Miner/Application/ISystemTransactionGenerator.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.Miner.Application; -namespace AElf.Kernel.Miner.Application +public interface ISystemTransactionGenerator { - public interface ISystemTransactionGenerator - { - Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, Hash preBlockHash); - } + Task> GenerateTransactionsAsync(Address from, long preBlockHeight, Hash preBlockHash); } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Miner/Application/SystemTransactionGenerationService.cs b/src/AElf.Kernel.Core/Miner/Application/SystemTransactionGenerationService.cs index f06cef0f71..e9f829e294 100644 --- a/src/AElf.Kernel.Core/Miner/Application/SystemTransactionGenerationService.cs +++ b/src/AElf.Kernel.Core/Miner/Application/SystemTransactionGenerationService.cs @@ -1,33 +1,25 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; -using Microsoft.Extensions.Logging; +namespace AElf.Kernel.Miner.Application; -namespace AElf.Kernel.Miner.Application +public class SystemTransactionGenerationService : ISystemTransactionGenerationService { - public class SystemTransactionGenerationService : ISystemTransactionGenerationService - { - private readonly IEnumerable _systemTransactionGenerators; + private readonly IEnumerable _systemTransactionGenerators; - public ILogger Logger { get; set; } + // TODO: A better strategy to control system transaction order. + public SystemTransactionGenerationService(IEnumerable systemTransactionGenerators) + { + _systemTransactionGenerators = systemTransactionGenerators; + } - // TODO: A better strategy to control system transaction order. - public SystemTransactionGenerationService(IEnumerable systemTransactionGenerators) - { - _systemTransactionGenerators = systemTransactionGenerators; - } + public ILogger Logger { get; set; } - public async Task> GenerateSystemTransactionsAsync(Address @from, long preBlockHeight, - Hash preBlockHash) - { - var generatedTransactions = new List(); - foreach (var generator in _systemTransactionGenerators) - { - generatedTransactions.AddRange( - await generator.GenerateTransactionsAsync(@from, preBlockHeight, preBlockHash)); - } + public async Task> GenerateSystemTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + var generatedTransactions = new List(); + foreach (var generator in _systemTransactionGenerators) + generatedTransactions.AddRange( + await generator.GenerateTransactionsAsync(from, preBlockHeight, preBlockHash)); - return generatedTransactions; - } + return generatedTransactions; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Miner/Application/SystemTransactionValidationProvider.cs b/src/AElf.Kernel.Core/Miner/Application/SystemTransactionValidationProvider.cs index ce58f0b97c..2d2deef80d 100644 --- a/src/AElf.Kernel.Core/Miner/Application/SystemTransactionValidationProvider.cs +++ b/src/AElf.Kernel.Core/Miner/Application/SystemTransactionValidationProvider.cs @@ -1,31 +1,29 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class SystemTransactionValidationProvider : IBlockValidationProvider { - public class SystemTransactionValidationProvider : IBlockValidationProvider - { - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; - public SystemTransactionValidationProvider(ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) - { - _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; - } + public SystemTransactionValidationProvider(ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) + { + _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; + } - public Task ValidateBeforeAttachAsync(IBlock block) - { - return Task.FromResult(_systemTransactionExtraDataProvider.TryGetSystemTransactionCount(block.Header, - out var systemTransactionCount) && systemTransactionCount > 0); - } + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(_systemTransactionExtraDataProvider.TryGetSystemTransactionCount(block.Header, + out var systemTransactionCount) && systemTransactionCount > 0); + } - public Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + return Task.FromResult(true); + } - public Task ValidateBlockAfterExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockAfterExecuteAsync(IBlock block) + { + return Task.FromResult(true); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Application/BlockExecutedDataBaseProvider.cs b/src/AElf.Kernel.Core/SmartContract/Application/BlockExecutedDataBaseProvider.cs index 05e9779408..25587c2127 100644 --- a/src/AElf.Kernel.Core/SmartContract/Application/BlockExecutedDataBaseProvider.cs +++ b/src/AElf.Kernel.Core/SmartContract/Application/BlockExecutedDataBaseProvider.cs @@ -1,62 +1,58 @@ -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public abstract class BlockExecutedDataBaseProvider { - public abstract class BlockExecutedDataBaseProvider - { - private readonly ICachedBlockchainExecutedDataService - _cachedBlockchainExecutedDataService; - - protected BlockExecutedDataBaseProvider(ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) - { - _cachedBlockchainExecutedDataService = cachedBlockchainExecutedDataService; - } - - protected T GetBlockExecutedData(IBlockIndex chainContext, IMessage key = null) - { - return _cachedBlockchainExecutedDataService.GetBlockExecutedData(chainContext, GetBlockExecutedDataKey(key)); - } - - protected T GetBlockExecutedData(IBlockIndex chainContext, string key) - { - return _cachedBlockchainExecutedDataService.GetBlockExecutedData(chainContext, GetBlockExecutedDataKey(key)); - } - - protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IMessage key, T blockExecutedData) - { - await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, - GetBlockExecutedDataKey(key), blockExecutedData); - } - - protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, string key, T blockExecutedData) - { - await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, - GetBlockExecutedDataKey(key), blockExecutedData); - } - - protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, T blockExecutedData) - { - await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, - GetBlockExecutedDataKey(), blockExecutedData); - } - - protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData) - where TKey : IMessage - { - var dic = blockExecutedData.ToDictionary(pair => GetBlockExecutedDataKey(pair.Key), pair => pair.Value); - await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, dic); - } - - protected abstract string GetBlockExecutedDataName(); - - private string GetBlockExecutedDataKey(object key = null) - { - var list = new List {KernelConstants.BlockExecutedDataKey, GetBlockExecutedDataName()}; - if(key != null) list.Add(key.ToString()); - return string.Join("/", list); - } + private readonly ICachedBlockchainExecutedDataService + _cachedBlockchainExecutedDataService; + + protected BlockExecutedDataBaseProvider(ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) + { + _cachedBlockchainExecutedDataService = cachedBlockchainExecutedDataService; + } + + protected T GetBlockExecutedData(IBlockIndex chainContext, IMessage key = null) + { + return _cachedBlockchainExecutedDataService.GetBlockExecutedData(chainContext, GetBlockExecutedDataKey(key)); + } + + protected T GetBlockExecutedData(IBlockIndex chainContext, string key) + { + return _cachedBlockchainExecutedDataService.GetBlockExecutedData(chainContext, GetBlockExecutedDataKey(key)); + } + + protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IMessage key, T blockExecutedData) + { + await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, + GetBlockExecutedDataKey(key), blockExecutedData); + } + + protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, string key, T blockExecutedData) + { + await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, + GetBlockExecutedDataKey(key), blockExecutedData); + } + + protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, T blockExecutedData) + { + await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, + GetBlockExecutedDataKey(), blockExecutedData); + } + + protected async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData) + where TKey : IMessage + { + var dic = blockExecutedData.ToDictionary(pair => GetBlockExecutedDataKey(pair.Key), pair => pair.Value); + await _cachedBlockchainExecutedDataService.AddBlockExecutedDataAsync(blockIndex, dic); + } + + protected abstract string GetBlockExecutedDataName(); + + private string GetBlockExecutedDataKey(object key = null) + { + var list = new List { KernelConstants.BlockExecutedDataKey, GetBlockExecutedDataName() }; + if (key != null) list.Add(key.ToString()); + return string.Join("/", list); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Application/BlockchainExecutedDataServiceExtensions.cs b/src/AElf.Kernel.Core/SmartContract/Application/BlockchainExecutedDataServiceExtensions.cs index e0c8d7061b..6fe0860202 100644 --- a/src/AElf.Kernel.Core/SmartContract/Application/BlockchainExecutedDataServiceExtensions.cs +++ b/src/AElf.Kernel.Core/SmartContract/Application/BlockchainExecutedDataServiceExtensions.cs @@ -1,40 +1,35 @@ -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using AElf.Types; -using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public static class BlockchainExecutedDataServiceExtensions { - public static class BlockchainExecutedDataServiceExtensions + public static async Task GetBlockExecutedDataAsync( + this IBlockchainExecutedDataService blockchainExecutedDataService, + IBlockIndex chainContext, string key) { - public static async Task GetBlockExecutedDataAsync( - this IBlockchainExecutedDataService blockchainExecutedDataService, - IBlockIndex chainContext, string key) - { - var byteString = await blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, key); - return SerializationHelper.Deserialize(byteString?.ToByteArray()); - } + var byteString = await blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, key); + return SerializationHelper.Deserialize(byteString?.ToByteArray()); + } - public static async Task AddBlockExecutedDataAsync( - this IBlockchainExecutedDataService blockchainExecutedDataService, - Hash blockHash, string key, T blockExecutedData) + public static async Task AddBlockExecutedDataAsync( + this IBlockchainExecutedDataService blockchainExecutedDataService, + Hash blockHash, string key, T blockExecutedData) + { + var dic = new Dictionary { - var dic = new Dictionary - { - {key, ByteString.CopyFrom(SerializationHelper.Serialize(blockExecutedData))} - }; - await blockchainExecutedDataService.AddBlockExecutedDataAsync(blockHash, dic); - } + { key, ByteString.CopyFrom(SerializationHelper.Serialize(blockExecutedData)) } + }; + await blockchainExecutedDataService.AddBlockExecutedDataAsync(blockHash, dic); + } - public static async Task AddBlockExecutedDataAsync( - this IBlockchainExecutedDataService blockchainExecutedDataService, - Hash blockHash, IDictionary blockExecutedData) - { - var dic = blockExecutedData.ToDictionary( - keyPair => keyPair.Key, - keyPair => ByteString.CopyFrom(SerializationHelper.Serialize(keyPair.Value))); - await blockchainExecutedDataService.AddBlockExecutedDataAsync(blockHash, dic); - } + public static async Task AddBlockExecutedDataAsync( + this IBlockchainExecutedDataService blockchainExecutedDataService, + Hash blockHash, IDictionary blockExecutedData) + { + var dic = blockExecutedData.ToDictionary( + keyPair => keyPair.Key, + keyPair => ByteString.CopyFrom(SerializationHelper.Serialize(keyPair.Value))); + await blockchainExecutedDataService.AddBlockExecutedDataAsync(blockHash, dic); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Application/CachedBlockchainExecutedDataServiceExtensions.cs b/src/AElf.Kernel.Core/SmartContract/Application/CachedBlockchainExecutedDataServiceExtensions.cs index 448ffc3be6..1d22f68c1b 100644 --- a/src/AElf.Kernel.Core/SmartContract/Application/CachedBlockchainExecutedDataServiceExtensions.cs +++ b/src/AElf.Kernel.Core/SmartContract/Application/CachedBlockchainExecutedDataServiceExtensions.cs @@ -1,20 +1,15 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.SmartContract.Application; -namespace AElf.Kernel.SmartContract.Application +public static class CachedBlockchainExecutedDataServiceExtensions { - public static class CachedBlockchainExecutedDataServiceExtensions + public static async Task AddBlockExecutedDataAsync( + this ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataGettingService, + IBlockIndex blockIndex, string key, T blockExecutedData) { - public static async Task AddBlockExecutedDataAsync( - this ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataGettingService, - IBlockIndex blockIndex, string key, T blockExecutedData) + var dic = new Dictionary { - var dic = new Dictionary - { - {key, blockExecutedData} - }; - await cachedBlockchainExecutedDataGettingService.AddBlockExecutedDataAsync(blockIndex, dic); - } + { key, blockExecutedData } + }; + await cachedBlockchainExecutedDataGettingService.AddBlockExecutedDataAsync(blockIndex, dic); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.Core/SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs index 07afbede80..50e5218b3b 100644 --- a/src/AElf.Kernel.Core/SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.Core/SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -1,21 +1,20 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Events; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class CleanBlockExecutedDataChangeHeightBaseEventHandler { - public class CleanBlockExecutedDataChangeHeightBaseEventHandler + private readonly ICachedBlockchainExecutedDataService _cachedBlockchainExecutedDataService; + + public CleanBlockExecutedDataChangeHeightBaseEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) { - private readonly ICachedBlockchainExecutedDataService _cachedBlockchainExecutedDataService; - - public CleanBlockExecutedDataChangeHeightBaseEventHandler(ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) - { - _cachedBlockchainExecutedDataService = cachedBlockchainExecutedDataService; - } + _cachedBlockchainExecutedDataService = cachedBlockchainExecutedDataService; + } - public Task HandleEventAsync(CleanBlockExecutedDataChangeHeightEventData eventData) - { - _cachedBlockchainExecutedDataService.CleanChangeHeight(eventData.IrreversibleBlockHeight); - return Task.CompletedTask; - } + public Task HandleEventAsync(CleanBlockExecutedDataChangeHeightEventData eventData) + { + _cachedBlockchainExecutedDataService.CleanChangeHeight(eventData.IrreversibleBlockHeight); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Application/IBlockchainStateService.cs b/src/AElf.Kernel.Core/SmartContract/Application/IBlockchainStateService.cs index 08a808d7fe..4663df53c9 100644 --- a/src/AElf.Kernel.Core/SmartContract/Application/IBlockchainStateService.cs +++ b/src/AElf.Kernel.Core/SmartContract/Application/IBlockchainStateService.cs @@ -1,206 +1,186 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Types; -using Google.Protobuf; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IBlockchainStateService { - public interface IBlockchainStateService - { - Task MergeBlockStateAsync(long lastIrreversibleBlockHeight, Hash lastIrreversibleBlockHash); + Task MergeBlockStateAsync(long lastIrreversibleBlockHeight, Hash lastIrreversibleBlockHash); - Task SetBlockStateSetAsync(BlockStateSet blockStateSet); + Task SetBlockStateSetAsync(BlockStateSet blockStateSet); - Task RemoveBlockStateSetsAsync(IList blockStateHashes); - } + Task RemoveBlockStateSetsAsync(IList blockStateHashes); +} - public interface IBlockchainExecutedDataService - { - Task GetBlockExecutedDataAsync(IBlockIndex chainContext, string key); +public interface IBlockchainExecutedDataService +{ + Task GetBlockExecutedDataAsync(IBlockIndex chainContext, string key); - Task AddBlockExecutedDataAsync(Hash blockHash, IDictionary blockExecutedData); - } + Task AddBlockExecutedDataAsync(Hash blockHash, IDictionary blockExecutedData); +} +public class BlockchainExecutedDataService : IBlockchainExecutedDataService +{ + private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; - public class BlockchainExecutedDataService : IBlockchainExecutedDataService + public BlockchainExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager) { - private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; - - //it's a infrastructure - private ConcurrentDictionary _cache = new ConcurrentDictionary(); - - public BlockchainExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager) - { - _blockchainExecutedDataManager = blockchainExecutedDataManager; - } + _blockchainExecutedDataManager = blockchainExecutedDataManager; + } + public ILogger Logger { get; set; } - public ILogger Logger { get; set; } + public async Task GetBlockExecutedDataAsync(IBlockIndex chainContext, string key) + { + return (await _blockchainExecutedDataManager.GetExecutedCacheAsync(key, chainContext.BlockHeight, + chainContext.BlockHash)).Value; + } + public async Task AddBlockExecutedDataAsync(Hash blockHash, IDictionary blockExecutedData) + { + await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockHash, blockExecutedData); + } +} - public async Task GetBlockExecutedDataAsync(IBlockIndex chainContext, string key) - { - return (await _blockchainExecutedDataManager.GetExecutedCacheAsync(key, chainContext.BlockHeight, - chainContext.BlockHash)).Value; - } +public interface ICachedBlockchainExecutedDataService +{ + T GetBlockExecutedData(IBlockIndex chainContext, string key); + Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData); + void CleanChangeHeight(long height); +} - public async Task AddBlockExecutedDataAsync(Hash blockHash, IDictionary blockExecutedData) - { - await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockHash, blockExecutedData); - } - } +public class CachedBlockchainExecutedDataService : ICachedBlockchainExecutedDataService +{ + private readonly IBlockchainExecutedDataCacheProvider _blockchainExecutedDataCacheProvider; + private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; - public interface ICachedBlockchainExecutedDataService + public CachedBlockchainExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager + , IBlockchainExecutedDataCacheProvider blockchainExecutedDataCacheProvider) { - T GetBlockExecutedData(IBlockIndex chainContext, string key); - Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData); - void CleanChangeHeight(long height); + _blockchainExecutedDataManager = blockchainExecutedDataManager; + _blockchainExecutedDataCacheProvider = blockchainExecutedDataCacheProvider; } - public class CachedBlockchainExecutedDataService : ICachedBlockchainExecutedDataService + public T GetBlockExecutedData(IBlockIndex chainContext, string key) { - private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; - private readonly IBlockchainExecutedDataCacheProvider _blockchainExecutedDataCacheProvider; + if (!_blockchainExecutedDataCacheProvider.TryGetChangeHeight(key, out _) + && _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData(key, out var value)) + return value; - public CachedBlockchainExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager - , IBlockchainExecutedDataCacheProvider blockchainExecutedDataCacheProvider) - { - _blockchainExecutedDataManager = blockchainExecutedDataManager; - _blockchainExecutedDataCacheProvider = blockchainExecutedDataCacheProvider; - } - - public T GetBlockExecutedData(IBlockIndex chainContext, string key) - { - if ( !_blockchainExecutedDataCacheProvider.TryGetChangeHeight(key,out _) - && _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData(key, out var value)) - { - return value; - } + var ret = AsyncHelper.RunSync(() => _blockchainExecutedDataManager.GetExecutedCacheAsync(key, + chainContext.BlockHeight, + chainContext.BlockHash)); - var ret = AsyncHelper.RunSync(() => _blockchainExecutedDataManager.GetExecutedCacheAsync(key, - chainContext.BlockHeight, - chainContext.BlockHash)); + var blockExecutedData = Deserialize(ret.Value); - var blockExecutedData = Deserialize(ret.Value); - - //if executed is in Store, it will not change when forking - if (ret.IsInStore && !_blockchainExecutedDataCacheProvider.TryGetChangeHeight(key, out _)) - _blockchainExecutedDataCacheProvider.SetBlockExecutedData(key, blockExecutedData); - return blockExecutedData; - } + //if executed is in Store, it will not change when forking + if (ret.IsInStore && !_blockchainExecutedDataCacheProvider.TryGetChangeHeight(key, out _)) + _blockchainExecutedDataCacheProvider.SetBlockExecutedData(key, blockExecutedData); + return blockExecutedData; + } - public async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData) - { - await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockIndex.BlockHash, blockExecutedData.ToDictionary + public async Task AddBlockExecutedDataAsync(IBlockIndex blockIndex, IDictionary blockExecutedData) + { + await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockIndex.BlockHash, + blockExecutedData.ToDictionary (pair => pair.Key, pair => Serialize(pair.Value))); - foreach (var pair in blockExecutedData) - { - if (blockIndex.BlockHeight > AElfConstants.GenesisBlockHeight && - (!_blockchainExecutedDataCacheProvider.TryGetChangeHeight(pair.Key, out var height) || - height < blockIndex.BlockHeight)) - { - _blockchainExecutedDataCacheProvider.SetChangeHeight(pair.Key, blockIndex.BlockHeight); - } - _blockchainExecutedDataCacheProvider.RemoveBlockExecutedData(pair.Key); - } - - } - - public void CleanChangeHeight(long height) + foreach (var pair in blockExecutedData) { - _blockchainExecutedDataCacheProvider.CleanChangeHeight(height); + if (blockIndex.BlockHeight > AElfConstants.GenesisBlockHeight && + (!_blockchainExecutedDataCacheProvider.TryGetChangeHeight(pair.Key, out var height) || + height < blockIndex.BlockHeight)) + _blockchainExecutedDataCacheProvider.SetChangeHeight(pair.Key, blockIndex.BlockHeight); + _blockchainExecutedDataCacheProvider.RemoveBlockExecutedData(pair.Key); } + } - protected virtual T Deserialize(ByteString byteString) - { - return SerializationHelper.Deserialize(byteString?.ToByteArray()); - } + public void CleanChangeHeight(long height) + { + _blockchainExecutedDataCacheProvider.CleanChangeHeight(height); + } - protected virtual ByteString Serialize(T value) - { - return ByteString.CopyFrom(SerializationHelper.Serialize(value)); - } + protected virtual T Deserialize(ByteString byteString) + { + return SerializationHelper.Deserialize(byteString?.ToByteArray()); } - public class BlockchainStateService : IBlockchainStateService + protected virtual ByteString Serialize(T value) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockStateSetManger _blockStateSetManger; - public ILogger Logger { get; set; } + return ByteString.CopyFrom(SerializationHelper.Serialize(value)); + } +} - public BlockchainStateService(IBlockchainService blockchainService, - IBlockStateSetManger blockStateSetManger) - { - _blockchainService = blockchainService; - _blockStateSetManger = blockStateSetManger; - Logger = NullLogger.Instance; - } +public class BlockchainStateService : IBlockchainStateService +{ + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + + public BlockchainStateService(IBlockchainService blockchainService, + IBlockStateSetManger blockStateSetManger) + { + _blockchainService = blockchainService; + _blockStateSetManger = blockStateSetManger; + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } - public async Task MergeBlockStateAsync(long lastIrreversibleBlockHeight, Hash lastIrreversibleBlockHash) + public async Task MergeBlockStateAsync(long lastIrreversibleBlockHeight, Hash lastIrreversibleBlockHash) + { + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + var firstHeightToMerge = chainStateInfo.BlockHeight == 0L + ? AElfConstants.GenesisBlockHeight + : chainStateInfo.BlockHeight + 1; + var mergeCount = lastIrreversibleBlockHeight - firstHeightToMerge; + if (mergeCount < 0) { - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - var firstHeightToMerge = chainStateInfo.BlockHeight == 0L - ? AElfConstants.GenesisBlockHeight - : chainStateInfo.BlockHeight + 1; - var mergeCount = lastIrreversibleBlockHeight - firstHeightToMerge; - if (mergeCount < 0) - { - Logger.LogWarning( - $"Last merge height: {chainStateInfo.BlockHeight}, lib height: {lastIrreversibleBlockHeight}, needn't merge"); - return; - } + Logger.LogWarning( + "Last merge height: {ChainStateInfoBlockHeight}, lib height: {LastIrreversibleBlockHeight}, needn't merge", + chainStateInfo.BlockHeight, lastIrreversibleBlockHeight); + return; + } - var blockIndexes = new List(); - if (chainStateInfo.Status == ChainStateMergingStatus.Merged) - { - blockIndexes.Add(new BlockIndex(chainStateInfo.MergingBlockHash, -1)); - } + var blockIndexes = new List(); + if (chainStateInfo.Status == ChainStateMergingStatus.Merged) + blockIndexes.Add(new BlockIndex(chainStateInfo.MergingBlockHash, -1)); - var reversedBlockIndexes = - await _blockchainService.GetReversedBlockIndexes(lastIrreversibleBlockHash, (int) mergeCount); - reversedBlockIndexes.Reverse(); + var reversedBlockIndexes = + await _blockchainService.GetReversedBlockIndexes(lastIrreversibleBlockHash, (int)mergeCount); + reversedBlockIndexes.Reverse(); - blockIndexes.AddRange(reversedBlockIndexes); + blockIndexes.AddRange(reversedBlockIndexes); - blockIndexes.Add(new BlockIndex(lastIrreversibleBlockHash, lastIrreversibleBlockHeight)); + blockIndexes.Add(new BlockIndex(lastIrreversibleBlockHash, lastIrreversibleBlockHeight)); - Logger.LogDebug( - $"Start merge lib height: {lastIrreversibleBlockHeight}, lib block hash: {lastIrreversibleBlockHash}, merge count: {blockIndexes.Count}"); + Logger.LogDebug( + "Start merge lib height: {LastIrreversibleBlockHeight}, lib block hash: {LastIrreversibleBlockHash}, merge count: {BlockIndexesCount}", + lastIrreversibleBlockHeight, lastIrreversibleBlockHash, blockIndexes.Count); - foreach (var blockIndex in blockIndexes) + foreach (var blockIndex in blockIndexes) + try { - try - { - Logger.LogDebug($"Merging state {chainStateInfo} for block {blockIndex}"); - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, blockIndex.BlockHash); - } - catch (Exception e) - { - Logger.LogError(e, - $"Exception while merge state {chainStateInfo} for block {blockIndex}"); - throw; - } + Logger.LogDebug("Merging state {ChainStateInfo} for block {BlockIndex}", chainStateInfo, blockIndex); + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, blockIndex.BlockHash); } - } + catch (Exception e) + { + Logger.LogError(e, + "Exception while merge state {ChainStateInfo} for block {BlockIndex}", chainStateInfo, blockIndex); + throw; + } + } - public async Task SetBlockStateSetAsync(BlockStateSet blockStateSet) - { - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - } + public async Task SetBlockStateSetAsync(BlockStateSet blockStateSet) + { + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + } - public async Task RemoveBlockStateSetsAsync(IList blockStateHashes) - { - await _blockStateSetManger.RemoveBlockStateSetsAsync(blockStateHashes); - } + public async Task RemoveBlockStateSetsAsync(IList blockStateHashes) + { + await _blockStateSetManger.RemoveBlockStateSetsAsync(blockStateHashes); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Domain/IBlockchainStateManager.cs b/src/AElf.Kernel.Core/SmartContract/Domain/IBlockchainStateManager.cs index f0ea413bba..55355e72c4 100644 --- a/src/AElf.Kernel.Core/SmartContract/Domain/IBlockchainStateManager.cs +++ b/src/AElf.Kernel.Core/SmartContract/Domain/IBlockchainStateManager.cs @@ -1,310 +1,290 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Types; -using Google.Protobuf; using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public interface IBlockchainStateManager { - public interface IBlockchainStateManager - { - //Task GetVersionedStateAsync(Hash blockHash,long blockHeight, string key); - Task GetStateAsync(string key, long blockHeight, Hash blockHash); - } + //Task GetVersionedStateAsync(Hash blockHash,long blockHeight, string key); + Task GetStateAsync(string key, long blockHeight, Hash blockHash); +} - public class BlockchainStateManager : BlockchainStateBaseManager, IBlockchainStateManager +public class BlockchainStateManager : BlockchainStateBaseManager, IBlockchainStateManager +{ + public BlockchainStateManager(IStateStore versionedStates, + INotModifiedCachedStateStore blockStateSets) : base(versionedStates, blockStateSets) { - public BlockchainStateManager(IStateStore versionedStates, - INotModifiedCachedStateStore blockStateSets) : base(versionedStates, blockStateSets) - { - } - - protected override bool TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value) - { - value = null; - return blockStateSet != null && blockStateSet.TryGetState(key, out value); - } - - public async Task GetStateAsync(string key, long blockHeight, Hash blockHash) - { - return (await GetAsync(key, blockHeight, blockHash)).Value; - } } - - public interface IBlockStateSetManger + public async Task GetStateAsync(string key, long blockHeight, Hash blockHash) { - Task SetBlockStateSetAsync(BlockStateSet blockStateSet); - Task MergeBlockStateAsync(ChainStateInfo chainStateInfo, Hash blockStateHash); - Task GetChainStateInfoAsync(); - Task GetBlockStateSetAsync(Hash blockHash); - Task RemoveBlockStateSetsAsync(IList blockStateHashes); + return (await GetAsync(key, blockHeight, blockHash)).Value; } - - public interface IBlockchainExecutedDataManager + protected override bool TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value) { - Task GetExecutedCacheAsync(string key, long blockHeight, Hash blockHash); - - Task AddBlockExecutedCacheAsync(Hash blockHash, IDictionary blockExecutedCache); + value = null; + return blockStateSet != null && blockStateSet.TryGetState(key, out value); } +} +public interface IBlockStateSetManger +{ + Task SetBlockStateSetAsync(BlockStateSet blockStateSet); + Task MergeBlockStateAsync(ChainStateInfo chainStateInfo, Hash blockStateHash); + Task GetChainStateInfoAsync(); + Task GetBlockStateSetAsync(Hash blockHash); + Task RemoveBlockStateSetsAsync(IList blockStateHashes); +} + +public interface IBlockchainExecutedDataManager +{ + Task GetExecutedCacheAsync(string key, long blockHeight, Hash blockHash); - public class BlockchainExecutedDataManager : BlockchainStateBaseManager, IBlockchainExecutedDataManager, - ITransientDependency - { - private IBlockStateSetManger _blockStateSetManger; + Task AddBlockExecutedCacheAsync(Hash blockHash, IDictionary blockExecutedCache); +} - public BlockchainExecutedDataManager(IStateStore versionedStates, - INotModifiedCachedStateStore blockStateSets, IBlockStateSetManger blockStateSetManger) : - base(versionedStates, blockStateSets) - { - _blockStateSetManger = blockStateSetManger; - } +public class BlockchainExecutedDataManager : BlockchainStateBaseManager, IBlockchainExecutedDataManager, + ITransientDependency +{ + private readonly IBlockStateSetManger _blockStateSetManger; - protected override bool TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value) - { - value = null; - return blockStateSet != null && blockStateSet.TryGetExecutedCache(key, out value); - } + public BlockchainExecutedDataManager(IStateStore versionedStates, + INotModifiedCachedStateStore blockStateSets, IBlockStateSetManger blockStateSetManger) : + base(versionedStates, blockStateSets) + { + _blockStateSetManger = blockStateSetManger; + } - public async Task GetExecutedCacheAsync(string key, long blockHeight, Hash blockHash) - { - return (await GetAsync(key, blockHeight, blockHash)); - } + public async Task GetExecutedCacheAsync(string key, long blockHeight, Hash blockHash) + { + return await GetAsync(key, blockHeight, blockHash); + } - public async Task AddBlockExecutedCacheAsync(Hash blockHash, IDictionary blockExecutedCache) - { - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); - if (blockStateSet == null) return; - foreach (var keyPair in blockExecutedCache) - { - blockStateSet.BlockExecutedData[keyPair.Key] = keyPair.Value; - } + public async Task AddBlockExecutedCacheAsync(Hash blockHash, IDictionary blockExecutedCache) + { + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); + if (blockStateSet == null) return; + foreach (var keyPair in blockExecutedCache) blockStateSet.BlockExecutedData[keyPair.Key] = keyPair.Value; - await _blockStateSets.SetWithCacheAsync(blockStateSet.BlockHash.ToStorageKey(), blockStateSet); - } + await BlockStateSets.SetWithCacheAsync(blockStateSet.BlockHash.ToStorageKey(), blockStateSet); } - public class StateReturn + protected override bool TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value) { - public ByteString Value { get; set; } - public bool IsInStore { get; set; } + value = null; + return blockStateSet != null && blockStateSet.TryGetExecutedCache(key, out value); } +} + +public class StateReturn +{ + public ByteString Value { get; set; } + public bool IsInStore { get; set; } +} + +public abstract class BlockchainStateBaseManager +{ + protected readonly INotModifiedCachedStateStore BlockStateSets; + protected readonly IStateStore VersionedStates; - public abstract class BlockchainStateBaseManager + public BlockchainStateBaseManager(IStateStore versionedStates, + INotModifiedCachedStateStore blockStateSets) { - protected readonly IStateStore _versionedStates; - protected readonly INotModifiedCachedStateStore _blockStateSets; + VersionedStates = versionedStates; + BlockStateSets = blockStateSets; + } - public BlockchainStateBaseManager(IStateStore versionedStates, - INotModifiedCachedStateStore blockStateSets) - { - _versionedStates = versionedStates; - _blockStateSets = blockStateSets; - } + protected abstract bool + TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value); - protected abstract bool - TryGetFromBlockStateSet(BlockStateSet blockStateSet, string key, out ByteString value); + protected async Task GetAsync(string key, long blockHeight, Hash blockHash) + { + ByteString value; + var isInStore = false; + //first DB read + var bestChainState = await VersionedStates.GetAsync(key); - protected async Task GetAsync(string key, long blockHeight, Hash blockHash) + if (bestChainState != null) { - ByteString value = null; - var isInStore = false; - //first DB read - var bestChainState = await _versionedStates.GetAsync(key); - - if (bestChainState != null) + if (bestChainState.BlockHash == blockHash) { - if (bestChainState.BlockHash == blockHash) - { - value = bestChainState.Value; - isInStore = true; - } - else - { - if (bestChainState.BlockHeight >= blockHeight) - { - //because we may clear history state - throw new InvalidOperationException( - $"cannot read history state, best chain state hash: {bestChainState.BlockHash.ToHex()}, key: {key}, block height: {blockHeight}, block hash{blockHash.ToHex()}"); - } - - //find value in block state set - var blockStateSet = await FindBlockStateSetWithKeyAsync(key, bestChainState.BlockHeight, blockHash); - - TryGetFromBlockStateSet(blockStateSet, key, out value); - - if (value == null && (blockStateSet == null || !blockStateSet.Deletes.Contains(key) || - blockStateSet.BlockHeight <= bestChainState.BlockHeight)) - { - //not found value in block state sets. for example, best chain is 100, blockHeight is 105, - //it will find 105 ~ 101 block state set. so the value could only be the best chain state value. - // retry versioned state in case conflict of get state during merging - bestChainState = await _versionedStates.GetAsync(key); - value = bestChainState.Value; - isInStore = true; - } - } + value = bestChainState.Value; + isInStore = true; } else { - //best chain state is null, it will find value in block state set - var blockStateSet = await FindBlockStateSetWithKeyAsync(key, 0, blockHash); + if (bestChainState.BlockHeight >= blockHeight) + //because we may clear history state + throw new InvalidOperationException( + $"cannot read history state, best chain state hash: {bestChainState.BlockHash.ToHex()}, key: {key}, block height: {blockHeight}, block hash{blockHash.ToHex()}"); + + //find value in block state set + var blockStateSet = await FindBlockStateSetWithKeyAsync(key, bestChainState.BlockHeight, blockHash); TryGetFromBlockStateSet(blockStateSet, key, out value); - if (value == null && blockStateSet == null) + if (value == null && (blockStateSet == null || !blockStateSet.Deletes.Contains(key) || + blockStateSet.BlockHeight <= bestChainState.BlockHeight)) { + //not found value in block state sets. for example, best chain is 100, blockHeight is 105, + //it will find 105 ~ 101 block state set. so the value could only be the best chain state value. // retry versioned state in case conflict of get state during merging - bestChainState = await _versionedStates.GetAsync(key); - value = bestChainState?.Value; + bestChainState = await VersionedStates.GetAsync(key); + value = bestChainState.Value; + isInStore = true; } } + } + else + { + //best chain state is null, it will find value in block state set + var blockStateSet = await FindBlockStateSetWithKeyAsync(key, 0, blockHash); + TryGetFromBlockStateSet(blockStateSet, key, out value); - return new StateReturn() + if (value == null && blockStateSet == null) { - Value = value, - IsInStore = isInStore - }; + // retry versioned state in case conflict of get state during merging + bestChainState = await VersionedStates.GetAsync(key); + value = bestChainState?.Value; + } } - private async Task FindBlockStateSetWithKeyAsync(string key, long bestChainHeight, - Hash blockHash) + + return new StateReturn { - var blockStateKey = blockHash.ToStorageKey(); - var blockStateSet = await _blockStateSets.GetAsync(blockStateKey); + Value = value, + IsInStore = isInStore + }; + } - while (blockStateSet != null && blockStateSet.BlockHeight > bestChainHeight) - { - if ( - TryGetFromBlockStateSet(blockStateSet, key, out _)) break; + private async Task FindBlockStateSetWithKeyAsync(string key, long bestChainHeight, + Hash blockHash) + { + var blockStateKey = blockHash.ToStorageKey(); + var blockStateSet = await BlockStateSets.GetAsync(blockStateKey); - blockStateKey = blockStateSet.PreviousHash?.ToStorageKey(); + while (blockStateSet != null && blockStateSet.BlockHeight > bestChainHeight) + { + if ( + TryGetFromBlockStateSet(blockStateSet, key, out _)) break; - if (blockStateKey != null) - { - blockStateSet = await _blockStateSets.GetAsync(blockStateKey); - } - else - { - blockStateSet = null; - } - } + blockStateKey = blockStateSet.PreviousHash?.ToStorageKey(); - return blockStateSet; + if (blockStateKey != null) + blockStateSet = await BlockStateSets.GetAsync(blockStateKey); + else + blockStateSet = null; } - } - public class BlockStateSetManger : IBlockStateSetManger, ITransientDependency - { - protected readonly IStateStore _versionedStates; - protected readonly INotModifiedCachedStateStore _blockStateSets; + return blockStateSet; + } +} - private readonly IStateStore _chainStateInfoCollection; - private readonly int _chainId; +public class BlockStateSetManger : IBlockStateSetManger, ITransientDependency +{ + private readonly int _chainId; + private readonly IStateStore _chainStateInfoCollection; + protected readonly INotModifiedCachedStateStore BlockStateSets; + protected readonly IStateStore VersionedStates; - public BlockStateSetManger(IStateStore versionedStates, - INotModifiedCachedStateStore blockStateSets, - IStateStore chainStateInfoCollection, IOptionsSnapshot options) - { - _versionedStates = versionedStates; - _blockStateSets = blockStateSets; - _chainStateInfoCollection = chainStateInfoCollection; - _chainId = options.Value.ChainId; - } - + public BlockStateSetManger(IStateStore versionedStates, + INotModifiedCachedStateStore blockStateSets, + IStateStore chainStateInfoCollection, IOptionsSnapshot options) + { + VersionedStates = versionedStates; + BlockStateSets = blockStateSets; + _chainStateInfoCollection = chainStateInfoCollection; + _chainId = options.Value.ChainId; + } - public async Task MergeBlockStateAsync(ChainStateInfo chainStateInfo, Hash blockStateHash) + public async Task MergeBlockStateAsync(ChainStateInfo chainStateInfo, Hash blockStateHash) + { + var blockState = await BlockStateSets.GetAsync(blockStateHash.ToStorageKey()); + if (blockState == null) { - var blockState = await _blockStateSets.GetAsync(blockStateHash.ToStorageKey()); - if (blockState == null) + if (chainStateInfo.Status == ChainStateMergingStatus.Merged && + chainStateInfo.MergingBlockHash == blockStateHash) { - if (chainStateInfo.Status == ChainStateMergingStatus.Merged && - chainStateInfo.MergingBlockHash == blockStateHash) - { - chainStateInfo.Status = ChainStateMergingStatus.Common; - chainStateInfo.MergingBlockHash = null; - - await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); - return; - } + chainStateInfo.Status = ChainStateMergingStatus.Common; + chainStateInfo.MergingBlockHash = null; - throw new InvalidOperationException($"cannot get block state of {blockStateHash}"); + await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); + return; } - if (chainStateInfo.BlockHash == null || chainStateInfo.BlockHash == blockState.PreviousHash || - (chainStateInfo.Status == ChainStateMergingStatus.Merged && - chainStateInfo.MergingBlockHash == blockState.BlockHash)) - { - chainStateInfo.Status = ChainStateMergingStatus.Merging; - chainStateInfo.MergingBlockHash = blockStateHash; + throw new InvalidOperationException($"cannot get block state of {blockStateHash}"); + } - await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); - var dic = blockState.Changes.Concat(blockState.BlockExecutedData).Select(change => new VersionedState - { - Key = change.Key, - Value = change.Value, - BlockHash = blockState.BlockHash, - BlockHeight = blockState.BlockHeight, - //OriginBlockHash = origin.BlockHash - }).ToDictionary(p => p.Key, p => p); + if (chainStateInfo.BlockHash == null || chainStateInfo.BlockHash == blockState.PreviousHash || + (chainStateInfo.Status == ChainStateMergingStatus.Merged && + chainStateInfo.MergingBlockHash == blockState.BlockHash)) + { + chainStateInfo.Status = ChainStateMergingStatus.Merging; + chainStateInfo.MergingBlockHash = blockStateHash; + + await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); + var dic = blockState.Changes.Concat(blockState.BlockExecutedData).Select(change => new VersionedState + { + Key = change.Key, + Value = change.Value, + BlockHash = blockState.BlockHash, + BlockHeight = blockState.BlockHeight + //OriginBlockHash = origin.BlockHash + }).ToDictionary(p => p.Key, p => p); - await _versionedStates.SetAllAsync(dic); + await VersionedStates.SetAllAsync(dic); - await _versionedStates.RemoveAllAsync(blockState.Deletes.ToList()); + await VersionedStates.RemoveAllAsync(blockState.Deletes.ToList()); - chainStateInfo.Status = ChainStateMergingStatus.Merged; - chainStateInfo.BlockHash = blockState.BlockHash; - chainStateInfo.BlockHeight = blockState.BlockHeight; - await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); + chainStateInfo.Status = ChainStateMergingStatus.Merged; + chainStateInfo.BlockHash = blockState.BlockHash; + chainStateInfo.BlockHeight = blockState.BlockHeight; + await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); - await _blockStateSets.RemoveAsync(blockStateHash.ToStorageKey()); + await BlockStateSets.RemoveAsync(blockStateHash.ToStorageKey()); - chainStateInfo.Status = ChainStateMergingStatus.Common; - chainStateInfo.MergingBlockHash = null; + chainStateInfo.Status = ChainStateMergingStatus.Common; + chainStateInfo.MergingBlockHash = null; - await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); - } - else - { - throw new InvalidOperationException( - "cannot merge block not linked, check new block's previous block hash "); - } + await _chainStateInfoCollection.SetAsync(chainStateInfo.ChainId.ToStorageKey(), chainStateInfo); } - - public async Task SetBlockStateSetAsync(BlockStateSet blockStateSet) + else { - await _blockStateSets.SetAsync(GetKey(blockStateSet), blockStateSet); + throw new InvalidOperationException( + "cannot merge block not linked, check new block's previous block hash "); } + } - protected string GetKey(BlockStateSet blockStateSet) - { - return blockStateSet.BlockHash.ToStorageKey(); - } + public async Task SetBlockStateSetAsync(BlockStateSet blockStateSet) + { + await BlockStateSets.SetAsync(GetKey(blockStateSet), blockStateSet); + } - public async Task GetBlockStateSetAsync(Hash blockHash) - { - return await _blockStateSets.GetAsync(blockHash.ToStorageKey()); - } + public async Task GetBlockStateSetAsync(Hash blockHash) + { + return await BlockStateSets.GetAsync(blockHash.ToStorageKey()); + } - public async Task RemoveBlockStateSetsAsync(IList blockStateHashes) - { - await _blockStateSets.RemoveAllAsync(blockStateHashes.Select(b => b.ToStorageKey()).ToList()); - } + public async Task RemoveBlockStateSetsAsync(IList blockStateHashes) + { + await BlockStateSets.RemoveAllAsync(blockStateHashes.Select(b => b.ToStorageKey()).ToList()); + } - public async Task GetChainStateInfoAsync() - { - var chainStateInfo = await _chainStateInfoCollection.GetAsync(_chainId.ToStorageKey()); - return chainStateInfo ?? new ChainStateInfo {ChainId = _chainId}; - } + public async Task GetChainStateInfoAsync() + { + var chainStateInfo = await _chainStateInfoCollection.GetAsync(_chainId.ToStorageKey()); + return chainStateInfo ?? new ChainStateInfo { ChainId = _chainId }; + } + + protected string GetKey(BlockStateSet blockStateSet) + { + return blockStateSet.BlockHash.ToStorageKey(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Events/CleanBlockExecutedDataChangeHeightEventData.cs b/src/AElf.Kernel.Core/SmartContract/Events/CleanBlockExecutedDataChangeHeightEventData.cs index 948542c08b..fbaa0e0983 100644 --- a/src/AElf.Kernel.Core/SmartContract/Events/CleanBlockExecutedDataChangeHeightEventData.cs +++ b/src/AElf.Kernel.Core/SmartContract/Events/CleanBlockExecutedDataChangeHeightEventData.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.SmartContract.Events +namespace AElf.Kernel.SmartContract.Events; + +public class CleanBlockExecutedDataChangeHeightEventData { - public class CleanBlockExecutedDataChangeHeightEventData - { - public long IrreversibleBlockHeight { get; set; } - } + public long IrreversibleBlockHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Infrastructure/BlockchainExecutedDataCacheProvider.cs b/src/AElf.Kernel.Core/SmartContract/Infrastructure/BlockchainExecutedDataCacheProvider.cs index 7e0ce0315f..4c69a9e7c5 100644 --- a/src/AElf.Kernel.Core/SmartContract/Infrastructure/BlockchainExecutedDataCacheProvider.cs +++ b/src/AElf.Kernel.Core/SmartContract/Infrastructure/BlockchainExecutedDataCacheProvider.cs @@ -1,60 +1,51 @@ using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface IBlockchainExecutedDataCacheProvider +{ + bool TryGetBlockExecutedData(string key, out T value); + void SetBlockExecutedData(string key, T blockExecutedData); + void RemoveBlockExecutedData(string key); + bool TryGetChangeHeight(string key, out long value); + void SetChangeHeight(string key, long value); + void CleanChangeHeight(long height); +} + +public class BlockchainExecutedDataCacheProvider : IBlockchainExecutedDataCacheProvider { - public interface IBlockchainExecutedDataCacheProvider + private readonly ConcurrentDictionary _blockExecutedDataDic = new(); + private readonly ConcurrentDictionary _changeHeightDic = new(); + + public bool TryGetBlockExecutedData(string key, out T value) + { + return _blockExecutedDataDic.TryGetValue(key, out value); + } + + public void SetBlockExecutedData(string key, T blockExecutedData) + { + _blockExecutedDataDic[key] = blockExecutedData; + } + + public void RemoveBlockExecutedData(string key) + { + _blockExecutedDataDic.TryRemove(key, out _); + } + + public bool TryGetChangeHeight(string key, out long value) + { + return _changeHeightDic.TryGetValue(key, out value); + } + + public void SetChangeHeight(string key, long value) { - bool TryGetBlockExecutedData(string key, out T value); - void SetBlockExecutedData(string key, T blockExecutedData); - void RemoveBlockExecutedData(string key); - bool TryGetChangeHeight(string key, out long value); - void SetChangeHeight(string key, long value); - void CleanChangeHeight(long height); + _changeHeightDic[key] = value; } - public class BlockchainExecutedDataCacheProvider : IBlockchainExecutedDataCacheProvider + public void CleanChangeHeight(long height) { - private readonly ConcurrentDictionary _blockExecutedDataDic = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _changeHeightDic = new ConcurrentDictionary(); - - public bool TryGetBlockExecutedData(string key, out T value) - { - return _blockExecutedDataDic.TryGetValue(key, out value); - } - - public void SetBlockExecutedData(string key, T blockExecutedData) - { - _blockExecutedDataDic[key] = blockExecutedData; - } - - public void RemoveBlockExecutedData(string key) - { - _blockExecutedDataDic.TryRemove(key, out _); - } - - public bool TryGetChangeHeight(string key, out long value) - { - return _changeHeightDic.TryGetValue(key, out value); - } - - public void SetChangeHeight(string key, long value) - { - _changeHeightDic[key] = value; - } - - public void CleanChangeHeight(long height) - { - var keys = _changeHeightDic.Where(pair => pair.Value <= height).Select(pair => pair.Key); - foreach (var key in keys) - { - _changeHeightDic.TryRemove(key, out _); - } - } + var keys = _changeHeightDic.Where(pair => pair.Value <= height).Select(pair => pair.Key); + foreach (var key in keys) _changeHeightDic.TryRemove(key, out _); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Infrastructure/IStateStore.cs b/src/AElf.Kernel.Core/SmartContract/Infrastructure/IStateStore.cs index 1c4235da33..86aaba84f1 100644 --- a/src/AElf.Kernel.Core/SmartContract/Infrastructure/IStateStore.cs +++ b/src/AElf.Kernel.Core/SmartContract/Infrastructure/IStateStore.cs @@ -1,10 +1,8 @@ using AElf.Kernel.Infrastructure; -using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface IStateStore : IKeyValueStore + where T : IMessage, new() { - public interface IStateStore : IKeyValueStore - where T : IMessage, new() - { - } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContract/Infrastructure/StateStore.cs b/src/AElf.Kernel.Core/SmartContract/Infrastructure/StateStore.cs index aa22e23fea..97f1ad7115 100644 --- a/src/AElf.Kernel.Core/SmartContract/Infrastructure/StateStore.cs +++ b/src/AElf.Kernel.Core/SmartContract/Infrastructure/StateStore.cs @@ -1,119 +1,98 @@ -using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Infrastructure; -using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public class StateStore : KeyValueStoreBase, IStateStore + where T : class, IMessage, new() { - public class StateStore : KeyValueStoreBase, IStateStore - where T : class, IMessage, new() + public StateStore(StateKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) : base( + keyValueDbContext, prefixProvider) { - public StateStore(StateKeyValueDbContext keyValueDbContext, IStoreKeyPrefixProvider prefixProvider) : base( - keyValueDbContext, prefixProvider) - { - } } +} + +public interface INotModifiedCachedStateStore : IStateStore + where T : IMessage, new() +{ + Task SetWithCacheAsync(string key, T value); +} - public interface INotModifiedCachedStateStore : IStateStore - where T : IMessage, new() +public class NotModifiedCachedStateStore : INotModifiedCachedStateStore + where T : class, IMessage, new() +{ + private readonly ConcurrentDictionary _cache = new(); + private readonly IStateStore _stateStoreImplementation; + + public NotModifiedCachedStateStore(IStateStore stateStoreImplementation) { - Task SetWithCacheAsync(string key, T value); + _stateStoreImplementation = stateStoreImplementation; } - public class NotModifiedCachedStateStore : INotModifiedCachedStateStore - where T : class, IMessage, new() + public async Task SetAsync(string key, T value) { - private readonly IStateStore _stateStoreImplementation; + await _stateStoreImplementation.SetAsync(key, value); + } - private readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + public async Task SetAllAsync(Dictionary pipelineSet) + { + await _stateStoreImplementation.SetAllAsync(pipelineSet); + } - public NotModifiedCachedStateStore(IStateStore stateStoreImplementation) - { - _stateStoreImplementation = stateStoreImplementation; - } + public async Task GetAsync(string key) + { + if (_cache.TryGetValue(key, out var item)) return item; - public async Task SetAsync(string key, T value) - { - await _stateStoreImplementation.SetAsync(key, value); - } + var state = await _stateStoreImplementation.GetAsync(key); + if (state != null) _cache[key] = state; - public async Task SetAllAsync(Dictionary pipelineSet) - { - await _stateStoreImplementation.SetAllAsync(pipelineSet); - } + return state; + } - public async Task GetAsync(string key) - { - if (_cache.TryGetValue(key, out var item)) - { - return item; - } + public async Task RemoveAsync(string key) + { + _cache.TryRemove(key, out _); + await _stateStoreImplementation.RemoveAsync(key); + } - var state = await _stateStoreImplementation.GetAsync(key); - if (state != null) - { - _cache[key] = state; - } + public async Task IsExistsAsync(string key) + { + if (_cache.ContainsKey(key)) + return true; - return state; - } + return await _stateStoreImplementation.IsExistsAsync(key); + } - public async Task RemoveAsync(string key) - { - _cache.TryRemove(key, out _); - await _stateStoreImplementation.RemoveAsync(key); - } + public async Task> GetAllAsync(List keys) + { + var notInCacheKeys = new List(); + var result = new List(); + foreach (var key in keys) + if (_cache.TryGetValue(key, out var item)) + result.Add(item); + else + notInCacheKeys.Add(key); - public async Task IsExistsAsync(string key) + if (notInCacheKeys.Count > 0) { - if (_cache.ContainsKey(key)) - return true; - - return await _stateStoreImplementation.IsExistsAsync(key); + var resultFromDb = await _stateStoreImplementation.GetAllAsync(notInCacheKeys); + if (resultFromDb != null) + result.AddRange(resultFromDb); } - public async Task> GetAllAsync(List keys) - { - var notInCacheKeys = new List(); - var result = new List(); - foreach (var key in keys) - { - if (_cache.TryGetValue(key, out var item)) - { - result.Add(item); - } - else - { - notInCacheKeys.Add(key); - } - } - - if (notInCacheKeys.Count > 0) - { - var resultFromDb = await _stateStoreImplementation.GetAllAsync(notInCacheKeys); - if (resultFromDb != null) - result.AddRange(resultFromDb); - } - - return result; - } + return result; + } - public async Task RemoveAllAsync(List keys) - { - foreach (var key in keys) - { - _cache.TryRemove(key, out _); - } + public async Task RemoveAllAsync(List keys) + { + foreach (var key in keys) _cache.TryRemove(key, out _); - await _stateStoreImplementation.RemoveAllAsync(keys); - } + await _stateStoreImplementation.RemoveAllAsync(keys); + } - public async Task SetWithCacheAsync(string key, T value) - { - await SetAsync(key, value); - _cache[key] = value; - } + public async Task SetWithCacheAsync(string key, T value) + { + await SetAsync(key, value); + _cache[key] = value; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/SmartContractExecution/Events/TransactionExecutedEventData.cs b/src/AElf.Kernel.Core/SmartContractExecution/Events/TransactionExecutedEventData.cs index aec2b1f6dc..c9d025f7e3 100644 --- a/src/AElf.Kernel.Core/SmartContractExecution/Events/TransactionExecutedEventData.cs +++ b/src/AElf.Kernel.Core/SmartContractExecution/Events/TransactionExecutedEventData.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.SmartContractExecution.Events +namespace AElf.Kernel.SmartContractExecution.Events; + +public class TransactionExecutedEventData { - public class TransactionExecutedEventData - { - public TransactionTrace TransactionTrace { get; set; } - } + public TransactionTrace TransactionTrace { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Txn/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.Core/Txn/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs index ad1fd67eb2..4fea020897 100644 --- a/src/AElf.Kernel.Core/Txn/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.Core/Txn/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -1,18 +1,16 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Events; using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.Txn.Application +namespace AElf.Kernel.Txn.Application; + +public class CleanBlockExecutedDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< + BoolValue>, ILocalEventHandler, ITransientDependency { - public class CleanBlockExecutedDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< - BoolValue>, ILocalEventHandler, ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Txn/Application/ITransactionPackingOptionProvider.cs b/src/AElf.Kernel.Core/Txn/Application/ITransactionPackingOptionProvider.cs index 11d0768906..c088e1bbc1 100644 --- a/src/AElf.Kernel.Core/Txn/Application/ITransactionPackingOptionProvider.cs +++ b/src/AElf.Kernel.Core/Txn/Application/ITransactionPackingOptionProvider.cs @@ -1,40 +1,37 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Application; using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Txn.Application +namespace AElf.Kernel.Txn.Application; + +public interface ITransactionPackingOptionProvider +{ + Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable); + bool IsTransactionPackable(IChainContext chainContext); +} + +public class TransactionPackingOptionProvider : BlockExecutedDataBaseProvider, + ITransactionPackingOptionProvider, ISingletonDependency { - public interface ITransactionPackingOptionProvider + private const string BlockExecutedDataName = nameof(TransactionPackingOptionProvider); + + public TransactionPackingOptionProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable); - bool IsTransactionPackable(IChainContext chainContext); } - public class TransactionPackingOptionProvider : BlockExecutedDataBaseProvider, - ITransactionPackingOptionProvider, ISingletonDependency + public async Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) { - private const string BlockExecutedDataName = nameof(TransactionPackingOptionProvider); - - public TransactionPackingOptionProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + await AddBlockExecutedDataAsync(blockIndex, new BoolValue { Value = isTransactionPackable }); + } - public async Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) - { - await AddBlockExecutedDataAsync(blockIndex, new BoolValue {Value = isTransactionPackable}); - } + public bool IsTransactionPackable(IChainContext chainContext) + { + return GetBlockExecutedData(chainContext)?.Value ?? true; + } - public bool IsTransactionPackable(IChainContext chainContext) - { - return GetBlockExecutedData(chainContext)?.Value ?? true; - } + protected override string GetBlockExecutedDataName() + { + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Txn/Application/ITransactionValidationProvider.cs b/src/AElf.Kernel.Core/Txn/Application/ITransactionValidationProvider.cs index 0330d2c81e..0d10cf563d 100644 --- a/src/AElf.Kernel.Core/Txn/Application/ITransactionValidationProvider.cs +++ b/src/AElf.Kernel.Core/Txn/Application/ITransactionValidationProvider.cs @@ -1,11 +1,7 @@ -using System.Threading.Tasks; -using AElf.Types; +namespace AElf.Kernel.Txn.Application; -namespace AElf.Kernel.Txn.Application +public interface ITransactionValidationProvider { - public interface ITransactionValidationProvider - { - bool ValidateWhileSyncing { get; } - Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext = null); - } + bool ValidateWhileSyncing { get; } + Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext = null); } \ No newline at end of file diff --git a/src/AElf.Kernel.FeatureManager/AElf.Kernel.FeatureManager.csproj b/src/AElf.Kernel.FeatureManager/AElf.Kernel.FeatureManager.csproj index 97e40bf68f..dc52cc861d 100644 --- a/src/AElf.Kernel.FeatureManager/AElf.Kernel.FeatureManager.csproj +++ b/src/AElf.Kernel.FeatureManager/AElf.Kernel.FeatureManager.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/AElf.Kernel.FeatureManager/FeatureActiveService.cs b/src/AElf.Kernel.FeatureManager/FeatureActiveService.cs index 1247322476..b8912e62dc 100644 --- a/src/AElf.Kernel.FeatureManager/FeatureActiveService.cs +++ b/src/AElf.Kernel.FeatureManager/FeatureActiveService.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Configuration; using Google.Protobuf; @@ -10,8 +9,8 @@ namespace AElf.Kernel.FeatureManager; public class FeatureActiveService : IFeatureActiveService, ITransientDependency { - private readonly IConfigurationService _configurationService; private readonly IBlockchainService _blockchainService; + private readonly IConfigurationService _configurationService; public FeatureActiveService(IConfigurationService configurationService, IBlockchainService blockchainService) { @@ -31,10 +30,7 @@ public async Task IsFeatureActive(string featureName) }); var activeHeight = new Int64Value(); activeHeight.MergeFrom(activeHeightByteString); - if (activeHeight.Value == 0) - { - return false; - } + if (activeHeight.Value == 0) return false; return chain.BestChainHeight >= activeHeight.Value; } diff --git a/src/AElf.Kernel.FeatureManager/FeatureManagerAElfModule.cs b/src/AElf.Kernel.FeatureManager/FeatureManagerAElfModule.cs index ef3c776b03..ce74c7f47e 100644 --- a/src/AElf.Kernel.FeatureManager/FeatureManagerAElfModule.cs +++ b/src/AElf.Kernel.FeatureManager/FeatureManagerAElfModule.cs @@ -6,8 +6,7 @@ namespace AElf.Kernel.FeatureManager; [DependsOn( typeof(ConfigurationAElfModule) - )] +)] public class FeatureManagerAElfModule : AElfModule { - -} +} \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/AElf.Kernel.FeeCalculation.csproj b/src/AElf.Kernel.FeeCalculation/AElf.Kernel.FeeCalculation.csproj index efb44a14a2..1bb381ee7d 100644 --- a/src/AElf.Kernel.FeeCalculation/AElf.Kernel.FeeCalculation.csproj +++ b/src/AElf.Kernel.FeeCalculation/AElf.Kernel.FeeCalculation.csproj @@ -1,23 +1,23 @@ - net6.0 + net6.0 latest AElf.Kernel.FeeCalculation true Fee Calculation Project. - - + + - + Protobuf\Proto\token_contract.proto - - Protobuf\Proto\transaction_fee.proto - + + Protobuf\Proto\transaction_fee.proto + \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/CalculateFunctionExecutedDataService.cs b/src/AElf.Kernel.FeeCalculation/Application/CalculateFunctionExecutedDataService.cs index ec682fcb9b..7741621eb8 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/CalculateFunctionExecutedDataService.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/CalculateFunctionExecutedDataService.cs @@ -10,44 +10,42 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public class CalculateFunctionExecutedDataService : + CachedBlockchainExecutedDataService> { - public class CalculateFunctionExecutedDataService : - CachedBlockchainExecutedDataService> + public CalculateFunctionExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager, + IBlockchainExecutedDataCacheProvider> blockchainExecutedDataCacheProvider) + : + base(blockchainExecutedDataManager, blockchainExecutedDataCacheProvider) { - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public CalculateFunctionExecutedDataService(IBlockchainExecutedDataManager blockchainExecutedDataManager, - IBlockchainExecutedDataCacheProvider> blockchainExecutedDataCacheProvider) : - base(blockchainExecutedDataManager, blockchainExecutedDataCacheProvider) - { - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - protected override Dictionary Deserialize(ByteString byteString) - { - var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); - allCalculateFeeCoefficients.MergeFrom(byteString); - Logger.LogDebug($"Deserialize AllCalculateFeeCoefficients: {allCalculateFeeCoefficients}"); - return allCalculateFeeCoefficients.Value.ToDictionary( - c => ((FeeTypeEnum) c.FeeTokenType).ToString().ToUpper(), - c => c.ToCalculateFunction()); - } + protected override Dictionary Deserialize(ByteString byteString) + { + var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); + allCalculateFeeCoefficients.MergeFrom(byteString); + Logger.LogDebug($"Deserialize AllCalculateFeeCoefficients: {allCalculateFeeCoefficients}"); + return allCalculateFeeCoefficients.Value.ToDictionary( + c => ((FeeTypeEnum)c.FeeTokenType).ToString().ToUpper(), + c => c.ToCalculateFunction()); + } - protected override ByteString Serialize(Dictionary functionMap) - { - var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); - foreach (var functionPair in functionMap) + protected override ByteString Serialize(Dictionary functionMap) + { + var allCalculateFeeCoefficients = new AllCalculateFeeCoefficients(); + foreach (var functionPair in functionMap) + allCalculateFeeCoefficients.Value.Add(new CalculateFeeCoefficients { - allCalculateFeeCoefficients.Value.Add(new CalculateFeeCoefficients - { - FeeTokenType = functionPair.Value.CalculateFeeCoefficients.FeeTokenType, - PieceCoefficientsList = {functionPair.Value.CalculateFeeCoefficients.PieceCoefficientsList} - }); - } + FeeTokenType = functionPair.Value.CalculateFeeCoefficients.FeeTokenType, + PieceCoefficientsList = { functionPair.Value.CalculateFeeCoefficients.PieceCoefficientsList } + }); - Logger.LogDebug($"Serialize AllCalculateFeeCoefficients: {allCalculateFeeCoefficients}"); - return allCalculateFeeCoefficients.ToByteString(); - } + Logger.LogDebug($"Serialize AllCalculateFeeCoefficients: {allCalculateFeeCoefficients}"); + return allCalculateFeeCoefficients.ToByteString(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.FeeCalculation/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs index 20c2ea65f4..fb7f1ca0ac 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -5,16 +5,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public class CleanBlockExecutedDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< + Dictionary>, ILocalEventHandler, + ITransientDependency { - public class CleanBlockExecutedDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< - Dictionary>, ILocalEventHandler, - ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService> + cachedBlockchainExecutedDataService) : base(cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService> - cachedBlockchainExecutedDataService) : base(cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/IPrimaryTokenFeeService.cs b/src/AElf.Kernel.FeeCalculation/Application/IPrimaryTokenFeeService.cs index 1be9b716cf..fb590dbf3f 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/IPrimaryTokenFeeService.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/IPrimaryTokenFeeService.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public interface IPrimaryTokenFeeService { - public interface IPrimaryTokenFeeService - { - Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext); - } + Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/IResourceTokenFeeService.cs b/src/AElf.Kernel.FeeCalculation/Application/IResourceTokenFeeService.cs index 187a5ce9b7..bd3b2a21d2 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/IResourceTokenFeeService.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/IResourceTokenFeeService.cs @@ -2,11 +2,10 @@ using System.Threading.Tasks; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public interface IResourceTokenFeeService { - public interface IResourceTokenFeeService - { - Task> CalculateFeeAsync(ITransactionContext transactionContext, - IChainContext chainContext); - } + Task> CalculateFeeAsync(ITransactionContext transactionContext, + IChainContext chainContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/PrimaryTokenFeeService.cs b/src/AElf.Kernel.FeeCalculation/Application/PrimaryTokenFeeService.cs index 0ac20c58f0..d3c6a5341d 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/PrimaryTokenFeeService.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/PrimaryTokenFeeService.cs @@ -2,21 +2,20 @@ using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public class PrimaryTokenFeeService : IPrimaryTokenFeeService { - public class PrimaryTokenFeeService : IPrimaryTokenFeeService - { - private readonly IPrimaryTokenFeeProvider _primaryTokenFeeProvider; + private readonly IPrimaryTokenFeeProvider _primaryTokenFeeProvider; - public PrimaryTokenFeeService(IPrimaryTokenFeeProvider primaryTokenFeeProvider) - { - _primaryTokenFeeProvider = primaryTokenFeeProvider; - } + public PrimaryTokenFeeService(IPrimaryTokenFeeProvider primaryTokenFeeProvider) + { + _primaryTokenFeeProvider = primaryTokenFeeProvider; + } - public async Task CalculateFeeAsync(ITransactionContext transactionContext, - IChainContext chainContext) - { - return await _primaryTokenFeeProvider.CalculateFeeAsync(transactionContext, chainContext); - } + public async Task CalculateFeeAsync(ITransactionContext transactionContext, + IChainContext chainContext) + { + return await _primaryTokenFeeProvider.CalculateFeeAsync(transactionContext, chainContext); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/ResourceTokenFeeService.cs b/src/AElf.Kernel.FeeCalculation/Application/ResourceTokenFeeService.cs index 3e47bd70ad..4ead664076 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/ResourceTokenFeeService.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/ResourceTokenFeeService.cs @@ -3,29 +3,26 @@ using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public class ResourceTokenFeeService : IResourceTokenFeeService { - public class ResourceTokenFeeService : IResourceTokenFeeService - { - private readonly IEnumerable _resourceTokenFeeProviders; + private readonly IEnumerable _resourceTokenFeeProviders; - public ResourceTokenFeeService(IEnumerable resourceTokenFeeProviders) - { - _resourceTokenFeeProviders = resourceTokenFeeProviders; - } + public ResourceTokenFeeService(IEnumerable resourceTokenFeeProviders) + { + _resourceTokenFeeProviders = resourceTokenFeeProviders; + } - public async Task> CalculateFeeAsync(ITransactionContext transactionContext, - IChainContext chainContext) - { - var result = new Dictionary(); - foreach (var resourceTokenFeeProvider in _resourceTokenFeeProviders) - { - result[resourceTokenFeeProvider.TokenName] = - await resourceTokenFeeProvider.CalculateFeeAsync(transactionContext, - chainContext); - } + public async Task> CalculateFeeAsync(ITransactionContext transactionContext, + IChainContext chainContext) + { + var result = new Dictionary(); + foreach (var resourceTokenFeeProvider in _resourceTokenFeeProviders) + result[resourceTokenFeeProvider.TokenName] = + await resourceTokenFeeProvider.CalculateFeeAsync(transactionContext, + chainContext); - return result; - } + return result; } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Application/TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor.cs b/src/AElf.Kernel.FeeCalculation/Application/TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor.cs index 20a437bd01..b56a61d41f 100644 --- a/src/AElf.Kernel.FeeCalculation/Application/TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor.cs +++ b/src/AElf.Kernel.FeeCalculation/Application/TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor.cs @@ -9,53 +9,52 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.FeeCalculation.Application +namespace AElf.Kernel.FeeCalculation.Application; + +public class TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor : LogEventProcessorBase, + IBlockAcceptedLogEventProcessor { - public class TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor : LogEventProcessorBase, - IBlockAcceptedLogEventProcessor + private readonly ICalculateFunctionProvider _calculateFunctionProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + + public TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor( + ISmartContractAddressService smartContractAddressService, + ICalculateFunctionProvider calculateFunctionProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ICalculateFunctionProvider _calculateFunctionProvider; + _smartContractAddressService = smartContractAddressService; + _calculateFunctionProvider = calculateFunctionProvider; + Logger = NullLogger.Instance; + } - private ILogger Logger { get; set; } - - public TransactionFeeCalculatorCoefficientUpdatedLogEventProcessor( - ISmartContractAddressService smartContractAddressService, - ICalculateFunctionProvider calculateFunctionProvider) - { - _smartContractAddressService = smartContractAddressService; - _calculateFunctionProvider = calculateFunctionProvider; - Logger = NullLogger.Instance; - } - - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; - - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, TokenSmartContractAddressNameProvider.StringName); - - if (smartContractAddressDto == null) return null; - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - - if (!smartContractAddressDto.Irreversible)return interestedEvent; - - InterestedEvent = interestedEvent; + private ILogger Logger { get; } + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; - } - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, TokenSmartContractAddressNameProvider.StringName); + + if (smartContractAddressDto == null) return null; + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + + if (!smartContractAddressDto.Irreversible) return interestedEvent; + + InterestedEvent = interestedEvent; + + return InterestedEvent; + } + + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var eventData = new CalculateFeeAlgorithmUpdated(); + eventData.MergeFrom(logEvent); + await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex { - var eventData = new CalculateFeeAlgorithmUpdated(); - eventData.MergeFrom(logEvent); - await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, eventData.AllTypeFeeCoefficients.ToCalculateFunctionDictionary()); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }, eventData.AllTypeFeeCoefficients.ToCalculateFunctionDictionary()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Extensions/AllCalculateFeeCoefficientsExtensions.cs b/src/AElf.Kernel.FeeCalculation/Extensions/AllCalculateFeeCoefficientsExtensions.cs index 9447401f52..867afab7bd 100644 --- a/src/AElf.Kernel.FeeCalculation/Extensions/AllCalculateFeeCoefficientsExtensions.cs +++ b/src/AElf.Kernel.FeeCalculation/Extensions/AllCalculateFeeCoefficientsExtensions.cs @@ -3,15 +3,14 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.FeeCalculation.Infrastructure; -namespace AElf.Kernel.FeeCalculation.Extensions +namespace AElf.Kernel.FeeCalculation.Extensions; + +public static class AllCalculateFeeCoefficientsExtensions { - public static class AllCalculateFeeCoefficientsExtensions + internal static Dictionary ToCalculateFunctionDictionary( + this AllCalculateFeeCoefficients allCalculateFeeCoefficients) { - internal static Dictionary ToCalculateFunctionDictionary( - this AllCalculateFeeCoefficients allCalculateFeeCoefficients) - { - return allCalculateFeeCoefficients.Value.ToDictionary(c => ((FeeTypeEnum) c.FeeTokenType).ToString().ToUpper(), - c => c.ToCalculateFunction()); - } + return allCalculateFeeCoefficients.Value.ToDictionary(c => ((FeeTypeEnum)c.FeeTokenType).ToString().ToUpper(), + c => c.ToCalculateFunction()); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Extensions/CalculateFeeCoefficientsExtensions.cs b/src/AElf.Kernel.FeeCalculation/Extensions/CalculateFeeCoefficientsExtensions.cs index 7f29c31217..2d490496b0 100644 --- a/src/AElf.Kernel.FeeCalculation/Extensions/CalculateFeeCoefficientsExtensions.cs +++ b/src/AElf.Kernel.FeeCalculation/Extensions/CalculateFeeCoefficientsExtensions.cs @@ -3,74 +3,68 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.FeeCalculation.Infrastructure; -namespace AElf.Kernel.FeeCalculation.Extensions +namespace AElf.Kernel.FeeCalculation.Extensions; + +public static class CalculateFeeCoefficientsExtensions { - public static class CalculateFeeCoefficientsExtensions + private const decimal Precision = 100000000; + + internal static CalculateFunction ToCalculateFunction( + this CalculateFeeCoefficients calculateFeeCoefficients) { - internal static CalculateFunction ToCalculateFunction( - this CalculateFeeCoefficients calculateFeeCoefficients) - { - var pieceCalculateFunction = new CalculateFunction(calculateFeeCoefficients.FeeTokenType); - foreach (var pieceCoefficients in calculateFeeCoefficients.PieceCoefficientsList.Where(pc => - (pc.Value.Count - 1) % 3 == 0)) - { - pieceCalculateFunction.AddFunction(pieceCoefficients.Value.ToArray(), - GetFunction(pieceCoefficients.Value.ToArray())); - } + var pieceCalculateFunction = new CalculateFunction(calculateFeeCoefficients.FeeTokenType); + foreach (var pieceCoefficients in calculateFeeCoefficients.PieceCoefficientsList.Where(pc => + (pc.Value.Count - 1) % 3 == 0)) + pieceCalculateFunction.AddFunction(pieceCoefficients.Value.ToArray(), + GetFunction(pieceCoefficients.Value.ToArray())); - return pieceCalculateFunction; - } + return pieceCalculateFunction; + } - private const decimal Precision = 100000000; + private static Func GetFunction(int[] parameters) + { + return count => GetExponentialFunc(count, parameters); + } + + // eg. 2x^2 + 3x + 1 -> (2,2,1, 1,3,1, 0,1,1) + private static long GetExponentialFunc(int count, params int[] parameters) + { + long cost = 0; - private static Func GetFunction(int[] parameters) + // Skip parameters[0] which is meant to be piece upper bound. + var currentIndex = 1; + while (currentIndex < parameters.Length) { - return count => GetExponentialFunc(count, parameters); + cost += GetUnitExponentialCalculation(count, parameters[currentIndex], + parameters[currentIndex + 1], + parameters[currentIndex + 2]); + currentIndex += 3; } - // eg. 2x^2 + 3x + 1 -> (2,2,1, 1,3,1, 0,1,1) - private static long GetExponentialFunc(int count, params int[] parameters) - { - long cost = 0; + return cost; + } - // Skip parameters[0] which is meant to be piece upper bound. - var currentIndex = 1; - while (currentIndex < parameters.Length) - { - cost += GetUnitExponentialCalculation(count, parameters[currentIndex], - parameters[currentIndex + 1], - parameters[currentIndex + 2]); - currentIndex += 3; - } + // (A, B, C) -> x^A * (B / C) + private static long GetUnitExponentialCalculation(int count, params int[] parameters) + { + if (parameters[2] == 0) parameters[2] = 1; - return cost; + decimal decimalResult; + var power = parameters[0]; + decimal divisor = parameters[1]; + decimal dividend = parameters[2]; + if (power == 0) + { + // This piece is (B / C) + decimalResult = divisor / dividend; } - - // (A, B, C) -> x^A * (B / C) - private static long GetUnitExponentialCalculation(int count, params int[] parameters) + else { - if (parameters[2] == 0) - { - parameters[2] = 1; - } - - decimal decimalResult; - var power = parameters[0]; - decimal divisor = parameters[1]; - decimal dividend = parameters[2]; - if (power == 0) - { - // This piece is (B / C) - decimalResult = divisor / dividend; - } - else - { - // Calculate x^A at first. - var powerResult = (decimal) Math.Pow(count, power); - decimalResult = powerResult * divisor / dividend; - } - - return (long) (decimalResult * Precision); + // Calculate x^A at first. + var powerResult = (decimal)Math.Pow(count, power); + decimalResult = powerResult * divisor / dividend; } + + return (long)(decimalResult * Precision); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Extensions/TransactionResultExtensions.cs b/src/AElf.Kernel.FeeCalculation/Extensions/TransactionResultExtensions.cs index 55f1f4b8d7..7f34f12b07 100644 --- a/src/AElf.Kernel.FeeCalculation/Extensions/TransactionResultExtensions.cs +++ b/src/AElf.Kernel.FeeCalculation/Extensions/TransactionResultExtensions.cs @@ -3,32 +3,31 @@ using AElf.Contracts.MultiToken; using AElf.Types; -namespace AElf.Kernel.FeeCalculation.Extensions +namespace AElf.Kernel.FeeCalculation.Extensions; + +public static class TransactionResultExtensions { - public static class TransactionResultExtensions + public static Dictionary GetChargedTransactionFees(this TransactionResult transactionResult) { - public static Dictionary GetChargedTransactionFees(this TransactionResult transactionResult) - { - var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(TransactionFeeCharged)).ToList(); - if (!relatedLogs.Any()) return new Dictionary(); - return relatedLogs.Select(l => TransactionFeeCharged.Parser.ParseFrom(l.NonIndexed)) - .ToDictionary(e => e.Symbol, e => e.Amount); - } + var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(TransactionFeeCharged)).ToList(); + if (!relatedLogs.Any()) return new Dictionary(); + return relatedLogs.Select(l => TransactionFeeCharged.Parser.ParseFrom(l.NonIndexed)) + .ToDictionary(e => e.Symbol, e => e.Amount); + } - public static Dictionary GetConsumedResourceTokens(this TransactionResult transactionResult) - { - var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ResourceTokenCharged)).ToList(); - if (!relatedLogs.Any()) return new Dictionary(); - return relatedLogs.Select(l => ResourceTokenCharged.Parser.ParseFrom(l.NonIndexed)) - .ToDictionary(e => e.Symbol, e => e.Amount); - } + public static Dictionary GetConsumedResourceTokens(this TransactionResult transactionResult) + { + var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ResourceTokenCharged)).ToList(); + if (!relatedLogs.Any()) return new Dictionary(); + return relatedLogs.Select(l => ResourceTokenCharged.Parser.ParseFrom(l.NonIndexed)) + .ToDictionary(e => e.Symbol, e => e.Amount); + } - public static Dictionary GetOwningResourceTokens(this TransactionResult transactionResult) - { - var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ResourceTokenOwned)).ToList(); - if (!relatedLogs.Any()) return new Dictionary(); - return relatedLogs.Select(l => ResourceTokenOwned.Parser.ParseFrom(l.NonIndexed)) - .ToDictionary(e => e.Symbol, e => e.Amount); - } + public static Dictionary GetOwningResourceTokens(this TransactionResult transactionResult) + { + var relatedLogs = transactionResult.Logs.Where(l => l.Name == nameof(ResourceTokenOwned)).ToList(); + if (!relatedLogs.Any()) return new Dictionary(); + return relatedLogs.Select(l => ResourceTokenOwned.Parser.ParseFrom(l.NonIndexed)) + .ToDictionary(e => e.Symbol, e => e.Amount); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/FeeCalculationModule.cs b/src/AElf.Kernel.FeeCalculation/FeeCalculationModule.cs index 200f37fa6e..1d8f3868fb 100644 --- a/src/AElf.Kernel.FeeCalculation/FeeCalculationModule.cs +++ b/src/AElf.Kernel.FeeCalculation/FeeCalculationModule.cs @@ -6,27 +6,26 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.FeeCalculation +namespace AElf.Kernel.FeeCalculation; + +public class FeeCalculationModule : AElfModule { - public class FeeCalculationModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services - .AddSingleton(); - services - .AddSingleton>, - CalculateFunctionExecutedDataService>(); - } + var services = context.Services; + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services + .AddSingleton(); + services + .AddSingleton>, + CalculateFunctionExecutedDataService>(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/CalculateFunction.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/CalculateFunction.cs index 848cae00de..7eeb4c8127 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/CalculateFunction.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/CalculateFunction.cs @@ -2,64 +2,58 @@ using System.Collections.Generic; using AElf.Contracts.MultiToken; -namespace AElf.Kernel.FeeCalculation.Infrastructure -{ - public class CalculateFunction - { - private readonly List> _currentCalculateFunctions = new List>(); +namespace AElf.Kernel.FeeCalculation.Infrastructure; - /// - /// Use this property to cache CalculateFeeCoefficients message. - /// - internal CalculateFeeCoefficients CalculateFeeCoefficients { get; set; } +public class CalculateFunction +{ + private readonly List> _currentCalculateFunctions = new(); - public CalculateFunction(int feeType) + public CalculateFunction(int feeType) + { + CalculateFeeCoefficients = new CalculateFeeCoefficients { - CalculateFeeCoefficients = new CalculateFeeCoefficients - { - FeeTokenType = feeType - }; - } + FeeTokenType = feeType + }; + } - public void AddFunction(IEnumerable coefficients, Func function) - { - _currentCalculateFunctions.Add(function); + /// + /// Use this property to cache CalculateFeeCoefficients message. + /// + internal CalculateFeeCoefficients CalculateFeeCoefficients { get; set; } - CalculateFeeCoefficients.PieceCoefficientsList.Add(new CalculateFeePieceCoefficients - { - Value = {coefficients} - }); - } + public void AddFunction(IEnumerable coefficients, Func function) + { + _currentCalculateFunctions.Add(function); - public long CalculateFee(int totalCount) + CalculateFeeCoefficients.PieceCoefficientsList.Add(new CalculateFeePieceCoefficients { - if (CalculateFeeCoefficients.PieceCoefficientsList.Count != _currentCalculateFunctions.Count) - { - throw new ArgumentOutOfRangeException(nameof(_currentCalculateFunctions), - "Coefficients count not match."); - } - - var remainCount = totalCount; - var result = 0L; - var pieceStart = 0; - for (var i = 0; i < _currentCalculateFunctions.Count; i++) - { - var function = _currentCalculateFunctions[i]; - var pieceCoefficient = CalculateFeeCoefficients.PieceCoefficientsList[i].Value; - var pieceUpperBound = pieceCoefficient[0]; - var interval = pieceUpperBound - pieceStart; - pieceStart = pieceUpperBound; - var count = Math.Min(interval, remainCount); - result += function(count); - if (pieceUpperBound > totalCount) - { - break; - } - - remainCount -= interval; - } + Value = { coefficients } + }); + } - return result; + public long CalculateFee(int totalCount) + { + if (CalculateFeeCoefficients.PieceCoefficientsList.Count != _currentCalculateFunctions.Count) + throw new ArgumentOutOfRangeException(nameof(_currentCalculateFunctions), + "Coefficients count not match."); + + var remainCount = totalCount; + var result = 0L; + var pieceStart = 0; + for (var i = 0; i < _currentCalculateFunctions.Count; i++) + { + var function = _currentCalculateFunctions[i]; + var pieceCoefficient = CalculateFeeCoefficients.PieceCoefficientsList[i].Value; + var pieceUpperBound = pieceCoefficient[0]; + var interval = pieceUpperBound - pieceStart; + pieceStart = pieceUpperBound; + var count = Math.Min(interval, remainCount); + result += function(count); + if (pieceUpperBound > totalCount) break; + + remainCount -= interval; } + + return result; } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/ICalculateFunctionProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/ICalculateFunctionProvider.cs index 2a4a7ef9a3..5e1235ed35 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/ICalculateFunctionProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/ICalculateFunctionProvider.cs @@ -2,46 +2,44 @@ using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.FeeCalculation.Extensions; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +/// +/// To provide basic function for piece-wise function. +/// +public interface ICalculateFunctionProvider +{ + Task AddCalculateFunctions(IBlockIndex blockIndex, + Dictionary calculateFunctionDictionary); + + Dictionary GetCalculateFunctions(IChainContext chainContext); +} + +public class CalculateFunctionProvider : BlockExecutedDataBaseProvider>, + ICalculateFunctionProvider, ISingletonDependency { - /// - /// To provide basic function for piece-wise function. - /// - public interface ICalculateFunctionProvider + private const string BlockExecutedDataName = nameof(AllCalculateFeeCoefficients); + + public CalculateFunctionProvider(ICachedBlockchainExecutedDataService> + calculateFunctionExecutedDataService) : base(calculateFunctionExecutedDataService) + { + } + + public async Task AddCalculateFunctions(IBlockIndex blockIndex, + Dictionary calculateFunctionDictionary) + { + await AddBlockExecutedDataAsync(blockIndex, calculateFunctionDictionary); + } + + public Dictionary GetCalculateFunctions(IChainContext chainContext) { - Task AddCalculateFunctions(IBlockIndex blockIndex, Dictionary calculateFunctionDictionary); - Dictionary GetCalculateFunctions(IChainContext chainContext); + return GetBlockExecutedData(chainContext); } - public class CalculateFunctionProvider : BlockExecutedDataBaseProvider>, ICalculateFunctionProvider, ISingletonDependency + protected override string GetBlockExecutedDataName() { - public CalculateFunctionProvider(ICachedBlockchainExecutedDataService> - calculateFunctionExecutedDataService) : base(calculateFunctionExecutedDataService) - { - } - - public async Task AddCalculateFunctions(IBlockIndex blockIndex, - Dictionary calculateFunctionDictionary) - { - await AddBlockExecutedDataAsync(blockIndex, calculateFunctionDictionary); - } - - public Dictionary GetCalculateFunctions(IChainContext chainContext) - { - return GetBlockExecutedData(chainContext); - } - - private const string BlockExecutedDataName = nameof(AllCalculateFeeCoefficients); - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/IFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/IFeeProvider.cs index de0d5f09f5..6484d2aa8c 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/IFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/IFeeProvider.cs @@ -1,23 +1,21 @@ -using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +public interface IFeeProvider { - public interface IFeeProvider - { - Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext); - } + Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext); +} - public interface IPrimaryTokenFeeProvider : IFeeProvider - { - } +public interface IPrimaryTokenFeeProvider : IFeeProvider +{ +} - public interface IResourceTokenFeeProvider : IFeeProvider - { - /// - /// To identify provider for specific resource token symbol. - /// - string TokenName { get; } - } +public interface IResourceTokenFeeProvider : IFeeProvider +{ + /// + /// To identify provider for specific resource token symbol. + /// + string TokenName { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/ReadFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/ReadFeeProvider.cs index 9dbfba2480..6ceda08265 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/ReadFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/ReadFeeProvider.cs @@ -1,21 +1,19 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal class ReadFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider { - internal class ReadFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider + public ReadFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( + calculateFunctionProvider, (int)FeeTypeEnum.Read) { - public ReadFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( - calculateFunctionProvider, (int) FeeTypeEnum.Read) - { - - } + } - public string TokenName => "READ"; + public string TokenName => "READ"; - protected override int GetCalculateCount(ITransactionContext transactionContext) - { - return transactionContext.Trace.StateSet.Reads.Count; - } + protected override int GetCalculateCount(ITransactionContext transactionContext) + { + return transactionContext.Trace.StateSet.Reads.Count; } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/StorageFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/StorageFeeProvider.cs index 93d0ed368d..b70396c76b 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/StorageFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/StorageFeeProvider.cs @@ -1,21 +1,19 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal class StorageFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider { - internal class StorageFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider + public StorageFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( + calculateFunctionProvider, (int)FeeTypeEnum.Storage) { - public StorageFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( - calculateFunctionProvider, (int) FeeTypeEnum.Storage) - { - - } + } - public string TokenName => "STORAGE"; + public string TokenName => "STORAGE"; - protected override int GetCalculateCount(ITransactionContext transactionContext) - { - return transactionContext.Transaction.Size(); - } + protected override int GetCalculateCount(ITransactionContext transactionContext) + { + return transactionContext.Transaction.Size(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/TokenFeeProviderBase.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/TokenFeeProviderBase.cs index 8dca39902f..cb9acb7af9 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/TokenFeeProviderBase.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/TokenFeeProviderBase.cs @@ -5,35 +5,36 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal abstract class TokenFeeProviderBase { - internal abstract class TokenFeeProviderBase + private readonly ICalculateFunctionProvider _calculateFunctionProvider; + private readonly int _tokenType; + + protected TokenFeeProviderBase(ICalculateFunctionProvider calculateFunctionProvider, int tokenType) { - private readonly ICalculateFunctionProvider _calculateFunctionProvider; - private readonly int _tokenType; - public ILogger Logger { get; set; } + _tokenType = tokenType; + _calculateFunctionProvider = calculateFunctionProvider; + Logger = NullLogger.Instance; + } - protected TokenFeeProviderBase(ICalculateFunctionProvider calculateFunctionProvider, int tokenType) - { - _tokenType = tokenType; - _calculateFunctionProvider = calculateFunctionProvider; - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext) + public Task CalculateFeeAsync(ITransactionContext transactionContext, IChainContext chainContext) + { + var functionDictionary = _calculateFunctionProvider.GetCalculateFunctions(chainContext); + var targetKey = ((FeeTypeEnum)_tokenType).ToString().ToUpper(); + if (!functionDictionary.ContainsKey(targetKey)) { - var functionDictionary = _calculateFunctionProvider.GetCalculateFunctions(chainContext); - var targetKey = ((FeeTypeEnum) _tokenType).ToString().ToUpper(); - if (!functionDictionary.ContainsKey(targetKey)) - { - var currentKeys = string.Join(" ", functionDictionary.Keys); - throw new InvalidOperationException($"Function not found. Current keys: {currentKeys}"); - } - var function = functionDictionary[targetKey]; - var count = GetCalculateCount(transactionContext); - return Task.FromResult(function.CalculateFee(count)); + var currentKeys = string.Join(" ", functionDictionary.Keys); + throw new InvalidOperationException($"Function not found. Current keys: {currentKeys}"); } - protected abstract int GetCalculateCount(ITransactionContext transactionContext); + var function = functionDictionary[targetKey]; + var count = GetCalculateCount(transactionContext); + return Task.FromResult(function.CalculateFee(count)); } + + protected abstract int GetCalculateCount(ITransactionContext transactionContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/TrafficFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/TrafficFeeProvider.cs index 1d58564f39..569b7a193b 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/TrafficFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/TrafficFeeProvider.cs @@ -1,21 +1,19 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal class TrafficFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider { - internal class TrafficFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider + public TrafficFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( + calculateFunctionProvider, (int)FeeTypeEnum.Traffic) { - public TrafficFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( - calculateFunctionProvider, (int) FeeTypeEnum.Traffic) - { - - } + } - public string TokenName => "TRAFFIC"; + public string TokenName => "TRAFFIC"; - protected override int GetCalculateCount(ITransactionContext transactionContext) - { - return transactionContext.Transaction.Size(); - } + protected override int GetCalculateCount(ITransactionContext transactionContext) + { + return transactionContext.Transaction.Size(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/TxFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/TxFeeProvider.cs index ca1a2b21aa..34494a8f83 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/TxFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/TxFeeProvider.cs @@ -1,19 +1,17 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal class TxFeeProvider : TokenFeeProviderBase, IPrimaryTokenFeeProvider { - internal class TxFeeProvider : TokenFeeProviderBase, IPrimaryTokenFeeProvider + public TxFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( + calculateFunctionProvider, (int)FeeTypeEnum.Tx) { - public TxFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( - calculateFunctionProvider, (int) FeeTypeEnum.Tx) - { - - } + } - protected override int GetCalculateCount(ITransactionContext transactionContext) - { - return transactionContext.Transaction.Size(); - } + protected override int GetCalculateCount(ITransactionContext transactionContext) + { + return transactionContext.Transaction.Size(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.FeeCalculation/Infrastructure/WriteFeeProvider.cs b/src/AElf.Kernel.FeeCalculation/Infrastructure/WriteFeeProvider.cs index ee2a1c62f3..3a69c7a65d 100644 --- a/src/AElf.Kernel.FeeCalculation/Infrastructure/WriteFeeProvider.cs +++ b/src/AElf.Kernel.FeeCalculation/Infrastructure/WriteFeeProvider.cs @@ -1,21 +1,19 @@ using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +internal class WriteFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider { - internal class WriteFeeProvider : TokenFeeProviderBase, IResourceTokenFeeProvider + public WriteFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( + calculateFunctionProvider, (int)FeeTypeEnum.Write) { - public WriteFeeProvider(ICalculateFunctionProvider calculateFunctionProvider) : base( - calculateFunctionProvider, (int) FeeTypeEnum.Write) - { - - } + } - public string TokenName => "WRITE"; + public string TokenName => "WRITE"; - protected override int GetCalculateCount(ITransactionContext transactionContext) - { - return transactionContext.Trace.StateSet.Writes.Count; - } + protected override int GetCalculateCount(ITransactionContext transactionContext) + { + return transactionContext.Trace.StateSet.Writes.Count; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Node/AElf.Kernel.Node.csproj b/src/AElf.Kernel.Node/AElf.Kernel.Node.csproj index ae5f4dd0cb..886b346a0a 100644 --- a/src/AElf.Kernel.Node/AElf.Kernel.Node.csproj +++ b/src/AElf.Kernel.Node/AElf.Kernel.Node.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,9 +9,9 @@ - - - + + + diff --git a/src/AElf.Kernel.Node/Application/IBlockchainNodeContextService.cs b/src/AElf.Kernel.Node/Application/IBlockchainNodeContextService.cs index e33393c769..9f9965b3c6 100644 --- a/src/AElf.Kernel.Node/Application/IBlockchainNodeContextService.cs +++ b/src/AElf.Kernel.Node/Application/IBlockchainNodeContextService.cs @@ -3,85 +3,82 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.ChainController.Application; using AElf.Kernel.Consensus.Application; -using AElf.Kernel.Node.Events; using AElf.Kernel.Node.Domain; +using AElf.Kernel.Node.Events; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Kernel.TransactionPool.Application; using AElf.Types; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Node.Application +namespace AElf.Kernel.Node.Application; + +public class BlockchainNodeContextStartDto { - public class BlockchainNodeContextStartDto - { - public int ChainId { get; set; } + public int ChainId { get; set; } - public Transaction[] Transactions { get; set; } + public Transaction[] Transactions { get; set; } - public Type ZeroSmartContractType { get; set; } - } + public Type ZeroSmartContractType { get; set; } +} - public interface IBlockchainNodeContextService - { - Task StartAsync(BlockchainNodeContextStartDto dto); +public interface IBlockchainNodeContextService +{ + Task StartAsync(BlockchainNodeContextStartDto dto); + + Task StopAsync(BlockchainNodeContext blockchainNodeContext); - Task StopAsync(BlockchainNodeContext blockchainNodeContext); + Task FinishInitialSyncAsync(); +} - Task FinishInitialSyncAsync(); +//Maybe we should call it CSharpBlockchainNodeContextService, or we should spilt the logic depended on CSharp +public class BlockchainNodeContextService : IBlockchainNodeContextService +{ + private readonly IBlockchainService _blockchainService; + private readonly IChainCreationService _chainCreationService; + private readonly IConsensusService _consensusService; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + + public BlockchainNodeContextService( + IBlockchainService blockchainService, IChainCreationService chainCreationService, + IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, IConsensusService consensusService) + { + _blockchainService = blockchainService; + _chainCreationService = chainCreationService; + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + _consensusService = consensusService; + + EventBus = NullLocalEventBus.Instance; } + public ILocalEventBus EventBus { get; set; } - //Maybe we should call it CSharpBlockchainNodeContextService, or we should spilt the logic depended on CSharp - public class BlockchainNodeContextService : IBlockchainNodeContextService + public async Task StartAsync(BlockchainNodeContextStartDto dto) { - private readonly IBlockchainService _blockchainService; - private readonly IChainCreationService _chainCreationService; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly IConsensusService _consensusService; + _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(dto.ZeroSmartContractType); - public ILocalEventBus EventBus { get; set; } + var chain = await _blockchainService.GetChainAsync(); + chain = chain == null + ? await _chainCreationService.CreateNewChainAsync(dto.Transactions) + : await _blockchainService.ResetChainToLibAsync(chain); - public BlockchainNodeContextService( - IBlockchainService blockchainService, IChainCreationService chainCreationService, - IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, IConsensusService consensusService) + await _consensusService.TriggerConsensusAsync(new ChainContext { - _blockchainService = blockchainService; - _chainCreationService = chainCreationService; - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - _consensusService = consensusService; - - EventBus = NullLocalEventBus.Instance; - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }); - public async Task StartAsync(BlockchainNodeContextStartDto dto) - { - _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(dto.ZeroSmartContractType); - - var chain = await _blockchainService.GetChainAsync(); - chain = chain == null - ? await _chainCreationService.CreateNewChainAsync(dto.Transactions) - : await _blockchainService.ResetChainToLibAsync(chain); - - await _consensusService.TriggerConsensusAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }); - - return new BlockchainNodeContext - { - ChainId = chain.Id, - }; - } - - public async Task FinishInitialSyncAsync() + return new BlockchainNodeContext { - await EventBus.PublishAsync(new InitialSyncFinishedEvent()); - } + ChainId = chain.Id + }; + } - public Task StopAsync(BlockchainNodeContext blockchainNodeContext) - { - return Task.CompletedTask; - } + public async Task FinishInitialSyncAsync() + { + await EventBus.PublishAsync(new InitialSyncFinishedEvent()); + } + + public Task StopAsync(BlockchainNodeContext blockchainNodeContext) + { + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Node/Domain/BlockchainNodeContext.cs b/src/AElf.Kernel.Node/Domain/BlockchainNodeContext.cs index 055e666a9c..8310051f19 100644 --- a/src/AElf.Kernel.Node/Domain/BlockchainNodeContext.cs +++ b/src/AElf.Kernel.Node/Domain/BlockchainNodeContext.cs @@ -1,9 +1,6 @@ -using AElf.Kernel.TransactionPool.Application; +namespace AElf.Kernel.Node.Domain; -namespace AElf.Kernel.Node.Domain +public class BlockchainNodeContext { - public class BlockchainNodeContext - { - public int ChainId { get; set; } - } + public int ChainId { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Node/Events/InitialSyncFinishedEvent.cs b/src/AElf.Kernel.Node/Events/InitialSyncFinishedEvent.cs index 1ef4f9799d..9d401f9c66 100644 --- a/src/AElf.Kernel.Node/Events/InitialSyncFinishedEvent.cs +++ b/src/AElf.Kernel.Node/Events/InitialSyncFinishedEvent.cs @@ -1,6 +1,5 @@ -namespace AElf.Kernel.Node.Events +namespace AElf.Kernel.Node.Events; + +public class InitialSyncFinishedEvent { - public class InitialSyncFinishedEvent - { - } } \ No newline at end of file diff --git a/src/AElf.Kernel.Node/Infrastructure/INodePlugin.cs b/src/AElf.Kernel.Node/Infrastructure/INodePlugin.cs index a08e24e8eb..fc529e242b 100644 --- a/src/AElf.Kernel.Node/Infrastructure/INodePlugin.cs +++ b/src/AElf.Kernel.Node/Infrastructure/INodePlugin.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; -namespace AElf.Kernel.Node.Infrastructure +namespace AElf.Kernel.Node.Infrastructure; + +public interface INodePlugin { - public interface INodePlugin - { - Task StartAsync(int chainId); - Task ShutdownAsync(); - } + Task StartAsync(int chainId); + Task ShutdownAsync(); } \ No newline at end of file diff --git a/src/AElf.Kernel.Node/NodeAElfModule.cs b/src/AElf.Kernel.Node/NodeAElfModule.cs index 7db11db283..006aabffc1 100644 --- a/src/AElf.Kernel.Node/NodeAElfModule.cs +++ b/src/AElf.Kernel.Node/NodeAElfModule.cs @@ -3,13 +3,12 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Kernel.Node +namespace AElf.Kernel.Node; + +[DependsOn(typeof(CoreKernelAElfModule), typeof(TransactionPoolAElfModule), typeof(ChainControllerAElfModule))] +public class NodeAElfModule : AElfModule { - [DependsOn(typeof(CoreKernelAElfModule), typeof(TransactionPoolAElfModule), typeof(ChainControllerAElfModule))] - public class NodeAElfModule: AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/AElf.Kernel.Proposal.csproj b/src/AElf.Kernel.Proposal/AElf.Kernel.Proposal.csproj index 0f5e5e6acc..417f66fc5f 100644 --- a/src/AElf.Kernel.Proposal/AElf.Kernel.Proposal.csproj +++ b/src/AElf.Kernel.Proposal/AElf.Kernel.Proposal.csproj @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\acs1.proto diff --git a/src/AElf.Kernel.Proposal/Application/IProposalService.cs b/src/AElf.Kernel.Proposal/Application/IProposalService.cs index de23bd439c..4c40c590af 100644 --- a/src/AElf.Kernel.Proposal/Application/IProposalService.cs +++ b/src/AElf.Kernel.Proposal/Application/IProposalService.cs @@ -2,12 +2,11 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.Proposal.Application +namespace AElf.Kernel.Proposal.Application; + +public interface IProposalService { - public interface IProposalService - { - void AddNotApprovedProposal(Hash proposalId, long height); - Task> GetNotApprovedProposalIdListAsync(Address @from, Hash blockHash, long blockHeight); - Task ClearProposalByLibAsync(Hash blockHash, long blockHeight); - } + void AddNotApprovedProposal(Hash proposalId, long height); + Task> GetNotApprovedProposalIdListAsync(Address from, Hash blockHash, long blockHeight); + Task ClearProposalByLibAsync(Hash blockHash, long blockHeight); } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/Application/ProposalApprovalTransactionGenerator.cs b/src/AElf.Kernel.Proposal/Application/ProposalApprovalTransactionGenerator.cs index bee817b2ca..9f670a5e5d 100644 --- a/src/AElf.Kernel.Proposal/Application/ProposalApprovalTransactionGenerator.cs +++ b/src/AElf.Kernel.Proposal/Application/ProposalApprovalTransactionGenerator.cs @@ -9,68 +9,64 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Proposal.Application +namespace AElf.Kernel.Proposal.Application; + +public class ProposalApprovalTransactionGenerator : ISystemTransactionGenerator { - public class ProposalApprovalTransactionGenerator : ISystemTransactionGenerator - { - private readonly IProposalService _proposalService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + private readonly IProposalService _proposalService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - public ILogger Logger { get; set; } + public ProposalApprovalTransactionGenerator(IProposalService proposalService, + ISmartContractAddressService smartContractAddressService, + ITransactionPackingOptionProvider transactionPackingOptionProvider) + { + _proposalService = proposalService; + _smartContractAddressService = smartContractAddressService; + _transactionPackingOptionProvider = transactionPackingOptionProvider; - public ProposalApprovalTransactionGenerator(IProposalService proposalService, - ISmartContractAddressService smartContractAddressService, - ITransactionPackingOptionProvider transactionPackingOptionProvider) - { - _proposalService = proposalService; - _smartContractAddressService = smartContractAddressService; - _transactionPackingOptionProvider = transactionPackingOptionProvider; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, - Hash preBlockHash) + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + var generatedTransactions = new List(); + var chainContext = new ChainContext { - var generatedTransactions = new List(); - var chainContext = new ChainContext - { - BlockHash = preBlockHash, BlockHeight = preBlockHeight - }; - if (!_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) - return generatedTransactions; + BlockHash = preBlockHash, BlockHeight = preBlockHeight + }; + if (!_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) + return generatedTransactions; - var parliamentContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( - chainContext, ParliamentSmartContractAddressNameProvider.StringName); + var parliamentContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( + chainContext, ParliamentSmartContractAddressNameProvider.StringName); - if (parliamentContractAddress == null) - { - return generatedTransactions; - } + if (parliamentContractAddress == null) return generatedTransactions; - var proposalIdList = - await _proposalService.GetNotApprovedProposalIdListAsync(from, preBlockHash, preBlockHeight); - if (proposalIdList == null || proposalIdList.Count == 0) - return generatedTransactions; + var proposalIdList = + await _proposalService.GetNotApprovedProposalIdListAsync(from, preBlockHash, preBlockHeight); + if (proposalIdList == null || proposalIdList.Count == 0) + return generatedTransactions; - var generatedTransaction = new Transaction + var generatedTransaction = new Transaction + { + From = from, + MethodName = nameof(ParliamentContractContainer.ParliamentContractStub.ApproveMultiProposals), + To = parliamentContractAddress, + RefBlockNumber = preBlockHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), + Params = new ProposalIdList { - From = from, - MethodName = nameof(ParliamentContractContainer.ParliamentContractStub.ApproveMultiProposals), - To = parliamentContractAddress, - RefBlockNumber = preBlockHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), - Params = new ProposalIdList - { - ProposalIds = {proposalIdList} - }.ToByteString() - }; - generatedTransactions.Add(generatedTransaction); - - Logger.LogTrace("Proposal approval transaction generated."); + ProposalIds = { proposalIdList } + }.ToByteString() + }; + generatedTransactions.Add(generatedTransaction); - return generatedTransactions; - } + Logger.LogTrace("Proposal approval transaction generated."); + + return generatedTransactions; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/Application/ProposalService.cs b/src/AElf.Kernel.Proposal/Application/ProposalService.cs index 8c1e009e0e..7ca3d3c5a1 100644 --- a/src/AElf.Kernel.Proposal/Application/ProposalService.cs +++ b/src/AElf.Kernel.Proposal/Application/ProposalService.cs @@ -8,42 +8,54 @@ using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Proposal.Application +namespace AElf.Kernel.Proposal.Application; + +internal class ProposalService : IProposalService, ITransientDependency { - internal class ProposalService : IProposalService, ITransientDependency - { - private readonly IProposalProvider _proposalProvider; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IContractReaderFactory + _contractReaderFactory; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly IProposalProvider _proposalProvider; + private readonly ISmartContractAddressService _smartContractAddressService; - public ILogger Logger { get; set; } + public ProposalService(IProposalProvider proposalProvider, + ISmartContractAddressService smartContractAddressService, + IContractReaderFactory contractReaderFactory) + { + _proposalProvider = proposalProvider; + _smartContractAddressService = smartContractAddressService; + _contractReaderFactory = contractReaderFactory; + } - private Task
GetParliamentContractAddressAsync(IChainContext chainContext) - { - return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - ParliamentSmartContractAddressNameProvider.StringName); - } + public ILogger Logger { get; set; } - public ProposalService(IProposalProvider proposalProvider, - ISmartContractAddressService smartContractAddressService, - IContractReaderFactory contractReaderFactory) - { - _proposalProvider = proposalProvider; - _smartContractAddressService = smartContractAddressService; - _contractReaderFactory = contractReaderFactory; - } + public void AddNotApprovedProposal(Hash proposalId, long height) + { + _proposalProvider.AddProposal(proposalId, height); + } - public void AddNotApprovedProposal(Hash proposalId, long height) + public async Task> GetNotApprovedProposalIdListAsync(Address from, Hash blockHash, long blockHeight) + { + var proposalIdList = _proposalProvider.GetAllProposals(); + var result = await _contractReaderFactory.Create(new ContractReaderContext { - _proposalProvider.AddProposal(proposalId, height); - } + BlockHash = blockHash, + BlockHeight = blockHeight, + ContractAddress = await GetParliamentContractAddressAsync(new ChainContext + { + BlockHash = blockHash, + BlockHeight = blockHeight + }), + Sender = from + }).GetNotVotedProposals.CallAsync(new ProposalIdList { ProposalIds = { proposalIdList } }); - public async Task> GetNotApprovedProposalIdListAsync(Address @from, Hash blockHash, long blockHeight) - { - var proposalIdList = _proposalProvider.GetAllProposals(); - var result = await _contractReaderFactory.Create(new ContractReaderContext + return result?.ProposalIds.ToList(); + } + + public async Task ClearProposalByLibAsync(Hash blockHash, long blockHeight) + { + var proposalIdList = _proposalProvider.GetAllProposals(); + var result = await _contractReaderFactory.Create(new ContractReaderContext { BlockHash = blockHash, BlockHeight = blockHeight, @@ -51,39 +63,26 @@ public async Task> GetNotApprovedProposalIdListAsync(Address @from, H { BlockHash = blockHash, BlockHeight = blockHeight - }), - Sender = from - }).GetNotVotedProposals.CallAsync(new ProposalIdList {ProposalIds = {proposalIdList}}); + }) + }).GetNotVotedPendingProposals + .CallAsync(new ProposalIdList { ProposalIds = { proposalIdList } }); - return result?.ProposalIds.ToList(); - } + if (result == null) + return; - public async Task ClearProposalByLibAsync(Hash blockHash, long blockHeight) + foreach (var proposalId in proposalIdList.Except(result.ProposalIds)) { - var proposalIdList = _proposalProvider.GetAllProposals(); - var result = await _contractReaderFactory.Create(new ContractReaderContext - { - BlockHash = blockHash, - BlockHeight = blockHeight, - ContractAddress = await GetParliamentContractAddressAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }) - }).GetNotVotedPendingProposals - .CallAsync(new ProposalIdList {ProposalIds = {proposalIdList}}); - - if (result == null) - return; - - foreach (var proposalId in proposalIdList.Except(result.ProposalIds)) - { - if (!_proposalProvider.TryGetProposalCreatedHeight(proposalId, out var h) || - h > blockHeight) - continue; - Logger.LogDebug($"Clear proposal {proposalId} by LIB hash {blockHash}, height {blockHeight}"); - _proposalProvider.RemoveProposalById(proposalId); - } + if (!_proposalProvider.TryGetProposalCreatedHeight(proposalId, out var h) || + h > blockHeight) + continue; + Logger.LogDebug($"Clear proposal {proposalId} by LIB hash {blockHash}, height {blockHeight}"); + _proposalProvider.RemoveProposalById(proposalId); } } + + private Task
GetParliamentContractAddressAsync(IChainContext chainContext) + { + return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + ParliamentSmartContractAddressNameProvider.StringName); + } } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/Infrastructure/IProposalProvider.cs b/src/AElf.Kernel.Proposal/Infrastructure/IProposalProvider.cs index 017394c769..ac218e8c96 100644 --- a/src/AElf.Kernel.Proposal/Infrastructure/IProposalProvider.cs +++ b/src/AElf.Kernel.Proposal/Infrastructure/IProposalProvider.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.Proposal.Infrastructure +namespace AElf.Kernel.Proposal.Infrastructure; + +public interface IProposalProvider { - public interface IProposalProvider - { - void AddProposal(Hash proposalId, long height); - List GetAllProposals(); - bool TryGetProposalCreatedHeight(Hash proposalId, out long height); - void RemoveProposalById(Hash proposalId); - } -} + void AddProposal(Hash proposalId, long height); + List GetAllProposals(); + bool TryGetProposalCreatedHeight(Hash proposalId, out long height); + void RemoveProposalById(Hash proposalId); +} \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/Infrastructure/ProposalProvider.cs b/src/AElf.Kernel.Proposal/Infrastructure/ProposalProvider.cs index 111db56a4e..bc3fe5e0bc 100644 --- a/src/AElf.Kernel.Proposal/Infrastructure/ProposalProvider.cs +++ b/src/AElf.Kernel.Proposal/Infrastructure/ProposalProvider.cs @@ -3,31 +3,30 @@ using System.Linq; using AElf.Types; -namespace AElf.Kernel.Proposal.Infrastructure +namespace AElf.Kernel.Proposal.Infrastructure; + +public class ProposalProvider : IProposalProvider { - public class ProposalProvider : IProposalProvider + private readonly ConcurrentDictionary _proposalsToApprove = new(); + + public void AddProposal(Hash proposalId, long height) { - private readonly ConcurrentDictionary _proposalsToApprove = new ConcurrentDictionary(); - - public void AddProposal(Hash proposalId, long height) - { - // keep the higher block index - _proposalsToApprove.AddOrUpdate(proposalId, height, (hash, h) => h >= height ? h : height); - } + // keep the higher block index + _proposalsToApprove.AddOrUpdate(proposalId, height, (hash, h) => h >= height ? h : height); + } - public List GetAllProposals() - { - return _proposalsToApprove.Keys.ToList(); - } + public List GetAllProposals() + { + return _proposalsToApprove.Keys.ToList(); + } - public bool TryGetProposalCreatedHeight(Hash proposalId, out long height) - { - return _proposalsToApprove.TryGetValue(proposalId, out height); - } + public bool TryGetProposalCreatedHeight(Hash proposalId, out long height) + { + return _proposalsToApprove.TryGetValue(proposalId, out height); + } - public void RemoveProposalById(Hash proposalId) - { - _proposalsToApprove.TryRemove(proposalId, out _); - } + public void RemoveProposalById(Hash proposalId) + { + _proposalsToApprove.TryRemove(proposalId, out _); } -} +} \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/NewIrreversibleBlockFoundEventHandler.cs b/src/AElf.Kernel.Proposal/NewIrreversibleBlockFoundEventHandler.cs index ef05fe7c85..de686720d3 100644 --- a/src/AElf.Kernel.Proposal/NewIrreversibleBlockFoundEventHandler.cs +++ b/src/AElf.Kernel.Proposal/NewIrreversibleBlockFoundEventHandler.cs @@ -4,21 +4,20 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.Proposal +namespace AElf.Kernel.Proposal; + +public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, + ITransientDependency { - public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, - ITransientDependency - { - private readonly IProposalService _proposalService; + private readonly IProposalService _proposalService; - public NewIrreversibleBlockFoundEventHandler(IProposalService proposalService) - { - _proposalService = proposalService; - } + public NewIrreversibleBlockFoundEventHandler(IProposalService proposalService) + { + _proposalService = proposalService; + } - public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) - { - await _proposalService.ClearProposalByLibAsync(eventData.BlockHash, eventData.BlockHeight); - } + public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + await _proposalService.ClearProposalByLibAsync(eventData.BlockHash, eventData.BlockHeight); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/ParliamentSmartContractAddressNameProvider.cs b/src/AElf.Kernel.Proposal/ParliamentSmartContractAddressNameProvider.cs index c3fc58aa92..2bfc47de7f 100644 --- a/src/AElf.Kernel.Proposal/ParliamentSmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.Proposal/ParliamentSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Proposal +namespace AElf.Kernel.Proposal; + +public class ParliamentSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ParliamentSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.Proposal/ProposalAElfModule.cs b/src/AElf.Kernel.Proposal/ProposalAElfModule.cs index 8de7ae5406..2635b33852 100644 --- a/src/AElf.Kernel.Proposal/ProposalAElfModule.cs +++ b/src/AElf.Kernel.Proposal/ProposalAElfModule.cs @@ -1,19 +1,17 @@ using AElf.Kernel.Miner.Application; using AElf.Kernel.Proposal.Application; using AElf.Kernel.Proposal.Infrastructure; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.Proposal +namespace AElf.Kernel.Proposal; + +public class ProposalAElfModule : AElfModule { - public class ProposalAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services.AddSingleton(); - } + context.Services.AddTransient(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj index 0b18cfe672..8fa28f5c0b 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,8 +9,8 @@ - - + + diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/CheckThresholdExecutionPlugin.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/CheckThresholdExecutionPlugin.cs index a661127cf4..ce5b2c45e9 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/CheckThresholdExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/CheckThresholdExecutionPlugin.cs @@ -1,98 +1,92 @@ -using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS5; using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; +using AElf.Standards.ACS5; using AElf.Types; using Google.Protobuf; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold; + +internal class MethodCallingThresholdPreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, + ISingletonDependency { - internal class MethodCallingThresholdPreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, ISingletonDependency + private readonly ISmartContractAddressService _smartContractAddressService; + + private readonly IContractReaderFactory + _thresholdSettingContractReaderFactory; + + private readonly IContractReaderFactory + _tokenContractReaderFactory; + + public MethodCallingThresholdPreExecutionPlugin( + IContractReaderFactory + thresholdSettingContractReaderFactory, + IContractReaderFactory tokenContractReaderFactory, + ISmartContractAddressService smartContractAddressService) : base("acs5") { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IContractReaderFactory - _thresholdSettingContractReaderFactory; - private readonly IContractReaderFactory - _tokenContractReaderFactory; + _thresholdSettingContractReaderFactory = thresholdSettingContractReaderFactory; + _tokenContractReaderFactory = tokenContractReaderFactory; + _smartContractAddressService = smartContractAddressService; + } - public MethodCallingThresholdPreExecutionPlugin(IContractReaderFactory - thresholdSettingContractReaderFactory, - IContractReaderFactory tokenContractReaderFactory, - ISmartContractAddressService smartContractAddressService) : base("acs5") - { - _thresholdSettingContractReaderFactory = thresholdSettingContractReaderFactory; - _tokenContractReaderFactory = tokenContractReaderFactory; - _smartContractAddressService = smartContractAddressService; - } + public async Task> GetPreTransactionsAsync( + IReadOnlyList descriptors, ITransactionContext transactionContext) + { + if (!IsTargetAcsSymbol(descriptors)) return new List(); - public async Task> GetPreTransactionsAsync( - IReadOnlyList descriptors, ITransactionContext transactionContext) + var thresholdSettingStub = _thresholdSettingContractReaderFactory.Create(new ContractReaderContext { - if (!IsTargetAcsSymbol(descriptors)) - { - return new List(); - } + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1, + ContractAddress = transactionContext.Transaction.To, + Sender = transactionContext.Transaction.To, + Timestamp = transactionContext.CurrentBlockTime, + StateCache = transactionContext.StateCache + }); - var thresholdSettingStub = _thresholdSettingContractReaderFactory.Create(new ContractReaderContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1, - ContractAddress = transactionContext.Transaction.To, - Sender = transactionContext.Transaction.To, - Timestamp = transactionContext.CurrentBlockTime, - StateCache = transactionContext.StateCache - }); - - var threshold = await thresholdSettingStub.GetMethodCallingThreshold.CallAsync(new StringValue - { - Value = transactionContext.Transaction.MethodName - }); - - // Generate token contract stub. - var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1 - }, TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - { - return new List(); - } + var threshold = await thresholdSettingStub.GetMethodCallingThreshold.CallAsync(new StringValue + { + Value = transactionContext.Transaction.MethodName + }); - var tokenStub = _tokenContractReaderFactory.Create(new ContractReaderContext - { - Sender = transactionContext.Transaction.To, - ContractAddress = tokenContractAddress - }); - if (transactionContext.Transaction.To == tokenContractAddress && - transactionContext.Transaction.MethodName == nameof(tokenStub.CheckThreshold)) - { - return new List(); - } + // Generate token contract stub. + var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext + { + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1 + }, TokenSmartContractAddressNameProvider.StringName); + if (tokenContractAddress == null) return new List(); - var checkThresholdTransaction = tokenStub.CheckThreshold.GetTransaction(new CheckThresholdInput - { - Sender = transactionContext.Transaction.From, - SymbolToThreshold = {threshold.SymbolToAmount}, - IsCheckAllowance = threshold.ThresholdCheckType == ThresholdCheckType.Allowance - }); + var tokenStub = _tokenContractReaderFactory.Create(new ContractReaderContext + { + Sender = transactionContext.Transaction.To, + ContractAddress = tokenContractAddress + }); + if (transactionContext.Transaction.To == tokenContractAddress && + transactionContext.Transaction.MethodName == nameof(tokenStub.CheckThreshold)) + return new List(); - return new List - { - checkThresholdTransaction - }; - } + var checkThresholdTransaction = tokenStub.CheckThreshold.GetTransaction(new CheckThresholdInput + { + Sender = transactionContext.Transaction.From, + SymbolToThreshold = { threshold.SymbolToAmount }, + IsCheckAllowance = threshold.ThresholdCheckType == ThresholdCheckType.Allowance + }); - public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + return new List { - preExecutionInformation = string.Empty; - return false; - } + checkThresholdTransaction + }; + } + + public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + { + preExecutionInformation = string.Empty; + return false; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/ExecutionPluginForCallThresholdModule.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/ExecutionPluginForCallThresholdModule.cs index 2f8cc16133..bbf0eab3e4 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/ExecutionPluginForCallThresholdModule.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold/ExecutionPluginForCallThresholdModule.cs @@ -1,13 +1,12 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold; + +[DependsOn(typeof(SmartContractAElfModule))] +public class ExecutionPluginForCallThresholdModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule))] - public class ExecutionPluginForCallThresholdModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj index 3c6ca0f576..3c583092ab 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,8 +9,8 @@ - - + + diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimFeeTransactionGenerator.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimFeeTransactionGenerator.cs index 7c2dc0f565..99ee72e517 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimFeeTransactionGenerator.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimFeeTransactionGenerator.cs @@ -9,66 +9,66 @@ using Google.Protobuf; using Microsoft.Extensions.Logging; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class ClaimFeeTransactionGenerator : ISystemTransactionGenerator { - internal class ClaimFeeTransactionGenerator : ISystemTransactionGenerator + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; + + public ClaimFeeTransactionGenerator(ISmartContractAddressService smartContractAddressService, + ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; - public ILogger Logger { get; set; } + _smartContractAddressService = smartContractAddressService; + _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; + } - public ClaimFeeTransactionGenerator(ISmartContractAddressService smartContractAddressService, - ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider) - { - _smartContractAddressService = smartContractAddressService; - _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; - } + public ILogger Logger { get; set; } - public async Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, - Hash preBlockHash) - { - var generatedTransactions = new List(); + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + var generatedTransactions = new List(); - if (preBlockHeight < AElfConstants.GenesisBlockHeight) - return generatedTransactions; + if (preBlockHeight < AElfConstants.GenesisBlockHeight) + return generatedTransactions; - var chainContext = new ChainContext - { - BlockHash = preBlockHash, - BlockHeight = preBlockHeight - }; + var chainContext = new ChainContext + { + BlockHash = preBlockHash, + BlockHeight = preBlockHeight + }; - var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - TokenSmartContractAddressNameProvider.StringName); + var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - return generatedTransactions; + if (tokenContractAddress == null) + return generatedTransactions; - var totalTxFeesMap = await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(chainContext); - if (totalTxFeesMap == null || !totalTxFeesMap.Value.Any() || totalTxFeesMap.BlockHeight != preBlockHeight || - totalTxFeesMap.BlockHash != preBlockHash) - { - Logger.LogDebug( - "Won't generate ClaimTransactionFees because no tx fee charged in previous block."); - // If previous block doesn't contain logEvent named TransactionFeeCharged, won't generate this tx. - return new List(); - } + var totalTxFeesMap = await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(chainContext); + if (totalTxFeesMap == null || !totalTxFeesMap.Value.Any() || totalTxFeesMap.BlockHeight != preBlockHeight || + totalTxFeesMap.BlockHash != preBlockHash) + { + Logger.LogDebug( + "Won't generate ClaimTransactionFees because no tx fee charged in previous block."); + // If previous block doesn't contain logEvent named TransactionFeeCharged, won't generate this tx. + return new List(); + } - generatedTransactions.AddRange(new List + generatedTransactions.AddRange(new List + { + new() { - new Transaction - { - From = from, - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ClaimTransactionFees), - To = tokenContractAddress, - RefBlockNumber = preBlockHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), - Params = totalTxFeesMap.ToByteString() - } - }); + From = from, + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ClaimTransactionFees), + To = tokenContractAddress, + RefBlockNumber = preBlockHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), + Params = totalTxFeesMap.ToByteString() + } + }); - Logger.LogTrace("Tx ClaimTransactionFees generated."); - return generatedTransactions; - } + Logger.LogTrace("Tx ClaimTransactionFees generated."); + return generatedTransactions; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimTransactionFeesValidationProvider.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimTransactionFeesValidationProvider.cs index 78414fde91..d4bb79835b 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimTransactionFeesValidationProvider.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ClaimTransactionFeesValidationProvider.cs @@ -3,98 +3,91 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; -using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class ClaimTransactionFeesValidationProvider : IBlockValidationProvider { - internal class ClaimTransactionFeesValidationProvider : IBlockValidationProvider - { - private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly IContractReaderFactory + _contractReaderFactory; - public ILogger Logger { get; set; } + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; - public ClaimTransactionFeesValidationProvider(ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider, - ISmartContractAddressService smartContractAddressService, - IContractReaderFactory contractReaderFactory) - { - _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; - _smartContractAddressService = smartContractAddressService; - _contractReaderFactory = contractReaderFactory; + public ClaimTransactionFeesValidationProvider(ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider, + ISmartContractAddressService smartContractAddressService, + IContractReaderFactory contractReaderFactory) + { + _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; + _smartContractAddressService = smartContractAddressService; + _contractReaderFactory = contractReaderFactory; - Logger = NullLogger.Instance; - } + Logger = NullLogger.Instance; + } - /// - /// No need to validate before attaching. - /// - /// - /// - public Task ValidateBeforeAttachAsync(IBlock block) - { - return Task.FromResult(true); - } + public ILogger Logger { get; set; } - /// - /// No need to validate before executing. - /// - /// - /// - public Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + /// + /// No need to validate before attaching. + /// + /// + /// + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(true); + } - /// - /// Compare - /// - /// - /// - public async Task ValidateBlockAfterExecuteAsync(IBlock block) - { - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Header.Height - }, TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - { - return true; - } + /// + /// No need to validate before executing. + /// + /// + /// + public Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + return Task.FromResult(true); + } - var hashFromState = await _contractReaderFactory.Create(new ContractReaderContext + /// + /// Compare + /// + /// + /// + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext { BlockHash = block.GetHash(), - BlockHeight = block.Header.Height, - ContractAddress = tokenContractAddress - }).GetLatestTotalTransactionFeesMapHash.CallAsync(new Empty()); - - var totalTransactionFeesMapFromProvider = - await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(new ChainContext - { - BlockHash = block.Header.PreviousBlockHash, - BlockHeight = block.Header.Height - 1 - }); - if (totalTransactionFeesMapFromProvider == null) - { - Logger.LogDebug("totalTransactionFeesMapFromProvider == null"); - return hashFromState.Value.IsEmpty; - } + BlockHeight = block.Header.Height + }, TokenSmartContractAddressNameProvider.StringName); + if (tokenContractAddress == null) return true; - var hashFromProvider = HashHelper.ComputeFrom(totalTransactionFeesMapFromProvider); - var result = hashFromProvider == hashFromState; - if (!result) - { - Logger.LogDebug($"Hash from provider: {hashFromProvider}\nHash from state: {hashFromState}"); - } + var hashFromState = await _contractReaderFactory.Create(new ContractReaderContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Header.Height, + ContractAddress = tokenContractAddress + }).GetLatestTotalTransactionFeesMapHash.CallAsync(new Empty()); - return result; + var totalTransactionFeesMapFromProvider = + await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(new ChainContext + { + BlockHash = block.Header.PreviousBlockHash, + BlockHeight = block.Header.Height - 1 + }); + if (totalTransactionFeesMapFromProvider == null) + { + Logger.LogDebug("totalTransactionFeesMapFromProvider == null"); + return hashFromState.Value.IsEmpty; } + + var hashFromProvider = HashHelper.ComputeFrom(totalTransactionFeesMapFromProvider); + var result = hashFromProvider == hashFromState; + if (!result) Logger.LogDebug($"Hash from provider: {hashFromProvider}\nHash from state: {hashFromState}"); + + return result; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanBlockExecutedDataChangeHeightEventHandler.cs index 7d0ad7c7e7..467d3fbb9f 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -4,16 +4,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class CleanBlockExecutedDataChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency { - internal class CleanBlockExecutedDataChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanTotalTransactionFeesMapChangeHeightEventHandler.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanTotalTransactionFeesMapChangeHeightEventHandler.cs index 5a9f21b301..2eb830064f 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanTotalTransactionFeesMapChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/CleanTotalTransactionFeesMapChangeHeightEventHandler.cs @@ -4,16 +4,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class CleanTotalTransactionFeesMapChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency { - internal class CleanTotalTransactionFeesMapChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency + public CleanTotalTransactionFeesMapChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanTotalTransactionFeesMapChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ExecutionPluginForMethodFeeModule.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ExecutionPluginForMethodFeeModule.cs index d6e1babe67..fe1621d674 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ExecutionPluginForMethodFeeModule.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ExecutionPluginForMethodFeeModule.cs @@ -1,26 +1,24 @@ -using AElf.Kernel.FeeCalculation; using AElf.Kernel.Blockchain.Application; +using AElf.Kernel.FeeCalculation; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +[DependsOn(typeof(SmartContractAElfModule), + typeof(FeeCalculationModule))] +public class ExecutionPluginForMethodFeeModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule), - typeof(FeeCalculationModule))] - public class ExecutionPluginForMethodFeeModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services - .AddSingleton(); - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddTransient(); + context.Services + .AddSingleton(); + context.Services + .AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/FeeChargePreExecutionPlugin.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/FeeChargePreExecutionPlugin.cs index b20eb5af7a..cc0951ecb6 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/FeeChargePreExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/FeeChargePreExecutionPlugin.cs @@ -12,114 +12,103 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class FeeChargePreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, + ISingletonDependency { - internal class FeeChargePreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, - ISingletonDependency - { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IPrimaryTokenFeeService _txFeeService; - private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; + private readonly IContractReaderFactory + _contractReaderFactory; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; + private readonly IPrimaryTokenFeeService _txFeeService; - public ILogger Logger { get; set; } + public FeeChargePreExecutionPlugin(ISmartContractAddressService smartContractAddressService, + IPrimaryTokenFeeService txFeeService, + ITransactionSizeFeeSymbolsProvider transactionSizeFeeSymbolsProvider, + IContractReaderFactory contractReaderFactory) : + base("acs1") + { + _smartContractAddressService = smartContractAddressService; + _txFeeService = txFeeService; + _transactionSizeFeeSymbolsProvider = transactionSizeFeeSymbolsProvider; + _contractReaderFactory = contractReaderFactory; + Logger = NullLogger.Instance; + } - public FeeChargePreExecutionPlugin(ISmartContractAddressService smartContractAddressService, - IPrimaryTokenFeeService txFeeService, - ITransactionSizeFeeSymbolsProvider transactionSizeFeeSymbolsProvider, - IContractReaderFactory contractReaderFactory) : - base("acs1") - { - _smartContractAddressService = smartContractAddressService; - _txFeeService = txFeeService; - _transactionSizeFeeSymbolsProvider = transactionSizeFeeSymbolsProvider; - _contractReaderFactory = contractReaderFactory; - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task> GetPreTransactionsAsync( - IReadOnlyList descriptors, ITransactionContext transactionContext) + public async Task> GetPreTransactionsAsync( + IReadOnlyList descriptors, ITransactionContext transactionContext) + { + try { - try + var chainContext = new ChainContext { - var chainContext = new ChainContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1 - }; + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1 + }; - var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( - chainContext, - TokenSmartContractAddressNameProvider.StringName); + var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync( + chainContext, + TokenSmartContractAddressNameProvider.StringName); - if (transactionContext.BlockHeight < AElfConstants.GenesisBlockHeight + 1 || - tokenContractAddress == null) - { - return new List(); - } + if (transactionContext.BlockHeight < AElfConstants.GenesisBlockHeight + 1 || + tokenContractAddress == null) + return new List(); - if (!IsTargetAcsSymbol(descriptors) && transactionContext.Transaction.To != tokenContractAddress) - { - return new List(); - } + if (!IsTargetAcsSymbol(descriptors) && transactionContext.Transaction.To != tokenContractAddress) + return new List(); - var tokenStub = _contractReaderFactory.Create(new ContractReaderContext - { - Sender = transactionContext.Transaction.From, - ContractAddress = tokenContractAddress - }); + var tokenStub = _contractReaderFactory.Create(new ContractReaderContext + { + Sender = transactionContext.Transaction.From, + ContractAddress = tokenContractAddress + }); - if (transactionContext.Transaction.To == tokenContractAddress && - transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeTransactionFees)) - { - // Skip ChargeTransactionFees itself - return new List(); - } + if (transactionContext.Transaction.To == tokenContractAddress && + transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeTransactionFees)) + // Skip ChargeTransactionFees itself + return new List(); - var txCost = await _txFeeService.CalculateFeeAsync(transactionContext, chainContext); - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = transactionContext.Transaction.MethodName, - ContractAddress = transactionContext.Transaction.To, - TransactionSizeFee = txCost, - }; + var txCost = await _txFeeService.CalculateFeeAsync(transactionContext, chainContext); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = transactionContext.Transaction.MethodName, + ContractAddress = transactionContext.Transaction.To, + TransactionSizeFee = txCost + }; - var transactionSizeFeeSymbols = - await _transactionSizeFeeSymbolsProvider.GetTransactionSizeFeeSymbolsAsync(chainContext); - if (transactionSizeFeeSymbols != null) - { - foreach (var transactionSizeFeeSymbol in transactionSizeFeeSymbols.TransactionSizeFeeSymbolList) + var transactionSizeFeeSymbols = + await _transactionSizeFeeSymbolsProvider.GetTransactionSizeFeeSymbolsAsync(chainContext); + if (transactionSizeFeeSymbols != null) + foreach (var transactionSizeFeeSymbol in transactionSizeFeeSymbols.TransactionSizeFeeSymbolList) + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee { - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = transactionSizeFeeSymbol.TokenSymbol, - BaseTokenWeight = transactionSizeFeeSymbol.BaseTokenWeight, - AddedTokenWeight = transactionSizeFeeSymbol.AddedTokenWeight - }); - } - } + TokenSymbol = transactionSizeFeeSymbol.TokenSymbol, + BaseTokenWeight = transactionSizeFeeSymbol.BaseTokenWeight, + AddedTokenWeight = transactionSizeFeeSymbol.AddedTokenWeight + }); - var chargeFeeTransaction = tokenStub.ChargeTransactionFees.GetTransaction(chargeTransactionFeesInput); - return new List - { - chargeFeeTransaction - }; - } - catch (Exception e) + var chargeFeeTransaction = tokenStub.ChargeTransactionFees.GetTransaction(chargeTransactionFeesInput); + return new List { - Logger.LogError($"Failed to generate ChargeTransactionFees tx. {e.Message}"); - throw; - } + chargeFeeTransaction + }; } - - public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + catch (Exception e) { - var chargeTransactionFeesOutput = new ChargeTransactionFeesOutput(); - chargeTransactionFeesOutput.MergeFrom(txReturnValue); - preExecutionInformation = chargeTransactionFeesOutput.ChargingInformation; - return !chargeTransactionFeesOutput.Success; + Logger.LogError($"Failed to generate ChargeTransactionFees tx. {e.Message}"); + throw; } } + + public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + { + var chargeTransactionFeesOutput = new ChargeTransactionFeesOutput(); + chargeTransactionFeesOutput.MergeFrom(txReturnValue); + preExecutionInformation = chargeTransactionFeesOutput.ChargingInformation; + return !chargeTransactionFeesOutput.Success; + } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ITotalTransactionFeesMapProvider.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ITotalTransactionFeesMapProvider.cs index e158bcfb1a..ea97b038d5 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ITotalTransactionFeesMapProvider.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/ITotalTransactionFeesMapProvider.cs @@ -3,40 +3,39 @@ using AElf.Kernel.SmartContract.Application; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal interface ITotalTransactionFeesMapProvider +{ + Task GetTotalTransactionFeesMapAsync(IChainContext chainContext); + Task SetTotalTransactionFeesMapAsync(IBlockIndex blockIndex, TotalTransactionFeesMap totalTransactionFeesMap); +} + +internal class TotalTransactionFeesMapProvider : BlockExecutedDataBaseProvider, + ITotalTransactionFeesMapProvider, ISingletonDependency { - internal interface ITotalTransactionFeesMapProvider + private const string BlockExecutedDataName = nameof(TotalTransactionFeesMap); + + public TotalTransactionFeesMapProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - Task GetTotalTransactionFeesMapAsync(IChainContext chainContext); - Task SetTotalTransactionFeesMapAsync(IBlockIndex blockIndex, TotalTransactionFeesMap totalTransactionFeesMap); } - internal class TotalTransactionFeesMapProvider : BlockExecutedDataBaseProvider, - ITotalTransactionFeesMapProvider, ISingletonDependency + public Task GetTotalTransactionFeesMapAsync(IChainContext chainContext) { - private const string BlockExecutedDataName = nameof(TotalTransactionFeesMap); - - public TotalTransactionFeesMapProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } - - public Task GetTotalTransactionFeesMapAsync(IChainContext chainContext) - { - var totalTxFeesMap = GetBlockExecutedData(chainContext); - return Task.FromResult(totalTxFeesMap); - } + var totalTxFeesMap = GetBlockExecutedData(chainContext); + return Task.FromResult(totalTxFeesMap); + } - public async Task SetTotalTransactionFeesMapAsync(IBlockIndex blockIndex, - TotalTransactionFeesMap totalTransactionFeesMap) - { - await AddBlockExecutedDataAsync(blockIndex, totalTransactionFeesMap); - } + public async Task SetTotalTransactionFeesMapAsync(IBlockIndex blockIndex, + TotalTransactionFeesMap totalTransactionFeesMap) + { + await AddBlockExecutedDataAsync(blockIndex, totalTransactionFeesMap); + } - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + protected override string GetBlockExecutedDataName() + { + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/SymbolListToPayTxFeeUpdatedLogEventProcessor.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/SymbolListToPayTxFeeUpdatedLogEventProcessor.cs index 2e4f79a4bd..c38d9d2c6d 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/SymbolListToPayTxFeeUpdatedLogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/SymbolListToPayTxFeeUpdatedLogEventProcessor.cs @@ -7,62 +7,60 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class SymbolListToPayTxFeeUpdatedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - internal class SymbolListToPayTxFeeUpdatedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor - { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; - private ILogger Logger { get; set; } + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; - public SymbolListToPayTxFeeUpdatedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ITransactionSizeFeeSymbolsProvider transactionSizeFeeSymbolsProvider) - { - _smartContractAddressService = smartContractAddressService; - _transactionSizeFeeSymbolsProvider = transactionSizeFeeSymbolsProvider; - Logger = NullLogger.Instance; - } - - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; + public SymbolListToPayTxFeeUpdatedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ITransactionSizeFeeSymbolsProvider transactionSizeFeeSymbolsProvider) + { + _smartContractAddressService = smartContractAddressService; + _transactionSizeFeeSymbolsProvider = transactionSizeFeeSymbolsProvider; + Logger = NullLogger.Instance; + } - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, TokenSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; - - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; - InterestedEvent = interestedEvent; + private ILogger Logger { get; } + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) return InterestedEvent; - } - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) - { - var eventData = new ExtraTokenListModified(); - eventData.MergeFrom(logEvent); - if (eventData.SymbolListToPayTxSizeFee == null) - return; + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, TokenSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; - var transactionSizeFeeSymbols = new TransactionSizeFeeSymbols(); - foreach (var symbolToPayTxSizeFee in eventData.SymbolListToPayTxSizeFee.SymbolsToPayTxSizeFee) - { - transactionSizeFeeSymbols.TransactionSizeFeeSymbolList.Add(new TransactionSizeFeeSymbol - { - TokenSymbol = symbolToPayTxSizeFee.TokenSymbol, - AddedTokenWeight = symbolToPayTxSizeFee.AddedTokenWeight, - BaseTokenWeight = symbolToPayTxSizeFee.BaseTokenWeight - }); - } + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; + InterestedEvent = interestedEvent; + + return InterestedEvent; + } - await _transactionSizeFeeSymbolsProvider.SetTransactionSizeFeeSymbolsAsync(new BlockIndex + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var eventData = new ExtraTokenListModified(); + eventData.MergeFrom(logEvent); + if (eventData.SymbolListToPayTxSizeFee == null) + return; + + var transactionSizeFeeSymbols = new TransactionSizeFeeSymbols(); + foreach (var symbolToPayTxSizeFee in eventData.SymbolListToPayTxSizeFee.SymbolsToPayTxSizeFee) + transactionSizeFeeSymbols.TransactionSizeFeeSymbolList.Add(new TransactionSizeFeeSymbol { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, transactionSizeFeeSymbols); - } + TokenSymbol = symbolToPayTxSizeFee.TokenSymbol, + AddedTokenWeight = symbolToPayTxSizeFee.AddedTokenWeight, + BaseTokenWeight = symbolToPayTxSizeFee.BaseTokenWeight + }); + + await _transactionSizeFeeSymbolsProvider.SetTransactionSizeFeeSymbolsAsync(new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }, transactionSizeFeeSymbols); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionFeeChargedLogEventProcessor.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionFeeChargedLogEventProcessor.cs index 33b1b060e6..0b62e1420a 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionFeeChargedLogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionFeeChargedLogEventProcessor.cs @@ -9,76 +9,70 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal class TransactionFeeChargedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - internal class TransactionFeeChargedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; + + public TransactionFeeChargedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; - private ILogger Logger { get; set; } + _smartContractAddressService = smartContractAddressService; + _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; + Logger = NullLogger.Instance; + } - public TransactionFeeChargedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ITotalTransactionFeesMapProvider totalTransactionFeesMapProvider) - { - _smartContractAddressService = smartContractAddressService; - _totalTransactionFeesMapProvider = totalTransactionFeesMapProvider; - Logger = NullLogger.Instance; - } + private ILogger Logger { get; } - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return InterestedEvent; - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, TokenSmartContractAddressNameProvider.StringName); + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, TokenSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; + if (smartContractAddressDto == null) return null; - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + if (!smartContractAddressDto.Irreversible) return interestedEvent; - InterestedEvent = interestedEvent; + InterestedEvent = interestedEvent; - return InterestedEvent; - } + return InterestedEvent; + } - public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + { + var blockHash = block.GetHash(); + var blockHeight = block.Height; + var totalTxFeesMap = new TotalTransactionFeesMap { - var blockHash = block.GetHash(); - var blockHeight = block.Height; - var totalTxFeesMap = new TotalTransactionFeesMap - { - BlockHash = blockHash, - BlockHeight = blockHeight - }; + BlockHash = blockHash, + BlockHeight = blockHeight + }; - foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) - { - var eventData = new TransactionFeeCharged(); - eventData.MergeFrom(logEvent); - if (eventData.Symbol == null || eventData.Amount == 0) - continue; + foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) + { + var eventData = new TransactionFeeCharged(); + eventData.MergeFrom(logEvent); + if (eventData.Symbol == null || eventData.Amount == 0) + continue; - if (totalTxFeesMap.Value.ContainsKey(eventData.Symbol)) - { - totalTxFeesMap.Value[eventData.Symbol] += eventData.Amount; - } - else - { - totalTxFeesMap.Value[eventData.Symbol] = eventData.Amount; - } - } + if (totalTxFeesMap.Value.ContainsKey(eventData.Symbol)) + totalTxFeesMap.Value[eventData.Symbol] += eventData.Amount; + else + totalTxFeesMap.Value[eventData.Symbol] = eventData.Amount; + } - if (totalTxFeesMap.Value.Any()) // for some TransactionFeeCharged event with 0 fee to charge. + if (totalTxFeesMap.Value.Any()) // for some TransactionFeeCharged event with 0 fee to charge. + await _totalTransactionFeesMapProvider.SetTotalTransactionFeesMapAsync(new BlockIndex { - await _totalTransactionFeesMapProvider.SetTotalTransactionFeesMapAsync(new BlockIndex - { - BlockHash = blockHash, - BlockHeight = blockHeight - }, totalTxFeesMap); - } - } + BlockHash = blockHash, + BlockHeight = blockHeight + }, totalTxFeesMap); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionSizeFeeSymbolsProvider.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionSizeFeeSymbolsProvider.cs index 50e9c9f48b..3dcbedf949 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionSizeFeeSymbolsProvider.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee/TransactionSizeFeeSymbolsProvider.cs @@ -3,40 +3,40 @@ using AElf.Kernel.SmartContract.Application; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; + +internal interface ITransactionSizeFeeSymbolsProvider +{ + Task GetTransactionSizeFeeSymbolsAsync(IChainContext chainContext); + Task SetTransactionSizeFeeSymbolsAsync(IBlockIndex blockIndex, TransactionSizeFeeSymbols transactionSizeFeeSymbols); +} + +internal class TransactionSizeFeeSymbolsProvider : BlockExecutedDataBaseProvider, + ITransactionSizeFeeSymbolsProvider, + ISingletonDependency { - internal interface ITransactionSizeFeeSymbolsProvider + private const string BlockExecutedDataName = nameof(TransactionSizeFeeSymbols); + + public TransactionSizeFeeSymbolsProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - Task GetTransactionSizeFeeSymbolsAsync(IChainContext chainContext); - Task SetTransactionSizeFeeSymbolsAsync(IBlockIndex blockIndex, TransactionSizeFeeSymbols transactionSizeFeeSymbols); } - internal class TransactionSizeFeeSymbolsProvider : BlockExecutedDataBaseProvider, ITransactionSizeFeeSymbolsProvider, - ISingletonDependency + public Task GetTransactionSizeFeeSymbolsAsync(IChainContext chainContext) { - private const string BlockExecutedDataName = nameof(TransactionSizeFeeSymbols); - - public TransactionSizeFeeSymbolsProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } - - public Task GetTransactionSizeFeeSymbolsAsync(IChainContext chainContext) - { - var transactionSizeFeeSymbols = GetBlockExecutedData(chainContext); - return Task.FromResult(transactionSizeFeeSymbols); - } + var transactionSizeFeeSymbols = GetBlockExecutedData(chainContext); + return Task.FromResult(transactionSizeFeeSymbols); + } - public async Task SetTransactionSizeFeeSymbolsAsync(IBlockIndex blockIndex, - TransactionSizeFeeSymbols transactionSizeFeeSymbols) - { - await AddBlockExecutedDataAsync(blockIndex, transactionSizeFeeSymbols); - } + public async Task SetTransactionSizeFeeSymbolsAsync(IBlockIndex blockIndex, + TransactionSizeFeeSymbols transactionSizeFeeSymbols) + { + await AddBlockExecutedDataAsync(blockIndex, transactionSizeFeeSymbols); + } - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + protected override string GetBlockExecutedDataName() + { + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj index c6a354ac43..3abe851ea8 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,8 +9,8 @@ - - + + @@ -35,6 +35,6 @@ - + diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/CleanBlockExecutedDataChangeHeightEventHandler.cs index 875ab92a8d..dbba0771be 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -4,16 +4,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class CleanBlockExecutedDataChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency { - internal class CleanBlockExecutedDataChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTokenValidationProvider.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTokenValidationProvider.cs index 79b3f12b8c..b66cf1c4b7 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTokenValidationProvider.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTokenValidationProvider.cs @@ -7,102 +7,96 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class DonateResourceTokenValidationProvider : IBlockValidationProvider { - internal class DonateResourceTokenValidationProvider : IBlockValidationProvider - { - private readonly ITotalResourceTokensMapsProvider _totalResourceTokensMapsProvider; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IContractReaderFactory + _contractReaderFactory; - private readonly IContractReaderFactory - _contractReaderFactory; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalResourceTokensMapsProvider _totalResourceTokensMapsProvider; - public ILogger Logger { get; set; } + public DonateResourceTokenValidationProvider(ITotalResourceTokensMapsProvider totalResourceTokensMapsProvider, + ISmartContractAddressService smartContractAddressService, + IContractReaderFactory contractReaderFactory) + { + _totalResourceTokensMapsProvider = totalResourceTokensMapsProvider; + _smartContractAddressService = smartContractAddressService; + _contractReaderFactory = contractReaderFactory; - public DonateResourceTokenValidationProvider(ITotalResourceTokensMapsProvider totalResourceTokensMapsProvider, - ISmartContractAddressService smartContractAddressService, - IContractReaderFactory contractReaderFactory) - { - _totalResourceTokensMapsProvider = totalResourceTokensMapsProvider; - _smartContractAddressService = smartContractAddressService; - _contractReaderFactory = contractReaderFactory; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - /// - /// No need to validate before attaching. - /// - /// - /// - public Task ValidateBeforeAttachAsync(IBlock block) - { - return Task.FromResult(true); - } - - /// - /// No need to validate before executing. - /// - /// - /// - public Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + /// + /// No need to validate before attaching. + /// + /// + /// + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(true); + } - /// - /// Compare - /// - /// - /// - public async Task ValidateBlockAfterExecuteAsync(IBlock block) - { - if (block.Header.Height == AElfConstants.GenesisBlockHeight) return true; + /// + /// No need to validate before executing. + /// + /// + /// + public Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + return Task.FromResult(true); + } - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Header.Height - }, TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - { - return true; - } + /// + /// Compare + /// + /// + /// + public async Task ValidateBlockAfterExecuteAsync(IBlock block) + { + if (block.Header.Height == AElfConstants.GenesisBlockHeight) return true; - var hashFromState = await _contractReaderFactory.Create(new ContractReaderContext + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext { BlockHash = block.GetHash(), - BlockHeight = block.Header.Height, - ContractAddress = tokenContractAddress - }).GetLatestTotalResourceTokensMapsHash.CallAsync(new Empty()); + BlockHeight = block.Header.Height + }, TokenSmartContractAddressNameProvider.StringName); + if (tokenContractAddress == null) return true; - var totalResourceTokensMapsFromProvider = - await _totalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync(new ChainContext - { - BlockHash = block.Header.PreviousBlockHash, - BlockHeight = block.Header.Height - 1 - }); + var hashFromState = await _contractReaderFactory.Create(new ContractReaderContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Header.Height, + ContractAddress = tokenContractAddress + }).GetLatestTotalResourceTokensMapsHash.CallAsync(new Empty()); - if (hashFromState.Value.IsEmpty) + var totalResourceTokensMapsFromProvider = + await _totalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync(new ChainContext { - // If hash from state is empty, data from provider must be null. - return totalResourceTokensMapsFromProvider == null; - } + BlockHash = block.Header.PreviousBlockHash, + BlockHeight = block.Header.Height - 1 + }); + + if (hashFromState.Value.IsEmpty) + // If hash from state is empty, data from provider must be null. + return totalResourceTokensMapsFromProvider == null; - if (hashFromState == HashHelper.ComputeFrom(new TotalResourceTokensMaps + if (hashFromState == HashHelper.ComputeFrom(new TotalResourceTokensMaps { BlockHash = block.Header.PreviousBlockHash, BlockHeight = block.Header.Height - 1 })) - { - if (totalResourceTokensMapsFromProvider == null) return true; - return totalResourceTokensMapsFromProvider.BlockHeight != block.Header.Height - 1; - } - - if (totalResourceTokensMapsFromProvider == null) return false; - var hashFromProvider = HashHelper.ComputeFrom(totalResourceTokensMapsFromProvider); - return hashFromState == hashFromProvider; + { + if (totalResourceTokensMapsFromProvider == null) return true; + return totalResourceTokensMapsFromProvider.BlockHeight != block.Header.Height - 1; } + + if (totalResourceTokensMapsFromProvider == null) return false; + var hashFromProvider = HashHelper.ComputeFrom(totalResourceTokensMapsFromProvider); + return hashFromState == hashFromProvider; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTransactionGenerator.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTransactionGenerator.cs index 6dac5fa919..25d26e5175 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTransactionGenerator.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/DonateResourceTransactionGenerator.cs @@ -8,77 +8,69 @@ using Google.Protobuf; using Microsoft.Extensions.Logging; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class DonateResourceTransactionGenerator : ISystemTransactionGenerator { - internal class DonateResourceTransactionGenerator : ISystemTransactionGenerator + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalResourceTokensMapsProvider _totalResourceTokensMapsProvider; + + + public DonateResourceTransactionGenerator(ISmartContractAddressService smartContractAddressService, + ITotalResourceTokensMapsProvider totalResourceTokensMapsProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITotalResourceTokensMapsProvider _totalResourceTokensMapsProvider; + _smartContractAddressService = smartContractAddressService; + _totalResourceTokensMapsProvider = totalResourceTokensMapsProvider; + } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, + Hash preBlockHash) + { + var generatedTransactions = new List(); - public DonateResourceTransactionGenerator(ISmartContractAddressService smartContractAddressService, - ITotalResourceTokensMapsProvider totalResourceTokensMapsProvider) + var chainContext = new ChainContext { - _smartContractAddressService = smartContractAddressService; - _totalResourceTokensMapsProvider = totalResourceTokensMapsProvider; - } + BlockHash = preBlockHash, + BlockHeight = preBlockHeight + }; - public async Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, - Hash preBlockHash) - { - var generatedTransactions = new List(); + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); - var chainContext = new ChainContext - { - BlockHash = preBlockHash, - BlockHeight = preBlockHeight - }; + if (tokenContractAddress == null) return generatedTransactions; - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - TokenSmartContractAddressNameProvider.StringName); + var totalResourceTokensMaps = await _totalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync( + chainContext); - if (tokenContractAddress == null) + ByteString input; + if (totalResourceTokensMaps != null && totalResourceTokensMaps.BlockHeight == preBlockHeight && + totalResourceTokensMaps.BlockHash == preBlockHash) + // If totalResourceTokensMaps match current block. + input = totalResourceTokensMaps.ToByteString(); + else + input = new TotalResourceTokensMaps { - return generatedTransactions; - } - - var totalResourceTokensMaps = await _totalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync( - chainContext); + BlockHash = preBlockHash, + BlockHeight = preBlockHeight + }.ToByteString(); - ByteString input; - if (totalResourceTokensMaps != null && totalResourceTokensMaps.BlockHeight == preBlockHeight && - totalResourceTokensMaps.BlockHash == preBlockHash) - { - // If totalResourceTokensMaps match current block. - input = totalResourceTokensMaps.ToByteString(); - } - else + generatedTransactions.AddRange(new List + { + new() { - input = new TotalResourceTokensMaps - { - BlockHash = preBlockHash, - BlockHeight = preBlockHeight - }.ToByteString(); + From = from, + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.DonateResourceToken), + To = tokenContractAddress, + RefBlockNumber = preBlockHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), + Params = input } + }); - generatedTransactions.AddRange(new List - { - new Transaction - { - From = from, - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.DonateResourceToken), - To = tokenContractAddress, - RefBlockNumber = preBlockHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash), - Params = input - } - }); - - Logger.LogTrace("Tx DonateResourceToken generated."); - return generatedTransactions; - } + Logger.LogTrace("Tx DonateResourceToken generated."); + return generatedTransactions; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ExecutionPluginForResourceFeeModule.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ExecutionPluginForResourceFeeModule.cs index 1f74cb2051..18877f946c 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ExecutionPluginForResourceFeeModule.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ExecutionPluginForResourceFeeModule.cs @@ -1,24 +1,21 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.FeeCalculation; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +[DependsOn(typeof(SmartContractAElfModule), + typeof(FeeCalculationModule))] +public class ExecutionPluginForResourceFeeModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule), - typeof(FeeCalculationModule))] - public class ExecutionPluginForResourceFeeModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddSingleton(); - } + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ITotalResourceTokensMapsProvider.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ITotalResourceTokensMapsProvider.cs index e865a3765e..0794e2c78d 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ITotalResourceTokensMapsProvider.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ITotalResourceTokensMapsProvider.cs @@ -5,45 +5,44 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal interface ITotalResourceTokensMapsProvider +{ + Task GetTotalResourceTokensMapsAsync(IChainContext chainContext); + Task SetTotalResourceTokensMapsAsync(IBlockIndex blockIndex, TotalResourceTokensMaps totalResourceTokensMap); +} + +internal class TotalResourceTokensMapsProvider : BlockExecutedDataBaseProvider, + ITotalResourceTokensMapsProvider, ISingletonDependency { - internal interface ITotalResourceTokensMapsProvider + private const string BlockExecutedDataName = nameof(TotalResourceTokensMaps); + + public TotalResourceTokensMapsProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) + { + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public Task GetTotalResourceTokensMapsAsync(IChainContext chainContext) + { + var totalTxFeesMap = GetBlockExecutedData(chainContext); + Logger.LogDebug($"Get TotalResourceTokensMaps: {totalTxFeesMap}"); + return Task.FromResult(totalTxFeesMap); + } + + public async Task SetTotalResourceTokensMapsAsync(IBlockIndex blockIndex, + TotalResourceTokensMaps totalResourceTokensMaps) { - Task GetTotalResourceTokensMapsAsync(IChainContext chainContext); - Task SetTotalResourceTokensMapsAsync(IBlockIndex blockIndex, TotalResourceTokensMaps totalResourceTokensMap); + Logger.LogDebug($"Add TotalResourceTokensMaps: {totalResourceTokensMaps}"); + await AddBlockExecutedDataAsync(blockIndex, totalResourceTokensMaps); } - internal class TotalResourceTokensMapsProvider : BlockExecutedDataBaseProvider, - ITotalResourceTokensMapsProvider, ISingletonDependency + protected override string GetBlockExecutedDataName() { - private const string BlockExecutedDataName = nameof(TotalResourceTokensMaps); - - public ILogger Logger { get; set; } - - public TotalResourceTokensMapsProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - Logger = NullLogger.Instance; - } - - public Task GetTotalResourceTokensMapsAsync(IChainContext chainContext) - { - var totalTxFeesMap = GetBlockExecutedData(chainContext); - Logger.LogDebug($"Get TotalResourceTokensMaps: {totalTxFeesMap}"); - return Task.FromResult(totalTxFeesMap); - } - - public async Task SetTotalResourceTokensMapsAsync(IBlockIndex blockIndex, - TotalResourceTokensMaps totalResourceTokensMaps) - { - Logger.LogDebug($"Add TotalResourceTokensMaps: {totalResourceTokensMaps}"); - await AddBlockExecutedDataAsync(blockIndex, totalResourceTokensMaps); - } - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPostExecutionPlugin.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPostExecutionPlugin.cs index a595be6d31..75f5e76c48 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPostExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPostExecutionPlugin.cs @@ -1,94 +1,85 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS8; using AElf.Contracts.MultiToken; using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; +using AElf.Standards.ACS8; using AElf.Types; using Google.Protobuf.Reflection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class ResourceConsumptionPostExecutionPlugin : SmartContractExecutionPluginBase, IPostExecutionPlugin, + ISingletonDependency { - internal class ResourceConsumptionPostExecutionPlugin : SmartContractExecutionPluginBase, IPostExecutionPlugin, ISingletonDependency + private readonly IContractReaderFactory + _contractReaderFactory; + + private readonly IResourceTokenFeeService _resourceTokenFeeService; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ResourceConsumptionPostExecutionPlugin(ISmartContractAddressService smartContractAddressService, + IResourceTokenFeeService resourceTokenFeeService, + IContractReaderFactory contractReaderFactory) : + base("acs8") + { + _smartContractAddressService = smartContractAddressService; + _resourceTokenFeeService = resourceTokenFeeService; + _contractReaderFactory = contractReaderFactory; + + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public async Task> GetPostTransactionsAsync( + IReadOnlyList descriptors, ITransactionContext transactionContext) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IResourceTokenFeeService _resourceTokenFeeService; - private readonly IContractReaderFactory - _contractReaderFactory; - - public ILogger Logger { get; set; } + if (!IsTargetAcsSymbol(descriptors)) return new List(); - public ResourceConsumptionPostExecutionPlugin(ISmartContractAddressService smartContractAddressService, - IResourceTokenFeeService resourceTokenFeeService, - IContractReaderFactory contractReaderFactory) : - base("acs8") + var chainContext = new ChainContext { - _smartContractAddressService = smartContractAddressService; - _resourceTokenFeeService = resourceTokenFeeService; - _contractReaderFactory = contractReaderFactory; + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1 + }; - Logger = NullLogger.Instance; - } + // Generate token contract stub. + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + if (tokenContractAddress == null) return new List(); - public async Task> GetPostTransactionsAsync( - IReadOnlyList descriptors, ITransactionContext transactionContext) + var tokenStub = _contractReaderFactory.Create(new ContractReaderContext { - if (!IsTargetAcsSymbol(descriptors)) - { - return new List(); - } - - var chainContext = new ChainContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1 - }; + ContractAddress = tokenContractAddress, + Sender = transactionContext.Transaction.To + }); - // Generate token contract stub. - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - { - return new List(); - } + if (transactionContext.Transaction.To == tokenContractAddress && + transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeResourceToken)) + return new List(); - var tokenStub = _contractReaderFactory.Create(new ContractReaderContext - { - ContractAddress = tokenContractAddress, - Sender = transactionContext.Transaction.To - }); - - if (transactionContext.Transaction.To == tokenContractAddress && - transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeResourceToken)) - { - return new List(); - } - - if (transactionContext.Transaction.MethodName == nameof(ResourceConsumptionContractContainer - .ResourceConsumptionContractStub.BuyResourceToken)) - { - return new List(); - } + if (transactionContext.Transaction.MethodName == + nameof(ResourceConsumptionContractContainer.ResourceConsumptionContractStub.BuyResourceToken)) + return new List(); - var chargeResourceTokenInput = new ChargeResourceTokenInput - { - Caller = transactionContext.Transaction.From - }; + var chargeResourceTokenInput = new ChargeResourceTokenInput + { + Caller = transactionContext.Transaction.From + }; - var feeCalculationResult = - await _resourceTokenFeeService.CalculateFeeAsync(transactionContext, chainContext); - chargeResourceTokenInput.CostDic.Add(feeCalculationResult); + var feeCalculationResult = + await _resourceTokenFeeService.CalculateFeeAsync(transactionContext, chainContext); + chargeResourceTokenInput.CostDic.Add(feeCalculationResult); - var chargeResourceTokenTransaction = tokenStub.ChargeResourceToken.GetTransaction(chargeResourceTokenInput); - return new List - { - chargeResourceTokenTransaction - }; - } + var chargeResourceTokenTransaction = tokenStub.ChargeResourceToken.GetTransaction(chargeResourceTokenInput); + return new List + { + chargeResourceTokenTransaction + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPreExecutionPlugin.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPreExecutionPlugin.cs index b652c93ef7..312fafb8ed 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPreExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceConsumptionPreExecutionPlugin.cs @@ -1,85 +1,75 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS8; using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; +using AElf.Standards.ACS8; using AElf.Types; using Google.Protobuf; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class ResourceConsumptionPreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, + ISingletonDependency { - internal class ResourceConsumptionPreExecutionPlugin : SmartContractExecutionPluginBase, IPreExecutionPlugin, - ISingletonDependency + private readonly IContractReaderFactory + _contractReaderFactory; + + private readonly ISmartContractAddressService _smartContractAddressService; + + public ResourceConsumptionPreExecutionPlugin(ISmartContractAddressService smartContractAddressService, + IContractReaderFactory contractReaderFactory) : + base("acs8") { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IContractReaderFactory - _contractReaderFactory; + _smartContractAddressService = smartContractAddressService; + _contractReaderFactory = contractReaderFactory; + } - public ResourceConsumptionPreExecutionPlugin(ISmartContractAddressService smartContractAddressService, - IContractReaderFactory contractReaderFactory) : - base("acs8") - { - _smartContractAddressService = smartContractAddressService; - _contractReaderFactory = contractReaderFactory; - } + public async Task> GetPreTransactionsAsync( + IReadOnlyList descriptors, ITransactionContext transactionContext) + { + if (!IsTargetAcsSymbol(descriptors)) return new List(); - public async Task> GetPreTransactionsAsync( - IReadOnlyList descriptors, ITransactionContext transactionContext) + var chainContext = new ChainContext { - if (!IsTargetAcsSymbol(descriptors)) - { - return new List(); - } - - var chainContext = new ChainContext - { - BlockHash = transactionContext.PreviousBlockHash, - BlockHeight = transactionContext.BlockHeight - 1 - }; + BlockHash = transactionContext.PreviousBlockHash, + BlockHeight = transactionContext.BlockHeight - 1 + }; - // Generate token contract stub. - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - TokenSmartContractAddressNameProvider.StringName); - if (tokenContractAddress == null) - { - return new List(); - } + // Generate token contract stub. + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + if (tokenContractAddress == null) return new List(); - var tokenStub = _contractReaderFactory.Create(new ContractReaderContext - { - ContractAddress = tokenContractAddress, - Sender = transactionContext.Transaction.To - }); - - if (transactionContext.Transaction.To == tokenContractAddress && - transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeResourceToken)) - { - return new List(); - } + var tokenStub = _contractReaderFactory.Create(new ContractReaderContext + { + ContractAddress = tokenContractAddress, + Sender = transactionContext.Transaction.To + }); - if (transactionContext.Transaction.MethodName == nameof(ResourceConsumptionContractContainer - .ResourceConsumptionContractStub.BuyResourceToken)) - { - return new List(); - } + if (transactionContext.Transaction.To == tokenContractAddress && + transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeResourceToken)) + return new List(); - var checkResourceTokenTransaction = tokenStub.CheckResourceToken.GetTransaction(new Empty()); + if (transactionContext.Transaction.MethodName == + nameof(ResourceConsumptionContractContainer.ResourceConsumptionContractStub.BuyResourceToken)) + return new List(); - return new List - { - checkResourceTokenTransaction - }; - } + var checkResourceTokenTransaction = tokenStub.CheckResourceToken.GetTransaction(new Empty()); - public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + return new List { - preExecutionInformation = string.Empty; - return false; - } + checkResourceTokenTransaction + }; + } + + public bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation) + { + preExecutionInformation = string.Empty; + return false; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceTokenChargedLogEventProcessor.cs b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceTokenChargedLogEventProcessor.cs index d7b0f3bffd..6b62992d03 100644 --- a/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceTokenChargedLogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee/ResourceTokenChargedLogEventProcessor.cs @@ -9,93 +9,89 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; + +internal class ResourceTokenChargedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - internal class ResourceTokenChargedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITotalResourceTokensMapsProvider _totalTotalResourceTokensMapsProvider; + + public ResourceTokenChargedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ITotalResourceTokensMapsProvider totalTotalResourceTokensMapsProvider) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITotalResourceTokensMapsProvider _totalTotalResourceTokensMapsProvider; - private ILogger Logger { get; set; } + _smartContractAddressService = smartContractAddressService; + _totalTotalResourceTokensMapsProvider = totalTotalResourceTokensMapsProvider; + Logger = NullLogger.Instance; + } - public ResourceTokenChargedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ITotalResourceTokensMapsProvider totalTotalResourceTokensMapsProvider) - { - _smartContractAddressService = smartContractAddressService; - _totalTotalResourceTokensMapsProvider = totalTotalResourceTokensMapsProvider; - Logger = NullLogger.Instance; - } + private ILogger Logger { get; } - public override async Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return InterestedEvent; + public override async Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return InterestedEvent; - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( - chainContext, TokenSmartContractAddressNameProvider.StringName); - if (smartContractAddressDto == null) return null; + var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync( + chainContext, TokenSmartContractAddressNameProvider.StringName); + if (smartContractAddressDto == null) return null; - var interestedEvent = - GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); + var interestedEvent = + GetInterestedEvent(smartContractAddressDto.SmartContractAddress.Address); - if (!smartContractAddressDto.Irreversible) return interestedEvent; - - InterestedEvent = interestedEvent; + if (!smartContractAddressDto.Irreversible) return interestedEvent; - return InterestedEvent; - } + InterestedEvent = interestedEvent; + + return InterestedEvent; + } - public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + public override async Task ProcessAsync(Block block, Dictionary> logEventsMap) + { + var blockHash = block.GetHash(); + var blockHeight = block.Height; + var totalResourceTokensMaps = new TotalResourceTokensMaps { - var blockHash = block.GetHash(); - var blockHeight = block.Height; - var totalResourceTokensMaps = new TotalResourceTokensMaps - { - BlockHash = blockHash, - BlockHeight = blockHeight - }; + BlockHash = blockHash, + BlockHeight = blockHeight + }; - foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) - { - var eventData = new ResourceTokenCharged(); - eventData.MergeFrom(logEvent); - if (eventData.Symbol == null || eventData.Amount == 0) - continue; + foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) + { + var eventData = new ResourceTokenCharged(); + eventData.MergeFrom(logEvent); + if (eventData.Symbol == null || eventData.Amount == 0) + continue; - if (totalResourceTokensMaps.Value.Any(b => b.ContractAddress == eventData.ContractAddress)) - { - var oldBill = - totalResourceTokensMaps.Value.First(b => b.ContractAddress == eventData.ContractAddress); - if (oldBill.TokensMap.Value.ContainsKey(eventData.Symbol)) - { - oldBill.TokensMap.Value[eventData.Symbol] += eventData.Amount; - } - else - { - oldBill.TokensMap.Value.Add(eventData.Symbol, eventData.Amount); - } - } + if (totalResourceTokensMaps.Value.Any(b => b.ContractAddress == eventData.ContractAddress)) + { + var oldBill = + totalResourceTokensMaps.Value.First(b => b.ContractAddress == eventData.ContractAddress); + if (oldBill.TokensMap.Value.ContainsKey(eventData.Symbol)) + oldBill.TokensMap.Value[eventData.Symbol] += eventData.Amount; else + oldBill.TokensMap.Value.Add(eventData.Symbol, eventData.Amount); + } + else + { + var contractTotalResourceTokens = new ContractTotalResourceTokens { - var contractTotalResourceTokens = new ContractTotalResourceTokens + ContractAddress = eventData.ContractAddress, + TokensMap = new TotalResourceTokensMap { - ContractAddress = eventData.ContractAddress, - TokensMap = new TotalResourceTokensMap + Value = { - Value = - { - {eventData.Symbol, eventData.Amount} - } + { eventData.Symbol, eventData.Amount } } - }; - totalResourceTokensMaps.Value.Add(contractTotalResourceTokens); - } + } + }; + totalResourceTokensMaps.Value.Add(contractTotalResourceTokens); } - - await _totalTotalResourceTokensMapsProvider.SetTotalResourceTokensMapsAsync(new BlockIndex - { - BlockHash = blockHash, - BlockHeight = blockHeight - }, totalResourceTokensMaps); } + + await _totalTotalResourceTokensMapsProvider.SetTotalResourceTokensMapsAsync(new BlockIndex + { + BlockHash = blockHash, + BlockHeight = blockHeight + }, totalResourceTokensMaps); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/AElf.Kernel.SmartContract.Parallel.csproj b/src/AElf.Kernel.SmartContract.Parallel/AElf.Kernel.SmartContract.Parallel.csproj index 88e9ef85f5..dc8ed0e072 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/AElf.Kernel.SmartContract.Parallel.csproj +++ b/src/AElf.Kernel.SmartContract.Parallel/AElf.Kernel.SmartContract.Parallel.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -21,6 +21,6 @@ - + diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/BlockParallelExecutingService.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/BlockParallelExecutingService.cs index 1682add1ab..a5b1a99925 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/BlockParallelExecutingService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/BlockParallelExecutingService.cs @@ -6,28 +6,26 @@ using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.SmartContractExecution.Application; -namespace AElf.Kernel.SmartContract.Parallel.Application +namespace AElf.Kernel.SmartContract.Parallel.Application; + +public class BlockParallelExecutingService : BlockExecutingService { - public class BlockParallelExecutingService : BlockExecutingService + public BlockParallelExecutingService(ITransactionExecutingService transactionExecutingService, + IBlockchainStateService blockchainStateService, ITransactionResultService transactionResultService, + ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) : base( + transactionExecutingService, blockchainStateService, transactionResultService, + systemTransactionExtraDataProvider) { - public BlockParallelExecutingService(ITransactionExecutingService transactionExecutingService, - IBlockchainStateService blockchainStateService, ITransactionResultService transactionResultService, - ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) : base( - transactionExecutingService, blockchainStateService, transactionResultService, - systemTransactionExtraDataProvider) - { - } + } - protected override async Task CleanUpReturnSetCollectionAsync(BlockHeader blockHeader, ExecutionReturnSetCollection executionReturnSetCollection) - { - await base.CleanUpReturnSetCollectionAsync(blockHeader, executionReturnSetCollection); - if (executionReturnSetCollection.Conflict.Count > 0) - { - await EventBus.PublishAsync(new ConflictingTransactionsFoundInParallelGroupsEvent( - blockHeader, executionReturnSetCollection.Executed.ToList(), - executionReturnSetCollection.Conflict - )); - } - } + protected override async Task CleanUpReturnSetCollectionAsync(BlockHeader blockHeader, + ExecutionReturnSetCollection executionReturnSetCollection) + { + await base.CleanUpReturnSetCollectionAsync(blockHeader, executionReturnSetCollection); + if (executionReturnSetCollection.Conflict.Count > 0) + await EventBus.PublishAsync(new ConflictingTransactionsFoundInParallelGroupsEvent( + blockHeader, executionReturnSetCollection.Executed.ToList(), + executionReturnSetCollection.Conflict + )); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs index 61c65b57a0..1add45b61d 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -3,16 +3,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.Parallel.Application +namespace AElf.Kernel.SmartContract.Parallel.Application; + +public class CleanBlockExecutedDataChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency { - public class CleanBlockExecutedDataChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/ConflictingTransactionsFoundInParallelGroupsEventHandler.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/ConflictingTransactionsFoundInParallelGroupsEventHandler.cs index b332b498ee..7674a07a52 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/ConflictingTransactionsFoundInParallelGroupsEventHandler.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/ConflictingTransactionsFoundInParallelGroupsEventHandler.cs @@ -4,50 +4,50 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.Parallel.Application +namespace AElf.Kernel.SmartContract.Parallel.Application; + +public class ConflictingTransactionsFoundInParallelGroupsEventHandler : + ILocalEventHandler, ITransientDependency { - public class ConflictingTransactionsFoundInParallelGroupsEventHandler : - ILocalEventHandler, ITransientDependency + private readonly IConflictingTransactionIdentificationService _conflictingTransactionIdentificationService; + private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; + private readonly IResourceExtractionService _resourceExtractionService; + + public ConflictingTransactionsFoundInParallelGroupsEventHandler( + IConflictingTransactionIdentificationService conflictingTransactionIdentificationService, + IResourceExtractionService resourceExtractionService, + INonparallelContractCodeProvider nonparallelContractCodeProvider) { - private readonly IConflictingTransactionIdentificationService _conflictingTransactionIdentificationService; - private readonly IResourceExtractionService _resourceExtractionService; - private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; - - public ConflictingTransactionsFoundInParallelGroupsEventHandler( - IConflictingTransactionIdentificationService conflictingTransactionIdentificationService, - IResourceExtractionService resourceExtractionService, - INonparallelContractCodeProvider nonparallelContractCodeProvider) - { - _conflictingTransactionIdentificationService = conflictingTransactionIdentificationService; - _resourceExtractionService = resourceExtractionService; - _nonparallelContractCodeProvider = nonparallelContractCodeProvider; - } + _conflictingTransactionIdentificationService = conflictingTransactionIdentificationService; + _resourceExtractionService = resourceExtractionService; + _nonparallelContractCodeProvider = nonparallelContractCodeProvider; + } - public async Task HandleEventAsync(ConflictingTransactionsFoundInParallelGroupsEvent eventData) + public async Task HandleEventAsync(ConflictingTransactionsFoundInParallelGroupsEvent eventData) + { + var chainContext = new ChainContext { - var chainContext = new ChainContext - { - BlockHash = eventData.BlockHeader.PreviousBlockHash, - BlockHeight = eventData.BlockHeader.Height - 1 - }; - var wrongTxWithResources = await _conflictingTransactionIdentificationService.IdentifyConflictingTransactionsAsync( + BlockHash = eventData.BlockHeader.PreviousBlockHash, + BlockHeight = eventData.BlockHeader.Height - 1 + }; + var wrongTxWithResources = + await _conflictingTransactionIdentificationService.IdentifyConflictingTransactionsAsync( chainContext, eventData.ExistingSets, eventData.ConflictingSets); - - var wrongTransactionIds = wrongTxWithResources.Select(t => t.Transaction.GetHash()).ToArray(); - var dic = wrongTxWithResources.GroupBy(t => t.Transaction.To) - .ToDictionary(g => g.Key, g => new NonparallelContractCode - { - CodeHash = g.First().TransactionResourceInfo.ContractHash - }); + var wrongTransactionIds = wrongTxWithResources.Select(t => t.Transaction.GetHash()).ToArray(); - await _nonparallelContractCodeProvider.SetNonparallelContractCodeAsync(new BlockIndex + var dic = wrongTxWithResources.GroupBy(t => t.Transaction.To) + .ToDictionary(g => g.Key, g => new NonparallelContractCode { - BlockHash = eventData.BlockHeader.GetHash(), - BlockHeight = eventData.BlockHeader.Height - }, dic); + CodeHash = g.First().TransactionResourceInfo.ContractHash + }); + + await _nonparallelContractCodeProvider.SetNonparallelContractCodeAsync(new BlockIndex + { + BlockHash = eventData.BlockHeader.GetHash(), + BlockHeight = eventData.BlockHeader.Height + }, dic); - _resourceExtractionService.ClearConflictingTransactionsResourceCache(wrongTransactionIds); - } + _resourceExtractionService.ClearConflictingTransactionsResourceCache(wrongTransactionIds); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/IParallelTransactionExecutingService.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/IParallelTransactionExecutingService.cs index 69fe696e61..fdbf3b1121 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/IParallelTransactionExecutingService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/IParallelTransactionExecutingService.cs @@ -1,9 +1,7 @@ using AElf.Kernel.SmartContract.Application; -namespace AElf.Kernel.SmartContract.Parallel.Application -{ - public interface IParallelTransactionExecutingService : ITransactionExecutingService - { +namespace AElf.Kernel.SmartContract.Parallel.Application; - } +public interface IParallelTransactionExecutingService : ITransactionExecutingService +{ } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/LocalParallelTransactionExecutingService.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/LocalParallelTransactionExecutingService.cs index 5a63b67ed7..5675625adc 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/LocalParallelTransactionExecutingService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/LocalParallelTransactionExecutingService.cs @@ -11,254 +11,251 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContract.Parallel.Application +namespace AElf.Kernel.SmartContract.Parallel.Application; + +public class LocalParallelTransactionExecutingService : IParallelTransactionExecutingService, ISingletonDependency { - public class LocalParallelTransactionExecutingService : IParallelTransactionExecutingService, ISingletonDependency + private readonly ITransactionGrouper _grouper; + private readonly IPlainTransactionExecutingService _planTransactionExecutingService; + + public LocalParallelTransactionExecutingService(ITransactionGrouper grouper, + IPlainTransactionExecutingService planTransactionExecutingService, + ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) { - private readonly ITransactionGrouper _grouper; - private readonly IPlainTransactionExecutingService _planTransactionExecutingService; - public ILogger Logger { get; set; } - public ILocalEventBus EventBus { get; set; } - - public LocalParallelTransactionExecutingService(ITransactionGrouper grouper, - IPlainTransactionExecutingService planTransactionExecutingService, - ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) - { - _grouper = grouper; - _planTransactionExecutingService = planTransactionExecutingService; - EventBus = NullLocalEventBus.Instance; - Logger = NullLogger.Instance; - } + _grouper = grouper; + _planTransactionExecutingService = planTransactionExecutingService; + EventBus = NullLocalEventBus.Instance; + Logger = NullLogger.Instance; + } - public async Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, - CancellationToken cancellationToken) + public ILogger Logger { get; set; } + public ILocalEventBus EventBus { get; set; } + + public async Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, + CancellationToken cancellationToken) + { + Logger.LogTrace("Entered parallel ExecuteAsync."); + var transactions = transactionExecutingDto.Transactions.ToList(); + var blockHeader = transactionExecutingDto.BlockHeader; + + var chainContext = new ChainContext { - Logger.LogTrace("Entered parallel ExecuteAsync."); - var transactions = transactionExecutingDto.Transactions.ToList(); - var blockHeader = transactionExecutingDto.BlockHeader; + BlockHash = blockHeader.PreviousBlockHash, + BlockHeight = blockHeader.Height - 1 + }; + var groupedTransactions = await _grouper.GroupAsync(chainContext, transactions); - var chainContext = new ChainContext - { - BlockHash = blockHeader.PreviousBlockHash, - BlockHeight = blockHeader.Height - 1 - }; - var groupedTransactions = await _grouper.GroupAsync(chainContext, transactions); - - var returnSets = new List(); - - var mergeResult = await ExecuteParallelizableTransactionsAsync(groupedTransactions.Parallelizables, - blockHeader, transactionExecutingDto.PartialBlockStateSet, cancellationToken); - returnSets.AddRange(mergeResult.ExecutionReturnSets); - var conflictingSets = mergeResult.ConflictingReturnSets; - - var returnSetCollection = new ExecutionReturnSetCollection(returnSets); - var updatedPartialBlockStateSet = GetUpdatedBlockStateSet(returnSetCollection, transactionExecutingDto); - - var nonParallelizableReturnSets = await ExecuteNonParallelizableTransactionsAsync(groupedTransactions.NonParallelizables, blockHeader, - updatedPartialBlockStateSet, cancellationToken); - returnSets.AddRange(nonParallelizableReturnSets); - - var transactionWithoutContractReturnSets = ProcessTransactionsWithoutContract( - groupedTransactions.TransactionsWithoutContract); - - Logger.LogTrace("Merged results from transactions without contract."); - returnSets.AddRange(transactionWithoutContractReturnSets); - - if (conflictingSets.Count > 0 && - returnSets.Count + conflictingSets.Count == transactionExecutingDto.Transactions.Count()) - { - ProcessConflictingSets(conflictingSets); - returnSets.AddRange(conflictingSets); - } + var returnSets = new List(); - return returnSets; - } + var mergeResult = await ExecuteParallelizableTransactionsAsync(groupedTransactions.Parallelizables, + blockHeader, transactionExecutingDto.PartialBlockStateSet, cancellationToken); + returnSets.AddRange(mergeResult.ExecutionReturnSets); + var conflictingSets = mergeResult.ConflictingReturnSets; - private async Task ExecuteParallelizableTransactionsAsync( - List> groupedTransactions, BlockHeader blockHeader, BlockStateSet blockStateSet, - CancellationToken cancellationToken) - { - var tasks = groupedTransactions.Select( - txns => ExecuteAndPreprocessResult(new TransactionExecutingDto - { - BlockHeader = blockHeader, - Transactions = txns, - PartialBlockStateSet = blockStateSet - }, cancellationToken)); - var results = await Task.WhenAll(tasks); - Logger.LogTrace("Executed parallelizables."); - - var executionReturnSets = MergeResults(results, out var conflictingSets); - Logger.LogTrace("Merged results from parallelizables."); - return new ExecutionReturnSetMergeResult - { - ExecutionReturnSets = executionReturnSets, - ConflictingReturnSets = conflictingSets - }; - } + var returnSetCollection = new ExecutionReturnSetCollection(returnSets); + var updatedPartialBlockStateSet = GetUpdatedBlockStateSet(returnSetCollection, transactionExecutingDto); + + var nonParallelizableReturnSets = await ExecuteNonParallelizableTransactionsAsync( + groupedTransactions.NonParallelizables, blockHeader, + updatedPartialBlockStateSet, cancellationToken); + returnSets.AddRange(nonParallelizableReturnSets); - private async Task> ExecuteNonParallelizableTransactionsAsync(List transactions, - BlockHeader blockHeader, BlockStateSet blockStateSet, CancellationToken cancellationToken) + var transactionWithoutContractReturnSets = ProcessTransactionsWithoutContract( + groupedTransactions.TransactionsWithoutContract); + + Logger.LogTrace("Merged results from transactions without contract."); + returnSets.AddRange(transactionWithoutContractReturnSets); + + if (conflictingSets.Count > 0 && + returnSets.Count + conflictingSets.Count == transactionExecutingDto.Transactions.Count()) { - var nonParallelizableReturnSets = await _planTransactionExecutingService.ExecuteAsync( - new TransactionExecutingDto - { - Transactions = transactions, - BlockHeader = blockHeader, - PartialBlockStateSet = blockStateSet - }, - cancellationToken); - - Logger.LogTrace("Merged results from non-parallelizables."); - return nonParallelizableReturnSets; + ProcessConflictingSets(conflictingSets); + returnSets.AddRange(conflictingSets); } - private List ProcessTransactionsWithoutContract(List transactions) - { - var returnSets = new List(); - foreach (var transaction in transactions) + return returnSets; + } + + private async Task ExecuteParallelizableTransactionsAsync( + List> groupedTransactions, BlockHeader blockHeader, BlockStateSet blockStateSet, + CancellationToken cancellationToken) + { + var tasks = groupedTransactions.Select( + txns => ExecuteAndPreprocessResult(new TransactionExecutingDto { - var result = new TransactionResult - { - TransactionId = transaction.GetHash(), - Status = TransactionResultStatus.Failed, - Error = "Invalid contract address." - }; - Logger.LogDebug(result.Error); - - var returnSet = new ExecutionReturnSet - { - TransactionId = result.TransactionId, - Status = result.Status, - Bloom = result.Bloom, - TransactionResult = result - }; - returnSets.Add(returnSet); - } - - return returnSets; - } + BlockHeader = blockHeader, + Transactions = txns, + PartialBlockStateSet = blockStateSet + }, cancellationToken)); + var results = await Task.WhenAll(tasks); + Logger.LogTrace("Executed parallelizables."); - private void ProcessConflictingSets(List conflictingSets) + var executionReturnSets = MergeResults(results, out var conflictingSets); + Logger.LogTrace("Merged results from parallelizables."); + return new ExecutionReturnSetMergeResult { - foreach (var conflictingSet in conflictingSets) + ExecutionReturnSets = executionReturnSets, + ConflictingReturnSets = conflictingSets + }; + } + + private async Task> ExecuteNonParallelizableTransactionsAsync( + List transactions, + BlockHeader blockHeader, BlockStateSet blockStateSet, CancellationToken cancellationToken) + { + var nonParallelizableReturnSets = await _planTransactionExecutingService.ExecuteAsync( + new TransactionExecutingDto { - var result = new TransactionResult - { - TransactionId = conflictingSet.TransactionId, - Status = TransactionResultStatus.Conflict, - Error = "Parallel conflict", - }; - conflictingSet.Status = result.Status; - conflictingSet.TransactionResult = result; - } + Transactions = transactions, + BlockHeader = blockHeader, + PartialBlockStateSet = blockStateSet + }, + cancellationToken); - } + Logger.LogTrace("Merged results from non-parallelizables."); + return nonParallelizableReturnSets; + } - private async Task ExecuteAndPreprocessResult( - TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken) + private List ProcessTransactionsWithoutContract(List transactions) + { + var returnSets = new List(); + foreach (var transaction in transactions) { - var executionReturnSets = - await _planTransactionExecutingService.ExecuteAsync(transactionExecutingDto, cancellationToken); - var changeKeys = - executionReturnSets.SelectMany(s => s.StateChanges.Keys.Concat(s.StateDeletes.Keys)); - var allKeys = new HashSet( - executionReturnSets.SelectMany(s =>s.StateAccesses.Keys)); - var readKeys = allKeys.Where(k => !changeKeys.Contains(k)); - - return new GroupedExecutionReturnSets + var result = new TransactionResult { - ReturnSets = executionReturnSets, - AllKeys = allKeys, - ChangeKeys = changeKeys, - ReadKeys = readKeys + TransactionId = transaction.GetHash(), + Status = TransactionResultStatus.Failed, + Error = "Invalid contract address." }; - } - - private class GroupedExecutionReturnSets - { - public List ReturnSets { get; set; } + Logger.LogDebug(result.Error); - public HashSet AllKeys { get; set; } - - public IEnumerable ChangeKeys { get; set; } - - public IEnumerable ReadKeys { get; set; } + var returnSet = new ExecutionReturnSet + { + TransactionId = result.TransactionId, + Status = result.Status, + Bloom = result.Bloom, + TransactionResult = result + }; + returnSets.Add(returnSet); } - private HashSet GetReadOnlyKeys(GroupedExecutionReturnSets[] groupedExecutionReturnSetsArray) + return returnSets; + } + + private void ProcessConflictingSets(List conflictingSets) + { + foreach (var conflictingSet in conflictingSets) { - var readKeys = new HashSet(groupedExecutionReturnSetsArray.SelectMany(s => s.ReadKeys));; - var changeKeys = new HashSet(groupedExecutionReturnSetsArray.SelectMany(s => s.ChangeKeys)); - readKeys.ExceptWith(changeKeys); - return readKeys; + var result = new TransactionResult + { + TransactionId = conflictingSet.TransactionId, + Status = TransactionResultStatus.Conflict, + Error = "Parallel conflict" + }; + conflictingSet.Status = result.Status; + conflictingSet.TransactionResult = result; } + } + + private async Task ExecuteAndPreprocessResult( + TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken) + { + var executionReturnSets = + await _planTransactionExecutingService.ExecuteAsync(transactionExecutingDto, cancellationToken); + var changeKeys = + executionReturnSets.SelectMany(s => s.StateChanges.Keys.Concat(s.StateDeletes.Keys)); + var allKeys = new HashSet( + executionReturnSets.SelectMany(s => s.StateAccesses.Keys)); + var readKeys = allKeys.Where(k => !changeKeys.Contains(k)); - private class ExecutionReturnSetMergeResult + return new GroupedExecutionReturnSets { - public List ExecutionReturnSets { get; set; } - - public List ConflictingReturnSets { get; set; } - } + ReturnSets = executionReturnSets, + AllKeys = allKeys, + ChangeKeys = changeKeys, + ReadKeys = readKeys + }; + } - private List MergeResults( - GroupedExecutionReturnSets[] groupedExecutionReturnSetsArray, - out List conflictingSets) + private HashSet GetReadOnlyKeys(GroupedExecutionReturnSets[] groupedExecutionReturnSetsArray) + { + var readKeys = new HashSet(groupedExecutionReturnSetsArray.SelectMany(s => s.ReadKeys)); + ; + var changeKeys = new HashSet(groupedExecutionReturnSetsArray.SelectMany(s => s.ChangeKeys)); + readKeys.ExceptWith(changeKeys); + return readKeys; + } + + private List MergeResults( + GroupedExecutionReturnSets[] groupedExecutionReturnSetsArray, + out List conflictingSets) + { + var returnSets = new List(); + conflictingSets = new List(); + var existingKeys = new HashSet(); + var readOnlyKeys = GetReadOnlyKeys(groupedExecutionReturnSetsArray); + foreach (var groupedExecutionReturnSets in groupedExecutionReturnSetsArray) { - var returnSets = new List(); - conflictingSets = new List(); - var existingKeys = new HashSet(); - var readOnlyKeys = GetReadOnlyKeys(groupedExecutionReturnSetsArray); - foreach (var groupedExecutionReturnSets in groupedExecutionReturnSetsArray) + groupedExecutionReturnSets.AllKeys.ExceptWith(readOnlyKeys); + if (!existingKeys.Overlaps(groupedExecutionReturnSets.AllKeys)) { - groupedExecutionReturnSets.AllKeys.ExceptWith(readOnlyKeys); - if (!existingKeys.Overlaps(groupedExecutionReturnSets.AllKeys)) - { - returnSets.AddRange(groupedExecutionReturnSets.ReturnSets); - foreach (var key in groupedExecutionReturnSets.AllKeys) - { - existingKeys.Add(key); - } - } - else - { - conflictingSets.AddRange(groupedExecutionReturnSets.ReturnSets); - } + returnSets.AddRange(groupedExecutionReturnSets.ReturnSets); + foreach (var key in groupedExecutionReturnSets.AllKeys) existingKeys.Add(key); } - - if (readOnlyKeys.Count == 0) return returnSets; - - foreach (var returnSet in returnSets.Concat(conflictingSets)) + else { - returnSet.StateAccesses.RemoveAll(k => readOnlyKeys.Contains(k.Key)); + conflictingSets.AddRange(groupedExecutionReturnSets.ReturnSets); } - - return returnSets; } - private BlockStateSet GetUpdatedBlockStateSet(ExecutionReturnSetCollection executionReturnSetCollection, - TransactionExecutingDto transactionExecutingDto) + if (readOnlyKeys.Count == 0) return returnSets; + + foreach (var returnSet in returnSets.Concat(conflictingSets)) + returnSet.StateAccesses.RemoveAll(k => readOnlyKeys.Contains(k.Key)); + + return returnSets; + } + + private BlockStateSet GetUpdatedBlockStateSet(ExecutionReturnSetCollection executionReturnSetCollection, + TransactionExecutingDto transactionExecutingDto) + { + var updatedPartialBlockStateSet = executionReturnSetCollection.ToBlockStateSet(); + if (transactionExecutingDto.PartialBlockStateSet != null) { - var updatedPartialBlockStateSet = executionReturnSetCollection.ToBlockStateSet(); - if (transactionExecutingDto.PartialBlockStateSet != null) + var partialBlockStateSet = transactionExecutingDto.PartialBlockStateSet.Clone(); + foreach (var change in partialBlockStateSet.Changes) { - var partialBlockStateSet = transactionExecutingDto.PartialBlockStateSet.Clone(); - foreach (var change in partialBlockStateSet.Changes) - { - if (updatedPartialBlockStateSet.Changes.TryGetValue(change.Key, out _)) continue; - if (updatedPartialBlockStateSet.Deletes.Contains(change.Key)) continue; - updatedPartialBlockStateSet.Changes[change.Key] = change.Value; - } - - foreach (var delete in partialBlockStateSet.Deletes) - { - if (updatedPartialBlockStateSet.Deletes.Contains(delete)) continue; - if (updatedPartialBlockStateSet.Changes.TryGetValue(delete, out _)) continue; - updatedPartialBlockStateSet.Deletes.Add(delete); - } + if (updatedPartialBlockStateSet.Changes.TryGetValue(change.Key, out _)) continue; + if (updatedPartialBlockStateSet.Deletes.Contains(change.Key)) continue; + updatedPartialBlockStateSet.Changes[change.Key] = change.Value; } - return updatedPartialBlockStateSet; + foreach (var delete in partialBlockStateSet.Deletes) + { + if (updatedPartialBlockStateSet.Deletes.Contains(delete)) continue; + if (updatedPartialBlockStateSet.Changes.TryGetValue(delete, out _)) continue; + updatedPartialBlockStateSet.Deletes.Add(delete); + } } + + return updatedPartialBlockStateSet; + } + + private class GroupedExecutionReturnSets + { + public List ReturnSets { get; set; } + + public HashSet AllKeys { get; set; } + + public IEnumerable ChangeKeys { get; set; } + + public IEnumerable ReadKeys { get; set; } + } + + private class ExecutionReturnSetMergeResult + { + public List ExecutionReturnSets { get; set; } + + public List ConflictingReturnSets { get; set; } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Application/ParallelExecutionInterestedEventsHandler.cs b/src/AElf.Kernel.SmartContract.Parallel/Application/ParallelExecutionInterestedEventsHandler.cs index 6e00984b4d..f3a08f73fc 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Application/ParallelExecutionInterestedEventsHandler.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Application/ParallelExecutionInterestedEventsHandler.cs @@ -1,44 +1,42 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Events; -using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.TransactionPool; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public class ParallelExecutionInterestedEventsHandler : ILocalEventHandler, + ILocalEventHandler, + ITransientDependency { - public class ParallelExecutionInterestedEventsHandler : ILocalEventHandler, - ILocalEventHandler, - ITransientDependency + private readonly IResourceExtractionService _resourceExtractionService; + private readonly ITaskQueueManager _taskQueueManager; + + public ParallelExecutionInterestedEventsHandler(IResourceExtractionService resourceExtractionService, + ITaskQueueManager taskQueueManager) { - private readonly IResourceExtractionService _resourceExtractionService; - private readonly ITaskQueueManager _taskQueueManager; + _resourceExtractionService = resourceExtractionService; + _taskQueueManager = taskQueueManager; + } - public ParallelExecutionInterestedEventsHandler(IResourceExtractionService resourceExtractionService, - ITaskQueueManager taskQueueManager) - { - _resourceExtractionService = resourceExtractionService; - _taskQueueManager = taskQueueManager; - } + public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + _taskQueueManager.Enqueue( + async () => { await _resourceExtractionService.HandleNewIrreversibleBlockFoundAsync(eventData); }, + KernelConstants.ChainCleaningQueueName); - public Task HandleEventAsync(TransactionAcceptedEvent eventData) - { - _ = _resourceExtractionService.HandleTransactionAcceptedEvent(eventData); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public async Task HandleEventAsync(BlockAcceptedEvent eventData) - { - await _resourceExtractionService.HandleBlockAcceptedAsync(eventData); - } + public Task HandleEventAsync(TransactionAcceptedEvent eventData) + { + _ = _resourceExtractionService.HandleTransactionAcceptedEvent(eventData); + return Task.CompletedTask; + } - public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) - { - _taskQueueManager.Enqueue( - async () => { await _resourceExtractionService.HandleNewIrreversibleBlockFoundAsync(eventData); }, - KernelConstants.ChainCleaningQueueName); - - return Task.CompletedTask; - } + public async Task HandleEventAsync(BlockAcceptedEvent eventData) + { + await _resourceExtractionService.HandleBlockAcceptedAsync(eventData); } -} +} \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionIdentificationService.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionIdentificationService.cs index d01222c81c..85054c643f 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionIdentificationService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionIdentificationService.cs @@ -3,80 +3,78 @@ using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.Parallel.Domain +namespace AElf.Kernel.SmartContract.Parallel.Domain; + +public class ConflictingTransactionIdentificationService : IConflictingTransactionIdentificationService { - public class ConflictingTransactionIdentificationService : IConflictingTransactionIdentificationService - { - private readonly IResourceExtractionService _resourceExtractionService; - private readonly IBlockchainService _blockchainService; - - public ILogger Logger { get; set; } + private readonly IBlockchainService _blockchainService; + private readonly IResourceExtractionService _resourceExtractionService; - public ConflictingTransactionIdentificationService(IResourceExtractionService resourceExtractionService, - IBlockchainService blockchainService) - { - _resourceExtractionService = resourceExtractionService; - _blockchainService = blockchainService; - - Logger = NullLogger.Instance; - } + public ConflictingTransactionIdentificationService(IResourceExtractionService resourceExtractionService, + IBlockchainService blockchainService) + { + _resourceExtractionService = resourceExtractionService; + _blockchainService = blockchainService; - public async Task> IdentifyConflictingTransactionsAsync(IChainContext chainContext, - List returnSets, List conflictingSets) - { - var possibleConflicting = FindPossibleConflictingReturnSets(returnSets, conflictingSets); - var wrongTxnWithResources = await FindContractOfWrongResourcesAsync(chainContext, possibleConflicting); - return wrongTxnWithResources; - } + Logger = NullLogger.Instance; + } - private List FindPossibleConflictingReturnSets(List returnSets, - List conflictingSets) - { - var existingKeys = new HashSet(returnSets.SelectMany(rs => rs.StateAccesses.Keys)); - var possibleConflictingKeys = new HashSet(conflictingSets.SelectMany(rs => rs.StateAccesses.Keys)); - possibleConflictingKeys.IntersectWith(existingKeys); - return returnSets.Concat(conflictingSets) - .Where(rs => rs.StateAccesses.Any(a => possibleConflictingKeys.Contains(a.Key))).ToList(); - } + public ILogger Logger { get; set; } - private async Task> FindContractOfWrongResourcesAsync(IChainContext chainContext, - List returnSets) - { - var transactionIds = returnSets.Select(rs => rs.TransactionId); - var transactions = await _blockchainService.GetTransactionsAsync(transactionIds); + public async Task> IdentifyConflictingTransactionsAsync( + IChainContext chainContext, + List returnSets, List conflictingSets) + { + var possibleConflicting = FindPossibleConflictingReturnSets(returnSets, conflictingSets); + var wrongTxnWithResources = await FindContractOfWrongResourcesAsync(chainContext, possibleConflicting); + return wrongTxnWithResources; + } - var txnWithResources = - await _resourceExtractionService.GetResourcesAsync(chainContext, transactions, CancellationToken.None); - txnWithResources = - txnWithResources.Where(t => t.TransactionResourceInfo.ParallelType == ParallelType.Parallelizable); + private List FindPossibleConflictingReturnSets(List returnSets, + List conflictingSets) + { + var existingKeys = new HashSet(returnSets.SelectMany(rs => rs.StateAccesses.Keys)); + var possibleConflictingKeys = new HashSet(conflictingSets.SelectMany(rs => rs.StateAccesses.Keys)); + possibleConflictingKeys.IntersectWith(existingKeys); + return returnSets.Concat(conflictingSets) + .Where(rs => rs.StateAccesses.Any(a => possibleConflictingKeys.Contains(a.Key))).ToList(); + } - var txnWithResourceList = txnWithResources.ToList(); - var readOnlyKeys = txnWithResourceList.GetReadOnlyPaths().Select(p=>p.ToStateKey()).ToList(); - var returnSetLookup = returnSets.ToDictionary(rs => rs.TransactionId, rs => rs); - var wrongTxnWithResources = new List(); - foreach (var txnWithResource in txnWithResourceList) - { - var extracted = new HashSet(txnWithResource.TransactionResourceInfo.WritePaths - .Concat(txnWithResource.TransactionResourceInfo.ReadPaths).Select(p => p.ToStateKey())); - extracted.ExceptWith(readOnlyKeys); - var actual = GetKeys(returnSetLookup[txnWithResource.Transaction.GetHash()]); - actual.ExceptWith(extracted); - if (actual.Count == 0) continue; - Logger.LogDebug($"Conflict keys:{string.Join(";", actual)}"); - wrongTxnWithResources.Add(txnWithResource); - } + private async Task> FindContractOfWrongResourcesAsync(IChainContext chainContext, + List returnSets) + { + var transactionIds = returnSets.Select(rs => rs.TransactionId); + var transactions = await _blockchainService.GetTransactionsAsync(transactionIds); - return wrongTxnWithResources; - } + var txnWithResources = + await _resourceExtractionService.GetResourcesAsync(chainContext, transactions, CancellationToken.None); + txnWithResources = + txnWithResources.Where(t => t.TransactionResourceInfo.ParallelType == ParallelType.Parallelizable); - private HashSet GetKeys(ExecutionReturnSet returnSet) + var txnWithResourceList = txnWithResources.ToList(); + var readOnlyKeys = txnWithResourceList.GetReadOnlyPaths().Select(p => p.ToStateKey()).ToList(); + var returnSetLookup = returnSets.ToDictionary(rs => rs.TransactionId, rs => rs); + var wrongTxnWithResources = new List(); + foreach (var txnWithResource in txnWithResourceList) { - return new HashSet(returnSet.StateAccesses.Keys); + var extracted = new HashSet(txnWithResource.TransactionResourceInfo.WritePaths + .Concat(txnWithResource.TransactionResourceInfo.ReadPaths).Select(p => p.ToStateKey())); + extracted.ExceptWith(readOnlyKeys); + var actual = GetKeys(returnSetLookup[txnWithResource.Transaction.GetHash()]); + actual.ExceptWith(extracted); + if (actual.Count == 0) continue; + Logger.LogDebug($"Conflict keys:{string.Join(";", actual)}"); + wrongTxnWithResources.Add(txnWithResource); } + return wrongTxnWithResources; + } + + private HashSet GetKeys(ExecutionReturnSet returnSet) + { + return new HashSet(returnSet.StateAccesses.Keys); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionsFoundInParallelGroupsEvent.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionsFoundInParallelGroupsEvent.cs index 26accbd0f4..fc030bd9fc 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionsFoundInParallelGroupsEvent.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/ConflictingTransactionsFoundInParallelGroupsEvent.cs @@ -1,22 +1,20 @@ using System.Collections.Generic; -using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public class ConflictingTransactionsFoundInParallelGroupsEvent { - public class ConflictingTransactionsFoundInParallelGroupsEvent + public ConflictingTransactionsFoundInParallelGroupsEvent( + BlockHeader blockHeader, + List existingSets, + List conflictingSets) { - public ConflictingTransactionsFoundInParallelGroupsEvent( - BlockHeader blockHeader, - List existingSets, - List conflictingSets) - { - BlockHeader = blockHeader; - ExistingSets = existingSets; - ConflictingSets = conflictingSets; - } - - public BlockHeader BlockHeader { get; set; } - public List ExistingSets { get; } - public List ConflictingSets { get; } + BlockHeader = blockHeader; + ExistingSets = existingSets; + ConflictingSets = conflictingSets; } + + public BlockHeader BlockHeader { get; set; } + public List ExistingSets { get; } + public List ConflictingSets { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/ExecutiveExtensions.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/ExecutiveExtensions.cs index 36c7989b7a..dbe21562bb 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/ExecutiveExtensions.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/ExecutiveExtensions.cs @@ -1,59 +1,55 @@ using System; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS2; using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS2; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +internal static class ExecutiveExtensions { - internal static class ExecutiveExtensions + public static async Task GetTransactionResourceInfoAsync(this IExecutive executive, + ITransactionContext transactionContext, Hash txId) { - public static async Task GetTransactionResourceInfoAsync(this IExecutive executive, - ITransactionContext transactionContext, Hash txId) - { - await executive.ApplyAsync(transactionContext); - if (!transactionContext.Trace.IsSuccessful()) - { - return NotParallelizable(txId, executive.ContractHash); - } + await executive.ApplyAsync(transactionContext); + if (!transactionContext.Trace.IsSuccessful()) return NotParallelizable(txId, executive.ContractHash); - try + try + { + var resourceInfo = ResourceInfo.Parser.ParseFrom(transactionContext.Trace.ReturnValue); + return new TransactionResourceInfo { - var resourceInfo = ResourceInfo.Parser.ParseFrom(transactionContext.Trace.ReturnValue); - return new TransactionResourceInfo + TransactionId = txId, + WritePaths = { - TransactionId = txId, - WritePaths = - { - resourceInfo.WritePaths - }, - ReadPaths = {resourceInfo.ReadPaths}, - ParallelType = resourceInfo.NonParallelizable - ? ParallelType.NonParallelizable - : ParallelType.Parallelizable, - ContractHash = executive.ContractHash - }; - } - catch (Exception) - { - return NotParallelizable(txId, executive.ContractHash); - } + resourceInfo.WritePaths + }, + ReadPaths = { resourceInfo.ReadPaths }, + ParallelType = resourceInfo.NonParallelizable + ? ParallelType.NonParallelizable + : ParallelType.Parallelizable, + ContractHash = executive.ContractHash + }; } - - internal static bool IsParallelizable(this IExecutive executive) + catch (Exception) { - return executive.Descriptors.Any(service => service.File.GetIdentity() == "acs2"); + return NotParallelizable(txId, executive.ContractHash); } + } - private static TransactionResourceInfo NotParallelizable(Hash transactionId,Hash codeHash) + internal static bool IsParallelizable(this IExecutive executive) + { + return executive.Descriptors.Any(service => service.File.GetIdentity() == "acs2"); + } + + private static TransactionResourceInfo NotParallelizable(Hash transactionId, Hash codeHash) + { + return new TransactionResourceInfo { - return new TransactionResourceInfo - { - TransactionId = transactionId, - ParallelType = ParallelType.NonParallelizable, - ContractHash = codeHash - }; - } + TransactionId = transactionId, + ParallelType = ParallelType.NonParallelizable, + ContractHash = codeHash + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/IConflictingTransactionIdentificationService.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/IConflictingTransactionIdentificationService.cs index 7a6706ba3f..8fa4be9c84 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/IConflictingTransactionIdentificationService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/IConflictingTransactionIdentificationService.cs @@ -1,13 +1,11 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel.Domain +namespace AElf.Kernel.SmartContract.Parallel.Domain; + +public interface IConflictingTransactionIdentificationService { - public interface IConflictingTransactionIdentificationService - { - Task> IdentifyConflictingTransactionsAsync( - IChainContext chainContext, List returnSets, - List conflictingSets); - } + Task> IdentifyConflictingTransactionsAsync( + IChainContext chainContext, List returnSets, + List conflictingSets); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/IResourceExtractionService.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/IResourceExtractionService.cs index ebc9e6585e..0111691164 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/IResourceExtractionService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/IResourceExtractionService.cs @@ -2,23 +2,21 @@ using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Events; -using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.TransactionPool; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public interface IResourceExtractionService { - public interface IResourceExtractionService - { - Task> GetResourcesAsync(IChainContext chainContext, - IEnumerable transactions, CancellationToken ct); + Task> GetResourcesAsync(IChainContext chainContext, + IEnumerable transactions, CancellationToken ct); + + Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData); - Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData); + Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData); - Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData); - - Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData); + Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData); - void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds); - } -} + void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds); +} \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/ITransactionGrouper.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/ITransactionGrouper.cs index 29e04bf442..0bb18d80d5 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/ITransactionGrouper.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/ITransactionGrouper.cs @@ -2,18 +2,17 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public interface ITransactionGrouper { - public interface ITransactionGrouper - { - Task GroupAsync(IChainContext chainContext, - List transactions); - } - - public class GroupedTransactions - { - public List> Parallelizables = new List>(); - public List NonParallelizables = new List(); - public List TransactionsWithoutContract = new List(); - } + Task GroupAsync(IChainContext chainContext, + List transactions); } + +public class GroupedTransactions +{ + public List NonParallelizables = new(); + public List> Parallelizables = new(); + public List TransactionsWithoutContract = new(); +} \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/NonparallelContractCodeProvider.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/NonparallelContractCodeProvider.cs index 794171eeae..308228bbe4 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/NonparallelContractCodeProvider.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/NonparallelContractCodeProvider.cs @@ -1,47 +1,46 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel.SmartContract.Application; using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Parallel.Domain +namespace AElf.Kernel.SmartContract.Parallel.Domain; + +public interface INonparallelContractCodeProvider +{ + Task GetNonparallelContractCodeAsync(IChainContext chainContext, Address address); + + Task SetNonparallelContractCodeAsync(IBlockIndex blockIndex, + IDictionary nonparallelContractCodes); +} + +public class NonparallelContractCodeProvider : BlockExecutedDataBaseProvider, + INonparallelContractCodeProvider, + ISingletonDependency { - public interface INonparallelContractCodeProvider + private const string BlockExecutedDataName = nameof(NonparallelContractCode); + + public NonparallelContractCodeProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - Task GetNonparallelContractCodeAsync(IChainContext chainContext, Address address); + } - Task SetNonparallelContractCodeAsync(IBlockIndex blockIndex, - IDictionary nonparallelContractCodes); + + public Task GetNonparallelContractCodeAsync(IChainContext chainContext, Address address) + { + var nonparallelContractCode = GetBlockExecutedData(chainContext, address); + return Task.FromResult(nonparallelContractCode); + } + + public async Task SetNonparallelContractCodeAsync(IBlockIndex blockIndex, + IDictionary nonparallelContractCodes) + { + await AddBlockExecutedDataAsync(blockIndex, nonparallelContractCodes); } - public class NonparallelContractCodeProvider : BlockExecutedDataBaseProvider, INonparallelContractCodeProvider, - ISingletonDependency + protected override string GetBlockExecutedDataName() { - private const string BlockExecutedDataName = nameof(NonparallelContractCode); - - public NonparallelContractCodeProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } - - - public Task GetNonparallelContractCodeAsync(IChainContext chainContext, Address address) - { - var nonparallelContractCode = GetBlockExecutedData(chainContext, address); - return Task.FromResult(nonparallelContractCode); - } - - public async Task SetNonparallelContractCodeAsync(IBlockIndex blockIndex, - IDictionary nonparallelContractCodes) - { - await AddBlockExecutedDataAsync(blockIndex, nonparallelContractCodes); - } - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/ResourceExtractionService.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/ResourceExtractionService.cs index d714e90501..028188e88b 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/ResourceExtractionService.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/ResourceExtractionService.cs @@ -4,277 +4,257 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS2; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Kernel.SmartContract.Parallel.Domain; -using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.TransactionPool; +using AElf.Standards.ACS2; using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public class ResourceExtractionService : IResourceExtractionService, ISingletonDependency { - public class ResourceExtractionService : IResourceExtractionService, ISingletonDependency + private readonly IBlockchainService _blockchainService; + private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; + + private readonly ConcurrentDictionary _resourceCache = new(); + + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ITransactionContextFactory _transactionContextFactory; + + public ResourceExtractionService(IBlockchainService blockchainService, + ISmartContractExecutiveService smartContractExecutiveService, + INonparallelContractCodeProvider nonparallelContractCodeProvider, + ITransactionContextFactory transactionContextFactory) { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractExecutiveService _smartContractExecutiveService; - private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; - private readonly ITransactionContextFactory _transactionContextFactory; - public ILogger Logger { get; set; } - - private readonly ConcurrentDictionary _resourceCache = - new ConcurrentDictionary(); - - public ResourceExtractionService(IBlockchainService blockchainService, - ISmartContractExecutiveService smartContractExecutiveService, - INonparallelContractCodeProvider nonparallelContractCodeProvider, - ITransactionContextFactory transactionContextFactory) - { - _smartContractExecutiveService = smartContractExecutiveService; - _nonparallelContractCodeProvider = nonparallelContractCodeProvider; - _transactionContextFactory = transactionContextFactory; - _blockchainService = blockchainService; + _smartContractExecutiveService = smartContractExecutiveService; + _nonparallelContractCodeProvider = nonparallelContractCodeProvider; + _transactionContextFactory = transactionContextFactory; + _blockchainService = blockchainService; - Logger = NullLogger.Instance; - } + Logger = NullLogger.Instance; + } - public async Task> GetResourcesAsync( - IChainContext chainContext, - IEnumerable transactions, CancellationToken ct) - { - // Parallel processing below (adding AsParallel) causes ReflectionTypeLoadException - var transactionResourceList = new List(); - var contractResourceInfoCache = new Dictionary(); - foreach (var t in transactions) - { - var transactionResourcePair = - await GetResourcesForOneWithCacheAsync(chainContext, t, ct, contractResourceInfoCache); - transactionResourceList.Add(transactionResourcePair); - } + public ILogger Logger { get; set; } - return transactionResourceList; + public async Task> GetResourcesAsync( + IChainContext chainContext, + IEnumerable transactions, CancellationToken ct) + { + // Parallel processing below (adding AsParallel) causes ReflectionTypeLoadException + var transactionResourceList = new List(); + var contractResourceInfoCache = new Dictionary(); + foreach (var t in transactions) + { + var transactionResourcePair = + await GetResourcesForOneWithCacheAsync(chainContext, t, ct, contractResourceInfoCache); + transactionResourceList.Add(transactionResourcePair); } - private async Task GetResourcesForOneWithCacheAsync( - IChainContext chainContext, - Transaction transaction, CancellationToken ct, - Dictionary contractResourceInfoCache) - { - if (ct.IsCancellationRequested) - return new TransactionWithResourceInfo - { - Transaction = transaction, - TransactionResourceInfo = new TransactionResourceInfo() - { - TransactionId = transaction.GetHash(), - ParallelType = ParallelType.NonParallelizable - } - }; + return transactionResourceList; + } + + public void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds) + { + ClearResourceCache(transactionIds); + } - if (_resourceCache.TryGetValue(transaction.GetHash(), out var resourceCache)) + private async Task GetResourcesForOneWithCacheAsync( + IChainContext chainContext, + Transaction transaction, CancellationToken ct, + Dictionary contractResourceInfoCache) + { + if (ct.IsCancellationRequested) + return new TransactionWithResourceInfo { - if (contractResourceInfoCache.TryGetValue(transaction.To, out var contractResourceInfo)) + Transaction = transaction, + TransactionResourceInfo = new TransactionResourceInfo { - if (resourceCache.ResourceInfo.ContractHash == contractResourceInfo.CodeHash && - resourceCache.ResourceInfo.IsNonparallelContractCode == contractResourceInfo.IsNonparallelContractCode) - { - return new TransactionWithResourceInfo - { - Transaction = transaction, - TransactionResourceInfo = resourceCache.ResourceInfo - }; - } + TransactionId = transaction.GetHash(), + ParallelType = ParallelType.NonParallelizable } - } + }; - var resourceInfo = await GetResourcesForOneAsync(chainContext, transaction, ct); - if (!contractResourceInfoCache.TryGetValue(transaction.To, out _)) - { - contractResourceInfoCache[transaction.To] = new ContractResourceInfo - { - CodeHash = resourceInfo.ContractHash, - IsNonparallelContractCode = resourceInfo.IsNonparallelContractCode - }; - } + if (_resourceCache.TryGetValue(transaction.GetHash(), out var resourceCache)) + if (contractResourceInfoCache.TryGetValue(transaction.To, out var contractResourceInfo)) + if (resourceCache.ResourceInfo.ContractHash == contractResourceInfo.CodeHash && + resourceCache.ResourceInfo.IsNonparallelContractCode == + contractResourceInfo.IsNonparallelContractCode) + return new TransactionWithResourceInfo + { + Transaction = transaction, + TransactionResourceInfo = resourceCache.ResourceInfo + }; - return new TransactionWithResourceInfo + var resourceInfo = await GetResourcesForOneAsync(chainContext, transaction, ct); + if (!contractResourceInfoCache.TryGetValue(transaction.To, out _)) + contractResourceInfoCache[transaction.To] = new ContractResourceInfo { - Transaction = transaction, - TransactionResourceInfo = resourceInfo + CodeHash = resourceInfo.ContractHash, + IsNonparallelContractCode = resourceInfo.IsNonparallelContractCode }; - } - private async Task GetResourcesForOneAsync(IChainContext chainContext, - Transaction transaction, CancellationToken ct) + return new TransactionWithResourceInfo { - IExecutive executive = null; - var address = transaction.To; - - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); - if (!executive.IsParallelizable()) - { - return new TransactionResourceInfo - { - TransactionId = transaction.GetHash(), - ParallelType = ParallelType.NonParallelizable, - ContractHash = executive.ContractHash - }; - } + Transaction = transaction, + TransactionResourceInfo = resourceInfo + }; + } - var nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, address); - if (nonparallelContractCode != null && nonparallelContractCode.CodeHash == executive.ContractHash) - { - return new TransactionResourceInfo - { - TransactionId = transaction.GetHash(), - ParallelType = ParallelType.NonParallelizable, - ContractHash = executive.ContractHash, - IsNonparallelContractCode = true - }; - } + private async Task GetResourcesForOneAsync(IChainContext chainContext, + Transaction transaction, CancellationToken ct) + { + IExecutive executive = null; + var address = transaction.To; - if (_resourceCache.TryGetValue(transaction.GetHash(), out var resourceCache) && - executive.ContractHash == resourceCache.ResourceInfo.ContractHash && - resourceCache.ResourceInfo.IsNonparallelContractCode == false) + try + { + executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); + if (!executive.IsParallelizable()) + return new TransactionResourceInfo { - return resourceCache.ResourceInfo; - } + TransactionId = transaction.GetHash(), + ParallelType = ParallelType.NonParallelizable, + ContractHash = executive.ContractHash + }; - var txContext = GetTransactionContext(chainContext, transaction.To, transaction.ToByteString()); - var resourceInfo = await executive.GetTransactionResourceInfoAsync(txContext, transaction.GetHash()); - // Try storing in cache here - return resourceInfo; - } - catch (SmartContractFindRegistrationException) - { + var nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, address); + if (nonparallelContractCode != null && nonparallelContractCode.CodeHash == executive.ContractHash) return new TransactionResourceInfo { TransactionId = transaction.GetHash(), - ParallelType = ParallelType.InvalidContractAddress + ParallelType = ParallelType.NonParallelizable, + ContractHash = executive.ContractHash, + IsNonparallelContractCode = true }; - } - finally + + if (_resourceCache.TryGetValue(transaction.GetHash(), out var resourceCache) && + executive.ContractHash == resourceCache.ResourceInfo.ContractHash && + resourceCache.ResourceInfo.IsNonparallelContractCode == false) + return resourceCache.ResourceInfo; + + var txContext = GetTransactionContext(chainContext, transaction.To, transaction.ToByteString()); + var resourceInfo = await executive.GetTransactionResourceInfoAsync(txContext, transaction.GetHash()); + // Try storing in cache here + return resourceInfo; + } + catch (SmartContractFindRegistrationException) + { + return new TransactionResourceInfo { - if (executive != null) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - } + TransactionId = transaction.GetHash(), + ParallelType = ParallelType.InvalidContractAddress + }; } - - public void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds) + finally { - ClearResourceCache(transactionIds); + if (executive != null) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); } + } - #region Event Handler Methods + private async Task GetChainContextAsync() + { + var chain = await _blockchainService.GetChainAsync(); + if (chain == null) return null; - public async Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData) + var chainContext = new ChainContext { - var chainContext = await GetChainContextAsync(); - var transaction = eventData.Transaction; - - var resourceInfo = await GetResourcesForOneAsync(chainContext, transaction, CancellationToken.None); - _resourceCache.TryAdd(transaction.GetHash(), - new TransactionResourceCache(resourceInfo, transaction.To, - eventData.Transaction.GetExpiryBlockNumber())); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + return chainContext; + } - public async Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData) + private ITransactionContext GetTransactionContext(IChainContext chainContext, Address contractAddress, + ByteString param) + { + var generatedTxn = new Transaction { - try - { - ClearResourceCache(_resourceCache - .Where(c => c.Value.ResourceUsedBlockHeight <= eventData.BlockHeight) - .Select(c => c.Key).Distinct().ToList()); - } - catch (InvalidOperationException e) - { - Logger.LogError(e, "Unexpected case occured when clear resource info."); - } - - await Task.CompletedTask; - } + From = contractAddress, + To = contractAddress, + MethodName = nameof(ACS2BaseContainer.ACS2BaseStub.GetResourceInfo), + Params = param, + Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) + }; + + var txContext = _transactionContextFactory.Create(generatedTxn, chainContext); + return txContext; + } - public async Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData) - { - ClearResourceCache(eventData.Block.TransactionIds); + private class ContractResourceInfo + { + public Hash CodeHash { get; set; } - await Task.CompletedTask; - } + public bool IsNonparallelContractCode { get; set; } + } - private void ClearResourceCache(IEnumerable transactions) - { - foreach (var transactionId in transactions) - { - _resourceCache.TryRemove(transactionId, out _); - } + #region Event Handler Methods - Logger.LogDebug($"Resource cache size after cleanup: {_resourceCache.Count}"); - } + public async Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData) + { + var chainContext = await GetChainContextAsync(); + var transaction = eventData.Transaction; - #endregion + var resourceInfo = await GetResourcesForOneAsync(chainContext, transaction, CancellationToken.None); + _resourceCache.TryAdd(transaction.GetHash(), + new TransactionResourceCache(resourceInfo, transaction.To, + eventData.Transaction.GetExpiryBlockNumber())); + } - private async Task GetChainContextAsync() + public async Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData) + { + try { - var chain = await _blockchainService.GetChainAsync(); - if (chain == null) - { - return null; - } - - var chainContext = new ChainContext() - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - return chainContext; + ClearResourceCache(_resourceCache + .Where(c => c.Value.ResourceUsedBlockHeight <= eventData.BlockHeight) + .Select(c => c.Key).Distinct().ToList()); } - - private ITransactionContext GetTransactionContext(IChainContext chainContext, Address contractAddress, ByteString param) + catch (InvalidOperationException e) { - var generatedTxn = new Transaction - { - From = contractAddress, - To = contractAddress, - MethodName = nameof(ACS2BaseContainer.ACS2BaseStub.GetResourceInfo), - Params = param, - Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) - }; - - var txContext = _transactionContextFactory.Create(generatedTxn, chainContext); - return txContext; + Logger.LogError(e, "Unexpected case occured when clear resource info."); } - - private class ContractResourceInfo - { - public Hash CodeHash { get; set; } - public bool IsNonparallelContractCode { get; set; } - } + await Task.CompletedTask; } - internal class TransactionResourceCache + public async Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData) { - public long ResourceUsedBlockHeight { get; set; } - public readonly TransactionResourceInfo ResourceInfo; - public readonly Address Address; + ClearResourceCache(eventData.Block.TransactionIds); - public TransactionResourceCache(TransactionResourceInfo resourceInfo, Address address, - long resourceUsedBlockHeight) - { - ResourceUsedBlockHeight = resourceUsedBlockHeight; - ResourceInfo = resourceInfo; - Address = address; - } + await Task.CompletedTask; } + + private void ClearResourceCache(IEnumerable transactions) + { + foreach (var transactionId in transactions) _resourceCache.TryRemove(transactionId, out _); + + Logger.LogDebug($"Resource cache size after cleanup: {_resourceCache.Count}"); + } + + #endregion +} + +internal class TransactionResourceCache +{ + public readonly Address Address; + public readonly TransactionResourceInfo ResourceInfo; + + public TransactionResourceCache(TransactionResourceInfo resourceInfo, Address address, + long resourceUsedBlockHeight) + { + ResourceUsedBlockHeight = resourceUsedBlockHeight; + ResourceInfo = resourceInfo; + Address = address; + } + + public long ResourceUsedBlockHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionGrouper.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionGrouper.cs index 870f21667d..75aefafbcd 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionGrouper.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionGrouper.cs @@ -9,165 +9,167 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public class GrouperOptions +{ + public int GroupingTimeOut { get; set; } = 500; // ms + public int MaxTransactions { get; set; } = int.MaxValue; // Maximum transactions to group +} + +public class TransactionGrouper : ITransactionGrouper, ISingletonDependency { - public class GrouperOptions + private readonly GrouperOptions _options; + private readonly IResourceExtractionService _resourceExtractionService; + + public TransactionGrouper(IResourceExtractionService resourceExtractionService, + IOptionsSnapshot options) { - public int GroupingTimeOut { get; set; } = 500; // ms - public int MaxTransactions { get; set; } = int.MaxValue; // Maximum transactions to group + _resourceExtractionService = resourceExtractionService; + _options = options.Value; + Logger = NullLogger.Instance; } - public class TransactionGrouper : ITransactionGrouper, ISingletonDependency + public ILogger Logger { get; set; } + + public async Task GroupAsync(IChainContext chainContext, List transactions) { - private readonly IResourceExtractionService _resourceExtractionService; - private readonly GrouperOptions _options; - public ILogger Logger { get; set; } + Logger.LogTrace("Entered GroupAsync"); - public TransactionGrouper(IResourceExtractionService resourceExtractionService, - IOptionsSnapshot options) - { - _resourceExtractionService = resourceExtractionService; - _options = options.Value; - Logger = NullLogger.Instance; - } + var toBeGrouped = GetTransactionsToBeGrouped(transactions, out var groupedTransactions); - public async Task GroupAsync(IChainContext chainContext, List transactions) + using (var cts = new CancellationTokenSource(_options.GroupingTimeOut)) { - Logger.LogTrace("Entered GroupAsync"); + var parallelizables = new List(); - var toBeGrouped = GetTransactionsToBeGrouped(transactions, out var groupedTransactions); + Logger.LogTrace("Extracting resources for transactions."); + var txsWithResources = + await _resourceExtractionService.GetResourcesAsync(chainContext, toBeGrouped, cts.Token); + Logger.LogTrace("Completed resource extraction."); - using (var cts = new CancellationTokenSource(_options.GroupingTimeOut)) + foreach (var twr in txsWithResources) { - var parallelizables = new List(); + if (twr.TransactionResourceInfo.ParallelType == ParallelType.InvalidContractAddress) + { + groupedTransactions.TransactionsWithoutContract.Add(twr.Transaction); + continue; + } - Logger.LogTrace("Extracting resources for transactions."); - var txsWithResources = - await _resourceExtractionService.GetResourcesAsync(chainContext, toBeGrouped, cts.Token); - Logger.LogTrace("Completed resource extraction."); + // If timed out at this point, return all transactions as non-parallelizable + if (cts.IsCancellationRequested) + { + groupedTransactions.NonParallelizables.Add(twr.Transaction); + continue; + } - foreach (var twr in txsWithResources) + if (twr.TransactionResourceInfo.ParallelType == ParallelType.NonParallelizable) { - if (twr.TransactionResourceInfo.ParallelType == ParallelType.InvalidContractAddress) - { - groupedTransactions.TransactionsWithoutContract.Add(twr.Transaction); - continue; - } - - // If timed out at this point, return all transactions as non-parallelizable - if (cts.IsCancellationRequested) - { - groupedTransactions.NonParallelizables.Add(twr.Transaction); - continue; - } - - if (twr.TransactionResourceInfo.ParallelType == ParallelType.NonParallelizable) - { - groupedTransactions.NonParallelizables.Add(twr.Transaction); - continue; - } - - if (twr.TransactionResourceInfo.WritePaths.Count == 0 && twr.TransactionResourceInfo.ReadPaths.Count == 0) - { - // groups.Add(new List() {twr.Item1}); // Run in their dedicated group - groupedTransactions.NonParallelizables.Add(twr.Transaction); - continue; - } - - parallelizables.Add(twr); + groupedTransactions.NonParallelizables.Add(twr.Transaction); + continue; } - groupedTransactions.Parallelizables.AddRange(GroupParallelizables(parallelizables)); + if (twr.TransactionResourceInfo.WritePaths.Count == 0 && + twr.TransactionResourceInfo.ReadPaths.Count == 0) + { + // groups.Add(new List() {twr.Item1}); // Run in their dedicated group + groupedTransactions.NonParallelizables.Add(twr.Transaction); + continue; + } - Logger.LogTrace("Completed transaction grouping."); + parallelizables.Add(twr); } - Logger.LogDebug($"From {transactions.Count} transactions, grouped {groupedTransactions.Parallelizables.Sum(p=>p.Count)} txs into " + - $"{groupedTransactions.Parallelizables.Count} groups, left " + - $"{groupedTransactions.NonParallelizables.Count} as non-parallelizable transactions."); + groupedTransactions.Parallelizables.AddRange(GroupParallelizables(parallelizables)); - return groupedTransactions; + Logger.LogTrace("Completed transaction grouping."); } - private List GetTransactionsToBeGrouped(List transactions, - out GroupedTransactions groupedTransactions) - { - List toBeGrouped; - groupedTransactions = new GroupedTransactions(); - if (transactions.Count > _options.MaxTransactions) - { - groupedTransactions.NonParallelizables.AddRange( - transactions.GetRange(_options.MaxTransactions, transactions.Count - _options.MaxTransactions)); + Logger.LogDebug( + $"From {transactions.Count} transactions, grouped {groupedTransactions.Parallelizables.Sum(p => p.Count)} txs into " + + $"{groupedTransactions.Parallelizables.Count} groups, left " + + $"{groupedTransactions.NonParallelizables.Count} as non-parallelizable transactions."); - toBeGrouped = transactions.GetRange(0, _options.MaxTransactions); - } - else - { - toBeGrouped = transactions; - } + return groupedTransactions; + } - return toBeGrouped; + private List GetTransactionsToBeGrouped(List transactions, + out GroupedTransactions groupedTransactions) + { + List toBeGrouped; + groupedTransactions = new GroupedTransactions(); + if (transactions.Count > _options.MaxTransactions) + { + groupedTransactions.NonParallelizables.AddRange( + transactions.GetRange(_options.MaxTransactions, transactions.Count - _options.MaxTransactions)); + + toBeGrouped = transactions.GetRange(0, _options.MaxTransactions); + } + else + { + toBeGrouped = transactions; } - private List> GroupParallelizables(List txsWithResources) + return toBeGrouped; + } + + private List> GroupParallelizables(List txsWithResources) + { + var resourceUnionSet = new Dictionary(); + var transactionResourceHandle = new Dictionary(); + var groups = new List>(); + var readOnlyPaths = txsWithResources.GetReadOnlyPaths(); + foreach (var txWithResource in txsWithResources) { - var resourceUnionSet = new Dictionary(); - var transactionResourceHandle = new Dictionary(); - var groups = new List>(); - var readOnlyPaths = txsWithResources.GetReadOnlyPaths(); - foreach (var txWithResource in txsWithResources) + UnionFindNode first = null; + var transaction = txWithResource.Transaction; + var transactionResourceInfo = txWithResource.TransactionResourceInfo; + + // Add resources to disjoint-set, later each resource will be connected to a node id, which will be our group id + foreach (var resource in transactionResourceInfo.WritePaths.Concat(transactionResourceInfo.ReadPaths) + .Where(p => !readOnlyPaths.Contains(p)) + .Select(p => p.GetHashCode())) { - UnionFindNode first = null; - var transaction = txWithResource.Transaction; - var transactionResourceInfo = txWithResource.TransactionResourceInfo; - - // Add resources to disjoint-set, later each resource will be connected to a node id, which will be our group id - foreach (var resource in transactionResourceInfo.WritePaths.Concat(transactionResourceInfo.ReadPaths) - .Where(p => !readOnlyPaths.Contains(p)) - .Select(p => p.GetHashCode())) + if (!resourceUnionSet.TryGetValue(resource, out var node)) { - if (!resourceUnionSet.TryGetValue(resource, out var node)) - { - node = new UnionFindNode(); - resourceUnionSet.Add(resource, node); - } - - if (first == null) - { - first = node; - transactionResourceHandle.Add(transaction, resource); - } - else - { - node.Union(first); - } + node = new UnionFindNode(); + resourceUnionSet.Add(resource, node); } - } - var grouped = new Dictionary>(); + if (first == null) + { + first = node; + transactionResourceHandle.Add(transaction, resource); + } + else + { + node.Union(first); + } + } + } - foreach (var txWithResource in txsWithResources) - { - var transaction = txWithResource.Transaction; - if (!transactionResourceHandle.TryGetValue(transaction, out var firstResource)) - continue; + var grouped = new Dictionary>(); - // Node Id will be our group id - var gId = resourceUnionSet[firstResource].Find().NodeId; + foreach (var txWithResource in txsWithResources) + { + var transaction = txWithResource.Transaction; + if (!transactionResourceHandle.TryGetValue(transaction, out var firstResource)) + continue; - if (!grouped.TryGetValue(gId, out var gTransactions)) - { - gTransactions = new List(); - grouped.Add(gId, gTransactions); - } + // Node Id will be our group id + var gId = resourceUnionSet[firstResource].Find().NodeId; - // Add transaction to its group - gTransactions.Add(transaction); + if (!grouped.TryGetValue(gId, out var gTransactions)) + { + gTransactions = new List(); + grouped.Add(gId, gTransactions); } - groups.AddRange(grouped.Values); - - return groups; + // Add transaction to its group + gTransactions.Add(transaction); } + + groups.AddRange(grouped.Values); + + return groups; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfo.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfo.cs index c8eee773de..d67494660c 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfo.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfo.cs @@ -1,10 +1,9 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +public class TransactionWithResourceInfo { - public class TransactionWithResourceInfo - { - public Transaction Transaction { get; set; } - public TransactionResourceInfo TransactionResourceInfo { get; set; } - } + public Transaction Transaction { get; set; } + public TransactionResourceInfo TransactionResourceInfo { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfoExtensions.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfoExtensions.cs index 0dd9297455..95e0704ae9 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfoExtensions.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/TransactionWithResourceInfoExtensions.cs @@ -2,19 +2,20 @@ using System.Linq; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel.Domain +namespace AElf.Kernel.SmartContract.Parallel.Domain; + +public static class TransactionWithResourceInfoExtensions { - public static class TransactionWithResourceInfoExtensions + public static HashSet GetReadOnlyPaths( + this List transactionWithResourceInfos) { - public static HashSet GetReadOnlyPaths( - this List transactionWithResourceInfos) - { - var readPaths = - new HashSet(transactionWithResourceInfos.SelectMany(r => r.TransactionResourceInfo.ReadPaths)); - var writePaths = - new HashSet(transactionWithResourceInfos.SelectMany(r => r.TransactionResourceInfo.WritePaths)); - readPaths.ExceptWith(writePaths); - return readPaths; - } + var readPaths = + new HashSet( + transactionWithResourceInfos.SelectMany(r => r.TransactionResourceInfo.ReadPaths)); + var writePaths = + new HashSet( + transactionWithResourceInfos.SelectMany(r => r.TransactionResourceInfo.WritePaths)); + readPaths.ExceptWith(writePaths); + return readPaths; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/Domain/UnionFindNode.cs b/src/AElf.Kernel.SmartContract.Parallel/Domain/UnionFindNode.cs index 8b97f5d56b..033c9eac25 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/Domain/UnionFindNode.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/Domain/UnionFindNode.cs @@ -1,79 +1,77 @@ using System; using System.Threading; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +/// +/// A UnionFindNode represents a set of nodes that it is a member of. +/// You can get the unique representative node of the set a given node is in by using the Find method. +/// Two nodes are in the same set when their Find methods return the same representative. +/// The IsUnionedWith method will check if two nodes' sets are the same (i.e. the nodes have the same representative). +/// You can merge the sets two nodes are in by using the Union operation. +/// There is no way to split sets after they have been merged. +/// +public class UnionFindNode { - /// - /// A UnionFindNode represents a set of nodes that it is a member of. - /// - /// You can get the unique representative node of the set a given node is in by using the Find method. - /// Two nodes are in the same set when their Find methods return the same representative. - /// The IsUnionedWith method will check if two nodes' sets are the same (i.e. the nodes have the same representative). - /// - /// You can merge the sets two nodes are in by using the Union operation. - /// There is no way to split sets after they have been merged. - /// - public class UnionFindNode - { - private static int _nextId = 0; - public int NodeId { get; private set; } - private UnionFindNode _parent; + private static int _nextId; + private UnionFindNode _parent; - /// - /// Creates a new disjoint node, representative of a set containing only the new node. - /// - public UnionFindNode() { - _parent = this; - NodeId = Interlocked.Increment(ref _nextId); - } + /// + /// Creates a new disjoint node, representative of a set containing only the new node. + /// + public UnionFindNode() + { + _parent = this; + NodeId = Interlocked.Increment(ref _nextId); + } - /// - /// Returns the current representative of the set this node is in. - /// Note that the representative is only accurate untl the next Union operation. - /// - public UnionFindNode Find() { - if (!ReferenceEquals(_parent, this)) _parent = _parent.Find(); - return _parent; - } + public int NodeId { get; } - /// - /// Determines whether or not this node and the other node are in the same set. - /// - public bool IsUnionedWith(UnionFindNode other) { - if (other == null) throw new ArgumentNullException("other"); - return ReferenceEquals(Find(), other.Find()); - } + /// + /// Returns the current representative of the set this node is in. + /// Note that the representative is only accurate untl the next Union operation. + /// + public UnionFindNode Find() + { + if (!ReferenceEquals(_parent, this)) _parent = _parent.Find(); + return _parent; + } + + /// + /// Determines whether or not this node and the other node are in the same set. + /// + public bool IsUnionedWith(UnionFindNode other) + { + if (other == null) throw new ArgumentNullException("other"); + return ReferenceEquals(Find(), other.Find()); + } - /// - /// Merges the sets represented by this node and the other node into a single set. - /// Returns whether or not the nodes were disjoint before the union operation (i.e. if the operation had an effect). - /// - /// True when the union had an effect, false when the nodes were already in the same set. - public bool Union(UnionFindNode other) { - if (other == null) throw new ArgumentNullException("other"); - var root1 = this.Find(); - var root2 = other.Find(); - if (ReferenceEquals(root1, root2)) return false; + /// + /// Merges the sets represented by this node and the other node into a single set. + /// Returns whether or not the nodes were disjoint before the union operation (i.e. if the operation had an effect). + /// + /// True when the union had an effect, false when the nodes were already in the same set. + public bool Union(UnionFindNode other) + { + if (other == null) throw new ArgumentNullException("other"); + var root1 = Find(); + var root2 = other.Find(); + if (ReferenceEquals(root1, root2)) return false; - if (root1.NodeId < root2.NodeId) - { - root2._parent = root1; - } - else - { - root1._parent = root2; - } - /* - if (root1._rank < root2._rank) { - root1._parent = root2; - } else if (root1._rank > root2._rank) { - root2._parent = root1; - } else { - root2._parent = root1; - root1._rank++; - } - */ - return true; + if (root1.NodeId < root2.NodeId) + root2._parent = root1; + else + root1._parent = root2; + /* + if (root1._rank < root2._rank) { + root1._parent = root2; + } else if (root1._rank > root2._rank) { + root2._parent = root1; + } else { + root2._parent = root1; + root1._rank++; } + */ + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Parallel/ParallelExecutionModule.cs b/src/AElf.Kernel.SmartContract.Parallel/ParallelExecutionModule.cs index 80d86d0d7a..3cafeda0b9 100644 --- a/src/AElf.Kernel.SmartContract.Parallel/ParallelExecutionModule.cs +++ b/src/AElf.Kernel.SmartContract.Parallel/ParallelExecutionModule.cs @@ -5,17 +5,16 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.Parallel +namespace AElf.Kernel.SmartContract.Parallel; + +[DependsOn(typeof(SmartContractAElfModule))] +public class ParallelExecutionModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule))] - public class ParallelExecutionModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddTransient(); + context.Services + .AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/AElf.Kernel.SmartContract.Shared.csproj b/src/AElf.Kernel.SmartContract.Shared/AElf.Kernel.SmartContract.Shared.csproj index 19bfba3812..c69bed6d92 100644 --- a/src/AElf.Kernel.SmartContract.Shared/AElf.Kernel.SmartContract.Shared.csproj +++ b/src/AElf.Kernel.SmartContract.Shared/AElf.Kernel.SmartContract.Shared.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,7 +10,7 @@ - + diff --git a/src/AElf.Kernel.SmartContract.Shared/ContextVariableDictionary.cs b/src/AElf.Kernel.SmartContract.Shared/ContextVariableDictionary.cs index 76a13b6c83..7ca1953d70 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ContextVariableDictionary.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ContextVariableDictionary.cs @@ -2,34 +2,30 @@ using System.Collections.ObjectModel; using System.Linq; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +/// +/// Convention: Use ',' as separator. +/// +public class ContextVariableDictionary : ReadOnlyDictionary { - /// - /// Convention: Use ',' as separator. - /// - public class ContextVariableDictionary : ReadOnlyDictionary + public const string NativeSymbolName = nameof(NativeSymbol); + + private readonly Dictionary _stringArrayDictionary = new(); + + public ContextVariableDictionary(IDictionary dictionary) : base(dictionary) + { + } + + public string NativeSymbol => this[nameof(NativeSymbol)]; + + public IEnumerable GetStringArray(string key) { - public ContextVariableDictionary(IDictionary dictionary) : base(dictionary) - { - } - - public string NativeSymbol => this[nameof(NativeSymbol)]; - - public const string NativeSymbolName = nameof(NativeSymbol); - - private readonly Dictionary _stringArrayDictionary = new Dictionary(); - - public IEnumerable GetStringArray(string key) - { - if (_stringArrayDictionary.TryGetValue(key, out var stringArray)) - return stringArray; - if (!ContainsKey(key)) - { - return new List(); - } - stringArray = this[key].Split(',').ToArray(); - _stringArrayDictionary[key] = stringArray; + if (_stringArrayDictionary.TryGetValue(key, out var stringArray)) return stringArray; - } + if (!ContainsKey(key)) return new List(); + stringArray = this[key].Split(',').ToArray(); + _stringArrayDictionary[key] = stringArray; + return stringArray; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/IExecutionObserver.cs b/src/AElf.Kernel.SmartContract.Shared/IExecutionObserver.cs index cb03e37103..be14244225 100644 --- a/src/AElf.Kernel.SmartContract.Shared/IExecutionObserver.cs +++ b/src/AElf.Kernel.SmartContract.Shared/IExecutionObserver.cs @@ -1,13 +1,12 @@ -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface IExecutionObserver { - public interface IExecutionObserver - { - void BranchCount(); + void BranchCount(); + + void CallCount(); - void CallCount(); + int GetCallCount(); - int GetCallCount(); - - int GetBranchCount(); - } + int GetBranchCount(); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index af81797146..35355e0851 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -1,192 +1,188 @@ using System; using System.Collections.Generic; -using System.Numerics; using System.Runtime.Serialization; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +/// +/// The transaction execution context in the smart contract. +/// +public interface ISmartContractBridgeContext { - /// - /// The transaction execution context in the smart contract. - /// - public interface ISmartContractBridgeContext - { - int ChainId { get; } + int ChainId { get; } - ContextVariableDictionary Variables { get; } + ContextVariableDictionary Variables { get; } - void LogDebug(Func func); + Hash TransactionId { get; } - void FireLogEvent(LogEvent logEvent); + Address Sender { get; } - Hash TransactionId { get; } + Address Self { get; } - Address Sender { get; } + Address Origin { get; } - Address Self { get; } + Hash OriginTransactionId { get; } - Address Origin { get; } + long CurrentHeight { get; } - Hash OriginTransactionId { get; } + Timestamp CurrentBlockTime { get; } + Hash PreviousBlockHash { get; } - long CurrentHeight { get; } + IStateProvider StateProvider { get; } - Timestamp CurrentBlockTime { get; } - Hash PreviousBlockHash { get; } + void LogDebug(Func func); - byte[] RecoverPublicKey(); + void FireLogEvent(LogEvent logEvent); - List GetPreviousBlockTransactions(); + byte[] RecoverPublicKey(); - bool VerifySignature(Transaction tx); + List GetPreviousBlockTransactions(); - void DeployContract(Address address, SmartContractRegistration registration, Hash name); + bool VerifySignature(Transaction tx); - void UpdateContract(Address address, SmartContractRegistration registration, Hash name); + void DeployContract(Address address, SmartContractRegistration registration, Hash name); - T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) - where T : IMessage, new(); + void UpdateContract(Address address, SmartContractRegistration registration, Hash name); - void SendInline(Address toAddress, string methodName, ByteString args); + T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) + where T : IMessage, new(); - void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args); + void SendInline(Address toAddress, string methodName, ByteString args); - void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, - ByteString args); + void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args); + void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, + ByteString args); - Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress); - Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, - Address contractAddress); + Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress); - Address GetZeroSmartContractAddress(); + Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, + Address contractAddress); - Address GetZeroSmartContractAddress(int chainId); + Address GetZeroSmartContractAddress(); - Address GetContractAddressByName(string hash); + Address GetZeroSmartContractAddress(int chainId); - IReadOnlyDictionary GetSystemContractNameToAddressMapping(); + Address GetContractAddressByName(string hash); - IStateProvider StateProvider { get; } + IReadOnlyDictionary GetSystemContractNameToAddressMapping(); - Hash GenerateId(Address contractAddress, IEnumerable bytes); + Hash GenerateId(Address contractAddress, IEnumerable bytes); - Hash GetRandomHash(Hash fromHash); + Hash GetRandomHash(Hash fromHash); - long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue); + long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue); - object ValidateStateSize(object obj); - } + object ValidateStateSize(object obj); +} - [Serializable] - public class SmartContractBridgeException : Exception +[Serializable] +public class SmartContractBridgeException : Exception +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public SmartContractBridgeException() { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // - - public SmartContractBridgeException() - { - } - - public SmartContractBridgeException(string message) : base(message) - { - } - - public SmartContractBridgeException(string message, Exception inner) : base(message, inner) - { - } - - protected SmartContractBridgeException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } } - [Serializable] - public class NoPermissionException : SmartContractBridgeException + public SmartContractBridgeException(string message) : base(message) { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // + } - public NoPermissionException() - { - } + public SmartContractBridgeException(string message, Exception inner) : base(message, inner) + { + } - public NoPermissionException(string message) : base(message) - { - } + protected SmartContractBridgeException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { + } +} - public NoPermissionException(string message, Exception inner) : base(message, inner) - { - } +[Serializable] +public class NoPermissionException : SmartContractBridgeException +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public NoPermissionException() + { + } - protected NoPermissionException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + public NoPermissionException(string message) : base(message) + { } + public NoPermissionException(string message, Exception inner) : base(message, inner) + { + } - [Serializable] - public class ContractCallException : SmartContractBridgeException + protected NoPermissionException( + SerializationInfo info, + StreamingContext context) : base(info, context) { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // + } +} - public ContractCallException() - { - } +[Serializable] +public class ContractCallException : SmartContractBridgeException +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // + + public ContractCallException() + { + } - public ContractCallException(string message) : base(message) - { - } + public ContractCallException(string message) : base(message) + { + } - public ContractCallException(string message, Exception inner) : base(message, inner) - { - } + public ContractCallException(string message, Exception inner) : base(message, inner) + { + } - protected ContractCallException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + protected ContractCallException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { } +} - [Serializable] - public class StateOverSizeException : SmartContractBridgeException +[Serializable] +public class StateOverSizeException : SmartContractBridgeException +{ + public StateOverSizeException() { - public StateOverSizeException() - { - } + } - public StateOverSizeException(string message) : base(message) - { - } + public StateOverSizeException(string message) : base(message) + { + } - public StateOverSizeException(string message, Exception inner) : base(message, inner) - { - } + public StateOverSizeException(string message, Exception inner) : base(message, inner) + { + } - protected StateOverSizeException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } + protected StateOverSizeException(SerializationInfo info, StreamingContext context) : base(info, context) + { } - } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/IStateProvider.cs b/src/AElf.Kernel.SmartContract.Shared/IStateProvider.cs index 5f079698b0..5b1813f2f8 100644 --- a/src/AElf.Kernel.SmartContract.Shared/IStateProvider.cs +++ b/src/AElf.Kernel.SmartContract.Shared/IStateProvider.cs @@ -1,9 +1,8 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface IStateProvider { - public interface IStateProvider - { - byte[] Get(StatePath path); - } + byte[] Get(StatePath path); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/AElf.Kernel.SmartContract.csproj b/src/AElf.Kernel.SmartContract/AElf.Kernel.SmartContract.csproj index f6172045bc..b4023b774c 100644 --- a/src/AElf.Kernel.SmartContract/AElf.Kernel.SmartContract.csproj +++ b/src/AElf.Kernel.SmartContract/AElf.Kernel.SmartContract.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Kernel.SmartContract @@ -7,12 +7,12 @@ High level smart contract definitions and core functionality implementation. - + - - - + + + diff --git a/src/AElf.Kernel.SmartContract/Application/ChainContextWithTieredStateCache.cs b/src/AElf.Kernel.SmartContract/Application/ChainContextWithTieredStateCache.cs index afb4615ae0..6c9a986d2b 100644 --- a/src/AElf.Kernel.SmartContract/Application/ChainContextWithTieredStateCache.cs +++ b/src/AElf.Kernel.SmartContract/Application/ChainContextWithTieredStateCache.cs @@ -1,31 +1,30 @@ using AElf.Kernel.SmartContract.Domain; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class ChainContextWithTieredStateCache : IChainContext { - public class ChainContextWithTieredStateCache : IChainContext + public ChainContextWithTieredStateCache(IChainContext chainContext, TieredStateCache stateCache) : this( + chainContext.BlockHash, chainContext.BlockHeight, stateCache) { - public ChainContextWithTieredStateCache(IChainContext chainContext, TieredStateCache stateCache) : this( - chainContext.BlockHash, chainContext.BlockHeight, stateCache) - { - } - - public ChainContextWithTieredStateCache(Hash blockHash, long blockHeight, TieredStateCache stateCache) - { - BlockHeight = blockHeight; - BlockHash = blockHash; - StateCache = stateCache; - } + } - public long BlockHeight { get; set; } - public Hash BlockHash { get; set; } + public ChainContextWithTieredStateCache(Hash blockHash, long blockHeight, TieredStateCache stateCache) + { + BlockHeight = blockHeight; + BlockHash = blockHash; + StateCache = stateCache; + } - IStateCache IChainContext.StateCache - { - get => StateCache; - set => StateCache = value as TieredStateCache; - } + public long BlockHeight { get; set; } + public Hash BlockHash { get; set; } - public TieredStateCache StateCache { get; set; } + IStateCache IChainContext.StateCache + { + get => StateCache; + set => StateCache = value as TieredStateCache; } + + public TieredStateCache StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs b/src/AElf.Kernel.SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs index d526afb44d..4107dbfbda 100644 --- a/src/AElf.Kernel.SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs +++ b/src/AElf.Kernel.SmartContract/Application/CleanBlockExecutedDataChangeHeightEventHandler.cs @@ -4,37 +4,36 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class CleanBlockExecutedDataChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency { - public class CleanBlockExecutedDataChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency + public CleanBlockExecutedDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanBlockExecutedDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } - - public class CleanSmartContractAddressChangeHeightEventHandler : - CleanBlockExecutedDataChangeHeightBaseEventHandler, - ILocalEventHandler, ITransientDependency +} + +public class CleanSmartContractAddressChangeHeightEventHandler : + CleanBlockExecutedDataChangeHeightBaseEventHandler, + ILocalEventHandler, ITransientDependency +{ + public CleanSmartContractAddressChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanSmartContractAddressChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } - - public class CleanIntegerDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< - Int32Value>, ILocalEventHandler, ITransientDependency +} + +public class CleanIntegerDataChangeHeightEventHandler : CleanBlockExecutedDataChangeHeightBaseEventHandler< + Int32Value>, ILocalEventHandler, ITransientDependency +{ + public CleanIntegerDataChangeHeightEventHandler( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public CleanIntegerDataChangeHeightEventHandler( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ContractReaderContext.cs b/src/AElf.Kernel.SmartContract/Application/ContractReaderContext.cs index 0095524791..8eecb0e1d0 100644 --- a/src/AElf.Kernel.SmartContract/Application/ContractReaderContext.cs +++ b/src/AElf.Kernel.SmartContract/Application/ContractReaderContext.cs @@ -1,15 +1,14 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class ContractReaderContext { - public class ContractReaderContext - { - public Address Sender { get; set; } - public Address ContractAddress { get; set; } - public Hash BlockHash { get; set; } - public long BlockHeight { get; set; } - public Timestamp Timestamp { get; set; } - public IStateCache StateCache { get; set; } - } + public Address Sender { get; set; } + public Address ContractAddress { get; set; } + public Hash BlockHash { get; set; } + public long BlockHeight { get; set; } + public Timestamp Timestamp { get; set; } + public IStateCache StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ContractReaderFactory.cs b/src/AElf.Kernel.SmartContract/Application/ContractReaderFactory.cs index 9bfedcf107..84e8aed4d1 100644 --- a/src/AElf.Kernel.SmartContract/Application/ContractReaderFactory.cs +++ b/src/AElf.Kernel.SmartContract/Application/ContractReaderFactory.cs @@ -1,27 +1,25 @@ using AElf.CSharp.Core; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class ContractReaderFactory : IContractReaderFactory + where T : ContractStubBase, new() { - public class ContractReaderFactory : IContractReaderFactory - where T : ContractStubBase, new() + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + + public ContractReaderFactory(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) { - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + } - public ContractReaderFactory(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) - { - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - } + public T Create(ContractReaderContext contractReaderContext) + { + var methodStubFactory = new ReadOnlyMethodStubFactory(_transactionReadOnlyExecutionService); + methodStubFactory.SetContractReaderContext(contractReaderContext); - public T Create(ContractReaderContext contractReaderContext) + return new T { - var methodStubFactory = new ReadOnlyMethodStubFactory(_transactionReadOnlyExecutionService); - methodStubFactory.SetContractReaderContext(contractReaderContext); - - return new T() - { - __factory = methodStubFactory - }; - } + __factory = methodStubFactory + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/HostSmartContractBridgeContextService.cs b/src/AElf.Kernel.SmartContract/Application/HostSmartContractBridgeContextService.cs index 2625739363..bd172b59c2 100644 --- a/src/AElf.Kernel.SmartContract/Application/HostSmartContractBridgeContextService.cs +++ b/src/AElf.Kernel.SmartContract/Application/HostSmartContractBridgeContextService.cs @@ -1,24 +1,22 @@ using System; -using AElf.Kernel.SmartContract; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class HostSmartContractBridgeContextService : IHostSmartContractBridgeContextService { - public class HostSmartContractBridgeContextService : IHostSmartContractBridgeContextService - { - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _serviceProvider; - public HostSmartContractBridgeContextService(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } + public HostSmartContractBridgeContextService(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } - public IHostSmartContractBridgeContext Create() - { - //Create a new context - var context = _serviceProvider.GetService(); - return context; - } + public IHostSmartContractBridgeContext Create() + { + //Create a new context + var context = _serviceProvider.GetService(); + return context; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IChainContext`.cs b/src/AElf.Kernel.SmartContract/Application/IChainContext`.cs index f34305776b..22f2d94565 100644 --- a/src/AElf.Kernel.SmartContract/Application/IChainContext`.cs +++ b/src/AElf.Kernel.SmartContract/Application/IChainContext`.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IChainContext : IChainContext where T : IStateCache { - public interface IChainContext : IChainContext where T : IStateCache - { - new T StateCache { get; set; } - } + new T StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IContractDeploymentListProvider.cs b/src/AElf.Kernel.SmartContract/Application/IContractDeploymentListProvider.cs index 448ee6f22b..e6280c65dd 100644 --- a/src/AElf.Kernel.SmartContract/Application/IContractDeploymentListProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/IContractDeploymentListProvider.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IContractDeploymentListProvider { - public interface IContractDeploymentListProvider - { - List GetDeployContractNameList(); - } + List GetDeployContractNameList(); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IContractInitializationProvider.cs b/src/AElf.Kernel.SmartContract/Application/IContractInitializationProvider.cs index 950ce681a0..7c85d761d1 100644 --- a/src/AElf.Kernel.SmartContract/Application/IContractInitializationProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/IContractInitializationProvider.cs @@ -2,19 +2,18 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IContractInitializationProvider +{ + Hash SystemSmartContractName { get; } + string ContractCodeName { get; } + List GetInitializeMethodList(byte[] contractCode); +} + +public class ContractInitializationMethodCall { - public interface IContractInitializationProvider - { - Hash SystemSmartContractName { get; } - string ContractCodeName { get; } - List GetInitializeMethodList(byte[] contractCode); - } - - public class ContractInitializationMethodCall - { - public string MethodName { get; set; } + public string MethodName { get; set; } - public ByteString Params { get; set; } - } + public ByteString Params { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IContractReaderFactory.cs b/src/AElf.Kernel.SmartContract/Application/IContractReaderFactory.cs index 7641d3cd91..bbae9a37de 100644 --- a/src/AElf.Kernel.SmartContract/Application/IContractReaderFactory.cs +++ b/src/AElf.Kernel.SmartContract/Application/IContractReaderFactory.cs @@ -1,10 +1,9 @@ using AElf.CSharp.Core; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IContractReaderFactory + where T : ContractStubBase, new() { - public interface IContractReaderFactory - where T : ContractStubBase, new() - { - T Create(ContractReaderContext contractReaderContext); - } + T Create(ContractReaderContext contractReaderContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs b/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs index 842413bed8..22df31d5a3 100644 --- a/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs @@ -3,65 +3,67 @@ using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IExecutionObserverThresholdProvider { - public interface IExecutionObserverThresholdProvider + IExecutionObserverThreshold GetExecutionObserverThreshold(IBlockIndex blockIndex); + + Task SetExecutionObserverThresholdAsync(IBlockIndex blockIndex, + IExecutionObserverThreshold executionObserverThreshold); +} + +public class ExecutionObserverThresholdProvider : BlockExecutedDataBaseProvider, + IExecutionObserverThresholdProvider, ITransientDependency +{ + private const string BlockExecutedDataName = "ExecutionObserverThreshold"; + private const string BranchCountThresholdKey = "BranchCountThreshold"; + private const string CallCountThresholdKey = "CallCountThreshold"; + + public ExecutionObserverThresholdProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : + base(cachedBlockchainExecutedDataService) { - IExecutionObserverThreshold GetExecutionObserverThreshold(IBlockIndex blockIndex); - Task SetExecutionObserverThresholdAsync(IBlockIndex blockIndex, IExecutionObserverThreshold executionObserverThreshold); } - - public class ExecutionObserverThresholdProvider : BlockExecutedDataBaseProvider, - IExecutionObserverThresholdProvider, ITransientDependency - { - private const string BlockExecutedDataName = "ExecutionObserverThreshold"; - private const string BranchCountThresholdKey = "BranchCountThreshold"; - private const string CallCountThresholdKey = "CallCountThreshold"; - public ILogger Logger { get; set; } - public ExecutionObserverThresholdProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : - base(cachedBlockchainExecutedDataService) - { - } + public ILogger Logger { get; set; } - public IExecutionObserverThreshold GetExecutionObserverThreshold(IBlockIndex blockIndex) + public IExecutionObserverThreshold GetExecutionObserverThreshold(IBlockIndex blockIndex) + { + var branchCountObserverThreshold = GetBlockExecutedData(blockIndex, BranchCountThresholdKey)?.Value ?? + SmartContractConstants.ExecutionBranchThreshold; + var callCountObserverThreshold = GetBlockExecutedData(blockIndex, CallCountThresholdKey)?.Value ?? + SmartContractConstants.ExecutionBranchThreshold; + return new ExecutionObserverThreshold { - var branchCountObserverThreshold = GetBlockExecutedData(blockIndex, BranchCountThresholdKey)?.Value ?? - SmartContractConstants.ExecutionBranchThreshold; - var callCountObserverThreshold = GetBlockExecutedData(blockIndex, CallCountThresholdKey)?.Value ?? - SmartContractConstants.ExecutionBranchThreshold; - return new ExecutionObserverThreshold - { - ExecutionBranchThreshold = branchCountObserverThreshold, - ExecutionCallThreshold = callCountObserverThreshold - }; - } + ExecutionBranchThreshold = branchCountObserverThreshold, + ExecutionCallThreshold = callCountObserverThreshold + }; + } - public async Task SetExecutionObserverThresholdAsync(IBlockIndex blockIndex, - IExecutionObserverThreshold executionObserverThreshold) - { - if (!ValidateExecutionObserverThreshold(executionObserverThreshold)) - return; + public async Task SetExecutionObserverThresholdAsync(IBlockIndex blockIndex, + IExecutionObserverThreshold executionObserverThreshold) + { + if (!ValidateExecutionObserverThreshold(executionObserverThreshold)) + return; - await AddBlockExecutedDataAsync(blockIndex, BranchCountThresholdKey, - new Int32Value {Value = executionObserverThreshold.ExecutionBranchThreshold}); - await AddBlockExecutedDataAsync(blockIndex, CallCountThresholdKey, - new Int32Value {Value = executionObserverThreshold.ExecutionCallThreshold}); - - Logger.LogDebug( - $"ExecutionObserverThreshold has been changed. Branch count threshold is {executionObserverThreshold.ExecutionBranchThreshold}. Call count threshold is {executionObserverThreshold.ExecutionCallThreshold}"); - } + await AddBlockExecutedDataAsync(blockIndex, BranchCountThresholdKey, + new Int32Value { Value = executionObserverThreshold.ExecutionBranchThreshold }); + await AddBlockExecutedDataAsync(blockIndex, CallCountThresholdKey, + new Int32Value { Value = executionObserverThreshold.ExecutionCallThreshold }); - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + Logger.LogDebug( + $"ExecutionObserverThreshold has been changed. Branch count threshold is {executionObserverThreshold.ExecutionBranchThreshold}. Call count threshold is {executionObserverThreshold.ExecutionCallThreshold}"); + } - private bool ValidateExecutionObserverThreshold(IExecutionObserverThreshold executionObserverThreshold) - { - return executionObserverThreshold.ExecutionBranchThreshold > 0 && - executionObserverThreshold.ExecutionCallThreshold > 0; - } + protected override string GetBlockExecutedDataName() + { + return BlockExecutedDataName; + } + + private bool ValidateExecutionObserverThreshold(IExecutionObserverThreshold executionObserverThreshold) + { + return executionObserverThreshold.ExecutionBranchThreshold > 0 && + executionObserverThreshold.ExecutionCallThreshold > 0; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IHostSmartContractBridgeContextService.cs b/src/AElf.Kernel.SmartContract/Application/IHostSmartContractBridgeContextService.cs index a67b3adc91..cfff92b1da 100644 --- a/src/AElf.Kernel.SmartContract/Application/IHostSmartContractBridgeContextService.cs +++ b/src/AElf.Kernel.SmartContract/Application/IHostSmartContractBridgeContextService.cs @@ -1,9 +1,6 @@ -using AElf.Kernel.SmartContract; +namespace AElf.Kernel.SmartContract.Application; -namespace AElf.Kernel.SmartContract.Application +public interface IHostSmartContractBridgeContextService { - public interface IHostSmartContractBridgeContextService - { - IHostSmartContractBridgeContext Create(); - } + IHostSmartContractBridgeContext Create(); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ILogEventProcessingService.cs b/src/AElf.Kernel.SmartContract/Application/ILogEventProcessingService.cs index cfa4cf2431..c48594d18f 100644 --- a/src/AElf.Kernel.SmartContract/Application/ILogEventProcessingService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ILogEventProcessingService.cs @@ -2,10 +2,9 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ILogEventProcessingService where T : ILogEventProcessor { - public interface ILogEventProcessingService where T : ILogEventProcessor - { - Task ProcessAsync(List blockExecutedSets); - } + Task ProcessAsync(List blockExecutedSets); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ILogEventProcessor.cs b/src/AElf.Kernel.SmartContract/Application/ILogEventProcessor.cs index 794dc4746e..105ee66659 100644 --- a/src/AElf.Kernel.SmartContract/Application/ILogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContract/Application/ILogEventProcessor.cs @@ -5,55 +5,52 @@ using AElf.CSharp.Core.Extension; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ILogEventProcessor { - public interface ILogEventProcessor - { - Task GetInterestedEventAsync(IChainContext chainContext); - Task ProcessAsync(Block block, Dictionary> logEventsMap); - } + Task GetInterestedEventAsync(IChainContext chainContext); + Task ProcessAsync(Block block, Dictionary> logEventsMap); +} - public class InterestedEvent - { - public LogEvent LogEvent { get; set; } - public Bloom Bloom { get; set; } - } +public class InterestedEvent +{ + public LogEvent LogEvent { get; set; } + public Bloom Bloom { get; set; } +} + +public interface IBlockAcceptedLogEventProcessor : ILogEventProcessor +{ +} + +public interface IBlocksExecutionSucceededLogEventProcessor : ILogEventProcessor +{ +} + +public abstract class LogEventProcessorBase : ILogEventProcessor +{ + protected InterestedEvent InterestedEvent; - public interface IBlockAcceptedLogEventProcessor : ILogEventProcessor + public abstract Task GetInterestedEventAsync(IChainContext chainContext); + + public virtual async Task ProcessAsync(Block block, Dictionary> logEventsMap) { + foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) + await ProcessLogEventAsync(block, logEvent); } - public interface IBlocksExecutionSucceededLogEventProcessor : ILogEventProcessor + protected virtual Task ProcessLogEventAsync(Block block, LogEvent logEvent) { + return Task.CompletedTask; } - public abstract class LogEventProcessorBase : ILogEventProcessor + protected InterestedEvent GetInterestedEvent(Address address) where T : IEvent, new() { - protected InterestedEvent InterestedEvent; - - public abstract Task GetInterestedEventAsync(IChainContext chainContext); - - public virtual async Task ProcessAsync(Block block, Dictionary> logEventsMap) - { - foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents)) - { - await ProcessLogEventAsync(block, logEvent); - } - } - - protected virtual Task ProcessLogEventAsync(Block block, LogEvent logEvent) - { - return Task.CompletedTask; - } - - protected InterestedEvent GetInterestedEvent(Address address) where T : IEvent, new() + var logEvent = new T().ToLogEvent(address); + return new InterestedEvent { - var logEvent = new T().ToLogEvent(address); - return new InterestedEvent - { - LogEvent = logEvent, - Bloom = logEvent.GetBloom() - }; - } + LogEvent = logEvent, + Bloom = logEvent.GetBloom() + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IPostExecutionPlugin.cs b/src/AElf.Kernel.SmartContract/Application/IPostExecutionPlugin.cs index dc79d64679..c9688a61bd 100644 --- a/src/AElf.Kernel.SmartContract/Application/IPostExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract/Application/IPostExecutionPlugin.cs @@ -1,14 +1,12 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf.Reflection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IPostExecutionPlugin { - public interface IPostExecutionPlugin - { - Task> GetPostTransactionsAsync(IReadOnlyList descriptors, - ITransactionContext transactionContext); - } + Task> GetPostTransactionsAsync(IReadOnlyList descriptors, + ITransactionContext transactionContext); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IPreExecutionPlugin.cs b/src/AElf.Kernel.SmartContract/Application/IPreExecutionPlugin.cs index ef458536b8..181fa2290a 100644 --- a/src/AElf.Kernel.SmartContract/Application/IPreExecutionPlugin.cs +++ b/src/AElf.Kernel.SmartContract/Application/IPreExecutionPlugin.cs @@ -4,13 +4,12 @@ using Google.Protobuf; using Google.Protobuf.Reflection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IPreExecutionPlugin { - public interface IPreExecutionPlugin - { - Task> GetPreTransactionsAsync(IReadOnlyList descriptors, - ITransactionContext transactionContext); + Task> GetPreTransactionsAsync(IReadOnlyList descriptors, + ITransactionContext transactionContext); - bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation); - } + bool IsStopExecuting(ByteString txReturnValue, out string preExecutionInformation); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressProvider.cs b/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressProvider.cs index e048eca22a..e8cc75d07b 100644 --- a/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressProvider.cs @@ -2,42 +2,42 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractAddressProvider { - public interface ISmartContractAddressProvider - { - Task GetSmartContractAddressAsync(IChainContext chainContext, string contractName); + Task GetSmartContractAddressAsync(IChainContext chainContext, string contractName); - Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address); - } + Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address); +} - public class SmartContractAddressProvider : BlockExecutedDataBaseProvider,ISmartContractAddressProvider, ISingletonDependency +public class SmartContractAddressProvider : BlockExecutedDataBaseProvider, + ISmartContractAddressProvider, ISingletonDependency +{ + public SmartContractAddressProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - public SmartContractAddressProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } + } - public Task GetSmartContractAddressAsync(IChainContext chainContext, string contractName) - { - var smartContractAddress = GetBlockExecutedData(chainContext, contractName); - return Task.FromResult(smartContractAddress); - } + public Task GetSmartContractAddressAsync(IChainContext chainContext, string contractName) + { + var smartContractAddress = GetBlockExecutedData(chainContext, contractName); + return Task.FromResult(smartContractAddress); + } - public async Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) + public async Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) + { + await AddBlockExecutedDataAsync(blockIndex, contractName, new SmartContractAddress { - await AddBlockExecutedDataAsync(blockIndex, contractName, new SmartContractAddress - { - Address = address, - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - } + Address = address, + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + } - protected override string GetBlockExecutedDataName() - { - return nameof(SmartContractAddress); - } + protected override string GetBlockExecutedDataName() + { + return nameof(SmartContractAddress); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressService.cs b/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressService.cs index 938a78a09a..e7fa3d4f05 100644 --- a/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ISmartContractAddressService.cs @@ -1,142 +1,142 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractAddressService { - public interface ISmartContractAddressService - { - Task
GetAddressByContractNameAsync(IChainContext chainContext, string name); - Task GetSmartContractAddressAsync(IChainContext chainContext, string name); - Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string name, Address address); + Task
GetAddressByContractNameAsync(IChainContext chainContext, string name); + Task GetSmartContractAddressAsync(IChainContext chainContext, string name); + Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string name, Address address); - Address GetZeroSmartContractAddress(); + Address GetZeroSmartContractAddress(); - Address GetZeroSmartContractAddress(int chainId); + Address GetZeroSmartContractAddress(int chainId); - Task> GetSystemContractNameToAddressMappingAsync(IChainContext chainContext); - } + Task> GetSystemContractNameToAddressMappingAsync(IChainContext chainContext); +} - public class SmartContractAddressService : ISmartContractAddressService, ISingletonDependency +public class SmartContractAddressService : ISmartContractAddressService, ISingletonDependency +{ + private readonly IBlockchainService _blockchainService; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly IEnumerable _smartContractAddressNameProviders; + private readonly ISmartContractAddressProvider _smartContractAddressProvider; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + + public SmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + ISmartContractAddressProvider smartContractAddressProvider, + IEnumerable smartContractAddressNameProviders, + IBlockchainService blockchainService) { - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private readonly ISmartContractAddressProvider _smartContractAddressProvider; - private readonly IEnumerable _smartContractAddressNameProviders; - private readonly IBlockchainService _blockchainService; - - public SmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - ISmartContractAddressProvider smartContractAddressProvider, - IEnumerable smartContractAddressNameProviders, - IBlockchainService blockchainService) - { - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - _smartContractAddressProvider = smartContractAddressProvider; - _smartContractAddressNameProviders = smartContractAddressNameProviders; - _blockchainService = blockchainService; - } + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + _smartContractAddressProvider = smartContractAddressProvider; + _smartContractAddressNameProviders = smartContractAddressNameProviders; + _blockchainService = blockchainService; + } - public async Task
GetAddressByContractNameAsync(IChainContext chainContext, string name) - { - var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, name); - var address = smartContractAddress?.Address; - if (address == null) address = await GetSmartContractAddressFromStateAsync(chainContext, name); - return address; - } + public async Task
GetAddressByContractNameAsync(IChainContext chainContext, string name) + { + var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, name); + var address = smartContractAddress?.Address; + if (address == null) address = await GetSmartContractAddressFromStateAsync(chainContext, name); + return address; + } - public async Task GetSmartContractAddressAsync(IChainContext chainContext, string name) + public async Task GetSmartContractAddressAsync(IChainContext chainContext, string name) + { + var smartContractAddress = + await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, name); + if (smartContractAddress != null) { - var smartContractAddress = - await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, name); - if (smartContractAddress != null) - { - var smartContractAddressDto = new SmartContractAddressDto - { - SmartContractAddress = smartContractAddress, - Irreversible = await CheckSmartContractAddressIrreversibleAsync(smartContractAddress) - }; - - return smartContractAddressDto; - } - - var address = await GetSmartContractAddressFromStateAsync(chainContext, name); - if (address == null) return null; - return new SmartContractAddressDto + var smartContractAddressDto = new SmartContractAddressDto { - SmartContractAddress = new SmartContractAddress - { - Address = address - } + SmartContractAddress = smartContractAddress, + Irreversible = await CheckSmartContractAddressIrreversibleAsync(smartContractAddress) }; + + return smartContractAddressDto; } - private async Task CheckSmartContractAddressIrreversibleAsync(SmartContractAddress smartContractAddress) + var address = await GetSmartContractAddressFromStateAsync(chainContext, name); + if (address == null) return null; + return new SmartContractAddressDto { - var chain = await _blockchainService.GetChainAsync(); - if (smartContractAddress.BlockHeight > chain.LastIrreversibleBlockHeight) return false; + SmartContractAddress = new SmartContractAddress + { + Address = address + } + }; + } - var blockHash = await _blockchainService.GetBlockHashByHeightAsync(chain, - smartContractAddress.BlockHeight, chain.LastIrreversibleBlockHash); - return blockHash == smartContractAddress.BlockHash; - } + public virtual async Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string name, Address address) + { + await _smartContractAddressProvider.SetSmartContractAddressAsync(blockIndex, name, address); + } - public virtual async Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string name, Address address) - { - await _smartContractAddressProvider.SetSmartContractAddressAsync(blockIndex, name, address); - } + public Address GetZeroSmartContractAddress() + { + return _defaultContractZeroCodeProvider.ContractZeroAddress; + } - public Address GetZeroSmartContractAddress() - { - return _defaultContractZeroCodeProvider.ContractZeroAddress; - } + public Address GetZeroSmartContractAddress(int chainId) + { + return _defaultContractZeroCodeProvider.GetZeroSmartContractAddress(chainId); + } - public Address GetZeroSmartContractAddress(int chainId) + public virtual async Task> GetSystemContractNameToAddressMappingAsync( + IChainContext chainContext) + { + var map = new Dictionary(); + foreach (var smartContractAddressNameProvider in _smartContractAddressNameProviders) { - return _defaultContractZeroCodeProvider.GetZeroSmartContractAddress(chainId); + var address = + await GetAddressByContractNameAsync(chainContext, smartContractAddressNameProvider.ContractStringName); + if (address != null) + map[smartContractAddressNameProvider.ContractName] = address; } - public virtual async Task> GetSystemContractNameToAddressMappingAsync( - IChainContext chainContext) - { - var map = new Dictionary(); - foreach (var smartContractAddressNameProvider in _smartContractAddressNameProviders) - { - var address = - await GetAddressByContractNameAsync(chainContext, smartContractAddressNameProvider.ContractStringName); - if(address != null) - map[smartContractAddressNameProvider.ContractName] = address; - } - return new ReadOnlyDictionary(map); - } + return new ReadOnlyDictionary(map); + } - private async Task
GetSmartContractAddressFromStateAsync(IChainContext chainContext, string name) - { - var zeroAddress = _defaultContractZeroCodeProvider.ContractZeroAddress; - var tx = new Transaction - { - From = zeroAddress, - To = zeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.GetContractAddressByName), - Params = Hash.LoadFromBase64(name).ToByteString() - }; - var address = await _transactionReadOnlyExecutionService.ExecuteAsync
( - chainContext, tx, TimestampHelper.GetUtcNow(), false); + private async Task CheckSmartContractAddressIrreversibleAsync(SmartContractAddress smartContractAddress) + { + var chain = await _blockchainService.GetChainAsync(); + if (smartContractAddress.BlockHeight > chain.LastIrreversibleBlockHeight) return false; - return address == null || address.Value.IsEmpty ? null : address; - } + var blockHash = await _blockchainService.GetBlockHashByHeightAsync(chain, + smartContractAddress.BlockHeight, chain.LastIrreversibleBlockHash); + return blockHash == smartContractAddress.BlockHash; } - - public class SmartContractAddressDto + + private async Task
GetSmartContractAddressFromStateAsync(IChainContext chainContext, string name) { - public SmartContractAddress SmartContractAddress { get; set; } - public bool Irreversible { get; set; } + var zeroAddress = _defaultContractZeroCodeProvider.ContractZeroAddress; + var tx = new Transaction + { + From = zeroAddress, + To = zeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.GetContractAddressByName), + Params = Hash.LoadFromBase64(name).ToByteString() + }; + var address = await _transactionReadOnlyExecutionService.ExecuteAsync
( + chainContext, tx, TimestampHelper.GetUtcNow(), false); + + return address == null || address.Value.IsEmpty ? null : address; } +} + +public class SmartContractAddressDto +{ + public SmartContractAddress SmartContractAddress { get; set; } + public bool Irreversible { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ISmartContractBridgeService.cs b/src/AElf.Kernel.SmartContract/Application/ISmartContractBridgeService.cs index 0e004dd8d1..48710fe68a 100644 --- a/src/AElf.Kernel.SmartContract/Application/ISmartContractBridgeService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ISmartContractBridgeService.cs @@ -7,119 +7,118 @@ using Google.Protobuf; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractBridgeService { - public interface ISmartContractBridgeService - { - void LogDebug(Func func); + void LogDebug(Func func); + + Task DeployContractAsync(ContractDto contractDto); - Task DeployContractAsync(ContractDto contractDto); + Task UpdateContractAsync(ContractDto contractDto); - Task UpdateContractAsync(ContractDto contractDto); + Task> GetBlockTransactions(Hash blockHash); + int GetChainId(); - Task> GetBlockTransactions(Hash blockHash); - int GetChainId(); + Task
GetAddressByContractNameAsync(IChainContext chainContext, string contractName); - Task
GetAddressByContractNameAsync(IChainContext chainContext, string contractName); + Task> GetSystemContractNameToAddressMappingAsync(IChainContext chainContext); - Task> GetSystemContractNameToAddressMappingAsync(IChainContext chainContext); + Address GetZeroSmartContractAddress(); - Address GetZeroSmartContractAddress(); - - Address GetZeroSmartContractAddress(int chainId); + Address GetZeroSmartContractAddress(int chainId); - Task GetStateAsync(Address contractAddress, string key, long blockHeight, Hash blockHash); + Task GetStateAsync(Address contractAddress, string key, long blockHeight, Hash blockHash); - Task GetStateSizeLimitAsync(IChainContext chainContext); + Task GetStateSizeLimitAsync(IChainContext chainContext); +} + +public class SmartContractBridgeService : ISmartContractBridgeService +{ + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateManager _blockchainStateManager; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractService _smartContractService; + private readonly IStateSizeLimitProvider _stateSizeLimitProvider; + + public SmartContractBridgeService(ISmartContractService smartContractService, + IBlockchainService blockchainService, ISmartContractAddressService smartContractAddressService, + IBlockchainStateManager blockchainStateManager, IStateSizeLimitProvider stateSizeLimitProvider) + { + _smartContractService = smartContractService; + _blockchainService = blockchainService; + _smartContractAddressService = smartContractAddressService; + _blockchainStateManager = blockchainStateManager; + _stateSizeLimitProvider = stateSizeLimitProvider; + Logger = NullLogger.Instance; } - public class SmartContractBridgeService : ISmartContractBridgeService + public ILogger Logger { get; set; } + + + public void LogDebug(Func func) { - private readonly ISmartContractService _smartContractService; - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainStateManager _blockchainStateManager; - private readonly IStateSizeLimitProvider _stateSizeLimitProvider; - - public ILogger Logger { get; set; } - - public SmartContractBridgeService(ISmartContractService smartContractService, - IBlockchainService blockchainService, ISmartContractAddressService smartContractAddressService, - IBlockchainStateManager blockchainStateManager, IStateSizeLimitProvider stateSizeLimitProvider) - { - _smartContractService = smartContractService; - _blockchainService = blockchainService; - _smartContractAddressService = smartContractAddressService; - _blockchainStateManager = blockchainStateManager; - _stateSizeLimitProvider = stateSizeLimitProvider; - Logger = NullLogger.Instance; - } - - - public void LogDebug(Func func) - { #if DEBUG - Logger.LogDebug(func()); + Logger.LogDebug(func()); #endif - } - - public async Task DeployContractAsync(ContractDto contractDto) - { - await _smartContractService.DeployContractAsync(contractDto); - } - - public async Task UpdateContractAsync(ContractDto contractDto) - { - await _smartContractService.UpdateContractAsync(contractDto); - } - - public async Task> GetBlockTransactions(Hash blockHash) - { - var block = await _blockchainService.GetBlockByHashAsync(blockHash); - return await _blockchainService.GetTransactionsAsync(block.Body.TransactionIds); - } - - public int GetChainId() - { - return _blockchainService.GetChainId(); - } - - public Task
GetAddressByContractNameAsync(IChainContext chainContext, string contractName) - { - return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, contractName); - } - - public Task> GetSystemContractNameToAddressMappingAsync(IChainContext chainContext) - { - return _smartContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - } - - public Address GetZeroSmartContractAddress() - { - return _smartContractAddressService.GetZeroSmartContractAddress(); - } - - public Address GetZeroSmartContractAddress(int chainId) - { - return _smartContractAddressService.GetZeroSmartContractAddress(chainId); - } - - public Task GetStateAsync(Address contractAddress, string key, long blockHeight, Hash blockHash) - { - var address = contractAddress.ToBase58(); - if(!key.StartsWith(address)) - throw new InvalidOperationException("a contract cannot access other contracts data"); - - return _blockchainStateManager.GetStateAsync(key, blockHeight, - blockHash); - } - - public async Task GetStateSizeLimitAsync(IChainContext chainContext) - { - var stateSizeLimit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(chainContext); - return stateSizeLimit; - } + } + + public async Task DeployContractAsync(ContractDto contractDto) + { + await _smartContractService.DeployContractAsync(contractDto); + } + + public async Task UpdateContractAsync(ContractDto contractDto) + { + await _smartContractService.UpdateContractAsync(contractDto); + } + + public async Task> GetBlockTransactions(Hash blockHash) + { + var block = await _blockchainService.GetBlockByHashAsync(blockHash); + return await _blockchainService.GetTransactionsAsync(block.Body.TransactionIds); + } + + public int GetChainId() + { + return _blockchainService.GetChainId(); + } + + public Task
GetAddressByContractNameAsync(IChainContext chainContext, string contractName) + { + return _smartContractAddressService.GetAddressByContractNameAsync(chainContext, contractName); + } + + public Task> GetSystemContractNameToAddressMappingAsync( + IChainContext chainContext) + { + return _smartContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); + } + + public Address GetZeroSmartContractAddress() + { + return _smartContractAddressService.GetZeroSmartContractAddress(); + } + + public Address GetZeroSmartContractAddress(int chainId) + { + return _smartContractAddressService.GetZeroSmartContractAddress(chainId); + } + + public Task GetStateAsync(Address contractAddress, string key, long blockHeight, Hash blockHash) + { + var address = contractAddress.ToBase58(); + if (!key.StartsWith(address)) + throw new InvalidOperationException("a contract cannot access other contracts data"); + + return _blockchainStateManager.GetStateAsync(key, blockHeight, + blockHash); + } + + public async Task GetStateSizeLimitAsync(IChainContext chainContext) + { + var stateSizeLimit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(chainContext); + return stateSizeLimit; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ISmartContractExecutiveService.cs b/src/AElf.Kernel.SmartContract/Application/ISmartContractExecutiveService.cs index 831af80bee..56c3675d27 100644 --- a/src/AElf.Kernel.SmartContract/Application/ISmartContractExecutiveService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ISmartContractExecutiveService.cs @@ -2,19 +2,18 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +/// +/// a smart contract executive, don't use it out of AElf.Kernel.SmartContract +/// +public interface ISmartContractExecutiveService { - /// - /// a smart contract executive, don't use it out of AElf.Kernel.SmartContract - /// - public interface ISmartContractExecutiveService - { - Task GetExecutiveAsync(IChainContext chainContext, Address address); + Task GetExecutiveAsync(IChainContext chainContext, Address address); - Task PutExecutiveAsync(IChainContext chainContext, Address address, IExecutive executive); + Task PutExecutiveAsync(IChainContext chainContext, Address address, IExecutive executive); - void CleanExecutive(Address address); + void CleanExecutive(Address address); - void CleanIdleExecutive(); - } + void CleanIdleExecutive(); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ISmartContractService.cs b/src/AElf.Kernel.SmartContract/Application/ISmartContractService.cs index 9252530f9f..35f102099c 100644 --- a/src/AElf.Kernel.SmartContract/Application/ISmartContractService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ISmartContractService.cs @@ -1,16 +1,15 @@ using System.Threading.Tasks; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractService { - public interface ISmartContractService - { - /// - /// Deploys a contract to the specified chain and account. - /// - /// - /// - Task DeployContractAsync(ContractDto contractDto); + /// + /// Deploys a contract to the specified chain and account. + /// + /// + /// + Task DeployContractAsync(ContractDto contractDto); - Task UpdateContractAsync(ContractDto contractDto); - } + Task UpdateContractAsync(ContractDto contractDto); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/IStateSizeLimitProvider.cs b/src/AElf.Kernel.SmartContract/Application/IStateSizeLimitProvider.cs index 172a207417..4d538a302c 100644 --- a/src/AElf.Kernel.SmartContract/Application/IStateSizeLimitProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/IStateSizeLimitProvider.cs @@ -3,43 +3,43 @@ using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface IStateSizeLimitProvider +{ + Task GetStateSizeLimitAsync(IBlockIndex blockIndex); + Task SetStateSizeLimitAsync(IBlockIndex blockIndex, int stateSizeLimit); +} + +internal class StateSizeLimitProvider : BlockExecutedDataBaseProvider, IStateSizeLimitProvider, + ITransientDependency { - public interface IStateSizeLimitProvider + private const string BlockExecutedDataName = "StateSizeLimit"; + + public StateSizeLimitProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) + { + } + + public ILogger Logger { get; set; } + + public Task GetStateSizeLimitAsync(IBlockIndex blockIndex) + { + var stateSizeLimit = GetBlockExecutedData(blockIndex)?.Value ?? SmartContractConstants.StateSizeLimit; + return Task.FromResult(stateSizeLimit); + } + + public async Task SetStateSizeLimitAsync(IBlockIndex blockIndex, int stateSizeLimit) { - Task GetStateSizeLimitAsync(IBlockIndex blockIndex); - Task SetStateSizeLimitAsync(IBlockIndex blockIndex, int stateSizeLimit); + if (stateSizeLimit <= 0) + return; + await AddBlockExecutedDataAsync(blockIndex, new Int32Value { Value = stateSizeLimit }); + Logger.LogDebug($"State limit size changed to {stateSizeLimit}"); } - class StateSizeLimitProvider : BlockExecutedDataBaseProvider, IStateSizeLimitProvider, - ITransientDependency + protected override string GetBlockExecutedDataName() { - private const string BlockExecutedDataName = "StateSizeLimit"; - public ILogger Logger { get; set; } - - public Task GetStateSizeLimitAsync(IBlockIndex blockIndex) - { - var stateSizeLimit = GetBlockExecutedData(blockIndex)?.Value ?? SmartContractConstants.StateSizeLimit; - return Task.FromResult(stateSizeLimit); - } - - public async Task SetStateSizeLimitAsync(IBlockIndex blockIndex, int stateSizeLimit) - { - if (stateSizeLimit <= 0) - return; - await AddBlockExecutedDataAsync(blockIndex, new Int32Value {Value = stateSizeLimit}); - Logger.LogDebug($"State limit size changed to {stateSizeLimit}"); - } - - public StateSizeLimitProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - } - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ITransactionContextFactory.cs b/src/AElf.Kernel.SmartContract/Application/ITransactionContextFactory.cs index 79e1c1698d..15884b9e66 100644 --- a/src/AElf.Kernel.SmartContract/Application/ITransactionContextFactory.cs +++ b/src/AElf.Kernel.SmartContract/Application/ITransactionContextFactory.cs @@ -1,67 +1,68 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ITransactionContextFactory { - public interface ITransactionContextFactory - { - ITransactionContext Create(Transaction transaction, IChainContext chainContext, Timestamp blockTime = null, - int callDepth = 0); + ITransactionContext Create(Transaction transaction, IChainContext chainContext, Timestamp blockTime = null, + int callDepth = 0); + + ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, + Address originAddress, int callDepth = 0, Timestamp blockTime = null); +} + +public class TransactionContextFactory : ITransactionContextFactory +{ + private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; - ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, - Address originAddress, int callDepth = 0, Timestamp blockTime = null); + public TransactionContextFactory(IExecutionObserverThresholdProvider executionObserverThresholdProvider) + { + _executionObserverThresholdProvider = executionObserverThresholdProvider; } - public class TransactionContextFactory : ITransactionContextFactory + public ITransactionContext Create(Transaction transaction, IChainContext chainContext, + Timestamp blockTime = null, int callDepth = 0) { - private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(chainContext); + return Create(transaction, chainContext.BlockHash, chainContext.BlockHeight + 1, chainContext.StateCache, + callDepth, blockTime, executionObserverThreshold); + } - public TransactionContextFactory(IExecutionObserverThresholdProvider executionObserverThresholdProvider) - { - _executionObserverThresholdProvider = executionObserverThresholdProvider; - } + public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, + Address originAddress, int callDepth = 0, Timestamp blockTime = null) + { + var txContext = Create(transaction, chainContext, blockTime, callDepth); - private ITransactionContext Create(Transaction transaction, Hash previousBlockHash, long blockHeight, - IStateCache stateCache, int callDepth, Timestamp blockTime, IExecutionObserverThreshold executionObserverThreshold) - { - return new TransactionContext - { - Trace = new TransactionTrace - { - TransactionId = transaction.GetHash() - }, - Transaction = transaction, - PreviousBlockHash = previousBlockHash, - BlockHeight = blockHeight, - CurrentBlockTime = blockTime ?? TimestampHelper.GetUtcNow(), - CallDepth = callDepth, - MaxCallDepth = 64, - Origin = transaction.From, - OriginTransactionId = transaction.GetHash(), - ExecutionObserverThreshold = executionObserverThreshold, - StateCache = stateCache - }; - } + if (originAddress != null) + txContext.Origin = originAddress; - public ITransactionContext Create(Transaction transaction, IChainContext chainContext, - Timestamp blockTime = null, int callDepth = 0) - { - var executionObserverThreshold = _executionObserverThresholdProvider.GetExecutionObserverThreshold(chainContext); - return Create(transaction, chainContext.BlockHash, chainContext.BlockHeight + 1, chainContext.StateCache, - callDepth, blockTime, executionObserverThreshold); - } + if (originTransactionId != null) + txContext.OriginTransactionId = originTransactionId; + return txContext; + } - public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, - Address originAddress, int callDepth = 0, Timestamp blockTime = null) + private ITransactionContext Create(Transaction transaction, Hash previousBlockHash, long blockHeight, + IStateCache stateCache, int callDepth, Timestamp blockTime, + IExecutionObserverThreshold executionObserverThreshold) + { + return new TransactionContext { - var txContext = Create(transaction, chainContext, blockTime, callDepth); - - if (originAddress != null) - txContext.Origin = originAddress; - - if (originTransactionId != null) - txContext.OriginTransactionId = originTransactionId; - return txContext; - } + Trace = new TransactionTrace + { + TransactionId = transaction.GetHash() + }, + Transaction = transaction, + PreviousBlockHash = previousBlockHash, + BlockHeight = blockHeight, + CurrentBlockTime = blockTime ?? TimestampHelper.GetUtcNow(), + CallDepth = callDepth, + MaxCallDepth = 64, + Origin = transaction.From, + OriginTransactionId = transaction.GetHash(), + ExecutionObserverThreshold = executionObserverThreshold, + StateCache = stateCache + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ITransactionExecutingService.cs b/src/AElf.Kernel.SmartContract/Application/ITransactionExecutingService.cs index 6cfcd67066..75ef1fa3bc 100644 --- a/src/AElf.Kernel.SmartContract/Application/ITransactionExecutingService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ITransactionExecutingService.cs @@ -2,16 +2,14 @@ using System.Threading; using System.Threading.Tasks; -namespace AElf.Kernel.SmartContract.Application -{ - public interface ITransactionExecutingService - { - Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, - CancellationToken cancellationToken); - } +namespace AElf.Kernel.SmartContract.Application; - public interface IPlainTransactionExecutingService : ITransactionExecutingService - { +public interface ITransactionExecutingService +{ + Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, + CancellationToken cancellationToken); +} - } +public interface IPlainTransactionExecutingService : ITransactionExecutingService +{ } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ITransactionReadOnlyExecutionService.cs b/src/AElf.Kernel.SmartContract/Application/ITransactionReadOnlyExecutionService.cs index 63fdbefbff..c894063b8f 100644 --- a/src/AElf.Kernel.SmartContract/Application/ITransactionReadOnlyExecutionService.cs +++ b/src/AElf.Kernel.SmartContract/Application/ITransactionReadOnlyExecutionService.cs @@ -4,19 +4,18 @@ using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ITransactionReadOnlyExecutionService { - public interface ITransactionReadOnlyExecutionService - { - Task ExecuteAsync(IChainContext chainContext, Transaction transaction, - Timestamp currentBlockTime); + Task ExecuteAsync(IChainContext chainContext, Transaction transaction, + Timestamp currentBlockTime); - Task GetFileDescriptorSetAsync(IChainContext chainContext, Address address); + Task GetFileDescriptorSetAsync(IChainContext chainContext, Address address); - Task> GetFileDescriptorsAsync(IChainContext chainContext, Address address); + Task> GetFileDescriptorsAsync(IChainContext chainContext, Address address); - Task GetTransactionParametersAsync(IChainContext chainContext, Transaction transaction); + Task GetTransactionParametersAsync(IChainContext chainContext, Transaction transaction); - Task IsViewTransactionAsync(IChainContext chainContext, Transaction transaction); - } + Task IsViewTransactionAsync(IChainContext chainContext, Transaction transaction); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/LogEventProcessingService.cs b/src/AElf.Kernel.SmartContract/Application/LogEventProcessingService.cs index 8c5b1f0c2f..6080ff5ccc 100644 --- a/src/AElf.Kernel.SmartContract/Application/LogEventProcessingService.cs +++ b/src/AElf.Kernel.SmartContract/Application/LogEventProcessingService.cs @@ -5,91 +5,80 @@ using AElf.Types; using Microsoft.Extensions.Logging; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class LogEventProcessingService : ILogEventProcessingService + where T : ILogEventProcessor { - public class LogEventProcessingService : ILogEventProcessingService - where T : ILogEventProcessor + private readonly List _logEventProcessors; + + public LogEventProcessingService(IEnumerable logEventProcessors) { - private readonly List _logEventProcessors; + _logEventProcessors = logEventProcessors.ToLookup(p => p.GetType()).Select(coll => coll.First()).ToList(); + } - public ILogger> Logger { get; set; } + public ILogger> Logger { get; set; } - public LogEventProcessingService(IEnumerable logEventProcessors) + public async Task ProcessAsync(List blockExecutedSets) + { + Logger.LogTrace("Apply log event processor."); + foreach (var executedSet in blockExecutedSets) { - _logEventProcessors = logEventProcessors.ToLookup(p => p.GetType()).Select(coll => coll.First()).ToList(); - } + var block = executedSet.Block; + // Should make sure tx results' order are same as tx ids in block body. + var txResults = executedSet.TransactionResultMap.Values + .OrderBy(d => block.Body.TransactionIds.IndexOf(d.TransactionId)).ToList(); - public async Task ProcessAsync(List blockExecutedSets) - { - Logger.LogTrace("Apply log event processor."); - foreach (var executedSet in blockExecutedSets) + if (!txResults.Any()) continue; + + var blockBloom = new Bloom(block.Header.Bloom.ToByteArray()); + var chainContext = new ChainContext { - var block = executedSet.Block; - // Should make sure tx results' order are same as tx ids in block body. - var txResults = executedSet.TransactionResultMap.Values - .OrderBy(d => block.Body.TransactionIds.IndexOf(d.TransactionId)).ToList(); + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; - if (!txResults.Any()) continue; + foreach (var processor in _logEventProcessors) + { + var interestedEvent = await processor.GetInterestedEventAsync(chainContext); + if (interestedEvent == null || !interestedEvent.Bloom.IsIn(blockBloom)) continue; - var blockBloom = new Bloom(block.Header.Bloom.ToByteArray()); - var chainContext = new ChainContext + var logEventsMap = new Dictionary>(); + foreach (var result in txResults) { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; + if (result.Bloom.Length == 0) continue; + var resultBloom = new Bloom(result.Bloom.ToByteArray()); - foreach (var processor in _logEventProcessors) - { - var interestedEvent = await processor.GetInterestedEventAsync(chainContext); - if (interestedEvent == null || !interestedEvent.Bloom.IsIn(blockBloom)) continue; + if (!interestedEvent.Bloom.IsIn(resultBloom)) + // Interested bloom is not found in the transaction result + continue; - var logEventsMap = new Dictionary>(); - foreach (var result in txResults) + // Interested bloom is found in the transaction result, + // find the log that yields the bloom and apply the processor + foreach (var log in result.Logs) { - if (result.Bloom.Length == 0) continue; - var resultBloom = new Bloom(result.Bloom.ToByteArray()); - - if (!interestedEvent.Bloom.IsIn(resultBloom)) - { - // Interested bloom is not found in the transaction result - continue; - } - - // Interested bloom is found in the transaction result, - // find the log that yields the bloom and apply the processor - foreach (var log in result.Logs) - { - if (log.Address != interestedEvent.LogEvent.Address || - log.Name != interestedEvent.LogEvent.Name) continue; - if (logEventsMap.ContainsKey(result)) - { - logEventsMap[result].Add(log); - } - else + if (log.Address != interestedEvent.LogEvent.Address || + log.Name != interestedEvent.LogEvent.Name) continue; + if (logEventsMap.ContainsKey(result)) + logEventsMap[result].Add(log); + else + logEventsMap[result] = new List { - logEventsMap[result] = new List - { - log - }; - } - } - } - - if (logEventsMap.Any()) - { - await processor.ProcessAsync(block, logEventsMap.ToDictionary(m => m.Key, m => m.Value)); - } - else - { - Logger.LogWarning( - $"LogEvent maps happened to be empty and passed the filter.\n" + - $"Block bloom: {blockBloom.Data.ToHex()}\n" + - $"LogEvent bloom: {interestedEvent.Bloom.Data.ToHex()}"); + log + }; } } - Logger.LogTrace("Finish apply log event processor."); + if (logEventsMap.Any()) + await processor.ProcessAsync(block, logEventsMap.ToDictionary(m => m.Key, m => m.Value)); + else + Logger.LogWarning( + "LogEvent maps happened to be empty and passed the filter.\n" + + $"Block bloom: {blockBloom.Data.ToHex()}\n" + + $"LogEvent bloom: {interestedEvent.Bloom.Data.ToHex()}"); } + + Logger.LogTrace("Finish apply log event processor."); } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs b/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs index e08f1868c9..66045dc7bc 100644 --- a/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs +++ b/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs @@ -3,9 +3,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -using AElf.Kernel.SmartContract.Domain; using Google.Protobuf.Collections; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; @@ -13,479 +13,456 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class PlainTransactionExecutingService : IPlainTransactionExecutingService, ISingletonDependency { - public class PlainTransactionExecutingService : IPlainTransactionExecutingService, ISingletonDependency + private readonly List _postPlugins; + private readonly List _prePlugins; + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ITransactionContextFactory _transactionContextFactory; + + public PlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService, + IEnumerable postPlugins, IEnumerable prePlugins, + ITransactionContextFactory transactionContextFactory) { - private readonly ISmartContractExecutiveService _smartContractExecutiveService; - private readonly ITransactionContextFactory _transactionContextFactory; - private readonly List _prePlugins; - private readonly List _postPlugins; - public ILogger Logger { get; set; } + _smartContractExecutiveService = smartContractExecutiveService; + _transactionContextFactory = transactionContextFactory; + _prePlugins = GetUniquePlugins(prePlugins); + _postPlugins = GetUniquePlugins(postPlugins); + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + } - public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public PlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService, - IEnumerable postPlugins, IEnumerable prePlugins, - ITransactionContextFactory transactionContextFactory) - { - _smartContractExecutiveService = smartContractExecutiveService; - _transactionContextFactory = transactionContextFactory; - _prePlugins = GetUniquePlugins(prePlugins); - _postPlugins = GetUniquePlugins(postPlugins); - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILocalEventBus LocalEventBus { get; set; } - public async Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, - CancellationToken cancellationToken) + public async Task> ExecuteAsync(TransactionExecutingDto transactionExecutingDto, + CancellationToken cancellationToken) + { + try { - try + var groupStateCache = transactionExecutingDto.PartialBlockStateSet.ToTieredStateCache(); + var groupChainContext = new ChainContextWithTieredStateCache( + transactionExecutingDto.BlockHeader.PreviousBlockHash, + transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); + + var returnSets = new List(); + foreach (var transaction in transactionExecutingDto.Transactions) { - var groupStateCache = transactionExecutingDto.PartialBlockStateSet.ToTieredStateCache(); - var groupChainContext = new ChainContextWithTieredStateCache( - transactionExecutingDto.BlockHeader.PreviousBlockHash, - transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); + TransactionTrace trace; + if (cancellationToken.IsCancellationRequested) + break; - var returnSets = new List(); - foreach (var transaction in transactionExecutingDto.Transactions) + var singleTxExecutingDto = new SingleTransactionExecutingDto { - TransactionTrace trace; + Depth = 0, + ChainContext = groupChainContext, + Transaction = transaction, + CurrentBlockTime = transactionExecutingDto.BlockHeader.Time, + OriginTransactionId = transaction.GetHash() + }; + try + { + var transactionExecutionTask = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto, + cancellationToken), cancellationToken); + + trace = await transactionExecutionTask.WithCancellation(cancellationToken); + } + catch (OperationCanceledException) + { + Logger.LogTrace("Transaction canceled"); if (cancellationToken.IsCancellationRequested) break; + continue; + } - var singleTxExecutingDto = new SingleTransactionExecutingDto - { - Depth = 0, - ChainContext = groupChainContext, - Transaction = transaction, - CurrentBlockTime = transactionExecutingDto.BlockHeader.Time, - OriginTransactionId = transaction.GetHash() - }; - try - { - var transactionExecutionTask = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto, - cancellationToken), cancellationToken); - - trace = await transactionExecutionTask.WithCancellation(cancellationToken); - } - catch (OperationCanceledException) - { - Logger.LogTrace("Transaction canceled."); - if (cancellationToken.IsCancellationRequested) - break; - continue; - } - - - if (!TryUpdateStateCache(trace, groupStateCache)) - break; + + if (!TryUpdateStateCache(trace, groupStateCache)) + break; #if DEBUG - if (!string.IsNullOrEmpty(trace.Error)) - { - Logger.LogInformation(trace.Error); - } + if (!string.IsNullOrEmpty(trace.Error)) Logger.LogInformation("{Error}", trace.Error); #endif - var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); - - var returnSet = GetReturnSet(trace, result); - returnSets.Add(returnSet); - } + var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); - return returnSets; + var returnSet = GetReturnSet(trace, result); + returnSets.Add(returnSet); } - catch (Exception e) - { - Logger.LogError(e, "Failed while executing txs in block."); - throw; - } - } - private static bool TryUpdateStateCache(TransactionTrace trace, TieredStateCache groupStateCache) + return returnSets; + } + catch (Exception e) { - if (trace == null) - return false; + Logger.LogError(e, "Failed while executing txs in block"); + throw; + } + } - if (!trace.IsSuccessful()) - { - var transactionExecutingStateSets = new List(); + private static bool TryUpdateStateCache(TransactionTrace trace, TieredStateCache groupStateCache) + { + if (trace == null) + return false; - AddToTransactionStateSets(transactionExecutingStateSets, trace.PreTraces); - AddToTransactionStateSets(transactionExecutingStateSets, trace.PostTraces); + if (!trace.IsSuccessful()) + { + var transactionExecutingStateSets = new List(); - groupStateCache.Update(transactionExecutingStateSets); - trace.SurfaceUpError(); - } - else - { - groupStateCache.Update(trace.GetStateSets()); - } + AddToTransactionStateSets(transactionExecutingStateSets, trace.PreTraces); + AddToTransactionStateSets(transactionExecutingStateSets, trace.PostTraces); - return true; + groupStateCache.Update(transactionExecutingStateSets); + trace.SurfaceUpError(); } - - private static void AddToTransactionStateSets(List transactionExecutingStateSets, - RepeatedField traces) + else { - transactionExecutingStateSets.AddRange(traces.Where(p => p.IsSuccessful()) - .SelectMany(p => p.GetStateSets())); + groupStateCache.Update(trace.GetStateSets()); } - protected virtual async Task ExecuteOneAsync( - SingleTransactionExecutingDto singleTxExecutingDto, - CancellationToken cancellationToken) - { - if (singleTxExecutingDto.IsCancellable) - cancellationToken.ThrowIfCancellationRequested(); + return true; + } - var txContext = CreateTransactionContext(singleTxExecutingDto); - var trace = txContext.Trace; + private static void AddToTransactionStateSets(List transactionExecutingStateSets, + RepeatedField traces) + { + transactionExecutingStateSets.AddRange(traces.Where(p => p.IsSuccessful()) + .SelectMany(p => p.GetStateSets())); + } - var internalStateCache = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache); - var internalChainContext = - new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache); + protected virtual async Task ExecuteOneAsync( + SingleTransactionExecutingDto singleTxExecutingDto, + CancellationToken cancellationToken) + { + if (singleTxExecutingDto.IsCancellable) + cancellationToken.ThrowIfCancellationRequested(); - IExecutive executive; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync( - internalChainContext, - singleTxExecutingDto.Transaction.To); - } - catch (SmartContractFindRegistrationException) - { - txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; - txContext.Trace.Error += "Invalid contract address.\n"; - return trace; - } + var txContext = CreateTransactionContext(singleTxExecutingDto); + var trace = txContext.Trace; - try - { - #region PreTransaction + var internalStateCache = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache); + var internalChainContext = + new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache); - if (singleTxExecutingDto.Depth == 0) - { - if (!await ExecutePluginOnPreTransactionStageAsync(executive, txContext, + IExecutive executive; + try + { + executive = await _smartContractExecutiveService.GetExecutiveAsync( + internalChainContext, + singleTxExecutingDto.Transaction.To); + } + catch (SmartContractFindRegistrationException) + { + txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; + txContext.Trace.Error += "Invalid contract address.\n"; + return trace; + } + + try + { + #region PreTransaction + + if (singleTxExecutingDto.Depth == 0) + if (!await ExecutePluginOnPreTransactionStageAsync(executive, txContext, singleTxExecutingDto.CurrentBlockTime, internalChainContext, internalStateCache, cancellationToken)) - { - trace.ExecutionStatus = ExecutionStatus.Prefailed; - return trace; - } + { + trace.ExecutionStatus = ExecutionStatus.Prefailed; + return trace; } - #endregion + #endregion - await executive.ApplyAsync(txContext); + await executive.ApplyAsync(txContext); - if (txContext.Trace.IsSuccessful()) - await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime, - txContext, internalStateCache, - internalChainContext, - singleTxExecutingDto.OriginTransactionId, - cancellationToken); + if (txContext.Trace.IsSuccessful()) + await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime, + txContext, internalStateCache, + internalChainContext, + singleTxExecutingDto.OriginTransactionId, + cancellationToken); - #region PostTransaction + #region PostTransaction - if (singleTxExecutingDto.Depth == 0) - { - if (!await ExecutePluginOnPostTransactionStageAsync(executive, txContext, + if (singleTxExecutingDto.Depth == 0) + if (!await ExecutePluginOnPostTransactionStageAsync(executive, txContext, singleTxExecutingDto.CurrentBlockTime, internalChainContext, internalStateCache, cancellationToken)) - { - trace.ExecutionStatus = ExecutionStatus.Postfailed; - return trace; - } + { + trace.ExecutionStatus = ExecutionStatus.Postfailed; + return trace; } - #endregion - } - catch (Exception ex) - { - Logger.LogError(ex, "Transaction execution failed."); - txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; - txContext.Trace.Error += ex + "\n"; - throw; - } - finally + #endregion + } + catch (Exception ex) + { + Logger.LogError(ex, "Transaction execution failed"); + txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; + txContext.Trace.Error += ex + "\n"; + throw; + } + finally + { + await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext, + singleTxExecutingDto.Transaction.To, executive); + } + + return trace; + } + + private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTime, + ITransactionContext txContext, TieredStateCache internalStateCache, + IChainContext internalChainContext, + Hash originTransactionId, + CancellationToken cancellationToken) + { + var trace = txContext.Trace; + internalStateCache.Update(txContext.Trace.GetStateSets()); + foreach (var inlineTx in txContext.Trace.InlineTransactions) + { + var singleTxExecutingDto = new SingleTransactionExecutingDto { - await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext, - singleTxExecutingDto.Transaction.To, executive); - } + Depth = depth + 1, + ChainContext = internalChainContext, + Transaction = inlineTx, + CurrentBlockTime = currentBlockTime, + Origin = txContext.Origin, + OriginTransactionId = originTransactionId + }; - return trace; + var inlineTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); + + if (inlineTrace == null) + break; + trace.InlineTraces.Add(inlineTrace); + if (!inlineTrace.IsSuccessful()) + // Already failed, no need to execute remaining inline transactions + break; + + internalStateCache.Update(inlineTrace.GetStateSets()); } + } - private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTime, - ITransactionContext txContext, TieredStateCache internalStateCache, - IChainContext internalChainContext, - Hash originTransactionId, - CancellationToken cancellationToken) + private async Task ExecutePluginOnPreTransactionStageAsync(IExecutive executive, + ITransactionContext txContext, + Timestamp currentBlockTime, + IChainContext internalChainContext, + TieredStateCache internalStateCache, + CancellationToken cancellationToken) + { + var trace = txContext.Trace; + foreach (var plugin in _prePlugins) { - var trace = txContext.Trace; - internalStateCache.Update(txContext.Trace.GetStateSets()); - foreach (var inlineTx in txContext.Trace.InlineTransactions) + var transactions = await plugin.GetPreTransactionsAsync(executive.Descriptors, txContext); + foreach (var preTx in transactions) { var singleTxExecutingDto = new SingleTransactionExecutingDto { - Depth = depth + 1, + Depth = 0, //TODO: this 0 means it is possible that pre/post txs could have own pre/post txs ChainContext = internalChainContext, - Transaction = inlineTx, + Transaction = preTx, CurrentBlockTime = currentBlockTime, - Origin = txContext.Origin, - OriginTransactionId = originTransactionId + OriginTransactionId = txContext.OriginTransactionId }; + var preTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); + if (preTrace == null) + return false; + trace.PreTransactions.Add(preTx); + trace.PreTraces.Add(preTrace); - var inlineTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); + if (!preTrace.IsSuccessful()) return false; - if (inlineTrace == null) - break; - trace.InlineTraces.Add(inlineTrace); - if (!inlineTrace.IsSuccessful()) - { - // Already failed, no need to execute remaining inline transactions - break; - } + var stateSets = preTrace.GetStateSets().ToList(); + internalStateCache.Update(stateSets); + var parentStateCache = txContext.StateCache as TieredStateCache; + parentStateCache?.Update(stateSets); + + if (!plugin.IsStopExecuting(preTrace.ReturnValue, out var error)) continue; - internalStateCache.Update(inlineTrace.GetStateSets()); + // If pre-tx fails, still commit the changes, but return false to notice outside to stop the execution. + preTrace.Error = error; + preTrace.ExecutionStatus = ExecutionStatus.Executed; + return false; } } - private async Task ExecutePluginOnPreTransactionStageAsync(IExecutive executive, - ITransactionContext txContext, - Timestamp currentBlockTime, - IChainContext internalChainContext, - TieredStateCache internalStateCache, - CancellationToken cancellationToken) + return true; + } + + private async Task ExecutePluginOnPostTransactionStageAsync(IExecutive executive, + ITransactionContext txContext, + Timestamp currentBlockTime, + IChainContext internalChainContext, + TieredStateCache internalStateCache, + CancellationToken cancellationToken) + { + var trace = txContext.Trace; + + if (!trace.IsSuccessful()) { - var trace = txContext.Trace; - foreach (var plugin in _prePlugins) + // If failed to execute this tx, at least we need to commit pre traces. + internalStateCache = new TieredStateCache(txContext.StateCache); + foreach (var preTrace in txContext.Trace.PreTraces) { - var transactions = await plugin.GetPreTransactionsAsync(executive.Descriptors, txContext); - foreach (var preTx in transactions) - { - var singleTxExecutingDto = new SingleTransactionExecutingDto - { - Depth = 0, //TODO: this 0 means it is possible that pre/post txs could have own pre/post txs - ChainContext = internalChainContext, - Transaction = preTx, - CurrentBlockTime = currentBlockTime, - OriginTransactionId = txContext.OriginTransactionId - }; - var preTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); - if (preTrace == null) - return false; - trace.PreTransactions.Add(preTx); - trace.PreTraces.Add(preTrace); - - if (!preTrace.IsSuccessful()) - { - return false; - } - - var stateSets = preTrace.GetStateSets().ToList(); - internalStateCache.Update(stateSets); - var parentStateCache = txContext.StateCache as TieredStateCache; - parentStateCache?.Update(stateSets); - - if (!plugin.IsStopExecuting(preTrace.ReturnValue, out var error)) continue; - - // If pre-tx fails, still commit the changes, but return false to notice outside to stop the execution. - preTrace.Error = error; - preTrace.ExecutionStatus = ExecutionStatus.Executed; - return false; - } + var stateSets = preTrace.GetStateSets(); + internalStateCache.Update(stateSets); } - return true; + internalChainContext.StateCache = internalStateCache; } - private async Task ExecutePluginOnPostTransactionStageAsync(IExecutive executive, - ITransactionContext txContext, - Timestamp currentBlockTime, - IChainContext internalChainContext, - TieredStateCache internalStateCache, - CancellationToken cancellationToken) + foreach (var plugin in _postPlugins) { - var trace = txContext.Trace; - - if (!trace.IsSuccessful()) + var transactions = await plugin.GetPostTransactionsAsync(executive.Descriptors, txContext); + foreach (var postTx in transactions) { - // If failed to execute this tx, at least we need to commit pre traces. - internalStateCache = new TieredStateCache(txContext.StateCache); - foreach (var preTrace in txContext.Trace.PreTraces) + var singleTxExecutingDto = new SingleTransactionExecutingDto { - var stateSets = preTrace.GetStateSets(); - internalStateCache.Update(stateSets); - } - - internalChainContext.StateCache = internalStateCache; - } + Depth = 0, + ChainContext = internalChainContext, + Transaction = postTx, + CurrentBlockTime = currentBlockTime, + OriginTransactionId = txContext.OriginTransactionId + }; + var postTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); - foreach (var plugin in _postPlugins) - { - var transactions = await plugin.GetPostTransactionsAsync(executive.Descriptors, txContext); - foreach (var postTx in transactions) - { - var singleTxExecutingDto = new SingleTransactionExecutingDto - { - Depth = 0, - ChainContext = internalChainContext, - Transaction = postTx, - CurrentBlockTime = currentBlockTime, - OriginTransactionId = txContext.OriginTransactionId - }; - var postTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); - - if (postTrace == null) - return false; - trace.PostTransactions.Add(postTx); - trace.PostTraces.Add(postTrace); - - if (!postTrace.IsSuccessful()) - { - return false; - } - - internalStateCache.Update(postTrace.GetStateSets()); - } - } + if (postTrace == null) + return false; + trace.PostTransactions.Add(postTx); + trace.PostTraces.Add(postTrace); - return true; - } + if (!postTrace.IsSuccessful()) return false; - private TransactionResult GetTransactionResult(TransactionTrace trace, long blockHeight) - { - var txResult = new TransactionResult - { - TransactionId = trace.TransactionId, - BlockNumber = blockHeight, - }; - - if (!trace.IsSuccessful()) - { - // Is failed. - txResult.Status = TransactionResultStatus.Failed; - if (trace.ExecutionStatus == ExecutionStatus.Undefined) - { - // Cannot find specific contract method. - txResult.Error = ExecutionStatus.Undefined.ToString(); - } - else - { - txResult.Error = trace.Error; - if (trace.ExecutionStatus != ExecutionStatus.Prefailed || IsExecutionStoppedByPrePlugin(trace)) - { - txResult.Logs.AddRange(trace.GetPluginLogs()); - txResult.UpdateBloom(); - } - } + internalStateCache.Update(postTrace.GetStateSets()); } - else - { - // Is successful. - txResult.Status = TransactionResultStatus.Mined; - txResult.ReturnValue = trace.ReturnValue; - txResult.Logs.AddRange(trace.FlattenedLogs); - - txResult.UpdateBloom(); - } - - return txResult; } - private ExecutionReturnSet GetReturnSet(TransactionTrace trace, TransactionResult result) + return true; + } + + private TransactionResult GetTransactionResult(TransactionTrace trace, long blockHeight) + { + var txResult = new TransactionResult { - var returnSet = new ExecutionReturnSet - { - TransactionId = result.TransactionId, - Status = result.Status, - Bloom = result.Bloom, - TransactionResult = result - }; + TransactionId = trace.TransactionId, + BlockNumber = blockHeight + }; - if (trace.IsSuccessful()) + if (!trace.IsSuccessful()) + { + // Is failed. + txResult.Status = TransactionResultStatus.Failed; + if (trace.ExecutionStatus == ExecutionStatus.Undefined) { - var transactionExecutingStateSets = trace.GetStateSets(); - returnSet = GetReturnSet(returnSet, transactionExecutingStateSets); - returnSet.ReturnValue = trace.ReturnValue; + // Cannot find specific contract method. + txResult.Error = ExecutionStatus.Undefined.ToString(); } else { - var transactionExecutingStateSets = new List(); - foreach (var preTrace in trace.PreTraces) + txResult.Error = trace.Error; + if (trace.ExecutionStatus != ExecutionStatus.Prefailed || IsExecutionStoppedByPrePlugin(trace)) { - if (preTrace.IsSuccessful()) - transactionExecutingStateSets.AddRange(preTrace.GetStateSets()); + txResult.Logs.AddRange(trace.GetPluginLogs()); + txResult.UpdateBloom(); } + } + } + else + { + // Is successful. + txResult.Status = TransactionResultStatus.Mined; + txResult.ReturnValue = trace.ReturnValue; + txResult.Logs.AddRange(trace.FlattenedLogs); - foreach (var postTrace in trace.PostTraces) - { - if (postTrace.IsSuccessful()) transactionExecutingStateSets.AddRange(postTrace.GetStateSets()); - } + txResult.UpdateBloom(); + } - returnSet = GetReturnSet(returnSet, transactionExecutingStateSets); - } + return txResult; + } - var reads = trace.GetFlattenedReads(); - foreach (var read in reads) - { - returnSet.StateAccesses[read.Key] = read.Value; - } + private ExecutionReturnSet GetReturnSet(TransactionTrace trace, TransactionResult result) + { + var returnSet = new ExecutionReturnSet + { + TransactionId = result.TransactionId, + Status = result.Status, + Bloom = result.Bloom, + TransactionResult = result + }; - return returnSet; + if (trace.IsSuccessful()) + { + var transactionExecutingStateSets = trace.GetStateSets(); + returnSet = GetReturnSet(returnSet, transactionExecutingStateSets); + returnSet.ReturnValue = trace.ReturnValue; } - - private ExecutionReturnSet GetReturnSet(ExecutionReturnSet returnSet, - IEnumerable transactionExecutingStateSets) + else { - foreach (var transactionExecutingStateSet in transactionExecutingStateSets) - { - foreach (var write in transactionExecutingStateSet.Writes) - { - returnSet.StateChanges[write.Key] = write.Value; - returnSet.StateDeletes.Remove(write.Key); - } + var transactionExecutingStateSets = new List(); + foreach (var preTrace in trace.PreTraces) + if (preTrace.IsSuccessful()) + transactionExecutingStateSets.AddRange(preTrace.GetStateSets()); - foreach (var delete in transactionExecutingStateSet.Deletes) - { - returnSet.StateDeletes[delete.Key] = delete.Value; - returnSet.StateChanges.Remove(delete.Key); - } - } + foreach (var postTrace in trace.PostTraces) + if (postTrace.IsSuccessful()) + transactionExecutingStateSets.AddRange(postTrace.GetStateSets()); - return returnSet; + returnSet = GetReturnSet(returnSet, transactionExecutingStateSets); } - private static List GetUniquePlugins(IEnumerable plugins) - { - // One instance per type - return plugins.ToLookup(p => p.GetType()).Select(coll => coll.First()).ToList(); - } + var reads = trace.GetFlattenedReads(); + foreach (var read in reads) returnSet.StateAccesses[read.Key] = read.Value; - private bool IsExecutionStoppedByPrePlugin(TransactionTrace trace) - { - return _prePlugins.Any(prePlugin => - trace.PreTraces.Any(preTrace => prePlugin.IsStopExecuting(preTrace.ReturnValue, out _))); - } + return returnSet; + } - protected ITransactionContext CreateTransactionContext(SingleTransactionExecutingDto singleTxExecutingDto) + private ExecutionReturnSet GetReturnSet(ExecutionReturnSet returnSet, + IEnumerable transactionExecutingStateSets) + { + foreach (var transactionExecutingStateSet in transactionExecutingStateSets) { - if (singleTxExecutingDto.Transaction.To == null || singleTxExecutingDto.Transaction.From == null) + foreach (var write in transactionExecutingStateSet.Writes) { - throw new Exception($"error tx: {singleTxExecutingDto.Transaction}"); + returnSet.StateChanges[write.Key] = write.Value; + returnSet.StateDeletes.Remove(write.Key); } + foreach (var delete in transactionExecutingStateSet.Deletes) + { + returnSet.StateDeletes[delete.Key] = delete.Value; + returnSet.StateChanges.Remove(delete.Key); + } + } - var origin = singleTxExecutingDto.Origin != null - ? singleTxExecutingDto.Origin - : singleTxExecutingDto.Transaction.From; - - var txContext = _transactionContextFactory.Create(singleTxExecutingDto.Transaction, - singleTxExecutingDto.ChainContext, singleTxExecutingDto.OriginTransactionId, origin, - singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime); + return returnSet; + } - return txContext; - } + private static List GetUniquePlugins(IEnumerable plugins) + { + // One instance per type + return plugins.ToLookup(p => p.GetType()).Select(coll => coll.First()).ToList(); + } + + private bool IsExecutionStoppedByPrePlugin(TransactionTrace trace) + { + return _prePlugins.Any(prePlugin => + trace.PreTraces.Any(preTrace => prePlugin.IsStopExecuting(preTrace.ReturnValue, out _))); + } + + protected ITransactionContext CreateTransactionContext(SingleTransactionExecutingDto singleTxExecutingDto) + { + if (singleTxExecutingDto.Transaction.To == null || singleTxExecutingDto.Transaction.From == null) + throw new Exception($"error tx: {singleTxExecutingDto.Transaction}"); + + + var origin = singleTxExecutingDto.Origin != null + ? singleTxExecutingDto.Origin + : singleTxExecutingDto.Transaction.From; + + var txContext = _transactionContextFactory.Create(singleTxExecutingDto.Transaction, + singleTxExecutingDto.ChainContext, singleTxExecutingDto.OriginTransactionId, origin, + singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime); + + return txContext; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/ReadOnlyMethodStubFactory.cs b/src/AElf.Kernel.SmartContract/Application/ReadOnlyMethodStubFactory.cs index ac01fc66cc..5dcf1c196f 100644 --- a/src/AElf.Kernel.SmartContract/Application/ReadOnlyMethodStubFactory.cs +++ b/src/AElf.Kernel.SmartContract/Application/ReadOnlyMethodStubFactory.cs @@ -4,73 +4,71 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class ReadOnlyMethodStubFactory : IMethodStubFactory { - public class ReadOnlyMethodStubFactory : IMethodStubFactory + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + private ContractReaderContext _contractReaderContext; + + public ReadOnlyMethodStubFactory(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) { - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private ContractReaderContext _contractReaderContext; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + } - public ReadOnlyMethodStubFactory(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) + public IMethodStub Create(Method method) + where TInput : IMessage, new() where TOutput : IMessage, new() + { + Task> SendAsync(TInput input) { - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + throw new NotSupportedException(); } - public IMethodStub Create(Method method) - where TInput : IMessage, new() where TOutput : IMessage, new() + async Task CallAsync(TInput input) { - Task> SendAsync(TInput input) - { - throw new NotSupportedException(); - } + if (_contractReaderContext.ContractAddress == null) + return default; - async Task CallAsync(TInput input) + var chainContext = new ChainContext { - if (_contractReaderContext.ContractAddress == null) - return default; - - var chainContext = new ChainContext - { - BlockHash = _contractReaderContext.BlockHash, - BlockHeight = _contractReaderContext.BlockHeight, - StateCache = _contractReaderContext.StateCache - }; - var transaction = new Transaction() - { - From = _contractReaderContext.Sender ?? _contractReaderContext.ContractAddress, - To = _contractReaderContext.ContractAddress, - MethodName = method.Name, - Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) - }; - - var trace = - await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - _contractReaderContext.Timestamp ?? TimestampHelper.GetUtcNow()); - - return trace.IsSuccessful() - ? method.ResponseMarshaller.Deserializer(trace.ReturnValue.ToByteArray()) - : default; - } - - Transaction GetTransaction(TInput input) + BlockHash = _contractReaderContext.BlockHash, + BlockHeight = _contractReaderContext.BlockHeight, + StateCache = _contractReaderContext.StateCache + }; + var transaction = new Transaction { - var transaction = new Transaction() - { - From = _contractReaderContext.Sender, - To = _contractReaderContext.ContractAddress, - MethodName = method.Name, - Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) - }; - return transaction; - } + From = _contractReaderContext.Sender ?? _contractReaderContext.ContractAddress, + To = _contractReaderContext.ContractAddress, + MethodName = method.Name, + Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + }; - return new MethodStub(method, SendAsync, CallAsync, GetTransaction); + var trace = + await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, + _contractReaderContext.Timestamp ?? TimestampHelper.GetUtcNow()); + + return trace.IsSuccessful() + ? method.ResponseMarshaller.Deserializer(trace.ReturnValue.ToByteArray()) + : default; } - public void SetContractReaderContext(ContractReaderContext contractReaderContext) + Transaction GetTransaction(TInput input) { - _contractReaderContext = contractReaderContext; + var transaction = new Transaction + { + From = _contractReaderContext.Sender, + To = _contractReaderContext.ContractAddress, + MethodName = method.Name, + Params = ByteString.CopyFrom(method.RequestMarshaller.Serializer(input)) + }; + return transaction; } + return new MethodStub(method, SendAsync, CallAsync, GetTransaction); + } + + public void SetContractReaderContext(ContractReaderContext contractReaderContext) + { + _contractReaderContext = contractReaderContext; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutingException.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutingException.cs index fa55c9f0c3..c2274fe2d2 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutingException.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutingException.cs @@ -1,34 +1,33 @@ using System; using System.Runtime.Serialization; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +[Serializable] +public class SmartContractExecutingException : Exception { - [Serializable] - public class SmartContractExecutingException : Exception - { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // - public SmartContractExecutingException() - { - } + public SmartContractExecutingException() + { + } - public SmartContractExecutingException(string message) : base(message) - { - } + public SmartContractExecutingException(string message) : base(message) + { + } - public SmartContractExecutingException(string message, Exception inner) : base(message, inner) - { - } + public SmartContractExecutingException(string message, Exception inner) : base(message, inner) + { + } - protected SmartContractExecutingException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + protected SmartContractExecutingException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutionPluginBase.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutionPluginBase.cs index e2e273f4a5..81ee3eb2d3 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutionPluginBase.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutionPluginBase.cs @@ -2,20 +2,19 @@ using System.Linq; using Google.Protobuf.Reflection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public abstract class SmartContractExecutionPluginBase { - public abstract class SmartContractExecutionPluginBase - { - private readonly string _acsSymbol; + private readonly string _acsSymbol; - protected SmartContractExecutionPluginBase(string acsSymbol) - { - _acsSymbol = acsSymbol; - } + protected SmartContractExecutionPluginBase(string acsSymbol) + { + _acsSymbol = acsSymbol; + } - protected bool IsTargetAcsSymbol(IReadOnlyList descriptors) - { - return descriptors.Any(service => service.File.GetIdentity() == _acsSymbol); - } + protected bool IsTargetAcsSymbol(IReadOnlyList descriptors) + { + return descriptors.Any(service => service.File.GetIdentity() == _acsSymbol); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveProvider.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveProvider.cs index db883172c9..14aa3c182e 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveProvider.cs @@ -7,56 +7,55 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractExecutiveProvider { - public interface ISmartContractExecutiveProvider - { - IReadOnlyDictionary> GetExecutivePools(); - ConcurrentBag GetPool(Address address); - bool TryGetValue(Address address, out ConcurrentBag executiveBag); - bool TryRemove(Address address, out ConcurrentBag executiveBag); - } + IReadOnlyDictionary> GetExecutivePools(); + ConcurrentBag GetPool(Address address); + bool TryGetValue(Address address, out ConcurrentBag executiveBag); + bool TryRemove(Address address, out ConcurrentBag executiveBag); +} - public class SmartContractExecutiveProvider : ISmartContractExecutiveProvider, ISingletonDependency - { - private readonly ConcurrentDictionary> - _executivePools = new ConcurrentDictionary>(); +public class SmartContractExecutiveProvider : ISmartContractExecutiveProvider, ISingletonDependency +{ + private readonly ConcurrentDictionary> + _executivePools = new(); - private readonly IReadOnlyDictionary> ExecutivePools; + private readonly IReadOnlyDictionary> ExecutivePools; - public ILogger Logger { get; set; } + public SmartContractExecutiveProvider() + { + ExecutivePools = + new ReadOnlyDictionary>(_executivePools); + Logger = NullLogger.Instance; + } - public SmartContractExecutiveProvider() - { - ExecutivePools = - new ReadOnlyDictionary>(_executivePools); - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public IReadOnlyDictionary> GetExecutivePools() - { - return ExecutivePools; - } + public IReadOnlyDictionary> GetExecutivePools() + { + return ExecutivePools; + } - public ConcurrentBag GetPool(Address address) + public ConcurrentBag GetPool(Address address) + { + if (!_executivePools.TryGetValue(address, out var pool)) { - if (!_executivePools.TryGetValue(address, out var pool)) - { - pool = new ConcurrentBag(); - _executivePools[address] = pool; - } - - return pool; + pool = new ConcurrentBag(); + _executivePools[address] = pool; } - public bool TryGetValue(Address address, out ConcurrentBag executiveBag) - { - return _executivePools.TryGetValue(address, out executiveBag); - } + return pool; + } - public bool TryRemove(Address address, out ConcurrentBag executiveBag) - { - return _executivePools.TryRemove(address, out executiveBag); - } + public bool TryGetValue(Address address, out ConcurrentBag executiveBag) + { + return _executivePools.TryGetValue(address, out executiveBag); + } + + public bool TryRemove(Address address, out ConcurrentBag executiveBag) + { + return _executivePools.TryRemove(address, out executiveBag); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveService.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveService.cs index 3ba7588d53..06d0bff8dd 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveService.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractExecutiveService.cs @@ -9,202 +9,191 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class SmartContractExecutiveService : ISmartContractExecutiveService, ISingletonDependency { - public class SmartContractExecutiveService : ISmartContractExecutiveService, ISingletonDependency + private const int ExecutiveExpirationTime = 3600; // 1 Hour + private const int ExecutiveClearLimit = 10; + + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; + private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + private readonly ISmartContractRunnerContainer _smartContractRunnerContainer; + private readonly ITransactionContextFactory _transactionContextFactory; + + public SmartContractExecutiveService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ISmartContractRunnerContainer smartContractRunnerContainer, + IHostSmartContractBridgeContextService hostSmartContractBridgeContextService, + ISmartContractRegistrationProvider smartContractRegistrationProvider, + ISmartContractExecutiveProvider smartContractExecutiveProvider, + ITransactionContextFactory transactionContextFactory) { - private const int ExecutiveExpirationTime = 3600; // 1 Hour - private const int ExecutiveClearLimit = 10; - - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ISmartContractRunnerContainer _smartContractRunnerContainer; - private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; - private readonly ITransactionContextFactory _transactionContextFactory; - public ILogger Logger { get; set; } - - public SmartContractExecutiveService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ISmartContractRunnerContainer smartContractRunnerContainer, - IHostSmartContractBridgeContextService hostSmartContractBridgeContextService, - ISmartContractRegistrationProvider smartContractRegistrationProvider, - ISmartContractExecutiveProvider smartContractExecutiveProvider, - ITransactionContextFactory transactionContextFactory) - { - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - _smartContractRunnerContainer = smartContractRunnerContainer; - _hostSmartContractBridgeContextService = hostSmartContractBridgeContextService; - _smartContractRegistrationProvider = smartContractRegistrationProvider; - _smartContractExecutiveProvider = smartContractExecutiveProvider; - _transactionContextFactory = transactionContextFactory; - - Logger = NullLogger.Instance; - } + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + _smartContractRunnerContainer = smartContractRunnerContainer; + _hostSmartContractBridgeContextService = hostSmartContractBridgeContextService; + _smartContractRegistrationProvider = smartContractRegistrationProvider; + _smartContractExecutiveProvider = smartContractExecutiveProvider; + _transactionContextFactory = transactionContextFactory; + + Logger = NullLogger.Instance; + } - public async Task GetExecutiveAsync(IChainContext chainContext, Address address) - { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + public ILogger Logger { get; set; } - var pool = _smartContractExecutiveProvider.GetPool(address); - var smartContractRegistration = await GetSmartContractRegistrationAsync(chainContext, address); + public async Task GetExecutiveAsync(IChainContext chainContext, Address address) + { + if (address == null) throw new ArgumentNullException(nameof(address)); - if (!pool.TryTake(out var executive)) - { - executive = await GetExecutiveAsync(smartContractRegistration); - } - else if (smartContractRegistration.CodeHash != executive.ContractHash) - { - _smartContractExecutiveProvider.TryRemove(address, out _); - executive = await GetExecutiveAsync(smartContractRegistration); - } + var pool = _smartContractExecutiveProvider.GetPool(address); + var smartContractRegistration = await GetSmartContractRegistrationAsync(chainContext, address); - return executive; + if (!pool.TryTake(out var executive)) + { + executive = await GetExecutiveAsync(smartContractRegistration); } + else if (smartContractRegistration.CodeHash != executive.ContractHash) + { + _smartContractExecutiveProvider.TryRemove(address, out _); + executive = await GetExecutiveAsync(smartContractRegistration); + } + + return executive; + } - public virtual async Task PutExecutiveAsync(IChainContext chainContext, Address address, IExecutive executive) + public virtual async Task PutExecutiveAsync(IChainContext chainContext, Address address, IExecutive executive) + { + if (_smartContractExecutiveProvider.TryGetValue(address, out var pool)) { - if (_smartContractExecutiveProvider.TryGetValue(address, out var pool)) - { - var smartContractRegistration = - await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, address); - if (smartContractRegistration != null && smartContractRegistration.CodeHash == executive.ContractHash && pool.Count < ExecutiveClearLimit|| - chainContext.BlockHeight <= AElfConstants.GenesisBlockHeight) - { - executive.LastUsedTime = TimestampHelper.GetUtcNow(); - pool.Add(executive); - return; - } - - Logger.LogDebug($"Lost an executive (no registration {address})"); - } - else + var smartContractRegistration = + await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, address); + if ((smartContractRegistration != null && smartContractRegistration.CodeHash == executive.ContractHash && + pool.Count < ExecutiveClearLimit) || + chainContext.BlockHeight <= AElfConstants.GenesisBlockHeight) { - Logger.LogDebug($"Lost an executive (no pool {address})"); + executive.LastUsedTime = TimestampHelper.GetUtcNow(); + pool.Add(executive); + return; } - await Task.CompletedTask; + Logger.LogDebug($"Lost an executive (no registration {address})"); } - - public void CleanExecutive(Address address) + else { - _smartContractExecutiveProvider.TryRemove(address, out _); + Logger.LogDebug($"Lost an executive (no pool {address})"); } - public void CleanIdleExecutive() + await Task.CompletedTask; + } + + public void CleanExecutive(Address address) + { + _smartContractExecutiveProvider.TryRemove(address, out _); + } + + public void CleanIdleExecutive() + { + var pools = _smartContractExecutiveProvider.GetExecutivePools(); + Logger.LogDebug($"Pools count {pools.Count}"); + var toBeRemoved = new List
(); + foreach (var executivePool in pools) { - var pools = _smartContractExecutiveProvider.GetExecutivePools(); - Logger.LogDebug($"Pools count {pools.Count}"); - var toBeRemoved = new List
(); - foreach (var executivePool in pools) - { - var executiveBag = executivePool.Value; - if (executiveBag.Count == 0) - continue; - - if (executiveBag.Count > ExecutiveClearLimit || executiveBag.Min(o => o.LastUsedTime) < - TimestampHelper.GetUtcNow() - TimestampHelper.DurationFromSeconds(ExecutiveExpirationTime)) - { - if (executiveBag.TryTake(out _)) - { - Logger.LogDebug($"Cleaned an idle executive for address {executivePool.Key}."); - } - - if (executiveBag.IsEmpty) - toBeRemoved.Add(executivePool.Key); - } - } + var executiveBag = executivePool.Value; + if (executiveBag.Count == 0) + continue; - // clean empty pools - foreach (var address in toBeRemoved) + if (executiveBag.Count > ExecutiveClearLimit || executiveBag.Min(o => o.LastUsedTime) < + TimestampHelper.GetUtcNow() - TimestampHelper.DurationFromSeconds(ExecutiveExpirationTime)) { - CleanExecutive(address); + if (executiveBag.TryTake(out _)) + Logger.LogDebug($"Cleaned an idle executive for address {executivePool.Key}."); + + if (executiveBag.IsEmpty) + toBeRemoved.Add(executivePool.Key); } } - private async Task GetExecutiveAsync(SmartContractRegistration reg) - { - // get runner - var runner = _smartContractRunnerContainer.GetRunner(reg.Category); + // clean empty pools + foreach (var address in toBeRemoved) CleanExecutive(address); + } - // run smartContract executive info and return executive - var executive = await runner.RunAsync(reg); + private async Task GetExecutiveAsync(SmartContractRegistration reg) + { + // get runner + var runner = _smartContractRunnerContainer.GetRunner(reg.Category); - var context = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(context); - return executive; - } + // run smartContract executive info and return executive + var executive = await runner.RunAsync(reg); - private async Task GetSmartContractRegistrationAsync( - IChainContext chainContext, Address address) - { - var smartContractRegistration = - await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, address); - if (smartContractRegistration != null) return smartContractRegistration; + var context = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(context); + return executive; + } - smartContractRegistration = await GetSmartContractRegistrationFromZeroAsync(chainContext, address); + private async Task GetSmartContractRegistrationAsync( + IChainContext chainContext, Address address) + { + var smartContractRegistration = + await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, address); + if (smartContractRegistration != null) return smartContractRegistration; - return smartContractRegistration; - } + smartContractRegistration = await GetSmartContractRegistrationFromZeroAsync(chainContext, address); + + return smartContractRegistration; + } - private async Task GetSmartContractRegistrationFromZeroAsync( - IChainContext chainContext, Address address) + private async Task GetSmartContractRegistrationFromZeroAsync( + IChainContext chainContext, Address address) + { + IExecutive executiveZero = null; + try { - IExecutive executiveZero = null; - try + if (address == _defaultContractZeroCodeProvider.ContractZeroAddress) { - if (address == _defaultContractZeroCodeProvider.ContractZeroAddress) - { - var smartContractRegistration = _defaultContractZeroCodeProvider.DefaultContractZeroRegistration; - if (chainContext.BlockHeight <= AElfConstants.GenesisBlockHeight) return smartContractRegistration; - //if Height > GenesisBlockHeight, maybe there is a new zero contract, - //the current smartContractRegistration is from code, - //not from zero contract, so we need to load new zero contract from the old smartContractRegistration, - //and replace it - executiveZero = await GetExecutiveAsync(smartContractRegistration); - } - else - { - executiveZero = - await GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - } - - return await GetSmartContractRegistrationFromZeroAsync(executiveZero, chainContext, address); + var smartContractRegistration = _defaultContractZeroCodeProvider.DefaultContractZeroRegistration; + if (chainContext.BlockHeight <= AElfConstants.GenesisBlockHeight) return smartContractRegistration; + //if Height > GenesisBlockHeight, maybe there is a new zero contract, + //the current smartContractRegistration is from code, + //not from zero contract, so we need to load new zero contract from the old smartContractRegistration, + //and replace it + executiveZero = await GetExecutiveAsync(smartContractRegistration); } - finally + else { - if (executiveZero != null) - { - await PutExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress, - executiveZero); - } + executiveZero = + await GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); } + + return await GetSmartContractRegistrationFromZeroAsync(executiveZero, chainContext, address); + } + finally + { + if (executiveZero != null) + await PutExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress, + executiveZero); } + } - private async Task GetSmartContractRegistrationFromZeroAsync( - IExecutive executiveZero, IChainContext chainContext, Address address) + private async Task GetSmartContractRegistrationFromZeroAsync( + IExecutive executiveZero, IChainContext chainContext, Address address) + { + var transaction = new Transaction { - var transaction = new Transaction() - { - From = _defaultContractZeroCodeProvider.ContractZeroAddress, - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = "GetSmartContractRegistrationByAddress", - Params = address.ToByteString() - }; + From = _defaultContractZeroCodeProvider.ContractZeroAddress, + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = "GetSmartContractRegistrationByAddress", + Params = address.ToByteString() + }; - var txContext = _transactionContextFactory.Create(transaction, chainContext); + var txContext = _transactionContextFactory.Create(transaction, chainContext); - await executiveZero.ApplyAsync(txContext); - var returnBytes = txContext.Trace?.ReturnValue; - if (returnBytes != null && returnBytes != ByteString.Empty) - { - return SmartContractRegistration.Parser.ParseFrom(returnBytes); - } + await executiveZero.ApplyAsync(txContext); + var returnBytes = txContext.Trace?.ReturnValue; + if (returnBytes != null && returnBytes != ByteString.Empty) + return SmartContractRegistration.Parser.ParseFrom(returnBytes); - throw new SmartContractFindRegistrationException( - $"failed to find registration from zero contract {txContext.Trace.Error}"); - } + throw new SmartContractFindRegistrationException( + $"failed to find registration from zero contract {txContext.Trace.Error}"); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractFindRegistrationException.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractFindRegistrationException.cs index 2f6c2643b5..c6ec6385fb 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractFindRegistrationException.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractFindRegistrationException.cs @@ -1,27 +1,26 @@ using System; using System.Runtime.Serialization; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +[Serializable] +public class SmartContractFindRegistrationException : Exception { - [Serializable] - public class SmartContractFindRegistrationException: Exception + public SmartContractFindRegistrationException() { - public SmartContractFindRegistrationException() - { - } + } - public SmartContractFindRegistrationException(string message) : base(message) - { - } + public SmartContractFindRegistrationException(string message) : base(message) + { + } - public SmartContractFindRegistrationException(string message, Exception inner) : base(message, inner) - { - } + public SmartContractFindRegistrationException(string message, Exception inner) : base(message, inner) + { + } - protected SmartContractFindRegistrationException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + protected SmartContractFindRegistrationException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractRegistrationProvider.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractRegistrationProvider.cs index ab342b1fed..a3b8713513 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractRegistrationProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractRegistrationProvider.cs @@ -1,45 +1,44 @@ -using System.Collections.Concurrent; using System.Threading.Tasks; using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ISmartContractRegistrationProvider { - public interface ISmartContractRegistrationProvider + Task GetSmartContractRegistrationAsync(IChainContext chainContext, Address address); + + Task SetSmartContractRegistrationAsync(IBlockIndex blockIndex, Address address, + SmartContractRegistration smartContractRegistration); +} + +public class SmartContractRegistrationProvider : BlockExecutedDataBaseProvider, + ISmartContractRegistrationProvider, + ISingletonDependency +{ + private const string BlockExecutedDataName = nameof(SmartContractRegistration); + + public SmartContractRegistrationProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( + cachedBlockchainExecutedDataService) { - Task GetSmartContractRegistrationAsync(IChainContext chainContext, Address address); + } - Task SetSmartContractRegistrationAsync(IBlockIndex blockIndex, Address address, - SmartContractRegistration smartContractRegistration); + public Task GetSmartContractRegistrationAsync(IChainContext chainContext, + Address address) + { + var smartContractRegistration = GetBlockExecutedData(chainContext, address); + return Task.FromResult(smartContractRegistration); + } + + public async Task SetSmartContractRegistrationAsync(IBlockIndex blockIndex, Address address, + SmartContractRegistration smartContractRegistration) + { + await AddBlockExecutedDataAsync(blockIndex, address, smartContractRegistration); } - public class SmartContractRegistrationProvider : BlockExecutedDataBaseProvider, ISmartContractRegistrationProvider, - ISingletonDependency + protected override string GetBlockExecutedDataName() { - private const string BlockExecutedDataName = nameof(SmartContractRegistration); - - public SmartContractRegistrationProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService) : base( - cachedBlockchainExecutedDataService) - { - - } - - public Task GetSmartContractRegistrationAsync(IChainContext chainContext, Address address) - { - var smartContractRegistration = GetBlockExecutedData(chainContext, address); - return Task.FromResult(smartContractRegistration); - } - - public async Task SetSmartContractRegistrationAsync(IBlockIndex blockIndex, Address address, - SmartContractRegistration smartContractRegistration) - { - await AddBlockExecutedDataAsync(blockIndex, address, smartContractRegistration); - } - - protected override string GetBlockExecutedDataName() - { - return BlockExecutedDataName; - } + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/SmartContractService.cs b/src/AElf.Kernel.SmartContract/Application/SmartContractService.cs index f6d681f915..1108c89743 100644 --- a/src/AElf.Kernel.SmartContract/Application/SmartContractService.cs +++ b/src/AElf.Kernel.SmartContract/Application/SmartContractService.cs @@ -2,35 +2,34 @@ using AElf.Kernel.SmartContract.Infrastructure; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class SmartContractService : ISmartContractService, ITransientDependency { - public class SmartContractService : ISmartContractService, ITransientDependency - { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ISmartContractRunnerContainer _smartContractRunnerContainer; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractRunnerContainer _smartContractRunnerContainer; - public SmartContractService(ISmartContractAddressService smartContractAddressService, - ISmartContractRunnerContainer smartContractRunnerContainer) - { - _smartContractAddressService = smartContractAddressService; - _smartContractRunnerContainer = smartContractRunnerContainer; - } + public SmartContractService(ISmartContractAddressService smartContractAddressService, + ISmartContractRunnerContainer smartContractRunnerContainer) + { + _smartContractAddressService = smartContractAddressService; + _smartContractRunnerContainer = smartContractRunnerContainer; + } - /// - public Task DeployContractAsync(ContractDto contractDto) - { - CheckRunner(contractDto.SmartContractRegistration.Category); - return Task.CompletedTask; - } + /// + public Task DeployContractAsync(ContractDto contractDto) + { + CheckRunner(contractDto.SmartContractRegistration.Category); + return Task.CompletedTask; + } - public Task UpdateContractAsync(ContractDto contractDto) - { - return Task.CompletedTask; - } + public Task UpdateContractAsync(ContractDto contractDto) + { + return Task.CompletedTask; + } - private void CheckRunner(int category) - { - _smartContractRunnerContainer.GetRunner(category); - } + private void CheckRunner(int category) + { + _smartContractRunnerContainer.GetRunner(category); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/StateCacheFromPartialBlockStateSet.cs b/src/AElf.Kernel.SmartContract/Application/StateCacheFromPartialBlockStateSet.cs index 6c99616c78..2202e01cb3 100644 --- a/src/AElf.Kernel.SmartContract/Application/StateCacheFromPartialBlockStateSet.cs +++ b/src/AElf.Kernel.SmartContract/Application/StateCacheFromPartialBlockStateSet.cs @@ -1,37 +1,37 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class StateCacheFromPartialBlockStateSet : IStateCache { - public class StateCacheFromPartialBlockStateSet : IStateCache + private readonly BlockStateSet _blockStateSet; + + public StateCacheFromPartialBlockStateSet(BlockStateSet blockStateSet) { - private readonly BlockStateSet _blockStateSet; + _blockStateSet = blockStateSet; + } - public StateCacheFromPartialBlockStateSet(BlockStateSet blockStateSet) + public bool TryGetValue(ScopedStatePath key, out byte[] value) + { + var stateKey = key.ToStateKey(); + var found = _blockStateSet.Deletes.Contains(stateKey); + if (found) { - _blockStateSet = blockStateSet; + value = null; + return true; } - public bool TryGetValue(ScopedStatePath key, out byte[] value) - { - var stateKey = key.ToStateKey(); - var found = _blockStateSet.Deletes.Contains(stateKey); - if (found) - { - value = null; - return true; - } - found = _blockStateSet.Changes.TryGetValue(stateKey, out var bs); - value = found ? bs.ToByteArray() : null; - return found; - } + found = _blockStateSet.Changes.TryGetValue(stateKey, out var bs); + value = found ? bs.ToByteArray() : null; + return found; + } - public byte[] this[ScopedStatePath key] + public byte[] this[ScopedStatePath key] + { + get => TryGetValue(key, out var value) ? value : null; + set { - get => TryGetValue(key, out var value) ? value : null; - set - { - //do nothing - } + //do nothing } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/TransactionExecutingDto.cs b/src/AElf.Kernel.SmartContract/Application/TransactionExecutingDto.cs index b7d97a03e1..4f8938f9b4 100644 --- a/src/AElf.Kernel.SmartContract/Application/TransactionExecutingDto.cs +++ b/src/AElf.Kernel.SmartContract/Application/TransactionExecutingDto.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class TransactionExecutingDto { - public class TransactionExecutingDto - { - public BlockHeader BlockHeader { get; set; } - public IEnumerable Transactions { get; set; } - public BlockStateSet PartialBlockStateSet { get; set; } - } + public BlockHeader BlockHeader { get; set; } + public IEnumerable Transactions { get; set; } + public BlockStateSet PartialBlockStateSet { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionService.cs b/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionService.cs index b681220ad7..350b0d586c 100644 --- a/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionService.cs +++ b/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionService.cs @@ -1,124 +1,112 @@ using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class TransactionReadOnlyExecutionService : ITransactionReadOnlyExecutionService { - public class TransactionReadOnlyExecutionService : ITransactionReadOnlyExecutionService + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ITransactionContextFactory _transactionContextFactory; + + public TransactionReadOnlyExecutionService(ISmartContractExecutiveService smartContractExecutiveService, + ITransactionContextFactory transactionContextFactory) { - private readonly ISmartContractExecutiveService _smartContractExecutiveService; - private readonly ITransactionContextFactory _transactionContextFactory; + _smartContractExecutiveService = smartContractExecutiveService; + _transactionContextFactory = transactionContextFactory; + } - public TransactionReadOnlyExecutionService(ISmartContractExecutiveService smartContractExecutiveService, - ITransactionContextFactory transactionContextFactory) + public async Task ExecuteAsync(IChainContext chainContext, Transaction transaction, + Timestamp currentBlockTime) + { + var transactionContext = _transactionContextFactory.Create(transaction, chainContext, currentBlockTime); + var executive = await _smartContractExecutiveService.GetExecutiveAsync( + chainContext, transaction.To); + + try { - _smartContractExecutiveService = smartContractExecutiveService; - _transactionContextFactory = transactionContextFactory; + await executive.ApplyAsync(transactionContext); } - - public async Task ExecuteAsync(IChainContext chainContext, Transaction transaction, - Timestamp currentBlockTime) + finally { - var transactionContext = _transactionContextFactory.Create(transaction, chainContext, currentBlockTime); - var executive = await _smartContractExecutiveService.GetExecutiveAsync( - chainContext, transaction.To); + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, transaction.To, executive); + } - try - { - await executive.ApplyAsync(transactionContext); - } - finally - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, transaction.To, executive); - } + return transactionContext.Trace; + } - return transactionContext.Trace; - } + public async Task GetFileDescriptorSetAsync(IChainContext chainContext, Address address) + { + IExecutive executive = null; - public async Task GetFileDescriptorSetAsync(IChainContext chainContext, Address address) + byte[] output; + try { - IExecutive executive = null; + executive = await _smartContractExecutiveService.GetExecutiveAsync( + chainContext, address); + output = executive.GetFileDescriptorSet(); + } + finally + { + if (executive != null) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + } - byte[] output; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync( - chainContext, address); - output = executive.GetFileDescriptorSet(); - } - finally - { - if (executive != null) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - } + return output; + } - return output; - } + public async Task> GetFileDescriptorsAsync(IChainContext chainContext, Address address) + { + IExecutive executive = null; - public async Task> GetFileDescriptorsAsync(IChainContext chainContext, Address address) + IEnumerable output; + try + { + executive = await _smartContractExecutiveService.GetExecutiveAsync( + chainContext, address); + output = executive.GetFileDescriptors(); + } + finally { - IExecutive executive = null; + if (executive != null) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + } - IEnumerable output; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync( - chainContext, address); - output = executive.GetFileDescriptors(); - } - finally - { - if (executive != null) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - } + return output; + } - return output; + public async Task GetTransactionParametersAsync(IChainContext chainContext, Transaction transaction) + { + var address = transaction.To; + IExecutive executive = null; + try + { + executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); + return executive.GetJsonStringOfParameters(transaction.MethodName, transaction.Params.ToByteArray()); } - - public async Task GetTransactionParametersAsync(IChainContext chainContext, Transaction transaction) + finally { - var address = transaction.To; - IExecutive executive = null; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); - return executive.GetJsonStringOfParameters(transaction.MethodName, transaction.Params.ToByteArray()); - } - finally - { - if (executive != null) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - } + if (executive != null) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); } + } - public async Task IsViewTransactionAsync(IChainContext chainContext, Transaction transaction) + public async Task IsViewTransactionAsync(IChainContext chainContext, Transaction transaction) + { + var address = transaction.To; + IExecutive executive = null; + try + { + executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); + return executive.IsView(transaction.MethodName); + } + finally { - var address = transaction.To; - IExecutive executive = null; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); - return executive.IsView(transaction.MethodName); - } - finally - { - if (executive != null) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - } + if (executive != null) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionServiceExtensions.cs b/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionServiceExtensions.cs index d377aa5ac9..738e2751c6 100644 --- a/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionServiceExtensions.cs +++ b/src/AElf.Kernel.SmartContract/Application/TransactionReadOnlyExecutionServiceExtensions.cs @@ -3,29 +3,25 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public static class TransactionReadOnlyExecutionServiceExtensions { - public static class TransactionReadOnlyExecutionServiceExtensions + public static async Task ExecuteAsync( + this ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + IChainContext chainContext, Transaction transaction, + Timestamp currentBlockTime, bool failedThrowException) where T : class, IMessage, new() { - public static async Task ExecuteAsync( - this ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - IChainContext chainContext, Transaction transaction, - Timestamp currentBlockTime, bool failedThrowException) where T : class, IMessage, new() + var trace = await transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, currentBlockTime); + if (trace.IsSuccessful()) { - var trace = await transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, currentBlockTime); - if (trace.IsSuccessful()) - { - var obj = new T(); - obj.MergeFrom(trace.ReturnValue); - return obj; - } + var obj = new T(); + obj.MergeFrom(trace.ReturnValue); + return obj; + } - if (failedThrowException) - { - throw new SmartContractExecutingException(trace.Error); - } + if (failedThrowException) throw new SmartContractExecutingException(trace.Error); - return default(T); - } + return default; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/AssemblyInfo.cs b/src/AElf.Kernel.SmartContract/AssemblyInfo.cs index 671c417116..76fe6bfe92 100644 --- a/src/AElf.Kernel.SmartContract/AssemblyInfo.cs +++ b/src/AElf.Kernel.SmartContract/AssemblyInfo.cs @@ -1,3 +1,3 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("AElf.Kernel.SmartContract.Tests")] +[assembly: InternalsVisibleTo("AElf.Kernel.SmartContract.Tests")] \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/CachedStateProvider.cs b/src/AElf.Kernel.SmartContract/CachedStateProvider.cs index d3f35a0cfa..93025a24a3 100644 --- a/src/AElf.Kernel.SmartContract/CachedStateProvider.cs +++ b/src/AElf.Kernel.SmartContract/CachedStateProvider.cs @@ -1,57 +1,51 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class CachedStateProvider : IScopedStateProvider { - public class CachedStateProvider : IScopedStateProvider + private readonly IScopedStateProvider _inner; + + public CachedStateProvider(IScopedStateProvider inner) { - public Address ContractAddress => _inner.ContractAddress; + _inner = inner; + } - private readonly IScopedStateProvider _inner; + public Address ContractAddress => _inner.ContractAddress; - public CachedStateProvider(IScopedStateProvider inner) + public IStateCache Cache { get; set; } = new InMemoryStateCache(); + + public byte[] Get(StatePath path) + { + var scoped = new ScopedStatePath { - _inner = inner; - } + Address = ContractAddress, + Path = path + }; - public IStateCache Cache { get; set; } = new InMemoryStateCache(); + if (Cache.TryGetValue(scoped, out var value)) return value; - public byte[] Get(StatePath path) - { - var scoped = new ScopedStatePath() - { - Address = ContractAddress, - Path = path - }; + var bytes = _inner.Get(path); - if (Cache.TryGetValue(scoped, out var value)) - { - return value; - } + Cache[scoped] = bytes; - var bytes = _inner.Get(path); + return bytes; + } - Cache[scoped] = bytes; + private class InMemoryStateCache : IStateCache + { + private readonly Dictionary _data = new(); - return bytes; + public bool TryGetValue(ScopedStatePath key, out byte[] value) + { + return _data.TryGetValue(key, out value); } - private class InMemoryStateCache : IStateCache + public byte[] this[ScopedStatePath key] { - private readonly Dictionary _data = - new Dictionary(); - - public bool TryGetValue(ScopedStatePath key, out byte[] value) - { - return _data.TryGetValue(key, out value); - } - - public byte[] this[ScopedStatePath key] - { - get => TryGetValue(key, out var value) ? value : null; - set => _data[key] = value; - } + get => TryGetValue(key, out var value) ? value : null; + set => _data[key] = value; } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ContractOptions.cs b/src/AElf.Kernel.SmartContract/ContractOptions.cs index 628ff7ece1..fd59240ab2 100644 --- a/src/AElf.Kernel.SmartContract/ContractOptions.cs +++ b/src/AElf.Kernel.SmartContract/ContractOptions.cs @@ -1,8 +1,7 @@ -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class ContractOptions { - public class ContractOptions - { - public bool ContractDeploymentAuthorityRequired { get; set; } = true; - public string GenesisContractDir { get; set; } - } + public bool ContractDeploymentAuthorityRequired { get; set; } = true; + public string GenesisContractDir { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Domain/BlockStateSetExtensions.cs b/src/AElf.Kernel.SmartContract/Domain/BlockStateSetExtensions.cs index bc5cf36e0e..0d74853948 100644 --- a/src/AElf.Kernel.SmartContract/Domain/BlockStateSetExtensions.cs +++ b/src/AElf.Kernel.SmartContract/Domain/BlockStateSetExtensions.cs @@ -1,17 +1,16 @@ using AElf.Kernel.SmartContract.Application; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public static class BlockStateSetExtensions { - public static class BlockStateSetExtensions + public static TieredStateCache ToTieredStateCache(this BlockStateSet blockStateSet) { - public static TieredStateCache ToTieredStateCache(this BlockStateSet blockStateSet) - { - var groupStateCache = blockStateSet == null - ? new TieredStateCache() - : new TieredStateCache( - new StateCacheFromPartialBlockStateSet(blockStateSet)); + var groupStateCache = blockStateSet == null + ? new TieredStateCache() + : new TieredStateCache( + new StateCacheFromPartialBlockStateSet(blockStateSet)); - return groupStateCache; - } + return groupStateCache; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Domain/ExecutionReturnSetCollection.cs b/src/AElf.Kernel.SmartContract/Domain/ExecutionReturnSetCollection.cs index 66ba0cd652..faa2755cd4 100644 --- a/src/AElf.Kernel.SmartContract/Domain/ExecutionReturnSetCollection.cs +++ b/src/AElf.Kernel.SmartContract/Domain/ExecutionReturnSetCollection.cs @@ -2,63 +2,52 @@ using System.Linq; using AElf.Types; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public class ExecutionReturnSetCollection { - public class ExecutionReturnSetCollection + public ExecutionReturnSetCollection(IEnumerable returnSets) { - private List _executed = new List(); - private List _conflict = new List(); + AddRange(returnSets); + } - public List Executed => _executed; + public List Executed { get; } = new(); - public List Conflict => _conflict; + public List Conflict { get; } = new(); - public ExecutionReturnSetCollection(IEnumerable returnSets) - { - AddRange(returnSets); - } + public void AddRange(IEnumerable returnSets) + { + foreach (var returnSet in returnSets) + if (returnSet.Status == TransactionResultStatus.Mined || + returnSet.Status == TransactionResultStatus.Failed) + Executed.Add(returnSet); + else if (returnSet.Status == TransactionResultStatus.Conflict) Conflict.Add(returnSet); + } - public void AddRange(IEnumerable returnSets) + public BlockStateSet ToBlockStateSet() + { + var blockStateSet = new BlockStateSet(); + foreach (var returnSet in Executed) { - foreach (var returnSet in returnSets) + foreach (var change in returnSet.StateChanges) { - if (returnSet.Status == TransactionResultStatus.Mined || - returnSet.Status == TransactionResultStatus.Failed) - { - _executed.Add(returnSet); - } - else if (returnSet.Status == TransactionResultStatus.Conflict) - { - _conflict.Add(returnSet); - } + blockStateSet.Changes[change.Key] = change.Value; + blockStateSet.Deletes.Remove(change.Key); } - } - public BlockStateSet ToBlockStateSet() - { - var blockStateSet = new BlockStateSet(); - foreach (var returnSet in _executed) + foreach (var delete in returnSet.StateDeletes) { - foreach (var change in returnSet.StateChanges) - { - blockStateSet.Changes[change.Key] = change.Value; - blockStateSet.Deletes.Remove(change.Key); - } - - foreach (var delete in returnSet.StateDeletes) - { - blockStateSet.Deletes.AddIfNotContains(delete.Key); - blockStateSet.Changes.Remove(delete.Key); - } + blockStateSet.Deletes.AddIfNotContains(delete.Key); + blockStateSet.Changes.Remove(delete.Key); } - - return blockStateSet; } - public List GetExecutionReturnSetList() - { - return _executed.Concat(_conflict).ToList(); - } + return blockStateSet; + } + + public List GetExecutionReturnSetList() + { + return Executed.Concat(Conflict).ToList(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Domain/TieredStateCache.cs b/src/AElf.Kernel.SmartContract/Domain/TieredStateCache.cs index 3462cc309d..549789d3dc 100644 --- a/src/AElf.Kernel.SmartContract/Domain/TieredStateCache.cs +++ b/src/AElf.Kernel.SmartContract/Domain/TieredStateCache.cs @@ -1,83 +1,67 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public class TieredStateCache : IStateCache { - public class TieredStateCache : IStateCache - { - private IStateCache _parent = new NullStateCache(); - private Dictionary _originalValues = new Dictionary(); - private Dictionary _currentValues = new Dictionary(); + private readonly Dictionary _currentValues = new(); + private readonly Dictionary _originalValues = new(); + private readonly IStateCache _parent = new NullStateCache(); - public TieredStateCache() : this(new NullStateCache()) - { - } + public TieredStateCache() : this(new NullStateCache()) + { + } - public TieredStateCache(IStateCache parent) - { - if (parent != null) - { - _parent = parent; - } - } + public TieredStateCache(IStateCache parent) + { + if (parent != null) _parent = parent; + } - public bool TryGetValue(ScopedStatePath key, out byte[] value) - { - var originalFound = TryGetOriginalValue(key, out value); + public bool TryGetValue(ScopedStatePath key, out byte[] value) + { + var originalFound = TryGetOriginalValue(key, out value); - var currentFound = _currentValues.TryGetValue(key.ToStateKey(), out var currentValue); - if (currentFound) - { - value = currentValue; - } + var currentFound = _currentValues.TryGetValue(key.ToStateKey(), out var currentValue); + if (currentFound) value = currentValue; - return originalFound || currentFound; - } + return originalFound || currentFound; + } - public byte[] this[ScopedStatePath key] + public byte[] this[ScopedStatePath key] + { + get => TryGetValue(key, out var value) ? value : null; + set { - get => TryGetValue(key, out var value) ? value : null; - set - { - // The setter is only used in StateProvider, changes have to be updated after execution - // by calling Update - _originalValues[key] = value; - _parent[key] = value; - } + // The setter is only used in StateProvider, changes have to be updated after execution + // by calling Update + _originalValues[key] = value; + _parent[key] = value; } + } - public void Update(IEnumerable stateSets) + public void Update(IEnumerable stateSets) + { + foreach (var stateSet in stateSets) { - foreach (var stateSet in stateSets) - { - var changes = stateSet.Writes; - foreach (var change in changes) - { - _currentValues[change.Key] = change.Value.ToByteArray(); - } + var changes = stateSet.Writes; + foreach (var change in changes) _currentValues[change.Key] = change.Value.ToByteArray(); - var deletes = stateSet.Deletes; - foreach (var delete in deletes) - { - _currentValues[delete.Key] = null; - } - } + var deletes = stateSet.Deletes; + foreach (var delete in deletes) _currentValues[delete.Key] = null; } + } - private bool TryGetOriginalValue(ScopedStatePath path, out byte[] value) - { - if (_originalValues.TryGetValue(path, out value)) - { - return true; - } - - if (_parent.TryGetValue(path, out value)) - { - _originalValues[path] = value; - return true; - } + private bool TryGetOriginalValue(ScopedStatePath path, out byte[] value) + { + if (_originalValues.TryGetValue(path, out value)) return true; - return false; + if (_parent.TryGetValue(path, out value)) + { + _originalValues[path] = value; + return true; } + + return false; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Dto/ContractDto.cs b/src/AElf.Kernel.SmartContract/Dto/ContractDto.cs index e5a4cfa0d8..1b3b8efc1e 100644 --- a/src/AElf.Kernel.SmartContract/Dto/ContractDto.cs +++ b/src/AElf.Kernel.SmartContract/Dto/ContractDto.cs @@ -1,17 +1,16 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class ContractDto { - public class ContractDto - { - public Address ContractAddress { get; set; } + public Address ContractAddress { get; set; } + + public SmartContractRegistration SmartContractRegistration { get; set; } - public SmartContractRegistration SmartContractRegistration { get; set; } - - public long BlockHeight { get; set; } + public long BlockHeight { get; set; } - public bool IsPrivileged { get; set; } + public bool IsPrivileged { get; set; } - public Hash ContractName { get; set; } = null; - } + public Hash ContractName { get; set; } = null; } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Dto/SingleTransactionExecutingDto.cs b/src/AElf.Kernel.SmartContract/Dto/SingleTransactionExecutingDto.cs index 1c3dee75cc..7dfe93020b 100644 --- a/src/AElf.Kernel.SmartContract/Dto/SingleTransactionExecutingDto.cs +++ b/src/AElf.Kernel.SmartContract/Dto/SingleTransactionExecutingDto.cs @@ -1,17 +1,16 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class SingleTransactionExecutingDto { - public class SingleTransactionExecutingDto - { - public int Depth { get; set; } - public IChainContext ChainContext { get; set; } - public Transaction Transaction { get; set; } - public Timestamp CurrentBlockTime { get; set; } - public Address Origin { get; set; } = null; - public bool IsCancellable { get; set; } = true; - - public Hash OriginTransactionId { get; set; } - } + public int Depth { get; set; } + public IChainContext ChainContext { get; set; } + public Transaction Transaction { get; set; } + public Timestamp CurrentBlockTime { get; set; } + public Address Origin { get; set; } = null; + public bool IsCancellable { get; set; } = true; + + public Hash OriginTransactionId { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Extensions/TaskExtensions.cs b/src/AElf.Kernel.SmartContract/Extensions/TaskExtensions.cs index 7b5ea7889a..616add4bfc 100644 --- a/src/AElf.Kernel.SmartContract/Extensions/TaskExtensions.cs +++ b/src/AElf.Kernel.SmartContract/Extensions/TaskExtensions.cs @@ -3,95 +3,91 @@ using System.Threading; using System.Threading.Tasks; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +//TODO: Move TaskExtensions to lower level. +public static class TaskExtensions { - //TODO: Move TaskExtensions to lower level. - public static class TaskExtensions + public static async Task WithCancellation(this Task originalTask, CancellationToken ct) { - private struct Void - { - } - - public static async Task WithCancellation(this Task originalTask, CancellationToken ct) + var cancelTask = new TaskCompletionSource(); + using (ct.Register(SetTaskResultCallback, cancelTask)) { - var cancelTask = new TaskCompletionSource(); - using (ct.Register(SetTaskResultCallback, cancelTask)) + await RunTaskWithCompletionSource(originalTask, new Dictionary { - await RunTaskWithCompletionSource(originalTask, new Dictionary - { - {ct, cancelTask.Task} - }); - } - - return await originalTask; + { ct, cancelTask.Task } + }); } - - public static async Task WithCancellation(this Task originalTask, CancellationToken ct1, CancellationToken ct2) - { - var cancelTask1 = new TaskCompletionSource(); - var cancelTask2 = new TaskCompletionSource(); - using (ct1.Register(SetTaskResultCallback, cancelTask1)) - using (ct2.Register(SetTaskResultCallback, cancelTask2)) - { - await RunTaskWithCompletionSource(originalTask, new Dictionary - { - {ct1, cancelTask1.Task}, - {ct2, cancelTask2.Task} - }); - } - return await originalTask; - } - - public static async Task WithCancellation(this Task originalTask, CancellationToken ct) - { - var cancelTask = new TaskCompletionSource(); - using (ct.Register(SetTaskResultCallback, cancelTask)) - { - await RunTaskWithCompletionSource(originalTask, new Dictionary - { - {ct, cancelTask.Task} - }); - } + return await originalTask; + } - await originalTask; - } - - - public static async Task WithCancellation(this Task originalTask, CancellationToken ct1, CancellationToken ct2) + public static async Task WithCancellation(this Task originalTask, CancellationToken ct1, + CancellationToken ct2) + { + var cancelTask1 = new TaskCompletionSource(); + var cancelTask2 = new TaskCompletionSource(); + using (ct1.Register(SetTaskResultCallback, cancelTask1)) + using (ct2.Register(SetTaskResultCallback, cancelTask2)) { - var cancelTask1 = new TaskCompletionSource(); - var cancelTask2 = new TaskCompletionSource(); - using (ct1.Register(SetTaskResultCallback, cancelTask1)) - using (ct2.Register(SetTaskResultCallback, cancelTask2)) + await RunTaskWithCompletionSource(originalTask, new Dictionary { - await RunTaskWithCompletionSource(originalTask, new Dictionary - { - {ct1, cancelTask1.Task}, - {ct2, cancelTask2.Task} - }); - } - - await originalTask; + { ct1, cancelTask1.Task }, + { ct2, cancelTask2.Task } + }); } - private static void SetTaskResultCallback(object obj) + return await originalTask; + } + + public static async Task WithCancellation(this Task originalTask, CancellationToken ct) + { + var cancelTask = new TaskCompletionSource(); + using (ct.Register(SetTaskResultCallback, cancelTask)) { - ((TaskCompletionSource) obj).TrySetResult(new Void()); + await RunTaskWithCompletionSource(originalTask, new Dictionary + { + { ct, cancelTask.Task } + }); } - private static async Task RunTaskWithCompletionSource(Task originalTask, - Dictionary completionSourceTokenTaskDict) - { - var any = await Task.WhenAny(completionSourceTokenTaskDict.Values.ToList().Append(originalTask)); + await originalTask; + } - foreach (var completionSourceTokenTask in completionSourceTokenTaskDict) + + public static async Task WithCancellation(this Task originalTask, CancellationToken ct1, CancellationToken ct2) + { + var cancelTask1 = new TaskCompletionSource(); + var cancelTask2 = new TaskCompletionSource(); + using (ct1.Register(SetTaskResultCallback, cancelTask1)) + using (ct2.Register(SetTaskResultCallback, cancelTask2)) + { + await RunTaskWithCompletionSource(originalTask, new Dictionary { - if (any == completionSourceTokenTask.Value) - { - completionSourceTokenTask.Key.ThrowIfCancellationRequested(); - } - } + { ct1, cancelTask1.Task }, + { ct2, cancelTask2.Task } + }); } + + await originalTask; + } + + private static void SetTaskResultCallback(object obj) + { + ((TaskCompletionSource)obj).TrySetResult(new Void()); + } + + private static async Task RunTaskWithCompletionSource(Task originalTask, + Dictionary completionSourceTokenTaskDict) + { + var any = await Task.WhenAny(completionSourceTokenTaskDict.Values.ToList().Append(originalTask)); + + foreach (var completionSourceTokenTask in completionSourceTokenTaskDict) + if (any == completionSourceTokenTask.Value) + completionSourceTokenTask.Key.ThrowIfCancellationRequested(); + } + + private struct Void + { } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index 7cd55c05e6..77c3eeead4 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -8,7 +8,6 @@ using AElf.CSharp.Core; using AElf.Kernel.Account.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -16,316 +15,310 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class HostSmartContractBridgeContextOptions { - public class HostSmartContractBridgeContextOptions - { - public Dictionary ContextVariables { get; set; } = new Dictionary(); - } + public Dictionary ContextVariables { get; set; } = new(); +} - public class HostSmartContractBridgeContext : IHostSmartContractBridgeContext, ITransientDependency - { - private readonly ISmartContractBridgeService _smartContractBridgeService; - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private readonly IAccountService _accountService; +public class HostSmartContractBridgeContext : IHostSmartContractBridgeContext, ITransientDependency +{ + private readonly IAccountService _accountService; - public HostSmartContractBridgeContext(ISmartContractBridgeService smartContractBridgeService, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, IAccountService accountService, - IOptionsSnapshot options) - { - _smartContractBridgeService = smartContractBridgeService; - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - _accountService = accountService; - - Variables = new ContextVariableDictionary(options.Value.ContextVariables); - - var self = this; - Address GetAddress() => self.Transaction.To; - _lazyStateProvider = new Lazy( - () => new CachedStateProvider( - new ScopedStateProvider() - { - ContractAddress = GetAddress(), - HostSmartContractBridgeContext = this - }), - LazyThreadSafetyMode.PublicationOnly); - } + private readonly Lazy _lazyStateProvider; + private readonly ISmartContractBridgeService _smartContractBridgeService; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private ITransactionContext _transactionContext; + private ITransactionContext _transactionContext; - public ITransactionContext TransactionContext - { - get => _transactionContext; - set - { - _transactionContext = value; - CachedStateProvider.Cache = _transactionContext?.StateCache ?? new NullStateCache(); - } - } + public HostSmartContractBridgeContext(ISmartContractBridgeService smartContractBridgeService, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, IAccountService accountService, + IOptionsSnapshot options) + { + _smartContractBridgeService = smartContractBridgeService; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + _accountService = accountService; - private readonly Lazy _lazyStateProvider; - private ICachedStateProvider CachedStateProvider => _lazyStateProvider.Value; + Variables = new ContextVariableDictionary(options.Value.ContextVariables); - public IStateProvider StateProvider => _lazyStateProvider.Value; + var self = this; - public Address GetContractAddressByName(string hash) + Address GetAddress() { - var chainContext = new ChainContext - { - BlockHash = TransactionContext.PreviousBlockHash, - BlockHeight = TransactionContext.BlockHeight - 1, - StateCache = CachedStateProvider.Cache - }; - return AsyncHelper.RunSync(() => - _smartContractBridgeService.GetAddressByContractNameAsync(chainContext, hash)); + return self.Transaction.To; } - public IReadOnlyDictionary GetSystemContractNameToAddressMapping() - { - var chainContext = new ChainContext - { - BlockHash = TransactionContext.PreviousBlockHash, - BlockHeight = TransactionContext.BlockHeight - 1, - StateCache = CachedStateProvider.Cache - }; - return AsyncHelper.RunSync(() => - _smartContractBridgeService.GetSystemContractNameToAddressMappingAsync(chainContext)); - } + _lazyStateProvider = new Lazy( + () => new CachedStateProvider( + new ScopedStateProvider + { + ContractAddress = GetAddress(), + HostSmartContractBridgeContext = this + }), + LazyThreadSafetyMode.PublicationOnly); + } - public void Initialize(ITransactionContext transactionContext) - { - TransactionContext = transactionContext; - } + private ICachedStateProvider CachedStateProvider => _lazyStateProvider.Value; + + public Transaction Transaction => TransactionContext.Transaction.Clone(); - public async Task GetStateAsync(string key) + public ITransactionContext TransactionContext + { + get => _transactionContext; + set { - return await _smartContractBridgeService.GetStateAsync( - Self, key, CurrentHeight - 1, PreviousBlockHash); + _transactionContext = value; + CachedStateProvider.Cache = _transactionContext?.StateCache ?? new NullStateCache(); } + } - public int ChainId => _smartContractBridgeService.GetChainId(); - public ContextVariableDictionary Variables { get; } + public IStateProvider StateProvider => _lazyStateProvider.Value; - public void LogDebug(Func func) + public Address GetContractAddressByName(string hash) + { + var chainContext = new ChainContext { -#if DEBUG - _smartContractBridgeService.LogDebug(() => - $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}"); -#endif - } + BlockHash = TransactionContext.PreviousBlockHash, + BlockHeight = TransactionContext.BlockHeight - 1, + StateCache = CachedStateProvider.Cache + }; + return AsyncHelper.RunSync(() => + _smartContractBridgeService.GetAddressByContractNameAsync(chainContext, hash)); + } - public void FireLogEvent(LogEvent logEvent) + public IReadOnlyDictionary GetSystemContractNameToAddressMapping() + { + var chainContext = new ChainContext { - TransactionContext.Trace.Logs.Add(logEvent); - } + BlockHash = TransactionContext.PreviousBlockHash, + BlockHeight = TransactionContext.BlockHeight - 1, + StateCache = CachedStateProvider.Cache + }; + return AsyncHelper.RunSync(() => + _smartContractBridgeService.GetSystemContractNameToAddressMappingAsync(chainContext)); + } - public Hash GenerateId(Address contractAddress, IEnumerable bytes) - { - var contactedBytes = OriginTransactionId.Value.Concat(contractAddress.Value); - var enumerable = bytes as byte[] ?? bytes?.ToArray(); - if (enumerable != null) - contactedBytes = contactedBytes.Concat(enumerable); - return HashHelper.ComputeFrom(contactedBytes.ToArray()); - } + public void Initialize(ITransactionContext transactionContext) + { + TransactionContext = transactionContext; + } - public object ValidateStateSize(object obj) - { - var stateSizeLimit = AsyncHelper.RunSync(() => _smartContractBridgeService.GetStateSizeLimitAsync( - new ChainContext - { - BlockHash = _transactionContext.PreviousBlockHash, - BlockHeight = _transactionContext.BlockHeight - 1 - })); - var size = SerializationHelper.Serialize(obj).Length; - if (size > stateSizeLimit) - throw new StateOverSizeException($"State size {size} exceeds limit of {stateSizeLimit}."); - return obj; - } + public async Task GetStateAsync(string key) + { + return await _smartContractBridgeService.GetStateAsync( + Self, key, CurrentHeight - 1, PreviousBlockHash); + } - public Hash GetRandomHash(Hash fromHash) - { - var currentBlockTimeHash = HashHelper.ComputeFrom(CurrentBlockTime); - return HashHelper.XorAndCompute(TransactionId, HashHelper.XorAndCompute(currentBlockTimeHash, - HashHelper.XorAndCompute(fromHash, PreviousBlockHash))); - } + public int ChainId => _smartContractBridgeService.GetChainId(); + public ContextVariableDictionary Variables { get; } - public long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue) - { - if (start < 0 || start > end) - { - throw new ArgumentException("Incorrect arguments."); - } - - var range = end.Sub(start); - var bigInteger = new BigInteger(hash.Value.ToByteArray()); - // This is safe because range is long type. - var index = Math.Abs((long) (bigInteger % range)); - return index.Add(start); - } + public void LogDebug(Func func) + { +#if DEBUG + _smartContractBridgeService.LogDebug(() => + $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}"); +#endif + } - public Transaction Transaction => TransactionContext.Transaction.Clone(); - public Hash TransactionId => TransactionContext.Transaction.GetHash(); - public Address Sender => TransactionContext.Transaction.From.Clone(); - public Address Self => TransactionContext.Transaction.To.Clone(); - public Address Origin => TransactionContext.Origin.Clone(); - public Hash OriginTransactionId => TransactionContext.OriginTransactionId; - public long CurrentHeight => TransactionContext.BlockHeight; - public Timestamp CurrentBlockTime => TransactionContext.CurrentBlockTime; - public Hash PreviousBlockHash => TransactionContext.PreviousBlockHash.Clone(); - - private byte[] RecoverPublicKey(byte[] signature, byte[] hash) - { - var cabBeRecovered = CryptoHelper.RecoverPublicKey(signature, hash, out var publicKey); - return !cabBeRecovered ? null : publicKey; - } + public void FireLogEvent(LogEvent logEvent) + { + TransactionContext.Trace.Logs.Add(logEvent); + } - /// - /// Recovers the first public key signing this transaction. - /// - /// Public key byte array - public byte[] RecoverPublicKey() - { - return RecoverPublicKey(TransactionContext.Transaction.Signature.ToByteArray(), - TransactionContext.Transaction.GetHash().ToByteArray()); - } + public Hash GenerateId(Address contractAddress, IEnumerable bytes) + { + var contactedBytes = OriginTransactionId.Value.Concat(contractAddress.Value); + var enumerable = bytes as byte[] ?? bytes?.ToArray(); + if (enumerable != null) + contactedBytes = contactedBytes.Concat(enumerable); + return HashHelper.ComputeFrom(contactedBytes.ToArray()); + } - public T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) - where T : IMessage, new() - { - TransactionTrace trace = AsyncHelper.RunSync(async () => + public object ValidateStateSize(object obj) + { + var stateSizeLimit = AsyncHelper.RunSync(() => _smartContractBridgeService.GetStateSizeLimitAsync( + new ChainContext { - var chainContext = new ChainContext() - { - BlockHash = this.TransactionContext.PreviousBlockHash, - BlockHeight = this.TransactionContext.BlockHeight - 1, - StateCache = CachedStateProvider.Cache - }; + BlockHash = _transactionContext.PreviousBlockHash, + BlockHeight = _transactionContext.BlockHeight - 1 + })); + var size = SerializationHelper.Serialize(obj).Length; + if (size > stateSizeLimit) + throw new StateOverSizeException($"State size {size} exceeds limit of {stateSizeLimit}."); + return obj; + } - var tx = new Transaction() - { - From = fromAddress, - To = toAddress, - MethodName = methodName, - Params = args - }; - return await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, tx, CurrentBlockTime); - }); - - if (!trace.IsSuccessful()) - { - throw new ContractCallException(trace.Error); - } + public Hash GetRandomHash(Hash fromHash) + { + var currentBlockTimeHash = HashHelper.ComputeFrom(CurrentBlockTime); + return HashHelper.XorAndCompute(TransactionId, HashHelper.XorAndCompute(currentBlockTimeHash, + HashHelper.XorAndCompute(fromHash, PreviousBlockHash))); + } - var obj = new T(); - obj.MergeFrom(trace.ReturnValue); - return obj; - } + public long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue) + { + if (start < 0 || start > end) throw new ArgumentException("Incorrect arguments."); - public void SendInline(Address toAddress, string methodName, ByteString args) - { - TransactionContext.Trace.InlineTransactions.Add(new Transaction() - { - From = Self, - To = toAddress, - MethodName = methodName, - Params = args - }); - } + var range = end.Sub(start); + var bigInteger = new BigInteger(hash.Value.ToByteArray()); + // This is safe because range is long type. + var index = Math.Abs((long)(bigInteger % range)); + return index.Add(start); + } - public void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, - ByteString args) + public Hash TransactionId => TransactionContext.Transaction.GetHash(); + public Address Sender => TransactionContext.Transaction.From.Clone(); + public Address Self => TransactionContext.Transaction.To.Clone(); + public Address Origin => TransactionContext.Origin.Clone(); + public Hash OriginTransactionId => TransactionContext.OriginTransactionId; + public long CurrentHeight => TransactionContext.BlockHeight; + public Timestamp CurrentBlockTime => TransactionContext.CurrentBlockTime; + public Hash PreviousBlockHash => TransactionContext.PreviousBlockHash.Clone(); + + /// + /// Recovers the first public key signing this transaction. + /// + /// Public key byte array + public byte[] RecoverPublicKey() + { + return RecoverPublicKey(TransactionContext.Transaction.Signature.ToByteArray(), + TransactionContext.Transaction.GetHash().ToByteArray()); + } + + public T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) + where T : IMessage, new() + { + var trace = AsyncHelper.RunSync(async () => { - TransactionContext.Trace.InlineTransactions.Add(new Transaction() + var chainContext = new ChainContext { - From = ConvertVirtualAddressToContractAddress(fromVirtualAddress, Self), - To = toAddress, - MethodName = methodName, - Params = args - }); - } + BlockHash = TransactionContext.PreviousBlockHash, + BlockHeight = TransactionContext.BlockHeight - 1, + StateCache = CachedStateProvider.Cache + }; - public void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, - ByteString args) - { - TransactionContext.Trace.InlineTransactions.Add(new Transaction + var tx = new Transaction { - From = ConvertVirtualAddressToContractAddressWithContractHashName(fromVirtualAddress, Self), + From = fromAddress, To = toAddress, MethodName = methodName, Params = args - }); - } + }; + return await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, tx, CurrentBlockTime); + }); - public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress) - { - return Address.FromPublicKey(contractAddress.Value.Concat( - virtualAddress.Value.ToByteArray().ComputeHash()).ToArray()); - } + if (!trace.IsSuccessful()) throw new ContractCallException(trace.Error); - public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, - Address contractAddress) - { - var systemHashName = GetSystemContractNameToAddressMapping().First(kv => kv.Value == contractAddress).Key; - return Address.FromPublicKey(systemHashName.Value.Concat(virtualAddress.Value.ToByteArray().ComputeHash()) - .ToArray()); - } + var obj = new T(); + obj.MergeFrom(trace.ReturnValue); + return obj; + } - public Address GetZeroSmartContractAddress() + public void SendInline(Address toAddress, string methodName, ByteString args) + { + TransactionContext.Trace.InlineTransactions.Add(new Transaction { - return _smartContractBridgeService.GetZeroSmartContractAddress(); - } + From = Self, + To = toAddress, + MethodName = methodName, + Params = args + }); + } - public Address GetZeroSmartContractAddress(int chainId) + public void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, + ByteString args) + { + TransactionContext.Trace.InlineTransactions.Add(new Transaction { - return _smartContractBridgeService.GetZeroSmartContractAddress(chainId); - } + From = ConvertVirtualAddressToContractAddress(fromVirtualAddress, Self), + To = toAddress, + MethodName = methodName, + Params = args + }); + } - public List GetPreviousBlockTransactions() + public void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, + ByteString args) + { + TransactionContext.Trace.InlineTransactions.Add(new Transaction { - return AsyncHelper.RunSync(() => _smartContractBridgeService.GetBlockTransactions( - TransactionContext.PreviousBlockHash)); - } + From = ConvertVirtualAddressToContractAddressWithContractHashName(fromVirtualAddress, Self), + To = toAddress, + MethodName = methodName, + Params = args + }); + } - public bool VerifySignature(Transaction tx) - { - return tx.VerifySignature(); - } + public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress) + { + return Address.FromPublicKey(contractAddress.Value.Concat( + virtualAddress.Value.ToByteArray().ComputeHash()).ToArray()); + } - public void DeployContract(Address address, SmartContractRegistration registration, Hash name) - { - if (!Self.Equals(_smartContractBridgeService.GetZeroSmartContractAddress())) - { - throw new NoPermissionException(); - } + public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, + Address contractAddress) + { + var systemHashName = GetSystemContractNameToAddressMapping().First(kv => kv.Value == contractAddress).Key; + return Address.FromPublicKey(systemHashName.Value.Concat(virtualAddress.Value.ToByteArray().ComputeHash()) + .ToArray()); + } - var contractDto = new ContractDto - { - BlockHeight = CurrentHeight, - ContractAddress = address, - SmartContractRegistration = registration, - ContractName = name, - IsPrivileged = false - }; + public Address GetZeroSmartContractAddress() + { + return _smartContractBridgeService.GetZeroSmartContractAddress(); + } - AsyncHelper.RunSync(() => _smartContractBridgeService.DeployContractAsync(contractDto)); - } + public Address GetZeroSmartContractAddress(int chainId) + { + return _smartContractBridgeService.GetZeroSmartContractAddress(chainId); + } + + public List GetPreviousBlockTransactions() + { + return AsyncHelper.RunSync(() => _smartContractBridgeService.GetBlockTransactions( + TransactionContext.PreviousBlockHash)); + } + + public bool VerifySignature(Transaction tx) + { + return tx.VerifySignature(); + } - public void UpdateContract(Address address, SmartContractRegistration registration, Hash name) + public void DeployContract(Address address, SmartContractRegistration registration, Hash name) + { + if (!Self.Equals(_smartContractBridgeService.GetZeroSmartContractAddress())) throw new NoPermissionException(); + + var contractDto = new ContractDto { - if (!Self.Equals(_smartContractBridgeService.GetZeroSmartContractAddress())) - { - throw new NoPermissionException(); - } + BlockHeight = CurrentHeight, + ContractAddress = address, + SmartContractRegistration = registration, + ContractName = name, + IsPrivileged = false + }; + + AsyncHelper.RunSync(() => _smartContractBridgeService.DeployContractAsync(contractDto)); + } - var contractDto = new ContractDto - { - BlockHeight = CurrentHeight, - ContractAddress = address, - SmartContractRegistration = registration, - ContractName = null, - IsPrivileged = false - }; - AsyncHelper.RunSync(() => _smartContractBridgeService.UpdateContractAsync(contractDto)); - } + public void UpdateContract(Address address, SmartContractRegistration registration, Hash name) + { + if (!Self.Equals(_smartContractBridgeService.GetZeroSmartContractAddress())) throw new NoPermissionException(); + + var contractDto = new ContractDto + { + BlockHeight = CurrentHeight, + ContractAddress = address, + SmartContractRegistration = registration, + ContractName = null, + IsPrivileged = false + }; + AsyncHelper.RunSync(() => _smartContractBridgeService.UpdateContractAsync(contractDto)); + } + + private byte[] RecoverPublicKey(byte[] signature, byte[] hash) + { + var cabBeRecovered = CryptoHelper.RecoverPublicKey(signature, hash, out var publicKey); + return !cabBeRecovered ? null : publicKey; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ICachedStateProvider.cs b/src/AElf.Kernel.SmartContract/ICachedStateProvider.cs index ca287d7c71..cdf54df2a9 100644 --- a/src/AElf.Kernel.SmartContract/ICachedStateProvider.cs +++ b/src/AElf.Kernel.SmartContract/ICachedStateProvider.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface ICachedStateProvider : IStateProvider { - public interface ICachedStateProvider : IStateProvider - { - IStateCache Cache { get; set; } - } + IStateCache Cache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/IExecutionObserverThreshold.cs b/src/AElf.Kernel.SmartContract/IExecutionObserverThreshold.cs index 022d8f7c75..d1dc27f790 100644 --- a/src/AElf.Kernel.SmartContract/IExecutionObserverThreshold.cs +++ b/src/AElf.Kernel.SmartContract/IExecutionObserverThreshold.cs @@ -1,25 +1,24 @@ -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface IExecutionObserverThreshold +{ + int ExecutionCallThreshold { get; set; } + int ExecutionBranchThreshold { get; set; } +} + +public class ExecutionObserverThreshold : IExecutionObserverThreshold { - public interface IExecutionObserverThreshold + public int ExecutionCallThreshold { get; set; } + public int ExecutionBranchThreshold { get; set; } + + public override bool Equals(object o) { - int ExecutionCallThreshold { get; set; } - int ExecutionBranchThreshold { get; set; } + return Equals(o as ExecutionObserverThreshold); } - - public class ExecutionObserverThreshold : IExecutionObserverThreshold - { - public int ExecutionCallThreshold { get; set; } - public int ExecutionBranchThreshold { get; set; } - - public override bool Equals(object o) - { - return Equals(o as ExecutionObserverThreshold); - } - private bool Equals(ExecutionObserverThreshold executionObserverThreshold) - { - return executionObserverThreshold.ExecutionBranchThreshold == ExecutionBranchThreshold && - executionObserverThreshold.ExecutionCallThreshold == ExecutionCallThreshold; - } + private bool Equals(ExecutionObserverThreshold executionObserverThreshold) + { + return executionObserverThreshold.ExecutionBranchThreshold == ExecutionBranchThreshold && + executionObserverThreshold.ExecutionCallThreshold == ExecutionCallThreshold; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/IHostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/IHostSmartContractBridgeContext.cs index e86ba25e01..d163b01b2a 100644 --- a/src/AElf.Kernel.SmartContract/IHostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/IHostSmartContractBridgeContext.cs @@ -1,16 +1,13 @@ using System.Threading.Tasks; -using AElf.Kernel.SmartContract; -using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface IHostSmartContractBridgeContext : ISmartContractBridgeContext { - public interface IHostSmartContractBridgeContext : ISmartContractBridgeContext - { - ITransactionContext TransactionContext { get; set; } + ITransactionContext TransactionContext { get; set; } + + void Initialize(ITransactionContext transactionContext); - void Initialize(ITransactionContext transactionContext); - - Task GetStateAsync(string key); - } + Task GetStateAsync(string key); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/IScopedStateProvider.cs b/src/AElf.Kernel.SmartContract/IScopedStateProvider.cs index 4fcbff48fc..a04533a9ea 100644 --- a/src/AElf.Kernel.SmartContract/IScopedStateProvider.cs +++ b/src/AElf.Kernel.SmartContract/IScopedStateProvider.cs @@ -1,9 +1,8 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface IScopedStateProvider : ICachedStateProvider { - public interface IScopedStateProvider : ICachedStateProvider - { - Address ContractAddress { get; } - } + Address ContractAddress { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ISmartContractAddressNameProvider.cs b/src/AElf.Kernel.SmartContract/ISmartContractAddressNameProvider.cs index 8aef5fbb69..03936c4558 100644 --- a/src/AElf.Kernel.SmartContract/ISmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.SmartContract/ISmartContractAddressNameProvider.cs @@ -1,11 +1,10 @@ using AElf.Types; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface ISmartContractAddressNameProvider { - public interface ISmartContractAddressNameProvider - { - Hash ContractName { get; } - - string ContractStringName { get; } - } + Hash ContractName { get; } + + string ContractStringName { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/IStateProviderFactory.cs b/src/AElf.Kernel.SmartContract/IStateProviderFactory.cs index 1da784f60b..f2b8c96527 100644 --- a/src/AElf.Kernel.SmartContract/IStateProviderFactory.cs +++ b/src/AElf.Kernel.SmartContract/IStateProviderFactory.cs @@ -1,8 +1,6 @@ -namespace AElf.Kernel.SmartContract -{ - public interface IStateProviderFactory - { - IStateProvider CreateStateProvider(); +namespace AElf.Kernel.SmartContract; - } +public interface IStateProviderFactory +{ + IStateProvider CreateStateProvider(); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ITransactionContext.cs b/src/AElf.Kernel.SmartContract/ITransactionContext.cs index 0a80b54e4b..0f1a3cecad 100644 --- a/src/AElf.Kernel.SmartContract/ITransactionContext.cs +++ b/src/AElf.Kernel.SmartContract/ITransactionContext.cs @@ -1,20 +1,19 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public interface ITransactionContext { - public interface ITransactionContext - { - Address Origin { get; set; } - Hash PreviousBlockHash { get; set; } - Hash OriginTransactionId { get; set; } - long BlockHeight { get; set; } - Timestamp CurrentBlockTime { get; set; } - int CallDepth { get; set; } - int MaxCallDepth { get; set; } - IExecutionObserverThreshold ExecutionObserverThreshold { get; set; } - Transaction Transaction { get; set; } - TransactionTrace Trace { get; set; } - IStateCache StateCache { get; set; } - } + Address Origin { get; set; } + Hash PreviousBlockHash { get; set; } + Hash OriginTransactionId { get; set; } + long BlockHeight { get; set; } + Timestamp CurrentBlockTime { get; set; } + int CallDepth { get; set; } + int MaxCallDepth { get; set; } + IExecutionObserverThreshold ExecutionObserverThreshold { get; set; } + Transaction Transaction { get; set; } + TransactionTrace Trace { get; set; } + IStateCache StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/IDefaultContractZeroCodeProvider.cs b/src/AElf.Kernel.SmartContract/Infrastructure/IDefaultContractZeroCodeProvider.cs index c773ffc42c..e673ded76c 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/IDefaultContractZeroCodeProvider.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/IDefaultContractZeroCodeProvider.cs @@ -6,56 +6,55 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface IDefaultContractZeroCodeProvider { - public interface IDefaultContractZeroCodeProvider - { - SmartContractRegistration DefaultContractZeroRegistration { get; set; } + SmartContractRegistration DefaultContractZeroRegistration { get; set; } - Address ContractZeroAddress { get; } + Address ContractZeroAddress { get; } - void SetDefaultContractZeroRegistrationByType(Type defaultZero); - - Address GetZeroSmartContractAddress(int chainId); - } + void SetDefaultContractZeroRegistrationByType(Type defaultZero); - public class DefaultContractZeroCodeProvider : IDefaultContractZeroCodeProvider, ISingletonDependency - { - private readonly IStaticChainInformationProvider _staticChainInformationProvider; - private readonly ContractOptions _contractOptions; + Address GetZeroSmartContractAddress(int chainId); +} - public DefaultContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, - IOptionsSnapshot contractOptions) - { - _staticChainInformationProvider = staticChainInformationProvider; - _contractOptions = contractOptions.Value; - } +public class DefaultContractZeroCodeProvider : IDefaultContractZeroCodeProvider, ISingletonDependency +{ + private readonly ContractOptions _contractOptions; + private readonly IStaticChainInformationProvider _staticChainInformationProvider; - public SmartContractRegistration DefaultContractZeroRegistration { get; set; } - public Address ContractZeroAddress => _staticChainInformationProvider.ZeroSmartContractAddress; + public DefaultContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, + IOptionsSnapshot contractOptions) + { + _staticChainInformationProvider = staticChainInformationProvider; + _contractOptions = contractOptions.Value; + } - public virtual void SetDefaultContractZeroRegistrationByType(Type defaultZero) - { - var dllPath = Directory.Exists(_contractOptions.GenesisContractDir) - ? Path.Combine(_contractOptions.GenesisContractDir, $"{defaultZero.Assembly.GetName().Name}.dll") - : defaultZero.Assembly.Location; - var code = File.ReadAllBytes(dllPath); - DefaultContractZeroRegistration = new SmartContractRegistration() - { - Category = GetCategory(), - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - }; - } - - protected virtual int GetCategory() - { - return KernelConstants.DefaultRunnerCategory; - } + public SmartContractRegistration DefaultContractZeroRegistration { get; set; } + public Address ContractZeroAddress => _staticChainInformationProvider.ZeroSmartContractAddress; - public Address GetZeroSmartContractAddress(int chainId) + public virtual void SetDefaultContractZeroRegistrationByType(Type defaultZero) + { + var dllPath = Directory.Exists(_contractOptions.GenesisContractDir) + ? Path.Combine(_contractOptions.GenesisContractDir, $"{defaultZero.Assembly.GetName().Name}.dll") + : defaultZero.Assembly.Location; + var code = File.ReadAllBytes(dllPath); + DefaultContractZeroRegistration = new SmartContractRegistration { - return _staticChainInformationProvider.GetZeroSmartContractAddress(chainId); - } + Category = GetCategory(), + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + }; + } + + public Address GetZeroSmartContractAddress(int chainId) + { + return _staticChainInformationProvider.GetZeroSmartContractAddress(chainId); + } + + protected virtual int GetCategory() + { + return KernelConstants.DefaultRunnerCategory; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/IExecutive.cs b/src/AElf.Kernel.SmartContract/Infrastructure/IExecutive.cs index 81552ee0cb..84be2734bf 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/IExecutive.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/IExecutive.cs @@ -4,23 +4,22 @@ using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +/// +/// An isolated environment for runtime contract code. +/// +public interface IExecutive { - /// - /// An isolated environment for runtime contract code. - /// - public interface IExecutive - { - IReadOnlyList Descriptors { get; } - IExecutive SetHostSmartContractBridgeContext(IHostSmartContractBridgeContext smartContractBridgeContext); - Task ApplyAsync(ITransactionContext transactionContext); - string GetJsonStringOfParameters(string methodName, byte[] paramsBytes); - bool IsView(string methodName); - byte[] GetFileDescriptorSet(); - IEnumerable GetFileDescriptors(); - - Hash ContractHash { get; } - Timestamp LastUsedTime { get; set; } - string ContractVersion { get; } - } -} + IReadOnlyList Descriptors { get; } + + Hash ContractHash { get; } + Timestamp LastUsedTime { get; set; } + string ContractVersion { get; } + IExecutive SetHostSmartContractBridgeContext(IHostSmartContractBridgeContext smartContractBridgeContext); + Task ApplyAsync(ITransactionContext transactionContext); + string GetJsonStringOfParameters(string methodName, byte[] paramsBytes); + bool IsView(string methodName); + byte[] GetFileDescriptorSet(); + IEnumerable GetFileDescriptors(); +} \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/IExecutivePlugin.cs b/src/AElf.Kernel.SmartContract/Infrastructure/IExecutivePlugin.cs index c72b92b5c3..b98a17f004 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/IExecutivePlugin.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/IExecutivePlugin.cs @@ -1,12 +1,7 @@ -using System; -using System.Threading.Tasks; -using AElf.Kernel.SmartContract.Application; -using Google.Protobuf; +namespace AElf.Kernel.SmartContract.Infrastructure; -namespace AElf.Kernel.SmartContract.Infrastructure -{ - // public interface IExecutivePlugin - // { - // void PostMain(IHostSmartContractBridgeContext context, ServerServiceDefinition definition); - // } -} \ No newline at end of file + +// public interface IExecutivePlugin +// { +// void PostMain(IHostSmartContractBridgeContext context, ServerServiceDefinition definition); +// } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractCategoryProvider.cs b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractCategoryProvider.cs index b1e88630a4..1fc7bae87a 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractCategoryProvider.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractCategoryProvider.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface ISmartContractCategoryProvider { - public interface ISmartContractCategoryProvider - { - int Category { get; } - } + int Category { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunner.cs b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunner.cs index 2217ccc2c2..ee10bacfdd 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunner.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunner.cs @@ -1,12 +1,10 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface ISmartContractRunner : ISmartContractCategoryProvider { - public interface ISmartContractRunner : ISmartContractCategoryProvider - { - Task RunAsync(SmartContractRegistration reg); - - string ContractVersion { get; } - } + string ContractVersion { get; } + Task RunAsync(SmartContractRegistration reg); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunnerContainer.cs b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunnerContainer.cs index 11370cd2d5..cf0d5ef10a 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunnerContainer.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/ISmartContractRunnerContainer.cs @@ -1,9 +1,8 @@ -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public interface ISmartContractRunnerContainer { - public interface ISmartContractRunnerContainer - { - ISmartContractRunner GetRunner(int category); - void AddRunner(int category, ISmartContractRunner runner); - void UpdateRunner(int category, ISmartContractRunner runner); - } + ISmartContractRunner GetRunner(int category); + void AddRunner(int category, ISmartContractRunner runner); + void UpdateRunner(int category, ISmartContractRunner runner); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/Infrastructure/SmartContractRunnerContainer.cs b/src/AElf.Kernel.SmartContract/Infrastructure/SmartContractRunnerContainer.cs index 39126b4e3f..09ccec434b 100644 --- a/src/AElf.Kernel.SmartContract/Infrastructure/SmartContractRunnerContainer.cs +++ b/src/AElf.Kernel.SmartContract/Infrastructure/SmartContractRunnerContainer.cs @@ -2,45 +2,32 @@ using System.Collections.Generic; using Org.BouncyCastle.Security; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public class SmartContractRunnerContainer : ISmartContractRunnerContainer { - public class SmartContractRunnerContainer : ISmartContractRunnerContainer - { - private readonly ConcurrentDictionary _runners = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _runners = new(); - public SmartContractRunnerContainer(IEnumerable runners) - { - foreach (var r in runners) - { - _runners[r.Category] = r; - } - } + public SmartContractRunnerContainer(IEnumerable runners) + { + foreach (var r in runners) _runners[r.Category] = r; + } - public ISmartContractRunner GetRunner(int category) - { - if (_runners.TryGetValue(category, out var runner)) - { - return runner; - } + public ISmartContractRunner GetRunner(int category) + { + if (_runners.TryGetValue(category, out var runner)) return runner; - throw new InvalidParameterException($"The runner for category {category} is not registered."); - } + throw new InvalidParameterException($"The runner for category {category} is not registered."); + } - public void AddRunner(int category, ISmartContractRunner runner) - { - if (!_runners.TryAdd(category, runner)) - { - throw new InvalidParameterException($"The runner for category {category} is already registered."); - } - } + public void AddRunner(int category, ISmartContractRunner runner) + { + if (!_runners.TryAdd(category, runner)) + throw new InvalidParameterException($"The runner for category {category} is already registered."); + } - public void UpdateRunner(int category, ISmartContractRunner runner) - { - if (_runners.ContainsKey(category)) - { - _runners.AddOrUpdate(category, runner, (key, oldVal) => runner); - } - } + public void UpdateRunner(int category, ISmartContractRunner runner) + { + if (_runners.ContainsKey(category)) _runners.AddOrUpdate(category, runner, (key, oldVal) => runner); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/RequiredAcs.cs b/src/AElf.Kernel.SmartContract/RequiredAcs.cs index 3babc4a56c..a843a089fc 100644 --- a/src/AElf.Kernel.SmartContract/RequiredAcs.cs +++ b/src/AElf.Kernel.SmartContract/RequiredAcs.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class RequiredAcs { - public class RequiredAcs - { - public bool RequireAll; - public List AcsList; - } + public List AcsList; + public bool RequireAll; } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ScopedStateProvider.cs b/src/AElf.Kernel.SmartContract/ScopedStateProvider.cs index 3aa8e216c2..79913c2cea 100644 --- a/src/AElf.Kernel.SmartContract/ScopedStateProvider.cs +++ b/src/AElf.Kernel.SmartContract/ScopedStateProvider.cs @@ -1,41 +1,39 @@ -using System.Threading.Tasks; using AElf.Types; using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class NullStateCache : IStateCache { - public class NullStateCache : IStateCache + public bool TryGetValue(ScopedStatePath key, out byte[] value) { - public bool TryGetValue(ScopedStatePath key, out byte[] value) - { - value = null; - return false; - } - - public byte[] this[ScopedStatePath key] - { - get => null; - set { } - } + value = null; + return false; } - internal class ScopedStateProvider : IScopedStateProvider + public byte[] this[ScopedStatePath key] { - public IHostSmartContractBridgeContext HostSmartContractBridgeContext { get; set; } - public IStateCache Cache { get; set; } = new NullStateCache(); + get => null; + set { } + } +} + +internal class ScopedStateProvider : IScopedStateProvider +{ + public IHostSmartContractBridgeContext HostSmartContractBridgeContext { get; set; } + public IStateCache Cache { get; set; } = new NullStateCache(); - public Address ContractAddress { get; set; } + public Address ContractAddress { get; set; } - public byte[] Get(StatePath path) + public byte[] Get(StatePath path) + { + var scoped = new ScopedStatePath { - var scoped = new ScopedStatePath() - { - Address = ContractAddress, - Path = path - }; - var byteString = - AsyncHelper.RunSync(() => HostSmartContractBridgeContext.GetStateAsync(scoped.ToStateKey())); - return byteString?.ToByteArray(); - } + Address = ContractAddress, + Path = path + }; + var byteString = + AsyncHelper.RunSync(() => HostSmartContractBridgeContext.GetStateAsync(scoped.ToStateKey())); + return byteString?.ToByteArray(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/SmartContractAElfModule.cs b/src/AElf.Kernel.SmartContract/SmartContractAElfModule.cs index 549a4b3a65..e8e62a97c8 100644 --- a/src/AElf.Kernel.SmartContract/SmartContractAElfModule.cs +++ b/src/AElf.Kernel.SmartContract/SmartContractAElfModule.cs @@ -4,18 +4,17 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +[DependsOn(typeof(CoreKernelAElfModule))] +public class SmartContractAElfModule : AElfModule { - [DependsOn(typeof(CoreKernelAElfModule))] - public class SmartContractAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddTransient(typeof(IContractReaderFactory<>), typeof(ContractReaderFactory<>)); - context.Services.AddSingleton(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddTransient(typeof(IContractReaderFactory<>), typeof(ContractReaderFactory<>)); + context.Services.AddSingleton(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/SmartContractConstants.cs b/src/AElf.Kernel.SmartContract/SmartContractConstants.cs index 4b0bd7d4f1..0a6cb05208 100644 --- a/src/AElf.Kernel.SmartContract/SmartContractConstants.cs +++ b/src/AElf.Kernel.SmartContract/SmartContractConstants.cs @@ -1,11 +1,10 @@ -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class SmartContractConstants { - public class SmartContractConstants - { - public const int ExecutionCallThreshold = 15000; + public const int ExecutionCallThreshold = 15000; + + public const int ExecutionBranchThreshold = 15000; - public const int ExecutionBranchThreshold = 15000; - - public const int StateSizeLimit = 128 * 1024; - } + public const int StateSizeLimit = 128 * 1024; } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/StateProviderFactory.cs b/src/AElf.Kernel.SmartContract/StateProviderFactory.cs index b09a99cfdb..a0db7da3a6 100644 --- a/src/AElf.Kernel.SmartContract/StateProviderFactory.cs +++ b/src/AElf.Kernel.SmartContract/StateProviderFactory.cs @@ -1,22 +1,18 @@ using AElf.Kernel.SmartContract.Domain; -namespace AElf.Kernel.SmartContract -{ - public class StateProviderFactory : IStateProviderFactory - { - private readonly IBlockchainStateManager _blockchainStateManager; +namespace AElf.Kernel.SmartContract; - public StateProviderFactory(IBlockchainStateManager blockchainStateManager) - { - _blockchainStateManager = blockchainStateManager; - } +public class StateProviderFactory : IStateProviderFactory +{ + private readonly IBlockchainStateManager _blockchainStateManager; - public IStateProvider CreateStateProvider() - { - return new ScopedStateProvider() - { - }; - } + public StateProviderFactory(IBlockchainStateManager blockchainStateManager) + { + _blockchainStateManager = blockchainStateManager; + } + public IStateProvider CreateStateProvider() + { + return new ScopedStateProvider(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/TransactionContext.cs b/src/AElf.Kernel.SmartContract/TransactionContext.cs index cee987ef1f..aaf3fe79e6 100644 --- a/src/AElf.Kernel.SmartContract/TransactionContext.cs +++ b/src/AElf.Kernel.SmartContract/TransactionContext.cs @@ -1,20 +1,19 @@ -using Google.Protobuf.WellKnownTypes; -using AElf.Types; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class TransactionContext : ITransactionContext { - public class TransactionContext : ITransactionContext - { - public Address Origin { get; set; } - public Hash PreviousBlockHash { get; set; } - public Hash OriginTransactionId { get; set; } - public long BlockHeight { get; set; } - public Timestamp CurrentBlockTime { get; set; } - public int CallDepth { get; set; } - public int MaxCallDepth { get; set; } - public IExecutionObserverThreshold ExecutionObserverThreshold { get; set; } - public Transaction Transaction { get; set; } - public TransactionTrace Trace { get; set; } - public IStateCache StateCache { get; set; } - } -} + public Address Origin { get; set; } + public Hash PreviousBlockHash { get; set; } + public Hash OriginTransactionId { get; set; } + public long BlockHeight { get; set; } + public Timestamp CurrentBlockTime { get; set; } + public int CallDepth { get; set; } + public int MaxCallDepth { get; set; } + public IExecutionObserverThreshold ExecutionObserverThreshold { get; set; } + public Transaction Transaction { get; set; } + public TransactionTrace Trace { get; set; } + public IStateCache StateCache { get; set; } +} \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/ZeroSmartContractAddressNameProvider.cs b/src/AElf.Kernel.SmartContract/ZeroSmartContractAddressNameProvider.cs index 5ef72811db..8d6782d452 100644 --- a/src/AElf.Kernel.SmartContract/ZeroSmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.SmartContract/ZeroSmartContractAddressNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf +namespace AElf; + +public class ZeroSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class ZeroSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = Hash.Empty; - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = Hash.Empty; + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/AElf.Kernel.SmartContractExecution.csproj b/src/AElf.Kernel.SmartContractExecution/AElf.Kernel.SmartContractExecution.csproj index ab84dfc8a4..ab40e1634d 100644 --- a/src/AElf.Kernel.SmartContractExecution/AElf.Kernel.SmartContractExecution.csproj +++ b/src/AElf.Kernel.SmartContractExecution/AElf.Kernel.SmartContractExecution.csproj @@ -1,15 +1,15 @@ - + net6.0 AElf.Kernel.SmartContractExecution true Smart contract execution related components. - + - - + + diff --git a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutingService.cs index c6c0e774f6..6dcfca3178 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutingService.cs @@ -16,239 +16,235 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class BlockExecutingService : IBlockExecutingService, ITransientDependency { - public class BlockExecutingService : IBlockExecutingService, ITransientDependency + private readonly IBlockchainStateService _blockchainStateService; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ITransactionExecutingService _transactionExecutingService; + private readonly ITransactionResultService _transactionResultService; + + public BlockExecutingService(ITransactionExecutingService transactionExecutingService, + IBlockchainStateService blockchainStateService, + ITransactionResultService transactionResultService, + ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) { - private readonly ITransactionExecutingService _transactionExecutingService; - private readonly IBlockchainStateService _blockchainStateService; - private readonly ITransactionResultService _transactionResultService; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; - public ILocalEventBus EventBus { get; set; } - public ILogger Logger { get; set; } - - public BlockExecutingService(ITransactionExecutingService transactionExecutingService, - IBlockchainStateService blockchainStateService, - ITransactionResultService transactionResultService, - ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) - { - _transactionExecutingService = transactionExecutingService; - _blockchainStateService = blockchainStateService; - _transactionResultService = transactionResultService; - _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; - EventBus = NullLocalEventBus.Instance; - } + _transactionExecutingService = transactionExecutingService; + _blockchainStateService = blockchainStateService; + _transactionResultService = transactionResultService; + _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; + EventBus = NullLocalEventBus.Instance; + } - public async Task ExecuteBlockAsync(BlockHeader blockHeader, - List nonCancellableTransactions) - { - _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader, - out var systemTransactionCount); - return await ExecuteBlockAsync(blockHeader, nonCancellableTransactions.Take(systemTransactionCount), - nonCancellableTransactions.Skip(systemTransactionCount), - CancellationToken.None); - } + public ILocalEventBus EventBus { get; set; } + public ILogger Logger { get; set; } - public async Task ExecuteBlockAsync(BlockHeader blockHeader, - IEnumerable nonCancellableTransactions, IEnumerable cancellableTransactions, - CancellationToken cancellationToken) - { - Logger.LogTrace("Entered ExecuteBlockAsync"); - var nonCancellable = nonCancellableTransactions.ToList(); - var cancellable = cancellableTransactions.ToList(); - var nonCancellableReturnSets = - await _transactionExecutingService.ExecuteAsync( - new TransactionExecutingDto {BlockHeader = blockHeader, Transactions = nonCancellable}, - CancellationToken.None); - Logger.LogTrace("Executed non-cancellable txs"); - - var returnSetCollection = new ExecutionReturnSetCollection(nonCancellableReturnSets); - List cancellableReturnSets = new List(); - - if (!cancellationToken.IsCancellationRequested && cancellable.Count > 0) - { - cancellableReturnSets = await _transactionExecutingService.ExecuteAsync( - new TransactionExecutingDto - { - BlockHeader = blockHeader, - Transactions = cancellable, - PartialBlockStateSet = returnSetCollection.ToBlockStateSet() - }, - cancellationToken); - returnSetCollection.AddRange(cancellableReturnSets); - Logger.LogTrace("Executed cancellable txs"); - } + public async Task ExecuteBlockAsync(BlockHeader blockHeader, + List nonCancellableTransactions) + { + _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader, + out var systemTransactionCount); + return await ExecuteBlockAsync(blockHeader, nonCancellableTransactions.Take(systemTransactionCount), + nonCancellableTransactions.Skip(systemTransactionCount), + CancellationToken.None); + } - var executedCancellableTransactions = new HashSet(cancellableReturnSets.Select(x => x.TransactionId)); - var allExecutedTransactions = - nonCancellable.Concat(cancellable.Where(x => executedCancellableTransactions.Contains(x.GetHash()))) - .ToList(); - var blockStateSet = - CreateBlockStateSet(blockHeader.PreviousBlockHash, blockHeader.Height, returnSetCollection); - var block = await FillBlockAfterExecutionAsync(blockHeader, allExecutedTransactions, returnSetCollection, - blockStateSet); - - // set txn results - var transactionResults = await SetTransactionResultsAsync(returnSetCollection, block.Header); - - // set blocks state - blockStateSet.BlockHash = block.GetHash(); - Logger.LogTrace("Set block state set."); - await _blockchainStateService.SetBlockStateSetAsync(blockStateSet); - - // handle execution cases - await CleanUpReturnSetCollectionAsync(block.Header, returnSetCollection); - - return new BlockExecutedSet - { - Block = block, - TransactionMap = allExecutedTransactions.ToDictionary(p => p.GetHash(), p => p), - TransactionResultMap = transactionResults.ToDictionary(p => p.TransactionId, p => p) - }; - } + public async Task ExecuteBlockAsync(BlockHeader blockHeader, + IEnumerable nonCancellableTransactions, IEnumerable cancellableTransactions, + CancellationToken cancellationToken) + { + Logger.LogTrace("Entered ExecuteBlockAsync"); + var nonCancellable = nonCancellableTransactions.ToList(); + var cancellable = cancellableTransactions.ToList(); + var nonCancellableReturnSets = + await _transactionExecutingService.ExecuteAsync( + new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = nonCancellable }, + CancellationToken.None); + Logger.LogTrace("Executed non-cancellable txs"); - private Task FillBlockAfterExecutionAsync(BlockHeader header, - IEnumerable transactions, ExecutionReturnSetCollection executionReturnSetCollection, BlockStateSet blockStateSet) - { - Logger.LogTrace("Start block field filling after execution."); - var bloom = new Bloom(); - foreach (var returnSet in executionReturnSetCollection.Executed) - { - bloom.Combine(new[] {new Bloom(returnSet.Bloom.ToByteArray())}); - } - - var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); - var orderedReturnSets = executionReturnSetCollection.GetExecutionReturnSetList() - .OrderBy(d => allExecutedTransactionIds.IndexOf(d.TransactionId)).ToList(); + var returnSetCollection = new ExecutionReturnSetCollection(nonCancellableReturnSets); + var cancellableReturnSets = new List(); - var block = new Block - { - Header = new BlockHeader(header) + if (!cancellationToken.IsCancellationRequested && cancellable.Count > 0) + { + cancellableReturnSets = await _transactionExecutingService.ExecuteAsync( + new TransactionExecutingDto { - Bloom = ByteString.CopyFrom(bloom.Data), - MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet), - MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(orderedReturnSets), - MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds) + BlockHeader = blockHeader, + Transactions = cancellable, + PartialBlockStateSet = returnSetCollection.ToBlockStateSet() }, - Body = new BlockBody - { - TransactionIds = {allExecutedTransactionIds} - } - }; - - Logger.LogTrace("Finish block field filling after execution."); - return Task.FromResult(block); + cancellationToken); + returnSetCollection.AddRange(cancellableReturnSets); + Logger.LogTrace("Executed cancellable txs"); } - protected virtual Task CleanUpReturnSetCollectionAsync(BlockHeader blockHeader, ExecutionReturnSetCollection executionReturnSetCollection) - { - return Task.CompletedTask; - } + var executedCancellableTransactions = new HashSet(cancellableReturnSets.Select(x => x.TransactionId)); + var allExecutedTransactions = + nonCancellable.Concat(cancellable.Where(x => executedCancellableTransactions.Contains(x.GetHash()))) + .ToList(); + var blockStateSet = + CreateBlockStateSet(blockHeader.PreviousBlockHash, blockHeader.Height, returnSetCollection); + var block = await FillBlockAfterExecutionAsync(blockHeader, allExecutedTransactions, returnSetCollection, + blockStateSet); + + // set txn results + var transactionResults = await SetTransactionResultsAsync(returnSetCollection, block.Header); + + // set blocks state + blockStateSet.BlockHash = block.GetHash(); + Logger.LogTrace("Set block state set."); + await _blockchainStateService.SetBlockStateSetAsync(blockStateSet); + + // handle execution cases + await CleanUpReturnSetCollectionAsync(block.Header, returnSetCollection); - private Hash CalculateWorldStateMerkleTreeRoot(BlockStateSet blockStateSet) + return new BlockExecutedSet { - Logger.LogTrace("Start world state calculation."); - Hash merkleTreeRootOfWorldState; - var byteArrays = GetDeterministicByteArrays(blockStateSet); - using (var hashAlgorithm = SHA256.Create()) - { - foreach (var bytes in byteArrays) - { - hashAlgorithm.TransformBlock(bytes, 0, bytes.Length, null, 0); - } + Block = block, + TransactionMap = allExecutedTransactions.ToDictionary(p => p.GetHash(), p => p), + TransactionResultMap = transactionResults.ToDictionary(p => p.TransactionId, p => p) + }; + } - hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0); - merkleTreeRootOfWorldState = Hash.LoadFromByteArray(hashAlgorithm.Hash); - } + private Task FillBlockAfterExecutionAsync(BlockHeader header, + IEnumerable transactions, ExecutionReturnSetCollection executionReturnSetCollection, + BlockStateSet blockStateSet) + { + Logger.LogTrace("Start block field filling after execution."); + var bloom = new Bloom(); + foreach (var returnSet in executionReturnSetCollection.Executed) + bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); - return merkleTreeRootOfWorldState; - } + var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); + var orderedReturnSets = executionReturnSetCollection.GetExecutionReturnSetList() + .OrderBy(d => allExecutedTransactionIds.IndexOf(d.TransactionId)).ToList(); - private IEnumerable GetDeterministicByteArrays(BlockStateSet blockStateSet) + var block = new Block { - var keys = blockStateSet.Changes.Keys; - foreach (var k in new SortedSet(keys)) + Header = new BlockHeader(header) { - yield return Encoding.UTF8.GetBytes(k); - yield return blockStateSet.Changes[k].ToByteArray(); - } - - keys = blockStateSet.Deletes; - foreach (var k in new SortedSet(keys)) + Bloom = ByteString.CopyFrom(bloom.Data), + MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet), + MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(orderedReturnSets), + MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds) + }, + Body = new BlockBody { - yield return Encoding.UTF8.GetBytes(k); - yield return ByteString.Empty.ToByteArray(); + TransactionIds = { allExecutedTransactionIds } } - } + }; - private Hash CalculateTransactionStatusMerkleTreeRoot(List blockExecutionReturnSet) + Logger.LogTrace("Finish block field filling after execution."); + return Task.FromResult(block); + } + + protected virtual Task CleanUpReturnSetCollectionAsync(BlockHeader blockHeader, + ExecutionReturnSetCollection executionReturnSetCollection) + { + return Task.CompletedTask; + } + + private Hash CalculateWorldStateMerkleTreeRoot(BlockStateSet blockStateSet) + { + Logger.LogTrace("Start world state calculation."); + Hash merkleTreeRootOfWorldState; + var byteArrays = GetDeterministicByteArrays(blockStateSet); + using (var hashAlgorithm = SHA256.Create()) { - Logger.LogTrace("Start transaction status merkle tree root calculation."); - var executionReturnSet = blockExecutionReturnSet.Select(executionReturn => - (executionReturn.TransactionId, executionReturn.Status)); - var nodes = new List(); - foreach (var (transactionId, status) in executionReturnSet) - { - nodes.Add(GetHashCombiningTransactionAndStatus(transactionId, status)); - } + foreach (var bytes in byteArrays) hashAlgorithm.TransformBlock(bytes, 0, bytes.Length, null, 0); - return BinaryMerkleTree.FromLeafNodes(nodes).Root; + hashAlgorithm.TransformFinalBlock(new byte[0], 0, 0); + merkleTreeRootOfWorldState = Hash.LoadFromByteArray(hashAlgorithm.Hash); } - private Hash CalculateTransactionMerkleTreeRoot(IEnumerable transactionIds) + return merkleTreeRootOfWorldState; + } + + private IEnumerable GetDeterministicByteArrays(BlockStateSet blockStateSet) + { + var keys = blockStateSet.Changes.Keys; + foreach (var k in new SortedSet(keys)) { - Logger.LogTrace("Start transaction merkle tree root calculation."); - return BinaryMerkleTree.FromLeafNodes(transactionIds).Root; + yield return Encoding.UTF8.GetBytes(k); + yield return blockStateSet.Changes[k].ToByteArray(); } - private Hash GetHashCombiningTransactionAndStatus(Hash txId, - TransactionResultStatus executionReturnStatus) + keys = blockStateSet.Deletes; + foreach (var k in new SortedSet(keys)) { - // combine tx result status - var rawBytes = ByteArrayHelper.ConcatArrays(txId.ToByteArray(), - EncodingHelper.EncodeUtf8(executionReturnStatus.ToString())); - return HashHelper.ComputeFrom(rawBytes); + yield return Encoding.UTF8.GetBytes(k); + yield return ByteString.Empty.ToByteArray(); } + } + + private Hash CalculateTransactionStatusMerkleTreeRoot(List blockExecutionReturnSet) + { + Logger.LogTrace("Start transaction status merkle tree root calculation."); + var executionReturnSet = blockExecutionReturnSet.Select(executionReturn => + (executionReturn.TransactionId, executionReturn.Status)); + var nodes = new List(); + foreach (var (transactionId, status) in executionReturnSet) + nodes.Add(GetHashCombiningTransactionAndStatus(transactionId, status)); + + return BinaryMerkleTree.FromLeafNodes(nodes).Root; + } + + private Hash CalculateTransactionMerkleTreeRoot(IEnumerable transactionIds) + { + Logger.LogTrace("Start transaction merkle tree root calculation."); + return BinaryMerkleTree.FromLeafNodes(transactionIds).Root; + } - private BlockStateSet CreateBlockStateSet(Hash previousBlockHash, long blockHeight, - ExecutionReturnSetCollection executionReturnSetCollection) + private Hash GetHashCombiningTransactionAndStatus(Hash txId, + TransactionResultStatus executionReturnStatus) + { + // combine tx result status + var rawBytes = ByteArrayHelper.ConcatArrays(txId.ToByteArray(), + EncodingHelper.EncodeUtf8(executionReturnStatus.ToString())); + return HashHelper.ComputeFrom(rawBytes); + } + + private BlockStateSet CreateBlockStateSet(Hash previousBlockHash, long blockHeight, + ExecutionReturnSetCollection executionReturnSetCollection) + { + var blockStateSet = new BlockStateSet { - var blockStateSet = new BlockStateSet - { - BlockHeight = blockHeight, - PreviousHash = previousBlockHash - }; - foreach (var returnSet in executionReturnSetCollection.Executed) + BlockHeight = blockHeight, + PreviousHash = previousBlockHash + }; + foreach (var returnSet in executionReturnSetCollection.Executed) + { + foreach (var change in returnSet.StateChanges) { - foreach (var change in returnSet.StateChanges) - { - blockStateSet.Changes[change.Key] = change.Value; - blockStateSet.Deletes.Remove(change.Key); - } - - foreach (var delete in returnSet.StateDeletes) - { - blockStateSet.Deletes.AddIfNotContains(delete.Key); - blockStateSet.Changes.Remove(delete.Key); - } + blockStateSet.Changes[change.Key] = change.Value; + blockStateSet.Deletes.Remove(change.Key); } - return blockStateSet; + foreach (var delete in returnSet.StateDeletes) + { + blockStateSet.Deletes.AddIfNotContains(delete.Key); + blockStateSet.Changes.Remove(delete.Key); + } } - private async Task> SetTransactionResultsAsync(ExecutionReturnSetCollection executionReturnSetCollection, BlockHeader blockHeader) - { - //save all transaction results - var results = executionReturnSetCollection.GetExecutionReturnSetList() - .Select(p => - { - p.TransactionResult.BlockHash = blockHeader.GetHash(); - p.TransactionResult.BlockNumber = blockHeader.Height; - return p.TransactionResult; - }).ToList(); + return blockStateSet; + } - await _transactionResultService.AddTransactionResultsAsync(results, blockHeader); - return results; - } + private async Task> SetTransactionResultsAsync( + ExecutionReturnSetCollection executionReturnSetCollection, BlockHeader blockHeader) + { + //save all transaction results + var results = executionReturnSetCollection.GetExecutionReturnSetList() + .Select(p => + { + p.TransactionResult.BlockHash = blockHeader.GetHash(); + p.TransactionResult.BlockNumber = blockHeader.Height; + return p.TransactionResult; + }).ToList(); + + await _transactionResultService.AddTransactionResultsAsync(results, blockHeader); + return results; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResult.cs b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResult.cs index 86c1a207b6..fdc7ae1dc2 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResult.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResult.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; using AElf.Kernel.Blockchain; -using Google.Protobuf; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class BlockExecutionResult { - public class BlockExecutionResult + public BlockExecutionResult() { - public List SuccessBlockExecutedSets { get; set; } + SuccessBlockExecutedSets = new List(); + ExecutedFailedBlocks = new List(); + } - public List ExecutedFailedBlocks { get; set; } + public List SuccessBlockExecutedSets { get; set; } - public BlockExecutionResult() - { - SuccessBlockExecutedSets = new List(); - ExecutedFailedBlocks = new List(); - } - } + public List ExecutedFailedBlocks { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResultProcessingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResultProcessingService.cs index bb974c05a9..0c02156f93 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResultProcessingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/BlockExecutionResultProcessingService.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.SmartContractExecution.Events; using AElf.Types; using Microsoft.Extensions.Logging; @@ -10,61 +9,58 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class BlockExecutionResultProcessingService : IBlockExecutionResultProcessingService, ITransientDependency { - public class BlockExecutionResultProcessingService : IBlockExecutionResultProcessingService, ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly IChainBlockLinkService _chainBlockLinkService; + + public BlockExecutionResultProcessingService(IBlockchainService blockchainService, + IChainBlockLinkService chainBlockLinkService) { - private readonly IBlockchainService _blockchainService; - private readonly IChainBlockLinkService _chainBlockLinkService; + _blockchainService = blockchainService; + _chainBlockLinkService = chainBlockLinkService; + + LocalEventBus = NullLocalEventBus.Instance; + Logger = NullLogger.Instance; + } - public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } - public BlockExecutionResultProcessingService(IBlockchainService blockchainService, - IChainBlockLinkService chainBlockLinkService) + public async Task ProcessBlockExecutionResultAsync(Chain chain, BlockExecutionResult blockExecutionResult) + { + if (blockExecutionResult.ExecutedFailedBlocks.Any() || + blockExecutionResult.SuccessBlockExecutedSets.Count == 0 || + blockExecutionResult.SuccessBlockExecutedSets.Last().Height < chain.BestChainHeight) { - _blockchainService = blockchainService; - _chainBlockLinkService = chainBlockLinkService; + await SetBlockExecutionStatusAsync(blockExecutionResult.ExecutedFailedBlocks.Select(b => b.GetHash()), + ChainBlockLinkExecutionStatus.ExecutionFailed); + await _blockchainService.RemoveLongestBranchAsync(chain); - LocalEventBus = NullLocalEventBus.Instance; - Logger = NullLogger.Instance; + Logger.LogDebug("No block executed successfully or no block is higher than best chain."); + return; } - public async Task ProcessBlockExecutionResultAsync(Chain chain, BlockExecutionResult blockExecutionResult) + var lastExecutedSuccessBlock = blockExecutionResult.SuccessBlockExecutedSets.Last(); + await _blockchainService.SetBestChainAsync(chain, lastExecutedSuccessBlock.Height, + lastExecutedSuccessBlock.GetHash()); + await SetBlockExecutionStatusAsync(blockExecutionResult.SuccessBlockExecutedSets.Select(b => b.GetHash()), + ChainBlockLinkExecutionStatus.ExecutionSuccess); + await LocalEventBus.PublishAsync(new BlocksExecutionSucceededEvent { - if (blockExecutionResult.ExecutedFailedBlocks.Any() || - blockExecutionResult.SuccessBlockExecutedSets.Count == 0 || - blockExecutionResult.SuccessBlockExecutedSets.Last().Height < chain.BestChainHeight) - { - await SetBlockExecutionStatusAsync(blockExecutionResult.ExecutedFailedBlocks.Select(b => b.GetHash()), - ChainBlockLinkExecutionStatus.ExecutionFailed); - await _blockchainService.RemoveLongestBranchAsync(chain); - - Logger.LogDebug("No block executed successfully or no block is higher than best chain."); - return; - } + BlockExecutedSets = blockExecutionResult.SuccessBlockExecutedSets + }); - var lastExecutedSuccessBlock = blockExecutionResult.SuccessBlockExecutedSets.Last(); - await _blockchainService.SetBestChainAsync(chain, lastExecutedSuccessBlock.Height, - lastExecutedSuccessBlock.GetHash()); - await SetBlockExecutionStatusAsync(blockExecutionResult.SuccessBlockExecutedSets.Select(b => b.GetHash()), - ChainBlockLinkExecutionStatus.ExecutionSuccess); - await LocalEventBus.PublishAsync(new BlocksExecutionSucceededEvent - { - BlockExecutedSets = blockExecutionResult.SuccessBlockExecutedSets - }); - - Logger.LogInformation( - $"Attach blocks to best chain, best chain hash: {chain.BestChainHash}, height: {chain.BestChainHeight}"); - } + Logger.LogInformation( + $"Attach blocks to best chain, best chain hash: {chain.BestChainHash}, height: {chain.BestChainHeight}"); + } - private async Task SetBlockExecutionStatusAsync(IEnumerable blockHashes, - ChainBlockLinkExecutionStatus status) - { - foreach (var blockHash in blockHashes) - { - await _chainBlockLinkService.SetChainBlockLinkExecutionStatusAsync(blockHash, status); - } - } + private async Task SetBlockExecutionStatusAsync(IEnumerable blockHashes, + ChainBlockLinkExecutionStatus status) + { + foreach (var blockHash in blockHashes) + await _chainBlockLinkService.SetChainBlockLinkExecutionStatusAsync(blockHash, status); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/BlockchainExecutingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/BlockchainExecutingService.cs index f9a45a7f67..219b1f4404 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/BlockchainExecutingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/BlockchainExecutingService.cs @@ -10,155 +10,148 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class FullBlockchainExecutingService : IBlockchainExecutingService, ITransientDependency { - public class FullBlockchainExecutingService : IBlockchainExecutingService, ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockValidationService _blockValidationService; + private readonly ITransactionResultService _transactionResultService; + + public FullBlockchainExecutingService(IBlockchainService blockchainService, + IBlockValidationService blockValidationService, + IBlockExecutingService blockExecutingService, + ITransactionResultService transactionResultService, IBlockStateSetManger blockStateSetManger) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockValidationService _blockValidationService; - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly ITransactionResultService _transactionResultService; - public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } - - public FullBlockchainExecutingService(IBlockchainService blockchainService, - IBlockValidationService blockValidationService, - IBlockExecutingService blockExecutingService, - ITransactionResultService transactionResultService, IBlockStateSetManger blockStateSetManger) - { - _blockchainService = blockchainService; - _blockValidationService = blockValidationService; - _blockExecutingService = blockExecutingService; - _transactionResultService = transactionResultService; - _blockStateSetManger = blockStateSetManger; + _blockchainService = blockchainService; + _blockValidationService = blockValidationService; + _blockExecutingService = blockExecutingService; + _transactionResultService = transactionResultService; + _blockStateSetManger = blockStateSetManger; - LocalEventBus = NullLocalEventBus.Instance; - } + LocalEventBus = NullLocalEventBus.Instance; + } - public async Task ExecuteBlocksAsync(IEnumerable blocks) + public ILocalEventBus LocalEventBus { get; set; } + public ILogger Logger { get; set; } + + public async Task ExecuteBlocksAsync(IEnumerable blocks) + { + var executionResult = new BlockExecutionResult(); + try { - var executionResult = new BlockExecutionResult(); - try - { - foreach (var block in blocks) - { - var blockExecutedSet = await ProcessBlockAsync(block); - if (blockExecutedSet == null) - { - executionResult.ExecutedFailedBlocks.Add(block); - return executionResult; - } - - executionResult.SuccessBlockExecutedSets.Add(blockExecutedSet); - Logger.LogInformation( - $"Executed block {block.GetHash()} at height {block.Height}, with {block.Body.TransactionsCount} txns."); - - await LocalEventBus.PublishAsync(new BlockAcceptedEvent {BlockExecutedSet = blockExecutedSet}); - } - } - catch (BlockValidationException ex) + foreach (var block in blocks) { - if (!(ex.InnerException is ValidateNextTimeBlockValidationException)) + var blockExecutedSet = await ProcessBlockAsync(block); + if (blockExecutedSet == null) { - throw; + executionResult.ExecutedFailedBlocks.Add(block); + return executionResult; } - Logger.LogDebug( - $"Block validation failed: {ex.Message}. Inner exception {ex.InnerException.Message}"); - } + executionResult.SuccessBlockExecutedSets.Add(blockExecutedSet); + Logger.LogInformation( + $"Executed block {block.GetHash()} at height {block.Height}, with {block.Body.TransactionsCount} txns."); - return executionResult; + await LocalEventBus.PublishAsync(new BlockAcceptedEvent { BlockExecutedSet = blockExecutedSet }); + } } - - - private async Task ExecuteBlockAsync(Block block) + catch (BlockValidationException ex) { - var blockHash = block.GetHash(); + if (!(ex.InnerException is ValidateNextTimeBlockValidationException)) throw; - var blockState = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); - if (blockState != null) - { - Logger.LogDebug($"Block already executed. block hash: {blockHash}"); - return await GetExecuteBlockSetAsync(block, blockHash); - } - - var transactions = await _blockchainService.GetTransactionsAsync(block.TransactionIds); - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); - var executedBlock = blockExecutedSet.Block; - - var blockHashWithoutCache = executedBlock.GetHashWithoutCache(); - if (blockHashWithoutCache == blockHash) - return blockExecutedSet; Logger.LogDebug( - $"Block execution failed. Expected: {block}, actual: {executedBlock}"); - return null; + $"Block validation failed: {ex.Message}. Inner exception {ex.InnerException.Message}"); } - private async Task GetExecuteBlockSetAsync(Block block, Hash blockHash) - { - var set = new BlockExecutedSet() - { - Block = block, - TransactionMap = new Dictionary(), - - TransactionResultMap = new Dictionary() - }; - if (block.TransactionIds.Any()) - { - set.TransactionMap = (await _blockchainService.GetTransactionsAsync(block.TransactionIds)) - .ToDictionary(p => p.GetHash(), p => p); - } - - foreach (var transactionId in block.TransactionIds) - { - if ((set.TransactionResultMap[transactionId] = - await _transactionResultService.GetTransactionResultAsync(transactionId, blockHash)) - == null) - { - Logger.LogWarning( - $"Fail to load transaction result. block hash : {blockHash}, tx id: {transactionId}"); + return executionResult; + } - return null; - } - } - return set; + private async Task ExecuteBlockAsync(Block block) + { + var blockHash = block.GetHash(); + + var blockState = await _blockStateSetManger.GetBlockStateSetAsync(blockHash); + if (blockState != null) + { + Logger.LogDebug($"Block already executed. block hash: {blockHash}"); + return await GetExecuteBlockSetAsync(block, blockHash); } - /// - /// Processing pipeline for a block contains ValidateBlockBeforeExecute, ExecuteBlock and ValidateBlockAfterExecute. - /// - /// - /// Block processing result is true if succeed, otherwise false. - private async Task ProcessBlockAsync(Block block) + var transactions = await _blockchainService.GetTransactionsAsync(block.TransactionIds); + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); + var executedBlock = blockExecutedSet.Block; + + var blockHashWithoutCache = executedBlock.GetHashWithoutCache(); + if (blockHashWithoutCache == blockHash) + return blockExecutedSet; + Logger.LogDebug( + $"Block execution failed. Expected: {block}, actual: {executedBlock}"); + return null; + } + + private async Task GetExecuteBlockSetAsync(Block block, Hash blockHash) + { + var set = new BlockExecutedSet { - var blockHash = block.GetHash(); - // Set the other blocks as bad block if found the first bad block - if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(block)) + Block = block, + TransactionMap = new Dictionary(), + + TransactionResultMap = new Dictionary() + }; + if (block.TransactionIds.Any()) + set.TransactionMap = (await _blockchainService.GetTransactionsAsync(block.TransactionIds)) + .ToDictionary(p => p.GetHash(), p => p); + + foreach (var transactionId in block.TransactionIds) + if ((set.TransactionResultMap[transactionId] = + await _transactionResultService.GetTransactionResultAsync(transactionId, blockHash)) + == null) { - Logger.LogDebug($"Block validate fails before execution. block hash : {blockHash}"); + Logger.LogWarning( + $"Fail to load transaction result. block hash : {blockHash}, tx id: {transactionId}"); + return null; } - var blockExecutedSet = await ExecuteBlockAsync(block); + return set; + } - if (blockExecutedSet == null) - { - Logger.LogDebug($"Block execution failed. block hash : {blockHash}"); - return null; - } + /// + /// Processing pipeline for a block contains ValidateBlockBeforeExecute, ExecuteBlock and ValidateBlockAfterExecute. + /// + /// + /// Block processing result is true if succeed, otherwise false. + private async Task ProcessBlockAsync(Block block) + { + var blockHash = block.GetHash(); + // Set the other blocks as bad block if found the first bad block + if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(block)) + { + Logger.LogDebug($"Block validate fails before execution. block hash : {blockHash}"); + return null; + } - if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(block)) - { - Logger.LogDebug($"Block validate fails after execution. block hash : {blockHash}"); - return null; - } + var blockExecutedSet = await ExecuteBlockAsync(block); - await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block.Header, - block.Body.TransactionIds.ToList()); + if (blockExecutedSet == null) + { + Logger.LogDebug($"Block execution failed. block hash : {blockHash}"); + return null; + } - return blockExecutedSet; + if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(block)) + { + Logger.LogDebug($"Block validate fails after execution. block hash : {blockHash}"); + return null; } + + await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block.Header, + block.Body.TransactionIds.ToList()); + + return blockExecutedSet; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/CodeUpdatedLogEventProcessor.cs b/src/AElf.Kernel.SmartContractExecution/Application/CodeUpdatedLogEventProcessor.cs index 621ee7f364..450c294c11 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/CodeUpdatedLogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/CodeUpdatedLogEventProcessor.cs @@ -1,66 +1,65 @@ using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.CSharp.Core.Extension; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class CodeUpdatedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - public class CodeUpdatedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + + public CodeUpdatedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ISmartContractRegistrationProvider smartContractRegistrationProvider, + ISmartContractRegistrationInStateProvider smartContractRegistrationInStateProvider, + ISmartContractExecutiveService smartContractExecutiveService) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; - private readonly ISmartContractExecutiveService _smartContractExecutiveService; + _smartContractAddressService = smartContractAddressService; + _smartContractRegistrationProvider = smartContractRegistrationProvider; + _smartContractRegistrationInStateProvider = smartContractRegistrationInStateProvider; + _smartContractExecutiveService = smartContractExecutiveService; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public CodeUpdatedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ISmartContractRegistrationProvider smartContractRegistrationProvider, - ISmartContractRegistrationInStateProvider smartContractRegistrationInStateProvider, - ISmartContractExecutiveService smartContractExecutiveService) - { - _smartContractAddressService = smartContractAddressService; - _smartContractRegistrationProvider = smartContractRegistrationProvider; - _smartContractRegistrationInStateProvider = smartContractRegistrationInStateProvider; - _smartContractExecutiveService = smartContractExecutiveService; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public override Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return Task.FromResult(InterestedEvent); - public override Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return Task.FromResult(InterestedEvent); + var address = _smartContractAddressService.GetZeroSmartContractAddress(); + if (address == null) return null; - var address = _smartContractAddressService.GetZeroSmartContractAddress(); - if (address == null) return null; + InterestedEvent = GetInterestedEvent(address); - InterestedEvent = GetInterestedEvent(address); + return Task.FromResult(InterestedEvent); + } - return Task.FromResult(InterestedEvent); - } + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var eventData = new CodeUpdated(); + eventData.MergeFrom(logEvent); - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + var chainContext = new ChainContext { - var eventData = new CodeUpdated(); - eventData.MergeFrom(logEvent); + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var smartContractRegistration = + await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext, + eventData.Address); + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, eventData.Address, + smartContractRegistration); + _smartContractExecutiveService.CleanExecutive(eventData.Address); - var chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - var smartContractRegistration = - await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext, - eventData.Address); - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, eventData.Address, - smartContractRegistration); - _smartContractExecutiveService.CleanExecutive(eventData.Address); - - Logger.LogDebug($"Updated contract {eventData}"); - } + Logger.LogDebug($"Updated contract {eventData}"); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/ContractDeployedLogEventProcessor.cs b/src/AElf.Kernel.SmartContractExecution/Application/ContractDeployedLogEventProcessor.cs index 8f5343c65f..d066000542 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/ContractDeployedLogEventProcessor.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/ContractDeployedLogEventProcessor.cs @@ -1,74 +1,73 @@ using System.Threading.Tasks; -using AElf.Standards.ACS0; +using AElf.CSharp.Core.Extension; +using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using AElf.CSharp.Core.Extension; -using AElf.Kernel.Infrastructure; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public class ContractDeployedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor { - public class ContractDeployedLogEventProcessor : LogEventProcessorBase, IBlockAcceptedLogEventProcessor + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + + public ContractDeployedLogEventProcessor(ISmartContractAddressService smartContractAddressService, + ISmartContractRegistrationProvider smartContractRegistrationProvider, + ISmartContractRegistrationInStateProvider smartContractRegistrationInStateProvider, + ISmartContractExecutiveService smartContractExecutiveService) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; - private readonly ISmartContractExecutiveService _smartContractExecutiveService; + _smartContractAddressService = smartContractAddressService; + _smartContractRegistrationProvider = smartContractRegistrationProvider; + _smartContractRegistrationInStateProvider = smartContractRegistrationInStateProvider; + _smartContractExecutiveService = smartContractExecutiveService; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public ContractDeployedLogEventProcessor(ISmartContractAddressService smartContractAddressService, - ISmartContractRegistrationProvider smartContractRegistrationProvider, - ISmartContractRegistrationInStateProvider smartContractRegistrationInStateProvider, - ISmartContractExecutiveService smartContractExecutiveService) - { - _smartContractAddressService = smartContractAddressService; - _smartContractRegistrationProvider = smartContractRegistrationProvider; - _smartContractRegistrationInStateProvider = smartContractRegistrationInStateProvider; - _smartContractExecutiveService = smartContractExecutiveService; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } - - public override Task GetInterestedEventAsync(IChainContext chainContext) - { - if (InterestedEvent != null) - return Task.FromResult(InterestedEvent); + public override Task GetInterestedEventAsync(IChainContext chainContext) + { + if (InterestedEvent != null) + return Task.FromResult(InterestedEvent); - var address = _smartContractAddressService.GetZeroSmartContractAddress(); - if (address == null) return null; - - InterestedEvent = GetInterestedEvent(address); + var address = _smartContractAddressService.GetZeroSmartContractAddress(); + if (address == null) return null; - return Task.FromResult(InterestedEvent); - } + InterestedEvent = GetInterestedEvent(address); - protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + return Task.FromResult(InterestedEvent); + } + + protected override async Task ProcessLogEventAsync(Block block, LogEvent logEvent) + { + var eventData = new ContractDeployed(); + eventData.MergeFrom(logEvent); + + var chainContext = new ChainContext { - var eventData = new ContractDeployed(); - eventData.MergeFrom(logEvent); + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + + var smartContractRegistration = + await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext + , eventData.Address); - var chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - - var smartContractRegistration = - await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext - , eventData.Address); + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, eventData.Address, + smartContractRegistration); + if (block.Height > AElfConstants.GenesisBlockHeight) + _smartContractExecutiveService.CleanExecutive(eventData.Address); - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, eventData.Address, - smartContractRegistration); - if (block.Height > AElfConstants.GenesisBlockHeight) - _smartContractExecutiveService.CleanExecutive(eventData.Address); + if (eventData.Name != null) + await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, eventData.Name.ToStorageKey(), + eventData.Address); - if (eventData.Name != null) - await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, eventData.Name.ToStorageKey(), - eventData.Address); - - Logger.LogDebug($"Deployed contract {eventData}"); - } + Logger.LogDebug($"Deployed contract {eventData}"); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/IBlockAttachService.cs b/src/AElf.Kernel.SmartContractExecution/Application/IBlockAttachService.cs index b42764b0d0..0686f46073 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/IBlockAttachService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/IBlockAttachService.cs @@ -1,74 +1,70 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public interface IBlockAttachService +{ + Task AttachBlockAsync(Block block); +} + +public class BlockAttachService : IBlockAttachService, ITransientDependency { - public interface IBlockAttachService + private readonly IBlockchainExecutingService _blockchainExecutingService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; + private readonly IChainBlockLinkService _chainBlockLinkService; + + public BlockAttachService(IBlockchainService blockchainService, + IBlockchainExecutingService blockchainExecutingService, + IChainBlockLinkService chainBlockLinkService, + IBlockExecutionResultProcessingService blockExecutionResultProcessingService) { - Task AttachBlockAsync(Block block); + _blockchainService = blockchainService; + _blockchainExecutingService = blockchainExecutingService; + _chainBlockLinkService = chainBlockLinkService; + _blockExecutionResultProcessingService = blockExecutionResultProcessingService; + + Logger = NullLogger.Instance; } - public class BlockAttachService : IBlockAttachService, ITransientDependency + public ILogger Logger { get; set; } + + public async Task AttachBlockAsync(Block block) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockchainExecutingService _blockchainExecutingService; - private readonly IChainBlockLinkService _chainBlockLinkService; - private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; - - public ILogger Logger { get; set; } + var chain = await _blockchainService.GetChainAsync(); - public BlockAttachService(IBlockchainService blockchainService, - IBlockchainExecutingService blockchainExecutingService, - IChainBlockLinkService chainBlockLinkService, - IBlockExecutionResultProcessingService blockExecutionResultProcessingService) + var status = await _blockchainService.AttachBlockToChainAsync(chain, block); + if (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound)) { - _blockchainService = blockchainService; - _blockchainExecutingService = blockchainExecutingService; - _chainBlockLinkService = chainBlockLinkService; - _blockExecutionResultProcessingService = blockExecutionResultProcessingService; - - Logger = NullLogger.Instance; + Logger.LogDebug($"Try to attach to chain but the status is {status}."); + return; } - public async Task AttachBlockAsync(Block block) - { - var chain = await _blockchainService.GetChainAsync(); + var notExecutedChainBlockLinks = + await _chainBlockLinkService.GetNotExecutedChainBlockLinksAsync(chain.LongestChainHash); + var notExecutedBlocks = + await _blockchainService.GetBlocksAsync(notExecutedChainBlockLinks.Select(l => l.BlockHash)); - var status = await _blockchainService.AttachBlockToChainAsync(chain, block); - if (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound)) - { - Logger.LogDebug($"Try to attach to chain but the status is {status}."); - return; - } - - var notExecutedChainBlockLinks = - await _chainBlockLinkService.GetNotExecutedChainBlockLinksAsync(chain.LongestChainHash); - var notExecutedBlocks = - await _blockchainService.GetBlocksAsync(notExecutedChainBlockLinks.Select(l => l.BlockHash)); - - var executionResult = new BlockExecutionResult(); - try - { - executionResult = await _blockchainExecutingService.ExecuteBlocksAsync(notExecutedBlocks); - } - catch (Exception e) - { - Logger.LogError(e, "Block execute fails."); - throw; - } - finally - { - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); - } + var executionResult = new BlockExecutionResult(); + try + { + executionResult = await _blockchainExecutingService.ExecuteBlocksAsync(notExecutedBlocks); + } + catch (Exception e) + { + Logger.LogError(e, "Block execute fails."); + throw; + } + finally + { + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); } } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutingService.cs index 06e94bcc75..3280991825 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutingService.cs @@ -4,13 +4,13 @@ using AElf.Kernel.Blockchain; using AElf.Types; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public interface IBlockExecutingService { - public interface IBlockExecutingService - { - Task ExecuteBlockAsync(BlockHeader blockHeader, List nonCancellableTransactions); + Task ExecuteBlockAsync(BlockHeader blockHeader, List nonCancellableTransactions); - Task ExecuteBlockAsync(BlockHeader blockHeader, IEnumerable nonCancellableTransactions, - IEnumerable cancellableTransactions, CancellationToken cancellationToken); - } + Task ExecuteBlockAsync(BlockHeader blockHeader, + IEnumerable nonCancellableTransactions, + IEnumerable cancellableTransactions, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutionResultProcessingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutionResultProcessingService.cs index 8fcfc1540b..ac697c51f3 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutionResultProcessingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/IBlockExecutionResultProcessingService.cs @@ -1,9 +1,8 @@ using System.Threading.Tasks; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public interface IBlockExecutionResultProcessingService { - public interface IBlockExecutionResultProcessingService - { - Task ProcessBlockExecutionResultAsync(Chain chain, BlockExecutionResult blockExecutionResult); - } + Task ProcessBlockExecutionResultAsync(Chain chain, BlockExecutionResult blockExecutionResult); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/IBlockchainExecutingService.cs b/src/AElf.Kernel.SmartContractExecution/Application/IBlockchainExecutingService.cs index 4261aa5880..953fe342da 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/IBlockchainExecutingService.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/IBlockchainExecutingService.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public interface IBlockchainExecutingService { - public interface IBlockchainExecutingService - { - Task ExecuteBlocksAsync(IEnumerable blocks); - } + Task ExecuteBlocksAsync(IEnumerable blocks); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Application/SmartContractRegistrationInStateProvider.cs b/src/AElf.Kernel.SmartContractExecution/Application/SmartContractRegistrationInStateProvider.cs index 6ccc0663f8..4a3461621f 100644 --- a/src/AElf.Kernel.SmartContractExecution/Application/SmartContractRegistrationInStateProvider.cs +++ b/src/AElf.Kernel.SmartContractExecution/Application/SmartContractRegistrationInStateProvider.cs @@ -1,43 +1,42 @@ -using System.ComponentModel; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public interface ISmartContractRegistrationInStateProvider +{ + Task GetSmartContractRegistrationAsync(IChainContext chainContext, Address address); +} + +public class SmartContractRegistrationInStateProvider : ISmartContractRegistrationInStateProvider { - public interface ISmartContractRegistrationInStateProvider + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + + public SmartContractRegistrationInStateProvider(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) { - Task GetSmartContractRegistrationAsync(IChainContext chainContext, Address address); + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; } - - public class SmartContractRegistrationInStateProvider : ISmartContractRegistrationInStateProvider - { - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - public SmartContractRegistrationInStateProvider(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) - { - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - } - - public async Task GetSmartContractRegistrationAsync(IChainContext chainContext,Address address) + public async Task GetSmartContractRegistrationAsync(IChainContext chainContext, + Address address) + { + var zeroAddress = _defaultContractZeroCodeProvider.ContractZeroAddress; + var tx = new Transaction { - var zeroAddress = _defaultContractZeroCodeProvider.ContractZeroAddress; - var tx = new Transaction - { - From = zeroAddress, - To = zeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), - Params = address.ToByteString() - }; + From = zeroAddress, + To = zeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), + Params = address.ToByteString() + }; - return await _transactionReadOnlyExecutionService.ExecuteAsync( - chainContext, tx, TimestampHelper.GetUtcNow(), false); - } + return await _transactionReadOnlyExecutionService.ExecuteAsync( + chainContext, tx, TimestampHelper.GetUtcNow(), false); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Events/BlocksExecutionSucceededEvent.cs b/src/AElf.Kernel.SmartContractExecution/Events/BlocksExecutionSucceededEvent.cs index 55f47a7379..533bb07c91 100644 --- a/src/AElf.Kernel.SmartContractExecution/Events/BlocksExecutionSucceededEvent.cs +++ b/src/AElf.Kernel.SmartContractExecution/Events/BlocksExecutionSucceededEvent.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using AElf.Kernel.Blockchain; -namespace AElf.Kernel.SmartContractExecution.Events +namespace AElf.Kernel.SmartContractExecution.Events; + +public class BlocksExecutionSucceededEvent { - public class BlocksExecutionSucceededEvent - { - public List BlockExecutedSets { get; set; } - } + public List BlockExecutedSets { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/ExecutionObserverThresholdConfigurationProcessor.cs b/src/AElf.Kernel.SmartContractExecution/ExecutionObserverThresholdConfigurationProcessor.cs index 73fee8816a..a9a6169f27 100644 --- a/src/AElf.Kernel.SmartContractExecution/ExecutionObserverThresholdConfigurationProcessor.cs +++ b/src/AElf.Kernel.SmartContractExecution/ExecutionObserverThresholdConfigurationProcessor.cs @@ -4,30 +4,29 @@ using AElf.Kernel.SmartContract.Application; using Google.Protobuf; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +public class ExecutionObserverThresholdConfigurationProcessor : IConfigurationProcessor { - public class ExecutionObserverThresholdConfigurationProcessor : IConfigurationProcessor + private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; + + public ExecutionObserverThresholdConfigurationProcessor( + IExecutionObserverThresholdProvider executionObserverThresholdProvider) { - private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; + _executionObserverThresholdProvider = executionObserverThresholdProvider; + } - public ExecutionObserverThresholdConfigurationProcessor( - IExecutionObserverThresholdProvider executionObserverThresholdProvider) - { - _executionObserverThresholdProvider = executionObserverThresholdProvider; - } + public string ConfigurationName => "ExecutionObserverThreshold"; - public string ConfigurationName => "ExecutionObserverThreshold"; - - public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) - { - var executionObserverBranchThreshold = new ExecutionObserverThreshold(); - executionObserverBranchThreshold.MergeFrom(byteString); - await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex, - executionObserverBranchThreshold); - } - } - - public partial class ExecutionObserverThreshold : IExecutionObserverThreshold + public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) { + var executionObserverBranchThreshold = new ExecutionObserverThreshold(); + executionObserverBranchThreshold.MergeFrom(byteString); + await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex, + executionObserverBranchThreshold); } +} + +public partial class ExecutionObserverThreshold : IExecutionObserverThreshold +{ } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/Extensions/BlockchainServiceExtensions.cs b/src/AElf.Kernel.SmartContractExecution/Extensions/BlockchainServiceExtensions.cs index 9f88b56cff..0d35970d9c 100644 --- a/src/AElf.Kernel.SmartContractExecution/Extensions/BlockchainServiceExtensions.cs +++ b/src/AElf.Kernel.SmartContractExecution/Extensions/BlockchainServiceExtensions.cs @@ -1,21 +1,19 @@ -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Types; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +public static class BlockchainServiceExtensions { - public static class BlockchainServiceExtensions + public static async Task> GetBlocksAsync(this IBlockchainService blockchainService, + IEnumerable blockHashes) { - public static async Task> GetBlocksAsync(this IBlockchainService blockchainService, - IEnumerable blockHashes) - { - var list = blockHashes - .Select(async blockHash => await blockchainService.GetBlockByHashAsync(blockHash)); + var list = blockHashes + .Select(async blockHash => await blockchainService.GetBlockByHashAsync(blockHash)); - return (await Task.WhenAll(list)).ToList(); - } + return (await Task.WhenAll(list)).ToList(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/SmartContractExecutionAElfModule.cs b/src/AElf.Kernel.SmartContractExecution/SmartContractExecutionAElfModule.cs index 9c72cf7467..f037e8a2b2 100644 --- a/src/AElf.Kernel.SmartContractExecution/SmartContractExecutionAElfModule.cs +++ b/src/AElf.Kernel.SmartContractExecution/SmartContractExecutionAElfModule.cs @@ -7,24 +7,23 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +[DependsOn(typeof(SmartContractAElfModule))] +public class SmartContractExecutionAElfModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule))] - public class SmartContractExecutionAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddTransient(typeof(IConfigurationProcessor), - typeof(ExecutionObserverThresholdConfigurationProcessor)); - context.Services.AddTransient(typeof(IConfigurationProcessor), - typeof(StateLimitSizeConfigurationProcessor)); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddTransient(typeof(IConfigurationProcessor), + typeof(ExecutionObserverThresholdConfigurationProcessor)); + context.Services.AddTransient(typeof(IConfigurationProcessor), + typeof(StateLimitSizeConfigurationProcessor)); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - //var executorType = context.ServiceProvider.GetService>().Value.ExecutorType; - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + //var executorType = context.ServiceProvider.GetService>().Value.ExecutorType; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContractExecution/StateLimitSizeConfigurationProcessor.cs b/src/AElf.Kernel.SmartContractExecution/StateLimitSizeConfigurationProcessor.cs index f4d9092efe..b18a15a9e3 100644 --- a/src/AElf.Kernel.SmartContractExecution/StateLimitSizeConfigurationProcessor.cs +++ b/src/AElf.Kernel.SmartContractExecution/StateLimitSizeConfigurationProcessor.cs @@ -4,23 +4,22 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +public class StateLimitSizeConfigurationProcessor : IConfigurationProcessor { - public class StateLimitSizeConfigurationProcessor : IConfigurationProcessor + private readonly IStateSizeLimitProvider _stateSizeLimitProvider; + + public StateLimitSizeConfigurationProcessor(IStateSizeLimitProvider stateSizeLimitProvider) { - private readonly IStateSizeLimitProvider _stateSizeLimitProvider; + _stateSizeLimitProvider = stateSizeLimitProvider; + } - public StateLimitSizeConfigurationProcessor(IStateSizeLimitProvider stateSizeLimitProvider) - { - _stateSizeLimitProvider = stateSizeLimitProvider; - } + public string ConfigurationName => "StateSizeLimit"; - public string ConfigurationName => "StateSizeLimit"; - - public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) - { - var limit = Int32Value.Parser.ParseFrom(byteString).Value; - await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, limit); - } + public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) + { + var limit = Int32Value.Parser.ParseFrom(byteString).Value; + await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, limit); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Token/AElf.Kernel.Token.csproj b/src/AElf.Kernel.Token/AElf.Kernel.Token.csproj index 386d43414b..0ed272fad3 100644 --- a/src/AElf.Kernel.Token/AElf.Kernel.Token.csproj +++ b/src/AElf.Kernel.Token/AElf.Kernel.Token.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,8 +9,8 @@ - - + + diff --git a/src/AElf.Kernel.Token/ITokenContractInitializationDataProvider.cs b/src/AElf.Kernel.Token/ITokenContractInitializationDataProvider.cs index d5ac72ffe5..4856db16da 100644 --- a/src/AElf.Kernel.Token/ITokenContractInitializationDataProvider.cs +++ b/src/AElf.Kernel.Token/ITokenContractInitializationDataProvider.cs @@ -1,33 +1,31 @@ -using System; using System.Collections.Generic; using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.Token +namespace AElf.Kernel.Token; + +/// +/// Add this interface because the initialization logic of Token Contract +/// are different from Main Chain, Side Chain and test cases. +/// +public interface ITokenContractInitializationDataProvider { - /// - /// Add this interface because the initialization logic of Token Contract - /// are different from Main Chain, Side Chain and test cases. - /// - public interface ITokenContractInitializationDataProvider - { - TokenContractInitializationData GetContractInitializationData(); - } + TokenContractInitializationData GetContractInitializationData(); +} - public class TokenContractInitializationData - { - public ByteString NativeTokenInfoData { get; set; } - public ByteString ResourceTokenListData { get; set; } - public Dictionary ResourceAmount { get; set; } - public Dictionary RegisteredOtherTokenContractAddresses { get; set; } - public Address Creator { get; set; } - public ByteString PrimaryTokenInfoData { get; set; } - public List TokenInitialIssueList { get; set; } - } +public class TokenContractInitializationData +{ + public ByteString NativeTokenInfoData { get; set; } + public ByteString ResourceTokenListData { get; set; } + public Dictionary ResourceAmount { get; set; } + public Dictionary RegisteredOtherTokenContractAddresses { get; set; } + public Address Creator { get; set; } + public ByteString PrimaryTokenInfoData { get; set; } + public List TokenInitialIssueList { get; set; } +} - public class TokenInitialIssue - { - public Address Address { get; set; } - public long Amount { get; set; } - } +public class TokenInitialIssue +{ + public Address Address { get; set; } + public long Amount { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs index dc5d5d2e08..7fa7bd32b6 100644 --- a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs +++ b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs @@ -6,144 +6,139 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Token +namespace AElf.Kernel.Token; + +public class TokenContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class TokenContractInitializationProvider : IContractInitializationProvider, ITransientDependency + private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + + public TokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) { - public Hash SystemSmartContractName { get; } = TokenSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.MultiToken"; + _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; + } - private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + public Hash SystemSmartContractName { get; } = TokenSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.MultiToken"; - public TokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) - { - _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; - } + public virtual List GetInitializeMethodList(byte[] contractCode) + { + var methodList = new List(); + var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); - public virtual List GetInitializeMethodList(byte[] contractCode) + // For the main chain, we use the economic contract to initialize the token contract. + // So no initialization methods are required in here. + // But for the side chain, which has no economic contract, we need initialize token contract. + if (initializationData != null) { - var methodList = new List(); - var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); + var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); + var resourceTokenList = + TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); - // For the main chain, we use the economic contract to initialize the token contract. - // So no initialization methods are required in here. - // But for the side chain, which has no economic contract, we need initialize token contract. - if (initializationData != null) + // native token + methodList.Add(new ContractInitializationMethodCall { - var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); - var resourceTokenList = - TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); + MethodName = nameof(TokenContractContainer.TokenContractStub.Create), + Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + }); - // native token + // resource token + foreach (var resourceTokenInfo in resourceTokenList.Value) methodList.Add(new ContractInitializationMethodCall { MethodName = nameof(TokenContractContainer.TokenContractStub.Create), - Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() }); - // resource token - foreach (var resourceTokenInfo in resourceTokenList.Value) - { - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Create), - Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() - }); - } + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), + Params = new Empty().ToByteString() + }); + + if (initializationData.PrimaryTokenInfoData != null) + { + // primary token + var chainPrimaryTokenInfo = + TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), - Params = new Empty().ToByteString() + MethodName = nameof(TokenContractContainer.TokenContractStub.Create), + Params = GenerateTokenCreateInput(chainPrimaryTokenInfo, initializationData.Creator) + .ToByteString() }); - if (initializationData.PrimaryTokenInfoData != null) - { - // primary token - var chainPrimaryTokenInfo = - TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); - - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Create), - Params = GenerateTokenCreateInput(chainPrimaryTokenInfo, initializationData.Creator) - .ToByteString() - }); - - foreach (var issueStuff in initializationData.TokenInitialIssueList) - { - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), - Params = new IssueInput - { - Symbol = chainPrimaryTokenInfo.Symbol, - Amount = issueStuff.Amount, - Memo = "Initial issue", - To = issueStuff.Address - }.ToByteString() - }); - } - + foreach (var issueStuff in initializationData.TokenInitialIssueList) methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput + MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), + Params = new IssueInput { - Symbol = chainPrimaryTokenInfo.Symbol + Symbol = chainPrimaryTokenInfo.Symbol, + Amount = issueStuff.Amount, + Memo = "Initial issue", + To = issueStuff.Address }.ToByteString() }); - } - else - { - // set primary token with native token - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = nativeTokenInfo.Symbol - }.ToByteString() - }); - } methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), - Params = new InitializeFromParentChainInput + MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - ResourceAmount = {initializationData.ResourceAmount}, - RegisteredOtherTokenContractAddresses = - { - initializationData.RegisteredOtherTokenContractAddresses - }, - Creator = initializationData.Creator + Symbol = chainPrimaryTokenInfo.Symbol }.ToByteString() }); - + } + else + { + // set primary token with native token methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController), - Params = ByteString.Empty + MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput + { + Symbol = nativeTokenInfo.Symbol + }.ToByteString() }); } - return methodList; - } + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), + Params = new InitializeFromParentChainInput + { + ResourceAmount = { initializationData.ResourceAmount }, + RegisteredOtherTokenContractAddresses = + { + initializationData.RegisteredOtherTokenContractAddresses + }, + Creator = initializationData.Creator + }.ToByteString() + }); - private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo, Address issuer = null) - { - return new CreateInput + methodList.Add(new ContractInitializationMethodCall { - Decimals = tokenInfo.Decimals, - IssueChainId = tokenInfo.IssueChainId, - Issuer = issuer ?? tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - Symbol = tokenInfo.Symbol, - TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply - }; + MethodName = nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController), + Params = ByteString.Empty + }); } + + return methodList; + } + + private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo, Address issuer = null) + { + return new CreateInput + { + Decimals = tokenInfo.Decimals, + IssueChainId = tokenInfo.IssueChainId, + Issuer = issuer ?? tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + Symbol = tokenInfo.Symbol, + TokenName = tokenInfo.TokenName, + TotalSupply = tokenInfo.TotalSupply + }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Token/TokenKernelAElfModule.cs b/src/AElf.Kernel.Token/TokenKernelAElfModule.cs index 8757762f97..ea44629f1b 100644 --- a/src/AElf.Kernel.Token/TokenKernelAElfModule.cs +++ b/src/AElf.Kernel.Token/TokenKernelAElfModule.cs @@ -1,8 +1,7 @@ using AElf.Modularity; -namespace AElf.Kernel.Token +namespace AElf.Kernel.Token; + +public class TokenKernelAElfModule : AElfModule { - public class TokenKernelAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/src/AElf.Kernel.Token/TokenSmartContractAddressNameProvider.cs b/src/AElf.Kernel.Token/TokenSmartContractAddressNameProvider.cs index da6b74977a..efaddb1730 100644 --- a/src/AElf.Kernel.Token/TokenSmartContractAddressNameProvider.cs +++ b/src/AElf.Kernel.Token/TokenSmartContractAddressNameProvider.cs @@ -3,14 +3,13 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Token +namespace AElf.Kernel.Token; + +public class TokenSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TokenSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Token"); + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.Token"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/AElf.Kernel.TransactionPool.csproj b/src/AElf.Kernel.TransactionPool/AElf.Kernel.TransactionPool.csproj index 4758f86343..59b7350b5d 100644 --- a/src/AElf.Kernel.TransactionPool/AElf.Kernel.TransactionPool.csproj +++ b/src/AElf.Kernel.TransactionPool/AElf.Kernel.TransactionPool.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,7 +10,7 @@ - + diff --git a/src/AElf.Kernel.TransactionPool/Application/BlockchainServiceExtensions.cs b/src/AElf.Kernel.TransactionPool/Application/BlockchainServiceExtensions.cs index b013b86d56..94b4b08bbc 100644 --- a/src/AElf.Kernel.TransactionPool/Application/BlockchainServiceExtensions.cs +++ b/src/AElf.Kernel.TransactionPool/Application/BlockchainServiceExtensions.cs @@ -3,26 +3,25 @@ using AElf.Kernel.Blockchain.Application; using AElf.Types; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public static class BlockchainServiceExtensions { - public static class BlockchainServiceExtensions + public static async Task> GetBlockIndexesAsync(this IBlockchainService blockchainService, + long firstHeight, Hash bestChainHash, long bestChainHeight) { - public static async Task> GetBlockIndexesAsync(this IBlockchainService blockchainService, - long firstHeight, Hash bestChainHash, long bestChainHeight) - { - if (firstHeight <= 0) - return new List(); - - var indexCount = bestChainHeight - firstHeight; - var blockIndexes = await blockchainService.GetReversedBlockIndexes(bestChainHash, (int) indexCount); + if (firstHeight <= 0) + return new List(); - blockIndexes.Add(new BlockIndex - { - BlockHash = bestChainHash, - BlockHeight = bestChainHeight - }); + var indexCount = bestChainHeight - firstHeight; + var blockIndexes = await blockchainService.GetReversedBlockIndexes(bestChainHash, (int)indexCount); + + blockIndexes.Add(new BlockIndex + { + BlockHash = bestChainHash, + BlockHeight = bestChainHeight + }); - return blockIndexes; - } + return blockIndexes; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Application/ExecutableTransactionSet.cs b/src/AElf.Kernel.TransactionPool/Application/ExecutableTransactionSet.cs index 88da41d709..f426aed81f 100644 --- a/src/AElf.Kernel.TransactionPool/Application/ExecutableTransactionSet.cs +++ b/src/AElf.Kernel.TransactionPool/Application/ExecutableTransactionSet.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public class ExecutableTransactionSet { - public class ExecutableTransactionSet - { - public Hash PreviousBlockHash { get; set; } - public long PreviousBlockHeight { get; set; } - public List Transactions { get; set; } = new List(); - } + public Hash PreviousBlockHash { get; set; } + public long PreviousBlockHeight { get; set; } + public List Transactions { get; set; } = new(); } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Application/ITransactionPoolService.cs b/src/AElf.Kernel.TransactionPool/Application/ITransactionPoolService.cs index 56043890ee..052d70724f 100644 --- a/src/AElf.Kernel.TransactionPool/Application/ITransactionPoolService.cs +++ b/src/AElf.Kernel.TransactionPool/Application/ITransactionPoolService.cs @@ -3,62 +3,61 @@ using AElf.Kernel.TransactionPool.Infrastructure; using AElf.Types; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public interface ITransactionPoolService +{ + Task AddTransactionsAsync(IEnumerable transactions); + Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight); + Task UpdateTransactionPoolByLibAsync(long libHeight); + Task CleanByTransactionIdsAsync(IEnumerable transactionIds); + Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount = 0); + Task GetQueuedTransactionAsync(Hash transactionId); + Task GetTransactionPoolStatusAsync(); +} + +public class TransactionPoolService : ITransactionPoolService { - public interface ITransactionPoolService + private readonly ITxHub _txHub; + + public TransactionPoolService(ITxHub txHub) { - Task AddTransactionsAsync(IEnumerable transactions); - Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight); - Task UpdateTransactionPoolByLibAsync(long libHeight); - Task CleanByTransactionIdsAsync(IEnumerable transactionIds); - Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount = 0); - Task GetQueuedTransactionAsync(Hash transactionId); - Task GetTransactionPoolStatusAsync(); + _txHub = txHub; } - public class TransactionPoolService : ITransactionPoolService + public async Task AddTransactionsAsync(IEnumerable transactions) { - private readonly ITxHub _txHub; + await _txHub.AddTransactionsAsync(transactions); + } - public TransactionPoolService(ITxHub txHub) - { - _txHub = txHub; - } + public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) + { + await _txHub.UpdateTransactionPoolByBestChainAsync(bestChainHash, bestChainHeight); + } - public async Task AddTransactionsAsync(IEnumerable transactions) - { - await _txHub.AddTransactionsAsync(transactions); - } + public async Task UpdateTransactionPoolByLibAsync(long libHeight) + { + await _txHub.CleanByHeightAsync(libHeight); + } - public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) - { - await _txHub.UpdateTransactionPoolByBestChainAsync(bestChainHash, bestChainHeight); - } - - public async Task UpdateTransactionPoolByLibAsync(long libHeight) - { - await _txHub.CleanByHeightAsync(libHeight); - } - - public async Task CleanByTransactionIdsAsync(IEnumerable transactionIds) - { - await _txHub.CleanByTransactionIdsAsync(transactionIds); - } - - public async Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount = 0) - { - return await _txHub.GetExecutableTransactionSetAsync(blockHash, transactionCount); - } - - public async Task GetQueuedTransactionAsync(Hash transactionId) - { - return await _txHub.GetQueuedTransactionAsync(transactionId); - } + public async Task CleanByTransactionIdsAsync(IEnumerable transactionIds) + { + await _txHub.CleanByTransactionIdsAsync(transactionIds); + } + + public async Task GetExecutableTransactionSetAsync(Hash blockHash, + int transactionCount = 0) + { + return await _txHub.GetExecutableTransactionSetAsync(blockHash, transactionCount); + } - public async Task GetTransactionPoolStatusAsync() - { - return await _txHub.GetTransactionPoolStatusAsync(); - } + public async Task GetQueuedTransactionAsync(Hash transactionId) + { + return await _txHub.GetQueuedTransactionAsync(transactionId); + } + public async Task GetTransactionPoolStatusAsync() + { + return await _txHub.GetTransactionPoolStatusAsync(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Application/ITransactionValidationService.cs b/src/AElf.Kernel.TransactionPool/Application/ITransactionValidationService.cs index a578815adb..d8816615a7 100644 --- a/src/AElf.Kernel.TransactionPool/Application/ITransactionValidationService.cs +++ b/src/AElf.Kernel.TransactionPool/Application/ITransactionValidationService.cs @@ -1,23 +1,22 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public interface ITransactionValidationService { - public interface ITransactionValidationService - { - /// - /// Validate tx while this tx is trying to add to tx hub. - /// - /// - /// - Task ValidateTransactionWhileCollectingAsync(IChainContext chainContext, Transaction transaction); + /// + /// Validate tx while this tx is trying to add to tx hub. + /// + /// + /// + Task ValidateTransactionWhileCollectingAsync(IChainContext chainContext, Transaction transaction); - /// - /// Validate tx while this tx is already contained in one block - /// received from network (produced by others). - /// - /// - /// - Task ValidateTransactionWhileSyncingAsync(Transaction transaction); - } + /// + /// Validate tx while this tx is already contained in one block + /// received from network (produced by others). + /// + /// + /// + Task ValidateTransactionWhileSyncingAsync(Transaction transaction); } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Application/TransactionPoolStatus.cs b/src/AElf.Kernel.TransactionPool/Application/TransactionPoolStatus.cs index 7805ddf676..b586d96d1c 100644 --- a/src/AElf.Kernel.TransactionPool/Application/TransactionPoolStatus.cs +++ b/src/AElf.Kernel.TransactionPool/Application/TransactionPoolStatus.cs @@ -1,8 +1,7 @@ -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public class TransactionPoolStatus { - public class TransactionPoolStatus - { - public int AllTransactionCount { get; set; } - public int ValidatedTransactionCount { get; set; } - } + public int AllTransactionCount { get; set; } + public int ValidatedTransactionCount { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Application/TransactionValidationService.cs b/src/AElf.Kernel.TransactionPool/Application/TransactionValidationService.cs index 44ddb144fc..fc33b15bbc 100644 --- a/src/AElf.Kernel.TransactionPool/Application/TransactionValidationService.cs +++ b/src/AElf.Kernel.TransactionPool/Application/TransactionValidationService.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Txn.Application; @@ -8,57 +7,56 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public class TransactionValidationService : ITransactionValidationService, ITransientDependency { - public class TransactionValidationService : ITransactionValidationService, ITransientDependency - { - private readonly IEnumerable _transactionValidationProviders; - private readonly IBlockchainService _blockchainService; + private readonly IBlockchainService _blockchainService; + private readonly IEnumerable _transactionValidationProviders; - public ILogger Logger { get; set; } + public TransactionValidationService( + IEnumerable transactionValidationProviders, + IBlockchainService blockchainService) + { + _transactionValidationProviders = transactionValidationProviders; + _blockchainService = blockchainService; - public TransactionValidationService( - IEnumerable transactionValidationProviders, - IBlockchainService blockchainService) - { - _transactionValidationProviders = transactionValidationProviders; - _blockchainService = blockchainService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - /// - /// Validate txs before they enter tx hub. - /// - /// - /// - /// - public async Task ValidateTransactionWhileCollectingAsync(IChainContext chainContext, - Transaction transaction) + /// + /// Validate txs before they enter tx hub. + /// + /// + /// + /// + public async Task ValidateTransactionWhileCollectingAsync(IChainContext chainContext, + Transaction transaction) + { + foreach (var provider in _transactionValidationProviders) { - foreach (var provider in _transactionValidationProviders) - { - if (await provider.ValidateTransactionAsync(transaction, chainContext)) continue; - Logger.LogDebug( - $"[ValidateTransactionWhileCollectingAsync]Transaction {transaction.GetHash()} validation failed in {provider.GetType()}"); - return false; - } - - return true; + if (await provider.ValidateTransactionAsync(transaction, chainContext)) continue; + Logger.LogDebug( + $"[ValidateTransactionWhileCollectingAsync]Transaction {transaction.GetHash()} validation failed in {provider.GetType()}"); + return false; } - public async Task ValidateTransactionWhileSyncingAsync(Transaction transaction) - { - foreach (var provider in _transactionValidationProviders) - { - if (!provider.ValidateWhileSyncing || - await provider.ValidateTransactionAsync(transaction)) continue; - Logger.LogDebug( - $"[ValidateTransactionWhileSyncingAsync]Transaction {transaction.GetHash()} validation failed in {provider.GetType()}"); - return false; - } + return true; + } - return true; + public async Task ValidateTransactionWhileSyncingAsync(Transaction transaction) + { + foreach (var provider in _transactionValidationProviders) + { + if (!provider.ValidateWhileSyncing || + await provider.ValidateTransactionAsync(transaction)) continue; + Logger.LogDebug( + $"[ValidateTransactionWhileSyncingAsync]Transaction {transaction.GetHash()} validation failed in {provider.GetType()}"); + return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Events/TransactionAcceptedEvent.cs b/src/AElf.Kernel.TransactionPool/Events/TransactionAcceptedEvent.cs index 7a81e0675a..fef7137984 100644 --- a/src/AElf.Kernel.TransactionPool/Events/TransactionAcceptedEvent.cs +++ b/src/AElf.Kernel.TransactionPool/Events/TransactionAcceptedEvent.cs @@ -1,10 +1,9 @@ using AElf.Types; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionAcceptedEvent { - public class TransactionAcceptedEvent - { - public int ChainId { get; set; } - public Transaction Transaction { get; set; } - } + public int ChainId { get; set; } + public Transaction Transaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Events/TransactionExecutionValidationFailedEvent.cs b/src/AElf.Kernel.TransactionPool/Events/TransactionExecutionValidationFailedEvent.cs index 508deb4153..be1ede18e8 100644 --- a/src/AElf.Kernel.TransactionPool/Events/TransactionExecutionValidationFailedEvent.cs +++ b/src/AElf.Kernel.TransactionPool/Events/TransactionExecutionValidationFailedEvent.cs @@ -1,9 +1,8 @@ using AElf.Types; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionExecutionValidationFailedEvent { - public class TransactionExecutionValidationFailedEvent - { - public Hash TransactionId { get; set; } - } + public Hash TransactionId { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Events/TransactionsReceivedEvent.cs b/src/AElf.Kernel.TransactionPool/Events/TransactionsReceivedEvent.cs index 993b5b095e..8beede3c2a 100644 --- a/src/AElf.Kernel.TransactionPool/Events/TransactionsReceivedEvent.cs +++ b/src/AElf.Kernel.TransactionPool/Events/TransactionsReceivedEvent.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionsReceivedEvent { - public class TransactionsReceivedEvent - { - public IEnumerable Transactions { get; set; } - } + public IEnumerable Transactions { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Infrastructure/BasicTransactionValidationProvider.cs b/src/AElf.Kernel.TransactionPool/Infrastructure/BasicTransactionValidationProvider.cs index 38fd9b7022..256ee20c37 100644 --- a/src/AElf.Kernel.TransactionPool/Infrastructure/BasicTransactionValidationProvider.cs +++ b/src/AElf.Kernel.TransactionPool/Infrastructure/BasicTransactionValidationProvider.cs @@ -3,44 +3,43 @@ using AElf.Types; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class BasicTransactionValidationProvider : ITransactionValidationProvider { - public class BasicTransactionValidationProvider : ITransactionValidationProvider + public BasicTransactionValidationProvider() { - public bool ValidateWhileSyncing => true; - public ILocalEventBus LocalEventBus { get; set; } + LocalEventBus = NullLocalEventBus.Instance; + } - public BasicTransactionValidationProvider() - { - LocalEventBus = NullLocalEventBus.Instance; - } + public ILocalEventBus LocalEventBus { get; set; } + public bool ValidateWhileSyncing => true; - public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext) + public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext) + { + var transactionId = transaction.GetHash(); + if (!transaction.VerifySignature()) { - var transactionId = transaction.GetHash(); - if (!transaction.VerifySignature()) + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent { - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transactionId, - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = "Incorrect transaction signature." - }); - return false; - } + TransactionId = transactionId, + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = "Incorrect transaction signature." + }); + return false; + } - if (transaction.CalculateSize() > TransactionPoolConsts.TransactionSizeLimit) + if (transaction.CalculateSize() > TransactionPoolConsts.TransactionSizeLimit) + { + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent { - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transactionId, - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = "Transaction size exceeded." - }); - return false; - } - - return true; + TransactionId = transactionId, + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = "Transaction size exceeded." + }); + return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Infrastructure/ITxHub.cs b/src/AElf.Kernel.TransactionPool/Infrastructure/ITxHub.cs index fcd4341327..58bd2e0161 100644 --- a/src/AElf.Kernel.TransactionPool/Infrastructure/ITxHub.cs +++ b/src/AElf.Kernel.TransactionPool/Infrastructure/ITxHub.cs @@ -1,18 +1,17 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Types; using AElf.Kernel.TransactionPool.Application; +using AElf.Types; + +namespace AElf.Kernel.TransactionPool.Infrastructure; -namespace AElf.Kernel.TransactionPool.Infrastructure +public interface ITxHub { - public interface ITxHub - { - Task AddTransactionsAsync(IEnumerable transactions); - Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight); - Task CleanByTransactionIdsAsync(IEnumerable transactionIds); - Task CleanByHeightAsync(long height); - Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount); - Task GetQueuedTransactionAsync(Hash transactionId); - Task GetTransactionPoolStatusAsync(); - } + Task AddTransactionsAsync(IEnumerable transactions); + Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight); + Task CleanByTransactionIdsAsync(IEnumerable transactionIds); + Task CleanByHeightAsync(long height); + Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount); + Task GetQueuedTransactionAsync(Hash transactionId); + Task GetTransactionPoolStatusAsync(); } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionExecutionValidationProvider.cs b/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionExecutionValidationProvider.cs index 2c3d203322..5880661d6d 100644 --- a/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionExecutionValidationProvider.cs +++ b/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionExecutionValidationProvider.cs @@ -2,67 +2,66 @@ using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Txn.Application; using AElf.Types; using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class TransactionExecutionValidationProvider : ITransactionValidationProvider { - public class TransactionExecutionValidationProvider : ITransactionValidationProvider - { - private readonly IPlainTransactionExecutingService _plainTransactionExecutingService; - private readonly TransactionOptions _transactionOptions; - public ILocalEventBus LocalEventBus { get; set; } + private readonly IPlainTransactionExecutingService _plainTransactionExecutingService; + private readonly TransactionOptions _transactionOptions; - public TransactionExecutionValidationProvider( - IPlainTransactionExecutingService plainTransactionExecutingService, - IBlockchainService blockchainService, IOptionsMonitor transactionOptionsMonitor) - { - _plainTransactionExecutingService = plainTransactionExecutingService; - _transactionOptions = transactionOptionsMonitor.CurrentValue; - LocalEventBus = NullLocalEventBus.Instance; - } + public TransactionExecutionValidationProvider( + IPlainTransactionExecutingService plainTransactionExecutingService, + IBlockchainService blockchainService, IOptionsMonitor transactionOptionsMonitor) + { + _plainTransactionExecutingService = plainTransactionExecutingService; + _transactionOptions = transactionOptionsMonitor.CurrentValue; + LocalEventBus = NullLocalEventBus.Instance; + } - public bool ValidateWhileSyncing { get; } = false; + public ILocalEventBus LocalEventBus { get; set; } - public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext) - { - if (!_transactionOptions.EnableTransactionExecutionValidation) - return true; + public bool ValidateWhileSyncing { get; } = false; - var executionReturnSets = await _plainTransactionExecutingService.ExecuteAsync(new TransactionExecutingDto() - { - Transactions = new[] {transaction}, - BlockHeader = new BlockHeader - { - PreviousBlockHash = chainContext.BlockHash, - Height = chainContext.BlockHeight + 1, - Time = TimestampHelper.GetUtcNow(), - } - }, CancellationToken.None); + public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext) + { + if (!_transactionOptions.EnableTransactionExecutionValidation) + return true; - var executionValidationResult = - executionReturnSets.FirstOrDefault()?.Status == TransactionResultStatus.Mined; - if (!executionValidationResult) + var executionReturnSets = await _plainTransactionExecutingService.ExecuteAsync(new TransactionExecutingDto + { + Transactions = new[] { transaction }, + BlockHeader = new BlockHeader { - var transactionId = transaction.GetHash(); - // TODO: Consider to remove TransactionExecutionValidationFailedEvent. - await LocalEventBus.PublishAsync(new TransactionExecutionValidationFailedEvent - { - TransactionId = transactionId - }); - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transactionId, - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = executionReturnSets.FirstOrDefault()?.TransactionResult?.Error ?? string.Empty - }); + PreviousBlockHash = chainContext.BlockHash, + Height = chainContext.BlockHeight + 1, + Time = TimestampHelper.GetUtcNow() } + }, CancellationToken.None); - return executionValidationResult; + var executionValidationResult = + executionReturnSets.FirstOrDefault()?.Status == TransactionResultStatus.Mined; + if (!executionValidationResult) + { + var transactionId = transaction.GetHash(); + // TODO: Consider to remove TransactionExecutionValidationFailedEvent. + await LocalEventBus.PublishAsync(new TransactionExecutionValidationFailedEvent + { + TransactionId = transactionId + }); + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent + { + TransactionId = transactionId, + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = executionReturnSets.FirstOrDefault()?.TransactionResult?.Error ?? string.Empty + }); } + + return executionValidationResult; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionMethodValidationProvider.cs b/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionMethodValidationProvider.cs index 7e11fdbb76..ba4a640c01 100644 --- a/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionMethodValidationProvider.cs +++ b/src/AElf.Kernel.TransactionPool/Infrastructure/TransactionMethodValidationProvider.cs @@ -4,34 +4,33 @@ using AElf.Types; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class TransactionMethodValidationProvider : ITransactionValidationProvider { - public class TransactionMethodValidationProvider : ITransactionValidationProvider + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + + public TransactionMethodValidationProvider(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) { - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - public ILocalEventBus LocalEventBus { get; set; } + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + LocalEventBus = NullLocalEventBus.Instance; + } - public TransactionMethodValidationProvider(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) - { - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILocalEventBus LocalEventBus { get; set; } - public bool ValidateWhileSyncing { get; } = false; - public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext = null) - { - var isView = await _transactionReadOnlyExecutionService.IsViewTransactionAsync(chainContext, transaction); - if (isView) + public bool ValidateWhileSyncing { get; } = false; + + public async Task ValidateTransactionAsync(Transaction transaction, IChainContext chainContext = null) + { + var isView = await _transactionReadOnlyExecutionService.IsViewTransactionAsync(chainContext, transaction); + if (isView) + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent { - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transaction.GetHash(), - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = "View transaction is not allowed." - }); - } + TransactionId = transaction.GetHash(), + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = "View transaction is not allowed." + }); - return !isView; - } + return !isView; } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/Infrastructure/TxHub.cs b/src/AElf.Kernel.TransactionPool/Infrastructure/TxHub.cs index 1a99a5f98b..eeb7a21242 100644 --- a/src/AElf.Kernel.TransactionPool/Infrastructure/TxHub.cs +++ b/src/AElf.Kernel.TransactionPool/Infrastructure/TxHub.cs @@ -15,392 +15,366 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class TxHub : ITxHub, ISingletonDependency { - public class TxHub : ITxHub, ISingletonDependency - { - public ILogger Logger { get; set; } - private readonly TransactionOptions _transactionOptions; + private readonly ConcurrentDictionary _allTransactions = new(); - private readonly ITransactionManager _transactionManager; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionValidationService _transactionValidationService; + private readonly IBlockchainService _blockchainService; - private readonly ConcurrentDictionary _allTransactions = - new ConcurrentDictionary(); + private readonly TransformBlock _processTransactionJobs; - private ConcurrentDictionary _validatedTransactions = - new ConcurrentDictionary(); + private readonly ITransactionManager _transactionManager; + private readonly TransactionOptions _transactionOptions; + private readonly ITransactionValidationService _transactionValidationService; + private Hash _bestChainHash = Hash.Empty; - private ConcurrentDictionary> _invalidatedByBlock = - new ConcurrentDictionary>(); + private long _bestChainHeight = AElfConstants.GenesisBlockHeight - 1; - private ConcurrentDictionary> _expiredByExpiryBlock = - new ConcurrentDictionary>(); + private ConcurrentDictionary> _expiredByExpiryBlock = new(); - private readonly TransformBlock _processTransactionJobs; + private ConcurrentDictionary> _invalidatedByBlock = new(); - private long _bestChainHeight = AElfConstants.GenesisBlockHeight - 1; - private Hash _bestChainHash = Hash.Empty; + private ConcurrentDictionary _validatedTransactions = new(); - public ILocalEventBus LocalEventBus { get; set; } + public TxHub(ITransactionManager transactionManager, IBlockchainService blockchainService, + IOptionsSnapshot transactionOptions, + ITransactionValidationService transactionValidationService) + { + Logger = NullLogger.Instance; + _transactionManager = transactionManager; + _blockchainService = blockchainService; + _transactionValidationService = transactionValidationService; + LocalEventBus = NullLocalEventBus.Instance; + _transactionOptions = transactionOptions.Value; + _processTransactionJobs = CreateQueuedTransactionBufferBlock(); + } - public TxHub(ITransactionManager transactionManager, IBlockchainService blockchainService, - IOptionsSnapshot transactionOptions, - ITransactionValidationService transactionValidationService) - { - Logger = NullLogger.Instance; - _transactionManager = transactionManager; - _blockchainService = blockchainService; - _transactionValidationService = transactionValidationService; - LocalEventBus = NullLocalEventBus.Instance; - _transactionOptions = transactionOptions.Value; - _processTransactionJobs = CreateQueuedTransactionBufferBlock(); - } + public ILogger Logger { get; set; } - public async Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount) - { - var output = new ExecutableTransactionSet - { - PreviousBlockHash = _bestChainHash, - PreviousBlockHeight = _bestChainHeight - }; + public ILocalEventBus LocalEventBus { get; set; } - if (transactionCount <= 0) - { - return output; - } - - if (blockHash != _bestChainHash) - { - Logger.LogWarning( - $"Attempting to retrieve executable transactions while best chain records don't match."); - return output; - } + public async Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount) + { + var output = new ExecutableTransactionSet + { + PreviousBlockHash = _bestChainHash, + PreviousBlockHeight = _bestChainHeight + }; - output.Transactions.AddRange(_validatedTransactions.Values.OrderBy(x => x.EnqueueTime) - .Take(transactionCount) - .Select(x => x.Transaction)); + if (transactionCount <= 0) return output; + if (blockHash != _bestChainHash) + { + Logger.LogWarning( + "Attempting to retrieve executable transactions while best chain records don't match."); return output; } - public async Task AddTransactionsAsync(IEnumerable transactions) - { - if (_bestChainHash == Hash.Empty) - return; + output.Transactions.AddRange(_validatedTransactions.Values.OrderBy(x => x.EnqueueTime) + .Take(transactionCount) + .Select(x => x.Transaction)); + + return output; + } + + public async Task AddTransactionsAsync(IEnumerable transactions) + { + if (_bestChainHash == Hash.Empty) + return; - foreach (var transaction in transactions) + foreach (var transaction in transactions) + { + var transactionId = transaction.GetHash(); + var queuedTransaction = new QueuedTransaction { - var transactionId = transaction.GetHash(); - var queuedTransaction = new QueuedTransaction - { - TransactionId = transactionId, - Transaction = transaction, - EnqueueTime = TimestampHelper.GetUtcNow() - }; - var sendResult = await _processTransactionJobs.SendAsync(queuedTransaction); - if (sendResult) continue; - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transactionId, - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = "Failed to enter tx hub." - }); - Logger.LogWarning($"Process transaction:{queuedTransaction.TransactionId} failed."); - } + TransactionId = transactionId, + Transaction = transaction, + EnqueueTime = TimestampHelper.GetUtcNow() + }; + var sendResult = await _processTransactionJobs.SendAsync(queuedTransaction); + if (sendResult) continue; + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent + { + TransactionId = transactionId, + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = "Failed to enter tx hub." + }); + Logger.LogWarning($"Process transaction:{queuedTransaction.TransactionId} failed."); } + } - public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) + public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) + { + var minimumHeight = _allTransactions.Count == 0 + ? 0 + : _allTransactions.Min(kv => kv.Value.Transaction.RefBlockNumber); + var prefixes = await GetPrefixesByHeightAsync(minimumHeight, bestChainHash, bestChainHeight); + ResetCurrentCollections(); + foreach (var queuedTransaction in _allTransactions.Values) { - var minimumHeight = _allTransactions.Count == 0 - ? 0 - : _allTransactions.Min(kv => kv.Value.Transaction.RefBlockNumber); - var prefixes = await GetPrefixesByHeightAsync(minimumHeight, bestChainHash, bestChainHeight); - ResetCurrentCollections(); - foreach (var queuedTransaction in _allTransactions.Values) - { - prefixes.TryGetValue(queuedTransaction.Transaction.RefBlockNumber, out var prefix); - queuedTransaction.RefBlockStatus = - CheckRefBlockStatus(queuedTransaction.Transaction, prefix, bestChainHeight); - AddToCollection(queuedTransaction); - } + prefixes.TryGetValue(queuedTransaction.Transaction.RefBlockNumber, out var prefix); + queuedTransaction.RefBlockStatus = + CheckRefBlockStatus(queuedTransaction.Transaction, prefix, bestChainHeight); + AddToCollection(queuedTransaction); + } - CleanTransactions(_expiredByExpiryBlock, bestChainHeight); + CleanTransactions(_expiredByExpiryBlock, bestChainHeight); - _bestChainHash = bestChainHash; - _bestChainHeight = bestChainHeight; - } + _bestChainHash = bestChainHash; + _bestChainHeight = bestChainHeight; + } - public Task CleanByHeightAsync(long height) - { - CleanTransactions(_expiredByExpiryBlock, height); - CleanTransactions(_invalidatedByBlock, height); + public Task CleanByHeightAsync(long height) + { + CleanTransactions(_expiredByExpiryBlock, height); + CleanTransactions(_invalidatedByBlock, height); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task CleanByTransactionIdsAsync(IEnumerable transactionIds) - { - CleanTransactions(transactionIds); - return Task.CompletedTask; - } + public Task CleanByTransactionIdsAsync(IEnumerable transactionIds) + { + CleanTransactions(transactionIds); + return Task.CompletedTask; + } - public Task GetTransactionPoolStatusAsync() + public Task GetTransactionPoolStatusAsync() + { + return Task.FromResult(new TransactionPoolStatus { - return Task.FromResult(new TransactionPoolStatus - { - AllTransactionCount = _allTransactions.Count, - ValidatedTransactionCount = _validatedTransactions.Count - }); - } + AllTransactionCount = _allTransactions.Count, + ValidatedTransactionCount = _validatedTransactions.Count + }); + } + + public Task GetQueuedTransactionAsync(Hash transactionId) + { + _allTransactions.TryGetValue(transactionId, out var receipt); + return Task.FromResult(receipt); + } - public Task GetQueuedTransactionAsync(Hash transactionId) + #region Private Methods + + private static void AddToCollection( + ConcurrentDictionary> collection, + QueuedTransaction receipt) + { + if (!collection.TryGetValue(receipt.Transaction.RefBlockNumber, out var receipts)) { - _allTransactions.TryGetValue(transactionId, out var receipt); - return Task.FromResult(receipt); + receipts = new ConcurrentDictionary(); + collection.TryAdd(receipt.Transaction.RefBlockNumber, receipts); } - #region Private Methods + receipts.TryAdd(receipt.TransactionId, receipt); + } - private static void AddToCollection( - ConcurrentDictionary> collection, - QueuedTransaction receipt) - { - if (!collection.TryGetValue(receipt.Transaction.RefBlockNumber, out var receipts)) - { - receipts = new ConcurrentDictionary(); - collection.TryAdd(receipt.Transaction.RefBlockNumber, receipts); - } + private static RefBlockStatus CheckRefBlockStatus(Transaction transaction, ByteString prefix, + long bestChainHeight) + { + if (transaction.GetExpiryBlockNumber() <= bestChainHeight) return RefBlockStatus.RefBlockExpired; - receipts.TryAdd(receipt.TransactionId, receipt); - } + return transaction.RefBlockPrefix == prefix ? RefBlockStatus.RefBlockValid : RefBlockStatus.RefBlockInvalid; + } - private static RefBlockStatus CheckRefBlockStatus(Transaction transaction, ByteString prefix, - long bestChainHeight) - { - if (transaction.GetExpiryBlockNumber() <= bestChainHeight) - { - return RefBlockStatus.RefBlockExpired; - } + private ByteString GetPrefixByHash(Hash hash) + { + return hash == null ? null : BlockHelper.GetRefBlockPrefix(hash); + } - return transaction.RefBlockPrefix == prefix ? RefBlockStatus.RefBlockValid : RefBlockStatus.RefBlockInvalid; - } + private async Task GetPrefixByHeightAsync(long height, Hash bestChainHash) + { + var chain = await _blockchainService.GetChainAsync(); + var hash = await _blockchainService.GetBlockHashByHeightAsync(chain, height, bestChainHash); + return GetPrefixByHash(hash); + } - private ByteString GetPrefixByHash(Hash hash) - { - return hash == null ? null : BlockHelper.GetRefBlockPrefix(hash); - } + private async Task> GetPrefixesByHeightAsync(long firstHeight, Hash bestChainHash, + long bestChainHeight) + { + var blockIndexes = + await _blockchainService.GetBlockIndexesAsync(firstHeight, bestChainHash, bestChainHeight); + + return blockIndexes.ToDictionary(blockIndex => blockIndex.BlockHeight, + blockIndex => GetPrefixByHash(blockIndex.BlockHash)); + } + + private void ResetCurrentCollections() + { + _expiredByExpiryBlock = new ConcurrentDictionary>(); + _invalidatedByBlock = new ConcurrentDictionary>(); + _validatedTransactions = new ConcurrentDictionary(); + } - private async Task GetPrefixByHeightAsync(long height, Hash bestChainHash) + private void AddToCollection(QueuedTransaction queuedTransaction) + { + switch (queuedTransaction.RefBlockStatus) { - var chain = await _blockchainService.GetChainAsync(); - var hash = await _blockchainService.GetBlockHashByHeightAsync(chain, height, bestChainHash); - return GetPrefixByHash(hash); + case RefBlockStatus.RefBlockExpired: + AddToCollection(_expiredByExpiryBlock, queuedTransaction); + break; + case RefBlockStatus.RefBlockInvalid: + AddToCollection(_invalidatedByBlock, queuedTransaction); + break; + case RefBlockStatus.RefBlockValid: + _validatedTransactions.TryAdd(queuedTransaction.TransactionId, queuedTransaction); + break; } + } - private async Task> GetPrefixesByHeightAsync(long firstHeight, Hash bestChainHash, - long bestChainHeight) - { - var blockIndexes = - await _blockchainService.GetBlockIndexesAsync(firstHeight, bestChainHash, bestChainHeight); + private void CleanTransactions(ConcurrentDictionary> + collection, long blockHeight) + { + foreach (var txIds in collection.Where(kv => kv.Key <= blockHeight)) + CleanTransactions(txIds.Value.Keys.ToList()); + } - return blockIndexes.ToDictionary(blockIndex => blockIndex.BlockHeight, - blockIndex => GetPrefixByHash(blockIndex.BlockHash)); - } + private void CleanTransactions(IEnumerable transactionIds) + { + foreach (var transactionId in transactionIds) _allTransactions.TryRemove(transactionId, out _); + } - private void ResetCurrentCollections() - { - _expiredByExpiryBlock = new ConcurrentDictionary>(); - _invalidatedByBlock = new ConcurrentDictionary>(); - _validatedTransactions = new ConcurrentDictionary(); - } + #endregion - private void AddToCollection(QueuedTransaction queuedTransaction) - { - switch (queuedTransaction.RefBlockStatus) - { - case RefBlockStatus.RefBlockExpired: - AddToCollection(_expiredByExpiryBlock, queuedTransaction); - break; - case RefBlockStatus.RefBlockInvalid: - AddToCollection(_invalidatedByBlock, queuedTransaction); - break; - case RefBlockStatus.RefBlockValid: - _validatedTransactions.TryAdd(queuedTransaction.TransactionId, queuedTransaction); - break; - } - } + #region Data flow - private void CleanTransactions(ConcurrentDictionary> - collection, long blockHeight) + private TransformBlock CreateQueuedTransactionBufferBlock() + { + var executionDataFlowBlockOptions = new ExecutionDataflowBlockOptions { - foreach (var txIds in collection.Where(kv => kv.Key <= blockHeight)) - { - CleanTransactions(txIds.Value.Keys.ToList()); - } - } - - private void CleanTransactions(IEnumerable transactionIds) + BoundedCapacity = Math.Max(_transactionOptions.PoolLimit, 1), // cannot be zero + MaxDegreeOfParallelism = _transactionOptions.PoolParallelismDegree + }; + var linkOptions = new DataflowLinkOptions { PropagateCompletion = true }; + + var updateBucketIndexTransformBlock = + new TransformBlock(UpdateBucketIndex, + executionDataFlowBlockOptions); + var i = 0; + while (i < _transactionOptions.PoolParallelismDegree) { - foreach (var transactionId in transactionIds) - { - _allTransactions.TryRemove(transactionId, out _); - } + var validationTransformBlock = new ActionBlock( + async queuedTransaction => + await ProcessQueuedTransactionAsync(queuedTransaction, AcceptTransactionAsync), + new ExecutionDataflowBlockOptions + { + BoundedCapacity = Math.Max(_transactionOptions.PoolLimit, 1), // cannot be zero + EnsureOrdered = false + }); + var index = i; + updateBucketIndexTransformBlock.LinkTo(validationTransformBlock, linkOptions, + queuedTransaction => queuedTransaction.BucketIndex == index); + i++; } - #endregion + updateBucketIndexTransformBlock.LinkTo(DataflowBlock.NullTarget()); + return updateBucketIndexTransformBlock; + } - #region Data flow + private QueuedTransaction UpdateBucketIndex(QueuedTransaction queuedTransaction) + { + queuedTransaction.BucketIndex = + Math.Abs(queuedTransaction.TransactionId.ToInt64() % _transactionOptions.PoolParallelismDegree); + return queuedTransaction; + } - private TransformBlock CreateQueuedTransactionBufferBlock() - { - var executionDataFlowBlockOptions = new ExecutionDataflowBlockOptions - { - BoundedCapacity = Math.Max(_transactionOptions.PoolLimit, 1), // cannot be zero - MaxDegreeOfParallelism = _transactionOptions.PoolParallelismDegree - }; - var linkOptions = new DataflowLinkOptions {PropagateCompletion = true}; + private async Task VerifyTransactionAcceptableAsync(QueuedTransaction queuedTransaction) + { + if (_allTransactions.ContainsKey(queuedTransaction.TransactionId)) return false; - var updateBucketIndexTransformBlock = - new TransformBlock(UpdateBucketIndex, - executionDataFlowBlockOptions); - int i = 0; - while (i < _transactionOptions.PoolParallelismDegree) - { - var validationTransformBlock = new ActionBlock( - async queuedTransaction => - await ProcessQueuedTransactionAsync(queuedTransaction, AcceptTransactionAsync), - new ExecutionDataflowBlockOptions - { - BoundedCapacity = Math.Max(_transactionOptions.PoolLimit, 1), // cannot be zero - EnsureOrdered = false - }); - var index = i; - updateBucketIndexTransformBlock.LinkTo(validationTransformBlock, linkOptions, - queuedTransaction => queuedTransaction.BucketIndex == index); - i++; - } - - updateBucketIndexTransformBlock.LinkTo(DataflowBlock.NullTarget()); - return updateBucketIndexTransformBlock; + if (!queuedTransaction.Transaction.VerifyExpiration(_bestChainHeight)) + { + await PublishTransactionNodeValidationFailedEventAsync(queuedTransaction.TransactionId, + $"Transaction expired.Transaction RefBlockNumber is {queuedTransaction.Transaction.RefBlockNumber},best chain height is {_bestChainHeight}"); + return false; } - private QueuedTransaction UpdateBucketIndex(QueuedTransaction queuedTransaction) + if (_allTransactions.Count >= _transactionOptions.PoolLimit) { - queuedTransaction.BucketIndex = - Math.Abs(queuedTransaction.TransactionId.ToInt64() % _transactionOptions.PoolParallelismDegree); - return queuedTransaction; + await PublishTransactionNodeValidationFailedEventAsync(queuedTransaction.TransactionId, + "Transaction Pool is full."); + return false; } - private async Task VerifyTransactionAcceptableAsync(QueuedTransaction queuedTransaction) - { - if (_allTransactions.ContainsKey(queuedTransaction.TransactionId)) - { - return false; - } + if (await _blockchainService.HasTransactionAsync(queuedTransaction.TransactionId)) return false; - if (!queuedTransaction.Transaction.VerifyExpiration(_bestChainHeight)) - { - await PublishTransactionNodeValidationFailedEventAsync(queuedTransaction.TransactionId, - $"Transaction expired.Transaction RefBlockNumber is {queuedTransaction.Transaction.RefBlockNumber},best chain height is {_bestChainHeight}"); - return false; - } + return true; + } - if (_allTransactions.Count >= _transactionOptions.PoolLimit) - { - await PublishTransactionNodeValidationFailedEventAsync(queuedTransaction.TransactionId, - "Transaction Pool is full."); - return false; - } + private async Task AcceptTransactionAsync(QueuedTransaction queuedTransaction) + { + if (!await VerifyTransactionAcceptableAsync(queuedTransaction)) return null; - if (await _blockchainService.HasTransactionAsync(queuedTransaction.TransactionId)) + var validationResult = + await _transactionValidationService.ValidateTransactionWhileCollectingAsync(new ChainContext { - return false; - } - - return true; - } - - private async Task AcceptTransactionAsync(QueuedTransaction queuedTransaction) + BlockHash = _bestChainHash, + BlockHeight = _bestChainHeight + }, queuedTransaction.Transaction); + if (!validationResult) { - if (!await VerifyTransactionAcceptableAsync(queuedTransaction)) - { - return null; - } - - var validationResult = - await _transactionValidationService.ValidateTransactionWhileCollectingAsync(new ChainContext - { - BlockHash = _bestChainHash, - BlockHeight = _bestChainHeight - }, queuedTransaction.Transaction); - if (!validationResult) - { - Logger.LogDebug($"Transaction {queuedTransaction.TransactionId} validation failed."); - return null; - } - - // double check - var hasTransaction = await _blockchainService.HasTransactionAsync(queuedTransaction.TransactionId); - if (hasTransaction) - return null; - - await _transactionManager.AddTransactionAsync(queuedTransaction.Transaction); - var addSuccess = _allTransactions.TryAdd(queuedTransaction.TransactionId, queuedTransaction); - if (addSuccess) - { - await UpdateQueuedTransactionRefBlockStatusAsync(queuedTransaction); - return queuedTransaction; - } - - Logger.LogWarning($"Transaction {queuedTransaction.TransactionId} insert failed."); + Logger.LogDebug($"Transaction {queuedTransaction.TransactionId} validation failed."); return null; } - private async Task PublishTransactionNodeValidationFailedEventAsync(Hash transactionId, string error) + // double check + var hasTransaction = await _blockchainService.HasTransactionAsync(queuedTransaction.TransactionId); + if (hasTransaction) + return null; + + await _transactionManager.AddTransactionAsync(queuedTransaction.Transaction); + var addSuccess = _allTransactions.TryAdd(queuedTransaction.TransactionId, queuedTransaction); + if (addSuccess) { - await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent - { - TransactionId = transactionId, - TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, - Error = error - }); + await UpdateQueuedTransactionRefBlockStatusAsync(queuedTransaction); + return queuedTransaction; } - private async Task UpdateQueuedTransactionRefBlockStatusAsync( - QueuedTransaction queuedTransaction) + Logger.LogWarning($"Transaction {queuedTransaction.TransactionId} insert failed."); + return null; + } + + private async Task PublishTransactionNodeValidationFailedEventAsync(Hash transactionId, string error) + { + await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent { - var prefix = await GetPrefixByHeightAsync(queuedTransaction.Transaction.RefBlockNumber, _bestChainHash); - queuedTransaction.RefBlockStatus = - CheckRefBlockStatus(queuedTransaction.Transaction, prefix, _bestChainHeight); + TransactionId = transactionId, + TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, + Error = error + }); + } - if (queuedTransaction.RefBlockStatus == RefBlockStatus.RefBlockValid) + private async Task UpdateQueuedTransactionRefBlockStatusAsync( + QueuedTransaction queuedTransaction) + { + var prefix = await GetPrefixByHeightAsync(queuedTransaction.Transaction.RefBlockNumber, _bestChainHash); + queuedTransaction.RefBlockStatus = + CheckRefBlockStatus(queuedTransaction.Transaction, prefix, _bestChainHeight); + + if (queuedTransaction.RefBlockStatus == RefBlockStatus.RefBlockValid) + await LocalEventBus.PublishAsync(new TransactionAcceptedEvent { - await LocalEventBus.PublishAsync(new TransactionAcceptedEvent - { - Transaction = queuedTransaction.Transaction - }); - } + Transaction = queuedTransaction.Transaction + }); - return queuedTransaction; - } + return queuedTransaction; + } - private async Task ProcessQueuedTransactionAsync(QueuedTransaction queuedTransaction, - Func> func) + private async Task ProcessQueuedTransactionAsync(QueuedTransaction queuedTransaction, + Func> func) + { + try { - try - { - return await func(queuedTransaction); - } - catch (Exception e) - { - Logger.LogError(e, - $"Unacceptable transaction {queuedTransaction.TransactionId}. Func: {func?.Method.Name}"); - return null; - } + return await func(queuedTransaction); + } + catch (Exception e) + { + Logger.LogError(e, + $"Unacceptable transaction {queuedTransaction.TransactionId}. Func: {func?.Method.Name}"); + return null; } - - #endregion } + + #endregion } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/TransactionOptions.cs b/src/AElf.Kernel.TransactionPool/TransactionOptions.cs index 645feda2e9..7847da5094 100644 --- a/src/AElf.Kernel.TransactionPool/TransactionOptions.cs +++ b/src/AElf.Kernel.TransactionPool/TransactionOptions.cs @@ -1,21 +1,20 @@ -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionOptions { - public class TransactionOptions - { - /// - /// Transaction pool limit. - /// - public int PoolLimit { get; set; } = 5120; + /// + /// Transaction pool limit. + /// + public int PoolLimit { get; set; } = 5120; - /// - /// Transaction processing data flow MaxDegreeOfParallelism for transaction pool. - /// - public int PoolParallelismDegree { get; set; } = 5; + /// + /// Transaction processing data flow MaxDegreeOfParallelism for transaction pool. + /// + public int PoolParallelismDegree { get; set; } = 5; - /// - /// Bp Node can disable this flag to make best performance. - /// But common node needs to enable it to prevent transaction flood attack - /// - public bool EnableTransactionExecutionValidation { get; set; } = true; - } + /// + /// Bp Node can disable this flag to make best performance. + /// But common node needs to enable it to prevent transaction flood attack + /// + public bool EnableTransactionExecutionValidation { get; set; } = true; } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/TransactionPoolAElfModule.cs b/src/AElf.Kernel.TransactionPool/TransactionPoolAElfModule.cs index 492ef071e2..4685f02603 100644 --- a/src/AElf.Kernel.TransactionPool/TransactionPoolAElfModule.cs +++ b/src/AElf.Kernel.TransactionPool/TransactionPoolAElfModule.cs @@ -5,22 +5,21 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +[DependsOn(typeof(CoreKernelAElfModule))] +public class TransactionPoolAElfModule : AElfModule { - [DependsOn(typeof(CoreKernelAElfModule))] - public class TransactionPoolAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - // Validate signature and tx size. - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - services.AddSingleton(); - var configuration = context.Services.GetConfiguration(); - Configure(configuration.GetSection("Transaction")); - } + var services = context.Services; + // Validate signature and tx size. + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(); + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("Transaction")); } } \ No newline at end of file diff --git a/src/AElf.Kernel.TransactionPool/TransactionPoolConsts.cs b/src/AElf.Kernel.TransactionPool/TransactionPoolConsts.cs index 04d37782ea..798ffc5d7e 100644 --- a/src/AElf.Kernel.TransactionPool/TransactionPoolConsts.cs +++ b/src/AElf.Kernel.TransactionPool/TransactionPoolConsts.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionPoolConsts { - public class TransactionPoolConsts - { - public const int TransactionSizeLimit = 1024 * 1024 * 5; // 5M - } + public const int TransactionSizeLimit = 1024 * 1024 * 5; // 5M } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/AElf.Kernel.Types.csproj b/src/AElf.Kernel.Types/AElf.Kernel.Types.csproj index 166e24ffdc..2b4ff86a2a 100644 --- a/src/AElf.Kernel.Types/AElf.Kernel.Types.csproj +++ b/src/AElf.Kernel.Types/AElf.Kernel.Types.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Kernel @@ -9,7 +9,7 @@ - + diff --git a/src/AElf.Kernel.Types/Block/Block.cs b/src/AElf.Kernel.Types/Block/Block.cs index 98a2ec2936..5c1d11fe00 100644 --- a/src/AElf.Kernel.Types/Block/Block.cs +++ b/src/AElf.Kernel.Types/Block/Block.cs @@ -2,43 +2,42 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class Block : ICustomDiagnosticMessage, IBlock { - public partial class Block : ICustomDiagnosticMessage, IBlock + /// + /// Initializes a new instance of the class. + /// A previous block must be referred, except for the genesis block. + /// + /// Pre block hash. + public Block(Hash preBlockHash) + { + Header = new BlockHeader(preBlockHash); + Body = new BlockBody(); + } + + public long Height => Header?.Height ?? 0; + + public IEnumerable TransactionIds => Body.TransactionIds; + + + public Hash GetHash() + { + return Header.GetHash(); + } + + /// + /// Used to override IMessage's default string representation. + /// + /// + public string ToDiagnosticString() + { + return $"{{ id: {GetHash()}, height: {Height} }}"; + } + + public Hash GetHashWithoutCache() { - /// - /// Used to override IMessage's default string representation. - /// - /// - public string ToDiagnosticString() - { - return $"{{ id: {GetHash()}, height: {Height} }}"; - } - - /// - /// Initializes a new instance of the class. - /// A previous block must be referred, except for the genesis block. - /// - /// Pre block hash. - public Block(Hash preBlockHash) - { - Header = new BlockHeader(preBlockHash); - Body = new BlockBody(); - } - - public IEnumerable TransactionIds => Body.TransactionIds; - - public long Height => Header?.Height ?? 0; - - - public Hash GetHash() - { - return Header.GetHash(); - } - - public Hash GetHashWithoutCache() - { - return Header.GetHashWithoutCache(); - } + return Header.GetHashWithoutCache(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/BlockBody.cs b/src/AElf.Kernel.Types/Block/BlockBody.cs index 65456350cd..e3824574c8 100644 --- a/src/AElf.Kernel.Types/Block/BlockBody.cs +++ b/src/AElf.Kernel.Types/Block/BlockBody.cs @@ -2,33 +2,32 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class BlockBody : IBlockBody { - public partial class BlockBody : IBlockBody - { - public int TransactionsCount => TransactionIds.Count; - private Hash _blockBodyHash; + private Hash _blockBodyHash; + public int TransactionsCount => TransactionIds.Count; - private Hash CalculateBodyHash() - { - if (!VerifyFields()) - throw new InvalidOperationException($"Invalid block body."); + public Hash GetHash() + { + return _blockBodyHash ?? CalculateBodyHash(); + } - _blockBodyHash = HashHelper.ComputeFrom(this.ToByteArray()); - return _blockBodyHash; - } + private Hash CalculateBodyHash() + { + if (!VerifyFields()) + throw new InvalidOperationException("Invalid block body."); - public bool VerifyFields() - { - if (TransactionIds.Count == 0) - return false; + _blockBodyHash = HashHelper.ComputeFrom(this.ToByteArray()); + return _blockBodyHash; + } - return true; - } + public bool VerifyFields() + { + if (TransactionIds.Count == 0) + return false; - public Hash GetHash() - { - return _blockBodyHash ?? CalculateBodyHash(); - } + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/BlockHeader.cs b/src/AElf.Kernel.Types/Block/BlockHeader.cs index 812091073a..fef0d25a95 100644 --- a/src/AElf.Kernel.Types/Block/BlockHeader.cs +++ b/src/AElf.Kernel.Types/Block/BlockHeader.cs @@ -2,71 +2,70 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class BlockHeader : IBlockHeader { - public partial class BlockHeader : IBlockHeader - { - private Hash _blockHash; + private Hash _blockHash; - public BlockHeader(Hash preBlockHash) - { - PreviousBlockHash = preBlockHash; - } + public BlockHeader(Hash preBlockHash) + { + PreviousBlockHash = preBlockHash; + } - public Hash GetHash() - { - if (_blockHash == null) - _blockHash = HashHelper.ComputeFrom(GetSignatureData()); + public Hash GetHash() + { + if (_blockHash == null) + _blockHash = HashHelper.ComputeFrom(GetSignatureData()); - return _blockHash; - } + return _blockHash; + } - public Hash GetHashWithoutCache() - { - _blockHash = null; - return GetHash(); - } + public Hash GetHashWithoutCache() + { + _blockHash = null; + return GetHash(); + } - public byte[] GetHashBytes() - { - return GetHash().ToByteArray(); - } + public byte[] GetHashBytes() + { + return GetHash().ToByteArray(); + } - private byte[] GetSignatureData() - { - if (!VerifyFields()) - throw new InvalidOperationException($"Invalid block header: {this}."); + private byte[] GetSignatureData() + { + if (!VerifyFields()) + throw new InvalidOperationException($"Invalid block header: {this}."); - if (Signature.IsEmpty) - return this.ToByteArray(); + if (Signature.IsEmpty) + return this.ToByteArray(); - var blockHeader = Clone(); - blockHeader.Signature = ByteString.Empty; - return blockHeader.ToByteArray(); - } + var blockHeader = Clone(); + blockHeader.Signature = ByteString.Empty; + return blockHeader.ToByteArray(); + } - public bool VerifyFields() - { - if (ChainId < 0) - return false; + public bool VerifyFields() + { + if (ChainId < 0) + return false; - if (Height < AElfConstants.GenesisBlockHeight) - return false; + if (Height < AElfConstants.GenesisBlockHeight) + return false; - if (Height > AElfConstants.GenesisBlockHeight && SignerPubkey.IsEmpty) - return false; + if (Height > AElfConstants.GenesisBlockHeight && SignerPubkey.IsEmpty) + return false; - if (PreviousBlockHash == null) - return false; + if (PreviousBlockHash == null) + return false; - if (MerkleTreeRootOfTransactions == null || MerkleTreeRootOfWorldState == null || - MerkleTreeRootOfTransactionStatus == null) - return false; + if (MerkleTreeRootOfTransactions == null || MerkleTreeRootOfWorldState == null || + MerkleTreeRootOfTransactionStatus == null) + return false; - if (Time == null) - return false; + if (Time == null) + return false; - return true; - } + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/IBlock.cs b/src/AElf.Kernel.Types/Block/IBlock.cs index d0485c11d7..156a92ab2d 100644 --- a/src/AElf.Kernel.Types/Block/IBlock.cs +++ b/src/AElf.Kernel.Types/Block/IBlock.cs @@ -1,8 +1,7 @@ -namespace AElf.Kernel +namespace AElf.Kernel; + +public interface IBlock : IBlockBase { - public interface IBlock : IBlockBase - { - BlockHeader Header { get; } - BlockBody Body { get; } - } + BlockHeader Header { get; } + BlockBody Body { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/IBlockBody.cs b/src/AElf.Kernel.Types/Block/IBlockBody.cs index 2c13cd8d12..b2bc716482 100644 --- a/src/AElf.Kernel.Types/Block/IBlockBody.cs +++ b/src/AElf.Kernel.Types/Block/IBlockBody.cs @@ -1,10 +1,9 @@ using AElf.Types; using Google.Protobuf.Collections; -namespace AElf.Kernel +namespace AElf.Kernel; + +public interface IBlockBody : IHashProvider { - public interface IBlockBody : IHashProvider - { - RepeatedField TransactionIds { get; } - } + RepeatedField TransactionIds { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/IBlockHeader.cs b/src/AElf.Kernel.Types/Block/IBlockHeader.cs index 560956917a..6e76b25546 100644 --- a/src/AElf.Kernel.Types/Block/IBlockHeader.cs +++ b/src/AElf.Kernel.Types/Block/IBlockHeader.cs @@ -1,12 +1,11 @@ using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public interface IBlockHeader : IHashProvider { - public interface IBlockHeader : IHashProvider - { - int Version { get; set; } - Hash MerkleTreeRootOfTransactions { get; set; } - int ChainId { get; set; } - long Height { get; } - } + int Version { get; set; } + Hash MerkleTreeRootOfTransactions { get; set; } + int ChainId { get; set; } + long Height { get; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Block/IBlockIndex.cs b/src/AElf.Kernel.Types/Block/IBlockIndex.cs index 84915fd15f..e06c3e34f3 100644 --- a/src/AElf.Kernel.Types/Block/IBlockIndex.cs +++ b/src/AElf.Kernel.Types/Block/IBlockIndex.cs @@ -1,24 +1,23 @@ using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public interface IBlockIndex +{ + Hash BlockHash { get; } + long BlockHeight { get; } +} + +public partial class BlockIndex : IBlockIndex { - public interface IBlockIndex + public BlockIndex(Hash hash, long height) { - Hash BlockHash { get; } - long BlockHeight { get; } + BlockHash = hash; + BlockHeight = height; } - public partial class BlockIndex : IBlockIndex + public string ToDiagnosticString() { - public BlockIndex(Hash hash, long height) - { - BlockHash = hash; - BlockHeight = height; - } - - public string ToDiagnosticString() - { - return $"[{BlockHash}: {BlockHeight}]"; - } + return $"[{BlockHash}: {BlockHeight}]"; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Bloom.cs b/src/AElf.Kernel.Types/Bloom.cs index a024a5892f..66c525ee41 100644 --- a/src/AElf.Kernel.Types/Bloom.cs +++ b/src/AElf.Kernel.Types/Bloom.cs @@ -3,116 +3,101 @@ using System.Linq; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class Bloom { - public class Bloom + private const int Length = 256; + + private const uint BucketPerVal = 3; // number of hash functions + + public Bloom() + { + Data = new byte[0]; + } + + public Bloom(byte[] data) { - private const int Length = 256; - public static byte[] AndMultipleBloomBytes(IEnumerable multipleBytes) + if (data.Length == 0) { - var res = new byte[Length]; - foreach (var bytes in multipleBytes) - { - for (var i = 0; i < Length; i++) - { - res[i] |= bytes[i]; - } - } - return res; + Data = new byte[0]; + return; } - private const uint BucketPerVal = 3; // number of hash functions - private byte[] _data; + if (data.Length != Length) throw new InvalidOperationException($"Bloom data has to be {Length} bytes long."); - public byte[] Data => _data; + Data = (byte[])data.Clone(); + } - public Bloom() - { - _data = new byte[0]; - } + public Bloom(Bloom bloom) : this(bloom.Data) + { + } - public Bloom(byte[] data) - { - if (data.Length == 0) - { - _data = new byte[0]; - return; - } - if (data.Length != Length) - { - throw new InvalidOperationException($"Bloom data has to be {Length} bytes long."); - } - - _data = (byte[]) data.Clone(); - } + public byte[] Data { get; private set; } - public Bloom(Bloom bloom) : this(bloom.Data) - { - } + public static byte[] AndMultipleBloomBytes(IEnumerable multipleBytes) + { + var res = new byte[Length]; + foreach (var bytes in multipleBytes) + for (var i = 0; i < Length; i++) + res[i] |= bytes[i]; + return res; + } - public void AddValue(byte[] bytes) - { - AddSha256Hash(bytes.ComputeHash()); - } + public void AddValue(byte[] bytes) + { + AddSha256Hash(bytes.ComputeHash()); + } - public void AddValue(IMessage message) - { - if (message == null) return; - var bytes = message.ToByteArray(); - AddValue(bytes); - } + public void AddValue(IMessage message) + { + if (message == null) return; + var bytes = message.ToByteArray(); + AddValue(bytes); + } - public void AddSha256Hash(byte[] hash256) - { - if (hash256.Length != 32) - { - throw new InvalidOperationException("Invalid input."); - } - - if (_data.Length == 0) _data = new byte[Length]; - for (uint i = 0; i < BucketPerVal * 2; i += 2) - { - var index = ((hash256[i] << 8) | hash256[i + 1]) & 2047; - var byteToSet = (byte) (((uint) 1) << (index % 8)); - _data[255 - index / 8] |= byteToSet; - } - } + public void AddSha256Hash(byte[] hash256) + { + if (hash256.Length != 32) throw new InvalidOperationException("Invalid input."); - /// - /// Combines some other blooms into current bloom. - /// - /// Other blooms - public void Combine(IEnumerable blooms) + if (Data.Length == 0) Data = new byte[Length]; + for (uint i = 0; i < BucketPerVal * 2; i += 2) { - if (!blooms.Any(b => b.Data.Length > 0)) return; - if (_data.Length == 0) _data = new byte[Length]; - foreach (var bloom in blooms) - { - for (var i = 0; i < Length; i++) - { - _data[i] |= bloom.Data[i]; - } - } + var index = ((hash256[i] << 8) | hash256[i + 1]) & 2047; + var byteToSet = (byte)((uint)1 << (index % 8)); + Data[255 - index / 8] |= byteToSet; } + } - /// - /// Checks if current bloom is contained in the input bloom. - /// - /// Other bloom - /// - public bool IsIn(Bloom bloom) - { - if (bloom.Data.Length == 0 || _data.Length == 0) return false; + /// + /// Combines some other blooms into current bloom. + /// + /// Other blooms + public void Combine(IEnumerable blooms) + { + if (blooms == null) return; + var bloomsList = blooms.ToList(); + if (!bloomsList.Any(b => b.Data.Length > 0)) return; + if (Data.Length == 0) Data = new byte[Length]; + foreach (var bloom in bloomsList) for (var i = 0; i < Length; i++) - { - var curByte = _data[i]; - if ((curByte & bloom.Data[i]) != curByte) - { - return false; - } - } - - return true; + Data[i] |= bloom.Data[i]; + } + + /// + /// Checks if current bloom is contained in the input bloom. + /// + /// Other bloom + /// + public bool IsIn(Bloom bloom) + { + if (bloom.Data.Length == 0 || Data.Length == 0) return false; + for (var i = 0; i < Length; i++) + { + var curByte = Data[i]; + if ((curByte & bloom.Data[i]) != curByte) return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Chain/Chain.cs b/src/AElf.Kernel.Types/Chain/Chain.cs index c049bc1556..d1e8ef8d13 100644 --- a/src/AElf.Kernel.Types/Chain/Chain.cs +++ b/src/AElf.Kernel.Types/Chain/Chain.cs @@ -1,14 +1,12 @@ using AElf.Types; -using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class Chain { - public partial class Chain + public Chain(int chainId, Hash genesisBlockHash) { - public Chain(int chainId, Hash genesisBlockHash) - { - Id = chainId; - GenesisBlockHash = genesisBlockHash; - } + Id = chainId; + GenesisBlockHash = genesisBlockHash; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Chain/ChainContext.cs b/src/AElf.Kernel.Types/Chain/ChainContext.cs index f10d860920..148d776d6d 100644 --- a/src/AElf.Kernel.Types/Chain/ChainContext.cs +++ b/src/AElf.Kernel.Types/Chain/ChainContext.cs @@ -1,11 +1,10 @@ using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class ChainContext : IChainContext { - public class ChainContext : IChainContext - { - public long BlockHeight { get; set; } - public Hash BlockHash { get; set; } - public IStateCache StateCache { get; set; } - } + public long BlockHeight { get; set; } + public Hash BlockHash { get; set; } + public IStateCache StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Chain/DiscardedBranch.cs b/src/AElf.Kernel.Types/Chain/DiscardedBranch.cs index d197d57882..4aff9bf07f 100644 --- a/src/AElf.Kernel.Types/Chain/DiscardedBranch.cs +++ b/src/AElf.Kernel.Types/Chain/DiscardedBranch.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class DiscardedBranch { - public class DiscardedBranch - { - public List BranchKeys { get; set; } + public List BranchKeys { get; set; } - public List NotLinkedKeys { get; set; } - } + public List NotLinkedKeys { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Chain/IChainContext.cs b/src/AElf.Kernel.Types/Chain/IChainContext.cs index 1fd313845c..df8db6c4e0 100644 --- a/src/AElf.Kernel.Types/Chain/IChainContext.cs +++ b/src/AElf.Kernel.Types/Chain/IChainContext.cs @@ -1,12 +1,9 @@ -using AElf.Types; +namespace AElf.Kernel; -namespace AElf.Kernel +/// +/// a running chain context +/// +public interface IChainContext : IBlockIndex { - /// - /// a running chain context - /// - public interface IChainContext : IBlockIndex - { - IStateCache StateCache { get; set; } - } + IStateCache StateCache { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Extensions/LogEventExtensions.cs b/src/AElf.Kernel.Types/Extensions/LogEventExtensions.cs index d843f1366a..da2dcc7100 100644 --- a/src/AElf.Kernel.Types/Extensions/LogEventExtensions.cs +++ b/src/AElf.Kernel.Types/Extensions/LogEventExtensions.cs @@ -1,20 +1,16 @@ using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class LogEventExtensions { - public static class LogEventExtensions + public static Bloom GetBloom(this LogEvent logEvent) { - public static Bloom GetBloom(this LogEvent logEvent) - { - var bloom = new Bloom(); - bloom.AddValue(logEvent.Address); - bloom.AddValue(logEvent.Name.GetBytes()); - foreach (var t in logEvent.Indexed) - { - bloom.AddValue(t.ToByteArray()); - } + var bloom = new Bloom(); + bloom.AddValue(logEvent.Address); + bloom.AddValue(logEvent.Name.GetBytes()); + foreach (var t in logEvent.Indexed) bloom.AddValue(t.ToByteArray()); - return bloom; - } + return bloom; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Helper/TimestampHelper.cs b/src/AElf.Kernel.Types/Helper/TimestampHelper.cs index 8095dcb7a4..84fc3243bc 100644 --- a/src/AElf.Kernel.Types/Helper/TimestampHelper.cs +++ b/src/AElf.Kernel.Types/Helper/TimestampHelper.cs @@ -1,28 +1,27 @@ using System; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class TimestampHelper { - public static class TimestampHelper + public static Timestamp GetUtcNow() { - public static Timestamp GetUtcNow() - { - return DateTime.UtcNow.ToTimestamp(); - } + return DateTime.UtcNow.ToTimestamp(); + } - public static Duration DurationFromMilliseconds(long milliseconds) - { - return new Duration {Seconds = milliseconds / 1000, Nanos = (int) (milliseconds % 1000) * 1000000}; - } + public static Duration DurationFromMilliseconds(long milliseconds) + { + return new Duration { Seconds = milliseconds / 1000, Nanos = (int)(milliseconds % 1000) * 1000000 }; + } - public static Duration DurationFromSeconds(long seconds) - { - return new Duration {Seconds = seconds}; - } + public static Duration DurationFromSeconds(long seconds) + { + return new Duration { Seconds = seconds }; + } - public static Duration DurationFromMinutes(long minutes) - { - return new Duration {Seconds = minutes * 60}; - } + public static Duration DurationFromMinutes(long minutes) + { + return new Duration { Seconds = minutes * 60 }; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/IStateCache.cs b/src/AElf.Kernel.Types/IStateCache.cs index 3e31d9a507..987da10cea 100644 --- a/src/AElf.Kernel.Types/IStateCache.cs +++ b/src/AElf.Kernel.Types/IStateCache.cs @@ -1,10 +1,9 @@ using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public interface IStateCache { - public interface IStateCache - { - bool TryGetValue(ScopedStatePath key, out byte[] value); - byte[] this[ScopedStatePath key] { set; } - } + byte[] this[ScopedStatePath key] { set; } + bool TryGetValue(ScopedStatePath key, out byte[] value); } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/KernelConstants.cs b/src/AElf.Kernel.Types/KernelConstants.cs index 80ea8857a9..4e2ad4eb64 100644 --- a/src/AElf.Kernel.Types/KernelConstants.cs +++ b/src/AElf.Kernel.Types/KernelConstants.cs @@ -1,20 +1,19 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class KernelConstants { - public static class KernelConstants - { - public const long ReferenceBlockValidPeriod = 64 * 8; - public const int ProtocolVersion = 1; - public const int DefaultRunnerCategory = 0; - public const int CodeCoverageRunnerCategory = 30; - public const string MergeBlockStateQueueName = "MergeBlockStateQueue"; - public const string UpdateChainQueueName = "UpdateChainQueue"; - public const string ConsensusRequestMiningQueueName = "ConsensusRequestMiningQueue"; - public const string ChainCleaningQueueName = "ChainCleaningQueue"; - public const string StorageKeySeparator = ","; - public static Duration AllowedFutureBlockTimeSpan = new Duration() { Seconds = 4 }; - public const string SignaturePlaceholder = "SignaturePlaceholder"; - public const string BlockExecutedDataKey = "BlockExecutedData"; - } + public const long ReferenceBlockValidPeriod = 64 * 8; + public const int ProtocolVersion = 1; + public const int DefaultRunnerCategory = 0; + public const int CodeCoverageRunnerCategory = 30; + public const string MergeBlockStateQueueName = "MergeBlockStateQueue"; + public const string UpdateChainQueueName = "UpdateChainQueue"; + public const string ConsensusRequestMiningQueueName = "ConsensusRequestMiningQueue"; + public const string ChainCleaningQueueName = "ChainCleaningQueue"; + public const string StorageKeySeparator = ","; + public const string SignaturePlaceholder = "SignaturePlaceholder"; + public const string BlockExecutedDataKey = "BlockExecutedData"; + public static Duration AllowedFutureBlockTimeSpan = new() { Seconds = 4 }; } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/StateValue.cs b/src/AElf.Kernel.Types/StateValue.cs index f51f442896..35f48d44eb 100644 --- a/src/AElf.Kernel.Types/StateValue.cs +++ b/src/AElf.Kernel.Types/StateValue.cs @@ -1,31 +1,30 @@ using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class StateValue { - public partial class StateValue - { - public bool IsDirty => OriginalValue != CurrentValue; + public bool IsDirty => OriginalValue != CurrentValue; - public static StateValue Create(byte[] value) + public static StateValue Create(byte[] value) + { + var sc = new StateValue(); + if (value != null) { - var sc = new StateValue(); - if (value != null) - { - sc.OriginalValue = ByteString.CopyFrom(value); - sc.CurrentValue = ByteString.CopyFrom(value); - } - - return sc; + sc.OriginalValue = ByteString.CopyFrom(value); + sc.CurrentValue = ByteString.CopyFrom(value); } - public byte[] Get() - { - return CurrentValue?.ToByteArray(); - } + return sc; + } - public void Set(byte[] value) - { - CurrentValue = ByteString.CopyFrom(value); - } + public byte[] Get() + { + return CurrentValue?.ToByteArray(); + } + + public void Set(byte[] value) + { + CurrentValue = ByteString.CopyFrom(value); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Transaction/QueuedTransaction.cs b/src/AElf.Kernel.Types/Transaction/QueuedTransaction.cs index a8d2a087e5..aa127ece35 100644 --- a/src/AElf.Kernel.Types/Transaction/QueuedTransaction.cs +++ b/src/AElf.Kernel.Types/Transaction/QueuedTransaction.cs @@ -1,22 +1,21 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel +namespace AElf.Kernel; + +public enum RefBlockStatus { - public enum RefBlockStatus - { - UnknownRefBlockStatus = 0, - RefBlockValid = 1, - RefBlockInvalid = -1, - RefBlockExpired = -2 - } + UnknownRefBlockStatus = 0, + RefBlockValid = 1, + RefBlockInvalid = -1, + RefBlockExpired = -2 +} - public class QueuedTransaction - { - public Transaction Transaction { get; set; } - public Hash TransactionId { get; set; } - public Timestamp EnqueueTime { get; set; } - public RefBlockStatus RefBlockStatus { get; set; } - public long BucketIndex { get; set; } - } +public class QueuedTransaction +{ + public Transaction Transaction { get; set; } + public Hash TransactionId { get; set; } + public Timestamp EnqueueTime { get; set; } + public RefBlockStatus RefBlockStatus { get; set; } + public long BucketIndex { 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 f909b44fd8..fbf78286a0 100644 --- a/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs +++ b/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs @@ -5,137 +5,88 @@ using Google.Protobuf.Collections; // ReSharper disable once CheckNamespace -namespace AElf.Kernel +namespace AElf.Kernel; + +public partial class TransactionTrace { - public partial class TransactionTrace + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + + public IEnumerable FlattenedLogs { - partial void OnConstruction() + get { - StateSet = new TransactionExecutingStateSet(); - } + var o = new RepeatedField(); + foreach (var trace in PreTraces) o.AddRange(trace.FlattenedLogs); - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } + o.AddRange(Logs); + foreach (var trace in InlineTraces) o.AddRange(trace.FlattenedLogs); - public IEnumerable FlattenedLogs - { - get - { - var o = new RepeatedField(); - foreach (var trace in PreTraces) - { - o.AddRange(trace.FlattenedLogs); - } - - o.AddRange(Logs); - foreach (var trace in InlineTraces) - { - o.AddRange(trace.FlattenedLogs); - } - - foreach (var trace in PostTraces) - { - o.AddRange(trace.FlattenedLogs); - } - - return o; - } + foreach (var trace in PostTraces) o.AddRange(trace.FlattenedLogs); + + return o; } + } + + partial void OnConstruction() + { + StateSet = new TransactionExecutingStateSet(); + } + + public IEnumerable> GetFlattenedWrites() + { + foreach (var trace in PreTraces) + foreach (var kv in trace.GetFlattenedWrites()) + yield return kv; + + foreach (var kv in StateSet.Writes) yield return kv; - public IEnumerable> GetFlattenedWrites() + foreach (var trace in InlineTraces) + foreach (var kv in trace.GetFlattenedWrites()) + yield return kv; + + foreach (var trace in PostTraces) + foreach (var kv in trace.GetFlattenedWrites()) + yield return kv; + } + + public IEnumerable> GetFlattenedReads() + { + foreach (var trace in PreTraces) + foreach (var kv in trace.GetFlattenedReads()) + yield return kv; + + foreach (var kv in StateSet.Reads) yield return kv; + + foreach (var trace in InlineTraces) + foreach (var kv in trace.GetFlattenedReads()) + yield return kv; + + foreach (var trace in PostTraces) + foreach (var kv in trace.GetFlattenedReads()) + yield return kv; + } + + public IEnumerable GetStateSets() + { + foreach (var trace in PreTraces) { - foreach (var trace in PreTraces) - { - foreach (var kv in trace.GetFlattenedWrites()) - { - yield return kv; - } - } - - foreach (var kv in StateSet.Writes) - { - yield return kv; - } - - foreach (var trace in InlineTraces) - { - foreach (var kv in trace.GetFlattenedWrites()) - { - yield return kv; - } - } - - foreach (var trace in PostTraces) - { - foreach (var kv in trace.GetFlattenedWrites()) - { - yield return kv; - } - } + var stateSets = trace.GetStateSets(); + foreach (var stateSet in stateSets) yield return stateSet; } - public IEnumerable> GetFlattenedReads() + yield return StateSet; + + foreach (var trace in InlineTraces) { - foreach (var trace in PreTraces) - { - foreach (var kv in trace.GetFlattenedReads()) - { - yield return kv; - } - } - - foreach (var kv in StateSet.Reads) - { - yield return kv; - } - - foreach (var trace in InlineTraces) - { - foreach (var kv in trace.GetFlattenedReads()) - { - yield return kv; - } - } - - foreach (var trace in PostTraces) - { - foreach (var kv in trace.GetFlattenedReads()) - { - yield return kv; - } - } + var stateSets = trace.GetStateSets(); + foreach (var stateSet in stateSets) yield return stateSet; } - public IEnumerable GetStateSets() + foreach (var trace in PostTraces) { - foreach (var trace in PreTraces) - { - var stateSets = trace.GetStateSets(); - foreach (var stateSet in stateSets) - { - yield return stateSet; - } - } - - yield return StateSet; - - foreach (var trace in InlineTraces) - { - var stateSets = trace.GetStateSets(); - foreach (var stateSet in stateSets) - { - yield return stateSet; - } - } - - foreach (var trace in PostTraces) - { - var stateSets = trace.GetStateSets(); - foreach (var stateSet in stateSets) - { - yield return stateSet; - } - } + var stateSets = trace.GetStateSets(); + foreach (var stateSet in stateSets) yield return stateSet; } } } \ No newline at end of file diff --git a/src/AElf.Kernel/AElf.Kernel.csproj b/src/AElf.Kernel/AElf.Kernel.csproj index d3ffcfd39a..20e2f545d3 100644 --- a/src/AElf.Kernel/AElf.Kernel.csproj +++ b/src/AElf.Kernel/AElf.Kernel.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,15 +9,15 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/AElf.Kernel/BlockMinedEventData.cs b/src/AElf.Kernel/BlockMinedEventData.cs index 679b669079..b4780c3009 100644 --- a/src/AElf.Kernel/BlockMinedEventData.cs +++ b/src/AElf.Kernel/BlockMinedEventData.cs @@ -1,7 +1,6 @@ -namespace AElf.Kernel +namespace AElf.Kernel; + +public class BlockMinedEventData { - public class BlockMinedEventData - { - public BlockHeader BlockHeader { get; set; } - } + public BlockHeader BlockHeader { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel/ConsensusRequestMiningEventHandler.cs b/src/AElf.Kernel/ConsensusRequestMiningEventHandler.cs index 7bc1d741f6..6c42b3605c 100644 --- a/src/AElf.Kernel/ConsensusRequestMiningEventHandler.cs +++ b/src/AElf.Kernel/ConsensusRequestMiningEventHandler.cs @@ -1,105 +1,100 @@ using System; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus; using AElf.Kernel.Consensus.Application; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContractExecution.Application; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class ConsensusRequestMiningEventHandler : ILocalEventHandler, + ITransientDependency { - public class ConsensusRequestMiningEventHandler : ILocalEventHandler, - ITransientDependency - { - private readonly IBlockAttachService _blockAttachService; - private readonly ITaskQueueManager _taskQueueManager; - private readonly IBlockchainService _blockchainService; - private readonly IConsensusService _consensusService; - private readonly IMiningRequestService _miningRequestService; + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IConsensusService _consensusService; + private readonly IMiningRequestService _miningRequestService; + private readonly ITaskQueueManager _taskQueueManager; - public ILogger Logger { get; set; } + public ConsensusRequestMiningEventHandler( + IBlockAttachService blockAttachService, + ITaskQueueManager taskQueueManager, + IBlockchainService blockchainService, + IConsensusService consensusService, IMiningRequestService miningRequestService) + { + _blockAttachService = blockAttachService; + _taskQueueManager = taskQueueManager; + _blockchainService = blockchainService; + _consensusService = consensusService; + _miningRequestService = miningRequestService; - public ILocalEventBus LocalEventBus { get; set; } + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + } - public ConsensusRequestMiningEventHandler( - IBlockAttachService blockAttachService, - ITaskQueueManager taskQueueManager, - IBlockchainService blockchainService, - IConsensusService consensusService, IMiningRequestService miningRequestService) - { - _blockAttachService = blockAttachService; - _taskQueueManager = taskQueueManager; - _blockchainService = blockchainService; - _consensusService = consensusService; - _miningRequestService = miningRequestService; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILocalEventBus LocalEventBus { get; set; } - public Task HandleEventAsync(ConsensusRequestMiningEventData eventData) + public Task HandleEventAsync(ConsensusRequestMiningEventData eventData) + { + _taskQueueManager.Enqueue(async () => { - _taskQueueManager.Enqueue(async () => + var chain = await _blockchainService.GetChainAsync(); + if (eventData.PreviousBlockHash != chain.BestChainHash) + { + Logger.LogDebug("Mining canceled because best chain already updated"); + return; + } + + try { - var chain = await _blockchainService.GetChainAsync(); - if (eventData.PreviousBlockHash != chain.BestChainHash) + var block = await _miningRequestService.RequestMiningAsync(new ConsensusRequestMiningDto { - Logger.LogDebug("Mining canceled because best chain already updated."); - return; - } + BlockTime = eventData.BlockTime, + BlockExecutionTime = eventData.BlockExecutionTime, + MiningDueTime = eventData.MiningDueTime, + PreviousBlockHash = eventData.PreviousBlockHash, + PreviousBlockHeight = eventData.PreviousBlockHeight + }); - try + if (block != null) { - var block = await _miningRequestService.RequestMiningAsync(new ConsensusRequestMiningDto - { - BlockTime = eventData.BlockTime, - BlockExecutionTime = eventData.BlockExecutionTime, - MiningDueTime = eventData.MiningDueTime, - PreviousBlockHash = eventData.PreviousBlockHash, - PreviousBlockHeight = eventData.PreviousBlockHeight - }); - - if (block != null) - { - await _blockchainService.AddBlockAsync(block); + await _blockchainService.AddBlockAsync(block); - Logger.LogTrace("Before enqueue attach job."); - _taskQueueManager.Enqueue(async () => await _blockAttachService.AttachBlockAsync(block), - KernelConstants.UpdateChainQueueName); + Logger.LogTrace("Before enqueue attach job"); + _taskQueueManager.Enqueue(async () => await _blockAttachService.AttachBlockAsync(block), + KernelConstants.UpdateChainQueueName); - Logger.LogTrace("Before publish block."); + Logger.LogTrace("Before publish block"); - await LocalEventBus.PublishAsync(new BlockMinedEventData - { - BlockHeader = block.Header, - }); - } - else - await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight); + await LocalEventBus.PublishAsync(new BlockMinedEventData + { + BlockHeader = block.Header + }); } - catch (Exception) + else { await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight); - throw; } - }, KernelConstants.ConsensusRequestMiningQueueName); + } + catch (Exception) + { + await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight); + throw; + } + }, KernelConstants.ConsensusRequestMiningQueueName); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - private async Task TriggerConsensusEventAsync(Hash blockHash, long blockHeight) + private async Task TriggerConsensusEventAsync(Hash blockHash, long blockHeight) + { + await _consensusService.TriggerConsensusAsync(new ChainContext { - await _consensusService.TriggerConsensusAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }); - } + BlockHash = blockHash, + BlockHeight = blockHeight + }); } } \ No newline at end of file diff --git a/src/AElf.Kernel/GlobalUsings.cs b/src/AElf.Kernel/GlobalUsings.cs new file mode 100644 index 0000000000..833a5d8b45 --- /dev/null +++ b/src/AElf.Kernel/GlobalUsings.cs @@ -0,0 +1,7 @@ +global using Google.Protobuf; +global using AElf.Types; +global using System.Threading.Tasks; +global using Volo.Abp.DependencyInjection; +global using Volo.Abp.EventBus; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging.Abstractions; \ No newline at end of file diff --git a/src/AElf.Kernel/InitialSyncFinishedEventHandler.cs b/src/AElf.Kernel/InitialSyncFinishedEventHandler.cs index a623b1e987..7311cf9c58 100644 --- a/src/AElf.Kernel/InitialSyncFinishedEventHandler.cs +++ b/src/AElf.Kernel/InitialSyncFinishedEventHandler.cs @@ -1,25 +1,21 @@ -using System.Threading.Tasks; using AElf.Kernel.CodeCheck; using AElf.Kernel.Node.Events; using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class InitialSyncFinishedEventHandler : ILocalEventHandler, ITransientDependency { - public class InitialSyncFinishedEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly CodeCheckOptions _codeCheckOptions; + private readonly CodeCheckOptions _codeCheckOptions; - public InitialSyncFinishedEventHandler(IOptionsMonitor codeCheckOptionsMonitor) - { - _codeCheckOptions = codeCheckOptionsMonitor.CurrentValue; - } + public InitialSyncFinishedEventHandler(IOptionsMonitor codeCheckOptionsMonitor) + { + _codeCheckOptions = codeCheckOptionsMonitor.CurrentValue; + } - public Task HandleEventAsync(InitialSyncFinishedEvent eventData) - { - _codeCheckOptions.CodeCheckEnabled = true; - return Task.CompletedTask; - } + public Task HandleEventAsync(InitialSyncFinishedEvent eventData) + { + _codeCheckOptions.CodeCheckEnabled = true; + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.Kernel/KernelAElfModule.cs b/src/AElf.Kernel/KernelAElfModule.cs index e7e8bcc0aa..d587922d61 100644 --- a/src/AElf.Kernel/KernelAElfModule.cs +++ b/src/AElf.Kernel/KernelAElfModule.cs @@ -1,45 +1,43 @@ -using AElf.Kernel.Configuration; using AElf.Kernel.ChainController; +using AElf.Kernel.Configuration; using AElf.Kernel.Miner; using AElf.Kernel.Node; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContractExecution; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.TransactionPool; using AElf.Modularity; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Modularity; -using Microsoft.Extensions.DependencyInjection; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(CoreKernelAElfModule), + typeof(ChainControllerAElfModule), + typeof(SmartContractAElfModule), + typeof(NodeAElfModule), + typeof(SmartContractExecutionAElfModule), + typeof(TransactionPoolAElfModule), + typeof(ConfigurationAElfModule), + typeof(ProposalAElfModule)) +] +public class KernelAElfModule : AElfModule { - [DependsOn( - typeof(CoreKernelAElfModule), - typeof(ChainControllerAElfModule), - typeof(SmartContractAElfModule), - typeof(NodeAElfModule), - typeof(SmartContractExecutionAElfModule), - typeof(TransactionPoolAElfModule), - typeof(ConfigurationAElfModule), - typeof(ProposalAElfModule)) - ] - public class KernelAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(typeof(IConfigurationProcessor), - typeof(BlockTransactionLimitConfigurationProcessor)); - } + context.Services.AddTransient(typeof(IConfigurationProcessor), + typeof(BlockTransactionLimitConfigurationProcessor)); + } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var taskQueueManager = context.ServiceProvider.GetService(); + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var taskQueueManager = context.ServiceProvider.GetService(); - taskQueueManager.CreateQueue(KernelConstants.MergeBlockStateQueueName); - taskQueueManager.CreateQueue(KernelConstants.ConsensusRequestMiningQueueName); - taskQueueManager.CreateQueue(KernelConstants.UpdateChainQueueName); - taskQueueManager.CreateQueue(KernelConstants.ChainCleaningQueueName); - } + taskQueueManager!.CreateQueue(KernelConstants.MergeBlockStateQueueName); + taskQueueManager.CreateQueue(KernelConstants.ConsensusRequestMiningQueueName); + taskQueueManager.CreateQueue(KernelConstants.UpdateChainQueueName); + taskQueueManager.CreateQueue(KernelConstants.ChainCleaningQueueName); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/BlockAcceptedEventHandler.cs b/src/AElf.Kernel/Miner/Application/BlockAcceptedEventHandler.cs index 91714c67a1..14e18dbf83 100644 --- a/src/AElf.Kernel/Miner/Application/BlockAcceptedEventHandler.cs +++ b/src/AElf.Kernel/Miner/Application/BlockAcceptedEventHandler.cs @@ -1,26 +1,22 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.SmartContract.Application; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class BlockAcceptedEventHandler : ILocalEventHandler, ITransientDependency { - public class BlockAcceptedEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly ILogEventProcessingService _logEventProcessingService; + private readonly ILogEventProcessingService _logEventProcessingService; - public BlockAcceptedEventHandler( - ILogEventProcessingService logEventProcessingService) - { - _logEventProcessingService = logEventProcessingService; - } + public BlockAcceptedEventHandler( + ILogEventProcessingService logEventProcessingService) + { + _logEventProcessingService = logEventProcessingService; + } - public async Task HandleEventAsync(BlockAcceptedEvent eventData) - { - await _logEventProcessingService.ProcessAsync(new List {eventData.BlockExecutedSet}); - } + public async Task HandleEventAsync(BlockAcceptedEvent eventData) + { + await _logEventProcessingService.ProcessAsync(new List { eventData.BlockExecutedSet }); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/BlockTemplateMinerService.cs b/src/AElf.Kernel/Miner/Application/BlockTemplateMinerService.cs index 5ed13546c8..a5437ee176 100644 --- a/src/AElf.Kernel/Miner/Application/BlockTemplateMinerService.cs +++ b/src/AElf.Kernel/Miner/Application/BlockTemplateMinerService.cs @@ -1,54 +1,48 @@ using System; -using System.Threading.Tasks; using AElf.Kernel.Account.Application; -using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Miner.Application -{ - public class BlockTemplateMinerService : IBlockTemplateMinerService, ISingletonDependency - { - private Block _blockCache = null; +namespace AElf.Kernel.Miner.Application; - private readonly IMinerService _minerService; +public class BlockTemplateMinerService : IBlockTemplateMinerService, ISingletonDependency +{ + private readonly IAccountService _accountService; - private readonly IAccountService _accountService; + private readonly IMinerService _minerService; + private Block _blockCache; - public BlockTemplateMinerService(IMinerService minerService, IAccountService accountService) - { - _minerService = minerService; - _accountService = accountService; - } + public BlockTemplateMinerService(IMinerService minerService, IAccountService accountService) + { + _minerService = minerService; + _accountService = accountService; + } - public async Task CreateTemplateCacheAsync(Hash previousBlockHash, long previousBlockHeight, - Timestamp blockTime, Duration blockExecutionTime) - { - _blockCache = - (await _minerService.MineAsync(previousBlockHash, previousBlockHeight, blockTime, blockExecutionTime)) - .Block; + public async Task CreateTemplateCacheAsync(Hash previousBlockHash, long previousBlockHeight, + Timestamp blockTime, Duration blockExecutionTime) + { + _blockCache = + (await _minerService.MineAsync(previousBlockHash, previousBlockHeight, blockTime, blockExecutionTime)) + .Block; - _blockCache.Header.Signature = ByteString.Empty; + _blockCache.Header.Signature = ByteString.Empty; - return _blockCache.Header; - } + return _blockCache.Header; + } - public async Task ChangeTemplateCacheBlockHeaderAndClearCacheAsync(BlockHeader blockHeader) - { - var block = _blockCache.Clone(); + public async Task ChangeTemplateCacheBlockHeaderAndClearCacheAsync(BlockHeader blockHeader) + { + var block = _blockCache.Clone(); - if (block == null || block.Header.PreviousBlockHash != blockHeader.PreviousBlockHash || - block.Header.MerkleTreeRootOfTransactions != blockHeader.MerkleTreeRootOfTransactions || - block.Header.Time != blockHeader.Time) - throw new InvalidOperationException("template cache not match"); + if (block == null || block.Header.PreviousBlockHash != blockHeader.PreviousBlockHash || + block.Header.MerkleTreeRootOfTransactions != blockHeader.MerkleTreeRootOfTransactions || + block.Header.Time != blockHeader.Time) + throw new InvalidOperationException("template cache not match"); - //same block - block.Header = blockHeader; - block.Header.Signature = - ByteString.CopyFrom(await _accountService.SignAsync(block.GetHash().ToByteArray())); + //same block + block.Header = blockHeader; + block.Header.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(block.GetHash().ToByteArray())); - return block; - } + return block; } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/BlockValidationProvider.cs b/src/AElf.Kernel/Miner/Application/BlockValidationProvider.cs index cef5206043..14ef8ffd59 100644 --- a/src/AElf.Kernel/Miner/Application/BlockValidationProvider.cs +++ b/src/AElf.Kernel/Miner/Application/BlockValidationProvider.cs @@ -1,43 +1,41 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class BlockValidationProvider : IBlockValidationProvider { - public class BlockValidationProvider : IBlockValidationProvider - { - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly int _systemTransactionCount; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly int _systemTransactionCount; - public BlockValidationProvider(IBlockTransactionLimitProvider blockTransactionLimitProvider, - IEnumerable systemTransactionGenerators) - { - _blockTransactionLimitProvider = blockTransactionLimitProvider; - _systemTransactionCount = systemTransactionGenerators.Count(); - } + public BlockValidationProvider(IBlockTransactionLimitProvider blockTransactionLimitProvider, + IEnumerable systemTransactionGenerators) + { + _blockTransactionLimitProvider = blockTransactionLimitProvider; + _systemTransactionCount = systemTransactionGenerators.Count(); + } - public Task ValidateBeforeAttachAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBeforeAttachAsync(IBlock block) + { + return Task.FromResult(true); + } - public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + public async Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + var txCountLimit = await _blockTransactionLimitProvider.GetLimitAsync(new ChainContext { - var txCountLimit = await _blockTransactionLimitProvider.GetLimitAsync(new ChainContext - { - BlockHash = block.Header.PreviousBlockHash, - BlockHeight = block.Header.Height - 1 - }); + BlockHash = block.Header.PreviousBlockHash, + BlockHeight = block.Header.Height - 1 + }); - return Math.Max(txCountLimit, _systemTransactionCount) >= block.TransactionIds.Count(); - } + return Math.Max(txCountLimit, _systemTransactionCount) >= block.TransactionIds.Count(); + } - public Task ValidateBlockAfterExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockAfterExecuteAsync(IBlock block) + { + return Task.FromResult(true); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/BlocksExecutionSucceededEventHandler.cs b/src/AElf.Kernel/Miner/Application/BlocksExecutionSucceededEventHandler.cs index 42af7e66d1..fb775aee25 100644 --- a/src/AElf.Kernel/Miner/Application/BlocksExecutionSucceededEventHandler.cs +++ b/src/AElf.Kernel/Miner/Application/BlocksExecutionSucceededEventHandler.cs @@ -1,24 +1,21 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContractExecution.Events; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class BlocksExecutionSucceededEventHandler : ILocalEventHandler, + ITransientDependency { - public class BlocksExecutionSucceededEventHandler : ILocalEventHandler, - ITransientDependency - { - private readonly ILogEventProcessingService _logEventProcessingService; + private readonly ILogEventProcessingService _logEventProcessingService; - public BlocksExecutionSucceededEventHandler(ILogEventProcessingService logEventProcessingService) - { - _logEventProcessingService = logEventProcessingService; - } + public BlocksExecutionSucceededEventHandler( + ILogEventProcessingService logEventProcessingService) + { + _logEventProcessingService = logEventProcessingService; + } - public async Task HandleEventAsync(BlocksExecutionSucceededEvent eventData) - { - await _logEventProcessingService.ProcessAsync(eventData.BlockExecutedSets); - } + public async Task HandleEventAsync(BlocksExecutionSucceededEvent eventData) + { + await _logEventProcessingService.ProcessAsync(eventData.BlockExecutedSets); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/IBlockTemplateMinerService.cs b/src/AElf.Kernel/Miner/Application/IBlockTemplateMinerService.cs index 1f71e9f867..c46e24f685 100644 --- a/src/AElf.Kernel/Miner/Application/IBlockTemplateMinerService.cs +++ b/src/AElf.Kernel/Miner/Application/IBlockTemplateMinerService.cs @@ -1,15 +1,11 @@ -using System.Threading.Tasks; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Miner.Application -{ - public interface IBlockTemplateMinerService - { - Task CreateTemplateCacheAsync(Hash previousBlockHash, long previousBlockHeight, - Timestamp blockTime, - Duration blockExecutionTime); +namespace AElf.Kernel.Miner.Application; - Task ChangeTemplateCacheBlockHeaderAndClearCacheAsync(BlockHeader blockHeader); - } +public interface IBlockTemplateMinerService +{ + Task CreateTemplateCacheAsync(Hash previousBlockHash, long previousBlockHeight, + Timestamp blockTime, Duration blockExecutionTime); + + Task ChangeTemplateCacheBlockHeaderAndClearCacheAsync(BlockHeader blockHeader); } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/IMinerService.cs b/src/AElf.Kernel/Miner/Application/IMinerService.cs index edcc9edc0e..5f6202c280 100644 --- a/src/AElf.Kernel/Miner/Application/IMinerService.cs +++ b/src/AElf.Kernel/Miner/Application/IMinerService.cs @@ -1,18 +1,14 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain; -using AElf.Kernel.SmartContractExecution; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public interface IMinerService { - public interface IMinerService - { - /// - /// This method mines a block. - /// - /// The block that has been produced. - Task MineAsync(Hash previousBlockHash, long previousBlockHeight, Timestamp blockTime, - Duration blockExecutionTime); - } + /// + /// This method mines a block. + /// + /// The block that has been produced. + Task MineAsync(Hash previousBlockHash, long previousBlockHeight, Timestamp blockTime, + Duration blockExecutionTime); } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/IMiningRequestService.cs b/src/AElf.Kernel/Miner/Application/IMiningRequestService.cs index 36b40c39ed..72bb7b990b 100644 --- a/src/AElf.Kernel/Miner/Application/IMiningRequestService.cs +++ b/src/AElf.Kernel/Miner/Application/IMiningRequestService.cs @@ -1,71 +1,70 @@ using System; -using System.Threading.Tasks; using AElf.CSharp.Core.Extension; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public interface IMiningRequestService { - public interface IMiningRequestService - { - Task RequestMiningAsync(ConsensusRequestMiningDto requestMiningDto); - } + Task RequestMiningAsync(ConsensusRequestMiningDto requestMiningDto); +} - public class ConsensusRequestMiningDto - { - public Hash PreviousBlockHash { get; set; } - public long PreviousBlockHeight { get; set; } - public Duration BlockExecutionTime { get; set; } - public Timestamp BlockTime { get; set; } - public Timestamp MiningDueTime { get; set; } - } +public class ConsensusRequestMiningDto +{ + public Hash PreviousBlockHash { get; set; } + public long PreviousBlockHeight { get; set; } + public Duration BlockExecutionTime { get; set; } + public Timestamp BlockTime { get; set; } + public Timestamp MiningDueTime { get; set; } +} - public class MiningRequestService : IMiningRequestService +public class MiningRequestService : IMiningRequestService +{ + private readonly IMinerService _minerService; + + public MiningRequestService(IMinerService minerService) { - private readonly IMinerService _minerService; - public ILogger Logger { get; set; } + _minerService = minerService; + } - public MiningRequestService(IMinerService minerService) - { - _minerService = minerService; - } + public ILogger Logger { get; set; } - public async Task RequestMiningAsync(ConsensusRequestMiningDto requestMiningDto) - { - if (!ValidateBlockMiningTime(requestMiningDto.BlockTime, requestMiningDto.MiningDueTime, + public async Task RequestMiningAsync(ConsensusRequestMiningDto requestMiningDto) + { + if (!ValidateBlockMiningTime(requestMiningDto.BlockTime, requestMiningDto.MiningDueTime, requestMiningDto.BlockExecutionTime)) - return null; + return null; - var blockExecutionDuration = - CalculateBlockMiningDuration(requestMiningDto.BlockTime, requestMiningDto.BlockExecutionTime); + var blockExecutionDuration = + CalculateBlockMiningDuration(requestMiningDto.BlockTime, requestMiningDto.BlockExecutionTime); - var block = (await _minerService.MineAsync(requestMiningDto.PreviousBlockHash, - requestMiningDto.PreviousBlockHeight, requestMiningDto.BlockTime, blockExecutionDuration)).Block; + var block = (await _minerService.MineAsync(requestMiningDto.PreviousBlockHash, + requestMiningDto.PreviousBlockHeight, requestMiningDto.BlockTime, blockExecutionDuration)).Block; - return block; - } + return block; + } - private bool ValidateBlockMiningTime(Timestamp blockTime, Timestamp miningDueTime, - Duration blockExecutionDuration) + private bool ValidateBlockMiningTime(Timestamp blockTime, Timestamp miningDueTime, + Duration blockExecutionDuration) + { + if (miningDueTime - Duration.FromTimeSpan(TimeSpan.FromMilliseconds(250)) < + blockTime + blockExecutionDuration) { - if (miningDueTime - Duration.FromTimeSpan(TimeSpan.FromMilliseconds(250)) < - blockTime + blockExecutionDuration) - { - Logger.LogDebug( - $"Mining canceled because mining time slot expired. MiningDueTime: {miningDueTime}, BlockTime: {blockTime}, Duration: {blockExecutionDuration}"); - return false; - } - - if (blockTime + blockExecutionDuration >= TimestampHelper.GetUtcNow()) return true; - Logger.LogDebug($"Will cancel mining due to timeout: Actual mining time: {blockTime}, " + - $"execution limit: {blockExecutionDuration.Milliseconds()} ms."); + Logger.LogDebug( + "Mining canceled because mining time slot expired. MiningDueTime: {MiningDueTime}, BlockTime: {BlockTime}, Duration: {BlockExecutionDuration}", + miningDueTime, blockTime, blockExecutionDuration); return false; } - private Duration CalculateBlockMiningDuration(Timestamp blockTime, Duration expectedDuration) - { - return blockTime + expectedDuration - TimestampHelper.GetUtcNow(); - } + if (blockTime + blockExecutionDuration >= TimestampHelper.GetUtcNow()) return true; + Logger.LogDebug( + "Will cancel mining due to timeout: Actual mining time: {BlockTime}, execution limit: {BlockExecutionDuration} ms", + blockTime, blockExecutionDuration.Milliseconds()); + return false; + } + + private Duration CalculateBlockMiningDuration(Timestamp blockTime, Duration expectedDuration) + { + return blockTime + expectedDuration - TimestampHelper.GetUtcNow(); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/IMiningService.cs b/src/AElf.Kernel/Miner/Application/IMiningService.cs index ea96fec3ab..6166baa0db 100644 --- a/src/AElf.Kernel/Miner/Application/IMiningService.cs +++ b/src/AElf.Kernel/Miner/Application/IMiningService.cs @@ -1,19 +1,15 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Blockchain; -using AElf.Kernel.SmartContractExecution; -using AElf.Kernel.SmartContractExecution.Application; -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public interface IMiningService { - public interface IMiningService - { - /// - /// This method mines a block. - /// - /// The block that has been produced. - Task MineAsync(RequestMiningDto requestMiningDto, List transactions, Timestamp blockTime); - } + /// + /// This method mines a block. + /// + /// The block that has been produced. + Task MineAsync(RequestMiningDto requestMiningDto, List transactions, + Timestamp blockTime); } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/MinerService.cs b/src/AElf.Kernel/Miner/Application/MinerService.cs index f971cc0dca..db6c813232 100644 --- a/src/AElf.Kernel/Miner/Application/MinerService.cs +++ b/src/AElf.Kernel/Miner/Application/MinerService.cs @@ -1,73 +1,69 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Blockchain; using AElf.Kernel.TransactionPool.Application; using AElf.Kernel.Txn.Application; using Google.Protobuf.WellKnownTypes; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class MinerService : IMinerService { - public class MinerService : IMinerService + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly IMiningService _miningService; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + private readonly ITransactionPoolService _transactionPoolService; + + public MinerService(IMiningService miningService, + IBlockTransactionLimitProvider blockTransactionLimitProvider, + ITransactionPackingOptionProvider transactionPackingOptionProvider, + ITransactionPoolService transactionPoolService) { - public ILogger Logger { get; set; } - private readonly ITransactionPoolService _transactionPoolService; - private readonly IMiningService _miningService; - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + _miningService = miningService; + _blockTransactionLimitProvider = blockTransactionLimitProvider; + _transactionPackingOptionProvider = transactionPackingOptionProvider; + _transactionPoolService = transactionPoolService; - public MinerService(IMiningService miningService, - IBlockTransactionLimitProvider blockTransactionLimitProvider, - ITransactionPackingOptionProvider transactionPackingOptionProvider, - ITransactionPoolService transactionPoolService) - { - _miningService = miningService; - _blockTransactionLimitProvider = blockTransactionLimitProvider; - _transactionPackingOptionProvider = transactionPackingOptionProvider; - _transactionPoolService = transactionPoolService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - /// - /// - /// Mine process. - /// - /// - public async Task MineAsync(Hash previousBlockHash, long previousBlockHeight, - Timestamp blockTime, - Duration blockExecutionTime) - { - var txList = new List(); - - var chainContext = new ChainContext - { - BlockHash = previousBlockHash, - BlockHeight = previousBlockHeight - }; + /// + /// + /// Mine process. + /// + /// + public async Task MineAsync(Hash previousBlockHash, long previousBlockHeight, + Timestamp blockTime, + Duration blockExecutionTime) + { + var txList = new List(); - var limit = await _blockTransactionLimitProvider.GetLimitAsync(chainContext); - if (_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) - { - var executableTransactionSet = await _transactionPoolService.GetExecutableTransactionSetAsync( - previousBlockHash, limit); + var chainContext = new ChainContext + { + BlockHash = previousBlockHash, + BlockHeight = previousBlockHeight + }; - txList.AddRange(executableTransactionSet.Transactions); - } - + var limit = await _blockTransactionLimitProvider.GetLimitAsync(chainContext); + if (_transactionPackingOptionProvider.IsTransactionPackable(chainContext)) + { + var executableTransactionSet = await _transactionPoolService.GetExecutableTransactionSetAsync( + previousBlockHash, limit); - Logger.LogInformation( - $"Start mining with previous hash: {previousBlockHash}, previous height: {previousBlockHeight}."); - return await _miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = previousBlockHash, - PreviousBlockHeight = previousBlockHeight, - BlockExecutionTime = blockExecutionTime, - TransactionCountLimit = limit - }, txList, blockTime); + txList.AddRange(executableTransactionSet.Transactions); } + + Logger.LogInformation( + "Start mining with previous hash: {PreviousBlockHash}, previous height: {PreviousBlockHeight}", + previousBlockHash, previousBlockHeight); + return await _miningService.MineAsync( + new RequestMiningDto + { + PreviousBlockHash = previousBlockHash, + PreviousBlockHeight = previousBlockHeight, + BlockExecutionTime = blockExecutionTime, + TransactionCountLimit = limit + }, txList, blockTime); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/MiningService.cs b/src/AElf.Kernel/Miner/Application/MiningService.cs index 80704823f5..72123a6643 100644 --- a/src/AElf.Kernel/Miner/Application/MiningService.cs +++ b/src/AElf.Kernel/Miner/Application/MiningService.cs @@ -2,146 +2,137 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContractExecution.Application; -using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class MiningService : IMiningService { - public class MiningService : IMiningService + private readonly IAccountService _accountService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockGenerationService _blockGenerationService; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ISystemTransactionGenerationService _systemTransactionGenerationService; + + public MiningService(IAccountService accountService, + IBlockGenerationService blockGenerationService, + ISystemTransactionGenerationService systemTransactionGenerationService, + IBlockExecutingService blockExecutingService, + IBlockchainService blockchainService, + ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) { - public ILogger Logger { get; set; } - private readonly ISystemTransactionGenerationService _systemTransactionGenerationService; - private readonly IBlockGenerationService _blockGenerationService; - private readonly IAccountService _accountService; - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; - - public ILocalEventBus EventBus { get; set; } - - public MiningService(IAccountService accountService, - IBlockGenerationService blockGenerationService, - ISystemTransactionGenerationService systemTransactionGenerationService, - IBlockExecutingService blockExecutingService, - IBlockchainService blockchainService, - ISystemTransactionExtraDataProvider systemTransactionExtraDataProvider) - { - Logger = NullLogger.Instance; - _blockGenerationService = blockGenerationService; - _systemTransactionGenerationService = systemTransactionGenerationService; - _blockExecutingService = blockExecutingService; - _accountService = accountService; - _blockchainService = blockchainService; - _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; - - EventBus = NullLocalEventBus.Instance; - } + Logger = NullLogger.Instance; + _blockGenerationService = blockGenerationService; + _systemTransactionGenerationService = systemTransactionGenerationService; + _blockExecutingService = blockExecutingService; + _accountService = accountService; + _blockchainService = blockchainService; + _systemTransactionExtraDataProvider = systemTransactionExtraDataProvider; + + EventBus = NullLocalEventBus.Instance; + } - private async Task> GenerateSystemTransactions(Hash previousBlockHash, - long previousBlockHeight) - { - var address = Address.FromPublicKey(await _accountService.GetPublicKeyAsync()); - var systemTransactions = await _systemTransactionGenerationService.GenerateSystemTransactionsAsync(address, - previousBlockHeight, previousBlockHash); + public ILogger Logger { get; set; } - foreach (var transaction in systemTransactions) + public ILocalEventBus EventBus { get; set; } + + public async Task MineAsync(RequestMiningDto requestMiningDto, List transactions, + Timestamp blockTime) + { + try + { + using var cts = new CancellationTokenSource(); + var expirationTime = blockTime + requestMiningDto.BlockExecutionTime; + if (expirationTime < TimestampHelper.GetUtcNow()) { - await SignAsync(transaction); + cts.Cancel(); } + else + { + var ts = (expirationTime - TimestampHelper.GetUtcNow()).ToTimeSpan(); + if (ts.TotalMilliseconds > int.MaxValue) ts = TimeSpan.FromMilliseconds(int.MaxValue); - await _blockchainService.AddTransactionsAsync(systemTransactions); + cts.CancelAfter(ts); + } - return systemTransactions; + var block = await GenerateBlock(requestMiningDto.PreviousBlockHash, + requestMiningDto.PreviousBlockHeight, blockTime); + var systemTransactions = await GenerateSystemTransactions(requestMiningDto.PreviousBlockHash, + requestMiningDto.PreviousBlockHeight); + _systemTransactionExtraDataProvider.SetSystemTransactionCount(systemTransactions.Count, + block.Header); + var txTotalCount = transactions.Count + systemTransactions.Count; + + var pending = txTotalCount > requestMiningDto.TransactionCountLimit + ? transactions + .Take(requestMiningDto.TransactionCountLimit - systemTransactions.Count) + .ToList() + : transactions; + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, + systemTransactions, pending, cts.Token); + + block = blockExecutedSet.Block; + await SignBlockAsync(block); + Logger.LogInformation("Generated block: {Block}, " + + "previous: {PreviousBlockHash}, " + + "executed transactions: {TransactionsCount}, " + + "not executed transactions {NotExecutedTransactionsCount}", + block.ToDiagnosticString(), block.Header.PreviousBlockHash, block.Body.TransactionsCount, + pending.Count + systemTransactions.Count - block.Body.TransactionsCount); + return blockExecutedSet; } - - private async Task SignAsync(Transaction notSignerTransaction) + catch (Exception e) { - var signature = await _accountService.SignAsync(notSignerTransaction.GetHash().ToByteArray()); - notSignerTransaction.Signature = ByteString.CopyFrom(signature); + Logger.LogError(e, "Failed while mining block"); + throw; } + } - /// - /// Generate block - /// - /// - private async Task GenerateBlock(Hash preBlockHash, long preBlockHeight, Timestamp expectedMiningTime) - { - var block = await _blockGenerationService.GenerateBlockBeforeExecutionAsync(new GenerateBlockDto - { - PreviousBlockHash = preBlockHash, - PreviousBlockHeight = preBlockHeight, - BlockTime = expectedMiningTime - }); - block.Header.SignerPubkey = ByteString.CopyFrom(await _accountService.GetPublicKeyAsync()); - return block; - } + private async Task> GenerateSystemTransactions(Hash previousBlockHash, + long previousBlockHeight) + { + var address = Address.FromPublicKey(await _accountService.GetPublicKeyAsync()); + var systemTransactions = await _systemTransactionGenerationService.GenerateSystemTransactionsAsync(address, + previousBlockHeight, previousBlockHash); - private async Task SignBlockAsync(Block block) - { - var signature = await _accountService.SignAsync(block.GetHash().ToByteArray()); - block.Header.Signature = ByteString.CopyFrom(signature); - } + foreach (var transaction in systemTransactions) await SignAsync(transaction); + + await _blockchainService.AddTransactionsAsync(systemTransactions); + + return systemTransactions; + } - public async Task MineAsync(RequestMiningDto requestMiningDto, List transactions, - Timestamp blockTime) + private async Task SignAsync(Transaction notSignerTransaction) + { + var signature = await _accountService.SignAsync(notSignerTransaction.GetHash().ToByteArray()); + notSignerTransaction.Signature = ByteString.CopyFrom(signature); + } + + /// + /// Generate block + /// + /// + private async Task GenerateBlock(Hash preBlockHash, long preBlockHeight, Timestamp expectedMiningTime) + { + var block = await _blockGenerationService.GenerateBlockBeforeExecutionAsync(new GenerateBlockDto { - try - { - using (var cts = new CancellationTokenSource()) - { - var expirationTime = blockTime + requestMiningDto.BlockExecutionTime; - if (expirationTime < TimestampHelper.GetUtcNow()) - cts.Cancel(); - else - { - var ts = (expirationTime - TimestampHelper.GetUtcNow()).ToTimeSpan(); - if (ts.TotalMilliseconds > int.MaxValue) - { - ts = TimeSpan.FromMilliseconds(int.MaxValue); - } - - cts.CancelAfter(ts); - } - - var block = await GenerateBlock(requestMiningDto.PreviousBlockHash, - requestMiningDto.PreviousBlockHeight, blockTime); - var systemTransactions = await GenerateSystemTransactions(requestMiningDto.PreviousBlockHash, - requestMiningDto.PreviousBlockHeight); - _systemTransactionExtraDataProvider.SetSystemTransactionCount(systemTransactions.Count, - block.Header); - var txTotalCount = transactions.Count + systemTransactions.Count; - - var pending = txTotalCount > requestMiningDto.TransactionCountLimit - ? transactions - .Take(requestMiningDto.TransactionCountLimit - systemTransactions.Count) - .ToList() - : transactions; - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, - systemTransactions, pending, cts.Token); - - block = blockExecutedSet.Block; - await SignBlockAsync(block); - Logger.LogInformation($"Generated block: {block.ToDiagnosticString()}, " + - $"previous: {block.Header.PreviousBlockHash}, " + - $"executed transactions: {block.Body.TransactionsCount}, " + - $"not executed transactions {pending.Count + systemTransactions.Count - block.Body.TransactionsCount} "); - return blockExecutedSet; - } - } - catch (Exception e) - { - Logger.LogError(e, "Failed while mining block."); - throw; - } - } + PreviousBlockHash = preBlockHash, + PreviousBlockHeight = preBlockHeight, + BlockTime = expectedMiningTime + }); + block.Header.SignerPubkey = ByteString.CopyFrom(await _accountService.GetPublicKeyAsync()); + return block; + } + + private async Task SignBlockAsync(Block block) + { + var signature = await _accountService.SignAsync(block.GetHash().ToByteArray()); + block.Header.Signature = ByteString.CopyFrom(signature); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Application/TxPoolInterestedEventsHandler.cs b/src/AElf.Kernel/Miner/Application/TxPoolInterestedEventsHandler.cs index 06f873ff47..bea33da017 100644 --- a/src/AElf.Kernel/Miner/Application/TxPoolInterestedEventsHandler.cs +++ b/src/AElf.Kernel/Miner/Application/TxPoolInterestedEventsHandler.cs @@ -1,44 +1,39 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Events; -using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.TransactionPool; using AElf.Kernel.TransactionPool.Application; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class TxPoolInterestedEventsHandler : ILocalEventHandler, + ILocalEventHandler, + ILocalEventHandler, + ILocalEventHandler, + ITransientDependency { - public class TxPoolInterestedEventsHandler : ILocalEventHandler, - ILocalEventHandler, - ILocalEventHandler, - ILocalEventHandler, - ITransientDependency - { - private readonly ITransactionPoolService _transactionPoolService; + private readonly ITransactionPoolService _transactionPoolService; - public TxPoolInterestedEventsHandler(ITransactionPoolService transactionPoolService) - { - _transactionPoolService = transactionPoolService; - } + public TxPoolInterestedEventsHandler(ITransactionPoolService transactionPoolService) + { + _transactionPoolService = transactionPoolService; + } - public async Task HandleEventAsync(TransactionsReceivedEvent eventData) - { - await _transactionPoolService.AddTransactionsAsync(eventData.Transactions); - } + public async Task HandleEventAsync(BestChainFoundEventData eventData) + { + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(eventData.BlockHash, eventData.BlockHeight); + } - public async Task HandleEventAsync(BlockAcceptedEvent eventData) - { - await _transactionPoolService.CleanByTransactionIdsAsync(eventData.Block.TransactionIds); - } + public async Task HandleEventAsync(BlockAcceptedEvent eventData) + { + await _transactionPoolService.CleanByTransactionIdsAsync(eventData.Block.TransactionIds); + } - public async Task HandleEventAsync(BestChainFoundEventData eventData) - { - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(eventData.BlockHash, eventData.BlockHeight); - } + public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + await _transactionPoolService.UpdateTransactionPoolByLibAsync(eventData.BlockHeight); + } - public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) - { - await _transactionPoolService.UpdateTransactionPoolByLibAsync(eventData.BlockHeight); - } + public async Task HandleEventAsync(TransactionsReceivedEvent eventData) + { + await _transactionPoolService.AddTransactionsAsync(eventData.Transactions); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/BlockTransactionLimitConfigurationProcessor.cs b/src/AElf.Kernel/Miner/BlockTransactionLimitConfigurationProcessor.cs index 6252d17ffe..08284edf39 100644 --- a/src/AElf.Kernel/Miner/BlockTransactionLimitConfigurationProcessor.cs +++ b/src/AElf.Kernel/Miner/BlockTransactionLimitConfigurationProcessor.cs @@ -1,29 +1,24 @@ -using System.Threading.Tasks; using AElf.Kernel.Configuration; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +public class BlockTransactionLimitConfigurationProcessor : IConfigurationProcessor, ITransientDependency { - public class BlockTransactionLimitConfigurationProcessor : IConfigurationProcessor, ITransientDependency - { - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - public BlockTransactionLimitConfigurationProcessor(IBlockTransactionLimitProvider blockTransactionLimitProvider) - { - _blockTransactionLimitProvider = blockTransactionLimitProvider; - } + public BlockTransactionLimitConfigurationProcessor(IBlockTransactionLimitProvider blockTransactionLimitProvider) + { + _blockTransactionLimitProvider = blockTransactionLimitProvider; + } + public string ConfigurationName => "BlockTransactionLimit"; - public string ConfigurationName => "BlockTransactionLimit"; - - public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) - { - var limit = new Int32Value(); - limit.MergeFrom(byteString); - if (limit.Value < 0) return; - await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, limit.Value); - } + public async Task ProcessConfigurationAsync(ByteString byteString, BlockIndex blockIndex) + { + var limit = new Int32Value(); + limit.MergeFrom(byteString); + if (limit.Value < 0) return; + await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, limit.Value); } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/BlockTransactionLimitProvider.cs b/src/AElf.Kernel/Miner/BlockTransactionLimitProvider.cs index e1b5d6bcc2..c82aa7c522 100644 --- a/src/AElf.Kernel/Miner/BlockTransactionLimitProvider.cs +++ b/src/AElf.Kernel/Miner/BlockTransactionLimitProvider.cs @@ -1,58 +1,55 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; -using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +public interface IBlockTransactionLimitProvider +{ + Task GetLimitAsync(IBlockIndex blockIndex); + Task SetLimitAsync(IBlockIndex blockIndex, int limit); +} + +internal class BlockTransactionLimitProvider : BlockExecutedDataBaseProvider, + IBlockTransactionLimitProvider, + ISingletonDependency { - public interface IBlockTransactionLimitProvider + private const string BlockExecutedDataName = "BlockTransactionLimit"; + private readonly int _systemTransactionCount; + + public BlockTransactionLimitProvider( + ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService, + IEnumerable systemTransactionGenerators) : base( + cachedBlockchainExecutedDataService) { - Task GetLimitAsync(IBlockIndex blockIndex); - Task SetLimitAsync(IBlockIndex blockIndex, int limit); + _systemTransactionCount = systemTransactionGenerators.Count(); } - internal class BlockTransactionLimitProvider : BlockExecutedDataBaseProvider, IBlockTransactionLimitProvider, - ISingletonDependency + public ILogger Logger { get; set; } + + public Task GetLimitAsync(IBlockIndex blockIndex) { - private const string BlockExecutedDataName = "BlockTransactionLimit"; - private readonly int _systemTransactionCount; - - public ILogger Logger { get; set; } - - public BlockTransactionLimitProvider( - ICachedBlockchainExecutedDataService cachedBlockchainExecutedDataService, - IEnumerable systemTransactionGenerators) : base( - cachedBlockchainExecutedDataService) - { - _systemTransactionCount = systemTransactionGenerators.Count(); - } + var limit = GetBlockExecutedData(blockIndex); + return Task.FromResult(limit?.Value ?? int.MaxValue); + } - public Task GetLimitAsync(IBlockIndex blockIndex) - { - var limit = GetBlockExecutedData(blockIndex); - return Task.FromResult(limit?.Value ?? int.MaxValue); - } + public async Task SetLimitAsync(IBlockIndex blockIndex, int limit) + { + if (limit <= _systemTransactionCount) + return; - public async Task SetLimitAsync(IBlockIndex blockIndex, int limit) - { - if (limit <= _systemTransactionCount) - return; - - var blockTransactionLimit = new Int32Value - { - Value = limit - }; - await AddBlockExecutedDataAsync(blockIndex, blockTransactionLimit); - Logger.LogDebug($"BlockTransactionLimit has been changed to {limit}"); - } - - protected override string GetBlockExecutedDataName() + var blockTransactionLimit = new Int32Value { - return BlockExecutedDataName; - } + Value = limit + }; + await AddBlockExecutedDataAsync(blockIndex, blockTransactionLimit); + Logger.LogDebug($"BlockTransactionLimit has been changed to {limit}"); + } + + protected override string GetBlockExecutedDataName() + { + return BlockExecutedDataName; } } \ No newline at end of file diff --git a/src/AElf.Kernel/Miner/Dto/RequestMiningDto.cs b/src/AElf.Kernel/Miner/Dto/RequestMiningDto.cs index 1c857293ac..cc3f72111f 100644 --- a/src/AElf.Kernel/Miner/Dto/RequestMiningDto.cs +++ b/src/AElf.Kernel/Miner/Dto/RequestMiningDto.cs @@ -1,16 +1,14 @@ -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +public class RequestMiningDto { - public class RequestMiningDto - { - public Hash PreviousBlockHash { get; set; } + public Hash PreviousBlockHash { get; set; } + + public long PreviousBlockHeight { get; set; } - public long PreviousBlockHeight { get; set; } + public Duration BlockExecutionTime { get; set; } - public Duration BlockExecutionTime { get; set; } - - public int TransactionCountLimit { get; set; } - } + public int TransactionCountLimit { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel/NewIrreversibleBlockFoundEventHandler.cs b/src/AElf.Kernel/NewIrreversibleBlockFoundEventHandler.cs index a0d62a59a4..313616a680 100644 --- a/src/AElf.Kernel/NewIrreversibleBlockFoundEventHandler.cs +++ b/src/AElf.Kernel/NewIrreversibleBlockFoundEventHandler.cs @@ -1,95 +1,87 @@ using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Events; -using AElf.Types; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; using Volo.Abp.EventBus.Local; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, + ITransientDependency { - public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, - ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IChainBlockLinkService _chainBlockLinkService; + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + private readonly ITaskQueueManager _taskQueueManager; + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + + public NewIrreversibleBlockFoundEventHandler(ITaskQueueManager taskQueueManager, + IBlockchainStateService blockchainStateService, + IBlockchainService blockchainService, + ITransactionBlockIndexService transactionBlockIndexService, + IChainBlockLinkService chainBlockLinkService, + ISmartContractExecutiveService smartContractExecutiveService) { - private readonly ITaskQueueManager _taskQueueManager; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - private readonly IChainBlockLinkService _chainBlockLinkService; - private readonly ISmartContractExecutiveService _smartContractExecutiveService; - public ILogger Logger { get; set; } - public ILocalEventBus LocalEventBus { get; set; } + _taskQueueManager = taskQueueManager; + _blockchainStateService = blockchainStateService; + _blockchainService = blockchainService; + _transactionBlockIndexService = transactionBlockIndexService; + _chainBlockLinkService = chainBlockLinkService; + _smartContractExecutiveService = smartContractExecutiveService; + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + } - public NewIrreversibleBlockFoundEventHandler(ITaskQueueManager taskQueueManager, - IBlockchainStateService blockchainStateService, - IBlockchainService blockchainService, - ITransactionBlockIndexService transactionBlockIndexService, - IChainBlockLinkService chainBlockLinkService, - ISmartContractExecutiveService smartContractExecutiveService) - { - _taskQueueManager = taskQueueManager; - _blockchainStateService = blockchainStateService; - _blockchainService = blockchainService; - _transactionBlockIndexService = transactionBlockIndexService; - _chainBlockLinkService = chainBlockLinkService; - _smartContractExecutiveService = smartContractExecutiveService; - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; - } + public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } - public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + _taskQueueManager.Enqueue(async () => { - _taskQueueManager.Enqueue(async () => - { - await _blockchainStateService.MergeBlockStateAsync(eventData.BlockHeight, - eventData.BlockHash); - - CleanChain(eventData.BlockHash, eventData.BlockHeight); - }, KernelConstants.MergeBlockStateQueueName); + await _blockchainStateService.MergeBlockStateAsync(eventData.BlockHeight, + eventData.BlockHash); - return Task.CompletedTask; - } + CleanChain(eventData.BlockHash, eventData.BlockHeight); + }, KernelConstants.MergeBlockStateQueueName); - private void CleanChain(Hash irreversibleBlockHash, long irreversibleBlockHeight) + return Task.CompletedTask; + } + + private void CleanChain(Hash irreversibleBlockHash, long irreversibleBlockHeight) + { + _taskQueueManager.Enqueue(async () => { - _taskQueueManager.Enqueue(async () => - { - // Clean BlockStateSet - var discardedBlockHashes = _chainBlockLinkService.GetCachedChainBlockLinks() - .Where(b => b.Height <= irreversibleBlockHeight).Select(b => b.BlockHash).ToList(); - await _blockchainStateService.RemoveBlockStateSetsAsync(discardedBlockHashes); - - // Clean chain branch - var chain = await _blockchainService.GetChainAsync(); - var discardedBranch = await _blockchainService.GetDiscardedBranchAsync(chain); + // Clean BlockStateSet + var discardedBlockHashes = _chainBlockLinkService.GetCachedChainBlockLinks() + .Where(b => b.Height <= irreversibleBlockHeight).Select(b => b.BlockHash).ToList(); + await _blockchainStateService.RemoveBlockStateSetsAsync(discardedBlockHashes); + + // Clean chain branch + var chain = await _blockchainService.GetChainAsync(); + var discardedBranch = await _blockchainService.GetDiscardedBranchAsync(chain); - _taskQueueManager.Enqueue( - async () => + _taskQueueManager.Enqueue( + async () => + { + if (discardedBranch.BranchKeys.Count > 0 || discardedBranch.NotLinkedKeys.Count > 0) + await _blockchainService.CleanChainBranchAsync(discardedBranch); + + await LocalEventBus.PublishAsync(new CleanBlockExecutedDataChangeHeightEventData { - if (discardedBranch.BranchKeys.Count > 0 || discardedBranch.NotLinkedKeys.Count > 0) - { - await _blockchainService.CleanChainBranchAsync(discardedBranch); - } + IrreversibleBlockHeight = irreversibleBlockHeight + }); + _chainBlockLinkService.CleanCachedChainBlockLinks(irreversibleBlockHeight); + }, + KernelConstants.UpdateChainQueueName); + + // Clean transaction block index cache + await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(irreversibleBlockHeight); - await LocalEventBus.PublishAsync(new CleanBlockExecutedDataChangeHeightEventData - { - IrreversibleBlockHeight = irreversibleBlockHeight - }); - _chainBlockLinkService.CleanCachedChainBlockLinks(irreversibleBlockHeight); - }, - KernelConstants.UpdateChainQueueName); - - // Clean transaction block index cache - await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(irreversibleBlockHeight); - - // Clean idle executive - _smartContractExecutiveService.CleanIdleExecutive(); - }, KernelConstants.ChainCleaningQueueName); - } + // Clean idle executive + _smartContractExecutiveService.CleanIdleExecutive(); + }, KernelConstants.ChainCleaningQueueName); } } \ No newline at end of file diff --git a/src/AElf.Launcher/AElf.Launcher.csproj b/src/AElf.Launcher/AElf.Launcher.csproj index 9282c6483e..0f4c8d7fd4 100644 --- a/src/AElf.Launcher/AElf.Launcher.csproj +++ b/src/AElf.Launcher/AElf.Launcher.csproj @@ -5,19 +5,19 @@ true - - + + Always - PreserveNewest + PreserveNewest - - - + + + @@ -41,8 +41,8 @@ PreserveNewest - PreserveNewest - PreserveNewest + PreserveNewest + PreserveNewest PreserveNewest diff --git a/src/AElf.Launcher/Program.cs b/src/AElf.Launcher/Program.cs index a5ace54b4e..b9c13a4a2b 100644 --- a/src/AElf.Launcher/Program.cs +++ b/src/AElf.Launcher/Program.cs @@ -1,67 +1,66 @@ using System; using System.IO; using System.Reflection; -using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.Launcher +namespace AElf.Launcher; + +internal class Program { - class Program + private static void RegisterAssemblyResolveEvent() { - private static void RegisterAssemblyResolveEvent() - { - AppDomain currentDomain = AppDomain.CurrentDomain; + var currentDomain = AppDomain.CurrentDomain; - currentDomain.AssemblyResolve += OnAssemblyResolve; - } + currentDomain.AssemblyResolve += OnAssemblyResolve; + } - private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + { + var folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); + if (!File.Exists(assemblyPath)) { - var folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); - if (!File.Exists(assemblyPath)) + if (assemblyPath.Contains("Contract")) { - if (assemblyPath.Contains("Contract")) - { - assemblyPath = assemblyPath.Substring(0, - assemblyPath.IndexOf("bin", StringComparison.Ordinal) - 1); - assemblyPath = Path.Combine(assemblyPath, "contracts", new AssemblyName(args.Name).Name + ".dll"); - } - else - return null; + assemblyPath = assemblyPath.Substring(0, + assemblyPath.IndexOf("bin", StringComparison.Ordinal) - 1); + assemblyPath = Path.Combine(assemblyPath, "contracts", new AssemblyName(args.Name).Name + ".dll"); + } + else + { + return null; } - - var assembly = Assembly.LoadFrom(assemblyPath); - return assembly; } - public static void Main(string[] args) + var assembly = Assembly.LoadFrom(assemblyPath); + return assembly; + } + + public static void Main(string[] args) + { + RegisterAssemblyResolveEvent(); + ILogger logger = NullLogger.Instance; + try { - RegisterAssemblyResolveEvent(); - ILogger logger = NullLogger.Instance; - try - { - CreateHostBuilder(args).Build().Run(); - } - catch (Exception e) - { - if (logger == NullLogger.Instance) - Console.WriteLine(e); - logger.LogCritical(e, "program crashed"); - } + CreateHostBuilder(args).Build().Run(); + } + catch (Exception e) + { + if (logger == NullLogger.Instance) + Console.WriteLine(e); + logger.LogCritical(e, "program crashed"); } + } - // create default https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs - private static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureLogging(builder => - { - builder.ClearProviders(); - }) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }) - .UseAutofac(); + // create default https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs + private static IHostBuilder CreateHostBuilder(string[] args) + { + return Host.CreateDefaultBuilder(args) + .ConfigureLogging(builder => { builder.ClearProviders(); }) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }) + .UseAutofac(); } } \ No newline at end of file diff --git a/src/AElf.Launcher/Startup.cs b/src/AElf.Launcher/Startup.cs index d796cefe13..1c293abd9a 100644 --- a/src/AElf.Launcher/Startup.cs +++ b/src/AElf.Launcher/Startup.cs @@ -11,72 +11,68 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Launcher +namespace AElf.Launcher; + +public class Startup { - public class Startup + private const string DefaultCorsPolicyName = "CorsPolicy"; + private readonly IConfiguration _configuration; + + public Startup(IConfiguration configuration) { - private readonly IConfiguration _configuration; - private const string DefaultCorsPolicyName = "CorsPolicy"; + _configuration = configuration; + } - public Startup(IConfiguration configuration) + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + var chainType = _configuration.GetValue("ChainType", ChainType.MainChain); + switch (chainType) { - _configuration = configuration; + case ChainType.SideChain: + AddApplication(services); + break; + default: + AddApplication(services); + break; } - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) + services.AddCors(options => { - var chainType = _configuration.GetValue("ChainType", ChainType.MainChain); - switch (chainType) + options.AddPolicy(DefaultCorsPolicyName, builder => { - case ChainType.SideChain: - AddApplication(services); - break; - default: - AddApplication(services); - break; - } - - services.AddCors(options => - { - options.AddPolicy(DefaultCorsPolicyName, builder => - { - builder - .WithOrigins(_configuration["CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() - ) - .WithAbpExposedHeaders() - .AllowAnyHeader() - .AllowAnyMethod(); - if (_configuration["CorsOrigins"] != "*") - { - builder.AllowCredentials(); - } - }); + builder + .WithOrigins(_configuration["CorsOrigins"] + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .AllowAnyHeader() + .AllowAnyMethod(); + if (_configuration["CorsOrigins"] != "*") builder.AllowCredentials(); }); - } + }); + } - private static void AddApplication(IServiceCollection services) where T : IAbpModule - { - services.AddApplication(); - } + private static void AddApplication(IServiceCollection services) where T : IAbpModule + { + services.AddApplication(); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - // ReSharper disable once UnusedMember.Global - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - var cultureInfo = CultureInfo.InvariantCulture; - CultureInfo.DefaultThreadCurrentCulture = cultureInfo; + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + // ReSharper disable once UnusedMember.Global + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + var cultureInfo = CultureInfo.InvariantCulture; + CultureInfo.DefaultThreadCurrentCulture = cultureInfo; - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - app.UseCors(DefaultCorsPolicyName); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseCors(DefaultCorsPolicyName); - app.InitializeApplication(); - } + app.InitializeApplication(); } } \ No newline at end of file diff --git a/src/AElf.Launcher/appsettings.MainChain.CustomNet.json b/src/AElf.Launcher/appsettings.MainChain.CustomNet.json index 3ac2885c52..da313cde56 100644 --- a/src/AElf.Launcher/appsettings.MainChain.CustomNet.json +++ b/src/AElf.Launcher/appsettings.MainChain.CustomNet.json @@ -1,18 +1,18 @@ { - "ChainId": "CUST", - "Economic": { - "Symbol": "CUSTOM", - "Name": "custom token", - "TotalSupply": 1000000000000000000, - "Decimals": 8, - "IsBurnable": true, - "DividendPoolRatio": 0.12, - "LockForElection": 10000000000000 - }, - "CrossChain": { - "Grpc": { - "ParentChainServerPort": 5000, - "ListeningPort": 5010 - } + "ChainId": "CUST", + "Economic": { + "Symbol": "CUSTOM", + "Name": "custom token", + "TotalSupply": 1000000000000000000, + "Decimals": 8, + "IsBurnable": true, + "DividendPoolRatio": 0.12, + "LockForElection": 10000000000000 + }, + "CrossChain": { + "Grpc": { + "ParentChainServerPort": 5000, + "ListeningPort": 5010 } + } } \ No newline at end of file diff --git a/src/AElf.Launcher/appsettings.MainChain.MainNet.json b/src/AElf.Launcher/appsettings.MainChain.MainNet.json index fd933a1c91..5d9ead6291 100644 --- a/src/AElf.Launcher/appsettings.MainChain.MainNet.json +++ b/src/AElf.Launcher/appsettings.MainChain.MainNet.json @@ -1,20 +1,20 @@ { - "ChainId": "AELF", - "Economic": { - "Symbol": "ELF", - "TokenName": "elf token", - "TotalSupply": 100000000000000000, - "Decimals": 8, - "IsBurnable": true, - "DividendPoolRatio": 0.12, - "MinimumLockTime": 7776000, - "MaximumLockTime": 93312000, - "SymbolListToPayTxFee": "WRITE,READ,STORAGE,TRAFFIC", - "SymbolListToPayRental": "CPU,RAM,DISK,NET" - }, - "CrossChain": { - "Grpc": { - "ListeningPort": 5000 - } + "ChainId": "AELF", + "Economic": { + "Symbol": "ELF", + "TokenName": "elf token", + "TotalSupply": 100000000000000000, + "Decimals": 8, + "IsBurnable": true, + "DividendPoolRatio": 0.12, + "MinimumLockTime": 7776000, + "MaximumLockTime": 93312000, + "SymbolListToPayTxFee": "WRITE,READ,STORAGE,TRAFFIC", + "SymbolListToPayRental": "CPU,RAM,DISK,NET" + }, + "CrossChain": { + "Grpc": { + "ListeningPort": 5000 } + } } \ No newline at end of file diff --git a/src/AElf.Launcher/appsettings.MainChain.TestNet.json b/src/AElf.Launcher/appsettings.MainChain.TestNet.json index 81b8ade9ca..dc587066cd 100644 --- a/src/AElf.Launcher/appsettings.MainChain.TestNet.json +++ b/src/AElf.Launcher/appsettings.MainChain.TestNet.json @@ -1,17 +1,17 @@ { - "ChainId": "TELF", - "Economic": { - "Symbol": "TELF", - "Name": "elf test token", - "TotalSupply": 1000000000000000000, - "Decimals": 8, - "IsBurnable": true, - "DividendPoolRatio": 0.12, - "LockForElection": 10000000000000 - }, - "CrossChain": { - "Grpc": { - "ListeningPort": 5000 - } + "ChainId": "TELF", + "Economic": { + "Symbol": "TELF", + "Name": "elf test token", + "TotalSupply": 1000000000000000000, + "Decimals": 8, + "IsBurnable": true, + "DividendPoolRatio": 0.12, + "LockForElection": 10000000000000 + }, + "CrossChain": { + "Grpc": { + "ListeningPort": 5000 } + } } \ No newline at end of file diff --git a/src/AElf.Launcher/appsettings.Production.json b/src/AElf.Launcher/appsettings.Production.json index b561ef6346..14aeb670bf 100644 --- a/src/AElf.Launcher/appsettings.Production.json +++ b/src/AElf.Launcher/appsettings.Production.json @@ -4,6 +4,6 @@ "StateDb": "redis://localhost:6379?db=1" }, "WebApp": { - "TransactionResultStatusCacheSeconds" : 180 + "TransactionResultStatusCacheSeconds": 180 } } diff --git a/src/AElf.Launcher/appsettings.SideChain.CustomNet.json b/src/AElf.Launcher/appsettings.SideChain.CustomNet.json index 95cfdc9b8c..57760023f0 100644 --- a/src/AElf.Launcher/appsettings.SideChain.CustomNet.json +++ b/src/AElf.Launcher/appsettings.SideChain.CustomNet.json @@ -1,13 +1,13 @@ { - "Contract": { - "ContractDeploymentAuthorityRequired": false + "Contract": { + "ContractDeploymentAuthorityRequired": false + }, + "CrossChain": { + "Grpc": { + "ParentChainServerPort": 5000, + "ListeningPort": 5010, + "ParentChainServerIp": "" }, - "CrossChain": { - "Grpc": { - "ParentChainServerPort": 5000, - "ListeningPort": 5010, - "ParentChainServerIp": "" - }, - "ParentChainId": "" - } + "ParentChainId": "" + } } \ No newline at end of file diff --git a/src/AElf.Launcher/appsettings.json b/src/AElf.Launcher/appsettings.json index 3a14308ffc..80b0e93f8f 100644 --- a/src/AElf.Launcher/appsettings.json +++ b/src/AElf.Launcher/appsettings.json @@ -33,20 +33,18 @@ "Transaction": { "PoolLimit": 10240 }, - "BasicAuth": { - "UserName" : "", + "UserName": "", "Password": "" }, - "Logging": { "LogLevel": { "Default": "Information", "System": "Error", "Microsoft": "Error", - "AElf.OS" : "Information", - "AElf.Kernel.Consensus" : "Information", - "AElf" : "Information" + "AElf.OS": "Information", + "AElf.Kernel.Consensus": "Information", + "AElf": "Information" } } } \ No newline at end of file diff --git a/src/AElf.OS.Core/AElf.OS.Core.csproj b/src/AElf.OS.Core/AElf.OS.Core.csproj index 47ea5135a5..794614116f 100644 --- a/src/AElf.OS.Core/AElf.OS.Core.csproj +++ b/src/AElf.OS.Core/AElf.OS.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.OS @@ -8,8 +8,8 @@ Core module for the OS layer. - - + + diff --git a/src/AElf.OS.Core/AccountOptions.cs b/src/AElf.OS.Core/AccountOptions.cs index 91e7b2c888..4bc09ff9db 100644 --- a/src/AElf.OS.Core/AccountOptions.cs +++ b/src/AElf.OS.Core/AccountOptions.cs @@ -1,8 +1,7 @@ -namespace AElf.OS +namespace AElf.OS; + +public class AccountOptions { - public class AccountOptions - { - public string NodeAccount { get; set; } - public string NodeAccountPassword { get; set; } - } + public string NodeAccount { get; set; } + public string NodeAccountPassword { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/CoreOSAElfModule.cs b/src/AElf.OS.Core/CoreOSAElfModule.cs index 02acfc199a..16e3e1026e 100644 --- a/src/AElf.OS.Core/CoreOSAElfModule.cs +++ b/src/AElf.OS.Core/CoreOSAElfModule.cs @@ -1,30 +1,28 @@ using AElf.Kernel; -using AElf.Kernel.Token; using AElf.Modularity; using AElf.OS.Network; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS +namespace AElf.OS; + +[DependsOn(typeof(CoreKernelAElfModule))] +public class CoreOSAElfModule : AElfModule { - [DependsOn(typeof(CoreKernelAElfModule))] - public class CoreOSAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); + var configuration = context.Services.GetConfiguration(); - Configure(configuration.GetSection("Network")); - } + Configure(configuration.GetSection("Network")); + } - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var taskQueueManager = context.ServiceProvider.GetService(); - taskQueueManager.CreateQueue(NetworkConstants.PeerReconnectionQueueName); - taskQueueManager.CreateQueue(NetworkConstants.BlockBroadcastQueueName); - taskQueueManager.CreateQueue(NetworkConstants.AnnouncementBroadcastQueueName); - taskQueueManager.CreateQueue(NetworkConstants.TransactionBroadcastQueueName); - } + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var taskQueueManager = context.ServiceProvider.GetService(); + taskQueueManager.CreateQueue(NetworkConstants.PeerReconnectionQueueName); + taskQueueManager.CreateQueue(NetworkConstants.BlockBroadcastQueueName); + taskQueueManager.CreateQueue(NetworkConstants.AnnouncementBroadcastQueueName); + taskQueueManager.CreateQueue(NetworkConstants.TransactionBroadcastQueueName); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/EconomicOptions.cs b/src/AElf.OS.Core/EconomicOptions.cs index fdb2336ce7..d159b3b76e 100644 --- a/src/AElf.OS.Core/EconomicOptions.cs +++ b/src/AElf.OS.Core/EconomicOptions.cs @@ -1,18 +1,17 @@ -namespace AElf.OS +namespace AElf.OS; + +public class EconomicOptions { - public class EconomicOptions - { - // Native Token Related - public string Symbol { get; set; } = "ELF"; - public string TokenName { get; set; } = "Native Token"; - public long TotalSupply { get; set; } = 1_000_000_000_00000000; - public int Decimals { get; set; } = 8; - public bool IsBurnable { get; set; } = true; - public double DividendPoolRatio { get; set; } = 0.12; + // Native Token Related + public string Symbol { get; set; } = "ELF"; + public string TokenName { get; set; } = "Native Token"; + public long TotalSupply { get; set; } = 1_000_000_000_00000000; + public int Decimals { get; set; } = 8; + public bool IsBurnable { get; set; } = true; + public double DividendPoolRatio { get; set; } = 0.12; - public long TransactionSizeFeeUnitPrice { get; set; } = 1000; + public long TransactionSizeFeeUnitPrice { get; set; } = 1000; - public long MaximumLockTime { get; set; } = 1080 * 86400; - public long MinimumLockTime { get; set; } = 90 * 86400; - } + public long MaximumLockTime { get; set; } = 1080 * 86400; + public long MinimumLockTime { get; set; } = 90 * 86400; } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/INetworkService.cs b/src/AElf.OS.Core/Network/Application/INetworkService.cs index 55118a1bbd..af015e10ee 100644 --- a/src/AElf.OS.Core/Network/Application/INetworkService.cs +++ b/src/AElf.OS.Core/Network/Application/INetworkService.cs @@ -4,26 +4,28 @@ using AElf.OS.Network.Types; using AElf.Types; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public interface INetworkService { - public interface INetworkService - { - Task AddPeerAsync(string endpoint); - Task AddTrustedPeerAsync(string endpoint); - Task RemovePeerByEndpointAsync(string endpoint, - int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds); - Task RemovePeerByPubkeyAsync(string peerPubkey, - int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds); - List GetPeers(bool includeFailing = true); - PeerInfo GetPeerByPubkey(string peerPubkey); - Task> GetBlockByHashAsync(Hash hash, string peerPubkey = null); - Task>> GetBlocksAsync(Hash previousBlock, int count, string peerPubkey = null); - Task BroadcastAnnounceAsync(BlockHeader blockHeader); - Task BroadcastTransactionAsync(Transaction transaction); - Task BroadcastBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions); - Task BroadcastLibAnnounceAsync(Hash libHash, long libHeight); - Task CheckPeersHealthAsync(); - void CheckNtpDrift(); - bool IsPeerPoolFull(); - } + Task AddPeerAsync(string endpoint); + Task AddTrustedPeerAsync(string endpoint); + + Task RemovePeerByEndpointAsync(string endpoint, + int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds); + + Task RemovePeerByPubkeyAsync(string peerPubkey, + int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds); + + List GetPeers(bool includeFailing = true); + PeerInfo GetPeerByPubkey(string peerPubkey); + Task> GetBlockByHashAsync(Hash hash, string peerPubkey = null); + Task>> GetBlocksAsync(Hash previousBlock, int count, string peerPubkey = null); + Task BroadcastAnnounceAsync(BlockHeader blockHeader); + Task BroadcastTransactionAsync(Transaction transaction); + Task BroadcastBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions); + Task BroadcastLibAnnounceAsync(Hash libHash, long libHeight); + Task CheckPeersHealthAsync(); + void CheckNtpDrift(); + bool IsPeerPoolFull(); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/IPeerDiscoveryService.cs b/src/AElf.OS.Core/Network/Application/IPeerDiscoveryService.cs index 0a44d520d9..6947b0c0b6 100644 --- a/src/AElf.OS.Core/Network/Application/IPeerDiscoveryService.cs +++ b/src/AElf.OS.Core/Network/Application/IPeerDiscoveryService.cs @@ -1,12 +1,11 @@ using System.Threading.Tasks; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public interface IPeerDiscoveryService { - public interface IPeerDiscoveryService - { - Task DiscoverNodesAsync(); - Task RefreshNodeAsync(); - Task GetNodesAsync(int maxCount); - Task AddNodeAsync(NodeInfo nodeInfo); - } + Task DiscoverNodesAsync(); + Task RefreshNodeAsync(); + Task GetNodesAsync(int maxCount); + Task AddNodeAsync(NodeInfo nodeInfo); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/IPeerInvalidTransactionProcessingService.cs b/src/AElf.OS.Core/Network/Application/IPeerInvalidTransactionProcessingService.cs index 1027281d56..6d6d00676b 100644 --- a/src/AElf.OS.Core/Network/Application/IPeerInvalidTransactionProcessingService.cs +++ b/src/AElf.OS.Core/Network/Application/IPeerInvalidTransactionProcessingService.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public interface IPeerInvalidTransactionProcessingService { - public interface IPeerInvalidTransactionProcessingService - { - Task ProcessPeerInvalidTransactionAsync(Hash transactionId); - } + Task ProcessPeerInvalidTransactionAsync(Hash transactionId); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/IReconnectionService.cs b/src/AElf.OS.Core/Network/Application/IReconnectionService.cs index 2e7cadb97a..d5d9bb36a5 100644 --- a/src/AElf.OS.Core/Network/Application/IReconnectionService.cs +++ b/src/AElf.OS.Core/Network/Application/IReconnectionService.cs @@ -6,72 +6,72 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public interface IReconnectionService +{ + bool SchedulePeerForReconnection(string endpoint); + bool CancelReconnection(string endpoint); + List GetPeersReadyForReconnection(Timestamp maxTime); + ReconnectingPeer GetReconnectingPeer(string endpoint); +} + +public class ReconnectionService : IReconnectionService { - public interface IReconnectionService + private readonly IPeerReconnectionStateProvider _reconnectionStateProvider; + + public ReconnectionService(IPeerReconnectionStateProvider reconnectionStateProvider) { - bool SchedulePeerForReconnection(string endpoint); - bool CancelReconnection(string endpoint); - List GetPeersReadyForReconnection(Timestamp maxTime); - ReconnectingPeer GetReconnectingPeer(string endpoint); + _reconnectionStateProvider = reconnectionStateProvider; } - public class ReconnectionService : IReconnectionService + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + + public ILogger Logger { get; set; } + + public List GetPeersReadyForReconnection(Timestamp maxTime) { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - - public ILogger Logger { get; set; } - - private readonly IPeerReconnectionStateProvider _reconnectionStateProvider; - - public ReconnectionService(IPeerReconnectionStateProvider reconnectionStateProvider) - { - _reconnectionStateProvider = reconnectionStateProvider; - } + return _reconnectionStateProvider.GetPeersReadyForReconnection(maxTime); + } - public List GetPeersReadyForReconnection(Timestamp maxTime) - { - return _reconnectionStateProvider.GetPeersReadyForReconnection(maxTime); - } + public ReconnectingPeer GetReconnectingPeer(string endpoint) + { + return _reconnectionStateProvider.GetReconnectingPeer(endpoint); + } + + public bool SchedulePeerForReconnection(string endpoint) + { + var nextTry = TimestampHelper.GetUtcNow().AddMilliseconds(NetworkOptions.PeerReconnectionPeriod); + + Logger.LogDebug($"Scheduling {endpoint} for reconnection at {nextTry}."); - public ReconnectingPeer GetReconnectingPeer(string endpoint) + var reconnectingPeer = new ReconnectingPeer { - return _reconnectionStateProvider.GetReconnectingPeer(endpoint); - } + Endpoint = endpoint, + NextAttempt = nextTry, + DisconnectionTime = TimestampHelper.GetUtcNow() + }; - public bool SchedulePeerForReconnection(string endpoint) + if (!_reconnectionStateProvider.AddReconnectingPeer(endpoint, reconnectingPeer)) { - var nextTry = TimestampHelper.GetUtcNow().AddMilliseconds(NetworkOptions.PeerReconnectionPeriod); - - Logger.LogDebug($"Scheduling {endpoint} for reconnection at {nextTry}."); - - var reconnectingPeer = new ReconnectingPeer { - Endpoint = endpoint, - NextAttempt = nextTry, - DisconnectionTime = TimestampHelper.GetUtcNow() - }; - - if (!_reconnectionStateProvider.AddReconnectingPeer(endpoint, reconnectingPeer)) - { - Logger.LogWarning($"Reconnection scheduling failed to {endpoint}."); - return false; - } - - return true; + Logger.LogWarning($"Reconnection scheduling failed to {endpoint}."); + return false; } - public bool CancelReconnection(string endpoint) + return true; + } + + public bool CancelReconnection(string endpoint) + { + if (!_reconnectionStateProvider.RemoveReconnectionPeer(endpoint)) { - if (!_reconnectionStateProvider.RemoveReconnectionPeer(endpoint)) - { - Logger.LogWarning($"Could not find reconnection {endpoint}"); - return false; - } - - Logger.LogDebug($"Successfully canceled reconnection {endpoint}"); - - return true; + Logger.LogWarning($"Could not find reconnection {endpoint}"); + return false; } + + Logger.LogDebug($"Successfully canceled reconnection {endpoint}"); + + return true; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/ISyncStateService.cs b/src/AElf.OS.Core/Network/Application/ISyncStateService.cs index 5706a24a6f..041ce150f4 100644 --- a/src/AElf.OS.Core/Network/Application/ISyncStateService.cs +++ b/src/AElf.OS.Core/Network/Application/ISyncStateService.cs @@ -8,161 +8,170 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public interface ISyncStateService +{ + SyncState SyncState { get; } + long GetCurrentSyncTarget(); + Task StartSyncAsync(); + Task UpdateSyncStateAsync(); +} + +public enum SyncState { - public interface ISyncStateService + UnInitialized, + Syncing, + Finished +} + +public class SyncStateService : ISyncStateService, ISingletonDependency +{ + private readonly IBlockchainNodeContextService _blockchainNodeContextService; + private readonly IBlockchainService _blockchainService; + private readonly IPeerPool _peerPool; + + private readonly INodeSyncStateProvider _syncStateProvider; + + public SyncStateService(INodeSyncStateProvider syncStateProvider, IBlockchainService blockchainService, + IBlockchainNodeContextService blockchainNodeContextService, IPeerPool peerPool) { - SyncState SyncState { get; } - long GetCurrentSyncTarget(); - Task StartSyncAsync(); - Task UpdateSyncStateAsync(); + _syncStateProvider = syncStateProvider; + _blockchainService = blockchainService; + _blockchainNodeContextService = blockchainNodeContextService; + _peerPool = peerPool; } - public enum SyncState { UnInitialized, Syncing, Finished } + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + + public ILogger Logger { get; set; } - public class SyncStateService : ISyncStateService, ISingletonDependency + public long GetCurrentSyncTarget() { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - - private readonly INodeSyncStateProvider _syncStateProvider; - private readonly IBlockchainService _blockchainService; - private readonly IBlockchainNodeContextService _blockchainNodeContextService; - private readonly IPeerPool _peerPool; - - public ILogger Logger { get; set; } - - public SyncStateService(INodeSyncStateProvider syncStateProvider, IBlockchainService blockchainService, - IBlockchainNodeContextService blockchainNodeContextService, IPeerPool peerPool) - { - _syncStateProvider = syncStateProvider; - _blockchainService = blockchainService; - _blockchainNodeContextService = blockchainNodeContextService; - _peerPool = peerPool; - } - - public long GetCurrentSyncTarget() => _syncStateProvider.SyncTarget; + return _syncStateProvider.SyncTarget; + } - public SyncState SyncState + public SyncState SyncState + { + get { - get + switch (_syncStateProvider.SyncTarget) { - switch (_syncStateProvider.SyncTarget) - { - case 0: - return SyncState.UnInitialized; - case -1: - return SyncState.Finished; - default: - return SyncState.Syncing; - } + case 0: + return SyncState.UnInitialized; + case -1: + return SyncState.Finished; + default: + return SyncState.Syncing; } } - - private void SetSyncTarget(long value) => _syncStateProvider.SetSyncTarget(value); - - /// - /// Based on current peers, will determine if a sync is needed or not. This method - /// should only be called once, to go from an uninitialized state to either syncing - /// or not syncing. - /// - /// - public async Task StartSyncAsync() - { - if (SyncState != SyncState.UnInitialized) - { - Logger.LogWarning("Trying to start the sync, but it has already been started/finished."); - return; - } + } - await UpdateSyncTargetAsync(); + /// + /// Based on current peers, will determine if a sync is needed or not. This method + /// should only be called once, to go from an uninitialized state to either syncing + /// or not syncing. + /// + /// + public async Task StartSyncAsync() + { + if (SyncState != SyncState.UnInitialized) + { + Logger.LogWarning("Trying to start the sync, but it has already been started/finished."); + return; } - /// - /// Updates the current target for the initial sync. For now this method will - /// not have any effect if the sync is already finished or the target has not - /// been initialized. - /// - /// - public async Task UpdateSyncStateAsync() + await UpdateSyncTargetAsync(); + } + + /// + /// Updates the current target for the initial sync. For now this method will + /// not have any effect if the sync is already finished or the target has not + /// been initialized. + /// + /// + public async Task UpdateSyncStateAsync() + { + // This method should only be called when the sync target has already been found and the + // node is syncing. + + if (SyncState != SyncState.Syncing) { - // This method should only be called when the sync target has already been found and the - // node is syncing. - - if (SyncState != SyncState.Syncing) - { - Logger.LogWarning("Trying to update the sync, but it is either finished or not yet been initialized."); - return; - } - - var chain = await _blockchainService.GetChainAsync(); - - // if the current best chain height is higher than the recorded target, - // check the peers current LIB height. Note that this condition will - // also be true when the node starts. - if (chain.BestChainHeight >= _syncStateProvider.SyncTarget) - { - await UpdateSyncTargetAsync(); - } + Logger.LogWarning("Trying to update the sync, but it is either finished or not yet been initialized."); + return; } - /// - /// Based on the given list of peer, will update the sync target. It take the peers that have an LIB higher - /// than (our LIB + offset), these constitute the possible nodes to sync to. If this group constitutes at - /// least ceil(2/3 * peer_count), take the one with the smallest LIB as target. Like this: - /// peer count: 1, nodes that must be higher: 1 - Note: if only one peer, sync. - /// peer count: 2, nodes that must be higher: 2 - /// peer count: 3, nodes that must be higher: 2 - /// peer count: 4, nodes that must be higher: 3 - /// - /// - private async Task UpdateSyncTargetAsync() + var chain = await _blockchainService.GetChainAsync(); + + // if the current best chain height is higher than the recorded target, + // check the peers current LIB height. Note that this condition will + // also be true when the node starts. + if (chain.BestChainHeight >= _syncStateProvider.SyncTarget) await UpdateSyncTargetAsync(); + } + + private void SetSyncTarget(long value) + { + _syncStateProvider.SetSyncTarget(value); + } + + /// + /// Based on the given list of peer, will update the sync target. It take the peers that have an LIB higher + /// than (our LIB + offset), these constitute the possible nodes to sync to. If this group constitutes at + /// least ceil(2/3 * peer_count), take the one with the smallest LIB as target. Like this: + /// peer count: 1, nodes that must be higher: 1 - Note: if only one peer, sync. + /// peer count: 2, nodes that must be higher: 2 + /// peer count: 3, nodes that must be higher: 2 + /// peer count: 4, nodes that must be higher: 3 + /// + /// + private async Task UpdateSyncTargetAsync() + { + // set the target to the lowest LIB + var chain = await _blockchainService.GetChainAsync(); + var peers = _peerPool.GetPeers().ToList(); + + var minSyncTarget = chain.LastIrreversibleBlockHeight + NetworkOptions.InitialSyncOffset; + + // determine the peers that are high enough to sync to + var candidates = peers + .Where(p => p.LastKnownLibHeight >= minSyncTarget) + .OrderBy(p => p.LastKnownLibHeight) + .ToList(); + + if (candidates.Count == 0) + { + // no peer has a LIB to sync to, stop the sync. + await SetSyncAsFinishedAsync(); + Logger.LogInformation( + $"Finishing sync, not enough peers have a sufficiently high LIB (peer count: {_peerPool.PeerCount})."); + } + else { - // set the target to the lowest LIB - var chain = await _blockchainService.GetChainAsync(); - var peers = _peerPool.GetPeers().ToList(); - - long minSyncTarget = chain.LastIrreversibleBlockHeight + NetworkOptions.InitialSyncOffset; - - // determine the peers that are high enough to sync to - var candidates = peers - .Where(p => p.LastKnownLibHeight >= minSyncTarget) - .OrderBy(p => p.LastKnownLibHeight) - .ToList(); - - if (candidates.Count == 0) + // If there's more than 2/3 of the nodes that we can + // sync to, take the lowest of them as target. + var minLib = candidates.First().LastKnownLibHeight; + + if (candidates.Count >= Math.Ceiling(2d / 3 * peers.Count)) { - // no peer has a LIB to sync to, stop the sync. - await SetSyncAsFinishedAsync(); - Logger.LogInformation($"Finishing sync, not enough peers have a sufficiently high LIB (peer count: {_peerPool.PeerCount})."); + SetSyncTarget(minLib); + Logger.LogDebug($"Set sync target to {minLib}."); } else { - // If there's more than 2/3 of the nodes that we can - // sync to, take the lowest of them as target. - var minLib = candidates.First().LastKnownLibHeight; - - if (candidates.Count >= Math.Ceiling(2d/3 * peers.Count)) - { - SetSyncTarget(minLib); - Logger.LogDebug($"Set sync target to {minLib}."); - } - else - { - await SetSyncAsFinishedAsync(); - Logger.LogInformation("Finishing sync, no peer has as a LIB high enough."); - } + await SetSyncAsFinishedAsync(); + Logger.LogInformation("Finishing sync, no peer has as a LIB high enough."); } } - - /// - /// Finalizes the sync by changing the target to -1 and launching the - /// notifying the Kernel of this change. - /// - private async Task SetSyncAsFinishedAsync() - { - SetSyncTarget(-1); - await _blockchainNodeContextService.FinishInitialSyncAsync(); - } + } + + /// + /// Finalizes the sync by changing the target to -1 and launching the + /// notifying the Kernel of this change. + /// + private async Task SetSyncAsFinishedAsync() + { + SetSyncTarget(-1); + await _blockchainNodeContextService.FinishInitialSyncAsync(); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/NetworkService.cs b/src/AElf.OS.Core/Network/Application/NetworkService.cs index 8eeb5f9299..deab564cbd 100644 --- a/src/AElf.OS.Core/Network/Application/NetworkService.cs +++ b/src/AElf.OS.Core/Network/Application/NetworkService.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Consensus.Application; @@ -11,412 +10,401 @@ using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +/// +/// Exposes networking functionality to the application handlers. +/// +public class NetworkService : INetworkService, ISingletonDependency { + private readonly IBlackListedPeerProvider _blackListedPeerProvider; + private readonly IBroadcastPrivilegedPubkeyListProvider _broadcastPrivilegedPubkeyListProvider; + private readonly IAElfNetworkServer _networkServer; + private readonly IPeerPool _peerPool; + private readonly ITaskQueueManager _taskQueueManager; + + public NetworkService(IPeerPool peerPool, ITaskQueueManager taskQueueManager, IAElfNetworkServer networkServer, + IBlackListedPeerProvider blackListedPeerProvider, + IBroadcastPrivilegedPubkeyListProvider broadcastPrivilegedPubkeyListProvider) + { + _peerPool = peerPool; + _taskQueueManager = taskQueueManager; + _networkServer = networkServer; + _broadcastPrivilegedPubkeyListProvider = broadcastPrivilegedPubkeyListProvider; + _blackListedPeerProvider = blackListedPeerProvider; + + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } + + public async Task AddPeerAsync(string endpoint) + { + return await TryAddPeerAsync(endpoint, false); + } + /// - /// Exposes networking functionality to the application handlers. + /// Add trusted peer, will remove the host from blacklist first. /// - public class NetworkService : INetworkService, ISingletonDependency + /// + /// + public async Task AddTrustedPeerAsync(string endpoint) { - private readonly IPeerPool _peerPool; - private readonly ITaskQueueManager _taskQueueManager; - private readonly IAElfNetworkServer _networkServer; - private readonly IBroadcastPrivilegedPubkeyListProvider _broadcastPrivilegedPubkeyListProvider; - private readonly IBlackListedPeerProvider _blackListedPeerProvider; + return await TryAddPeerAsync(endpoint, true); + } - public ILogger Logger { get; set; } + public async Task RemovePeerByEndpointAsync(string endpoint, + int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds) + { + if (!AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint)) + return false; - public NetworkService(IPeerPool peerPool, ITaskQueueManager taskQueueManager, IAElfNetworkServer networkServer, - IBlackListedPeerProvider blackListedPeerProvider, - IBroadcastPrivilegedPubkeyListProvider broadcastPrivilegedPubkeyListProvider) + var peer = _peerPool.FindPeerByEndpoint(aelfPeerEndpoint); + if (!await TryRemovePeerAsync(peer, removalSeconds)) { - _peerPool = peerPool; - _taskQueueManager = taskQueueManager; - _networkServer = networkServer; - _broadcastPrivilegedPubkeyListProvider = broadcastPrivilegedPubkeyListProvider; - _blackListedPeerProvider = blackListedPeerProvider; - - Logger = NullLogger.Instance; + Logger.LogWarning($"Remove peer failed. Peer address: {endpoint}"); + return false; } - public async Task AddPeerAsync(string endpoint) - { - return await TryAddPeerAsync(endpoint, false); - } + return true; + } - /// - /// Add trusted peer, will remove the host from blacklist first. - /// - /// - /// - public async Task AddTrustedPeerAsync(string endpoint) + public async Task RemovePeerByPubkeyAsync(string peerPubkey, + int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds) + { + var peer = _peerPool.FindPeerByPublicKey(peerPubkey); + if (!await TryRemovePeerAsync(peer, removalSeconds)) { - return await TryAddPeerAsync(endpoint, true); + Logger.LogWarning($"Remove peer failed. Peer pubkey: {peerPubkey}"); + return false; } - - private async Task TryAddPeerAsync(string endpoint, bool isTrusted) - { - if (!AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint)) - { - Logger.LogDebug($"Could not parse endpoint {endpoint}."); - return false; - } - if(isTrusted) - _blackListedPeerProvider.RemoveHostFromBlackList(aelfPeerEndpoint.Host); - - return await _networkServer.ConnectAsync(aelfPeerEndpoint); - } + return true; + } - public async Task RemovePeerByEndpointAsync(string endpoint, int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds) - { - if (!AElfPeerEndpointHelper.TryParse(endpoint, out DnsEndPoint aelfPeerEndpoint)) - return false; - - var peer = _peerPool.FindPeerByEndpoint(aelfPeerEndpoint); - if (!await TryRemovePeerAsync(peer, removalSeconds)) - { - Logger.LogWarning($"Remove peer failed. Peer address: {endpoint}"); - return false; - } - - return true; - } - - public async Task RemovePeerByPubkeyAsync(string peerPubkey, int removalSeconds = NetworkConstants.DefaultPeerRemovalSeconds) - { - var peer = _peerPool.FindPeerByPublicKey(peerPubkey); - if (!await TryRemovePeerAsync(peer, removalSeconds)) - { - Logger.LogWarning($"Remove peer failed. Peer pubkey: {peerPubkey}"); - return false; - } + public List GetPeers(bool includeFailing = true) + { + return _peerPool.GetPeers(includeFailing).Select(PeerInfoHelper.FromNetworkPeer).ToList(); + } - return true; - } - - /// - /// Try remove the peer, put the peer to blacklist, and disconnect. - /// - /// - /// - /// If the peer is null, return false. - private async Task TryRemovePeerAsync(IPeer peer, int removalSeconds) - { - if (peer == null) - { - return false; - } + public PeerInfo GetPeerByPubkey(string peerPubkey) + { + var peer = _peerPool.FindPeerByPublicKey(peerPubkey); + return peer == null ? null : PeerInfoHelper.FromNetworkPeer(peer); + } - _blackListedPeerProvider.AddHostToBlackList(peer.RemoteEndpoint.Host, removalSeconds); - Logger.LogDebug($"Blacklisted {peer.RemoteEndpoint.Host} ({peer.Info.Pubkey})"); - - await _networkServer.DisconnectAsync(peer); + public async Task BroadcastBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions) + { + if (IsOldBlock(blockWithTransactions.Header)) + return; - return true; - } + var nextMinerPubkey = await GetNextMinerPubkey(blockWithTransactions.Header); - public List GetPeers(bool includeFailing = true) - { - return _peerPool.GetPeers(includeFailing).Select(PeerInfoHelper.FromNetworkPeer).ToList(); - } + var nextPeer = _peerPool.FindPeerByPublicKey(nextMinerPubkey); + if (nextPeer != null) + EnqueueBlock(nextPeer, blockWithTransactions); - public PeerInfo GetPeerByPubkey(string peerPubkey) + foreach (var peer in _peerPool.GetPeers()) { - var peer = _peerPool.FindPeerByPublicKey(peerPubkey); - return peer == null ? null : PeerInfoHelper.FromNetworkPeer(peer); + if (nextPeer != null && peer.Info.Pubkey == nextPeer.Info.Pubkey) + continue; + + EnqueueBlock(peer, blockWithTransactions); } + } - private bool IsOldBlock(BlockHeader header) - { - var limit = TimestampHelper.GetUtcNow() - - TimestampHelper.DurationFromMinutes(NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes); - - if (header.Time < limit) - return true; + public Task BroadcastAnnounceAsync(BlockHeader blockHeader) + { + var blockHash = blockHeader.GetHash(); - return false; - } + if (IsOldBlock(blockHeader)) + return Task.CompletedTask; - public async Task BroadcastBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions) + var blockAnnouncement = new BlockAnnouncement { - if (IsOldBlock(blockWithTransactions.Header)) - return; - - var nextMinerPubkey = await GetNextMinerPubkey(blockWithTransactions.Header); - - var nextPeer = _peerPool.FindPeerByPublicKey(nextMinerPubkey); - if (nextPeer != null) - EnqueueBlock(nextPeer, blockWithTransactions); - - foreach (var peer in _peerPool.GetPeers()) - { - if (nextPeer != null && peer.Info.Pubkey == nextPeer.Info.Pubkey) - continue; + BlockHash = blockHash, + BlockHeight = blockHeader.Height + }; - EnqueueBlock(peer, blockWithTransactions); - } - } - - private void EnqueueBlock(IPeer peer, BlockWithTransactions blockWithTransactions) - { + foreach (var peer in _peerPool.GetPeers()) try { - var blockHash = blockWithTransactions.GetHash(); - if (peer.KnowsBlock(blockHash)) - return; // block already known to this peer + continue; // block already known to this peer - peer.EnqueueBlock(blockWithTransactions, async ex => + peer.EnqueueAnnouncement(blockAnnouncement, async ex => { peer.TryAddKnownBlock(blockHash); - if (ex != null) { - Logger.LogWarning(ex, $"Could not broadcast block to {peer} - status {peer.ConnectionStatus}."); + Logger.LogInformation(ex, $"Could not broadcast announcement to {peer} " + + $"- status {peer.ConnectionStatus}."); + await HandleNetworkException(peer, ex); } }); } catch (NetworkException ex) { - Logger.LogWarning(ex, $"Could not enqueue block to {peer} - status {peer.ConnectionStatus}."); + Logger.LogWarning(ex, $"Could not enqueue announcement to {peer} " + + $"- status {peer.ConnectionStatus}."); } - } - - private async Task GetNextMinerPubkey(BlockHeader blockHeader) - { - var broadcastList = await _broadcastPrivilegedPubkeyListProvider.GetPubkeyList(blockHeader); - return broadcastList.IsNullOrEmpty() ? null : broadcastList[0]; - } - public Task BroadcastAnnounceAsync(BlockHeader blockHeader) - { - var blockHash = blockHeader.GetHash(); + return Task.CompletedTask; + } - if (IsOldBlock(blockHeader)) - return Task.CompletedTask; - - var blockAnnouncement = new BlockAnnouncement + public Task BroadcastTransactionAsync(Transaction transaction) + { + var txHash = transaction.GetHash(); + foreach (var peer in _peerPool.GetPeers()) + try { - BlockHash = blockHash, - BlockHeight = blockHeader.Height - }; + if (peer.KnowsTransaction(txHash)) + continue; // transaction already known to this peer - foreach (var peer in _peerPool.GetPeers()) - { - try + peer.EnqueueTransaction(transaction, async ex => { - if (peer.KnowsBlock(blockHash)) - continue; // block already known to this peer - - peer.EnqueueAnnouncement(blockAnnouncement, async ex => + if (ex != null) { - peer.TryAddKnownBlock(blockHash); - if (ex != null) - { - Logger.LogInformation(ex, $"Could not broadcast announcement to {peer} " + - $"- status {peer.ConnectionStatus}."); - - await HandleNetworkException(peer, ex); - } - }); - } - catch (NetworkException ex) - { - Logger.LogWarning(ex, $"Could not enqueue announcement to {peer} " + + Logger.LogWarning(ex, $"Could not broadcast transaction to {peer} " + $"- status {peer.ConnectionStatus}."); - } + + await HandleNetworkException(peer, ex); + } + }); } - - return Task.CompletedTask; - } - - public Task BroadcastTransactionAsync(Transaction transaction) - { - var txHash = transaction.GetHash(); - foreach (var peer in _peerPool.GetPeers()) + catch (NetworkException ex) { - try - { - if (peer.KnowsTransaction(txHash)) - continue; // transaction already known to this peer - - peer.EnqueueTransaction(transaction, async ex => - { - if (ex != null) - { - Logger.LogWarning(ex, $"Could not broadcast transaction to {peer} " + - $"- status {peer.ConnectionStatus}."); - - await HandleNetworkException(peer, ex); - } - }); - } - catch (NetworkException ex) - { - Logger.LogWarning(ex, $"Could not enqueue transaction to {peer} - " + - $"status {peer.ConnectionStatus}."); - } + Logger.LogWarning(ex, $"Could not enqueue transaction to {peer} - " + + $"status {peer.ConnectionStatus}."); } - - return Task.CompletedTask; - } - - public Task BroadcastLibAnnounceAsync(Hash libHash, long libHeight) + + return Task.CompletedTask; + } + + public Task BroadcastLibAnnounceAsync(Hash libHash, long libHeight) + { + var announce = new LibAnnouncement { - var announce = new LibAnnouncement - { - LibHash = libHash, - LibHeight = libHeight - }; + LibHash = libHash, + LibHeight = libHeight + }; - foreach (var peer in _peerPool.GetPeers()) + foreach (var peer in _peerPool.GetPeers()) + try { - try + peer.EnqueueLibAnnouncement(announce, async ex => { - peer.EnqueueLibAnnouncement(announce, async ex => + if (ex != null) { - if (ex != null) - { - Logger.LogWarning(ex, $"Could not broadcast lib announcement to {peer} " + - $"- status {peer.ConnectionStatus}."); - await HandleNetworkException(peer, ex); - } - }); - } - catch (NetworkException ex) - { - Logger.LogWarning(ex, $"Could not enqueue lib announcement to {peer} " + + Logger.LogWarning(ex, $"Could not broadcast lib announcement to {peer} " + $"- status {peer.ConnectionStatus}."); - } + await HandleNetworkException(peer, ex); + } + }); + } + catch (NetworkException ex) + { + Logger.LogWarning(ex, $"Could not enqueue lib announcement to {peer} " + + $"- status {peer.ConnectionStatus}."); } - - return Task.CompletedTask; - } - public async Task CheckPeersHealthAsync() + return Task.CompletedTask; + } + + public async Task CheckPeersHealthAsync() + { + foreach (var peer in _peerPool.GetPeers(true)) { - foreach (var peer in _peerPool.GetPeers(true)) - { - Logger.LogDebug($"Health checking: {peer}"); + Logger.LogDebug($"Health checking: {peer}"); - if (peer.IsInvalid) - { - _peerPool.RemovePeer(peer.Info.Pubkey); - await peer.DisconnectAsync(false); - Logger.LogInformation($"Remove invalid peer: {peer}"); - continue; - } + if (peer.IsInvalid) + { + _peerPool.RemovePeer(peer.Info.Pubkey); + await peer.DisconnectAsync(false); + Logger.LogInformation($"Remove invalid peer: {peer}"); + continue; + } - try - { - await peer.CheckHealthAsync(); - } - catch (NetworkException ex) + try + { + await peer.CheckHealthAsync(); + } + catch (NetworkException ex) + { + if (ex.ExceptionType == NetworkExceptionType.Unrecoverable + || ex.ExceptionType == NetworkExceptionType.PeerUnstable) { - if (ex.ExceptionType == NetworkExceptionType.Unrecoverable - || ex.ExceptionType == NetworkExceptionType.PeerUnstable) - { - Logger.LogInformation(ex, $"Removing unhealthy peer {peer}."); - await _networkServer.TrySchedulePeerReconnectionAsync(peer); - } + Logger.LogInformation(ex, $"Removing unhealthy peer {peer}."); + await _networkServer.TrySchedulePeerReconnectionAsync(peer); } } } + } + + public void CheckNtpDrift() + { + _networkServer.CheckNtpDrift(); + } + + public async Task>> GetBlocksAsync(Hash previousBlock, int count, + string peerPubkey) + { + var peer = _peerPool.FindPeerByPublicKey(peerPubkey); + + if (peer == null) + throw new InvalidOperationException($"Could not find peer {peerPubkey}."); + + var response = await Request(peer, p => p.GetBlocksAsync(previousBlock, count)); + + if (response.Success && response.Payload != null + && (response.Payload.Count == 0 || response.Payload.Count != count)) + Logger.LogDebug($"Requested blocks from {peer} - count miss match, " + + $"asked for {count} but got {response.Payload.Count} (from {previousBlock})"); + + return response; + } + + public async Task> GetBlockByHashAsync(Hash hash, string peerPubkey) + { + var peer = _peerPool.FindPeerByPublicKey(peerPubkey); + + if (peer == null) + throw new InvalidOperationException($"Could not find peer {peerPubkey}."); + + Logger.LogDebug($"Getting block by hash, hash: {hash} from {peer}."); - public void CheckNtpDrift() + return await Request(peer, p => p.GetBlockByHashAsync(hash)); + } + + public bool IsPeerPoolFull() + { + return _peerPool.IsFull(); + } + + private async Task TryAddPeerAsync(string endpoint, bool isTrusted) + { + if (!AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint)) { - _networkServer.CheckNtpDrift(); + Logger.LogDebug($"Could not parse endpoint {endpoint}."); + return false; } - public async Task>> GetBlocksAsync(Hash previousBlock, int count, - string peerPubkey) - { - IPeer peer = _peerPool.FindPeerByPublicKey(peerPubkey); + if (isTrusted) + _blackListedPeerProvider.RemoveHostFromBlackList(aelfPeerEndpoint.Host); - if (peer == null) - throw new InvalidOperationException($"Could not find peer {peerPubkey}."); + return await _networkServer.ConnectAsync(aelfPeerEndpoint); + } - var response = await Request(peer, p => p.GetBlocksAsync(previousBlock, count)); + /// + /// Try remove the peer, put the peer to blacklist, and disconnect. + /// + /// + /// + /// If the peer is null, return false. + private async Task TryRemovePeerAsync(IPeer peer, int removalSeconds) + { + if (peer == null) return false; - if (response.Success && response.Payload != null - && (response.Payload.Count == 0 || response.Payload.Count != count)) - { - Logger.LogDebug($"Requested blocks from {peer} - count miss match, " + - $"asked for {count} but got {response.Payload.Count} (from {previousBlock})"); - } + _blackListedPeerProvider.AddHostToBlackList(peer.RemoteEndpoint.Host, removalSeconds); + Logger.LogDebug($"Blacklisted {peer.RemoteEndpoint.Host} ({peer.Info.Pubkey})"); - return response; - } + await _networkServer.DisconnectAsync(peer); + + return true; + } + + private bool IsOldBlock(BlockHeader header) + { + var limit = TimestampHelper.GetUtcNow() + - TimestampHelper.DurationFromMinutes(NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes); - public async Task> GetBlockByHashAsync(Hash hash, string peerPubkey) + if (header.Time < limit) + return true; + + return false; + } + + private void EnqueueBlock(IPeer peer, BlockWithTransactions blockWithTransactions) + { + try { - IPeer peer = _peerPool.FindPeerByPublicKey(peerPubkey); - - if (peer == null) - throw new InvalidOperationException($"Could not find peer {peerPubkey}."); - - Logger.LogDebug($"Getting block by hash, hash: {hash} from {peer}."); - - return await Request(peer, p => p.GetBlockByHashAsync(hash)); + var blockHash = blockWithTransactions.GetHash(); + + if (peer.KnowsBlock(blockHash)) + return; // block already known to this peer + + peer.EnqueueBlock(blockWithTransactions, async ex => + { + peer.TryAddKnownBlock(blockHash); + + if (ex != null) + { + Logger.LogWarning(ex, $"Could not broadcast block to {peer} - status {peer.ConnectionStatus}."); + await HandleNetworkException(peer, ex); + } + }); } - - public bool IsPeerPoolFull() + catch (NetworkException ex) { - return _peerPool.IsFull(); + Logger.LogWarning(ex, $"Could not enqueue block to {peer} - status {peer.ConnectionStatus}."); } + } - private async Task> Request(IPeer peer, Func> func) where T : class - { - try - { - return new Response(await func(peer)); - } - catch (NetworkException ex) - { - Logger.LogWarning(ex, $"Request failed from {peer.RemoteEndpoint}."); - - if (ex.ExceptionType == NetworkExceptionType.HandlerException) - return new Response(default(T)); - - await HandleNetworkException(peer, ex); - } + private async Task GetNextMinerPubkey(BlockHeader blockHeader) + { + var broadcastList = await _broadcastPrivilegedPubkeyListProvider.GetPubkeyList(blockHeader); + return broadcastList.IsNullOrEmpty() ? null : broadcastList[0]; + } - return new Response(); + private async Task> Request(IPeer peer, Func> func) where T : class + { + try + { + return new Response(await func(peer)); } - - private async Task HandleNetworkException(IPeer peer, NetworkException exception) + catch (NetworkException ex) { - if (exception.ExceptionType == NetworkExceptionType.Unrecoverable) - { - Logger.LogInformation(exception, $"Removing unrecoverable {peer}."); - await _networkServer.TrySchedulePeerReconnectionAsync(peer); - } - else if (exception.ExceptionType == NetworkExceptionType.PeerUnstable) - { - Logger.LogDebug(exception, $"Queuing peer for reconnection {peer.RemoteEndpoint}."); - QueueNetworkTask(async () => await RecoverPeerAsync(peer)); - } + Logger.LogWarning(ex, $"Request failed from {peer.RemoteEndpoint}."); + + if (ex.ExceptionType == NetworkExceptionType.HandlerException) + return new Response(default); + + await HandleNetworkException(peer, ex); } - private async Task RecoverPeerAsync(IPeer peer) - { - if (peer.IsReady) // peer recovered already - return; - - var success = await peer.TryRecoverAsync(); + return new Response(); + } - if (!success) - await _networkServer.TrySchedulePeerReconnectionAsync(peer); + private async Task HandleNetworkException(IPeer peer, NetworkException exception) + { + if (exception.ExceptionType == NetworkExceptionType.Unrecoverable) + { + Logger.LogInformation(exception, $"Removing unrecoverable {peer}."); + await _networkServer.TrySchedulePeerReconnectionAsync(peer); } - - private void QueueNetworkTask(Func task) + else if (exception.ExceptionType == NetworkExceptionType.PeerUnstable) { - _taskQueueManager.Enqueue(task, NetworkConstants.PeerReconnectionQueueName); + Logger.LogDebug(exception, $"Queuing peer for reconnection {peer.RemoteEndpoint}."); + QueueNetworkTask(async () => await RecoverPeerAsync(peer)); } } + + private async Task RecoverPeerAsync(IPeer peer) + { + if (peer.IsReady) // peer recovered already + return; + + var success = await peer.TryRecoverAsync(); + + if (!success) + await _networkServer.TrySchedulePeerReconnectionAsync(peer); + } + + private void QueueNetworkTask(Func task) + { + _taskQueueManager.Enqueue(task, NetworkConstants.PeerReconnectionQueueName); + } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/PeerDiscoveryService.cs b/src/AElf.OS.Core/Network/Application/PeerDiscoveryService.cs index 4cd84fb766..b1335b4062 100644 --- a/src/AElf.OS.Core/Network/Application/PeerDiscoveryService.cs +++ b/src/AElf.OS.Core/Network/Application/PeerDiscoveryService.cs @@ -1,90 +1,87 @@ using System.Linq; using System.Threading.Tasks; using AElf.OS.Network.Domain; +using AElf.OS.Network.Extensions; using AElf.OS.Network.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp; -using AElf.OS.Network.Extensions; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class PeerDiscoveryService : IPeerDiscoveryService { - public class PeerDiscoveryService : IPeerDiscoveryService + private readonly IAElfNetworkServer _aelfNetworkServer; + private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; + private readonly INodeManager _nodeManager; + private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + private readonly IPeerPool _peerPool; + + public PeerDiscoveryService(IPeerPool peerPool, INodeManager nodeManager, + IDiscoveredNodeCacheProvider discoveredNodeCacheProvider, IAElfNetworkServer aelfNetworkServer, + IPeerDiscoveryJobProcessor peerDiscoveryJobProcessor) { - private readonly IPeerPool _peerPool; - private readonly INodeManager _nodeManager; - private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; - private readonly IAElfNetworkServer _aelfNetworkServer; - private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + _peerPool = peerPool; + _nodeManager = nodeManager; + _discoveredNodeCacheProvider = discoveredNodeCacheProvider; + _aelfNetworkServer = aelfNetworkServer; + _peerDiscoveryJobProcessor = peerDiscoveryJobProcessor; - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; + } - public PeerDiscoveryService(IPeerPool peerPool, INodeManager nodeManager, - IDiscoveredNodeCacheProvider discoveredNodeCacheProvider, IAElfNetworkServer aelfNetworkServer, - IPeerDiscoveryJobProcessor peerDiscoveryJobProcessor) - { - _peerPool = peerPool; - _nodeManager = nodeManager; - _discoveredNodeCacheProvider = discoveredNodeCacheProvider; - _aelfNetworkServer = aelfNetworkServer; - _peerDiscoveryJobProcessor = peerDiscoveryJobProcessor; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + public async Task DiscoverNodesAsync() + { + var peers = _peerPool.GetPeers() + .OrderBy(x => RandomHelper.GetRandom()) + .Take(NetworkConstants.DefaultDiscoveryPeersToRequestCount) + .ToList(); - public async Task DiscoverNodesAsync() + foreach (var peer in peers) { - var peers = _peerPool.GetPeers() - .OrderBy(x => RandomHelper.GetRandom()) - .Take(NetworkConstants.DefaultDiscoveryPeersToRequestCount) - .ToList(); - - foreach (var peer in peers) - { - var result = await _peerDiscoveryJobProcessor.SendDiscoveryJobAsync(peer); - if (!result) - Logger.LogWarning($"Send discovery job failed: {peer}"); - } + var result = await _peerDiscoveryJobProcessor.SendDiscoveryJobAsync(peer); + if (!result) + Logger.LogWarning($"Send discovery job failed: {peer}"); } + } - public async Task RefreshNodeAsync() + public async Task RefreshNodeAsync() + { + var endpoint = await TakeEndpointFromDiscoveredNodeCacheAsync(); + if (endpoint != null) { - var endpoint = await TakeEndpointFromDiscoveredNodeCacheAsync(); - if (endpoint != null) + if (await _aelfNetworkServer.CheckEndpointAvailableAsync(endpoint)) + { + _discoveredNodeCacheProvider.Add(endpoint); + Logger.LogDebug($"Refresh node successfully: {endpoint}"); + } + else { - if (await _aelfNetworkServer.CheckEndpointAvailableAsync(endpoint)) - { - _discoveredNodeCacheProvider.Add(endpoint); - Logger.LogDebug($"Refresh node successfully: {endpoint}"); - } - else - { - await _nodeManager.RemoveNodeAsync(endpoint); - Logger.LogDebug($"Clean unavailable node: {endpoint}"); - } + await _nodeManager.RemoveNodeAsync(endpoint); + Logger.LogDebug($"Clean unavailable node: {endpoint}"); } } + } - public async Task AddNodeAsync(NodeInfo nodeInfo) - { - if (await _nodeManager.AddNodeAsync(nodeInfo)) - _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); - } + public async Task AddNodeAsync(NodeInfo nodeInfo) + { + if (await _nodeManager.AddNodeAsync(nodeInfo)) + _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); + } - public Task GetNodesAsync(int maxCount) - { - return _nodeManager.GetRandomNodesAsync(maxCount); - } + public Task GetNodesAsync(int maxCount) + { + return _nodeManager.GetRandomNodesAsync(maxCount); + } - private async Task TakeEndpointFromDiscoveredNodeCacheAsync() - { - while (_discoveredNodeCacheProvider.TryTake(out var endpoint)) - { - if (await _nodeManager.GetNodeAsync(endpoint) != null) - return endpoint; - } + private async Task TakeEndpointFromDiscoveredNodeCacheAsync() + { + while (_discoveredNodeCacheProvider.TryTake(out var endpoint)) + if (await _nodeManager.GetNodeAsync(endpoint) != null) + return endpoint; - return null; - } + return null; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/PeerInvalidTransactionProcessingService.cs b/src/AElf.OS.Core/Network/Application/PeerInvalidTransactionProcessingService.cs index bed37b7d86..750608b74d 100644 --- a/src/AElf.OS.Core/Network/Application/PeerInvalidTransactionProcessingService.cs +++ b/src/AElf.OS.Core/Network/Application/PeerInvalidTransactionProcessingService.cs @@ -5,44 +5,40 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class PeerInvalidTransactionProcessingService : IPeerInvalidTransactionProcessingService, + ITransientDependency { - public class PeerInvalidTransactionProcessingService : IPeerInvalidTransactionProcessingService, - ITransientDependency + private readonly INetworkService _networkService; + private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; + private readonly IPeerPool _peerPool; + + public PeerInvalidTransactionProcessingService(INetworkService networkService, IPeerPool peerPool, + IPeerInvalidTransactionProvider peerInvalidTransactionProvider) { - private readonly INetworkService _networkService; - private readonly IPeerPool _peerPool; - private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; + _networkService = networkService; + _peerPool = peerPool; + _peerInvalidTransactionProvider = peerInvalidTransactionProvider; + } - public PeerInvalidTransactionProcessingService(INetworkService networkService, IPeerPool peerPool, - IPeerInvalidTransactionProvider peerInvalidTransactionProvider) - { - _networkService = networkService; - _peerPool = peerPool; - _peerInvalidTransactionProvider = peerInvalidTransactionProvider; - } + public async Task ProcessPeerInvalidTransactionAsync(Hash transactionId) + { + var knowsTransactionPeers = _peerPool.GetPeers().Where(p => p.KnowsTransaction(transactionId)).ToList(); + var toRemovePeerPubkey = new List(); - public async Task ProcessPeerInvalidTransactionAsync(Hash transactionId) + foreach (var knowsTransactionPeer in knowsTransactionPeers) { - var knowsTransactionPeers = _peerPool.GetPeers().Where(p => p.KnowsTransaction(transactionId)).ToList(); - var toRemovePeerPubkey = new List(); - - foreach (var knowsTransactionPeer in knowsTransactionPeers) - { - var host = knowsTransactionPeer.RemoteEndpoint.Host; - if (_peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, transactionId)) - continue; + var host = knowsTransactionPeer.RemoteEndpoint.Host; + if (_peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, transactionId)) + continue; - var peers = _peerPool.GetPeersByHost(host); - toRemovePeerPubkey.AddRange(peers.Select(p => p.Info.Pubkey)); + var peers = _peerPool.GetPeersByHost(host); + toRemovePeerPubkey.AddRange(peers.Select(p => p.Info.Pubkey)); - _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host); - } - - foreach (var pubkey in toRemovePeerPubkey) - { - await _networkService.RemovePeerByPubkeyAsync(pubkey); - } + _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host); } + + foreach (var pubkey in toRemovePeerPubkey) await _networkService.RemovePeerByPubkeyAsync(pubkey); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Application/Response.cs b/src/AElf.OS.Core/Network/Application/Response.cs index b766cf06fe..4105411a29 100644 --- a/src/AElf.OS.Core/Network/Application/Response.cs +++ b/src/AElf.OS.Core/Network/Application/Response.cs @@ -1,16 +1,18 @@ -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class Response { - public class Response + public Response() { - public bool Success { get; } - public T Payload { get; } - - public Response() { /* for unsuccessful responses */ } + /* for unsuccessful responses */ + } - public Response(T payload) - { - Success = true; - Payload = payload; - } + public Response(T payload) + { + Success = true; + Payload = payload; } + + public bool Success { get; } + public T Payload { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Domain/NodeManager.cs b/src/AElf.OS.Core/Network/Domain/NodeManager.cs index 72c575dcda..41f81dd2ac 100644 --- a/src/AElf.OS.Core/Network/Domain/NodeManager.cs +++ b/src/AElf.OS.Core/Network/Domain/NodeManager.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; @@ -8,71 +7,69 @@ using Volo.Abp; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Domain +namespace AElf.OS.Network.Domain; + +public interface INodeManager +{ + Task AddNodeAsync(NodeInfo nodeInfo); + Task GetRandomNodesAsync(int maxCount); + Task GetNodeAsync(string endpoint); + Task UpdateNodeAsync(NodeInfo nodeInfo); + Task RemoveNodeAsync(string endpoint); +} + +public class NodeManager : INodeManager, ISingletonDependency { - public interface INodeManager + private readonly NetworkOptions _networkOptions; + private readonly ConcurrentDictionary _nodes; + + public NodeManager(IOptionsSnapshot networkOptions) { - Task AddNodeAsync(NodeInfo nodeInfo); - Task GetRandomNodesAsync(int maxCount); - Task GetNodeAsync(string endpoint); - Task UpdateNodeAsync(NodeInfo nodeInfo); - Task RemoveNodeAsync(string endpoint); + _nodes = new ConcurrentDictionary(); + + _networkOptions = networkOptions.Value; + Logger = NullLogger.Instance; } - - public class NodeManager : INodeManager, ISingletonDependency - { - private readonly ConcurrentDictionary _nodes; - public ILogger Logger { get; set;} - private readonly NetworkOptions _networkOptions; - public NodeManager(IOptionsSnapshot networkOptions) - { - _nodes = new ConcurrentDictionary(); - - _networkOptions = networkOptions.Value; - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public Task AddNodeAsync(NodeInfo nodeInfo) - { - if (_nodes.Count >= _networkOptions.PeerDiscoveryMaxNodesToKeep) - return Task.FromResult(false); + public Task AddNodeAsync(NodeInfo nodeInfo) + { + if (_nodes.Count >= _networkOptions.PeerDiscoveryMaxNodesToKeep) + return Task.FromResult(false); - var addResult = _nodes.TryAdd(nodeInfo.Endpoint, nodeInfo); - return Task.FromResult(addResult); - } + var addResult = _nodes.TryAdd(nodeInfo.Endpoint, nodeInfo); + return Task.FromResult(addResult); + } - public Task GetRandomNodesAsync(int maxCount) - { - var randomPeers = _nodes.OrderBy(x => RandomHelper.GetRandom()).Take(maxCount).Select(n => n.Value) - .ToList(); + public Task GetRandomNodesAsync(int maxCount) + { + var randomPeers = _nodes.OrderBy(x => RandomHelper.GetRandom()).Take(maxCount).Select(n => n.Value) + .ToList(); - NodeList nodes = new NodeList(); - nodes.Nodes.AddRange(randomPeers); + var nodes = new NodeList(); + nodes.Nodes.AddRange(randomPeers); - return Task.FromResult(nodes); - } + return Task.FromResult(nodes); + } - public Task GetNodeAsync(string endpoint) - { - _nodes.TryGetValue(endpoint, out var nodeInfo); - return Task.FromResult(nodeInfo); - } + public Task GetNodeAsync(string endpoint) + { + _nodes.TryGetValue(endpoint, out var nodeInfo); + return Task.FromResult(nodeInfo); + } - public Task UpdateNodeAsync(NodeInfo nodeInfo) - { - if (_nodes.TryGetValue(nodeInfo.Endpoint, out var oldNodeInfo) && oldNodeInfo.Pubkey!=nodeInfo.Pubkey) - { - _nodes.TryUpdate(nodeInfo.Endpoint, nodeInfo, oldNodeInfo); - } + public Task UpdateNodeAsync(NodeInfo nodeInfo) + { + if (_nodes.TryGetValue(nodeInfo.Endpoint, out var oldNodeInfo) && oldNodeInfo.Pubkey != nodeInfo.Pubkey) + _nodes.TryUpdate(nodeInfo.Endpoint, nodeInfo, oldNodeInfo); - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task RemoveNodeAsync(string endpoint) - { - _nodes.TryRemove(endpoint, out _); - return Task.CompletedTask; - } + public Task RemoveNodeAsync(string endpoint) + { + _nodes.TryRemove(endpoint, out _); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Events/AnnoucementReceivedEventData.cs b/src/AElf.OS.Core/Network/Events/AnnoucementReceivedEventData.cs index f1ce8e5c85..3be2bf193b 100644 --- a/src/AElf.OS.Core/Network/Events/AnnoucementReceivedEventData.cs +++ b/src/AElf.OS.Core/Network/Events/AnnoucementReceivedEventData.cs @@ -1,14 +1,13 @@ -namespace AElf.OS.Network.Events +namespace AElf.OS.Network.Events; + +public class AnnouncementReceivedEventData { - public class AnnouncementReceivedEventData + public AnnouncementReceivedEventData(BlockAnnouncement an, string senderPubKey) { - public BlockAnnouncement Announce { get; } - public string SenderPubKey { get; } - - public AnnouncementReceivedEventData(BlockAnnouncement an, string senderPubKey) - { - SenderPubKey = senderPubKey; - Announce = an; - } + SenderPubKey = senderPubKey; + Announce = an; } + + public BlockAnnouncement Announce { get; } + public string SenderPubKey { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Events/BlockReceivedEvent.cs b/src/AElf.OS.Core/Network/Events/BlockReceivedEvent.cs index 05ab64f9cc..9a1fc7b423 100644 --- a/src/AElf.OS.Core/Network/Events/BlockReceivedEvent.cs +++ b/src/AElf.OS.Core/Network/Events/BlockReceivedEvent.cs @@ -1,15 +1,14 @@ -namespace AElf.OS.Network.Events +namespace AElf.OS.Network.Events; + +public class BlockReceivedEvent { - public class BlockReceivedEvent + public BlockReceivedEvent(BlockWithTransactions block, string senderPubkey) { - public BlockWithTransactions BlockWithTransactions { get; } - - public string SenderPubkey { get; } - - public BlockReceivedEvent(BlockWithTransactions block, string senderPubkey) - { - BlockWithTransactions = block; - SenderPubkey = senderPubkey; - } + BlockWithTransactions = block; + SenderPubkey = senderPubkey; } + + public BlockWithTransactions BlockWithTransactions { get; } + + public string SenderPubkey { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Events/NetworkInitializedEvent.cs b/src/AElf.OS.Core/Network/Events/NetworkInitializedEvent.cs index a46105cf1a..1913c357e6 100644 --- a/src/AElf.OS.Core/Network/Events/NetworkInitializedEvent.cs +++ b/src/AElf.OS.Core/Network/Events/NetworkInitializedEvent.cs @@ -1,6 +1,5 @@ -namespace AElf.OS.Network.Events +namespace AElf.OS.Network.Events; + +public class NetworkInitializedEvent { - public class NetworkInitializedEvent - { - } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Events/PeerConnectedEventData.cs b/src/AElf.OS.Core/Network/Events/PeerConnectedEventData.cs index a7154ba416..3b59c06b5f 100644 --- a/src/AElf.OS.Core/Network/Events/PeerConnectedEventData.cs +++ b/src/AElf.OS.Core/Network/Events/PeerConnectedEventData.cs @@ -1,19 +1,17 @@ -using AElf.Kernel; using AElf.Types; -namespace AElf.OS.Network.Events +namespace AElf.OS.Network.Events; + +public class PeerConnectedEventData { - public class PeerConnectedEventData + public PeerConnectedEventData(NodeInfo nodeInfo, Hash bestChainHash, long bestChainHeight) { - public NodeInfo NodeInfo { get; } - public Hash BestChainHash { get; } - public long BestChainHeight { get; } - - public PeerConnectedEventData(NodeInfo nodeInfo, Hash bestChainHash, long bestChainHeight) - { - NodeInfo = nodeInfo; - BestChainHash = bestChainHash; - BestChainHeight = bestChainHeight; - } + NodeInfo = nodeInfo; + BestChainHash = bestChainHash; + BestChainHeight = bestChainHeight; } + + public NodeInfo NodeInfo { get; } + public Hash BestChainHash { get; } + public long BestChainHeight { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Extensions/AElfNetworkServerExtensions.cs b/src/AElf.OS.Core/Network/Extensions/AElfNetworkServerExtensions.cs index 0d30046fe2..a7b627fa86 100644 --- a/src/AElf.OS.Core/Network/Extensions/AElfNetworkServerExtensions.cs +++ b/src/AElf.OS.Core/Network/Extensions/AElfNetworkServerExtensions.cs @@ -2,19 +2,15 @@ using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; -namespace AElf.OS.Network.Extensions +namespace AElf.OS.Network.Extensions; + +public static class AElfNetworkServerExtensions { - public static class AElfNetworkServerExtensions + public static async Task CheckEndpointAvailableAsync(this IAElfNetworkServer networkServer, + string endpoint) { - public static async Task CheckEndpointAvailableAsync(this IAElfNetworkServer networkServer, - string endpoint) - { - if (!AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint)) - { - return false; - } + if (!AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint)) return false; - return await networkServer.CheckEndpointAvailableAsync(aelfPeerEndpoint); - } + return await networkServer.CheckEndpointAvailableAsync(aelfPeerEndpoint); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Extensions/BlockWithTransactionsExtensions.cs b/src/AElf.OS.Core/Network/Extensions/BlockWithTransactionsExtensions.cs index 5f3996c0c6..a92c58f280 100644 --- a/src/AElf.OS.Core/Network/Extensions/BlockWithTransactionsExtensions.cs +++ b/src/AElf.OS.Core/Network/Extensions/BlockWithTransactionsExtensions.cs @@ -1,20 +1,19 @@ using System.Linq; using AElf.Kernel; -namespace AElf.OS.Network.Extensions +namespace AElf.OS.Network.Extensions; + +public static class BlockWithTransactionsExtensions { - public static class BlockWithTransactionsExtensions + public static Block ToBlock(this BlockWithTransactions block) { - public static Block ToBlock(this BlockWithTransactions block) + return new Block { - return new Block + Header = block.Header, + Body = new BlockBody { - Header = block.Header, - Body = new BlockBody - { - TransactionIds = {block.Transactions.Select(tx => tx.GetHash()).ToList()} - } - }; - } + TransactionIds = { block.Transactions.Select(tx => tx.GetHash()).ToList() } + } + }; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Extensions/BlockchainServiceExtensions.cs b/src/AElf.OS.Core/Network/Extensions/BlockchainServiceExtensions.cs index 51519d93f7..311686ed6e 100644 --- a/src/AElf.OS.Core/Network/Extensions/BlockchainServiceExtensions.cs +++ b/src/AElf.OS.Core/Network/Extensions/BlockchainServiceExtensions.cs @@ -4,35 +4,36 @@ using AElf.Kernel.Blockchain.Application; using AElf.Types; -namespace AElf.OS.Network.Extensions +namespace AElf.OS.Network.Extensions; + +public static class BlockchainServiceExtensions { - public static class BlockchainServiceExtensions + public static async Task GetBlockWithTransactionsByHashAsync( + this IBlockchainService blockchainService, Hash blockHash) { - public static async Task GetBlockWithTransactionsByHashAsync(this IBlockchainService blockchainService, Hash blockHash) - { - var block = await blockchainService.GetBlockByHashAsync(blockHash); - - if (block == null) - return null; - - var transactions = await blockchainService.GetTransactionsAsync(block.TransactionIds); - - return new BlockWithTransactions { Header = block.Header, Transactions = { transactions }}; - } - - public static async Task> GetBlocksWithTransactionsAsync(this IBlockchainService blockchainService, - Hash firstHash, int count) - { - var blocks = await blockchainService.GetBlocksInBestChainBranchAsync(firstHash, count); - - var list = blocks - .Select(async block => - { - var transactions = await blockchainService.GetTransactionsAsync(block.TransactionIds); - return new BlockWithTransactions { Header = block.Header, Transactions = { transactions } }; - }); - - return (await Task.WhenAll(list)).ToList(); - } + var block = await blockchainService.GetBlockByHashAsync(blockHash); + + if (block == null) + return null; + + var transactions = await blockchainService.GetTransactionsAsync(block.TransactionIds); + + return new BlockWithTransactions { Header = block.Header, Transactions = { transactions } }; + } + + public static async Task> GetBlocksWithTransactionsAsync( + this IBlockchainService blockchainService, + Hash firstHash, int count) + { + var blocks = await blockchainService.GetBlocksInBestChainBranchAsync(firstHash, count); + + var list = blocks + .Select(async block => + { + var transactions = await blockchainService.GetTransactionsAsync(block.TransactionIds); + return new BlockWithTransactions { Header = block.Header, Transactions = { transactions } }; + }); + + return (await Task.WhenAll(list)).ToList(); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Helpers/AElfPeerEndpointHelper.cs b/src/AElf.OS.Core/Network/Helpers/AElfPeerEndpointHelper.cs index f27383b630..b45b5208f3 100644 --- a/src/AElf.OS.Core/Network/Helpers/AElfPeerEndpointHelper.cs +++ b/src/AElf.OS.Core/Network/Helpers/AElfPeerEndpointHelper.cs @@ -1,82 +1,80 @@ -using System; using System.Linq; using System.Net; using AElf.OS.Network.Types; -namespace AElf.OS.Network.Helpers +namespace AElf.OS.Network.Helpers; + +public static class AElfPeerEndpointHelper { - public static class AElfPeerEndpointHelper + public static bool TryParse(string endpointString, out DnsEndPoint endpoint, + int defaultPort = NetworkConstants.DefaultPeerPort) { - public static bool TryParse(string endpointString, out DnsEndPoint endpoint, - int defaultPort = NetworkConstants.DefaultPeerPort) - { - endpoint = null; + endpoint = null; - if (string.IsNullOrEmpty(endpointString) || endpointString.Trim().Length == 0) - return false; + if (string.IsNullOrEmpty(endpointString) || endpointString.Trim().Length == 0) + return false; - if (defaultPort != -1 && (defaultPort < IPEndPoint.MinPort || defaultPort > IPEndPoint.MaxPort)) - return false; + if (defaultPort != -1 && (defaultPort < IPEndPoint.MinPort || defaultPort > IPEndPoint.MaxPort)) + return false; - string[] values = endpointString.Split(new char[] { ':' }); - string host; - int port = -1; + var values = endpointString.Split(new[] { ':' }); + string host; + var port = -1; - if (values.Length <= 2) + if (values.Length <= 2) + { + // ipv4 or hostname + host = values[0]; + + if (values.Length == 1) { - // ipv4 or hostname - host = values[0]; - - if (values.Length == 1) - { - port = defaultPort; - } - else - { - var parsedPort = GetPort(values[1]); - - if (parsedPort == 0) - return false; - - port = parsedPort; - } + port = defaultPort; } else { - //ipv6 - //could be [a:b:c]:d - if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]")) - { - host = string.Join(":", values.Take(values.Length - 1).ToArray()); - var parsedPort = GetPort(values[values.Length - 1]); - - if (parsedPort == 0) - return false; - - port = parsedPort; - } - else // [a:b:c] or a:b:c - { - host = endpointString; - port = defaultPort; - } - } + var parsedPort = GetPort(values[1]); - if (port == -1) - return false; + if (parsedPort == 0) + return false; - // we leave semantic analysis of the ip/hostname to lower levels. - endpoint = new AElfPeerEndpoint(host, port); - - return true; + port = parsedPort; + } } - - private static int GetPort(string p) + else { - if (!int.TryParse(p, out int port) || port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) - return 0; + //ipv6 + //could be [a:b:c]:d + if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]")) + { + host = string.Join(":", values.Take(values.Length - 1).ToArray()); + var parsedPort = GetPort(values[values.Length - 1]); - return port; + if (parsedPort == 0) + return false; + + port = parsedPort; + } + else // [a:b:c] or a:b:c + { + host = endpointString; + port = defaultPort; + } } + + if (port == -1) + return false; + + // we leave semantic analysis of the ip/hostname to lower levels. + endpoint = new AElfPeerEndpoint(host, port); + + return true; + } + + private static int GetPort(string p) + { + if (!int.TryParse(p, out var port) || port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) + return 0; + + return port; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Helpers/PeerInfoHelper.cs b/src/AElf.OS.Core/Network/Helpers/PeerInfoHelper.cs index 3831c6f20b..3ebcfbe1e0 100644 --- a/src/AElf.OS.Core/Network/Helpers/PeerInfoHelper.cs +++ b/src/AElf.OS.Core/Network/Helpers/PeerInfoHelper.cs @@ -2,27 +2,26 @@ using AElf.OS.Network.Infrastructure; using AElf.OS.Network.Types; -namespace AElf.OS.Network.Helpers +namespace AElf.OS.Network.Helpers; + +public static class PeerInfoHelper { - public static class PeerInfoHelper + public static PeerInfo FromNetworkPeer(IPeer peer) { - public static PeerInfo FromNetworkPeer(IPeer peer) + return new PeerInfo { - return new PeerInfo - { - IpAddress = peer.RemoteEndpoint.ToString(), - Pubkey = peer.Info.Pubkey, - LastKnownLibHeight = peer.LastKnownLibHeight, - ProtocolVersion = peer.Info.ProtocolVersion, - ConnectionTime = peer.Info.ConnectionTime.Seconds, - ConnectionStatus = peer.ConnectionStatus, - Inbound = peer.Info.IsInbound, - SyncState = peer.SyncState, - BufferedAnnouncementsCount = peer.BufferedAnnouncementsCount, - BufferedBlocksCount = peer.BufferedBlocksCount, - BufferedTransactionsCount = peer.BufferedTransactionsCount, - RequestMetrics = peer.GetRequestMetrics()?.Values.SelectMany(kvp => kvp).ToList() - }; - } + IpAddress = peer.RemoteEndpoint.ToString(), + Pubkey = peer.Info.Pubkey, + LastKnownLibHeight = peer.LastKnownLibHeight, + ProtocolVersion = peer.Info.ProtocolVersion, + ConnectionTime = peer.Info.ConnectionTime.Seconds, + ConnectionStatus = peer.ConnectionStatus, + Inbound = peer.Info.IsInbound, + SyncState = peer.SyncState, + BufferedAnnouncementsCount = peer.BufferedAnnouncementsCount, + BufferedBlocksCount = peer.BufferedBlocksCount, + BufferedTransactionsCount = peer.BufferedTransactionsCount, + RequestMetrics = peer.GetRequestMetrics()?.Values.SelectMany(kvp => kvp).ToList() + }; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/Exceptions/NetworkException.cs b/src/AElf.OS.Core/Network/Infrastructure/Exceptions/NetworkException.cs index 17b4188618..4a603344f4 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/Exceptions/NetworkException.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/Exceptions/NetworkException.cs @@ -1,33 +1,40 @@ using System; using System.Runtime.Serialization; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public enum NetworkExceptionType { - public enum NetworkExceptionType { Rpc, PeerUnstable, Unrecoverable, FullBuffer, NotConnected, HandlerException } + Rpc, + PeerUnstable, + Unrecoverable, + FullBuffer, + NotConnected, + HandlerException +} - [Serializable] - public class NetworkException : Exception +[Serializable] +public class NetworkException : Exception +{ + public NetworkException() { - public NetworkExceptionType ExceptionType { get; } - - public NetworkException() - { - } + } - public NetworkException(string message, NetworkExceptionType exceptionType) : base(message) - { - ExceptionType = exceptionType; - } + public NetworkException(string message, NetworkExceptionType exceptionType) : base(message) + { + ExceptionType = exceptionType; + } - public NetworkException(string message, Exception inner, - NetworkExceptionType exceptionType = NetworkExceptionType.Rpc) : base(message, inner) - { - ExceptionType = exceptionType; - } + public NetworkException(string message, Exception inner, + NetworkExceptionType exceptionType = NetworkExceptionType.Rpc) : base(message, inner) + { + ExceptionType = exceptionType; + } - protected NetworkException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } + protected NetworkException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + + public NetworkExceptionType ExceptionType { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IAElfNetworkServer.cs b/src/AElf.OS.Core/Network/Infrastructure/IAElfNetworkServer.cs index b1bda85591..3bf1afdd6d 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IAElfNetworkServer.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IAElfNetworkServer.cs @@ -1,17 +1,15 @@ -using System; using System.Net; using System.Threading.Tasks; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IAElfNetworkServer { - public interface IAElfNetworkServer - { - Task ConnectAsync(DnsEndPoint endpoint); - Task DisconnectAsync(IPeer peer, bool sendDisconnect = false); - Task TrySchedulePeerReconnectionAsync(IPeer peer); - Task StartAsync(); - Task StopAsync(bool gracefulDisconnect = true); - void CheckNtpDrift(); - Task CheckEndpointAvailableAsync(DnsEndPoint endpoint); - } + Task ConnectAsync(DnsEndPoint endpoint); + Task DisconnectAsync(IPeer peer, bool sendDisconnect = false); + Task TrySchedulePeerReconnectionAsync(IPeer peer); + Task StartAsync(); + Task StopAsync(bool gracefulDisconnect = true); + void CheckNtpDrift(); + Task CheckEndpointAvailableAsync(DnsEndPoint endpoint); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IBlackListedPeerProvider.cs b/src/AElf.OS.Core/Network/Infrastructure/IBlackListedPeerProvider.cs index c01230a958..5df070a7f4 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IBlackListedPeerProvider.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IBlackListedPeerProvider.cs @@ -1,71 +1,65 @@ using System.Collections.Concurrent; -using System.Collections.Generic; using AElf.CSharp.Core.Extension; using AElf.Kernel; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IBlackListedPeerProvider +{ + bool AddHostToBlackList(string host, int limitSeconds); + bool IsIpBlackListed(string host); + bool RemoveHostFromBlackList(string host); +} + +public class BlackListedPeerProvider : IBlackListedPeerProvider, ISingletonDependency { - public interface IBlackListedPeerProvider + private readonly ConcurrentDictionary _blackListedPeers; + + public BlackListedPeerProvider() { - bool AddHostToBlackList(string host, int limitSeconds); - bool IsIpBlackListed(string host); - bool RemoveHostFromBlackList(string host); + _blackListedPeers = new ConcurrentDictionary(); } - - public class BlackListedPeerProvider : IBlackListedPeerProvider, ISingletonDependency + + public ILogger Logger { get; set; } + + public bool AddHostToBlackList(string host, int limitSeconds) { - public ILogger Logger { get; set; } - - private readonly ConcurrentDictionary _blackListedPeers; + CleanBlackList(); + return _blackListedPeers.TryAdd(host, TimestampHelper.GetUtcNow().AddSeconds(limitSeconds)); + } - public BlackListedPeerProvider() - { - _blackListedPeers = new ConcurrentDictionary(); - } + public bool RemoveHostFromBlackList(string host) + { + Logger.LogDebug($"Removing blacklisted peer {host}"); + return _blackListedPeers.TryRemove(host, out _); + } - public bool AddHostToBlackList(string host, int limitSeconds) - { - CleanBlackList(); - return _blackListedPeers.TryAdd(host, TimestampHelper.GetUtcNow().AddSeconds(limitSeconds)); - } + public bool IsIpBlackListed(string host) + { + if (!_blackListedPeers.TryGetValue(host, out var expirationDate)) + return false; - public bool RemoveHostFromBlackList(string host) + if (IsOverdue(expirationDate)) { - Logger.LogDebug($"Removing blacklisted peer {host}"); - return _blackListedPeers.TryRemove(host, out _); + RemoveHostFromBlackList(host); + return false; } - public bool IsIpBlackListed(string host) - { - if (!_blackListedPeers.TryGetValue(host, out var expirationDate)) - return false; + return true; + } - if (IsOverdue(expirationDate)) - { - RemoveHostFromBlackList(host); - return false; - } - - return true; - } + private bool IsOverdue(Timestamp expirationDate) + { + return TimestampHelper.GetUtcNow() > expirationDate; + } - private bool IsOverdue(Timestamp expirationDate) - { - return TimestampHelper.GetUtcNow() > expirationDate; - } - - private void CleanBlackList() - { - foreach (var blackListedPeer in _blackListedPeers) - { - if (IsOverdue(blackListedPeer.Value)) - { - RemoveHostFromBlackList(blackListedPeer.Key); - } - } - } + private void CleanBlackList() + { + foreach (var blackListedPeer in _blackListedPeers) + if (IsOverdue(blackListedPeer.Value)) + RemoveHostFromBlackList(blackListedPeer.Key); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IDiscoveredNodeCacheProvider.cs b/src/AElf.OS.Core/Network/Infrastructure/IDiscoveredNodeCacheProvider.cs index fe203846b4..db9c0f43a2 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IDiscoveredNodeCacheProvider.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IDiscoveredNodeCacheProvider.cs @@ -1,32 +1,31 @@ using System.Collections.Concurrent; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IDiscoveredNodeCacheProvider { - public interface IDiscoveredNodeCacheProvider + void Add(string nodeEndpoint); + + bool TryTake(out string nodeEndpoint); +} + +public class DiscoveredNodeCacheProvider : IDiscoveredNodeCacheProvider, ISingletonDependency +{ + private readonly ConcurrentQueue _queuedNodes; + + public DiscoveredNodeCacheProvider() { - void Add(string nodeEndpoint); - - bool TryTake(out string nodeEndpoint); + _queuedNodes = new ConcurrentQueue(); } - public class DiscoveredNodeCacheProvider : IDiscoveredNodeCacheProvider, ISingletonDependency + public void Add(string nodeEndpoint) { - private readonly ConcurrentQueue _queuedNodes; - - public DiscoveredNodeCacheProvider() - { - _queuedNodes = new ConcurrentQueue(); - } - - public void Add(string nodeEndpoint) - { - _queuedNodes.Enqueue(nodeEndpoint); - } + _queuedNodes.Enqueue(nodeEndpoint); + } - public bool TryTake(out string nodeEndpoint) - { - return _queuedNodes.TryDequeue(out nodeEndpoint); - } + public bool TryTake(out string nodeEndpoint) + { + return _queuedNodes.TryDequeue(out nodeEndpoint); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/INodeSyncStateProvider.cs b/src/AElf.OS.Core/Network/Infrastructure/INodeSyncStateProvider.cs index 7342834660..90f2be863c 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/INodeSyncStateProvider.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/INodeSyncStateProvider.cs @@ -1,25 +1,24 @@ using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface INodeSyncStateProvider { - public interface INodeSyncStateProvider - { - long SyncTarget { get; } - void SetSyncTarget(long target); - } - - public class NodeSyncStateProvider : INodeSyncStateProvider, ISingletonDependency - { - /// - /// The target block height of the sync. 0 is the initial state, meaning - /// the target has never being set. The value is set to -1 when the sync - /// is finished. - /// - public long SyncTarget { get; private set; } = 0; + long SyncTarget { get; } + void SetSyncTarget(long target); +} - public void SetSyncTarget(long target) - { - SyncTarget = target; - } +public class NodeSyncStateProvider : INodeSyncStateProvider, ISingletonDependency +{ + /// + /// The target block height of the sync. 0 is the initial state, meaning + /// the target has never being set. The value is set to -1 when the sync + /// is finished. + /// + public long SyncTarget { get; private set; } + + public void SetSyncTarget(long target) + { + SyncTarget = target; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IPeer.cs b/src/AElf.OS.Core/Network/Infrastructure/IPeer.cs index 72081552fe..464a4caac5 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IPeer.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IPeer.cs @@ -8,47 +8,46 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IPeer { - public interface IPeer - { - bool IsReady { get; } - string ConnectionStatus { get; } - bool IsInvalid { get; } - SyncState SyncState { get; } - Hash LastKnownLibHash { get; } - long LastKnownLibHeight { get; } - Timestamp LastReceivedHandshakeTime { get; } - DnsEndPoint RemoteEndpoint { get; } - - int BufferedTransactionsCount { get; } - int BufferedBlocksCount { get; } - int BufferedAnnouncementsCount { get; } - - byte[] InboundSessionId { get; } - - PeerConnectionInfo Info { get; } - - Task CheckHealthAsync(); - - bool KnowsBlock(Hash hash); - bool TryAddKnownBlock(Hash blockHash); - bool KnowsTransaction(Hash hash); - bool TryAddKnownTransaction(Hash transactionHash); - void UpdateLastKnownLib(LibAnnouncement libAnnouncement); - - void EnqueueAnnouncement(BlockAnnouncement transaction, Action sendCallback); - void EnqueueTransaction(Transaction transaction, Action sendCallback); - void EnqueueBlock(BlockWithTransactions blockWithTransactions, Action sendCallback); - void EnqueueLibAnnouncement(LibAnnouncement libAnnouncement,Action sendCallback); - - Task GetBlockByHashAsync(Hash hash); - Task> GetBlocksAsync(Hash previousHash, int count); - Task GetNodesAsync(int count = NetworkConstants.DefaultDiscoveryMaxNodesToRequest); - - Task TryRecoverAsync(); - - Dictionary> GetRequestMetrics(); - Task DisconnectAsync(bool gracefulDisconnect); - } + bool IsReady { get; } + string ConnectionStatus { get; } + bool IsInvalid { get; } + SyncState SyncState { get; } + Hash LastKnownLibHash { get; } + long LastKnownLibHeight { get; } + Timestamp LastReceivedHandshakeTime { get; } + DnsEndPoint RemoteEndpoint { get; } + + int BufferedTransactionsCount { get; } + int BufferedBlocksCount { get; } + int BufferedAnnouncementsCount { get; } + + byte[] InboundSessionId { get; } + + PeerConnectionInfo Info { get; } + + Task CheckHealthAsync(); + + bool KnowsBlock(Hash hash); + bool TryAddKnownBlock(Hash blockHash); + bool KnowsTransaction(Hash hash); + bool TryAddKnownTransaction(Hash transactionHash); + void UpdateLastKnownLib(LibAnnouncement libAnnouncement); + + void EnqueueAnnouncement(BlockAnnouncement transaction, Action sendCallback); + void EnqueueTransaction(Transaction transaction, Action sendCallback); + void EnqueueBlock(BlockWithTransactions blockWithTransactions, Action sendCallback); + void EnqueueLibAnnouncement(LibAnnouncement libAnnouncement, Action sendCallback); + + Task GetBlockByHashAsync(Hash hash); + Task> GetBlocksAsync(Hash previousHash, int count); + Task GetNodesAsync(int count = NetworkConstants.DefaultDiscoveryMaxNodesToRequest); + + Task TryRecoverAsync(); + + Dictionary> GetRequestMetrics(); + Task DisconnectAsync(bool gracefulDisconnect); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IPeerDiscoveryJobProcessor.cs b/src/AElf.OS.Core/Network/Infrastructure/IPeerDiscoveryJobProcessor.cs index ad53b3706e..cc1be3d022 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IPeerDiscoveryJobProcessor.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IPeerDiscoveryJobProcessor.cs @@ -5,166 +5,162 @@ using System.Threading.Tasks.Dataflow; using AElf.Kernel.Account.Application; using AElf.OS.Network.Domain; +using AElf.OS.Network.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; -using AElf.OS.Network.Extensions; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IPeerDiscoveryJobProcessor { - public interface IPeerDiscoveryJobProcessor + Task SendDiscoveryJobAsync(IPeer peer); + Task CompleteAsync(); +} + +public class PeerDiscoveryJobProcessor : IPeerDiscoveryJobProcessor, ISingletonDependency +{ + private const int DiscoverNodesBoundedCapacity = 50; + private const int DiscoverNodesMaxDegreeOfParallelism = 5; + private const int ProcessNodeBoundedCapacity = 200; + private const int ProcessNodeMaxDegreeOfParallelism = 5; + private readonly IAccountService _accountService; + private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; + private readonly IAElfNetworkServer _networkServer; + private readonly INodeManager _nodeManager; + + private TransformManyBlock _discoverNodesDataflow; + private ActionBlock _processNodeDataflow; + + public PeerDiscoveryJobProcessor(INodeManager nodeManager, + IDiscoveredNodeCacheProvider discoveredNodeCacheProvider, IAElfNetworkServer networkServer, + IAccountService accountService) { - Task SendDiscoveryJobAsync(IPeer peer); - Task CompleteAsync(); + _nodeManager = nodeManager; + _discoveredNodeCacheProvider = discoveredNodeCacheProvider; + _networkServer = networkServer; + _accountService = accountService; + CreatePeerDiscoveryDataflow(); + + Logger = NullLogger.Instance; } - public class PeerDiscoveryJobProcessor : IPeerDiscoveryJobProcessor, ISingletonDependency + public ILogger Logger { get; set; } + + public async Task SendDiscoveryJobAsync(IPeer peer) { - private readonly INodeManager _nodeManager; - private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; - private readonly IAElfNetworkServer _networkServer; - private readonly IAccountService _accountService; + return await _discoverNodesDataflow.SendAsync(peer); + } - private TransformManyBlock _discoverNodesDataflow; - private ActionBlock _processNodeDataflow; + public async Task CompleteAsync() + { + _discoverNodesDataflow.Complete(); + await _processNodeDataflow.Completion; + } - private const int DiscoverNodesBoundedCapacity = 50; - private const int DiscoverNodesMaxDegreeOfParallelism = 5; - private const int ProcessNodeBoundedCapacity = 200; - private const int ProcessNodeMaxDegreeOfParallelism = 5; + private void CreatePeerDiscoveryDataflow() + { + _discoverNodesDataflow = new TransformManyBlock( + async peer => await DiscoverNodesAsync(peer), + new ExecutionDataflowBlockOptions + { + BoundedCapacity = DiscoverNodesBoundedCapacity, + MaxDegreeOfParallelism = DiscoverNodesMaxDegreeOfParallelism + }); - public ILogger Logger { get; set; } + _processNodeDataflow = + new ActionBlock(async node => await ProcessNodeAsync(node), new ExecutionDataflowBlockOptions + { + BoundedCapacity = ProcessNodeBoundedCapacity, + MaxDegreeOfParallelism = ProcessNodeMaxDegreeOfParallelism + }); - public PeerDiscoveryJobProcessor(INodeManager nodeManager, - IDiscoveredNodeCacheProvider discoveredNodeCacheProvider, IAElfNetworkServer networkServer, - IAccountService accountService) + _discoverNodesDataflow.LinkTo(_processNodeDataflow, new DataflowLinkOptions { PropagateCompletion = true }); + } + + private async Task> DiscoverNodesAsync(IPeer peer) + { + try { - _nodeManager = nodeManager; - _discoveredNodeCacheProvider = discoveredNodeCacheProvider; - _networkServer = networkServer; - _accountService = accountService; - CreatePeerDiscoveryDataflow(); + var nodeList = await peer.GetNodesAsync(); - Logger = NullLogger.Instance; - } + if (nodeList?.Nodes == null) + return new List(); - public async Task SendDiscoveryJobAsync(IPeer peer) - { - return await _discoverNodesDataflow.SendAsync(peer); + Logger.LogDebug($"Discover nodes: {nodeList} from peer: {peer}."); + return nodeList.Nodes.ToList(); } - - public async Task CompleteAsync() + catch (Exception e) { - _discoverNodesDataflow.Complete(); - await _processNodeDataflow.Completion; + Logger.LogWarning(e, "Discover nodes failed."); + return new List(); } + } - private void CreatePeerDiscoveryDataflow() + private async Task ProcessNodeAsync(NodeInfo node) + { + try { - _discoverNodesDataflow = new TransformManyBlock( - async peer => await DiscoverNodesAsync(peer), - new ExecutionDataflowBlockOptions - { - BoundedCapacity = DiscoverNodesBoundedCapacity, - MaxDegreeOfParallelism = DiscoverNodesMaxDegreeOfParallelism - }); - - _processNodeDataflow = - new ActionBlock(async node => await ProcessNodeAsync(node), new ExecutionDataflowBlockOptions - { - BoundedCapacity = ProcessNodeBoundedCapacity, - MaxDegreeOfParallelism = ProcessNodeMaxDegreeOfParallelism - }); - - _discoverNodesDataflow.LinkTo(_processNodeDataflow, new DataflowLinkOptions {PropagateCompletion = true}); - } + if (!await ValidateNodeAsync(node)) + return; - private async Task> DiscoverNodesAsync(IPeer peer) - { - try + if (await _nodeManager.AddNodeAsync(node)) { - var nodeList = await peer.GetNodesAsync(); - - if (nodeList?.Nodes == null) - return new List(); - - Logger.LogDebug($"Discover nodes: {nodeList} from peer: {peer}."); - return nodeList.Nodes.ToList(); + _discoveredNodeCacheProvider.Add(node.Endpoint); + Logger.LogDebug($"Discover and add node: {node.Endpoint} successfully."); } - catch (Exception e) + else { - Logger.LogWarning(e, "Discover nodes failed."); - return new List(); - } - } + var endpointLocal = await TakeEndpointFromDiscoveredNodeCacheAsync(); - private async Task ProcessNodeAsync(NodeInfo node) - { - try - { - if (!await ValidateNodeAsync(node)) + if (endpointLocal.IsNullOrWhiteSpace()) return; - if (await _nodeManager.AddNodeAsync(node)) + if (await _networkServer.CheckEndpointAvailableAsync(endpointLocal)) { - _discoveredNodeCacheProvider.Add(node.Endpoint); - Logger.LogDebug($"Discover and add node: {node.Endpoint} successfully."); + _discoveredNodeCacheProvider.Add(endpointLocal); + Logger.LogDebug($"Only refresh node: {endpointLocal}."); } else { - var endpointLocal = await TakeEndpointFromDiscoveredNodeCacheAsync(); - - if(endpointLocal.IsNullOrWhiteSpace()) - return; - - if (await _networkServer.CheckEndpointAvailableAsync(endpointLocal)) - { - _discoveredNodeCacheProvider.Add(endpointLocal); - Logger.LogDebug($"Only refresh node: {endpointLocal}."); - } - else - { - await _nodeManager.RemoveNodeAsync(endpointLocal); - if (await _nodeManager.AddNodeAsync(node)) - _discoveredNodeCacheProvider.Add(node.Endpoint); - - Logger.LogDebug( - $"Remove unavailable node: {endpointLocal}, and add node: {node.Endpoint} successfully."); - } + await _nodeManager.RemoveNodeAsync(endpointLocal); + if (await _nodeManager.AddNodeAsync(node)) + _discoveredNodeCacheProvider.Add(node.Endpoint); + + Logger.LogDebug( + $"Remove unavailable node: {endpointLocal}, and add node: {node.Endpoint} successfully."); } } - catch (Exception e) - { - Logger.LogWarning(e, "Process node failed."); - } } - - private async Task ValidateNodeAsync(NodeInfo node) + catch (Exception e) { - if ((await _accountService.GetPublicKeyAsync()).ToHex() == node.Pubkey.ToHex()) - return false; - - if (await _nodeManager.GetNodeAsync(node.Endpoint) != null) - { - await _nodeManager.UpdateNodeAsync(node); - return false; - } + Logger.LogWarning(e, "Process node failed."); + } + } - if (!await _networkServer.CheckEndpointAvailableAsync(node.Endpoint)) - return false; + private async Task ValidateNodeAsync(NodeInfo node) + { + if ((await _accountService.GetPublicKeyAsync()).ToHex() == node.Pubkey.ToHex()) + return false; - return true; + if (await _nodeManager.GetNodeAsync(node.Endpoint) != null) + { + await _nodeManager.UpdateNodeAsync(node); + return false; } - private async Task TakeEndpointFromDiscoveredNodeCacheAsync() - { - while (_discoveredNodeCacheProvider.TryTake(out var endpoint)) - { - if (await _nodeManager.GetNodeAsync(endpoint) != null) - return endpoint; - } + if (!await _networkServer.CheckEndpointAvailableAsync(node.Endpoint)) + return false; - return null; - } + return true; + } + + private async Task TakeEndpointFromDiscoveredNodeCacheAsync() + { + while (_discoveredNodeCacheProvider.TryTake(out var endpoint)) + if (await _nodeManager.GetNodeAsync(endpoint) != null) + return endpoint; + + return null; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IPeerInvalidTransactionProvider.cs b/src/AElf.OS.Core/Network/Infrastructure/IPeerInvalidTransactionProvider.cs index 806e78b863..9ea04c2c1d 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IPeerInvalidTransactionProvider.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IPeerInvalidTransactionProvider.cs @@ -2,104 +2,100 @@ using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IPeerInvalidTransactionProvider { - public interface IPeerInvalidTransactionProvider - { - bool TryMarkInvalidTransaction(string host, Hash transactionId); - bool TryRemoveInvalidRecord(string host); - } + bool TryMarkInvalidTransaction(string host, Hash transactionId); + bool TryRemoveInvalidRecord(string host); +} - public class PeerInvalidTransactionProvider : IPeerInvalidTransactionProvider, ISingletonDependency - { - private readonly NetworkOptions _networkOptions; +public class PeerInvalidTransactionProvider : IPeerInvalidTransactionProvider, ISingletonDependency +{ + private readonly ConcurrentDictionary _hostInvalidTransactionIdCache; - private readonly ConcurrentDictionary> _invalidTransactionCache; - private readonly ConcurrentDictionary _hostInvalidTransactionIdCache; + private readonly ConcurrentDictionary> _invalidTransactionCache; + private readonly NetworkOptions _networkOptions; - public ILogger Logger { get; set; } + public PeerInvalidTransactionProvider(IOptionsSnapshot networkOptions) + { + _networkOptions = networkOptions.Value; + _invalidTransactionCache = new ConcurrentDictionary>(); + _hostInvalidTransactionIdCache = new ConcurrentDictionary(); + Logger = NullLogger.Instance; + } - public PeerInvalidTransactionProvider(IOptionsSnapshot networkOptions) - { - _networkOptions = networkOptions.Value; - _invalidTransactionCache = new ConcurrentDictionary>(); - _hostInvalidTransactionIdCache = new ConcurrentDictionary(); - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public bool TryMarkInvalidTransaction(string host, Hash transactionId) + public bool TryMarkInvalidTransaction(string host, Hash transactionId) + { + var txId = transactionId.ToHex(); + if (_hostInvalidTransactionIdCache.TryAdd(GetHostInvalidTransactionIdCacheKey(host, txId), 1)) { - var txId = transactionId.ToHex(); - if (_hostInvalidTransactionIdCache.TryAdd(GetHostInvalidTransactionIdCacheKey(host, txId), 1)) + if (!_invalidTransactionCache.TryGetValue(host, out var queue)) { - if (!_invalidTransactionCache.TryGetValue(host, out var queue)) - { - queue = new ConcurrentQueue(); - _invalidTransactionCache[host] = queue; - } - - CleanCache(host, queue); - - queue.Enqueue(new InvalidTransaction - { - TransactionId = txId, - Timestamp = TimestampHelper.GetUtcNow() - }); - - Logger.LogDebug($"Mark peer invalid transaction. host: {host}, count: {queue.Count}"); - - return queue.Count <= _networkOptions.PeerInvalidTransactionLimit; + queue = new ConcurrentQueue(); + _invalidTransactionCache[host] = queue; } - return true; - } + CleanCache(host, queue); - public bool TryRemoveInvalidRecord(string host) - { - if (_invalidTransactionCache.TryGetValue(host, out var invalidTransactions)) + queue.Enqueue(new InvalidTransaction { - foreach (var invalidTransaction in invalidTransactions) - { - _hostInvalidTransactionIdCache.TryRemove( - GetHostInvalidTransactionIdCacheKey(host, invalidTransaction.TransactionId), out _); - } + TransactionId = txId, + Timestamp = TimestampHelper.GetUtcNow() + }); - return _invalidTransactionCache.TryRemove(host, out _); - } + Logger.LogDebug($"Mark peer invalid transaction. host: {host}, count: {queue.Count}"); - return false; + return queue.Count <= _networkOptions.PeerInvalidTransactionLimit; } - private void CleanCache(string host, ConcurrentQueue queue) + return true; + } + + public bool TryRemoveInvalidRecord(string host) + { + if (_invalidTransactionCache.TryGetValue(host, out var invalidTransactions)) { - while (!queue.IsEmpty - && queue.TryPeek(out var invalidTransaction) - && invalidTransaction.Timestamp.AddMilliseconds(_networkOptions.PeerInvalidTransactionTimeout) < - TimestampHelper.GetUtcNow()) - { + foreach (var invalidTransaction in invalidTransactions) _hostInvalidTransactionIdCache.TryRemove( GetHostInvalidTransactionIdCacheKey(host, invalidTransaction.TransactionId), out _); - queue.TryDequeue(out _); - } + + return _invalidTransactionCache.TryRemove(host, out _); } - private string GetHostInvalidTransactionIdCacheKey(string host, string transactionId) + return false; + } + + private void CleanCache(string host, ConcurrentQueue queue) + { + while (!queue.IsEmpty + && queue.TryPeek(out var invalidTransaction) + && invalidTransaction.Timestamp.AddMilliseconds(_networkOptions.PeerInvalidTransactionTimeout) < + TimestampHelper.GetUtcNow()) { - return host + transactionId; + _hostInvalidTransactionIdCache.TryRemove( + GetHostInvalidTransactionIdCacheKey(host, invalidTransaction.TransactionId), out _); + queue.TryDequeue(out _); } } - public class InvalidTransaction + private string GetHostInvalidTransactionIdCacheKey(string host, string transactionId) { - public string TransactionId { get; set; } - - public Timestamp Timestamp { get; set; } + return host + transactionId; } +} + +public class InvalidTransaction +{ + public string TransactionId { get; set; } + + public Timestamp Timestamp { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IPeerPool.cs b/src/AElf.OS.Core/Network/Infrastructure/IPeerPool.cs index 9301b7d4ef..265a1f9621 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IPeerPool.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IPeerPool.cs @@ -1,31 +1,29 @@ -using System; -using System.Collections.Generic; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Net; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public interface IPeerPool { - public interface IPeerPool - { - int PeerCount { get; } + int PeerCount { get; } - bool IsFull(); - bool IsPeerBlackListed(string host); - bool IsOverIpLimit(string host); + bool IsFull(); + bool IsPeerBlackListed(string host); + bool IsOverIpLimit(string host); - bool AddHandshakingPeer(string host, string pubkey); - bool RemoveHandshakingPeer(string host, string pubkey); - Dictionary> GetHandshakingPeers(); + bool AddHandshakingPeer(string host, string pubkey); + bool RemoveHandshakingPeer(string host, string pubkey); + Dictionary> GetHandshakingPeers(); - List GetPeers(bool includeFailing = false); + List GetPeers(bool includeFailing = false); - IPeer FindPeerByEndpoint(DnsEndPoint peerEndpoint); - IPeer FindPeerByPublicKey(string remotePubKey); + IPeer FindPeerByEndpoint(DnsEndPoint peerEndpoint); + IPeer FindPeerByPublicKey(string remotePubKey); - List GetPeersByHost(string host); + List GetPeersByHost(string host); - bool TryReplace(string pubkey, IPeer oldPeer, IPeer newPeer); - bool TryAddPeer(IPeer peer); - IPeer RemovePeer(string publicKey); - } + bool TryReplace(string pubkey, IPeer oldPeer, IPeer newPeer); + bool TryAddPeer(IPeer peer); + IPeer RemovePeer(string publicKey); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/IPeerReconnectionStateProvider.cs b/src/AElf.OS.Core/Network/Infrastructure/IPeerReconnectionStateProvider.cs index 79a4f90d49..321df9604e 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/IPeerReconnectionStateProvider.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/IPeerReconnectionStateProvider.cs @@ -1,60 +1,57 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Google.Protobuf.WellKnownTypes; -using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class ReconnectingPeer +{ + public string Endpoint { get; set; } + public Timestamp NextAttempt { get; set; } + public int RetryCount { get; set; } + public Timestamp DisconnectionTime { get; set; } +} + +public interface IPeerReconnectionStateProvider { - public class ReconnectingPeer + bool AddReconnectingPeer(string peerEndpoint, ReconnectingPeer reconnectingPeer); + List GetPeersReadyForReconnection(Timestamp maxTime); + ReconnectingPeer GetReconnectingPeer(string peerEndpoint); + bool RemoveReconnectionPeer(string peerEndpoint); +} + +public class PeerReconnectionStateProvider : IPeerReconnectionStateProvider, ISingletonDependency +{ + private readonly ConcurrentDictionary _reconnectingPeers; + + public PeerReconnectionStateProvider() { - public string Endpoint { get; set; } - public Timestamp NextAttempt { get; set; } - public int RetryCount { get; set; } - public Timestamp DisconnectionTime { get; set; } + _reconnectingPeers = new ConcurrentDictionary(); } - public interface IPeerReconnectionStateProvider + public bool AddReconnectingPeer(string peerEndpoint, ReconnectingPeer reconnectingPeer) { - bool AddReconnectingPeer(string peerEndpoint, ReconnectingPeer reconnectingPeer); - List GetPeersReadyForReconnection(Timestamp maxTime); - ReconnectingPeer GetReconnectingPeer(string peerEndpoint); - bool RemoveReconnectionPeer(string peerEndpoint); + return _reconnectingPeers.TryAdd(peerEndpoint, reconnectingPeer); } - public class PeerReconnectionStateProvider : IPeerReconnectionStateProvider, ISingletonDependency + public bool RemoveReconnectionPeer(string peerEndpoint) { - private readonly ConcurrentDictionary _reconnectingPeers; - - public PeerReconnectionStateProvider() - { - _reconnectingPeers = new ConcurrentDictionary(); - } - - public bool AddReconnectingPeer(string peerEndpoint, ReconnectingPeer reconnectingPeer) - { - return _reconnectingPeers.TryAdd(peerEndpoint, reconnectingPeer); - } - - public bool RemoveReconnectionPeer(string peerEndpoint) - { - return _reconnectingPeers.TryRemove(peerEndpoint, out _); - } - - public ReconnectingPeer GetReconnectingPeer(string peerEndpoint) - { - _reconnectingPeers.TryGetValue(peerEndpoint, out var reconnectingPeer); - return reconnectingPeer; - } - - public List GetPeersReadyForReconnection(Timestamp maxTime) - { - if (maxTime == null) - return _reconnectingPeers.Values.ToList(); - - return _reconnectingPeers.Values.Where(rp => rp.NextAttempt < maxTime).ToList(); - } + return _reconnectingPeers.TryRemove(peerEndpoint, out _); + } + + public ReconnectingPeer GetReconnectingPeer(string peerEndpoint) + { + _reconnectingPeers.TryGetValue(peerEndpoint, out var reconnectingPeer); + return reconnectingPeer; + } + + public List GetPeersReadyForReconnection(Timestamp maxTime) + { + if (maxTime == null) + return _reconnectingPeers.Values.ToList(); + + return _reconnectingPeers.Values.Where(rp => rp.NextAttempt < maxTime).ToList(); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Infrastructure/PeerPool.cs b/src/AElf.OS.Core/Network/Infrastructure/PeerPool.cs index 6b1fce3d79..fe2faa1682 100644 --- a/src/AElf.OS.Core/Network/Infrastructure/PeerPool.cs +++ b/src/AElf.OS.Core/Network/Infrastructure/PeerPool.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -8,168 +7,171 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +/// +/// Manages all active connections to peers. +/// +public class PeerPool : IPeerPool, ISingletonDependency { - /// - /// Manages all active connections to peers. - /// - public class PeerPool : IPeerPool, ISingletonDependency + private readonly IBlackListedPeerProvider _blackListedPeerProvider; + protected readonly ConcurrentDictionary> HandshakingPeers; + + protected readonly ConcurrentDictionary Peers; + + public PeerPool(IBlackListedPeerProvider blackListedPeerProvider) { - private readonly IBlackListedPeerProvider _blackListedPeerProvider; - public ILogger Logger { get; set; } + _blackListedPeerProvider = blackListedPeerProvider; + Peers = new ConcurrentDictionary(); + HandshakingPeers = new ConcurrentDictionary>(); + Logger = NullLogger.Instance; + } - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + public ILogger Logger { get; set; } - public int PeerCount => Peers.Count; - public Dictionary> GetHandshakingPeers() - => HandshakingPeers.ToDictionary(p => p.Key, p => p.Value); + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - protected readonly ConcurrentDictionary Peers; - protected readonly ConcurrentDictionary> HandshakingPeers; + public int PeerCount => Peers.Count; - public PeerPool(IBlackListedPeerProvider blackListedPeerProvider) - { - _blackListedPeerProvider = blackListedPeerProvider; - Peers = new ConcurrentDictionary(); - HandshakingPeers = new ConcurrentDictionary>(); - Logger = NullLogger.Instance; - } + public Dictionary> GetHandshakingPeers() + { + return HandshakingPeers.ToDictionary(p => p.Key, p => p.Value); + } - public bool IsFull() - { - var peerCount = Peers.Where(p => !p.Value.IsInvalid).ToList().Count; - return NetworkOptions.MaxPeers != 0 && peerCount >= NetworkOptions.MaxPeers; - } + public bool IsFull() + { + var peerCount = Peers.Where(p => !p.Value.IsInvalid).ToList().Count; + return NetworkOptions.MaxPeers != 0 && peerCount >= NetworkOptions.MaxPeers; + } - public bool IsPeerBlackListed(string host) - { - return _blackListedPeerProvider.IsIpBlackListed(host); - } + public bool IsPeerBlackListed(string host) + { + return _blackListedPeerProvider.IsIpBlackListed(host); + } + + public bool IsOverIpLimit(string host) + { + if (NetworkOptions.MaxPeersPerIpAddress == 0 || host.Equals(IPAddress.Loopback.ToString())) + return false; + + var initiatedHandshakes = 0; + if (HandshakingPeers.TryGetValue(host, out var handshakes)) + initiatedHandshakes = handshakes.Count; - public bool IsOverIpLimit(string host) + var peersFromIpCount = GetPeersByHost(host).Count; + if (peersFromIpCount + initiatedHandshakes >= NetworkOptions.MaxPeersPerIpAddress) { - if (NetworkOptions.MaxPeersPerIpAddress == 0 || host.Equals(IPAddress.Loopback.ToString())) - return false; - - int initiatedHandshakes = 0; - if (HandshakingPeers.TryGetValue(host, out var handshakes)) - initiatedHandshakes = handshakes.Count; - - int peersFromIpCount = GetPeersByHost(host).Count; - if (peersFromIpCount + initiatedHandshakes >= NetworkOptions.MaxPeersPerIpAddress) - { - Logger.LogWarning($"Max peers from {host} exceeded, current count {peersFromIpCount} " + - $"(max. per ip {NetworkOptions.MaxPeersPerIpAddress})."); + Logger.LogWarning($"Max peers from {host} exceeded, current count {peersFromIpCount} " + + $"(max. per ip {NetworkOptions.MaxPeersPerIpAddress})."); - return true; - } + return true; + } + return false; + } + + public bool AddHandshakingPeer(string host, string pubkey) + { + if (IsPeerBlackListed(host)) + { + Logger.LogDebug($"{host} - peer pool is blacklisted."); return false; } - public bool AddHandshakingPeer(string host, string pubkey) + // check if we have room for a new peer + if (IsFull() || IsOverIpLimit(host)) { - if (IsPeerBlackListed(host)) - { - Logger.LogDebug($"{host} - peer pool is blacklisted."); - return false; - } + Logger.LogWarning($"{host} - peer pool is full."); + return false; + } - // check if we have room for a new peer - if (IsFull() || IsOverIpLimit(host)) + var added = true; + HandshakingPeers.AddOrUpdate(host, new ConcurrentDictionary { [pubkey] = pubkey }, + (key, handshakes) => { - Logger.LogWarning($"{host} - peer pool is full."); - return false; - } - - bool added = true; - HandshakingPeers.AddOrUpdate(host, new ConcurrentDictionary { [pubkey] = pubkey }, - (key, handshakes) => + if (IsOverIpLimit(host)) { - if (IsOverIpLimit(host)) - { - added = false; - Logger.LogWarning($"{host} - peer pool is full."); - return handshakes; - } - - if (!handshakes.TryAdd(pubkey, pubkey)) - { - added = false; - Logger.LogDebug($"{host} - pubkey {pubkey} is already handshaking."); - } - + added = false; + Logger.LogWarning($"{host} - peer pool is full."); return handshakes; - }); + } - return added; - } + if (!handshakes.TryAdd(pubkey, pubkey)) + { + added = false; + Logger.LogDebug($"{host} - pubkey {pubkey} is already handshaking."); + } - public bool RemoveHandshakingPeer(string host, string pubkey) - { - bool removed = false; - if (HandshakingPeers.TryGetValue(host, out var pubkeys)) - { - removed = pubkeys.TryRemove(pubkey, out _); + return handshakes; + }); - if (pubkeys.IsNullOrEmpty()) - HandshakingPeers.TryRemove(host, out _); - } + return added; + } - return removed; + public bool RemoveHandshakingPeer(string host, string pubkey) + { + var removed = false; + if (HandshakingPeers.TryGetValue(host, out var pubkeys)) + { + removed = pubkeys.TryRemove(pubkey, out _); + + if (pubkeys.IsNullOrEmpty()) + HandshakingPeers.TryRemove(host, out _); } - public List GetPeers(bool includeFailing = false) - { - var peers = Peers.Select(p => p.Value); + return removed; + } - if (!includeFailing) - peers = peers.Where(p => p.IsReady); + public List GetPeers(bool includeFailing = false) + { + var peers = Peers.Select(p => p.Value); - return peers.Select(p => p).ToList(); - } + if (!includeFailing) + peers = peers.Where(p => p.IsReady); - public IPeer FindPeerByEndpoint(DnsEndPoint endpoint) - { - return Peers - .Where(p => p.Value.RemoteEndpoint.Equals(endpoint)) - .Select(p => p.Value) - .FirstOrDefault(); - } + return peers.Select(p => p).ToList(); + } - public IPeer FindPeerByPublicKey(string publicKey) - { - if (string.IsNullOrEmpty(publicKey)) - return null; + public IPeer FindPeerByEndpoint(DnsEndPoint endpoint) + { + return Peers + .Where(p => p.Value.RemoteEndpoint.Equals(endpoint)) + .Select(p => p.Value) + .FirstOrDefault(); + } - Peers.TryGetValue(publicKey, out IPeer p); + public IPeer FindPeerByPublicKey(string publicKey) + { + if (string.IsNullOrEmpty(publicKey)) + return null; - return p; - } + Peers.TryGetValue(publicKey, out var p); - public List GetPeersByHost(string host) - { - return Peers - .Where(p => p.Value.RemoteEndpoint.Host.Equals(host)) - .Select(p => p.Value) - .ToList(); - } + return p; + } - public IPeer RemovePeer(string publicKey) - { - Peers.TryRemove(publicKey, out IPeer removed); - return removed; - } + public List GetPeersByHost(string host) + { + return Peers + .Where(p => p.Value.RemoteEndpoint.Host.Equals(host)) + .Select(p => p.Value) + .ToList(); + } - public bool TryAddPeer(IPeer peer) - { - return Peers.TryAdd(peer.Info.Pubkey, peer); - } - - public bool TryReplace(string pubKey, IPeer oldPeer, IPeer newPeer) - { - return Peers.TryUpdate(pubKey, newPeer, oldPeer); - } + public IPeer RemovePeer(string publicKey) + { + Peers.TryRemove(publicKey, out var removed); + return removed; + } + + public bool TryAddPeer(IPeer peer) + { + return Peers.TryAdd(peer.Info.Pubkey, peer); + } + + public bool TryReplace(string pubKey, IPeer oldPeer, IPeer newPeer) + { + return Peers.TryUpdate(pubKey, newPeer, oldPeer); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Metrics/RequestMetric.cs b/src/AElf.OS.Core/Network/Metrics/RequestMetric.cs index 79185f3036..c87d7e100d 100644 --- a/src/AElf.OS.Core/Network/Metrics/RequestMetric.cs +++ b/src/AElf.OS.Core/Network/Metrics/RequestMetric.cs @@ -1,12 +1,11 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.Network.Metrics +namespace AElf.OS.Network.Metrics; + +public class RequestMetric { - public class RequestMetric - { - public long RoundTripTime { get; set; } - public string MethodName { get; set; } - public string Info { get; set; } - public Timestamp RequestTime { get; set; } - } + public long RoundTripTime { get; set; } + public string MethodName { get; set; } + public string Info { get; set; } + public Timestamp RequestTime { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/NetworkConstants.cs b/src/AElf.OS.Core/Network/NetworkConstants.cs index cd2514d9ca..21bd91d915 100644 --- a/src/AElf.OS.Core/Network/NetworkConstants.cs +++ b/src/AElf.OS.Core/Network/NetworkConstants.cs @@ -1,50 +1,47 @@ -using System; +namespace AElf.OS.Network; -namespace AElf.OS.Network +public static class NetworkConstants { - public static class NetworkConstants - { - public const int DefaultSslCertifFetchTimeout = 3000; - public const int DefaultPeerDialTimeout = 3000; - public const int DefaultPeerRecoveryTimeout = 3000; - public const bool DefaultCompressBlocks = true; - public const int DefaultRequestRetryCount = 1; - public const int DefaultMaxPeers = 25; - public const int DefaultMaxPeersPerIpAddress = 1; + public const int DefaultSslCertifFetchTimeout = 3000; + public const int DefaultPeerDialTimeout = 3000; + public const int DefaultPeerRecoveryTimeout = 3000; + public const bool DefaultCompressBlocks = true; + public const int DefaultRequestRetryCount = 1; + public const int DefaultMaxPeers = 25; + public const int DefaultMaxPeersPerIpAddress = 1; - public const int DefaultSessionIdSize = 5; + public const int DefaultSessionIdSize = 5; - public const int DefaultMaxBlockAgeToBroadcastInMinutes = 10; + public const int DefaultMaxBlockAgeToBroadcastInMinutes = 10; - public const int DefaultInitialSyncOffset = 512; + public const int DefaultInitialSyncOffset = 512; - public const int DefaultDiscoveryMaxNodesToRequest = 10; - public const int DefaultDiscoveryPeriod = 60_000; - public const int DefaultDiscoveryPeersToRequestCount = 5; - public const int DefaultDiscoveryMaxNodesToKeep = 512; + public const int DefaultDiscoveryMaxNodesToRequest = 10; + public const int DefaultDiscoveryPeriod = 60_000; + public const int DefaultDiscoveryPeersToRequestCount = 5; + public const int DefaultDiscoveryMaxNodesToKeep = 512; - public const string PeerReconnectionQueueName = "PeerReconnectionQueue"; - public const string AnnouncementBroadcastQueueName = "AnnouncementBroadcastQueue"; - public const string TransactionBroadcastQueueName = "TransactionBroadcastQueue"; - public const string BlockBroadcastQueueName = "BlockBroadcastQueue"; + public const string PeerReconnectionQueueName = "PeerReconnectionQueue"; + public const string AnnouncementBroadcastQueueName = "AnnouncementBroadcastQueue"; + public const string TransactionBroadcastQueueName = "TransactionBroadcastQueue"; + public const string BlockBroadcastQueueName = "BlockBroadcastQueue"; - public const long HandshakeTimeout = 1500; + public const long HandshakeTimeout = 1500; - public const long PeerConnectionTimeout = 10000; + public const long PeerConnectionTimeout = 10000; - public const int DefaultMaxBufferedTransactionCount = 100; - public const int DefaultMaxBufferedBlockCount = 50; - public const int DefaultMaxBufferedAnnouncementCount = 200; + public const int DefaultMaxBufferedTransactionCount = 100; + public const int DefaultMaxBufferedBlockCount = 50; + public const int DefaultMaxBufferedAnnouncementCount = 200; - public const int DefaultPeerReconnectionPeriod = 60_000; // 1 min - public const int DefaultMaximumReconnectionTime = 60_000 * 60 * 24; // 1 day - public const int DefaultPeerRemovalSeconds = 300; + public const int DefaultPeerReconnectionPeriod = 60_000; // 1 min + public const int DefaultMaximumReconnectionTime = 60_000 * 60 * 24; // 1 day + public const int DefaultPeerRemovalSeconds = 300; - public const int DefaultPeerPort = 6800; + public const int DefaultPeerPort = 6800; - public const int DefaultNtpDriftThreshold = 1_000; + public const int DefaultNtpDriftThreshold = 1_000; - public const int DefaultPeerInvalidTransactionTimeout = 10_000; - public const int DefaultPeerInvalidTransactionLimit = 50; - } + public const int DefaultPeerInvalidTransactionTimeout = 10_000; + public const int DefaultPeerInvalidTransactionLimit = 50; } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/NetworkOptions.cs b/src/AElf.OS.Core/Network/NetworkOptions.cs index edd61f3efb..a298f86376 100644 --- a/src/AElf.OS.Core/Network/NetworkOptions.cs +++ b/src/AElf.OS.Core/Network/NetworkOptions.cs @@ -1,86 +1,85 @@ using System; using System.Collections.Generic; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public class NetworkOptions +{ + /// + /// Initial set of nodes. + /// + public List BootNodes { get; set; } + + /// + /// Indicates the types of peers that are authorized to connect to this node. + /// Use Authorized in conjunction with . + /// + public AuthorizedPeers AuthorizedPeers { get; set; } = AuthorizedPeers.Any; + + /// + /// A list of allowed public keys that are authorized to connect to the node. + /// This will be used when is set to Authorized. + /// + public List AuthorizedKeys { get; set; } + + /// + /// Node Server listening Port. + /// + public int ListeningPort { get; set; } + + /// + /// The maximum number of peers accepted by this node (0 for no limit). + /// + public int MaxPeers { get; set; } = NetworkConstants.DefaultMaxPeers; + + /// + /// The maximum number of connection from a given host (0 for no limit). + /// + public int MaxPeersPerIpAddress { get; set; } = NetworkConstants.DefaultMaxPeersPerIpAddress; + + /// + /// Timeout used when trying to connect to another peer. + /// + public int PeerDialTimeout { get; set; } = NetworkConstants.DefaultPeerDialTimeout; + + /// + /// Period used to try and reconnect to outbound peers that have disconnected. + /// + public int PeerReconnectionPeriod { get; set; } = NetworkConstants.DefaultPeerReconnectionPeriod; + + /// + /// The maximum amount of time the node will try a reconnection (0 for no limit). + /// + public int MaximumReconnectionTime { get; set; } = NetworkConstants.DefaultMaximumReconnectionTime; + + /// + /// Indicates if this node will compress blocks when a peer requests blocks. + /// + public bool CompressBlocksOnRequest { get; set; } = NetworkConstants.DefaultCompressBlocks; + + /// + /// Indicates if the node will participate in peer discovery operations. + /// + public bool EnablePeerDiscovery { get; set; } = true; + + /// + /// The maximum number of nodes that we can keep through peer discovery. + /// + public int PeerDiscoveryMaxNodesToKeep { get; set; } = NetworkConstants.DefaultDiscoveryMaxNodesToKeep; + + /// + /// The minimum distance between this node and peers needed to trigger initial sync. + /// + public int InitialSyncOffset { get; set; } = NetworkConstants.DefaultInitialSyncOffset; + + public int PeerInvalidTransactionTimeout { get; set; } = NetworkConstants.DefaultPeerInvalidTransactionTimeout; + + public int PeerInvalidTransactionLimit { get; set; } = NetworkConstants.DefaultPeerInvalidTransactionLimit; +} + +[Flags] +public enum AuthorizedPeers { - public class NetworkOptions - { - /// - /// Initial set of nodes. - /// - public List BootNodes { get; set; } - - /// - /// Indicates the types of peers that are authorized to connect to this node. - /// Use Authorized in conjunction with . - /// - public AuthorizedPeers AuthorizedPeers { get; set; } = AuthorizedPeers.Any; - - /// - /// A list of allowed public keys that are authorized to connect to the node. - /// This will be used when is set to Authorized. - /// - public List AuthorizedKeys { get; set; } - - /// - /// Node Server listening Port. - /// - public int ListeningPort { get; set; } - - /// - /// The maximum number of peers accepted by this node (0 for no limit). - /// - public int MaxPeers { get; set; } = NetworkConstants.DefaultMaxPeers; - - /// - /// The maximum number of connection from a given host (0 for no limit). - /// - public int MaxPeersPerIpAddress { get; set; } = NetworkConstants.DefaultMaxPeersPerIpAddress; - - /// - /// Timeout used when trying to connect to another peer. - /// - public int PeerDialTimeout { get; set; } = NetworkConstants.DefaultPeerDialTimeout; - - /// - /// Period used to try and reconnect to outbound peers that have disconnected. - /// - public int PeerReconnectionPeriod { get; set; } = NetworkConstants.DefaultPeerReconnectionPeriod; - - /// - /// The maximum amount of time the node will try a reconnection (0 for no limit). - /// - public int MaximumReconnectionTime { get; set; } = NetworkConstants.DefaultMaximumReconnectionTime; - - /// - /// Indicates if this node will compress blocks when a peer requests blocks. - /// - public bool CompressBlocksOnRequest { get; set; } = NetworkConstants.DefaultCompressBlocks; - - /// - /// Indicates if the node will participate in peer discovery operations. - /// - public bool EnablePeerDiscovery { get; set; } = true; - - /// - /// The maximum number of nodes that we can keep through peer discovery. - /// - public int PeerDiscoveryMaxNodesToKeep { get; set; } = NetworkConstants.DefaultDiscoveryMaxNodesToKeep; - - /// - /// The minimum distance between this node and peers needed to trigger initial sync. - /// - public int InitialSyncOffset { get; set; } = NetworkConstants.DefaultInitialSyncOffset; - - public int PeerInvalidTransactionTimeout { get; set; } = NetworkConstants.DefaultPeerInvalidTransactionTimeout; - - public int PeerInvalidTransactionLimit { get; set; } = NetworkConstants.DefaultPeerInvalidTransactionLimit; - } - - [Flags] - public enum AuthorizedPeers - { - Any, // Any node can connect - Authorized // Only whitelisted peers can connect - } + Any, // Any node can connect + Authorized // Only whitelisted peers can connect } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/HandshakeProvider.cs b/src/AElf.OS.Core/Network/Protocol/HandshakeProvider.cs index d7c0685bf1..f517671e95 100644 --- a/src/AElf.OS.Core/Network/Protocol/HandshakeProvider.cs +++ b/src/AElf.OS.Core/Network/Protocol/HandshakeProvider.cs @@ -4,133 +4,129 @@ using AElf.Kernel; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; -using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -namespace AElf.OS.Network.Protocol +namespace AElf.OS.Network.Protocol; + +public class HandshakeProvider : IHandshakeProvider { - public class HandshakeProvider : IHandshakeProvider + private readonly IAccountService _accountService; + private readonly IBlockchainService _blockchainService; + private readonly NetworkOptions _networkOptions; + + public HandshakeProvider(IAccountService accountService, IBlockchainService blockchainService, + IOptionsSnapshot networkOptions) { - private readonly IAccountService _accountService; - private readonly IBlockchainService _blockchainService; - private readonly NetworkOptions _networkOptions; + _accountService = accountService; + _blockchainService = blockchainService; + _networkOptions = networkOptions.Value; + + Logger = NullLogger.Instance; + } + + public ILogger Logger { get; set; } - public ILogger Logger { get; set; } + public async Task GetHandshakeAsync() + { + var chain = await _blockchainService.GetChainAsync(); - public HandshakeProvider(IAccountService accountService, IBlockchainService blockchainService, - IOptionsSnapshot networkOptions) + var handshakeData = new HandshakeData { - _accountService = accountService; - _blockchainService = blockchainService; - _networkOptions = networkOptions.Value; + ChainId = chain.Id, + Version = KernelConstants.ProtocolVersion, + ListeningPort = _networkOptions.ListeningPort, + Pubkey = ByteString.CopyFrom(await _accountService.GetPublicKeyAsync()), + BestChainHash = chain.BestChainHash, + BestChainHeight = chain.BestChainHeight, + LastIrreversibleBlockHash = chain.LastIrreversibleBlockHash, + LastIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight, + Time = TimestampHelper.GetUtcNow() + }; + + var signature = await _accountService.SignAsync(HashHelper.ComputeFrom(handshakeData).ToByteArray()); + + var handshake = new Handshake + { + HandshakeData = handshakeData, + SessionId = ByteString.CopyFrom(GenerateRandomToken()), + Signature = ByteString.CopyFrom(signature) + }; + + return handshake; + } - Logger = NullLogger.Instance; + public async Task ValidateHandshakeAsync(Handshake handshake) + { + var pubkey = handshake.HandshakeData.Pubkey.ToHex(); + if (_networkOptions.AuthorizedPeers == AuthorizedPeers.Authorized && + !_networkOptions.AuthorizedKeys.Contains(pubkey)) + return HandshakeValidationResult.Unauthorized; + + var chainId = _blockchainService.GetChainId(); + if (handshake.HandshakeData.ChainId != chainId) + { + Logger.LogDebug($"Chain is is incorrect: {handshake.HandshakeData.ChainId}."); + return HandshakeValidationResult.InvalidChainId; } - public async Task GetHandshakeAsync() + if (handshake.HandshakeData.Version != KernelConstants.ProtocolVersion) { - var chain = await _blockchainService.GetChainAsync(); - - var handshakeData = new HandshakeData - { - ChainId = chain.Id, - Version = KernelConstants.ProtocolVersion, - ListeningPort = _networkOptions.ListeningPort, - Pubkey = ByteString.CopyFrom(await _accountService.GetPublicKeyAsync()), - BestChainHash = chain.BestChainHash, - BestChainHeight = chain.BestChainHeight, - LastIrreversibleBlockHash = chain.LastIrreversibleBlockHash, - LastIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight, - Time = TimestampHelper.GetUtcNow() - }; - - var signature = await _accountService.SignAsync(HashHelper.ComputeFrom(handshakeData).ToByteArray()); - - var handshake = new Handshake - { - HandshakeData = handshakeData, - SessionId = ByteString.CopyFrom(GenerateRandomToken()), - Signature = ByteString.CopyFrom(signature) - }; - - return handshake; + Logger.LogDebug($"Version is is incorrect: {handshake.HandshakeData.Version}."); + return HandshakeValidationResult.InvalidVersion; } - - public static byte[] GenerateRandomToken() + + var now = TimestampHelper.GetUtcNow(); + if (now > handshake.HandshakeData.Time + + TimestampHelper.DurationFromMilliseconds(NetworkConstants.HandshakeTimeout)) { - byte[] sessionId = new byte[NetworkConstants.DefaultSessionIdSize]; + Logger.LogDebug($"Handshake is expired: {handshake.HandshakeData.Time}, reference now: {now}."); + return HandshakeValidationResult.HandshakeTimeout; + } + + var handshakePubkey = handshake.HandshakeData.Pubkey.ToByteArray(); - using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider()) - { - rg.GetBytes(sessionId); - } + var validData = CryptoHelper.VerifySignature(handshake.Signature.ToByteArray(), + HashHelper.ComputeFrom(handshake.HandshakeData).ToByteArray(), handshakePubkey); - return sessionId; + if (!validData) + { + Logger.LogDebug("Handshake signature is incorrect."); + return HandshakeValidationResult.InvalidSignature; } - public async Task ValidateHandshakeAsync(Handshake handshake) + var nodePubKey = await _accountService.GetPublicKeyAsync(); + if (handshakePubkey.BytesEqual(nodePubKey)) { - var pubkey = handshake.HandshakeData.Pubkey.ToHex(); - if (_networkOptions.AuthorizedPeers == AuthorizedPeers.Authorized && - !_networkOptions.AuthorizedKeys.Contains(pubkey)) - { - return HandshakeValidationResult.Unauthorized; - } - - var chainId = _blockchainService.GetChainId(); - if (handshake.HandshakeData.ChainId != chainId) - { - Logger.LogDebug($"Chain is is incorrect: {handshake.HandshakeData.ChainId}."); - return HandshakeValidationResult.InvalidChainId; - } - - if (handshake.HandshakeData.Version != KernelConstants.ProtocolVersion) - { - Logger.LogDebug($"Version is is incorrect: {handshake.HandshakeData.Version}."); - return HandshakeValidationResult.InvalidVersion; - } - - var now = TimestampHelper.GetUtcNow(); - if (now > handshake.HandshakeData.Time + - TimestampHelper.DurationFromMilliseconds(NetworkConstants.HandshakeTimeout)) - { - Logger.LogDebug($"Handshake is expired: {handshake.HandshakeData.Time}, reference now: {now}."); - return HandshakeValidationResult.HandshakeTimeout; - } - - byte[] handshakePubkey = handshake.HandshakeData.Pubkey.ToByteArray(); - - var validData = CryptoHelper.VerifySignature(handshake.Signature.ToByteArray(), - HashHelper.ComputeFrom(handshake.HandshakeData).ToByteArray(), handshakePubkey); - - if (!validData) - { - Logger.LogDebug("Handshake signature is incorrect."); - return HandshakeValidationResult.InvalidSignature; - } - - var nodePubKey = await _accountService.GetPublicKeyAsync(); - if (handshakePubkey.BytesEqual(nodePubKey)) - { - Logger.LogDebug("Self connection detected."); - return HandshakeValidationResult.SelfConnection; - } - - return HandshakeValidationResult.Ok; + Logger.LogDebug("Self connection detected."); + return HandshakeValidationResult.SelfConnection; } + + return HandshakeValidationResult.Ok; } - public enum HandshakeValidationResult + public static byte[] GenerateRandomToken() { - Ok = 0, - InvalidChainId = 1, - InvalidVersion = 2, - HandshakeTimeout = 3, - InvalidSignature = 4, - Unauthorized = 5, - SelfConnection = 6 + var sessionId = new byte[NetworkConstants.DefaultSessionIdSize]; + + using (var rg = new RNGCryptoServiceProvider()) + { + rg.GetBytes(sessionId); + } + + return sessionId; } +} + +public enum HandshakeValidationResult +{ + Ok = 0, + InvalidChainId = 1, + InvalidVersion = 2, + HandshakeTimeout = 3, + InvalidSignature = 4, + Unauthorized = 5, + SelfConnection = 6 } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/IHandshakeProvider.cs b/src/AElf.OS.Core/Network/Protocol/IHandshakeProvider.cs index 2230db2e79..4bc90d32c6 100644 --- a/src/AElf.OS.Core/Network/Protocol/IHandshakeProvider.cs +++ b/src/AElf.OS.Core/Network/Protocol/IHandshakeProvider.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; -namespace AElf.OS.Network.Protocol +namespace AElf.OS.Network.Protocol; + +public interface IHandshakeProvider { - public interface IHandshakeProvider - { - Task GetHandshakeAsync(); - Task ValidateHandshakeAsync(Handshake handshake); - } + Task GetHandshakeAsync(); + Task ValidateHandshakeAsync(Handshake handshake); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/Types/BlockWithTransactions.cs b/src/AElf.OS.Core/Network/Protocol/Types/BlockWithTransactions.cs index f4b0969d83..bb4c68741d 100644 --- a/src/AElf.OS.Core/Network/Protocol/Types/BlockWithTransactions.cs +++ b/src/AElf.OS.Core/Network/Protocol/Types/BlockWithTransactions.cs @@ -1,40 +1,39 @@ -using System.Linq; using System.Collections.Generic; +using System.Linq; using AElf.Kernel; using AElf.Types; using Google.Protobuf; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public partial class BlockWithTransactions : IBlock, ICustomDiagnosticMessage { - public partial class BlockWithTransactions : IBlock, ICustomDiagnosticMessage - { - partial void OnConstruction() - { - Header = new BlockHeader(); - } + public IEnumerable FullTransactionList => Transactions; - /// - /// Used to override IMessage's default string representation. - /// - /// - public string ToDiagnosticString() - { - return $"{{ id: {GetHash()}, height: {Height} }}"; - } + public long Height => Header?.Height ?? 0; + public IEnumerable TransactionIds => Transactions.Select(tx => tx.GetHash()); - public IEnumerable FullTransactionList => Transactions; - public IEnumerable TransactionIds => Transactions.Select(tx => tx.GetHash()); + public BlockBody Body => new() + { + TransactionIds = { Transactions.Select(tx => tx.GetHash()).ToList() } + }; - public BlockBody Body => new BlockBody - { - TransactionIds = {Transactions.Select(tx => tx.GetHash()).ToList()} - }; + public Hash GetHash() + { + return Header.GetHash(); + } - public long Height => Header?.Height ?? 0; + /// + /// Used to override IMessage's default string representation. + /// + /// + public string ToDiagnosticString() + { + return $"{{ id: {GetHash()}, height: {Height} }}"; + } - public Hash GetHash() - { - return Header.GetHash(); - } + partial void OnConstruction() + { + Header = new BlockHeader(); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/Types/NodeInfo.cs b/src/AElf.OS.Core/Network/Protocol/Types/NodeInfo.cs index 4c969cd17f..ee495d1011 100644 --- a/src/AElf.OS.Core/Network/Protocol/Types/NodeInfo.cs +++ b/src/AElf.OS.Core/Network/Protocol/Types/NodeInfo.cs @@ -1,10 +1,9 @@ -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public partial class NodeInfo { - public partial class NodeInfo + public string ToDiagnosticString() { - public string ToDiagnosticString() - { - return $"{{ endpoint: {Endpoint}, key: {Pubkey.ToHex().Substring(0, 45)}... }}"; - } + return $"{{ endpoint: {Endpoint}, key: {Pubkey.ToHex().Substring(0, 45)}... }}"; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/Types/NodeList.cs b/src/AElf.OS.Core/Network/Protocol/Types/NodeList.cs index 017e1b2cc8..53960defc3 100644 --- a/src/AElf.OS.Core/Network/Protocol/Types/NodeList.cs +++ b/src/AElf.OS.Core/Network/Protocol/Types/NodeList.cs @@ -1,10 +1,9 @@ -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public partial class NodeList { - public partial class NodeList + public string ToDiagnosticString() { - public string ToDiagnosticString() - { - return string.Join(", ", Nodes); - } + return string.Join(", ", Nodes); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Protocol/Types/PeerConnectionInfo.cs b/src/AElf.OS.Core/Network/Protocol/Types/PeerConnectionInfo.cs index 76d9166f20..540a848420 100644 --- a/src/AElf.OS.Core/Network/Protocol/Types/PeerConnectionInfo.cs +++ b/src/AElf.OS.Core/Network/Protocol/Types/PeerConnectionInfo.cs @@ -1,13 +1,12 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.Network.Protocol.Types +namespace AElf.OS.Network.Protocol.Types; + +public class PeerConnectionInfo { - public class PeerConnectionInfo - { - public string Pubkey { get; set; } - public int ProtocolVersion { get; set; } - public Timestamp ConnectionTime { get; set; } - public bool IsInbound { get; set; } - public byte[] SessionId { get; set; } - } + public string Pubkey { get; set; } + public int ProtocolVersion { get; set; } + public Timestamp ConnectionTime { get; set; } + public bool IsInbound { get; set; } + public byte[] SessionId { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Types/AElfPeerEndpoint.cs b/src/AElf.OS.Core/Network/Types/AElfPeerEndpoint.cs index b57a9f4ba4..f7d2928139 100644 --- a/src/AElf.OS.Core/Network/Types/AElfPeerEndpoint.cs +++ b/src/AElf.OS.Core/Network/Types/AElfPeerEndpoint.cs @@ -1,19 +1,18 @@ using System.Net; using System.Net.Sockets; -namespace AElf.OS.Network.Types +namespace AElf.OS.Network.Types; + +// TODO: Which one is correct, Endpoint or EndPoint? +public class AElfPeerEndpoint : DnsEndPoint { - // TODO: Which one is correct, Endpoint or EndPoint? - public class AElfPeerEndpoint : DnsEndPoint + public AElfPeerEndpoint(string host, int port) + : base(host, port, AddressFamily.Unspecified) { - public AElfPeerEndpoint(string host, int port) - : base(host, port, AddressFamily.Unspecified) - { - } + } - public override string ToString() - { - return Host + ":" + Port; - } + public override string ToString() + { + return Host + ":" + Port; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Network/Types/PeerInfo.cs b/src/AElf.OS.Core/Network/Types/PeerInfo.cs index b70d101777..77909e1bc2 100644 --- a/src/AElf.OS.Core/Network/Types/PeerInfo.cs +++ b/src/AElf.OS.Core/Network/Types/PeerInfo.cs @@ -2,21 +2,20 @@ using AElf.OS.Network.Application; using AElf.OS.Network.Metrics; -namespace AElf.OS.Network.Types +namespace AElf.OS.Network.Types; + +public class PeerInfo { - public class PeerInfo - { - public string Pubkey { get; set; } - public long LastKnownLibHeight { get; set; } - public string IpAddress { get; set; } - public int ProtocolVersion { get; set; } - public long ConnectionTime { get; set; } - public string ConnectionStatus { get; set; } - public bool Inbound { get; set; } - public SyncState SyncState { get; set; } - public int BufferedTransactionsCount { get; set; } - public int BufferedBlocksCount { get; set; } - public int BufferedAnnouncementsCount { get; set; } - public List RequestMetrics { get; set; } - } + public string Pubkey { get; set; } + public long LastKnownLibHeight { get; set; } + public string IpAddress { get; set; } + public int ProtocolVersion { get; set; } + public long ConnectionTime { get; set; } + public string ConnectionStatus { get; set; } + public bool Inbound { get; set; } + public SyncState SyncState { get; set; } + public int BufferedTransactionsCount { get; set; } + public int BufferedBlocksCount { get; set; } + public int BufferedAnnouncementsCount { get; set; } + public List RequestMetrics { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/GenesisSmartContractDto.cs b/src/AElf.OS.Core/Node/Application/GenesisSmartContractDto.cs index f5f193203b..6135c163b0 100644 --- a/src/AElf.OS.Core/Node/Application/GenesisSmartContractDto.cs +++ b/src/AElf.OS.Core/Node/Application/GenesisSmartContractDto.cs @@ -2,13 +2,12 @@ using AElf.Kernel.SmartContract.Application; using AElf.Types; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public class GenesisSmartContractDto { - public class GenesisSmartContractDto - { - public byte[] Code { get; set; } - public Hash SystemSmartContractName { get; set; } + public byte[] Code { get; set; } + public Hash SystemSmartContractName { get; set; } - public List ContractInitializationMethodCallList { get; set; } - } + public List ContractInitializationMethodCallList { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/GenesisSmartContractDtoExtensions.cs b/src/AElf.OS.Core/Node/Application/GenesisSmartContractDtoExtensions.cs index 26bf17acac..a937b2ac83 100644 --- a/src/AElf.OS.Core/Node/Application/GenesisSmartContractDtoExtensions.cs +++ b/src/AElf.OS.Core/Node/Application/GenesisSmartContractDtoExtensions.cs @@ -2,26 +2,25 @@ using AElf.Kernel.SmartContract.Application; using Google.Protobuf; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public static class GenesisSmartContractDtoExtensions { - public static class GenesisSmartContractDtoExtensions + public static void AddGenesisTransactionMethodCall(this GenesisSmartContractDto genesisSmartContractDto, + params ContractInitializationMethodCall[] contractInitializationMethodCalls) { - public static void AddGenesisTransactionMethodCall(this GenesisSmartContractDto genesisSmartContractDto, - params ContractInitializationMethodCall[] contractInitializationMethodCalls) - { - genesisSmartContractDto.ContractInitializationMethodCallList.AddRange(contractInitializationMethodCalls); - } - - public static void Add( - this List contractInitializationMethodCallList, - string methodName, - IMessage input) + genesisSmartContractDto.ContractInitializationMethodCallList.AddRange(contractInitializationMethodCalls); + } + + public static void Add( + this List contractInitializationMethodCallList, + string methodName, + IMessage input) + { + contractInitializationMethodCallList.Add(new ContractInitializationMethodCall { - contractInitializationMethodCallList.Add(new ContractInitializationMethodCall - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/IGenesisSmartContractDtoProvider.cs b/src/AElf.OS.Core/Node/Application/IGenesisSmartContractDtoProvider.cs index 3341b93e63..67b2de3c5c 100644 --- a/src/AElf.OS.Core/Node/Application/IGenesisSmartContractDtoProvider.cs +++ b/src/AElf.OS.Core/Node/Application/IGenesisSmartContractDtoProvider.cs @@ -1,10 +1,8 @@ using System.Collections.Generic; -using AElf.Types; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public interface IGenesisSmartContractDtoProvider { - public interface IGenesisSmartContractDtoProvider - { - IEnumerable GetGenesisSmartContractDtos(); - } + IEnumerable GetGenesisSmartContractDtos(); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/INodeEnvironmentService.cs b/src/AElf.OS.Core/Node/Application/INodeEnvironmentService.cs index 30f34e4e51..ccacf875ee 100644 --- a/src/AElf.OS.Core/Node/Application/INodeEnvironmentService.cs +++ b/src/AElf.OS.Core/Node/Application/INodeEnvironmentService.cs @@ -1,7 +1,6 @@ -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public interface INodeEnvironmentService { - public interface INodeEnvironmentService - { - string GetAppDataPath(); - } + string GetAppDataPath(); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/IOsBlockchainNodeContextService.cs b/src/AElf.OS.Core/Node/Application/IOsBlockchainNodeContextService.cs index 2879ed6716..17d702424f 100644 --- a/src/AElf.OS.Core/Node/Application/IOsBlockchainNodeContextService.cs +++ b/src/AElf.OS.Core/Node/Application/IOsBlockchainNodeContextService.cs @@ -1,12 +1,11 @@ using System.Threading.Tasks; using AElf.OS.Node.Domain; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public interface IOsBlockchainNodeContextService { - public interface IOsBlockchainNodeContextService - { - Task StartAsync(OsBlockchainNodeContextStartDto dto); + Task StartAsync(OsBlockchainNodeContextStartDto dto); - Task StopAsync(OsBlockchainNodeContext blockchainNodeContext); - } + Task StopAsync(OsBlockchainNodeContext blockchainNodeContext); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/NodeEnvironmentService.cs b/src/AElf.OS.Core/Node/Application/NodeEnvironmentService.cs index b43e96fc66..0a9f0bda0d 100644 --- a/src/AElf.OS.Core/Node/Application/NodeEnvironmentService.cs +++ b/src/AElf.OS.Core/Node/Application/NodeEnvironmentService.cs @@ -1,19 +1,18 @@ using AElf.OS.Node.Infrastructure; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public class NodeEnvironmentService : INodeEnvironmentService { - public class NodeEnvironmentService : INodeEnvironmentService + private readonly INodeEnvironmentProvider _nodeEnvironmentProvider; + + public NodeEnvironmentService(INodeEnvironmentProvider nodeEnvironmentProvider) { - private readonly INodeEnvironmentProvider _nodeEnvironmentProvider; - - public NodeEnvironmentService(INodeEnvironmentProvider nodeEnvironmentProvider) - { - _nodeEnvironmentProvider = nodeEnvironmentProvider; - } + _nodeEnvironmentProvider = nodeEnvironmentProvider; + } - public string GetAppDataPath() - { - return _nodeEnvironmentProvider.GetAppDataPath(); - } + public string GetAppDataPath() + { + return _nodeEnvironmentProvider.GetAppDataPath(); } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextService.cs b/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextService.cs index 317ab91649..36c751e8a1 100644 --- a/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextService.cs +++ b/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextService.cs @@ -4,146 +4,142 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.Genesis; -using AElf.Standards.ACS0; using AElf.Kernel.Node.Application; using AElf.Kernel.Node.Infrastructure; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using AElf.OS.Network.Infrastructure; using AElf.OS.Node.Domain; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public class OsBlockchainNodeContextService : IOsBlockchainNodeContextService, ITransientDependency { - public class OsBlockchainNodeContextService : IOsBlockchainNodeContextService, ITransientDependency + private readonly IBlockchainNodeContextService _blockchainNodeContextService; + private readonly ContractOptions _contractOptions; + private readonly IAElfNetworkServer _networkServer; + private readonly IEnumerable _nodePlugins; + private readonly ISmartContractAddressService _smartContractAddressService; + + public OsBlockchainNodeContextService(IBlockchainNodeContextService blockchainNodeContextService, + IAElfNetworkServer networkServer, ISmartContractAddressService smartContractAddressService, + IEnumerable nodePlugins, IOptionsSnapshot contractOptions) { - private readonly IBlockchainNodeContextService _blockchainNodeContextService; - private readonly IAElfNetworkServer _networkServer; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IEnumerable _nodePlugins; - private readonly ContractOptions _contractOptions; - - public OsBlockchainNodeContextService(IBlockchainNodeContextService blockchainNodeContextService, - IAElfNetworkServer networkServer, ISmartContractAddressService smartContractAddressService, - IEnumerable nodePlugins,IOptionsSnapshot contractOptions) - { - _blockchainNodeContextService = blockchainNodeContextService; - _networkServer = networkServer; - _smartContractAddressService = smartContractAddressService; - _nodePlugins = nodePlugins; - _contractOptions = contractOptions.Value; - } + _blockchainNodeContextService = blockchainNodeContextService; + _networkServer = networkServer; + _smartContractAddressService = smartContractAddressService; + _nodePlugins = nodePlugins; + _contractOptions = contractOptions.Value; + } - public async Task StartAsync(OsBlockchainNodeContextStartDto dto) - { - var transactions = new List(); + public async Task StartAsync(OsBlockchainNodeContextStartDto dto) + { + var transactions = new List(); - transactions.Add(GetTransactionForDeployment(dto.ZeroSmartContract, - ZeroSmartContractAddressNameProvider.Name, - dto.SmartContractRunnerCategory)); + transactions.Add(GetTransactionForDeployment(dto.ZeroSmartContract, + ZeroSmartContractAddressNameProvider.Name, + dto.SmartContractRunnerCategory)); - transactions.AddRange(dto.InitializationSmartContracts - .Select(p => GetTransactionForDeployment(p.Code, p.SystemSmartContractName, - dto.SmartContractRunnerCategory, - p.ContractInitializationMethodCallList))); + transactions.AddRange(dto.InitializationSmartContracts + .Select(p => GetTransactionForDeployment(p.Code, p.SystemSmartContractName, + dto.SmartContractRunnerCategory, + p.ContractInitializationMethodCallList))); - if (dto.InitializationTransactions != null) - transactions.AddRange(dto.InitializationTransactions); + if (dto.InitializationTransactions != null) + transactions.AddRange(dto.InitializationTransactions); - // Add transaction for initialization - transactions.Add(GetTransactionForGenesisOwnerInitialization(dto)); - - var blockchainNodeContextStartDto = new BlockchainNodeContextStartDto() - { - ChainId = dto.ChainId, - ZeroSmartContractType = dto.ZeroSmartContract, - Transactions = transactions.ToArray() - }; + // Add transaction for initialization + transactions.Add(GetTransactionForGenesisOwnerInitialization(dto)); - var context = new OsBlockchainNodeContext - { - BlockchainNodeContext = - await _blockchainNodeContextService.StartAsync(blockchainNodeContextStartDto), - AElfNetworkServer = _networkServer - }; + var blockchainNodeContextStartDto = new BlockchainNodeContextStartDto + { + ChainId = dto.ChainId, + ZeroSmartContractType = dto.ZeroSmartContract, + Transactions = transactions.ToArray() + }; - await _networkServer.StartAsync(); + var context = new OsBlockchainNodeContext + { + BlockchainNodeContext = + await _blockchainNodeContextService.StartAsync(blockchainNodeContextStartDto), + AElfNetworkServer = _networkServer + }; - foreach (var nodePlugin in _nodePlugins) - { - await nodePlugin.StartAsync(dto.ChainId); - } + await _networkServer.StartAsync(); - return context; - } + foreach (var nodePlugin in _nodePlugins) await nodePlugin.StartAsync(dto.ChainId); - private Transaction GetTransactionForDeployment(Type contractType, Hash systemContractName, - int category, - List contractInitializationMethodCallList = null) - { - var dllPath = Directory.Exists(_contractOptions.GenesisContractDir) - ? Path.Combine(_contractOptions.GenesisContractDir, $"{contractType.Assembly.GetName().Name}.dll") - : contractType.Assembly.Location; - var code = File.ReadAllBytes(dllPath); + return context; + } - return GetTransactionForDeployment(code, systemContractName, category, contractInitializationMethodCallList); - } + public async Task StopAsync(OsBlockchainNodeContext blockchainNodeContext) + { + await _networkServer.StopAsync(false); - private Transaction GetTransactionForDeployment(byte[] code, Hash systemContractName, - int category, - List contractInitializationMethodCallList = null) - { - var transactionMethodCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - if (contractInitializationMethodCallList != null) - transactionMethodCallList.Value.Add(contractInitializationMethodCallList.Select(call => - new SystemContractDeploymentInput.Types.SystemTransactionMethodCall - { - MethodName = call.MethodName, - Params = call.Params ?? ByteString.Empty - })); - var zeroAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - - return new Transaction() - { - From = zeroAddress, - To = zeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), - Params = new SystemContractDeploymentInput() - { - Name = systemContractName, - Category = category, - Code = ByteString.CopyFrom(code), - TransactionMethodCallList = transactionMethodCallList - }.ToByteString() - }; - } - - private Transaction GetTransactionForGenesisOwnerInitialization(OsBlockchainNodeContextStartDto dto) + await _blockchainNodeContextService.StopAsync(blockchainNodeContext.BlockchainNodeContext); + + foreach (var nodePlugin in _nodePlugins) { - var zeroAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - return new Transaction - { - From = zeroAddress, - To = zeroAddress, - MethodName = nameof(BasicContractZeroContainer.BasicContractZeroStub.Initialize), - Params = new InitializeInput - {ContractDeploymentAuthorityRequired = dto.ContractDeploymentAuthorityRequired}.ToByteString() - }; + var _ = nodePlugin.ShutdownAsync(); } + } - public async Task StopAsync(OsBlockchainNodeContext blockchainNodeContext) - { - await _networkServer.StopAsync(false); + private Transaction GetTransactionForDeployment(Type contractType, Hash systemContractName, + int category, + List contractInitializationMethodCallList = null) + { + var dllPath = Directory.Exists(_contractOptions.GenesisContractDir) + ? Path.Combine(_contractOptions.GenesisContractDir, $"{contractType.Assembly.GetName().Name}.dll") + : contractType.Assembly.Location; + var code = File.ReadAllBytes(dllPath); + + return GetTransactionForDeployment(code, systemContractName, category, contractInitializationMethodCallList); + } - await _blockchainNodeContextService.StopAsync(blockchainNodeContext.BlockchainNodeContext); + private Transaction GetTransactionForDeployment(byte[] code, Hash systemContractName, + int category, + List contractInitializationMethodCallList = null) + { + var transactionMethodCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + if (contractInitializationMethodCallList != null) + transactionMethodCallList.Value.Add(contractInitializationMethodCallList.Select(call => + new SystemContractDeploymentInput.Types.SystemTransactionMethodCall + { + MethodName = call.MethodName, + Params = call.Params ?? ByteString.Empty + })); + var zeroAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - foreach (var nodePlugin in _nodePlugins) + return new Transaction + { + From = zeroAddress, + To = zeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), + Params = new SystemContractDeploymentInput { - var _ = nodePlugin.ShutdownAsync(); - } - } + Name = systemContractName, + Category = category, + Code = ByteString.CopyFrom(code), + TransactionMethodCallList = transactionMethodCallList + }.ToByteString() + }; + } + + private Transaction GetTransactionForGenesisOwnerInitialization(OsBlockchainNodeContextStartDto dto) + { + var zeroAddress = _smartContractAddressService.GetZeroSmartContractAddress(); + return new Transaction + { + From = zeroAddress, + To = zeroAddress, + MethodName = nameof(BasicContractZeroContainer.BasicContractZeroStub.Initialize), + Params = new InitializeInput + { ContractDeploymentAuthorityRequired = dto.ContractDeploymentAuthorityRequired }.ToByteString() + }; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextStartDto.cs b/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextStartDto.cs index 715dc0d490..87befaf27d 100644 --- a/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextStartDto.cs +++ b/src/AElf.OS.Core/Node/Application/OsBlockchainNodeContextStartDto.cs @@ -3,21 +3,19 @@ using AElf.Kernel; using AElf.Types; -namespace AElf.OS.Node.Application +namespace AElf.OS.Node.Application; + +public class OsBlockchainNodeContextStartDto { - public class OsBlockchainNodeContextStartDto - { - public int ChainId { get; set; } + public int ChainId { get; set; } + + public List InitializationSmartContracts { get; set; } = new(); - public List InitializationSmartContracts { get; set; } = - new List(); + public Transaction[] InitializationTransactions { get; set; } - public Transaction[] InitializationTransactions { get; set; } + public Type ZeroSmartContract { get; set; } - public Type ZeroSmartContract { get; set; } + public int SmartContractRunnerCategory { get; set; } = KernelConstants.DefaultRunnerCategory; - public int SmartContractRunnerCategory { get; set; } = KernelConstants.DefaultRunnerCategory; - - public bool ContractDeploymentAuthorityRequired { get; set; } - } + public bool ContractDeploymentAuthorityRequired { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Domain/OsBlockchainNodeContext.cs b/src/AElf.OS.Core/Node/Domain/OsBlockchainNodeContext.cs index 9b54ada304..06abb100eb 100644 --- a/src/AElf.OS.Core/Node/Domain/OsBlockchainNodeContext.cs +++ b/src/AElf.OS.Core/Node/Domain/OsBlockchainNodeContext.cs @@ -1,14 +1,11 @@ -using System.Collections.Generic; using AElf.Kernel.Node.Domain; -using AElf.Kernel.Node.Infrastructure; using AElf.OS.Network.Infrastructure; -namespace AElf.OS.Node.Domain +namespace AElf.OS.Node.Domain; + +public class OsBlockchainNodeContext { - public class OsBlockchainNodeContext - { - public BlockchainNodeContext BlockchainNodeContext { get; set; } - - public IAElfNetworkServer AElfNetworkServer { get; set; } - } + public BlockchainNodeContext BlockchainNodeContext { get; set; } + + public IAElfNetworkServer AElfNetworkServer { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Infrastructure/INodeEnvironmentProvider.cs b/src/AElf.OS.Core/Node/Infrastructure/INodeEnvironmentProvider.cs index 0f1dd2f7e1..1c55248ac5 100644 --- a/src/AElf.OS.Core/Node/Infrastructure/INodeEnvironmentProvider.cs +++ b/src/AElf.OS.Core/Node/Infrastructure/INodeEnvironmentProvider.cs @@ -1,7 +1,6 @@ -namespace AElf.OS.Node.Infrastructure +namespace AElf.OS.Node.Infrastructure; + +public interface INodeEnvironmentProvider { - public interface INodeEnvironmentProvider - { - string GetAppDataPath(); - } + string GetAppDataPath(); } \ No newline at end of file diff --git a/src/AElf.OS.Core/Node/Infrastructure/NodeEnvironmentProvider.cs b/src/AElf.OS.Core/Node/Infrastructure/NodeEnvironmentProvider.cs index 1babb8c6e7..9dbd332238 100644 --- a/src/AElf.OS.Core/Node/Infrastructure/NodeEnvironmentProvider.cs +++ b/src/AElf.OS.Core/Node/Infrastructure/NodeEnvironmentProvider.cs @@ -2,30 +2,23 @@ using System.IO; using Volo.Abp.DependencyInjection; -namespace AElf.OS.Node.Infrastructure -{ - public class NodeEnvironmentProvider : INodeEnvironmentProvider, ISingletonDependency - { - private const string ApplicationFolderName = "aelf"; - private string _appDataPath; +namespace AElf.OS.Node.Infrastructure; - public NodeEnvironmentProvider() - { - } +public class NodeEnvironmentProvider : INodeEnvironmentProvider, ISingletonDependency +{ + private const string ApplicationFolderName = "aelf"; + private string _appDataPath; - public string GetAppDataPath() + public string GetAppDataPath() + { + if (string.IsNullOrWhiteSpace(_appDataPath)) { - if (string.IsNullOrWhiteSpace(_appDataPath)) - { - _appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ApplicationFolderName); + _appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + ApplicationFolderName); - if (!Directory.Exists(_appDataPath)) - { - Directory.CreateDirectory(_appDataPath); - } - } - - return _appDataPath; + if (!Directory.Exists(_appDataPath)) Directory.CreateDirectory(_appDataPath); } + + return _appDataPath; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/AElf.OS.Network.Grpc.csproj b/src/AElf.OS.Network.Grpc/AElf.OS.Network.Grpc.csproj index b1c9f56229..ae33d21245 100644 --- a/src/AElf.OS.Network.Grpc/AElf.OS.Network.Grpc.csproj +++ b/src/AElf.OS.Network.Grpc/AElf.OS.Network.Grpc.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,30 +9,30 @@ - - - - + + + + - + - - Protobuf/peer_service.proto - + + Protobuf/peer_service.proto + - - + + - + diff --git a/src/AElf.OS.Network.Grpc/BoundedExpirationCache.cs b/src/AElf.OS.Network.Grpc/BoundedExpirationCache.cs index f6c3aeb9dc..1eeb1abe58 100644 --- a/src/AElf.OS.Network.Grpc/BoundedExpirationCache.cs +++ b/src/AElf.OS.Network.Grpc/BoundedExpirationCache.cs @@ -4,64 +4,61 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class BoundedExpirationCache { - public class BoundedExpirationCache + private readonly ConcurrentQueue _expiryHashQueue; + private readonly ConcurrentDictionary _hashLookup; + private readonly int _maximumCapacity; + private readonly int _timeout; + + public BoundedExpirationCache(int maximumCapacity, int timeout) { - private readonly int _timeout; - private readonly int _maximumCapacity; + _timeout = timeout; + _maximumCapacity = maximumCapacity; - private readonly ConcurrentQueue _expiryHashQueue; - private readonly ConcurrentDictionary _hashLookup; + _expiryHashQueue = new ConcurrentQueue(); + _hashLookup = new ConcurrentDictionary(); + } - public BoundedExpirationCache(int maximumCapacity, int timeout) - { - _timeout = timeout; - _maximumCapacity = maximumCapacity; - - _expiryHashQueue = new ConcurrentQueue(); - _hashLookup = new ConcurrentDictionary(); - } + public bool HasHash(Hash hash, bool clean = true) + { + if (clean) + CleanExpired(); - public bool HasHash(Hash hash, bool clean = true) - { - if (clean) - CleanExpired(); + return _hashLookup.ContainsKey(hash); + } - return _hashLookup.ContainsKey(hash); - } + public bool TryAdd(Hash itemHash) + { + CleanExpired(); - public bool TryAdd(Hash itemHash) - { - CleanExpired(); + // we've reached the maximum buffered items. + if (_expiryHashQueue.Count >= _maximumCapacity) + return false; - // we've reached the maximum buffered items. - if (_expiryHashQueue.Count >= _maximumCapacity) - return false; + var now = TimestampHelper.GetUtcNow(); - var now = TimestampHelper.GetUtcNow(); + // check for existence. + if (!_hashLookup.TryAdd(itemHash, now)) + return false; - // check for existence. - if (!_hashLookup.TryAdd(itemHash, now)) - return false; - - _expiryHashQueue.Enqueue(new QueuedHash - { - ItemHash = itemHash, EnqueueTime = now - }); + _expiryHashQueue.Enqueue(new QueuedHash + { + ItemHash = itemHash, EnqueueTime = now + }); - return true; - } + return true; + } - private void CleanExpired() - { - // clean old items. - while (!_expiryHashQueue.IsEmpty && _expiryHashQueue.TryPeek(out var queuedHash) - && queuedHash.EnqueueTime.AddMilliseconds(_timeout) < TimestampHelper.GetUtcNow()) - { - if (_expiryHashQueue.TryDequeue(out var expiredItem)) - _hashLookup.TryRemove(expiredItem.ItemHash, out _); - } - } + private void CleanExpired() + { + // clean old items. + while (!_expiryHashQueue.IsEmpty && _expiryHashQueue.TryPeek(out var queuedHash) + && queuedHash.EnqueueTime.AddMilliseconds(_timeout) < + TimestampHelper.GetUtcNow()) + if (_expiryHashQueue.TryDequeue(out var expiredItem)) + _hashLookup.TryRemove(expiredItem.ItemHash, out _); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Connection/ConnectionService.cs b/src/AElf.OS.Network.Grpc/Connection/ConnectionService.cs index 659c8c6a91..bbd01152ac 100644 --- a/src/AElf.OS.Network.Grpc/Connection/ConnectionService.cs +++ b/src/AElf.OS.Network.Grpc/Connection/ConnectionService.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -13,341 +12,339 @@ using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Local; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class ConnectionService : IConnectionService { - public class ConnectionService : IConnectionService + private readonly IHandshakeProvider _handshakeProvider; + private readonly IPeerDialer _peerDialer; + + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public ConnectionService(IPeerPool peerPool, IPeerDialer peerDialer, + IHandshakeProvider handshakeProvider, IReconnectionService reconnectionService) { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - - private readonly IPeerPool _peerPool; - private readonly IPeerDialer _peerDialer; - private readonly IHandshakeProvider _handshakeProvider; - private readonly IReconnectionService _reconnectionService; - public ILocalEventBus EventBus { get; set; } - public ILogger Logger { get; set; } - - public ConnectionService(IPeerPool peerPool, IPeerDialer peerDialer, - IHandshakeProvider handshakeProvider, IReconnectionService reconnectionService) - { - _peerPool = peerPool; - _peerDialer = peerDialer; - _handshakeProvider = handshakeProvider; - _reconnectionService = reconnectionService; + _peerPool = peerPool; + _peerDialer = peerDialer; + _handshakeProvider = handshakeProvider; + _reconnectionService = reconnectionService; - Logger = NullLogger.Instance; - EventBus = NullLocalEventBus.Instance; - } + Logger = NullLogger.Instance; + EventBus = NullLocalEventBus.Instance; + } - public async Task DisconnectAsync(IPeer peer, bool sendDisconnect = false) - { - // clean the pool - if (_peerPool.RemovePeer(peer.Info.Pubkey) == null) - Logger.LogWarning($"{peer} was not found in pool."); - - // cancel any pending reconnection - _reconnectionService.CancelReconnection(peer.RemoteEndpoint.ToString()); - - // dispose the peer - await peer.DisconnectAsync(sendDisconnect); - - Logger.LogInformation($"Removed peer {peer}"); - } + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + public ILocalEventBus EventBus { get; set; } + public ILogger Logger { get; set; } - public Task SchedulePeerReconnection(DnsEndPoint endpoint) - { - return Task.FromResult(_reconnectionService.SchedulePeerForReconnection(endpoint.ToString())); - } + public async Task DisconnectAsync(IPeer peer, bool sendDisconnect = false) + { + // clean the pool + if (_peerPool.RemovePeer(peer.Info.Pubkey) == null) + Logger.LogWarning($"{peer} was not found in pool."); - public async Task TrySchedulePeerReconnectionAsync(IPeer peer) - { - await DisconnectAsync(peer); - - if (peer.Info.IsInbound && (NetworkOptions.BootNodes == null || !NetworkOptions.BootNodes.Any() - || !NetworkOptions.BootNodes.Contains(peer.RemoteEndpoint.ToString()))) - { - Logger.LogDebug($"Completely dropping {peer.RemoteEndpoint} (inbound: {peer.Info.IsInbound})."); - return false; - } - - return _reconnectionService.SchedulePeerForReconnection(peer.RemoteEndpoint.ToString()); - } + // cancel any pending reconnection + _reconnectionService.CancelReconnection(peer.RemoteEndpoint.ToString()); + + // dispose the peer + await peer.DisconnectAsync(sendDisconnect); + + Logger.LogInformation($"Removed peer {peer}"); + } - public GrpcPeer GetPeerByPubkey(string pubkey) + public Task SchedulePeerReconnection(DnsEndPoint endpoint) + { + return Task.FromResult(_reconnectionService.SchedulePeerForReconnection(endpoint.ToString())); + } + + public async Task TrySchedulePeerReconnectionAsync(IPeer peer) + { + await DisconnectAsync(peer); + + if (peer.Info.IsInbound && (NetworkOptions.BootNodes == null || !NetworkOptions.BootNodes.Any() + || !NetworkOptions.BootNodes.Contains( + peer.RemoteEndpoint.ToString()))) { - return _peerPool.FindPeerByPublicKey(pubkey) as GrpcPeer; + Logger.LogDebug($"Completely dropping {peer.RemoteEndpoint} (inbound: {peer.Info.IsInbound})."); + return false; } - /// - /// Connects to a node with the given ip address and adds it to the node's peer pool. - /// - /// the ip address of the distant node - /// True if the connection was successful, false otherwise - public async Task ConnectAsync(DnsEndPoint endpoint) + return _reconnectionService.SchedulePeerForReconnection(peer.RemoteEndpoint.ToString()); + } + + public GrpcPeer GetPeerByPubkey(string pubkey) + { + return _peerPool.FindPeerByPublicKey(pubkey) as GrpcPeer; + } + + /// + /// Connects to a node with the given ip address and adds it to the node's peer pool. + /// + /// the ip address of the distant node + /// True if the connection was successful, false otherwise + public async Task ConnectAsync(DnsEndPoint endpoint) + { + Logger.LogDebug($"Attempting to reach {endpoint}."); + + var dialedPeer = await GetDialedPeerWithEndpointAsync(endpoint); + if (dialedPeer == null) return false; + + var inboundPeer = _peerPool.FindPeerByPublicKey(dialedPeer.Info.Pubkey) as GrpcPeer; + + /* A connection already exists, this can happen when both peers dial each other at the same time. To make + sure both sides close the same connection, they both decide based on the times of the handshakes. + Scenario steps, chronologically: + 1) P1 (hsk_time: t1) --> dials P2 --and-- P1 <-- P2 dials (hsk_time: t2) + 2) P2 receives P1s dial with t1 (in the hsk) and add to the pool + 3) P1 receives P2s dial with and adds to pool + 4) both dials finish and find that the pool already contains the dialed node. + To resolve this situation, both peers will choose the connection that was initiated the earliest, + so either P1s dial or P2s. */ + + var currentPeer = dialedPeer; + if (inboundPeer != null) { - Logger.LogDebug($"Attempting to reach {endpoint}."); + Logger.LogDebug("Duplicate peer connection detected: " + + $"{inboundPeer} ({inboundPeer.LastReceivedHandshakeTime}) " + + $"vs {dialedPeer} ({dialedPeer.LastSentHandshakeTime})."); - var dialedPeer = await GetDialedPeerWithEndpointAsync(endpoint); - if (dialedPeer == null) + if (inboundPeer.LastReceivedHandshakeTime > dialedPeer.LastSentHandshakeTime) { - return false; - } + // we started the dial first, replace the inbound connection with the dialed + if (!_peerPool.TryReplace(inboundPeer.Info.Pubkey, inboundPeer, dialedPeer)) + Logger.LogWarning("Replacing the inbound connection failed."); - var inboundPeer = _peerPool.FindPeerByPublicKey(dialedPeer.Info.Pubkey) as GrpcPeer; - - /* A connection already exists, this can happen when both peers dial each other at the same time. To make - sure both sides close the same connection, they both decide based on the times of the handshakes. - Scenario steps, chronologically: - 1) P1 (hsk_time: t1) --> dials P2 --and-- P1 <-- P2 dials (hsk_time: t2) - 2) P2 receives P1s dial with t1 (in the hsk) and add to the pool - 3) P1 receives P2s dial with and adds to pool - 4) both dials finish and find that the pool already contains the dialed node. - To resolve this situation, both peers will choose the connection that was initiated the earliest, - so either P1s dial or P2s. */ - - GrpcPeer currentPeer = dialedPeer; - if (inboundPeer != null) - { - Logger.LogDebug("Duplicate peer connection detected: " + - $"{inboundPeer} ({inboundPeer.LastReceivedHandshakeTime}) " + - $"vs {dialedPeer} ({dialedPeer.LastSentHandshakeTime})."); - - if (inboundPeer.LastReceivedHandshakeTime > dialedPeer.LastSentHandshakeTime) - { - // we started the dial first, replace the inbound connection with the dialed - if (!_peerPool.TryReplace(inboundPeer.Info.Pubkey, inboundPeer, dialedPeer)) - Logger.LogWarning("Replacing the inbound connection failed."); - - await inboundPeer.DisconnectAsync(false); - - Logger.LogDebug($"Replaced the inbound connection with the dialed peer {inboundPeer} ."); - } - else - { - // keep the inbound connection - await dialedPeer.DisconnectAsync(false); - currentPeer = inboundPeer; - - Logger.LogDebug($"Disconnected dialed peer {dialedPeer}."); - } + await inboundPeer.DisconnectAsync(false); + + Logger.LogDebug($"Replaced the inbound connection with the dialed peer {inboundPeer} ."); } else { - if (!_peerPool.TryAddPeer(dialedPeer)) - { - Logger.LogWarning($"Peer add to the failed {dialedPeer.Info.Pubkey}."); - await dialedPeer.DisconnectAsync(false); - return false; - } - - Logger.LogDebug($"Added to pool {dialedPeer.RemoteEndpoint} - {dialedPeer.Info.Pubkey}."); - } + // keep the inbound connection + await dialedPeer.DisconnectAsync(false); + currentPeer = inboundPeer; - try - { - await currentPeer.ConfirmHandshakeAsync(); + Logger.LogDebug($"Disconnected dialed peer {dialedPeer}."); } - catch (Exception e) + } + else + { + if (!_peerPool.TryAddPeer(dialedPeer)) { - Logger.LogDebug(e, $"Confirm handshake error. Peer: {currentPeer.Info.Pubkey}."); - _peerPool.RemovePeer(currentPeer.Info.Pubkey); - await currentPeer.DisconnectAsync(false); - throw; + Logger.LogWarning($"Peer add to the failed {dialedPeer.Info.Pubkey}."); + await dialedPeer.DisconnectAsync(false); + return false; } - currentPeer.IsConnected = true; - currentPeer.SyncState = SyncState.Syncing; - - Logger.LogInformation($"Connected to: {currentPeer.RemoteEndpoint} - {currentPeer.Info.Pubkey.Substring(0, 45)}" + - $" - in-token {currentPeer.InboundSessionId?.ToHex()}, out-token {currentPeer.OutboundSessionId?.ToHex()}" + - $" - LIB height {currentPeer.LastKnownLibHeight}" + - $" - best chain [{currentPeer.CurrentBlockHeight}, {currentPeer.CurrentBlockHash}]"); - - FireConnectionEvent(currentPeer); + Logger.LogDebug($"Added to pool {dialedPeer.RemoteEndpoint} - {dialedPeer.Info.Pubkey}."); + } - return true; + try + { + await currentPeer.ConfirmHandshakeAsync(); + } + catch (Exception e) + { + Logger.LogDebug(e, $"Confirm handshake error. Peer: {currentPeer.Info.Pubkey}."); + _peerPool.RemovePeer(currentPeer.Info.Pubkey); + await currentPeer.DisconnectAsync(false); + throw; } - private void FireConnectionEvent(GrpcPeer peer) + currentPeer.IsConnected = true; + currentPeer.SyncState = SyncState.Syncing; + + Logger.LogInformation( + $"Connected to: {currentPeer.RemoteEndpoint} - {currentPeer.Info.Pubkey.Substring(0, 45)}" + + $" - in-token {currentPeer.InboundSessionId?.ToHex()}, out-token {currentPeer.OutboundSessionId?.ToHex()}" + + $" - LIB height {currentPeer.LastKnownLibHeight}" + + $" - best chain [{currentPeer.CurrentBlockHeight}, {currentPeer.CurrentBlockHash}]"); + + FireConnectionEvent(currentPeer); + + return true; + } + + public async Task DoHandshakeAsync(DnsEndPoint endpoint, Handshake handshake) + { + // validate the handshake (signature, chain id...) + var handshakeValidationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + if (handshakeValidationResult != HandshakeValidationResult.Ok) { - var nodeInfo = new NodeInfo {Endpoint = peer.RemoteEndpoint.ToString(), Pubkey = ByteStringHelper.FromHexString(peer.Info.Pubkey)}; - var bestChainHash = peer.CurrentBlockHash; - var bestChainHeight = peer.CurrentBlockHeight; + var handshakeError = GetHandshakeError(handshakeValidationResult); + return new HandshakeReply { Error = handshakeError }; + } + + Logger.LogDebug($"peer {endpoint} sent a valid handshake {handshake}"); + + var pubkey = handshake.HandshakeData.Pubkey.ToHex(); - _ = EventBus.PublishAsync(new PeerConnectedEventData(nodeInfo, bestChainHash, bestChainHeight)); + // keep the healthy peer. + var currentPeer = _peerPool.FindPeerByPublicKey(pubkey); + if (currentPeer != null) + { + Logger.LogDebug($"Peer: {pubkey} already in peer pool, repeated connection {endpoint}"); + return new HandshakeReply { Error = HandshakeError.RepeatedConnection }; } - private async Task GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint) + try { - var peer = _peerPool.FindPeerByEndpoint(endpoint); - if (peer != null) - { - if (peer.IsInvalid) - { - _peerPool.RemovePeer(peer.Info.Pubkey); - await peer.DisconnectAsync(false); - } - else - { - Logger.LogDebug($"Peer with endpoint {endpoint} is already in the pool."); - return null; - } - } + // mark the (IP; pubkey) pair as currently handshaking + if (!_peerPool.AddHandshakingPeer(endpoint.Host, pubkey)) + return new HandshakeReply { Error = HandshakeError.ConnectionRefused }; - if (_peerPool.IsPeerBlackListed(endpoint.Host)) + // create the connection to the peer + var peerEndpoint = new AElfPeerEndpoint(endpoint.Host, handshake.HandshakeData.ListeningPort); + var grpcPeer = await _peerDialer.DialBackPeerAsync(peerEndpoint, handshake); + + if (grpcPeer == null) { - Logger.LogDebug($"Peer with endpoint {endpoint} is blacklisted."); - return null; + Logger.LogWarning($"Could not dial back {peerEndpoint}."); + return new HandshakeReply { Error = HandshakeError.InvalidConnection }; } - if (_peerPool.IsOverIpLimit(endpoint.Host)) + // add the new peer to the pool + if (!_peerPool.TryAddPeer(grpcPeer)) { - Logger.LogDebug($"{endpoint.Host} is over ip limit."); - return null; + Logger.LogDebug($"Stopping connection, peer already in the pool {grpcPeer.Info.Pubkey}."); + await grpcPeer.DisconnectAsync(false); + return new HandshakeReply { Error = HandshakeError.RepeatedConnection }; } - var dialedPeer = await _peerDialer.DialPeerAsync(endpoint); + Logger.LogDebug($"Added to pool {grpcPeer.RemoteEndpoint} - {grpcPeer.Info.Pubkey}."); - if (dialedPeer == null) - { - Logger.LogDebug($"Error dialing {endpoint}."); - return null; - } + // send back our handshake + var replyHandshake = await _handshakeProvider.GetHandshakeAsync(); + grpcPeer.InboundSessionId = replyHandshake.SessionId.ToByteArray(); + grpcPeer.UpdateLastSentHandshake(replyHandshake); - return dialedPeer; + Logger.LogDebug($"Sending back handshake to {peerEndpoint}."); + return new HandshakeReply { Handshake = replyHandshake, Error = HandshakeError.HandshakeOk }; } - - public async Task DoHandshakeAsync(DnsEndPoint endpoint, Handshake handshake) + finally { - // validate the handshake (signature, chain id...) - var handshakeValidationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - if (handshakeValidationResult != HandshakeValidationResult.Ok) - { - var handshakeError = GetHandshakeError(handshakeValidationResult); - return new HandshakeReply {Error = handshakeError}; - } - - Logger.LogDebug($"peer {endpoint} sent a valid handshake {handshake}"); - - var pubkey = handshake.HandshakeData.Pubkey.ToHex(); - - // keep the healthy peer. - var currentPeer = _peerPool.FindPeerByPublicKey(pubkey); - if (currentPeer != null) - { - Logger.LogDebug($"Peer: {pubkey} already in peer pool, repeated connection {endpoint}"); - return new HandshakeReply {Error = HandshakeError.RepeatedConnection}; - } - - try - { - // mark the (IP; pubkey) pair as currently handshaking - if (!_peerPool.AddHandshakingPeer(endpoint.Host, pubkey)) - return new HandshakeReply {Error = HandshakeError.ConnectionRefused}; - - // create the connection to the peer - var peerEndpoint = new AElfPeerEndpoint(endpoint.Host, handshake.HandshakeData.ListeningPort); - var grpcPeer = await _peerDialer.DialBackPeerAsync(peerEndpoint, handshake); - - if (grpcPeer == null) - { - Logger.LogWarning($"Could not dial back {peerEndpoint}."); - return new HandshakeReply {Error = HandshakeError.InvalidConnection}; - } - - // add the new peer to the pool - if (!_peerPool.TryAddPeer(grpcPeer)) - { - Logger.LogDebug($"Stopping connection, peer already in the pool {grpcPeer.Info.Pubkey}."); - await grpcPeer.DisconnectAsync(false); - return new HandshakeReply {Error = HandshakeError.RepeatedConnection}; - } - - Logger.LogDebug($"Added to pool {grpcPeer.RemoteEndpoint} - {grpcPeer.Info.Pubkey}."); - - // send back our handshake - var replyHandshake = await _handshakeProvider.GetHandshakeAsync(); - grpcPeer.InboundSessionId = replyHandshake.SessionId.ToByteArray(); - grpcPeer.UpdateLastSentHandshake(replyHandshake); - - Logger.LogDebug($"Sending back handshake to {peerEndpoint}."); - return new HandshakeReply { Handshake = replyHandshake, Error = HandshakeError.HandshakeOk }; - } - finally - { - // remove the handshaking mark (IP; pubkey) - _peerPool.RemoveHandshakingPeer(endpoint.Host, pubkey); - } + // remove the handshaking mark (IP; pubkey) + _peerPool.RemoveHandshakingPeer(endpoint.Host, pubkey); } + } - private HandshakeError GetHandshakeError(HandshakeValidationResult handshakeValidationResult) + public void ConfirmHandshake(string peerPubkey) + { + var peer = _peerPool.FindPeerByPublicKey(peerPubkey) as GrpcPeer; + if (peer == null) { - HandshakeError handshakeError; - - switch (handshakeValidationResult) - { - case HandshakeValidationResult.InvalidChainId: - handshakeError = HandshakeError.ChainMismatch; - break; - case HandshakeValidationResult.InvalidVersion: - handshakeError = HandshakeError.ProtocolMismatch; - break; - case HandshakeValidationResult.HandshakeTimeout: - handshakeError = HandshakeError.SignatureTimeout; - break; - case HandshakeValidationResult.InvalidSignature: - handshakeError = HandshakeError.WrongSignature; - break; - case HandshakeValidationResult.Unauthorized: - case HandshakeValidationResult.SelfConnection: - handshakeError = HandshakeError.ConnectionRefused; - break; - default: - throw new ArgumentException($"Unable to process handshake validation result: {handshakeValidationResult}"); - } - - return handshakeError; + Logger.LogWarning($"Cannot find Peer {peerPubkey} in the pool."); + return; } - public void ConfirmHandshake(string peerPubkey) - { - var peer = _peerPool.FindPeerByPublicKey(peerPubkey) as GrpcPeer; - if (peer == null) - { - Logger.LogWarning($"Cannot find Peer {peerPubkey} in the pool."); - return; - } - - Logger.LogInformation($"Connected to: {peer.RemoteEndpoint} - {peer.Info.Pubkey.Substring(0, 45)}" + + Logger.LogInformation($"Connected to: {peer.RemoteEndpoint} - {peer.Info.Pubkey.Substring(0, 45)}" + $" - in-token {peer.InboundSessionId?.ToHex()}, out-token {peer.OutboundSessionId?.ToHex()}" + $" - LIB height {peer.LastKnownLibHeight}" + $" - best chain [{peer.CurrentBlockHeight}, {peer.CurrentBlockHash}]"); - peer.IsConnected = true; - peer.SyncState = SyncState.Syncing; - - FireConnectionEvent(peer); - } + peer.IsConnected = true; + peer.SyncState = SyncState.Syncing; + + FireConnectionEvent(peer); + } + + public async Task DisconnectPeersAsync(bool gracefulDisconnect) + { + var peers = _peerPool.GetPeers(true); + foreach (var peer in peers) await peer.DisconnectAsync(gracefulDisconnect); + } - public async Task DisconnectPeersAsync(bool gracefulDisconnect) + public async Task RemovePeerAsync(string pubkey) + { + var peer = _peerPool.RemovePeer(pubkey); + if (peer != null) + await peer.DisconnectAsync(false); + } + + public async Task CheckEndpointAvailableAsync(DnsEndPoint endpoint) + { + return await _peerDialer.CheckEndpointAvailableAsync(endpoint); + } + + private void FireConnectionEvent(GrpcPeer peer) + { + var nodeInfo = new NodeInfo + { Endpoint = peer.RemoteEndpoint.ToString(), Pubkey = ByteStringHelper.FromHexString(peer.Info.Pubkey) }; + var bestChainHash = peer.CurrentBlockHash; + var bestChainHeight = peer.CurrentBlockHeight; + + _ = EventBus.PublishAsync(new PeerConnectedEventData(nodeInfo, bestChainHash, bestChainHeight)); + } + + private async Task GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint) + { + var peer = _peerPool.FindPeerByEndpoint(endpoint); + if (peer != null) { - var peers = _peerPool.GetPeers(true); - foreach (var peer in peers) + if (peer.IsInvalid) { - await peer.DisconnectAsync(gracefulDisconnect); + _peerPool.RemovePeer(peer.Info.Pubkey); + await peer.DisconnectAsync(false); + } + else + { + Logger.LogDebug($"Peer with endpoint {endpoint} is already in the pool."); + return null; } } - public async Task RemovePeerAsync(string pubkey) + if (_peerPool.IsPeerBlackListed(endpoint.Host)) { - var peer = _peerPool.RemovePeer(pubkey); - if (peer != null) - await peer.DisconnectAsync(false); + Logger.LogDebug($"Peer with endpoint {endpoint} is blacklisted."); + return null; + } + + if (_peerPool.IsOverIpLimit(endpoint.Host)) + { + Logger.LogDebug($"{endpoint.Host} is over ip limit."); + return null; + } + + var dialedPeer = await _peerDialer.DialPeerAsync(endpoint); + + if (dialedPeer == null) + { + Logger.LogDebug($"Error dialing {endpoint}."); + return null; } - public async Task CheckEndpointAvailableAsync(DnsEndPoint endpoint) + return dialedPeer; + } + + private HandshakeError GetHandshakeError(HandshakeValidationResult handshakeValidationResult) + { + HandshakeError handshakeError; + + switch (handshakeValidationResult) { - return await _peerDialer.CheckEndpointAvailableAsync(endpoint); + case HandshakeValidationResult.InvalidChainId: + handshakeError = HandshakeError.ChainMismatch; + break; + case HandshakeValidationResult.InvalidVersion: + handshakeError = HandshakeError.ProtocolMismatch; + break; + case HandshakeValidationResult.HandshakeTimeout: + handshakeError = HandshakeError.SignatureTimeout; + break; + case HandshakeValidationResult.InvalidSignature: + handshakeError = HandshakeError.WrongSignature; + break; + case HandshakeValidationResult.Unauthorized: + case HandshakeValidationResult.SelfConnection: + handshakeError = HandshakeError.ConnectionRefused; + break; + default: + throw new ArgumentException( + $"Unable to process handshake validation result: {handshakeValidationResult}"); } + + return handshakeError; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Connection/IConnectionService.cs b/src/AElf.OS.Network.Grpc/Connection/IConnectionService.cs index 271e61fd7c..0623af748a 100644 --- a/src/AElf.OS.Network.Grpc/Connection/IConnectionService.cs +++ b/src/AElf.OS.Network.Grpc/Connection/IConnectionService.cs @@ -1,21 +1,19 @@ -using System; using System.Net; using System.Threading.Tasks; using AElf.OS.Network.Infrastructure; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public interface IConnectionService { - public interface IConnectionService - { - GrpcPeer GetPeerByPubkey(string pubkey); - Task DisconnectAsync(IPeer peer, bool sendDisconnect = false); - Task SchedulePeerReconnection(DnsEndPoint endpoint); - Task TrySchedulePeerReconnectionAsync(IPeer peer); - Task ConnectAsync(DnsEndPoint endpoint); - Task DoHandshakeAsync(DnsEndPoint endpoint, Handshake handshake); - void ConfirmHandshake(string peerPubkey); - Task DisconnectPeersAsync(bool gracefulDisconnect); - Task CheckEndpointAvailableAsync(DnsEndPoint endpoint); - Task RemovePeerAsync(string pubkey); - } + GrpcPeer GetPeerByPubkey(string pubkey); + Task DisconnectAsync(IPeer peer, bool sendDisconnect = false); + Task SchedulePeerReconnection(DnsEndPoint endpoint); + Task TrySchedulePeerReconnectionAsync(IPeer peer); + Task ConnectAsync(DnsEndPoint endpoint); + Task DoHandshakeAsync(DnsEndPoint endpoint, Handshake handshake); + void ConfirmHandshake(string peerPubkey); + Task DisconnectPeersAsync(bool gracefulDisconnect); + Task CheckEndpointAvailableAsync(DnsEndPoint endpoint); + Task RemovePeerAsync(string pubkey); } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Connection/IPeerDialer.cs b/src/AElf.OS.Network.Grpc/Connection/IPeerDialer.cs index 6c66dbc2ef..7d3d70b755 100644 --- a/src/AElf.OS.Network.Grpc/Connection/IPeerDialer.cs +++ b/src/AElf.OS.Network.Grpc/Connection/IPeerDialer.cs @@ -1,12 +1,11 @@ using System.Net; using System.Threading.Tasks; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public interface IPeerDialer { - public interface IPeerDialer - { - Task DialPeerAsync(DnsEndPoint remoteEndpoint); - Task DialBackPeerAsync(DnsEndPoint remoteEndpoint, Handshake handshake); - Task CheckEndpointAvailableAsync(DnsEndPoint remoteEndpoint); - } + Task DialPeerAsync(DnsEndPoint remoteEndpoint); + Task DialBackPeerAsync(DnsEndPoint remoteEndpoint, Handshake handshake); + Task CheckEndpointAvailableAsync(DnsEndPoint remoteEndpoint); } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Connection/PeerDialer.cs b/src/AElf.OS.Network.Grpc/Connection/PeerDialer.cs index 54bc939a1c..1bc1f53031 100644 --- a/src/AElf.OS.Network.Grpc/Connection/PeerDialer.cs +++ b/src/AElf.OS.Network.Grpc/Connection/PeerDialer.cs @@ -19,279 +19,278 @@ using Org.BouncyCastle.X509; using Volo.Abp.Threading; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +/// +/// Provides functionality to setup a connection to a distant node by exchanging some +/// low level information. +/// +public class PeerDialer : IPeerDialer { - /// - /// Provides functionality to setup a connection to a distant node by exchanging some - /// low level information. - /// - public class PeerDialer : IPeerDialer + private readonly IAccountService _accountService; + private readonly IHandshakeProvider _handshakeProvider; + + private KeyCertificatePair _clientKeyCertificatePair; + + public PeerDialer(IAccountService accountService, + IHandshakeProvider handshakeProvider) { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + _accountService = accountService; + _handshakeProvider = handshakeProvider; - private readonly IAccountService _accountService; - private readonly IHandshakeProvider _handshakeProvider; + Logger = NullLogger.Instance; - public ILogger Logger { get; set; } + CreateClientKeyCertificatePair(); + } - private KeyCertificatePair _clientKeyCertificatePair; + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - public PeerDialer(IAccountService accountService, - IHandshakeProvider handshakeProvider) - { - _accountService = accountService; - _handshakeProvider = handshakeProvider; + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; + /// + /// Given an IP address, will create a handshake to the distant node for + /// further communications. + /// + /// The created peer + public async Task DialPeerAsync(DnsEndPoint remoteEndpoint) + { + var client = await CreateClientAsync(remoteEndpoint); - CreateClientKeyCertificatePair(); - } + if (client == null) + return null; + + var handshake = await _handshakeProvider.GetHandshakeAsync(); + var handshakeReply = await CallDoHandshakeAsync(client, remoteEndpoint, handshake); - private void CreateClientKeyCertificatePair() + // verify handshake + if (handshakeReply.Error != HandshakeError.HandshakeOk) { - _clientKeyCertificatePair = TlsHelper.GenerateKeyCertificatePair(); + Logger.LogWarning($"Handshake error: {remoteEndpoint} {handshakeReply.Error}."); + await client.Channel.ShutdownAsync(); + return null; } - /// - /// Given an IP address, will create a handshake to the distant node for - /// further communications. - /// - /// The created peer - public async Task DialPeerAsync(DnsEndPoint remoteEndpoint) + if (await _handshakeProvider.ValidateHandshakeAsync(handshakeReply.Handshake) != + HandshakeValidationResult.Ok) { - var client = await CreateClientAsync(remoteEndpoint); + Logger.LogWarning($"Connect error: {remoteEndpoint} {handshakeReply}."); + await client.Channel.ShutdownAsync(); + return null; + } - if (client == null) - return null; + var peer = new GrpcPeer(client, remoteEndpoint, new PeerConnectionInfo + { + Pubkey = handshakeReply.Handshake.HandshakeData.Pubkey.ToHex(), + ConnectionTime = TimestampHelper.GetUtcNow(), + ProtocolVersion = handshakeReply.Handshake.HandshakeData.Version, + SessionId = handshakeReply.Handshake.SessionId.ToByteArray(), + IsInbound = false + }); - var handshake = await _handshakeProvider.GetHandshakeAsync(); - var handshakeReply = await CallDoHandshakeAsync(client, remoteEndpoint, handshake); + peer.UpdateLastReceivedHandshake(handshakeReply.Handshake); - // verify handshake - if (handshakeReply.Error != HandshakeError.HandshakeOk) - { - Logger.LogWarning($"Handshake error: {remoteEndpoint} {handshakeReply.Error}."); - await client.Channel.ShutdownAsync(); - return null; - } + peer.InboundSessionId = handshake.SessionId.ToByteArray(); + peer.UpdateLastSentHandshake(handshake); - if (await _handshakeProvider.ValidateHandshakeAsync(handshakeReply.Handshake) != - HandshakeValidationResult.Ok) - { - Logger.LogWarning($"Connect error: {remoteEndpoint} {handshakeReply}."); - await client.Channel.ShutdownAsync(); - return null; - } - - var peer = new GrpcPeer(client, remoteEndpoint, new PeerConnectionInfo - { - Pubkey = handshakeReply.Handshake.HandshakeData.Pubkey.ToHex(), - ConnectionTime = TimestampHelper.GetUtcNow(), - ProtocolVersion = handshakeReply.Handshake.HandshakeData.Version, - SessionId = handshakeReply.Handshake.SessionId.ToByteArray(), - IsInbound = false - }); + return peer; + } - peer.UpdateLastReceivedHandshake(handshakeReply.Handshake); + public async Task CheckEndpointAvailableAsync(DnsEndPoint remoteEndpoint) + { + var client = await CreateClientAsync(remoteEndpoint); - peer.InboundSessionId = handshake.SessionId.ToByteArray(); - peer.UpdateLastSentHandshake(handshake); + if (client == null) + return false; - return peer; + try + { + await PingNodeAsync(client, remoteEndpoint); + await client.Channel.ShutdownAsync(); + return true; } - - /// - /// Calls the server side DoHandshake RPC method, in order to establish a 2-way connection. - /// - /// The reply from the server. - private async Task CallDoHandshakeAsync(GrpcClient client, DnsEndPoint remoteEndPoint, - Handshake handshake) + catch (Exception e) { - HandshakeReply handshakeReply; - - try - { - var metadata = new Metadata - { - {GrpcConstants.RetryCountMetadataKey, "0"}, - {GrpcConstants.TimeoutMetadataKey, (NetworkOptions.PeerDialTimeout * 2).ToString()} - }; + Logger.LogWarning(e, $"Could not ping peer {remoteEndpoint}."); + return false; + } + } - handshakeReply = - await client.Client.DoHandshakeAsync(new HandshakeRequest {Handshake = handshake}, metadata); + public async Task DialBackPeerAsync(DnsEndPoint remoteEndpoint, Handshake handshake) + { + var client = await CreateClientAsync(remoteEndpoint); - Logger.LogDebug($"Handshake to {remoteEndPoint} successful."); - } - catch (Exception) - { - await client.Channel.ShutdownAsync(); - throw; - } + if (client == null) + return null; - return handshakeReply; - } + await PingNodeAsync(client, remoteEndpoint); - public async Task CheckEndpointAvailableAsync(DnsEndPoint remoteEndpoint) + var peer = new GrpcPeer(client, remoteEndpoint, new PeerConnectionInfo { - var client = await CreateClientAsync(remoteEndpoint); + Pubkey = handshake.HandshakeData.Pubkey.ToHex(), + ConnectionTime = TimestampHelper.GetUtcNow(), + SessionId = handshake.SessionId.ToByteArray(), + ProtocolVersion = handshake.HandshakeData.Version, + IsInbound = true + }); - if (client == null) - return false; + peer.UpdateLastReceivedHandshake(handshake); - try - { - await PingNodeAsync(client, remoteEndpoint); - await client.Channel.ShutdownAsync(); - return true; - } - catch (Exception e) - { - Logger.LogWarning(e, $"Could not ping peer {remoteEndpoint}."); - return false; - } - } - - public async Task DialBackPeerAsync(DnsEndPoint remoteEndpoint, Handshake handshake) - { - var client = await CreateClientAsync(remoteEndpoint); + return peer; + } - if (client == null) - return null; + private void CreateClientKeyCertificatePair() + { + _clientKeyCertificatePair = TlsHelper.GenerateKeyCertificatePair(); + } - await PingNodeAsync(client, remoteEndpoint); + /// + /// Calls the server side DoHandshake RPC method, in order to establish a 2-way connection. + /// + /// The reply from the server. + private async Task CallDoHandshakeAsync(GrpcClient client, DnsEndPoint remoteEndPoint, + Handshake handshake) + { + HandshakeReply handshakeReply; - var peer = new GrpcPeer(client, remoteEndpoint, new PeerConnectionInfo + try + { + var metadata = new Metadata { - Pubkey = handshake.HandshakeData.Pubkey.ToHex(), - ConnectionTime = TimestampHelper.GetUtcNow(), - SessionId = handshake.SessionId.ToByteArray(), - ProtocolVersion = handshake.HandshakeData.Version, - IsInbound = true - }); + { GrpcConstants.RetryCountMetadataKey, "0" }, + { GrpcConstants.TimeoutMetadataKey, (NetworkOptions.PeerDialTimeout * 2).ToString() } + }; - peer.UpdateLastReceivedHandshake(handshake); + handshakeReply = + await client.Client.DoHandshakeAsync(new HandshakeRequest { Handshake = handshake }, metadata); - return peer; + Logger.LogDebug($"Handshake to {remoteEndPoint} successful."); } + catch (Exception) + { + await client.Channel.ShutdownAsync(); + throw; + } + + return handshakeReply; + } - /// - /// Checks that the distant node is reachable by pinging it. - /// - /// The reply from the server. - private async Task PingNodeAsync(GrpcClient client, DnsEndPoint peerEndpoint) + /// + /// Checks that the distant node is reachable by pinging it. + /// + /// The reply from the server. + private async Task PingNodeAsync(GrpcClient client, DnsEndPoint peerEndpoint) + { + try { - try + var metadata = new Metadata { - var metadata = new Metadata - { - {GrpcConstants.RetryCountMetadataKey, "0"}, - {GrpcConstants.TimeoutMetadataKey, NetworkOptions.PeerDialTimeout.ToString()} - }; + { GrpcConstants.RetryCountMetadataKey, "0" }, + { GrpcConstants.TimeoutMetadataKey, NetworkOptions.PeerDialTimeout.ToString() } + }; - await client.Client.PingAsync(new PingRequest(), metadata); + await client.Client.PingAsync(new PingRequest(), metadata); - Logger.LogDebug($"Pinged {peerEndpoint} successfully."); - } - catch (Exception ex) - { - Logger.LogWarning(ex, $"Could not ping {peerEndpoint}."); - await client.Channel.ShutdownAsync(); - throw; - } + Logger.LogDebug($"Pinged {peerEndpoint} successfully."); } - - /// - /// Creates a channel/client pair with the appropriate options and interceptors. - /// - /// A tuple of the channel and client - private async Task CreateClientAsync(DnsEndPoint remoteEndpoint) + catch (Exception ex) { - var certificate = await RetrieveServerCertificateAsync(remoteEndpoint); + Logger.LogWarning(ex, $"Could not ping {peerEndpoint}."); + await client.Channel.ShutdownAsync(); + throw; + } + } - if (certificate == null) - return null; + /// + /// Creates a channel/client pair with the appropriate options and interceptors. + /// + /// A tuple of the channel and client + private async Task CreateClientAsync(DnsEndPoint remoteEndpoint) + { + var certificate = await RetrieveServerCertificateAsync(remoteEndpoint); - Logger.LogDebug($"Upgrading connection to TLS: {certificate}."); - ChannelCredentials credentials = - new SslCredentials(TlsHelper.ObjectToPem(certificate), _clientKeyCertificatePair); + if (certificate == null) + return null; - var channel = new Channel(remoteEndpoint.ToString(), credentials, new List - { - new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), - new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength), - new ChannelOption(ChannelOptions.SslTargetNameOverride, GrpcConstants.DefaultTlsCommonName) - }); + Logger.LogDebug($"Upgrading connection to TLS: {certificate}."); + ChannelCredentials credentials = + new SslCredentials(TlsHelper.ObjectToPem(certificate), _clientKeyCertificatePair); - var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex(); + var channel = new Channel(remoteEndpoint.ToString(), credentials, new List + { + new(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), + new(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength), + new(ChannelOptions.SslTargetNameOverride, GrpcConstants.DefaultTlsCommonName) + }); - var interceptedChannel = channel.Intercept(metadata => - { - metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey); - return metadata; - }).Intercept(new RetryInterceptor()); + var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex(); - var client = new PeerService.PeerServiceClient(interceptedChannel); + var interceptedChannel = channel.Intercept(metadata => + { + metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey); + return metadata; + }).Intercept(new RetryInterceptor()); - return new GrpcClient(channel, client, certificate); - } + var client = new PeerService.PeerServiceClient(interceptedChannel); - private async Task RetrieveServerCertificateAsync(DnsEndPoint remoteEndpoint) - { - Logger.LogDebug($"Starting certificate retrieval for {remoteEndpoint}."); + return new GrpcClient(channel, client, certificate); + } + + private async Task RetrieveServerCertificateAsync(DnsEndPoint remoteEndpoint) + { + Logger.LogDebug($"Starting certificate retrieval for {remoteEndpoint}."); - TcpClient client = null; + TcpClient client = null; - try + try + { + client = new TcpClient(); + using (var cts = new CancellationTokenSource()) { - client = new TcpClient(); - using (var cts = new CancellationTokenSource()) + cts.CancelAfter(NetworkConstants.DefaultSslCertifFetchTimeout); + await client.ConnectAsync(remoteEndpoint.Host, remoteEndpoint.Port).WithCancellation(cts.Token); + + using (var sslStream = new SslStream(client.GetStream(), true, (a, b, c, d) => true)) { - cts.CancelAfter(NetworkConstants.DefaultSslCertifFetchTimeout); - await client.ConnectAsync(remoteEndpoint.Host, remoteEndpoint.Port).WithCancellation(cts.Token); + sslStream.ReadTimeout = NetworkConstants.DefaultSslCertifFetchTimeout; + sslStream.WriteTimeout = NetworkConstants.DefaultSslCertifFetchTimeout; + await sslStream.AuthenticateAsClientAsync(remoteEndpoint.Host).WithCancellation(cts.Token); - using (var sslStream = new SslStream(client.GetStream(), true, (a, b, c, d) => true)) + if (sslStream.RemoteCertificate == null) { - sslStream.ReadTimeout = NetworkConstants.DefaultSslCertifFetchTimeout; - sslStream.WriteTimeout = NetworkConstants.DefaultSslCertifFetchTimeout; - await sslStream.AuthenticateAsClientAsync(remoteEndpoint.Host).WithCancellation(cts.Token); - - if (sslStream.RemoteCertificate == null) - { - Logger.LogDebug($"Certificate from {remoteEndpoint} is null"); - return null; - } + Logger.LogDebug($"Certificate from {remoteEndpoint} is null"); + return null; + } - Logger.LogDebug($"Retrieved certificate for {remoteEndpoint}."); + Logger.LogDebug($"Retrieved certificate for {remoteEndpoint}."); - return FromX509Certificate(sslStream.RemoteCertificate); - } + return FromX509Certificate(sslStream.RemoteCertificate); } } - catch (OperationCanceledException) - { - Logger.LogDebug($"Certificate retrieval connection timeout for {remoteEndpoint}."); - return null; - } - catch (Exception ex) - { - // swallow exception because it's currently not a hard requirement to - // upgrade the connection. - Logger.LogWarning(ex, $"Could not retrieve certificate from {remoteEndpoint}."); - } - finally - { - client?.Close(); - } - + } + catch (OperationCanceledException) + { + Logger.LogDebug($"Certificate retrieval connection timeout for {remoteEndpoint}."); return null; } - - public static X509Certificate FromX509Certificate( - System.Security.Cryptography.X509Certificates.X509Certificate x509Cert) + catch (Exception ex) { - return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData()); + // swallow exception because it's currently not a hard requirement to + // upgrade the connection. + Logger.LogWarning(ex, $"Could not retrieve certificate from {remoteEndpoint}."); } + finally + { + client?.Close(); + } + + return null; + } + + public static X509Certificate FromX509Certificate( + System.Security.Cryptography.X509Certificates.X509Certificate x509Cert) + { + return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData()); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Extensions/CallContextExtensions.cs b/src/AElf.OS.Network.Grpc/Extensions/CallContextExtensions.cs index 6f95b0b10f..563985b974 100644 --- a/src/AElf.OS.Network.Grpc/Extensions/CallContextExtensions.cs +++ b/src/AElf.OS.Network.Grpc/Extensions/CallContextExtensions.cs @@ -1,27 +1,25 @@ using System.Linq; using Grpc.Core; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public static class CallContextExtensions { - public static class CallContextExtensions + public static string GetPublicKey(this ServerCallContext context) + { + return context.RequestHeaders + .FirstOrDefault(entry => entry.Key == GrpcConstants.PubkeyMetadataKey)?.Value; + } + + public static byte[] GetSessionId(this ServerCallContext context) + { + return context.RequestHeaders + .FirstOrDefault(entry => entry.Key == GrpcConstants.SessionIdMetadataKey)?.ValueBytes; + } + + public static string GetPeerInfo(this ServerCallContext context) { - public static string GetPublicKey(this ServerCallContext context) - { - - return context.RequestHeaders - .FirstOrDefault(entry => entry.Key == GrpcConstants.PubkeyMetadataKey)?.Value; - } - - public static byte[] GetSessionId(this ServerCallContext context) - { - return context.RequestHeaders - .FirstOrDefault(entry => entry.Key == GrpcConstants.SessionIdMetadataKey)?.ValueBytes; - } - - public static string GetPeerInfo(this ServerCallContext context) - { - return context.RequestHeaders - .FirstOrDefault(entry => entry.Key == GrpcConstants.PeerInfoMetadataKey)?.Value; - } + return context.RequestHeaders + .FirstOrDefault(entry => entry.Key == GrpcConstants.PeerInfoMetadataKey)?.Value; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Extensions/ClientInterceptorContextExtensions.cs b/src/AElf.OS.Network.Grpc/Extensions/ClientInterceptorContextExtensions.cs index 2760673ca9..2e54f16ef8 100644 --- a/src/AElf.OS.Network.Grpc/Extensions/ClientInterceptorContextExtensions.cs +++ b/src/AElf.OS.Network.Grpc/Extensions/ClientInterceptorContextExtensions.cs @@ -1,41 +1,40 @@ using System; using System.Linq; -using Grpc.Core; using Grpc.Core.Interceptors; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public static class ClientInterceptorContextExtensions { - public static class ClientInterceptorContextExtensions + /// + /// Returns the header with the given key. If the key is not found or there's no headers, returns null. If the + /// header is found and the parameter is true, the parameter will be removed from the + /// headers. + /// + public static string GetHeaderStringValue( + this ClientInterceptorContext context, string key, bool clearHeader = false) + where TRequest : class + where TResponse : class { - /// - /// Returns the header with the given key. If the key is not found or there's no headers, returns null. If the - /// header is found and the parameter is true, the parameter will be removed from the - /// headers. - /// - public static string GetHeaderStringValue( - this ClientInterceptorContext context, string key, bool clearHeader = false) - where TRequest : class - where TResponse : class - { - if (!AnyHeaders(context)) - return null; + if (!AnyHeaders(context)) + return null; - Metadata.Entry valueItem = context.Options.Headers.FirstOrDefault(m => string.Equals(m.Key, key, StringComparison.Ordinal)); + var valueItem = + context.Options.Headers.FirstOrDefault(m => string.Equals(m.Key, key, StringComparison.Ordinal)); - if (clearHeader && valueItem != null) - context.Options.Headers.Remove(valueItem); + if (clearHeader && valueItem != null) + context.Options.Headers.Remove(valueItem); - return valueItem?.Value; - } + return valueItem?.Value; + } - /// - /// Returns true if any headers are available, false otherwise. - /// - public static bool AnyHeaders(ClientInterceptorContext context) - where TRequest : class - where TResponse : class - { - return context.Options.Headers != null && context.Options.Headers.Any(); - } + /// + /// Returns true if any headers are available, false otherwise. + /// + public static bool AnyHeaders(ClientInterceptorContext context) + where TRequest : class + where TResponse : class + { + return context.Options.Headers != null && context.Options.Headers.Any(); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcClient.cs b/src/AElf.OS.Network.Grpc/GrpcClient.cs index c252ac1926..2d7d17a986 100644 --- a/src/AElf.OS.Network.Grpc/GrpcClient.cs +++ b/src/AElf.OS.Network.Grpc/GrpcClient.cs @@ -1,19 +1,18 @@ using Grpc.Core; using Org.BouncyCastle.X509; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcClient { - public class GrpcClient + public GrpcClient(Channel channel, PeerService.PeerServiceClient client, X509Certificate certificate = null) { - public X509Certificate Certificate { get; } - public Channel Channel { get; } - public PeerService.PeerServiceClient Client { get; } - - public GrpcClient(Channel channel, PeerService.PeerServiceClient client, X509Certificate certificate = null) - { - Channel = channel; - Client = client; - Certificate = certificate; - } + Channel = channel; + Client = client; + Certificate = certificate; } + + public X509Certificate Certificate { get; } + public Channel Channel { get; } + public PeerService.PeerServiceClient Client { get; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcConstants.cs b/src/AElf.OS.Network.Grpc/GrpcConstants.cs index f6781b05d4..f7f263d075 100644 --- a/src/AElf.OS.Network.Grpc/GrpcConstants.cs +++ b/src/AElf.OS.Network.Grpc/GrpcConstants.cs @@ -1,25 +1,24 @@ -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public static class GrpcConstants { - public static class GrpcConstants - { - public const string PubkeyMetadataKey = "public-key"; - public const string SessionIdMetadataKey = "session-id-bin"; - public const string PeerInfoMetadataKey = "peer-info"; - public const string TimeoutMetadataKey = "timeout"; - public const string RetryCountMetadataKey = "retry-count"; - public const string GrpcRequestCompressKey = "grpc-internal-encoding-request"; - - public const string GrpcGzipConst = "gzip"; - - public const int DefaultRequestTimeout = 200; - - public const int DefaultMaxReceiveMessageLength = 100 * 1024 * 1024; - public const int DefaultMaxSendMessageLength = 100 * 1024 * 1024; + public const string PubkeyMetadataKey = "public-key"; + public const string SessionIdMetadataKey = "session-id-bin"; + public const string PeerInfoMetadataKey = "peer-info"; + public const string TimeoutMetadataKey = "timeout"; + public const string RetryCountMetadataKey = "retry-count"; + public const string GrpcRequestCompressKey = "grpc-internal-encoding-request"; + + public const string GrpcGzipConst = "gzip"; + + public const int DefaultRequestTimeout = 200; + + public const int DefaultMaxReceiveMessageLength = 100 * 1024 * 1024; + public const int DefaultMaxSendMessageLength = 100 * 1024 * 1024; - public const int MaxSendBlockCountLimit = 50; + public const int MaxSendBlockCountLimit = 50; - public const string DefaultTlsCommonName = "aelf"; + public const string DefaultTlsCommonName = "aelf"; - public const int DefaultDiscoveryMaxNodesToResponse = 10; - } + public const int DefaultDiscoveryMaxNodesToResponse = 10; } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcNetworkModule.cs b/src/AElf.OS.Network.Grpc/GrpcNetworkModule.cs index e88826b19b..a9aa0f7527 100644 --- a/src/AElf.OS.Network.Grpc/GrpcNetworkModule.cs +++ b/src/AElf.OS.Network.Grpc/GrpcNetworkModule.cs @@ -3,24 +3,23 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcNetworkModule : AElfModule { - public class GrpcNetworkModule : AElfModule + /// + /// Registers the components implemented by the gRPC library. + /// + public override void ConfigureServices(ServiceConfigurationContext context) { - /// - /// Registers the components implemented by the gRPC library. - /// - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + + // Internal dependencies + context.Services.AddTransient(); + context.Services.AddSingleton(); - // Internal dependencies - context.Services.AddTransient(); - context.Services.AddSingleton(); - - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcNetworkServer.cs b/src/AElf.OS.Network.Grpc/GrpcNetworkServer.cs index 50cae6b67a..f3ece8513d 100644 --- a/src/AElf.OS.Network.Grpc/GrpcNetworkServer.cs +++ b/src/AElf.OS.Network.Grpc/GrpcNetworkServer.cs @@ -4,186 +4,184 @@ using System.Net; using System.Threading.Tasks; using AElf.OS.Network.Events; -using AElf.OS.Network.Helpers; using AElf.OS.Network.Grpc.Helpers; +using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; using Grpc.Core; using Grpc.Core.Interceptors; -using Grpc.Core.Logging; using GuerrillaNtp; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -using Org.BouncyCastle.Asn1.X509; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +/// +/// Implements and manages the lifecycle of the network layer. +/// +public class GrpcNetworkServer : IAElfNetworkServer, ISingletonDependency { - /// - /// Implements and manages the lifecycle of the network layer. - /// - public class GrpcNetworkServer : IAElfNetworkServer, ISingletonDependency + private readonly AuthInterceptor _authInterceptor; + private readonly IConnectionService _connectionService; + + private readonly PeerService.PeerServiceBase _serverService; + + private Server _server; + + public GrpcNetworkServer(PeerService.PeerServiceBase serverService, IConnectionService connectionService, + AuthInterceptor authInterceptor) { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + _serverService = serverService; + _connectionService = connectionService; + _authInterceptor = authInterceptor; - private readonly PeerService.PeerServiceBase _serverService; - private readonly IConnectionService _connectionService; - private readonly AuthInterceptor _authInterceptor; + Logger = NullLogger.Instance; + EventBus = NullLocalEventBus.Instance; + } - public ILocalEventBus EventBus { get; set; } - public ILogger Logger { get; set; } - - private Server _server; + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - public GrpcNetworkServer(PeerService.PeerServiceBase serverService, IConnectionService connectionService, AuthInterceptor authInterceptor) - { - _serverService = serverService; - _connectionService = connectionService; - _authInterceptor = authInterceptor; + public ILocalEventBus EventBus { get; set; } + public ILogger Logger { get; set; } - Logger = NullLogger.Instance; - EventBus = NullLocalEventBus.Instance; - } + public async Task StartAsync() + { + await StartListeningAsync(); + await DialBootNodesAsync(); - public async Task StartAsync() - { - await StartListeningAsync(); - await DialBootNodesAsync(); + await EventBus.PublishAsync(new NetworkInitializedEvent()); + } - await EventBus.PublishAsync(new NetworkInitializedEvent()); - } - - /// - /// Starts gRPC's server by binding the peer services, sets options and adds interceptors. - /// - internal Task StartListeningAsync() - { - ServerServiceDefinition serviceDefinition = PeerService.BindService(_serverService); + /// + /// Connects to a node with the given ip address and adds it to the node's peer pool. + /// + /// the ip address of the distant node + /// True if the connection was successful, false otherwise + public async Task ConnectAsync(DnsEndPoint endpoint) + { + return await _connectionService.ConnectAsync(endpoint); + } - if (_authInterceptor != null) - serviceDefinition = serviceDefinition.Intercept(_authInterceptor); + public async Task DisconnectAsync(IPeer peer, bool sendDisconnect = false) + { + await _connectionService.DisconnectAsync(peer, sendDisconnect); + } - var serverOptions = new List - { - new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), - new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength) - }; - - // setup service - _server = new Server(serverOptions); - _server.Services.Add(serviceDefinition); - - var serverCredentials = CreateCredentials(); - - // setup encrypted endpoint - _server.Ports.Add(new ServerPort(IPAddress.Any.ToString(), NetworkOptions.ListeningPort, serverCredentials)); - - return Task.Run(() => - { - _server.Start(); - - foreach (var port in _server.Ports) - Logger.LogDebug($"Server listening on {port.Host}:{port.BoundPort}."); - }); - } + public async Task TrySchedulePeerReconnectionAsync(IPeer peer) + { + return await _connectionService.TrySchedulePeerReconnectionAsync(peer); + } - private SslServerCredentials CreateCredentials() + public void CheckNtpDrift() + { + TimeSpan offset; + using (var ntp = new NtpClient(Dns.GetHostAddresses("pool.ntp.org")[0])) { - var keyCertificatePair = TlsHelper.GenerateKeyCertificatePair(); - return new SslServerCredentials(new List {keyCertificatePair}); + offset = ntp.GetCorrectionOffset(); } - /// - /// Connects to the boot nodes provided in the network options. - /// - private async Task DialBootNodesAsync() - { - if (NetworkOptions.BootNodes == null || !NetworkOptions.BootNodes.Any()) - { - Logger.LogWarning("Boot nodes list is empty."); - return; - } + if (offset.Duration().TotalMilliseconds > NetworkConstants.DefaultNtpDriftThreshold) + Logger.LogWarning($"NTP clock drift is more that {NetworkConstants.DefaultNtpDriftThreshold} ms : " + + $"{offset.Duration().TotalMilliseconds} ms"); + } - var taskList = NetworkOptions.BootNodes - .Select(async node => - { - bool dialed = false; - - if (!AElfPeerEndpointHelper.TryParse(node, out DnsEndPoint endpoint)) - { - Logger.LogWarning($"Could not parse endpoint {node}."); - return; - } - - try - { - dialed = await _connectionService.ConnectAsync(endpoint); - } - catch (Exception e) - { - Logger.LogWarning(e, $"Connect peer failed {node}."); - } - - if (!dialed) - await _connectionService.SchedulePeerReconnection(endpoint); - - }).ToList(); - - await Task.WhenAll(taskList.ToArray()); - } + public async Task CheckEndpointAvailableAsync(DnsEndPoint endpoint) + { + return await _connectionService.CheckEndpointAvailableAsync(endpoint); + } - /// - /// Connects to a node with the given ip address and adds it to the node's peer pool. - /// - /// the ip address of the distant node - /// True if the connection was successful, false otherwise - public async Task ConnectAsync(DnsEndPoint endpoint) + public async Task StopAsync(bool gracefulDisconnect = true) + { + try { - return await _connectionService.ConnectAsync(endpoint); + await _server.ShutdownAsync(); } - - public async Task DisconnectAsync(IPeer peer, bool sendDisconnect = false) + catch (InvalidOperationException) { - await _connectionService.DisconnectAsync(peer, sendDisconnect); + // if server already shutdown, we continue and clear the channels. } - public async Task TrySchedulePeerReconnectionAsync(IPeer peer) + await _connectionService.DisconnectPeersAsync(gracefulDisconnect); + } + + /// + /// Starts gRPC's server by binding the peer services, sets options and adds interceptors. + /// + internal Task StartListeningAsync() + { + ServerServiceDefinition serviceDefinition = PeerService.BindService(_serverService); + + if (_authInterceptor != null) + serviceDefinition = serviceDefinition.Intercept(_authInterceptor); + + var serverOptions = new List { - return await _connectionService.TrySchedulePeerReconnectionAsync(peer); - } + new(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), + new(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength) + }; + + // setup service + _server = new Server(serverOptions); + _server.Services.Add(serviceDefinition); + + var serverCredentials = CreateCredentials(); - public void CheckNtpDrift() + // setup encrypted endpoint + _server.Ports.Add(new ServerPort(IPAddress.Any.ToString(), NetworkOptions.ListeningPort, serverCredentials)); + + return Task.Run(() => { - TimeSpan offset; - using (var ntp = new NtpClient(Dns.GetHostAddresses("pool.ntp.org")[0])) - offset = ntp.GetCorrectionOffset(); - - if (offset.Duration().TotalMilliseconds > NetworkConstants.DefaultNtpDriftThreshold) - { - Logger.LogWarning($"NTP clock drift is more that {NetworkConstants.DefaultNtpDriftThreshold} ms : " + - $"{offset.Duration().TotalMilliseconds} ms"); - } - } + _server.Start(); - public async Task CheckEndpointAvailableAsync(DnsEndPoint endpoint) + foreach (var port in _server.Ports) + Logger.LogDebug($"Server listening on {port.Host}:{port.BoundPort}."); + }); + } + + private SslServerCredentials CreateCredentials() + { + var keyCertificatePair = TlsHelper.GenerateKeyCertificatePair(); + return new SslServerCredentials(new List { keyCertificatePair }); + } + + /// + /// Connects to the boot nodes provided in the network options. + /// + private async Task DialBootNodesAsync() + { + if (NetworkOptions.BootNodes == null || !NetworkOptions.BootNodes.Any()) { - return await _connectionService.CheckEndpointAvailableAsync(endpoint); + Logger.LogWarning("Boot nodes list is empty."); + return; } - public async Task StopAsync(bool gracefulDisconnect = true) - { - try + var taskList = NetworkOptions.BootNodes + .Select(async node => { - await _server.ShutdownAsync(); - } - catch (InvalidOperationException) - { - // if server already shutdown, we continue and clear the channels. - } + var dialed = false; - await _connectionService.DisconnectPeersAsync(gracefulDisconnect); - } + if (!AElfPeerEndpointHelper.TryParse(node, out var endpoint)) + { + Logger.LogWarning($"Could not parse endpoint {node}."); + return; + } + + try + { + dialed = await _connectionService.ConnectAsync(endpoint); + } + catch (Exception e) + { + Logger.LogWarning(e, $"Connect peer failed {node}."); + } + + if (!dialed) + await _connectionService.SchedulePeerReconnection(endpoint); + }).ToList(); + + await Task.WhenAll(taskList.ToArray()); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcPeer.cs b/src/AElf.OS.Network.Grpc/GrpcPeer.cs index 267aaacdd1..4289970128 100644 --- a/src/AElf.OS.Network.Grpc/GrpcPeer.cs +++ b/src/AElf.OS.Network.Grpc/GrpcPeer.cs @@ -17,618 +17,598 @@ using Google.Protobuf.WellKnownTypes; using Grpc.Core; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +/// +/// Represents a connection to a peer. +/// +public class GrpcPeer : IPeer { - /// - /// Represents a connection to a peer. - /// - public class GrpcPeer : IPeer - { - private const int MaxMetricsPerMethod = 100; - private const int BlockRequestTimeout = 700; - private const int CheckHealthTimeout = 1000; - private const int BlocksRequestTimeout = 5000; - private const int GetNodesTimeout = 500; - private const int UpdateHandshakeTimeout = 3000; - private const int StreamRecoveryWaitTime = 500; + private const int MaxMetricsPerMethod = 100; + private const int BlockRequestTimeout = 700; + private const int CheckHealthTimeout = 1000; + private const int BlocksRequestTimeout = 5000; + private const int GetNodesTimeout = 500; + private const int UpdateHandshakeTimeout = 3000; + private const int StreamRecoveryWaitTime = 500; - private const int BlockCacheMaxItems = 1024; - private const int TransactionCacheMaxItems = 10_000; + private const int BlockCacheMaxItems = 1024; + private const int TransactionCacheMaxItems = 10_000; - private const int QueuedTransactionTimeout = 10_000; - private const int QueuedBlockTimeout = 100_000; + private const int QueuedTransactionTimeout = 10_000; + private const int QueuedBlockTimeout = 100_000; - private enum MetricNames - { - GetBlocks, - GetBlock - }; + private readonly Channel _channel; + private readonly PeerService.PeerServiceClient _client; + private readonly BoundedExpirationCache _knownBlockCache; - private readonly Channel _channel; - private readonly PeerService.PeerServiceClient _client; + private readonly BoundedExpirationCache _knownTransactionCache; + private readonly ConcurrentDictionary> _recentRequestsRoundtripTimes; - /// - /// Property that describes that describes if the peer is ready for send/request operations. It's based - /// on the state of the underlying channel and the IsConnected. - /// - public bool IsReady - { - get { return (_channel.State == ChannelState.Idle || _channel.State == ChannelState.Ready) && IsConnected; } - } + private readonly ActionBlock _sendAnnouncementJobs; + private readonly ActionBlock _sendBlockJobs; + private readonly ActionBlock _sendTransactionJobs; + private AsyncClientStreamingCall _announcementStreamCall; + private AsyncClientStreamingCall _blockStreamCall; + private AsyncClientStreamingCall _libAnnouncementStreamCall; - public bool IsInvalid - { - get - { - return !IsConnected && - Info.ConnectionTime.AddMilliseconds(NetworkConstants.PeerConnectionTimeout) < - TimestampHelper.GetUtcNow(); - } - } + private AsyncClientStreamingCall _transactionStreamCall; - public string ConnectionStatus => _channel.State.ToString(); - - public Hash LastKnownLibHash { get; private set; } - public long LastKnownLibHeight { get; private set; } - public Timestamp LastReceivedHandshakeTime { get; private set; } - public Timestamp LastSentHandshakeTime { get; private set; } - - public bool IsConnected { get; set; } - public bool IsShutdown { get; set; } - public Hash CurrentBlockHash { get; private set; } - public long CurrentBlockHeight { get; private set; } - public SyncState SyncState { get; set; } - - /// - /// Session ID to use when authenticating messages from this peer, announced to the - /// remote peer at connection. - /// - public byte[] InboundSessionId { get; set; } - - /// - /// Session ID to use when sending messages to this peer, announced at connection - /// from the other peer. - /// - public byte[] OutboundSessionId => Info.SessionId; - - public DnsEndPoint RemoteEndpoint { get; } - public int BufferedTransactionsCount => _sendTransactionJobs.InputCount; - public int BufferedBlocksCount => _sendBlockJobs.InputCount; - public int BufferedAnnouncementsCount => _sendAnnouncementJobs.InputCount; - - public PeerConnectionInfo Info { get; } - - private readonly BoundedExpirationCache _knownTransactionCache; - private readonly BoundedExpirationCache _knownBlockCache; - - public IReadOnlyDictionary> RecentRequestsRoundtripTimes { get; } - private readonly ConcurrentDictionary> _recentRequestsRoundtripTimes; - - private AsyncClientStreamingCall _transactionStreamCall; - private AsyncClientStreamingCall _announcementStreamCall; - private AsyncClientStreamingCall _blockStreamCall; - private AsyncClientStreamingCall _libAnnouncementStreamCall; - - private readonly ActionBlock _sendAnnouncementJobs; - private readonly ActionBlock _sendBlockJobs; - private readonly ActionBlock _sendTransactionJobs; - - public GrpcPeer(GrpcClient client, DnsEndPoint remoteEndpoint, PeerConnectionInfo peerConnectionInfo) - { - _channel = client.Channel; - _client = client.Client; - - RemoteEndpoint = remoteEndpoint; - Info = peerConnectionInfo; - - _knownTransactionCache = new BoundedExpirationCache(TransactionCacheMaxItems, QueuedTransactionTimeout); - _knownBlockCache = new BoundedExpirationCache(BlockCacheMaxItems, QueuedBlockTimeout); - - _recentRequestsRoundtripTimes = new ConcurrentDictionary>(); - RecentRequestsRoundtripTimes = - new ReadOnlyDictionary>(_recentRequestsRoundtripTimes); - - _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue()); - _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue()); - - _sendAnnouncementJobs = new ActionBlock(SendStreamJobAsync, - new ExecutionDataflowBlockOptions - { - BoundedCapacity = NetworkConstants.DefaultMaxBufferedAnnouncementCount - }); - _sendBlockJobs = new ActionBlock(SendStreamJobAsync, - new ExecutionDataflowBlockOptions - { - BoundedCapacity = NetworkConstants.DefaultMaxBufferedBlockCount - }); - _sendTransactionJobs = new ActionBlock(SendStreamJobAsync, - new ExecutionDataflowBlockOptions - { - BoundedCapacity = NetworkConstants.DefaultMaxBufferedTransactionCount - }); - } + public GrpcPeer(GrpcClient client, DnsEndPoint remoteEndpoint, PeerConnectionInfo peerConnectionInfo) + { + _channel = client.Channel; + _client = client.Client; - public Dictionary> GetRequestMetrics() - { - Dictionary> metrics = new Dictionary>(); - foreach (var roundtripTime in _recentRequestsRoundtripTimes.ToArray()) - { - var metricsToAdd = new List(); + RemoteEndpoint = remoteEndpoint; + Info = peerConnectionInfo; - metrics.Add(roundtripTime.Key, metricsToAdd); - foreach (var requestMetric in roundtripTime.Value) - { - metricsToAdd.Add(requestMetric); - } - } + _knownTransactionCache = new BoundedExpirationCache(TransactionCacheMaxItems, QueuedTransactionTimeout); + _knownBlockCache = new BoundedExpirationCache(BlockCacheMaxItems, QueuedBlockTimeout); - return metrics; - } + _recentRequestsRoundtripTimes = new ConcurrentDictionary>(); + RecentRequestsRoundtripTimes = + new ReadOnlyDictionary>(_recentRequestsRoundtripTimes); - public Task GetNodesAsync(int count = NetworkConstants.DefaultDiscoveryMaxNodesToRequest) - { - GrpcRequest request = new GrpcRequest {ErrorMessage = "Request nodes failed."}; - Metadata data = new Metadata + _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue()); + _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue()); + + _sendAnnouncementJobs = new ActionBlock(SendStreamJobAsync, + new ExecutionDataflowBlockOptions + { + BoundedCapacity = NetworkConstants.DefaultMaxBufferedAnnouncementCount + }); + _sendBlockJobs = new ActionBlock(SendStreamJobAsync, + new ExecutionDataflowBlockOptions { - { GrpcConstants.TimeoutMetadataKey, GetNodesTimeout.ToString() }, - { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } - }; + BoundedCapacity = NetworkConstants.DefaultMaxBufferedBlockCount + }); + _sendTransactionJobs = new ActionBlock(SendStreamJobAsync, + new ExecutionDataflowBlockOptions + { + BoundedCapacity = NetworkConstants.DefaultMaxBufferedTransactionCount + }); + } - return RequestAsync(() => _client.GetNodesAsync(new NodesRequest {MaxCount = count}, data), request); - } + public Timestamp LastSentHandshakeTime { get; private set; } - public void UpdateLastReceivedHandshake(Handshake handshake) - { - LastKnownLibHeight = handshake.HandshakeData.LastIrreversibleBlockHeight; - CurrentBlockHash = handshake.HandshakeData.BestChainHash; - CurrentBlockHeight = handshake.HandshakeData.BestChainHeight; - LastReceivedHandshakeTime = handshake.HandshakeData.Time; - } + public bool IsConnected { get; set; } + public bool IsShutdown { get; set; } + public Hash CurrentBlockHash { get; private set; } + public long CurrentBlockHeight { get; private set; } - public void UpdateLastSentHandshake(Handshake handshake) + /// + /// Session ID to use when sending messages to this peer, announced at connection + /// from the other peer. + /// + public byte[] OutboundSessionId => Info.SessionId; + + public IReadOnlyDictionary> RecentRequestsRoundtripTimes { get; } + + /// + /// Property that describes that describes if the peer is ready for send/request operations. It's based + /// on the state of the underlying channel and the IsConnected. + /// + public bool IsReady => (_channel.State == ChannelState.Idle || _channel.State == ChannelState.Ready) && IsConnected; + + public bool IsInvalid => + !IsConnected && + Info.ConnectionTime.AddMilliseconds(NetworkConstants.PeerConnectionTimeout) < + TimestampHelper.GetUtcNow(); + + public string ConnectionStatus => _channel.State.ToString(); + + public Hash LastKnownLibHash { get; private set; } + public long LastKnownLibHeight { get; private set; } + public Timestamp LastReceivedHandshakeTime { get; private set; } + public SyncState SyncState { get; set; } + + /// + /// Session ID to use when authenticating messages from this peer, announced to the + /// remote peer at connection. + /// + public byte[] InboundSessionId { get; set; } + + public DnsEndPoint RemoteEndpoint { get; } + public int BufferedTransactionsCount => _sendTransactionJobs.InputCount; + public int BufferedBlocksCount => _sendBlockJobs.InputCount; + public int BufferedAnnouncementsCount => _sendAnnouncementJobs.InputCount; + + public PeerConnectionInfo Info { get; } + + public Dictionary> GetRequestMetrics() + { + var metrics = new Dictionary>(); + foreach (var roundtripTime in _recentRequestsRoundtripTimes.ToArray()) { - LastSentHandshakeTime = handshake.HandshakeData.Time; + var metricsToAdd = new List(); + + metrics.Add(roundtripTime.Key, metricsToAdd); + foreach (var requestMetric in roundtripTime.Value) metricsToAdd.Add(requestMetric); } - public void UpdateLastKnownLib(LibAnnouncement libAnnouncement) + return metrics; + } + + public Task GetNodesAsync(int count = NetworkConstants.DefaultDiscoveryMaxNodesToRequest) + { + var request = new GrpcRequest { ErrorMessage = "Request nodes failed." }; + var data = new Metadata { - if (libAnnouncement.LibHeight <= LastKnownLibHeight) - { - return; - } + { GrpcConstants.TimeoutMetadataKey, GetNodesTimeout.ToString() }, + { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } + }; - LastKnownLibHash = libAnnouncement.LibHash; - LastKnownLibHeight = libAnnouncement.LibHeight; - } + return RequestAsync(() => _client.GetNodesAsync(new NodesRequest { MaxCount = count }, data), request); + } + + public void UpdateLastKnownLib(LibAnnouncement libAnnouncement) + { + if (libAnnouncement.LibHeight <= LastKnownLibHeight) return; + + LastKnownLibHash = libAnnouncement.LibHash; + LastKnownLibHeight = libAnnouncement.LibHeight; + } + + public async Task CheckHealthAsync() + { + var request = new GrpcRequest { ErrorMessage = "Check health failed." }; - public async Task CheckHealthAsync() + var data = new Metadata { - var request = new GrpcRequest { ErrorMessage = "Check health failed." }; + { GrpcConstants.TimeoutMetadataKey, CheckHealthTimeout.ToString() }, + { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } + }; - var data = new Metadata - { - { GrpcConstants.TimeoutMetadataKey, CheckHealthTimeout.ToString() }, - { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } - }; + await RequestAsync(() => _client.CheckHealthAsync(new HealthCheckRequest(), data), request); + } - await RequestAsync(() => _client.CheckHealthAsync(new HealthCheckRequest(), data), request); - } + public async Task GetBlockByHashAsync(Hash hash) + { + var blockRequest = new BlockRequest { Hash = hash }; - public async Task GetBlockByHashAsync(Hash hash) + var request = new GrpcRequest { - var blockRequest = new BlockRequest {Hash = hash}; + ErrorMessage = $"Block request for {hash} failed.", + MetricName = nameof(MetricNames.GetBlock), + MetricInfo = $"Block request for {hash}" + }; - GrpcRequest request = new GrpcRequest - { - ErrorMessage = $"Block request for {hash} failed.", - MetricName = nameof(MetricNames.GetBlock), - MetricInfo = $"Block request for {hash}" - }; + var data = new Metadata + { + { GrpcConstants.TimeoutMetadataKey, BlockRequestTimeout.ToString() }, + { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } + }; - Metadata data = new Metadata - { - { GrpcConstants.TimeoutMetadataKey, BlockRequestTimeout.ToString() }, - { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } - }; + var blockReply = await RequestAsync(() => _client.RequestBlockAsync(blockRequest, data), request); - var blockReply = await RequestAsync(() => _client.RequestBlockAsync(blockRequest, data), request); + return blockReply?.Block; + } - return blockReply?.Block; - } + public async Task> GetBlocksAsync(Hash firstHash, int count) + { + var blockRequest = new BlocksRequest { PreviousBlockHash = firstHash, Count = count }; + var blockInfo = $"{{ first: {firstHash}, count: {count} }}"; - public async Task> GetBlocksAsync(Hash firstHash, int count) + var request = new GrpcRequest { - var blockRequest = new BlocksRequest {PreviousBlockHash = firstHash, Count = count}; - var blockInfo = $"{{ first: {firstHash}, count: {count} }}"; + ErrorMessage = $"Get blocks for {blockInfo} failed.", + MetricName = nameof(MetricNames.GetBlocks), + MetricInfo = $"Get blocks for {blockInfo}" + }; - GrpcRequest request = new GrpcRequest - { - ErrorMessage = $"Get blocks for {blockInfo} failed.", - MetricName = nameof(MetricNames.GetBlocks), - MetricInfo = $"Get blocks for {blockInfo}" - }; + var data = new Metadata + { + { GrpcConstants.TimeoutMetadataKey, BlocksRequestTimeout.ToString() }, + { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } + }; - Metadata data = new Metadata - { - { GrpcConstants.TimeoutMetadataKey, BlocksRequestTimeout.ToString() }, - { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } - }; + var list = await RequestAsync(() => _client.RequestBlocksAsync(blockRequest, data), request); - var list = await RequestAsync(() => _client.RequestBlocksAsync(blockRequest, data), request); + if (list == null) + return new List(); - if (list == null) - return new List(); + return list.Blocks.ToList(); + } - return list.Blocks.ToList(); - } + public async Task TryRecoverAsync() + { + if (_channel.State == ChannelState.Shutdown) + return false; - #region Streaming + await _channel.TryWaitForStateChangedAsync(_channel.State, + DateTime.UtcNow.AddSeconds(NetworkConstants.DefaultPeerRecoveryTimeout)); - public void EnqueueTransaction(Transaction transaction, Action sendCallback) + // Either we connected again or the state change wait timed out. + if (_channel.State == ChannelState.TransientFailure || _channel.State == ChannelState.Connecting) { - if (!IsReady) - throw new NetworkException($"Dropping transaction, peer is not ready - {this}.", - NetworkExceptionType.NotConnected); - - _sendTransactionJobs.Post(new StreamJob{Transaction = transaction, SendCallback = sendCallback}); + IsConnected = false; + return false; } - public void EnqueueAnnouncement(BlockAnnouncement announcement, Action sendCallback) - { - if (!IsReady) - throw new NetworkException($"Dropping announcement, peer is not ready - {this}.", - NetworkExceptionType.NotConnected); + return true; + } - _sendAnnouncementJobs.Post(new StreamJob {BlockAnnouncement = announcement, SendCallback = sendCallback}); - } + public bool KnowsBlock(Hash hash) + { + return _knownBlockCache.HasHash(hash, false); + } - public void EnqueueBlock(BlockWithTransactions blockWithTransactions, Action sendCallback) - { - if (!IsReady) - throw new NetworkException($"Dropping block, peer is not ready - {this}.", - NetworkExceptionType.NotConnected); + public bool TryAddKnownBlock(Hash blockHash) + { + return _knownBlockCache.TryAdd(blockHash); + } - _sendBlockJobs.Post(new StreamJob{BlockWithTransactions = blockWithTransactions, SendCallback = sendCallback}); - } - - public void EnqueueLibAnnouncement(LibAnnouncement libAnnouncement, Action sendCallback) - { - if (!IsReady) - throw new NetworkException($"Dropping lib announcement, peer is not ready - {this}.", - NetworkExceptionType.NotConnected); + public bool KnowsTransaction(Hash hash) + { + return _knownTransactionCache.HasHash(hash, false); + } - _sendAnnouncementJobs.Post(new StreamJob - { - LibAnnouncement = libAnnouncement, - SendCallback = sendCallback - }); - } + public bool TryAddKnownTransaction(Hash transactionHash) + { + return _knownTransactionCache.TryAdd(transactionHash); + } + + public async Task DisconnectAsync(bool gracefulDisconnect) + { + IsConnected = false; + IsShutdown = true; + + // we complete but no need to await the jobs + _sendAnnouncementJobs.Complete(); + _sendBlockJobs.Complete(); + _sendTransactionJobs.Complete(); + + _announcementStreamCall?.Dispose(); + _transactionStreamCall?.Dispose(); + _blockStreamCall?.Dispose(); - private async Task SendStreamJobAsync(StreamJob job) + // send disconnect message if the peer is still connected and the connection + // is stable. + if (gracefulDisconnect && (_channel.State == ChannelState.Idle || _channel.State == ChannelState.Ready)) { - if (!IsReady) - return; + var request = new GrpcRequest { ErrorMessage = "Could not send disconnect." }; try { - if (job.Transaction != null) - { - await SendTransactionAsync(job.Transaction); - } - else if (job.BlockAnnouncement != null) - { - await SendAnnouncementAsync(job.BlockAnnouncement); - } - else if (job.BlockWithTransactions != null) - { - await BroadcastBlockAsync(job.BlockWithTransactions); - } - else if (job.LibAnnouncement != null) - { - await SendLibAnnouncementAsync(job.LibAnnouncement); - } - } - catch (RpcException ex) - { - job.SendCallback?.Invoke(HandleRpcException(ex, $"Could not broadcast to {this}: ")); - await Task.Delay(StreamRecoveryWaitTime); - return; + var metadata = new Metadata { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }; + + await RequestAsync( + () => _client.DisconnectAsync(new DisconnectReason + { Why = DisconnectReason.Types.Reason.Shutdown }, metadata), request); } - catch (Exception ex) + catch (NetworkException) { - job.SendCallback?.Invoke(new NetworkException("Unknown exception during broadcast.", ex)); - throw; + // swallow the exception, we don't care because we're disconnecting. } + } - job.SendCallback?.Invoke(null); + try + { + await _channel.ShutdownAsync(); + } + catch (InvalidOperationException) + { + // if channel already shutdown } + } - private async Task BroadcastBlockAsync(BlockWithTransactions blockWithTransactions) + public void UpdateLastReceivedHandshake(Handshake handshake) + { + LastKnownLibHeight = handshake.HandshakeData.LastIrreversibleBlockHeight; + CurrentBlockHash = handshake.HandshakeData.BestChainHash; + CurrentBlockHeight = handshake.HandshakeData.BestChainHeight; + LastReceivedHandshakeTime = handshake.HandshakeData.Time; + } + + public void UpdateLastSentHandshake(Handshake handshake) + { + LastSentHandshakeTime = handshake.HandshakeData.Time; + } + + public async Task ConfirmHandshakeAsync() + { + var request = new GrpcRequest { ErrorMessage = "Could not send confirm handshake." }; + + var data = new Metadata { - if (_blockStreamCall == null) - _blockStreamCall = _client.BlockBroadcastStream(new Metadata {{ GrpcConstants.SessionIdMetadataKey, OutboundSessionId }}); + { GrpcConstants.TimeoutMetadataKey, UpdateHandshakeTimeout.ToString() }, + { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } + }; - try - { - await _blockStreamCall.RequestStream.WriteAsync(blockWithTransactions); - } - catch (RpcException) - { - _blockStreamCall.Dispose(); - _blockStreamCall = null; + await RequestAsync(() => _client.ConfirmHandshakeAsync(new ConfirmHandshakeRequest(), data), request); + } - throw; - } - } + private async Task RequestAsync(Func> func, GrpcRequest requestParams) + { + var metricsName = requestParams.MetricName; + var timeRequest = !string.IsNullOrEmpty(metricsName); + var requestStartTime = TimestampHelper.GetUtcNow(); + + Stopwatch requestTimer = null; + + if (timeRequest) + requestTimer = Stopwatch.StartNew(); - /// - /// Send a announcement to the peer using the stream call. - /// Note: this method is not thread safe. - /// - private async Task SendAnnouncementAsync(BlockAnnouncement header) + try { - if (_announcementStreamCall == null) - _announcementStreamCall = _client.AnnouncementBroadcastStream(new Metadata {{ GrpcConstants.SessionIdMetadataKey, OutboundSessionId }}); - - try + var response = await func(); + if (timeRequest) { - await _announcementStreamCall.RequestStream.WriteAsync(header); + requestTimer.Stop(); + RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds); } - catch (RpcException) - { - _announcementStreamCall.Dispose(); - _announcementStreamCall = null; - throw; - } + return response; + } + catch (ObjectDisposedException ex) + { + throw new NetworkException("Peer is closed", ex, NetworkExceptionType.Unrecoverable); + } + catch (AggregateException ex) + { + if (!(ex.InnerException is RpcException rpcException)) + throw new NetworkException($"Unknown exception. {this}: {requestParams.ErrorMessage}", + NetworkExceptionType.Unrecoverable); + + throw HandleRpcException(rpcException, requestParams.ErrorMessage); } + } - /// - /// Send a transaction to the peer using the stream call. - /// Note: this method is not thread safe. - /// - private async Task SendTransactionAsync(Transaction transaction) + private void RecordMetric(GrpcRequest grpcRequest, Timestamp requestStartTime, long elapsedMilliseconds) + { + var metrics = _recentRequestsRoundtripTimes[grpcRequest.MetricName]; + + while (metrics.Count >= MaxMetricsPerMethod) + metrics.TryDequeue(out _); + + metrics.Enqueue(new RequestMetric { - if (_transactionStreamCall == null) - _transactionStreamCall = _client.TransactionBroadcastStream(new Metadata {{ GrpcConstants.SessionIdMetadataKey, OutboundSessionId }}); + Info = grpcRequest.MetricInfo, + RequestTime = requestStartTime, + MethodName = grpcRequest.MetricName, + RoundTripTime = elapsedMilliseconds + }); + } - try + /// + /// This method handles the case where the peer is potentially down. If the Rpc call + /// put the channel in TransientFailure or Connecting, we give the connection a certain time to recover. + /// + private NetworkException HandleRpcException(RpcException exception, string errorMessage) + { + var message = $"Failed request to {this}: {errorMessage}"; + var type = NetworkExceptionType.Rpc; + + if (_channel.State != ChannelState.Ready) + { + // if channel has been shutdown (unrecoverable state) remove it. + if (_channel.State == ChannelState.Shutdown) { - await _transactionStreamCall.RequestStream.WriteAsync(transaction); + message = $"Peer is shutdown - {this}: {errorMessage}"; + type = NetworkExceptionType.Unrecoverable; } - catch (RpcException) + else if (_channel.State == ChannelState.TransientFailure || _channel.State == ChannelState.Connecting) { - _transactionStreamCall.Dispose(); - _transactionStreamCall = null; - - throw; + // from this we try to recover + message = $"Peer is unstable - {this}: {errorMessage}"; + type = NetworkExceptionType.PeerUnstable; + } + else + { + // if idle just after an exception, disconnect. + message = $"Peer idle, channel state {_channel.State} - {this}: {errorMessage}"; + type = NetworkExceptionType.Unrecoverable; } } - - /// - /// Send a lib announcement to the peer using the stream call. - /// Note: this method is not thread safe. - /// - public async Task SendLibAnnouncementAsync(LibAnnouncement libAnnouncement) + else { - if (_libAnnouncementStreamCall == null) - _libAnnouncementStreamCall = _client.LibAnnouncementBroadcastStream(new Metadata {{ GrpcConstants.SessionIdMetadataKey, OutboundSessionId }}); - - try + // there was an exception, not related to connectivity. + if (exception.StatusCode == StatusCode.Cancelled) { - await _libAnnouncementStreamCall.RequestStream.WriteAsync(libAnnouncement); + message = $"Request was cancelled {this}: {errorMessage}"; + type = NetworkExceptionType.Unrecoverable; } - catch (RpcException) + else if (exception.StatusCode == StatusCode.Unknown) { - _libAnnouncementStreamCall.Dispose(); - _libAnnouncementStreamCall = null; - - throw; + message = $"Exception in handler {this}: {errorMessage}"; + type = NetworkExceptionType.HandlerException; } } - #endregion - - public async Task ConfirmHandshakeAsync() - { - var request = new GrpcRequest {ErrorMessage = "Could not send confirm handshake."}; + return new NetworkException(message, exception, type); + } - Metadata data = new Metadata - { - {GrpcConstants.TimeoutMetadataKey, UpdateHandshakeTimeout.ToString()}, - {GrpcConstants.SessionIdMetadataKey, OutboundSessionId} - }; + public override string ToString() + { + return $"{{ listening-port: {RemoteEndpoint}, key: {Info.Pubkey.Substring(0, 45)}... }}"; + } - await RequestAsync(() => _client.ConfirmHandshakeAsync(new ConfirmHandshakeRequest(), data), request); - } + private enum MetricNames + { + GetBlocks, + GetBlock + } - private async Task RequestAsync(Func> func, GrpcRequest requestParams) - { - var metricsName = requestParams.MetricName; - var timeRequest = !string.IsNullOrEmpty(metricsName); - var requestStartTime = TimestampHelper.GetUtcNow(); + #region Streaming - Stopwatch requestTimer = null; + public void EnqueueTransaction(Transaction transaction, Action sendCallback) + { + if (!IsReady) + throw new NetworkException($"Dropping transaction, peer is not ready - {this}.", + NetworkExceptionType.NotConnected); - if (timeRequest) - requestTimer = Stopwatch.StartNew(); + _sendTransactionJobs.Post(new StreamJob { Transaction = transaction, SendCallback = sendCallback }); + } - try - { - var response = await func(); - if (timeRequest) - { - requestTimer.Stop(); - RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds); - } - - return response; - } - catch (ObjectDisposedException ex) - { - throw new NetworkException("Peer is closed", ex, NetworkExceptionType.Unrecoverable); - } - catch (AggregateException ex) - { - if (!(ex.InnerException is RpcException rpcException)) - { - throw new NetworkException($"Unknown exception. {this}: {requestParams.ErrorMessage}", - NetworkExceptionType.Unrecoverable); - } + public void EnqueueAnnouncement(BlockAnnouncement announcement, Action sendCallback) + { + if (!IsReady) + throw new NetworkException($"Dropping announcement, peer is not ready - {this}.", + NetworkExceptionType.NotConnected); - throw HandleRpcException(rpcException, requestParams.ErrorMessage); - } - } + _sendAnnouncementJobs.Post(new StreamJob { BlockAnnouncement = announcement, SendCallback = sendCallback }); + } - private void RecordMetric(GrpcRequest grpcRequest, Timestamp requestStartTime, long elapsedMilliseconds) - { - var metrics = _recentRequestsRoundtripTimes[grpcRequest.MetricName]; + public void EnqueueBlock(BlockWithTransactions blockWithTransactions, Action sendCallback) + { + if (!IsReady) + throw new NetworkException($"Dropping block, peer is not ready - {this}.", + NetworkExceptionType.NotConnected); - while (metrics.Count >= MaxMetricsPerMethod) - metrics.TryDequeue(out _); + _sendBlockJobs.Post( + new StreamJob { BlockWithTransactions = blockWithTransactions, SendCallback = sendCallback }); + } - metrics.Enqueue(new RequestMetric - { - Info = grpcRequest.MetricInfo, - RequestTime = requestStartTime, - MethodName = grpcRequest.MetricName, - RoundTripTime = elapsedMilliseconds - }); - } + public void EnqueueLibAnnouncement(LibAnnouncement libAnnouncement, Action sendCallback) + { + if (!IsReady) + throw new NetworkException($"Dropping lib announcement, peer is not ready - {this}.", + NetworkExceptionType.NotConnected); - /// - /// This method handles the case where the peer is potentially down. If the Rpc call - /// put the channel in TransientFailure or Connecting, we give the connection a certain time to recover. - /// - private NetworkException HandleRpcException(RpcException exception, string errorMessage) + _sendAnnouncementJobs.Post(new StreamJob { - string message = $"Failed request to {this}: {errorMessage}"; - NetworkExceptionType type = NetworkExceptionType.Rpc; - - if (_channel.State != ChannelState.Ready) - { - // if channel has been shutdown (unrecoverable state) remove it. - if (_channel.State == ChannelState.Shutdown) - { - message = $"Peer is shutdown - {this}: {errorMessage}"; - type = NetworkExceptionType.Unrecoverable; - } - else if (_channel.State == ChannelState.TransientFailure || _channel.State == ChannelState.Connecting) - { - // from this we try to recover - message = $"Peer is unstable - {this}: {errorMessage}"; - type = NetworkExceptionType.PeerUnstable; - } - else - { - // if idle just after an exception, disconnect. - message = $"Peer idle, channel state {_channel.State} - {this}: {errorMessage}"; - type = NetworkExceptionType.Unrecoverable; - } - } - else - { - // there was an exception, not related to connectivity. - if (exception.StatusCode == StatusCode.Cancelled) - { - message = $"Request was cancelled {this}: {errorMessage}"; - type = NetworkExceptionType.Unrecoverable; - } - else if (exception.StatusCode == StatusCode.Unknown) - { - message = $"Exception in handler {this}: {errorMessage}"; - type = NetworkExceptionType.HandlerException; - } - } + LibAnnouncement = libAnnouncement, + SendCallback = sendCallback + }); + } - return new NetworkException(message, exception, type); + private async Task SendStreamJobAsync(StreamJob job) + { + if (!IsReady) + return; + + try + { + if (job.Transaction != null) + await SendTransactionAsync(job.Transaction); + else if (job.BlockAnnouncement != null) + await SendAnnouncementAsync(job.BlockAnnouncement); + else if (job.BlockWithTransactions != null) + await BroadcastBlockAsync(job.BlockWithTransactions); + else if (job.LibAnnouncement != null) await SendLibAnnouncementAsync(job.LibAnnouncement); } - - public async Task TryRecoverAsync() + catch (RpcException ex) { - if (_channel.State == ChannelState.Shutdown) - return false; + job.SendCallback?.Invoke(HandleRpcException(ex, $"Could not broadcast to {this}: ")); + await Task.Delay(StreamRecoveryWaitTime); + return; + } + catch (Exception ex) + { + job.SendCallback?.Invoke(new NetworkException("Unknown exception during broadcast.", ex)); + throw; + } - await _channel.TryWaitForStateChangedAsync(_channel.State, - DateTime.UtcNow.AddSeconds(NetworkConstants.DefaultPeerRecoveryTimeout)); + job.SendCallback?.Invoke(null); + } - // Either we connected again or the state change wait timed out. - if (_channel.State == ChannelState.TransientFailure || _channel.State == ChannelState.Connecting) - { - IsConnected = false; - return false; - } + private async Task BroadcastBlockAsync(BlockWithTransactions blockWithTransactions) + { + if (_blockStreamCall == null) + _blockStreamCall = _client.BlockBroadcastStream(new Metadata + { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }); - return true; + try + { + await _blockStreamCall.RequestStream.WriteAsync(blockWithTransactions); } - - public bool KnowsBlock(Hash hash) + catch (RpcException) { - return _knownBlockCache.HasHash(hash, false); + _blockStreamCall.Dispose(); + _blockStreamCall = null; + + throw; } + } - public bool TryAddKnownBlock(Hash blockHash) + /// + /// Send a announcement to the peer using the stream call. + /// Note: this method is not thread safe. + /// + private async Task SendAnnouncementAsync(BlockAnnouncement header) + { + if (_announcementStreamCall == null) + _announcementStreamCall = _client.AnnouncementBroadcastStream(new Metadata + { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }); + + try { - return _knownBlockCache.TryAdd(blockHash); + await _announcementStreamCall.RequestStream.WriteAsync(header); } - - public bool KnowsTransaction(Hash hash) + catch (RpcException) { - return _knownTransactionCache.HasHash(hash, false); + _announcementStreamCall.Dispose(); + _announcementStreamCall = null; + + throw; } + } - public bool TryAddKnownTransaction(Hash transactionHash) + /// + /// Send a transaction to the peer using the stream call. + /// Note: this method is not thread safe. + /// + private async Task SendTransactionAsync(Transaction transaction) + { + if (_transactionStreamCall == null) + _transactionStreamCall = _client.TransactionBroadcastStream(new Metadata + { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }); + + try { - return _knownTransactionCache.TryAdd(transactionHash); + await _transactionStreamCall.RequestStream.WriteAsync(transaction); } - - public async Task DisconnectAsync(bool gracefulDisconnect) + catch (RpcException) { - IsConnected = false; - IsShutdown = true; + _transactionStreamCall.Dispose(); + _transactionStreamCall = null; - // we complete but no need to await the jobs - _sendAnnouncementJobs.Complete(); - _sendBlockJobs.Complete(); - _sendTransactionJobs.Complete(); - - _announcementStreamCall?.Dispose(); - _transactionStreamCall?.Dispose(); - _blockStreamCall?.Dispose(); + throw; + } + } - // send disconnect message if the peer is still connected and the connection - // is stable. - if (gracefulDisconnect && (_channel.State == ChannelState.Idle || _channel.State == ChannelState.Ready)) - { - GrpcRequest request = new GrpcRequest {ErrorMessage = "Could not send disconnect."}; - - try - { - Metadata metadata = new Metadata {{ GrpcConstants.SessionIdMetadataKey, OutboundSessionId }}; - - await RequestAsync( - () => _client.DisconnectAsync(new DisconnectReason - {Why = DisconnectReason.Types.Reason.Shutdown}, metadata), request); - } - catch (NetworkException) - { - // swallow the exception, we don't care because we're disconnecting. - } - } + /// + /// Send a lib announcement to the peer using the stream call. + /// Note: this method is not thread safe. + /// + public async Task SendLibAnnouncementAsync(LibAnnouncement libAnnouncement) + { + if (_libAnnouncementStreamCall == null) + _libAnnouncementStreamCall = _client.LibAnnouncementBroadcastStream(new Metadata + { { GrpcConstants.SessionIdMetadataKey, OutboundSessionId } }); - try - { - await _channel.ShutdownAsync(); - } - catch (InvalidOperationException) - { - // if channel already shutdown - } + try + { + await _libAnnouncementStreamCall.RequestStream.WriteAsync(libAnnouncement); } - - public override string ToString() + catch (RpcException) { - return $"{{ listening-port: {RemoteEndpoint}, key: {Info.Pubkey.Substring(0, 45)}... }}"; + _libAnnouncementStreamCall.Dispose(); + _libAnnouncementStreamCall = null; + + throw; } } + + #endregion } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/GrpcRequest.cs b/src/AElf.OS.Network.Grpc/GrpcRequest.cs index cc18d8c71e..c25f4eab3b 100644 --- a/src/AElf.OS.Network.Grpc/GrpcRequest.cs +++ b/src/AElf.OS.Network.Grpc/GrpcRequest.cs @@ -1,9 +1,8 @@ -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcRequest { - public class GrpcRequest - { - public string ErrorMessage { get; set; } - public string MetricName { get; set; } - public string MetricInfo { get; set; } - } + public string ErrorMessage { get; set; } + public string MetricName { get; set; } + public string MetricInfo { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Helpers/GrpcEndPointHelper.cs b/src/AElf.OS.Network.Grpc/Helpers/GrpcEndPointHelper.cs index bb067a936d..3a71ee8cd8 100644 --- a/src/AElf.OS.Network.Grpc/Helpers/GrpcEndPointHelper.cs +++ b/src/AElf.OS.Network.Grpc/Helpers/GrpcEndPointHelper.cs @@ -1,23 +1,22 @@ using System.Net; using AElf.OS.Network.Helpers; -namespace AElf.OS.Network.Grpc.Helpers +namespace AElf.OS.Network.Grpc.Helpers; + +public static class GrpcEndPointHelper { - public static class GrpcEndPointHelper + public static bool ParseDnsEndPoint(string grpcEndpoint, out DnsEndPoint outEndPoint) { - public static bool ParseDnsEndPoint(string grpcEndpoint, out DnsEndPoint outEndPoint) - { - outEndPoint = null; + outEndPoint = null; - var splitRes = grpcEndpoint.Split(':'); - var nonPrefixedGrpcEndpoint = splitRes[1] + ":" + splitRes[2]; + var splitRes = grpcEndpoint.Split(':'); + var nonPrefixedGrpcEndpoint = splitRes[1] + ":" + splitRes[2]; - if (!AElfPeerEndpointHelper.TryParse(nonPrefixedGrpcEndpoint, out DnsEndPoint parsedDnsEndpoint)) - return false; + if (!AElfPeerEndpointHelper.TryParse(nonPrefixedGrpcEndpoint, out var parsedDnsEndpoint)) + return false; - outEndPoint = parsedDnsEndpoint; + outEndPoint = parsedDnsEndpoint; - return true; - } + return true; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Helpers/TlsHelper.cs b/src/AElf.OS.Network.Grpc/Helpers/TlsHelper.cs index 33c4776bc6..fada2c4262 100644 --- a/src/AElf.OS.Network.Grpc/Helpers/TlsHelper.cs +++ b/src/AElf.OS.Network.Grpc/Helpers/TlsHelper.cs @@ -12,57 +12,57 @@ using Org.BouncyCastle.Utilities; using Org.BouncyCastle.X509; -namespace AElf.OS.Network.Grpc.Helpers +namespace AElf.OS.Network.Grpc.Helpers; + +public static class TlsHelper { - public static class TlsHelper + private const int RsaKeyLength = 2048; + private const string X509NamePrefix = "CN="; + + public static string ObjectToPem(object obj) + { + TextWriter textWriter = new StringWriter(); + var pemWriter = new PemWriter(textWriter); + pemWriter.WriteObject(obj); + pemWriter.Writer.Flush(); + + return textWriter.ToString(); + } + + public static AsymmetricCipherKeyPair GenerateRsaKeyPair() { - private const int RsaKeyLength = 2048; - private const string X509NamePrefix = "CN="; - - public static string ObjectToPem(object obj) - { - TextWriter textWriter = new StringWriter(); - PemWriter pemWriter = new PemWriter(textWriter); - pemWriter.WriteObject(obj); - pemWriter.Writer.Flush(); - - return textWriter.ToString(); - } + var generator = new RsaKeyPairGenerator(); + generator.Init(new KeyGenerationParameters(new SecureRandom(), RsaKeyLength)); - public static AsymmetricCipherKeyPair GenerateRsaKeyPair() - { - RsaKeyPairGenerator generator = new RsaKeyPairGenerator(); - generator.Init(new KeyGenerationParameters(new SecureRandom(), RsaKeyLength)); - - return generator.GenerateKeyPair(); - } + return generator.GenerateKeyPair(); + } - public static X509Certificate GenerateCertificate(X509Name issuer, X509Name subject, - AsymmetricKeyParameter issuerPrivate, AsymmetricKeyParameter subjectPublic) - { - ISignatureFactory signatureFactory = new Asn1SignatureFactory( - PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString(), issuerPrivate); + public static X509Certificate GenerateCertificate(X509Name issuer, X509Name subject, + AsymmetricKeyParameter issuerPrivate, AsymmetricKeyParameter subjectPublic) + { + ISignatureFactory signatureFactory = new Asn1SignatureFactory( + PkcsObjectIdentifiers.Sha256WithRsaEncryption.ToString(), issuerPrivate); - var certGenerator = new X509V3CertificateGenerator(); - certGenerator.SetIssuerDN(issuer); - certGenerator.SetSubjectDN(subject); - certGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), new SecureRandom())); - certGenerator.SetNotBefore(DateTime.UtcNow.Date); - certGenerator.SetNotAfter(DateTime.MaxValue); - certGenerator.SetPublicKey(subjectPublic); + var certGenerator = new X509V3CertificateGenerator(); + certGenerator.SetIssuerDN(issuer); + certGenerator.SetSubjectDN(subject); + certGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(long.MaxValue), + new SecureRandom())); + certGenerator.SetNotBefore(DateTime.UtcNow.Date); + certGenerator.SetNotAfter(DateTime.MaxValue); + certGenerator.SetPublicKey(subjectPublic); - return certGenerator.Generate(signatureFactory); - } + return certGenerator.Generate(signatureFactory); + } - public static KeyCertificatePair GenerateKeyCertificatePair() - { - var rsaKeyPair = GenerateRsaKeyPair(); - var certificate = GenerateCertificate(new X509Name(X509NamePrefix + GrpcConstants.DefaultTlsCommonName), - new X509Name(X509NamePrefix + GrpcConstants.DefaultTlsCommonName), rsaKeyPair.Private, rsaKeyPair.Public); + public static KeyCertificatePair GenerateKeyCertificatePair() + { + var rsaKeyPair = GenerateRsaKeyPair(); + var certificate = GenerateCertificate(new X509Name(X509NamePrefix + GrpcConstants.DefaultTlsCommonName), + new X509Name(X509NamePrefix + GrpcConstants.DefaultTlsCommonName), rsaKeyPair.Private, rsaKeyPair.Public); - var keyCertificatePair = new KeyCertificatePair(ObjectToPem(certificate), ObjectToPem(rsaKeyPair.Private)); + var keyCertificatePair = new KeyCertificatePair(ObjectToPem(certificate), ObjectToPem(rsaKeyPair.Private)); - return keyCertificatePair; - } + return keyCertificatePair; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Interceptors/AuthInterceptor.cs b/src/AElf.OS.Network.Grpc/Interceptors/AuthInterceptor.cs index 6dcb055f79..4ff85ff911 100644 --- a/src/AElf.OS.Network.Grpc/Interceptors/AuthInterceptor.cs +++ b/src/AElf.OS.Network.Grpc/Interceptors/AuthInterceptor.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using AElf.OS.Network.Infrastructure; using Grpc.Core; @@ -7,108 +6,109 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class AuthInterceptor : Interceptor { - public class AuthInterceptor : Interceptor + private readonly IPeerPool _peerPool; + + public AuthInterceptor(IPeerPool peerPool) { - private readonly IPeerPool _peerPool; - - public ILogger Logger { get; set; } + _peerPool = peerPool; + Logger = NullLogger.Instance; + } - public AuthInterceptor(IPeerPool peerPool) - { - _peerPool = peerPool; - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public override Task UnaryServerHandler(TRequest request, - ServerCallContext context, UnaryServerMethod continuation) + public override Task UnaryServerHandler(TRequest request, + ServerCallContext context, UnaryServerMethod continuation) + { + try { - try + if (IsNeedAuth(context.Method)) { - if (IsNeedAuth(context.Method)) + var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey()); + + if (peer == null) { - var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey()); + Logger.LogWarning($"Could not find peer {context.GetPublicKey()}"); + return Task.FromResult(null); + } + + // check that the peers session is equal to one announced in the headers + var sessionId = context.GetSessionId(); - if (peer == null) + if (!peer.InboundSessionId.BytesEqual(sessionId)) + { + if (peer.InboundSessionId == null) { - Logger.LogWarning($"Could not find peer {context.GetPublicKey()}"); + Logger.LogWarning($"Wrong inbound session id {context.Peer}, {context.Method}"); return Task.FromResult(null); } - // check that the peers session is equal to one announced in the headers - var sessionId = context.GetSessionId(); - - if (!peer.InboundSessionId.BytesEqual(sessionId)) + if (sessionId == null) { - if (peer.InboundSessionId == null) - { - Logger.LogWarning($"Wrong inbound session id {context.Peer}, {context.Method}"); - return Task.FromResult(null); - } - - if (sessionId == null) - { - Logger.LogWarning($"Wrong context session id {context.Peer}, {context.Method}, {peer}"); - return Task.FromResult(null); - } - - Logger.LogWarning( - $"Unequal session id, {context.Peer} ({peer.InboundSessionId.ToHex()} vs {sessionId.ToHex()}) {context.GetPublicKey()}"); + Logger.LogWarning($"Wrong context session id {context.Peer}, {context.Method}, {peer}"); return Task.FromResult(null); } - context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}")); + Logger.LogWarning( + $"Unequal session id, {context.Peer} ({peer.InboundSessionId.ToHex()} vs {sessionId.ToHex()}) {context.GetPublicKey()}"); + return Task.FromResult(null); } - } - catch (Exception e) - { - Logger.LogError(e, $"Auth interceptor error {context.Peer}, {context.Method}: "); - throw; - } - return continuation(request, context); + context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}")); + } } - - private bool IsNeedAuth(string methodName) + catch (Exception e) { - return methodName != GetFullMethodName(nameof(PeerService.PeerServiceBase.Ping)) && - methodName != GetFullMethodName(nameof(PeerService.PeerServiceBase.DoHandshake)); + Logger.LogError(e, $"Auth interceptor error {context.Peer}, {context.Method}: "); + throw; } - private string GetFullMethodName(string methodName) - { - return "/" + nameof(PeerService) + "/" + methodName; - } + return continuation(request, context); + } - public override Task ClientStreamingServerHandler(IAsyncStreamReader requestStream, ServerCallContext context, - ClientStreamingServerMethod continuation) + private bool IsNeedAuth(string methodName) + { + return methodName != GetFullMethodName(nameof(PeerService.PeerServiceBase.Ping)) && + methodName != GetFullMethodName(nameof(PeerService.PeerServiceBase.DoHandshake)); + } + + private string GetFullMethodName(string methodName) + { + return "/" + nameof(PeerService) + "/" + methodName; + } + + public override Task ClientStreamingServerHandler( + IAsyncStreamReader requestStream, ServerCallContext context, + ClientStreamingServerMethod continuation) + { + try { - try - { - var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey()); + var peer = _peerPool.FindPeerByPublicKey(context.GetPublicKey()); - if (peer == null) - { - Logger.LogWarning($"Could not find peer {context.GetPublicKey()}"); - return Task.FromResult(null); - } - - if (!peer.InboundSessionId.BytesEqual(context.GetSessionId())) - { - Logger.LogWarning($"Wrong session id, ({peer.InboundSessionId.ToHex()} vs {context.GetSessionId().ToHex()}) {context.GetPublicKey()}"); - return Task.FromResult(null); - } - - context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}")); + if (peer == null) + { + Logger.LogWarning($"Could not find peer {context.GetPublicKey()}"); + return Task.FromResult(null); } - catch (Exception e) + + if (!peer.InboundSessionId.BytesEqual(context.GetSessionId())) { - Logger.LogError(e, "Auth stream interceptor error: "); - return null; + Logger.LogWarning( + $"Wrong session id, ({peer.InboundSessionId.ToHex()} vs {context.GetSessionId().ToHex()}) {context.GetPublicKey()}"); + return Task.FromResult(null); } - - return continuation(requestStream, context); + + context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PeerInfoMetadataKey, $"{peer}")); } + catch (Exception e) + { + Logger.LogError(e, "Auth stream interceptor error: "); + return null; + } + + return continuation(requestStream, context); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Interceptors/RetryInterceptor.cs b/src/AElf.OS.Network.Grpc/Interceptors/RetryInterceptor.cs index b7789afdf3..882abf2a32 100644 --- a/src/AElf.OS.Network.Grpc/Interceptors/RetryInterceptor.cs +++ b/src/AElf.OS.Network.Grpc/Interceptors/RetryInterceptor.cs @@ -5,91 +5,84 @@ using Grpc.Core; using Grpc.Core.Interceptors; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class RetryInterceptor : Interceptor { - public class RetryInterceptor : Interceptor + public override AsyncUnaryCall AsyncUnaryCall(TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) { - public override AsyncUnaryCall AsyncUnaryCall(TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) - { - var currentRetry = 0; + var currentRetry = 0; - string headerTimeout = context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey, true); - int timeout = headerTimeout == null ? GrpcConstants.DefaultRequestTimeout : int.Parse(headerTimeout); - var timeoutSpan = TimeSpan.FromMilliseconds(timeout); + var headerTimeout = context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey, true); + var timeout = headerTimeout == null ? GrpcConstants.DefaultRequestTimeout : int.Parse(headerTimeout); + var timeoutSpan = TimeSpan.FromMilliseconds(timeout); - string headerRetryCount = context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey, true); - int retryCount = headerRetryCount == null - ? NetworkConstants.DefaultRequestRetryCount - : int.Parse(headerRetryCount); + var headerRetryCount = context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey, true); + var retryCount = headerRetryCount == null + ? NetworkConstants.DefaultRequestRetryCount + : int.Parse(headerRetryCount); - async Task RetryCallback(Task responseTask) - { - var response = responseTask; + async Task RetryCallback(Task responseTask) + { + var response = responseTask; - // if no problem occured return - if (!response.IsFaulted) - { - return response.Result; - } + // if no problem occured return + if (!response.IsFaulted) return response.Result; - // if a problem occured but reached the max retries - if (currentRetry == retryCount) - { - return response.Result; - } + // if a problem occured but reached the max retries + if (currentRetry == retryCount) return response.Result; - currentRetry++; + currentRetry++; - // try again - var retryContext = BuildNewContext(context, timeoutSpan); + // try again + var retryContext = BuildNewContext(context, timeoutSpan); - var result = GetResponseAsync(continuation(request, retryContext), timeoutSpan) - .ContinueWith(RetryCallback).Unwrap(); + var result = GetResponseAsync(continuation(request, retryContext), timeoutSpan) + .ContinueWith(RetryCallback).Unwrap(); - return await result; - } + return await result; + } - var newContext = BuildNewContext(context, timeoutSpan); - var responseContinuation = continuation(request, newContext); + var newContext = BuildNewContext(context, timeoutSpan); + var responseContinuation = continuation(request, newContext); - var responseAsync = GetResponseAsync(responseContinuation, timeoutSpan).ContinueWith(RetryCallback) - .Unwrap(); + var responseAsync = GetResponseAsync(responseContinuation, timeoutSpan).ContinueWith(RetryCallback) + .Unwrap(); - return new AsyncUnaryCall( - responseAsync, - responseContinuation.ResponseHeadersAsync, - responseContinuation.GetStatus, - responseContinuation.GetTrailers, - responseContinuation.Dispose); - } + return new AsyncUnaryCall( + responseAsync, + responseContinuation.ResponseHeadersAsync, + responseContinuation.GetStatus, + responseContinuation.GetTrailers, + responseContinuation.Dispose); + } - private async Task GetResponseAsync(AsyncUnaryCall responseContinuation, - TimeSpan timeout) + private async Task GetResponseAsync(AsyncUnaryCall responseContinuation, + TimeSpan timeout) + { + try { - try - { - using (var cts = new CancellationTokenSource()) - { - // Ensure that under normal circumstances, the timeout is no earlier than on the server side. - cts.CancelAfter(timeout.Add(TimeSpan.FromSeconds(1))); - return await responseContinuation.ResponseAsync.WithCancellation(cts.Token); - } - } - catch (OperationCanceledException) + using (var cts = new CancellationTokenSource()) { - throw new RpcException(new Status(StatusCode.Cancelled, "The server is not responding.")); + // Ensure that under normal circumstances, the timeout is no earlier than on the server side. + cts.CancelAfter(timeout.Add(TimeSpan.FromSeconds(1))); + return await responseContinuation.ResponseAsync.WithCancellation(cts.Token); } } - - private ClientInterceptorContext BuildNewContext( - ClientInterceptorContext oldContext, TimeSpan timeout) - where TRequest : class - where TResponse : class + catch (OperationCanceledException) { - return new ClientInterceptorContext(oldContext.Method, oldContext.Host, - oldContext.Options.WithDeadline(DateTime.UtcNow.Add(timeout))); + throw new RpcException(new Status(StatusCode.Cancelled, "The server is not responding.")); } } + + private ClientInterceptorContext BuildNewContext( + ClientInterceptorContext oldContext, TimeSpan timeout) + where TRequest : class + where TResponse : class + { + return new ClientInterceptorContext(oldContext.Method, oldContext.Host, + oldContext.Options.WithDeadline(DateTime.UtcNow.Add(timeout))); + } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/QueuedHash.cs b/src/AElf.OS.Network.Grpc/QueuedHash.cs index b8f186b73f..b9449d7707 100644 --- a/src/AElf.OS.Network.Grpc/QueuedHash.cs +++ b/src/AElf.OS.Network.Grpc/QueuedHash.cs @@ -1,11 +1,10 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +internal class QueuedHash { - internal class QueuedHash - { - public Hash ItemHash { get; set; } - public Timestamp EnqueueTime { get; set; } - } + public Hash ItemHash { get; set; } + public Timestamp EnqueueTime { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/Service/GrpcServerService.cs b/src/AElf.OS.Network.Grpc/Service/GrpcServerService.cs index 9a117e0a8d..c88affdddf 100644 --- a/src/AElf.OS.Network.Grpc/Service/GrpcServerService.cs +++ b/src/AElf.OS.Network.Grpc/Service/GrpcServerService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Net; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.TransactionPool; @@ -17,394 +16,381 @@ using Microsoft.Extensions.Options; using Volo.Abp.EventBus.Local; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +/// +/// Implementation of the grpc generated service. It contains the rpc methods +/// exposed to peers. +/// +public class GrpcServerService : PeerService.PeerServiceBase { - /// - /// Implementation of the grpc generated service. It contains the rpc methods - /// exposed to peers. - /// - public class GrpcServerService : PeerService.PeerServiceBase + private readonly IBlockchainService _blockchainService; + private readonly IConnectionService _connectionService; + private readonly INodeManager _nodeManager; + + private readonly ISyncStateService _syncStateService; + + public GrpcServerService(ISyncStateService syncStateService, IConnectionService connectionService, + IBlockchainService blockchainService, INodeManager nodeManager) { - private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; - public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } + _syncStateService = syncStateService; + _connectionService = connectionService; + _blockchainService = blockchainService; + _nodeManager = nodeManager; - private readonly ISyncStateService _syncStateService; - private readonly IBlockchainService _blockchainService; - private readonly INodeManager _nodeManager; - private readonly IConnectionService _connectionService; + EventBus = NullLocalEventBus.Instance; + Logger = NullLogger.Instance; + } + + private NetworkOptions NetworkOptions => NetworkOptionsSnapshot.Value; + public IOptionsSnapshot NetworkOptionsSnapshot { get; set; } - public ILocalEventBus EventBus { get; set; } - public ILogger Logger { get; set; } + public ILocalEventBus EventBus { get; set; } + public ILogger Logger { get; set; } - public GrpcServerService(ISyncStateService syncStateService, IConnectionService connectionService, - IBlockchainService blockchainService, INodeManager nodeManager) + public override async Task DoHandshake(HandshakeRequest request, ServerCallContext context) + { + try { - _syncStateService = syncStateService; - _connectionService = connectionService; - _blockchainService = blockchainService; - _nodeManager = nodeManager; + Logger.LogDebug($"Peer {context.Peer} has requested a handshake."); - EventBus = NullLocalEventBus.Instance; - Logger = NullLogger.Instance; - } + if (context.AuthContext?.Properties != null) + foreach (var authProperty in context.AuthContext.Properties) + Logger.LogDebug($"Auth property: {authProperty.Name} -> {authProperty.Value}"); + + if (!GrpcEndPointHelper.ParseDnsEndPoint(context.Peer, out var peerEndpoint)) + return new HandshakeReply { Error = HandshakeError.InvalidConnection }; - public override async Task DoHandshake(HandshakeRequest request, ServerCallContext context) + return await _connectionService.DoHandshakeAsync(peerEndpoint, request.Handshake); + } + catch (Exception e) { - try - { - Logger.LogDebug($"Peer {context.Peer} has requested a handshake."); - - if (context.AuthContext?.Properties != null) - { - foreach (var authProperty in context.AuthContext.Properties) - Logger.LogDebug($"Auth property: {authProperty.Name} -> {authProperty.Value}"); - } - - if(!GrpcEndPointHelper.ParseDnsEndPoint(context.Peer, out DnsEndPoint peerEndpoint)) - return new HandshakeReply { Error = HandshakeError.InvalidConnection}; - - return await _connectionService.DoHandshakeAsync(peerEndpoint, request.Handshake); - } - catch (Exception e) - { - Logger.LogWarning(e, $"Handshake failed - {context.Peer}: "); - throw; - } + Logger.LogWarning(e, $"Handshake failed - {context.Peer}: "); + throw; } + } - public override Task ConfirmHandshake(ConfirmHandshakeRequest request, - ServerCallContext context) + public override Task ConfirmHandshake(ConfirmHandshakeRequest request, + ServerCallContext context) + { + try { - try - { - Logger.LogDebug($"Peer {context.GetPeerInfo()} has requested a handshake confirmation."); + Logger.LogDebug($"Peer {context.GetPeerInfo()} has requested a handshake confirmation."); - _connectionService.ConfirmHandshake(context.GetPublicKey()); - } - catch (Exception e) - { - Logger.LogWarning(e, $"Confirm handshake error - {context.GetPeerInfo()}: "); - throw; - } - - return Task.FromResult(new VoidReply()); + _connectionService.ConfirmHandshake(context.GetPublicKey()); } - - public override async Task BlockBroadcastStream( - IAsyncStreamReader requestStream, ServerCallContext context) + catch (Exception e) { - Logger.LogDebug($"Block stream started with {context.GetPeerInfo()} - {context.Peer}."); + Logger.LogWarning(e, $"Confirm handshake error - {context.GetPeerInfo()}: "); + throw; + } - try - { - var peerPubkey = context.GetPublicKey(); - await requestStream.ForEachAsync(async block => await ProcessBlockAsync(block, peerPubkey)); - } - catch (Exception e) - { - Logger.LogError(e, $"Block stream error - {context.GetPeerInfo()}: "); - throw; - } + return Task.FromResult(new VoidReply()); + } - Logger.LogDebug($"Block stream finished with {context.GetPeerInfo()} - {context.Peer}."); + public override async Task BlockBroadcastStream( + IAsyncStreamReader requestStream, ServerCallContext context) + { + Logger.LogDebug($"Block stream started with {context.GetPeerInfo()} - {context.Peer}."); - return new VoidReply(); + try + { + var peerPubkey = context.GetPublicKey(); + await requestStream.ForEachAsync(async block => await ProcessBlockAsync(block, peerPubkey)); } - - private Task ProcessBlockAsync(BlockWithTransactions block, string peerPubkey) + catch (Exception e) { - var peer = TryGetPeerByPubkey(peerPubkey); + Logger.LogError(e, $"Block stream error - {context.GetPeerInfo()}: "); + throw; + } - if (peer.SyncState != SyncState.Finished) - { - peer.SyncState = SyncState.Finished; - } - - if (!peer.TryAddKnownBlock(block.GetHash())) - return Task.CompletedTask; - - _ = EventBus.PublishAsync(new BlockReceivedEvent(block, peerPubkey)); + Logger.LogDebug($"Block stream finished with {context.GetPeerInfo()} - {context.Peer}."); + + return new VoidReply(); + } + + private Task ProcessBlockAsync(BlockWithTransactions block, string peerPubkey) + { + var peer = TryGetPeerByPubkey(peerPubkey); + + if (peer.SyncState != SyncState.Finished) peer.SyncState = SyncState.Finished; + + if (!peer.TryAddKnownBlock(block.GetHash())) return Task.CompletedTask; - } - public override async Task AnnouncementBroadcastStream( - IAsyncStreamReader requestStream, ServerCallContext context) + _ = EventBus.PublishAsync(new BlockReceivedEvent(block, peerPubkey)); + return Task.CompletedTask; + } + + public override async Task AnnouncementBroadcastStream( + IAsyncStreamReader requestStream, ServerCallContext context) + { + Logger.LogDebug($"Announcement stream started with {context.GetPeerInfo()} - {context.Peer}."); + + try + { + var peerPubkey = context.GetPublicKey(); + await requestStream.ForEachAsync(async r => await ProcessAnnouncementAsync(r, peerPubkey)); + } + catch (Exception e) { - Logger.LogDebug($"Announcement stream started with {context.GetPeerInfo()} - {context.Peer}."); + Logger.LogError(e, $"Announcement stream error: {context.GetPeerInfo()}"); + throw; + } - try - { - var peerPubkey = context.GetPublicKey(); - await requestStream.ForEachAsync(async r => await ProcessAnnouncementAsync(r, peerPubkey)); - } - catch (Exception e) - { - Logger.LogError(e, $"Announcement stream error: {context.GetPeerInfo()}"); - throw; - } + Logger.LogDebug($"Announcement stream finished with {context.GetPeerInfo()} - {context.Peer}."); - Logger.LogDebug($"Announcement stream finished with {context.GetPeerInfo()} - {context.Peer}."); + return new VoidReply(); + } - return new VoidReply(); + private Task ProcessAnnouncementAsync(BlockAnnouncement announcement, string peerPubkey) + { + if (announcement?.BlockHash == null) + { + Logger.LogWarning($"Received null announcement or header from {peerPubkey}."); + return Task.CompletedTask; } - private Task ProcessAnnouncementAsync(BlockAnnouncement announcement, string peerPubkey) - { - if (announcement?.BlockHash == null) - { - Logger.LogWarning($"Received null announcement or header from {peerPubkey}."); - return Task.CompletedTask; - } + var peer = TryGetPeerByPubkey(peerPubkey); - var peer = TryGetPeerByPubkey(peerPubkey); + if (!peer.TryAddKnownBlock(announcement.BlockHash)) + return Task.CompletedTask; - if (!peer.TryAddKnownBlock(announcement.BlockHash)) - return Task.CompletedTask; + if (peer.SyncState != SyncState.Finished) peer.SyncState = SyncState.Finished; - if (peer.SyncState != SyncState.Finished) - { - peer.SyncState = SyncState.Finished; - } + _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, peerPubkey)); - _ = EventBus.PublishAsync(new AnnouncementReceivedEventData(announcement, peerPubkey)); + return Task.CompletedTask; + } - return Task.CompletedTask; - } + public override async Task TransactionBroadcastStream(IAsyncStreamReader requestStream, + ServerCallContext context) + { + Logger.LogDebug($"Transaction stream started with {context.GetPeerInfo()} - {context.Peer}."); - public override async Task TransactionBroadcastStream(IAsyncStreamReader requestStream, - ServerCallContext context) + try { - Logger.LogDebug($"Transaction stream started with {context.GetPeerInfo()} - {context.Peer}."); + var peerPubkey = context.GetPublicKey(); + await requestStream.ForEachAsync(async tx => await ProcessTransactionAsync(tx, peerPubkey)); + } + catch (Exception e) + { + Logger.LogError(e, $"Transaction stream error - {context.GetPeerInfo()}: "); + throw; + } - try - { - var peerPubkey = context.GetPublicKey(); - await requestStream.ForEachAsync(async tx => await ProcessTransactionAsync(tx, peerPubkey)); - } - catch (Exception e) - { - Logger.LogError(e, $"Transaction stream error - {context.GetPeerInfo()}: "); - throw; - } + Logger.LogDebug($"Transaction stream finished with {context.GetPeerInfo()} - {context.Peer}."); - Logger.LogDebug($"Transaction stream finished with {context.GetPeerInfo()} - {context.Peer}."); + return new VoidReply(); + } - return new VoidReply(); - } + private async Task ProcessTransactionAsync(Transaction tx, string peerPubkey) + { + var chain = await _blockchainService.GetChainAsync(); - private async Task ProcessTransactionAsync(Transaction tx, string peerPubkey) - { - var chain = await _blockchainService.GetChainAsync(); + // if this transaction's ref block is a lot higher than our chain + // then don't participate in p2p network + if (tx.RefBlockNumber > chain.LongestChainHeight + NetworkConstants.DefaultInitialSyncOffset) + return; - // if this transaction's ref block is a lot higher than our chain - // then don't participate in p2p network - if (tx.RefBlockNumber > chain.LongestChainHeight + NetworkConstants.DefaultInitialSyncOffset) - return; + var peer = TryGetPeerByPubkey(peerPubkey); - var peer = TryGetPeerByPubkey(peerPubkey); + if (!peer.TryAddKnownTransaction(tx.GetHash())) + return; - if (!peer.TryAddKnownTransaction(tx.GetHash())) - return; - - _ = EventBus.PublishAsync(new TransactionsReceivedEvent {Transactions = new List {tx}}); - } + _ = EventBus.PublishAsync(new TransactionsReceivedEvent { Transactions = new List { tx } }); + } + + public override async Task LibAnnouncementBroadcastStream( + IAsyncStreamReader requestStream, ServerCallContext context) + { + Logger.LogDebug($"Lib announcement stream started with {context.GetPeerInfo()} - {context.Peer}."); - public override async Task LibAnnouncementBroadcastStream( - IAsyncStreamReader requestStream, ServerCallContext context) + try + { + var peerPubkey = context.GetPublicKey(); + await requestStream.ForEachAsync(async r => await ProcessLibAnnouncementAsync(r, peerPubkey)); + } + catch (Exception e) { - Logger.LogDebug($"Lib announcement stream started with {context.GetPeerInfo()} - {context.Peer}."); + Logger.LogError(e, $"Lib announcement stream error: {context.GetPeerInfo()}"); + throw; + } - try - { - var peerPubkey = context.GetPublicKey(); - await requestStream.ForEachAsync(async r => await ProcessLibAnnouncementAsync(r, peerPubkey)); - } - catch (Exception e) - { - Logger.LogError(e, $"Lib announcement stream error: {context.GetPeerInfo()}"); - throw; - } + Logger.LogDebug($"Lib announcement stream finished with {context.GetPeerInfo()} - {context.Peer}."); - Logger.LogDebug($"Lib announcement stream finished with {context.GetPeerInfo()} - {context.Peer}."); + return new VoidReply(); + } - return new VoidReply(); + public Task ProcessLibAnnouncementAsync(LibAnnouncement announcement, string peerPubkey) + { + if (announcement?.LibHash == null) + { + Logger.LogWarning($"Received null or empty announcement from {peerPubkey}."); + return Task.CompletedTask; } - public Task ProcessLibAnnouncementAsync(LibAnnouncement announcement, string peerPubkey) - { - if (announcement?.LibHash == null) - { - Logger.LogWarning($"Received null or empty announcement from {peerPubkey}."); - return Task.CompletedTask; - } + Logger.LogDebug( + $"Received lib announce hash: {announcement.LibHash}, height {announcement.LibHeight} from {peerPubkey}."); - Logger.LogDebug( - $"Received lib announce hash: {announcement.LibHash}, height {announcement.LibHeight} from {peerPubkey}."); + var peer = TryGetPeerByPubkey(peerPubkey); - var peer = TryGetPeerByPubkey(peerPubkey); + peer.UpdateLastKnownLib(announcement); - peer.UpdateLastKnownLib(announcement); + if (peer.SyncState != SyncState.Finished) peer.SyncState = SyncState.Finished; - if (peer.SyncState != SyncState.Finished) - { - peer.SyncState = SyncState.Finished; - } + return Task.CompletedTask; + } - return Task.CompletedTask; - } + /// + /// This method returns a block. The parameter is a object, if the value + /// of is not null, the request is by ID, otherwise it will be + /// by height. + /// + public override async Task RequestBlock(BlockRequest request, ServerCallContext context) + { + if (request == null || request.Hash == null || _syncStateService.SyncState != SyncState.Finished) + return new BlockReply(); - /// - /// This method returns a block. The parameter is a object, if the value - /// of is not null, the request is by ID, otherwise it will be - /// by height. - /// - public override async Task RequestBlock(BlockRequest request, ServerCallContext context) - { - if (request == null || request.Hash == null || _syncStateService.SyncState != SyncState.Finished) - return new BlockReply(); + Logger.LogDebug($"Peer {context.GetPeerInfo()} requested block {request.Hash}."); - Logger.LogDebug($"Peer {context.GetPeerInfo()} requested block {request.Hash}."); + BlockWithTransactions block; + try + { + block = await _blockchainService.GetBlockWithTransactionsByHashAsync(request.Hash); - BlockWithTransactions block; - try + if (block == null) { - block = await _blockchainService.GetBlockWithTransactionsByHashAsync(request.Hash); - - if (block == null) - { - Logger.LogDebug($"Could not find block {request.Hash} for {context.GetPeerInfo()}."); - } - else - { - var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey()); - peer.TryAddKnownBlock(block.GetHash()); - } + Logger.LogDebug($"Could not find block {request.Hash} for {context.GetPeerInfo()}."); } - catch (Exception e) + else { - Logger.LogWarning(e, $"Request block error: {context.GetPeerInfo()}"); - throw; + var peer = _connectionService.GetPeerByPubkey(context.GetPublicKey()); + peer.TryAddKnownBlock(block.GetHash()); } - - return new BlockReply {Block = block}; } - - public override async Task RequestBlocks(BlocksRequest request, ServerCallContext context) + catch (Exception e) { - if (request == null || - request.PreviousBlockHash == null || - _syncStateService.SyncState != SyncState.Finished || - request.Count == 0 || - request.Count > GrpcConstants.MaxSendBlockCountLimit) - { - return new BlockList(); - } + Logger.LogWarning(e, $"Request block error: {context.GetPeerInfo()}"); + throw; + } - Logger.LogDebug( - $"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}."); + return new BlockReply { Block = block }; + } - var blockList = new BlockList(); + public override async Task RequestBlocks(BlocksRequest request, ServerCallContext context) + { + if (request == null || + request.PreviousBlockHash == null || + _syncStateService.SyncState != SyncState.Finished || + request.Count == 0 || + request.Count > GrpcConstants.MaxSendBlockCountLimit) + return new BlockList(); - try - { - var blocks = - await _blockchainService.GetBlocksWithTransactionsAsync(request.PreviousBlockHash, request.Count); + Logger.LogDebug( + $"Peer {context.GetPeerInfo()} requested {request.Count} blocks from {request.PreviousBlockHash}."); - blockList.Blocks.AddRange(blocks); + var blockList = new BlockList(); - if (NetworkOptions.CompressBlocksOnRequest) - { - var headers = new Metadata - {new Metadata.Entry(GrpcConstants.GrpcRequestCompressKey, GrpcConstants.GrpcGzipConst)}; - await context.WriteResponseHeadersAsync(headers); - } + try + { + var blocks = + await _blockchainService.GetBlocksWithTransactionsAsync(request.PreviousBlockHash, request.Count); - Logger.LogDebug( - $"Replied to {context.GetPeerInfo()} with {blockList.Blocks.Count}, request was {request}"); - } - catch (Exception e) + blockList.Blocks.AddRange(blocks); + + if (NetworkOptions.CompressBlocksOnRequest) { - Logger.LogWarning(e, $"Request blocks error - {context.GetPeerInfo()} - request {request}: "); - throw; + var headers = new Metadata + { new(GrpcConstants.GrpcRequestCompressKey, GrpcConstants.GrpcGzipConst) }; + await context.WriteResponseHeadersAsync(headers); } - return blockList; + Logger.LogDebug( + $"Replied to {context.GetPeerInfo()} with {blockList.Blocks.Count}, request was {request}"); } - - public override async Task GetNodes(NodesRequest request, ServerCallContext context) + catch (Exception e) { - if (request == null) - return new NodeList(); + Logger.LogWarning(e, $"Request blocks error - {context.GetPeerInfo()} - request {request}: "); + throw; + } - var nodesCount = Math.Min(request.MaxCount, GrpcConstants.DefaultDiscoveryMaxNodesToResponse); - Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {nodesCount} nodes."); + return blockList; + } - NodeList nodes; - try - { - nodes = await _nodeManager.GetRandomNodesAsync(nodesCount); - } - catch (Exception e) - { - Logger.LogWarning(e, "Get nodes error: "); - throw; - } + public override async Task GetNodes(NodesRequest request, ServerCallContext context) + { + if (request == null) + return new NodeList(); - Logger.LogDebug($"Sending {nodes.Nodes.Count} to {context.GetPeerInfo()}."); + var nodesCount = Math.Min(request.MaxCount, GrpcConstants.DefaultDiscoveryMaxNodesToResponse); + Logger.LogDebug($"Peer {context.GetPeerInfo()} requested {nodesCount} nodes."); - return nodes; + NodeList nodes; + try + { + nodes = await _nodeManager.GetRandomNodesAsync(nodesCount); } - - public override Task Ping(PingRequest request, ServerCallContext context) + catch (Exception e) { - return Task.FromResult(new PongReply()); + Logger.LogWarning(e, "Get nodes error: "); + throw; } - public override Task CheckHealth(HealthCheckRequest request, ServerCallContext context) + Logger.LogDebug($"Sending {nodes.Nodes.Count} to {context.GetPeerInfo()}."); + + return nodes; + } + + public override Task Ping(PingRequest request, ServerCallContext context) + { + return Task.FromResult(new PongReply()); + } + + public override Task CheckHealth(HealthCheckRequest request, ServerCallContext context) + { + return Task.FromResult(new HealthCheckReply()); + } + + /// + /// Clients should call this method to disconnect explicitly. + /// + public override async Task Disconnect(DisconnectReason request, ServerCallContext context) + { + Logger.LogDebug($"Peer {context.GetPeerInfo()} has sent a disconnect request."); + + try { - return Task.FromResult(new HealthCheckReply()); + await _connectionService.RemovePeerAsync(context.GetPublicKey()); } - - /// - /// Clients should call this method to disconnect explicitly. - /// - public override async Task Disconnect(DisconnectReason request, ServerCallContext context) + catch (Exception e) { - Logger.LogDebug($"Peer {context.GetPeerInfo()} has sent a disconnect request."); + Logger.LogError(e, "Disconnect error: "); + throw; + } - try - { - await _connectionService.RemovePeerAsync(context.GetPublicKey()); - } - catch (Exception e) - { - Logger.LogError(e, "Disconnect error: "); - throw; - } + return new VoidReply(); + } - return new VoidReply(); - } + /// + /// Try to get the peer based on pubkey. + /// + /// + /// + /// + /// If the peer does not exist, a cancelled RPC exception is thrown to tell the client. + /// Need to verify the existence of the peer here, + /// because when we start transferring data using the streaming RPC, + /// the request no longer goes through the . + /// + private GrpcPeer TryGetPeerByPubkey(string peerPubkey) + { + var peer = _connectionService.GetPeerByPubkey(peerPubkey); - /// - /// Try to get the peer based on pubkey. - /// - /// - /// - /// - /// If the peer does not exist, a cancelled RPC exception is thrown to tell the client. - /// Need to verify the existence of the peer here, - /// because when we start transferring data using the streaming RPC, - /// the request no longer goes through the . - /// - private GrpcPeer TryGetPeerByPubkey(string peerPubkey) - { - var peer = _connectionService.GetPeerByPubkey(peerPubkey); + if (peer != null) + return peer; - if (peer != null) - return peer; - - Logger.LogDebug($"Peer: {peerPubkey} already removed."); - throw new RpcException(Status.DefaultCancelled); - } + Logger.LogDebug($"Peer: {peerPubkey} already removed."); + throw new RpcException(Status.DefaultCancelled); } } \ No newline at end of file diff --git a/src/AElf.OS.Network.Grpc/StreamJob.cs b/src/AElf.OS.Network.Grpc/StreamJob.cs index 84c48aa1db..02f3b8098a 100644 --- a/src/AElf.OS.Network.Grpc/StreamJob.cs +++ b/src/AElf.OS.Network.Grpc/StreamJob.cs @@ -2,14 +2,13 @@ using AElf.OS.Network.Application; using AElf.Types; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class StreamJob { - public class StreamJob - { - public Transaction Transaction { get; set; } - public BlockAnnouncement BlockAnnouncement { get; set; } - public BlockWithTransactions BlockWithTransactions { get; set; } - public LibAnnouncement LibAnnouncement { get; set; } - public Action SendCallback { get; set; } - } + public Transaction Transaction { get; set; } + public BlockAnnouncement BlockAnnouncement { get; set; } + public BlockWithTransactions BlockWithTransactions { get; set; } + public LibAnnouncement LibAnnouncement { get; set; } + public Action SendCallback { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/AElf.OS.csproj b/src/AElf.OS/AElf.OS.csproj index 48fb4f2abe..c155aa5ca3 100644 --- a/src/AElf.OS/AElf.OS.csproj +++ b/src/AElf.OS/AElf.OS.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,13 +9,13 @@ - - + + - - + + diff --git a/src/AElf.OS/Account/Application/AccountService.cs b/src/AElf.OS/Account/Application/AccountService.cs index ab51790357..9e2e2400d4 100644 --- a/src/AElf.OS/Account/Application/AccountService.cs +++ b/src/AElf.OS/Account/Application/AccountService.cs @@ -7,74 +7,73 @@ using AElf.Types; using Microsoft.Extensions.Options; -namespace AElf.OS.Account.Application +namespace AElf.OS.Account.Application; + +public class AccountService : IAccountService { - public class AccountService : IAccountService - { - private readonly IKeyStore _keyStore; - private readonly AccountOptions _accountOptions; + private readonly AccountOptions _accountOptions; + private readonly IKeyStore _keyStore; - public AccountService(IKeyStore keyStore, IOptionsSnapshot options) - { - _keyStore = keyStore; - _accountOptions = options.Value; - } + public AccountService(IKeyStore keyStore, IOptionsSnapshot options) + { + _keyStore = keyStore; + _accountOptions = options.Value; + } - public async Task SignAsync(byte[] data) - { - var signature = CryptoHelper.SignWithPrivateKey((await GetAccountKeyPairAsync()).PrivateKey, data); - return signature; - } + public async Task SignAsync(byte[] data) + { + var signature = CryptoHelper.SignWithPrivateKey((await GetAccountKeyPairAsync()).PrivateKey, data); + return signature; + } - public async Task GetPublicKeyAsync() - { - return (await GetAccountKeyPairAsync()).PublicKey; - } + public async Task GetPublicKeyAsync() + { + return (await GetAccountKeyPairAsync()).PublicKey; + } - public async Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage) - { - return CryptoHelper.EncryptMessage((await GetAccountKeyPairAsync()).PrivateKey, receiverPublicKey, - plainMessage); - } + public async Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage) + { + return CryptoHelper.EncryptMessage((await GetAccountKeyPairAsync()).PrivateKey, receiverPublicKey, + plainMessage); + } - public async Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage) - { - return CryptoHelper.DecryptMessage(senderPublicKey, (await GetAccountKeyPairAsync()).PrivateKey, - cipherMessage); - } + public async Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage) + { + return CryptoHelper.DecryptMessage(senderPublicKey, (await GetAccountKeyPairAsync()).PrivateKey, + cipherMessage); + } - public async Task
GetAccountAsync() - { - var publicKey = (await GetAccountKeyPairAsync()).PublicKey; - return Address.FromPublicKey(publicKey); - } + public async Task
GetAccountAsync() + { + var publicKey = (await GetAccountKeyPairAsync()).PublicKey; + return Address.FromPublicKey(publicKey); + } - private async Task GetAccountKeyPairAsync() + private async Task GetAccountKeyPairAsync() + { + var nodeAccount = _accountOptions.NodeAccount; + var nodePassword = _accountOptions.NodeAccountPassword ?? string.Empty; + if (string.IsNullOrWhiteSpace(nodeAccount)) { - var nodeAccount = _accountOptions.NodeAccount; - var nodePassword = _accountOptions.NodeAccountPassword ?? string.Empty; - if (string.IsNullOrWhiteSpace(nodeAccount)) + var accountList = await _keyStore.GetAccountsAsync(); + if (accountList.Count == 0) { - var accountList = await _keyStore.GetAccountsAsync(); - if (accountList.Count == 0) - { - var keyPair = await _keyStore.CreateAccountKeyPairAsync(nodePassword); - nodeAccount = Address.FromPublicKey(keyPair.PublicKey).ToBase58(); - } - else - { - nodeAccount = accountList.First(); - } + var keyPair = await _keyStore.CreateAccountKeyPairAsync(nodePassword); + nodeAccount = Address.FromPublicKey(keyPair.PublicKey).ToBase58(); } - - var accountKeyPair = _keyStore.GetAccountKeyPair(nodeAccount); - if (accountKeyPair == null) + else { - await _keyStore.UnlockAccountAsync(nodeAccount, nodePassword); - accountKeyPair = _keyStore.GetAccountKeyPair(nodeAccount); + nodeAccount = accountList.First(); } + } - return accountKeyPair; + var accountKeyPair = _keyStore.GetAccountKeyPair(nodeAccount); + if (accountKeyPair == null) + { + await _keyStore.UnlockAccountAsync(nodeAccount, nodePassword); + accountKeyPair = _keyStore.GetAccountKeyPair(nodeAccount); } + + return accountKeyPair; } } \ No newline at end of file diff --git a/src/AElf.OS/Account/Infrastructure/AElfKeyStore.cs b/src/AElf.OS/Account/Infrastructure/AElfKeyStore.cs index ea767b4a99..4fa998a9bd 100644 --- a/src/AElf.OS/Account/Infrastructure/AElfKeyStore.cs +++ b/src/AElf.OS/Account/Infrastructure/AElfKeyStore.cs @@ -1,8 +1,6 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading; using System.Threading.Tasks; using AElf.Cryptography; using AElf.Cryptography.ECDSA; @@ -11,161 +9,159 @@ using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; using Nethereum.KeyStore; using Nethereum.KeyStore.Crypto; +using Volo.Abp.DependencyInjection; + +namespace AElf.OS.Account.Infrastructure; -namespace AElf.OS.Account.Infrastructure +public class AElfKeyStore : IKeyStore, ISingletonDependency { - public class AElfKeyStore : IKeyStore, ISingletonDependency + private const string KeyFileExtension = ".json"; + private const string KeyFolderName = "keys"; + private readonly KeyStoreService _keyStoreService; + private readonly INodeEnvironmentService _nodeEnvironmentService; + + private readonly List _unlockedAccounts; + + public AElfKeyStore(INodeEnvironmentService nodeEnvironmentService) { - private readonly INodeEnvironmentService _nodeEnvironmentService; + _nodeEnvironmentService = nodeEnvironmentService; + _unlockedAccounts = new List(); + _keyStoreService = new KeyStoreService(); - private const string KeyFileExtension = ".json"; - private const string KeyFolderName = "keys"; + Logger = NullLogger.Instance; + } - private readonly List _unlockedAccounts; - private readonly KeyStoreService _keyStoreService; - - public ILogger Logger { get; set; } - - public AElfKeyStore(INodeEnvironmentService nodeEnvironmentService) - { - _nodeEnvironmentService = nodeEnvironmentService; - _unlockedAccounts = new List(); - _keyStoreService = new KeyStoreService(); - - Logger = NullLogger.Instance; - } - - public async Task UnlockAccountAsync(string address, string password) - { - try - { - if (_unlockedAccounts.Any(x => x.AccountName == address)) - return AccountError.AccountAlreadyUnlocked; + public ILogger Logger { get; set; } - var keyPair = await ReadKeyPairAsync(address, password); - var unlockedAccount = new Account(address) {KeyPair = keyPair}; + public async Task UnlockAccountAsync(string address, string password) + { + try + { + if (_unlockedAccounts.Any(x => x.AccountName == address)) + return AccountError.AccountAlreadyUnlocked; - _unlockedAccounts.Add(unlockedAccount); - } - catch (InvalidPasswordException ex) - { - Logger.LogError(ex, "Invalid password: "); - return AccountError.WrongPassword; - } - catch (KeyStoreNotFoundException ex) - { - Logger.LogError(ex, "Could not load account:"); - return AccountError.AccountFileNotFound; - } + var keyPair = await ReadKeyPairAsync(address, password); + var unlockedAccount = new Account(address) { KeyPair = keyPair }; - return AccountError.None; + _unlockedAccounts.Add(unlockedAccount); } - - public ECKeyPair GetAccountKeyPair(string address) + catch (InvalidPasswordException ex) { - return _unlockedAccounts.FirstOrDefault(oa => oa.AccountName == address)?.KeyPair; + Logger.LogError(ex, "Invalid password: "); + return AccountError.WrongPassword; } - - public async Task CreateAccountKeyPairAsync(string password) + catch (KeyStoreNotFoundException ex) { - var keyPair = CryptoHelper.GenerateKeyPair(); - var res = await WriteKeyPairAsync(keyPair, password); - return !res ? null : keyPair; + Logger.LogError(ex, "Could not load account:"); + return AccountError.AccountFileNotFound; } - public async Task> GetAccountsAsync() - { - var dir = CreateKeystoreDirectory(); - var files = dir.GetFiles("*" + KeyFileExtension); - - return await Task.Run(() => files.Select(f => Path.GetFileNameWithoutExtension(f.Name)).ToList()); - } + return AccountError.None; + } - public async Task ReadKeyPairAsync(string address, string password) - { - try - { - var keyFilePath = GetKeyFileFullPath(address); - var privateKey = await Task.Run(() => - { - using (var textReader = File.OpenText(keyFilePath)) - { - var json = textReader.ReadToEnd(); - return _keyStoreService.DecryptKeyStoreFromJson(password, json); - } - }); - - return CryptoHelper.FromPrivateKey(privateKey); - } - catch (FileNotFoundException ex) - { - throw new KeyStoreNotFoundException("Keystore file not found.", ex); - } - catch (DirectoryNotFoundException ex) - { - throw new KeyStoreNotFoundException("Invalid keystore path.", ex); - } - catch (DecryptionException ex) - { - throw new InvalidPasswordException("Invalid password.", ex); - } - } + public ECKeyPair GetAccountKeyPair(string address) + { + return _unlockedAccounts.FirstOrDefault(oa => oa.AccountName == address)?.KeyPair; + } - private async Task WriteKeyPairAsync(ECKeyPair keyPair, string password) - { - if (keyPair?.PrivateKey == null || keyPair.PublicKey == null) - throw new InvalidKeyPairException("Invalid keypair (null reference).", null); + public async Task CreateAccountKeyPairAsync(string password) + { + var keyPair = CryptoHelper.GenerateKeyPair(); + var res = await WriteKeyPairAsync(keyPair, password); + return !res ? null : keyPair; + } - // Ensure path exists - CreateKeystoreDirectory(); + public async Task> GetAccountsAsync() + { + var dir = CreateKeystoreDirectory(); + var files = dir.GetFiles("*" + KeyFileExtension); - var address = Address.FromPublicKey(keyPair.PublicKey); - var fullPath = GetKeyFileFullPath(address.ToBase58()); + return await Task.Run(() => files.Select(f => Path.GetFileNameWithoutExtension(f.Name)).ToList()); + } - await Task.Run(() => + public async Task ReadKeyPairAsync(string address, string password) + { + try + { + var keyFilePath = GetKeyFileFullPath(address); + var privateKey = await Task.Run(() => { - using (var writer = File.CreateText(fullPath)) + using (var textReader = File.OpenText(keyFilePath)) { - var scryptResult = _keyStoreService.EncryptAndGenerateDefaultKeyStoreAsJson(password, - keyPair.PrivateKey, - address.ToBase58()); - writer.Write(scryptResult); - writer.Flush(); + var json = textReader.ReadToEnd(); + return _keyStoreService.DecryptKeyStoreFromJson(password, json); } }); - - return true; - } - /// - /// Return the full path of the files - /// - private string GetKeyFileFullPath(string address) + return CryptoHelper.FromPrivateKey(privateKey); + } + catch (FileNotFoundException ex) { - var path = GetKeyFileFullPathStrict(address); - return File.Exists(path) ? path : GetKeyFileFullPathStrict(address); + throw new KeyStoreNotFoundException("Keystore file not found.", ex); } - - private string GetKeyFileFullPathStrict(string address) + catch (DirectoryNotFoundException ex) { - var dirPath = GetKeystoreDirectoryPath(); - var filePath = Path.Combine(dirPath, address); - var filePathWithExtension = Path.ChangeExtension(filePath, KeyFileExtension); - return filePathWithExtension; + throw new KeyStoreNotFoundException("Invalid keystore path.", ex); } - - private DirectoryInfo CreateKeystoreDirectory() + catch (DecryptionException ex) { - var dirPath = GetKeystoreDirectoryPath(); - return Directory.CreateDirectory(dirPath); + throw new InvalidPasswordException("Invalid password.", ex); } + } + + private async Task WriteKeyPairAsync(ECKeyPair keyPair, string password) + { + if (keyPair?.PrivateKey == null || keyPair.PublicKey == null) + throw new InvalidKeyPairException("Invalid keypair (null reference).", null); + + // Ensure path exists + CreateKeystoreDirectory(); - private string GetKeystoreDirectoryPath() + var address = Address.FromPublicKey(keyPair.PublicKey); + var fullPath = GetKeyFileFullPath(address.ToBase58()); + + await Task.Run(() => { - return Path.Combine(_nodeEnvironmentService.GetAppDataPath(), KeyFolderName); - } + using (var writer = File.CreateText(fullPath)) + { + var scryptResult = _keyStoreService.EncryptAndGenerateDefaultKeyStoreAsJson(password, + keyPair.PrivateKey, + address.ToBase58()); + writer.Write(scryptResult); + writer.Flush(); + } + }); + + return true; + } + + /// + /// Return the full path of the files + /// + private string GetKeyFileFullPath(string address) + { + var path = GetKeyFileFullPathStrict(address); + return File.Exists(path) ? path : GetKeyFileFullPathStrict(address); + } + + private string GetKeyFileFullPathStrict(string address) + { + var dirPath = GetKeystoreDirectoryPath(); + var filePath = Path.Combine(dirPath, address); + var filePathWithExtension = Path.ChangeExtension(filePath, KeyFileExtension); + return filePathWithExtension; + } + + private DirectoryInfo CreateKeystoreDirectory() + { + var dirPath = GetKeystoreDirectoryPath(); + return Directory.CreateDirectory(dirPath); + } + + private string GetKeystoreDirectoryPath() + { + return Path.Combine(_nodeEnvironmentService.GetAppDataPath(), KeyFolderName); } } \ No newline at end of file diff --git a/src/AElf.OS/Account/Infrastructure/Account.cs b/src/AElf.OS/Account/Infrastructure/Account.cs index f207b76258..62d3b870ac 100644 --- a/src/AElf.OS/Account/Infrastructure/Account.cs +++ b/src/AElf.OS/Account/Infrastructure/Account.cs @@ -1,16 +1,14 @@ -using System.Threading; -using AElf.Cryptography.ECDSA; +using AElf.Cryptography.ECDSA; -namespace AElf.OS.Account.Infrastructure +namespace AElf.OS.Account.Infrastructure; + +public class Account { - public class Account + public Account(string address) { - public ECKeyPair KeyPair { get; set; } - public string AccountName { get; } - - public Account(string address) - { - AccountName = address; - } + AccountName = address; } + + public ECKeyPair KeyPair { get; set; } + public string AccountName { get; } } \ No newline at end of file diff --git a/src/AElf.OS/Account/Infrastructure/AccountError.cs b/src/AElf.OS/Account/Infrastructure/AccountError.cs index 7dca283345..327cba0311 100644 --- a/src/AElf.OS/Account/Infrastructure/AccountError.cs +++ b/src/AElf.OS/Account/Infrastructure/AccountError.cs @@ -1,10 +1,9 @@ -namespace AElf.OS.Account.Infrastructure +namespace AElf.OS.Account.Infrastructure; + +public enum AccountError { - public enum AccountError - { - None = 0, - AccountAlreadyUnlocked = 1, - WrongPassword = 2, - AccountFileNotFound = 3 - } + None = 0, + AccountAlreadyUnlocked = 1, + WrongPassword = 2, + AccountFileNotFound = 3 } \ No newline at end of file diff --git a/src/AElf.OS/Account/Infrastructure/IKeyStore.cs b/src/AElf.OS/Account/Infrastructure/IKeyStore.cs index 57b22182c2..a4ae322482 100644 --- a/src/AElf.OS/Account/Infrastructure/IKeyStore.cs +++ b/src/AElf.OS/Account/Infrastructure/IKeyStore.cs @@ -2,16 +2,15 @@ using System.Threading.Tasks; using AElf.Cryptography.ECDSA; -namespace AElf.OS.Account.Infrastructure +namespace AElf.OS.Account.Infrastructure; + +public interface IKeyStore { - public interface IKeyStore - { - Task UnlockAccountAsync(string address, string password); + Task UnlockAccountAsync(string address, string password); - ECKeyPair GetAccountKeyPair(string address); + ECKeyPair GetAccountKeyPair(string address); - Task CreateAccountKeyPairAsync(string password); + Task CreateAccountKeyPairAsync(string password); - Task> GetAccountsAsync(); - } + Task> GetAccountsAsync(); } \ No newline at end of file diff --git a/src/AElf.OS/Account/Infrastructure/Password.cs b/src/AElf.OS/Account/Infrastructure/Password.cs index 2201620301..a76aab8c35 100644 --- a/src/AElf.OS/Account/Infrastructure/Password.cs +++ b/src/AElf.OS/Account/Infrastructure/Password.cs @@ -1,19 +1,18 @@ using Org.BouncyCastle.OpenSsl; -namespace AElf.OS.Account.Infrastructure +namespace AElf.OS.Account.Infrastructure; + +public class Password : IPasswordFinder { - public class Password : IPasswordFinder - { - private readonly char[] _password; + private readonly char[] _password; - public Password(char[] word) - { - _password = (char[]) word.Clone(); - } + public Password(char[] word) + { + _password = (char[])word.Clone(); + } - public char[] GetPassword() - { - return (char[]) _password.Clone(); - } + public char[] GetPassword() + { + return (char[])_password.Clone(); } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockDownloadService.cs b/src/AElf.OS/BlockSync/Application/BlockDownloadService.cs index bf2bd66c4a..bd540b59f1 100644 --- a/src/AElf.OS/BlockSync/Application/BlockDownloadService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockDownloadService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -16,304 +15,293 @@ using Volo.Abp; using Volo.Abp.EventBus.Local; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockDownloadService : IBlockDownloadService { - public class BlockDownloadService : IBlockDownloadService + /// + /// Make sure we have enough peers to check the block hash + /// + private const int PeerCheckMinimumCount = 15; + + private readonly IBlockSyncAttachService _blockSyncAttachService; + private readonly IBlockSyncQueueService _blockSyncQueueService; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly INetworkService _networkService; + + public BlockDownloadService(INetworkService networkService, + IBlockSyncAttachService blockSyncAttachService, + IBlockSyncQueueService blockSyncQueueService, + IBlockSyncStateProvider blockSyncStateProvider) { - private readonly INetworkService _networkService; - private readonly IBlockSyncAttachService _blockSyncAttachService; - private readonly IBlockSyncQueueService _blockSyncQueueService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; - public ILocalEventBus LocalEventBus { get; set; } + _networkService = networkService; + _blockSyncAttachService = blockSyncAttachService; + _blockSyncQueueService = blockSyncQueueService; + _blockSyncStateProvider = blockSyncStateProvider; + } - public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } - /// - /// Make sure we have enough peers to check the block hash - /// - private const int PeerCheckMinimumCount = 15; + public ILogger Logger { get; set; } - public BlockDownloadService(INetworkService networkService, - IBlockSyncAttachService blockSyncAttachService, - IBlockSyncQueueService blockSyncQueueService, - IBlockSyncStateProvider blockSyncStateProvider) - { - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; + /// + /// Download and attach blocks + /// UseSuggestedPeer == true: Download blocks from suggested peer directly; + /// Target download height > peer lib height, download blocks from suggested peer; + /// Target download height <= peer lib height, select a random peer to download. + /// + /// + /// + public async Task DownloadBlocksAsync(DownloadBlockDto downloadBlockDto) + { + var downloadResult = new DownloadBlocksResult(); + var peerPubkey = downloadBlockDto.SuggestedPeerPubkey; - _networkService = networkService; - _blockSyncAttachService = blockSyncAttachService; - _blockSyncQueueService = blockSyncQueueService; - _blockSyncStateProvider = blockSyncStateProvider; - } + if (!IsPeerAvailable(peerPubkey)) return downloadResult; - /// - /// Download and attach blocks - /// UseSuggestedPeer == true: Download blocks from suggested peer directly; - /// Target download height > peer lib height, download blocks from suggested peer; - /// Target download height <= peer lib height, select a random peer to download. - /// - /// - /// - public async Task DownloadBlocksAsync(DownloadBlockDto downloadBlockDto) + try { - var downloadResult = new DownloadBlocksResult(); - var peerPubkey = downloadBlockDto.SuggestedPeerPubkey; - - if (!IsPeerAvailable(peerPubkey)) + if (UseSuggestedPeer(downloadBlockDto)) { - return downloadResult; + downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); } - - try + else { - if (UseSuggestedPeer(downloadBlockDto)) + // If cannot get the blocks, there should be network problems or abnormal peer, + // because we have selected peer with lib height greater than or equal to the target height. + // 1. network problems, need to retry from other peer. + // 2. not network problems, this peer or the last peer is abnormal peer, we need to remove it. + var downloadTargetHeight = + downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount; + var exceptedPeers = new List { _blockSyncStateProvider.LastRequestPeerPubkey }; + var retryTimes = 2; + + while (true) { - downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); - } - else - { - // If cannot get the blocks, there should be network problems or abnormal peer, - // because we have selected peer with lib height greater than or equal to the target height. - // 1. network problems, need to retry from other peer. - // 2. not network problems, this peer or the last peer is abnormal peer, we need to remove it. - var downloadTargetHeight = - downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount; - var exceptedPeers = new List {_blockSyncStateProvider.LastRequestPeerPubkey}; - var retryTimes = 2; - - while (true) - { - peerPubkey = GetRandomPeerPubkey(downloadBlockDto.SuggestedPeerPubkey, downloadTargetHeight, - exceptedPeers); + peerPubkey = GetRandomPeerPubkey(downloadBlockDto.SuggestedPeerPubkey, downloadTargetHeight, + exceptedPeers); - downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); - - if (downloadResult.Success || retryTimes <= 0) - break; + downloadResult = await DownloadBlocksAsync(peerPubkey, downloadBlockDto); - exceptedPeers.Add(peerPubkey); - retryTimes--; - } + if (downloadResult.Success || retryTimes <= 0) + break; - if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) - { - await CheckAbnormalPeerAsync(peerPubkey, downloadBlockDto.PreviousBlockHash, - downloadBlockDto.PreviousBlockHeight); - } + exceptedPeers.Add(peerPubkey); + retryTimes--; } + + if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) + await CheckAbnormalPeerAsync(peerPubkey, downloadBlockDto.PreviousBlockHash, + downloadBlockDto.PreviousBlockHeight); } - catch (BlockDownloadException e) + } + catch (BlockDownloadException e) + { + await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData { - await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData - { - BlockHash = e.BlockHash, - BlockHeight = e.BlockHeight, - PeerPubkey = e.PeerPubkey - }); - } - - return downloadResult; + BlockHash = e.BlockHash, + BlockHeight = e.BlockHeight, + PeerPubkey = e.PeerPubkey + }); } - private bool IsPeerAvailable(string peerPubkey) + return downloadResult; + } + + public bool ValidateQueueAvailabilityBeforeDownload() + { + if (!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName)) { - return _networkService.GetPeerByPubkey(peerPubkey) != null; + Logger.LogWarning("Block sync attach queue is too busy."); + return false; } - /// - /// Ask all of peers to check the irreversible block hash is correct. - /// - /// - /// - /// - /// Null: No enough results to known if it's correct - /// True: More than 2/3 peers say is correct - /// False: More than 2/3 peers say is incorrect - /// - private async Task CheckIrreversibleBlockHashAsync(Hash blockHash, long blockHeight) + if (!_blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName)) { - var peers = _networkService.GetPeers(false) - .Where(p => p.SyncState == SyncState.Finished && - p.LastKnownLibHeight >= blockHeight) - .ToList(); + Logger.LogWarning("Block sync attach and execute queue is too busy."); + return false; + } - if (peers.Count < PeerCheckMinimumCount) - { - return null; - } + return true; + } - var taskList = peers.Select(async peer => - await _networkService.GetBlocksAsync(blockHash, 1, peer.Pubkey)); + public void RemoveDownloadJobTargetState(Hash targetBlockHash) + { + if (targetBlockHash != null) + _blockSyncStateProvider.TryRemoveDownloadJobTargetState(targetBlockHash); + } - var hashCheckResult = await Task.WhenAll(taskList); + public bool IsNotReachedDownloadTarget(Hash targetBlockHash) + { + return _blockSyncStateProvider.TryGetDownloadJobTargetState(targetBlockHash, out var state) + && state == false; + } - var confirmCount = 2 * peers.Count() / 3 + 1; - var result = hashCheckResult.Where(r => r.Success) - .GroupBy(a => a.Payload != null && a.Payload.Count == 1) - .FirstOrDefault(group => group.Count() >= confirmCount); + private bool IsPeerAvailable(string peerPubkey) + { + return _networkService.GetPeerByPubkey(peerPubkey) != null; + } - return result?.Key; - } + /// + /// Ask all of peers to check the irreversible block hash is correct. + /// + /// + /// + /// + /// Null: No enough results to known if it's correct + /// True: More than 2/3 peers say is correct + /// False: More than 2/3 peers say is incorrect + /// + private async Task CheckIrreversibleBlockHashAsync(Hash blockHash, long blockHeight) + { + var peers = _networkService.GetPeers(false) + .Where(p => p.SyncState == SyncState.Finished && + p.LastKnownLibHeight >= blockHeight) + .ToList(); - private async Task CheckAbnormalPeerAsync(string peerPubkey, Hash downloadPreviousBlockHash, - long downloadPreviousBlockHeight) - { - var checkResult = - await CheckIrreversibleBlockHashAsync(downloadPreviousBlockHash, downloadPreviousBlockHeight); + if (peers.Count < PeerCheckMinimumCount) return null; - if (checkResult.HasValue) - { - var wrongPeerPubkey = checkResult.Value ? peerPubkey : _blockSyncStateProvider.LastRequestPeerPubkey; - Logger.LogWarning( - $"Wrong irreversible block: {wrongPeerPubkey}, block hash: {downloadPreviousBlockHash}, block height: {downloadPreviousBlockHeight}"); - throw new BlockDownloadException(downloadPreviousBlockHash, downloadPreviousBlockHeight, - wrongPeerPubkey); - } - } + var taskList = peers.Select(async peer => + await _networkService.GetBlocksAsync(blockHash, 1, peer.Pubkey)); - private bool UseSuggestedPeer(DownloadBlockDto downloadBlockDto) - { - if (downloadBlockDto.UseSuggestedPeer) - return true; + var hashCheckResult = await Task.WhenAll(taskList); - var suggestedPeer = _networkService.GetPeerByPubkey(downloadBlockDto.SuggestedPeerPubkey); - var downloadTargetHeight = downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount; - if (downloadTargetHeight > suggestedPeer.LastKnownLibHeight) - return true; + var confirmCount = 2 * peers.Count() / 3 + 1; + var result = hashCheckResult.Where(r => r.Success) + .GroupBy(a => a.Payload != null && a.Payload.Count == 1) + .FirstOrDefault(group => group.Count() >= confirmCount); - return false; - } - - private string GetRandomPeerPubkey(string defaultPeerPubkey, long peerLibHeight, List exceptedPeers) - { - var peers = _networkService.GetPeers(false) - .Where(p => p.SyncState == SyncState.Finished && - p.LastKnownLibHeight >= peerLibHeight && - (exceptedPeers.IsNullOrEmpty() || !exceptedPeers.Contains(p.Pubkey))) - .ToList(); + return result?.Key; + } - var randomPeerPubkey = peers.Count == 0 - ? defaultPeerPubkey - : peers[RandomHelper.GetRandom() % peers.Count].Pubkey; + private async Task CheckAbnormalPeerAsync(string peerPubkey, Hash downloadPreviousBlockHash, + long downloadPreviousBlockHeight) + { + var checkResult = + await CheckIrreversibleBlockHashAsync(downloadPreviousBlockHash, downloadPreviousBlockHeight); - return randomPeerPubkey; + if (checkResult.HasValue) + { + var wrongPeerPubkey = checkResult.Value ? peerPubkey : _blockSyncStateProvider.LastRequestPeerPubkey; + Logger.LogWarning( + $"Wrong irreversible block: {wrongPeerPubkey}, block hash: {downloadPreviousBlockHash}, block height: {downloadPreviousBlockHeight}"); + throw new BlockDownloadException(downloadPreviousBlockHash, downloadPreviousBlockHeight, + wrongPeerPubkey); } + } - private async Task DownloadBlocksAsync(string peerPubkey, - DownloadBlockDto downloadBlockDto) - { - var downloadBlockCount = 0; - var lastDownloadBlockHash = downloadBlockDto.PreviousBlockHash; - var lastDownloadBlockHeight = downloadBlockDto.PreviousBlockHeight; + private bool UseSuggestedPeer(DownloadBlockDto downloadBlockDto) + { + if (downloadBlockDto.UseSuggestedPeer) + return true; - Logger.LogDebug( - $"Download blocks start with block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}, PeerPubkey: {peerPubkey}"); + var suggestedPeer = _networkService.GetPeerByPubkey(downloadBlockDto.SuggestedPeerPubkey); + var downloadTargetHeight = downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount; + if (downloadTargetHeight > suggestedPeer.LastKnownLibHeight) + return true; - while (downloadBlockCount < downloadBlockDto.MaxBlockDownloadCount) - { - var getBlocksResult = await _networkService.GetBlocksAsync(lastDownloadBlockHash, - downloadBlockDto.BatchRequestBlockCount, peerPubkey); - if (!getBlocksResult.Success) - { - return new DownloadBlocksResult - { - Success = false - }; - } + return false; + } - var blocksWithTransactions = getBlocksResult.Payload; - if (blocksWithTransactions == null || !blocksWithTransactions.Any()) - { - Logger.LogDebug( - $"No blocks returned from peer: {peerPubkey}, Previous block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}."); - break; - } + private string GetRandomPeerPubkey(string defaultPeerPubkey, long peerLibHeight, List exceptedPeers) + { + var peers = _networkService.GetPeers(false) + .Where(p => p.SyncState == SyncState.Finished && + p.LastKnownLibHeight >= peerLibHeight && + (exceptedPeers.IsNullOrEmpty() || !exceptedPeers.Contains(p.Pubkey))) + .ToList(); - foreach (var blockWithTransactions in blocksWithTransactions) - { - Logger.LogDebug($"Processing block {blockWithTransactions}."); + var randomPeerPubkey = peers.Count == 0 + ? defaultPeerPubkey + : peers[RandomHelper.GetRandom() % peers.Count].Pubkey; - if (blockWithTransactions.Height != lastDownloadBlockHeight + 1 || - blockWithTransactions.Header.PreviousBlockHash != lastDownloadBlockHash) - { - Logger.LogWarning( - $"Received invalid block, peer: {peerPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); - throw new BlockDownloadException(blockWithTransactions.GetHash(), blockWithTransactions.Height, - peerPubkey); - } + return randomPeerPubkey; + } - lastDownloadBlockHash = blockWithTransactions.GetHash(); - lastDownloadBlockHeight = blockWithTransactions.Height; + private async Task DownloadBlocksAsync(string peerPubkey, + DownloadBlockDto downloadBlockDto) + { + var downloadBlockCount = 0; + var lastDownloadBlockHash = downloadBlockDto.PreviousBlockHash; + var lastDownloadBlockHeight = downloadBlockDto.PreviousBlockHeight; - EnqueueAttachBlockJob(blockWithTransactions, peerPubkey); - downloadBlockCount++; - } + Logger.LogDebug( + $"Download blocks start with block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}, PeerPubkey: {peerPubkey}"); - var lastBlock = blocksWithTransactions.Last(); - lastDownloadBlockHash = lastBlock.GetHash(); - lastDownloadBlockHeight = lastBlock.Height; - } + while (downloadBlockCount < downloadBlockDto.MaxBlockDownloadCount) + { + var getBlocksResult = await _networkService.GetBlocksAsync(lastDownloadBlockHash, + downloadBlockDto.BatchRequestBlockCount, peerPubkey); + if (!getBlocksResult.Success) + return new DownloadBlocksResult + { + Success = false + }; - if (downloadBlockCount != 0) + var blocksWithTransactions = getBlocksResult.Payload; + if (blocksWithTransactions == null || !blocksWithTransactions.Any()) { - _blockSyncStateProvider.SetDownloadJobTargetState(lastDownloadBlockHash, false); - _blockSyncStateProvider.LastRequestPeerPubkey = peerPubkey; + Logger.LogDebug( + $"No blocks returned from peer: {peerPubkey}, Previous block height: {lastDownloadBlockHeight}, hash: {lastDownloadBlockHash}."); + break; } - return new DownloadBlocksResult + foreach (var blockWithTransactions in blocksWithTransactions) { - Success = true, - DownloadBlockCount = downloadBlockCount, - LastDownloadBlockHash = lastDownloadBlockHash, - LastDownloadBlockHeight = lastDownloadBlockHeight - }; - } + Logger.LogDebug($"Processing block {blockWithTransactions}."); - private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey) - { - _blockSyncQueueService.Enqueue( - async () => + if (blockWithTransactions.Height != lastDownloadBlockHeight + 1 || + blockWithTransactions.Header.PreviousBlockHash != lastDownloadBlockHash) { - await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey, - () => - { - _blockSyncStateProvider.TryUpdateDownloadJobTargetState( - blockWithTransactions.GetHash(), true); - return Task.CompletedTask; - }); - }, - OSConstants.BlockSyncAttachQueueName); - } + Logger.LogWarning( + $"Received invalid block, peer: {peerPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); + throw new BlockDownloadException(blockWithTransactions.GetHash(), blockWithTransactions.Height, + peerPubkey); + } - public bool ValidateQueueAvailabilityBeforeDownload() - { - if (!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName)) - { - Logger.LogWarning("Block sync attach queue is too busy."); - return false; - } + lastDownloadBlockHash = blockWithTransactions.GetHash(); + lastDownloadBlockHeight = blockWithTransactions.Height; - if (!_blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName)) - { - Logger.LogWarning("Block sync attach and execute queue is too busy."); - return false; + EnqueueAttachBlockJob(blockWithTransactions, peerPubkey); + downloadBlockCount++; } - return true; + var lastBlock = blocksWithTransactions.Last(); + lastDownloadBlockHash = lastBlock.GetHash(); + lastDownloadBlockHeight = lastBlock.Height; } - public void RemoveDownloadJobTargetState(Hash targetBlockHash) + if (downloadBlockCount != 0) { - if (targetBlockHash != null) - _blockSyncStateProvider.TryRemoveDownloadJobTargetState(targetBlockHash); + _blockSyncStateProvider.SetDownloadJobTargetState(lastDownloadBlockHash, false); + _blockSyncStateProvider.LastRequestPeerPubkey = peerPubkey; } - public bool IsNotReachedDownloadTarget(Hash targetBlockHash) + return new DownloadBlocksResult { - return _blockSyncStateProvider.TryGetDownloadJobTargetState(targetBlockHash, out var state) - && state == false; - } + Success = true, + DownloadBlockCount = downloadBlockCount, + LastDownloadBlockHash = lastDownloadBlockHash, + LastDownloadBlockHeight = lastDownloadBlockHeight + }; + } + + private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey) + { + _blockSyncQueueService.Enqueue( + async () => + { + await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey, + () => + { + _blockSyncStateProvider.TryUpdateDownloadJobTargetState( + blockWithTransactions.GetHash(), true); + return Task.CompletedTask; + }); + }, + OSConstants.BlockSyncAttachQueueName); } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockFetchService.cs b/src/AElf.OS/BlockSync/Application/BlockFetchService.cs index 99c88dd25b..126bef59b4 100644 --- a/src/AElf.OS/BlockSync/Application/BlockFetchService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockFetchService.cs @@ -1,79 +1,74 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.OS.BlockSync.Events; -using AElf.OS.BlockSync.Exceptions; using AElf.OS.Network.Application; using AElf.Types; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.EventBus.Local; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockFetchService : IBlockFetchService { - public class BlockFetchService : IBlockFetchService - { - private readonly IBlockchainService _blockchainService; - private readonly INetworkService _networkService; - private readonly IBlockSyncAttachService _blockSyncAttachService; - private readonly IBlockSyncQueueService _blockSyncQueueService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockSyncAttachService _blockSyncAttachService; + private readonly IBlockSyncQueueService _blockSyncQueueService; + private readonly INetworkService _networkService; - public ILogger Logger { get; set; } + public BlockFetchService(IBlockSyncAttachService blockSyncAttachService, + IBlockchainService blockchainService, + INetworkService networkService, + IBlockSyncQueueService blockSyncQueueService) + { + Logger = NullLogger.Instance; - public ILocalEventBus LocalEventBus { get; set; } + _blockchainService = blockchainService; + _networkService = networkService; + _blockSyncAttachService = blockSyncAttachService; + _blockSyncQueueService = blockSyncQueueService; + } - public BlockFetchService(IBlockSyncAttachService blockSyncAttachService, - IBlockchainService blockchainService, - INetworkService networkService, - IBlockSyncQueueService blockSyncQueueService) - { - Logger = NullLogger.Instance; + public ILogger Logger { get; set; } - _blockchainService = blockchainService; - _networkService = networkService; - _blockSyncAttachService = blockSyncAttachService; - _blockSyncQueueService = blockSyncQueueService; - } + public ILocalEventBus LocalEventBus { get; set; } - public async Task FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey) + public async Task FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey) + { + var hasBlock = await _blockchainService.HasBlockAsync(blockHash); + if (hasBlock) { - var hasBlock = await _blockchainService.HasBlockAsync(blockHash); - if (hasBlock) - { - Logger.LogDebug($"Block {blockHash} already know."); - return true; - } + Logger.LogDebug($"Block {blockHash} already know."); + return true; + } - var response = await _networkService.GetBlockByHashAsync(blockHash, suggestedPeerPubKey); + var response = await _networkService.GetBlockByHashAsync(blockHash, suggestedPeerPubKey); - if (!response.Success || response.Payload == null) - { - return false; - } + if (!response.Success || response.Payload == null) return false; - var blockWithTransactions = response.Payload; - if (blockWithTransactions.GetHash() != blockHash || blockWithTransactions.Height != blockHeight) + var blockWithTransactions = response.Payload; + if (blockWithTransactions.GetHash() != blockHash || blockWithTransactions.Height != blockHeight) + { + Logger.LogWarning( + $"Fetched invalid block, peer: {suggestedPeerPubKey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); + await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData { - Logger.LogWarning( - $"Fetched invalid block, peer: {suggestedPeerPubKey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); - await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData - { - BlockHash = blockWithTransactions.GetHash(), - BlockHeight = blockWithTransactions.Height, - PeerPubkey = suggestedPeerPubKey - }); + BlockHash = blockWithTransactions.GetHash(), + BlockHeight = blockWithTransactions.Height, + PeerPubkey = suggestedPeerPubKey + }); - return false; - } + return false; + } - _blockSyncQueueService.Enqueue( - async () => - { - await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, - suggestedPeerPubKey); - }, - OSConstants.BlockSyncAttachQueueName); + _blockSyncQueueService.Enqueue( + async () => + { + await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, + suggestedPeerPubKey); + }, + OSConstants.BlockSyncAttachQueueName); - return true; - } + return true; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockSyncAttachService.cs b/src/AElf.OS/BlockSync/Application/BlockSyncAttachService.cs index 9fdb006775..aad59a9cba 100644 --- a/src/AElf.OS/BlockSync/Application/BlockSyncAttachService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockSyncAttachService.cs @@ -10,70 +10,66 @@ using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.EventBus.Local; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncAttachService : IBlockSyncAttachService { - public class BlockSyncAttachService : IBlockSyncAttachService + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockSyncQueueService _blockSyncQueueService; + private readonly IBlockSyncValidationService _blockSyncValidationService; + + public BlockSyncAttachService(IBlockchainService blockchainService, + IBlockAttachService blockAttachService, + IBlockSyncValidationService blockSyncValidationService, + IBlockSyncQueueService blockSyncQueueService) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockAttachService _blockAttachService; - private readonly IBlockSyncQueueService _blockSyncQueueService; - private readonly IBlockSyncValidationService _blockSyncValidationService; + Logger = NullLogger.Instance; + LocalEventBus = NullLocalEventBus.Instance; + + _blockchainService = blockchainService; + _blockAttachService = blockAttachService; + _blockSyncValidationService = blockSyncValidationService; + _blockSyncQueueService = blockSyncQueueService; + } - public ILocalEventBus LocalEventBus { get; set; } + public ILocalEventBus LocalEventBus { get; set; } - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } - public BlockSyncAttachService(IBlockchainService blockchainService, - IBlockAttachService blockAttachService, - IBlockSyncValidationService blockSyncValidationService, - IBlockSyncQueueService blockSyncQueueService) + public async Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions, + string senderPubkey, Func attachFinishedCallback = null) + { + var blockValid = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions); + if (!blockValid) { - Logger = NullLogger.Instance; - LocalEventBus = NullLocalEventBus.Instance; + Logger.LogDebug( + $"Sync block validation failed, peer: {senderPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); + await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData + { + BlockHash = blockWithTransactions.GetHash(), + BlockHeight = blockWithTransactions.Height, + PeerPubkey = senderPubkey + }); - _blockchainService = blockchainService; - _blockAttachService = blockAttachService; - _blockSyncValidationService = blockSyncValidationService; - _blockSyncQueueService = blockSyncQueueService; + return; } - public async Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions, - string senderPubkey, Func attachFinishedCallback = null) - { - var blockValid = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions); - if (!blockValid) + await _blockchainService.AddTransactionsAsync(blockWithTransactions.Transactions); + var block = blockWithTransactions.ToBlock(); + await _blockchainService.AddBlockAsync(block); + + _blockSyncQueueService.Enqueue(async () => { - Logger.LogDebug( - $"Sync block validation failed, peer: {senderPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}"); - await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData + try { - BlockHash = blockWithTransactions.GetHash(), - BlockHeight = blockWithTransactions.Height, - PeerPubkey = senderPubkey - }); - - return; - } - - await _blockchainService.AddTransactionsAsync(blockWithTransactions.Transactions); - var block = blockWithTransactions.ToBlock(); - await _blockchainService.AddBlockAsync(block); - - _blockSyncQueueService.Enqueue(async () => + await _blockAttachService.AttachBlockAsync(block); + } + finally { - try - { - await _blockAttachService.AttachBlockAsync(block); - } - finally - { - if (attachFinishedCallback != null) - { - await attachFinishedCallback(); - } - } - }, - KernelConstants.UpdateChainQueueName); - } + if (attachFinishedCallback != null) await attachFinishedCallback(); + } + }, + KernelConstants.UpdateChainQueueName); } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockSyncQueueService.cs b/src/AElf.OS/BlockSync/Application/BlockSyncQueueService.cs index ec5082839d..0a06ffe8f0 100644 --- a/src/AElf.OS/BlockSync/Application/BlockSyncQueueService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockSyncQueueService.cs @@ -6,74 +6,73 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncQueueService : IBlockSyncQueueService { - public class BlockSyncQueueService : IBlockSyncQueueService - { - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - private readonly ITaskQueueManager _taskQueueManager; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly ITaskQueueManager _taskQueueManager; - public ILogger Logger { get; set; } + public BlockSyncQueueService(IBlockSyncStateProvider blockSyncStateProvider, ITaskQueueManager taskQueueManager) + { + Logger = NullLogger.Instance; - public BlockSyncQueueService(IBlockSyncStateProvider blockSyncStateProvider, ITaskQueueManager taskQueueManager) - { - Logger = NullLogger.Instance; + _blockSyncStateProvider = blockSyncStateProvider; + _taskQueueManager = taskQueueManager; + } - _blockSyncStateProvider = blockSyncStateProvider; - _taskQueueManager = taskQueueManager; - } + public ILogger Logger { get; set; } - public bool ValidateQueueAvailability(string queueName) + public bool ValidateQueueAvailability(string queueName) + { + bool isAvailable; + var enqueueTime = _blockSyncStateProvider.GetEnqueueTime(queueName); + switch (queueName) { - bool isAvailable; - var enqueueTime = _blockSyncStateProvider.GetEnqueueTime(queueName); - switch (queueName) - { - case OSConstants.BlockFetchQueueName: - isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncFetchBlockAgeLimit); - break; - case OSConstants.BlockSyncAttachQueueName: - isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncAttachBlockAgeLimit); - break; - case KernelConstants.UpdateChainQueueName: - isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit); - break; - default: - throw new InvalidOperationException($"invalid queue name: {queueName}"); - } - - return isAvailable; + case OSConstants.BlockFetchQueueName: + isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncFetchBlockAgeLimit); + break; + case OSConstants.BlockSyncAttachQueueName: + isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncAttachBlockAgeLimit); + break; + case KernelConstants.UpdateChainQueueName: + isAvailable = CheckAgeLimit(enqueueTime, BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit); + break; + default: + throw new InvalidOperationException($"invalid queue name: {queueName}"); } - public void Enqueue(Func task, string queueName) + return isAvailable; + } + + public void Enqueue(Func task, string queueName) + { + var enqueueTime = TimestampHelper.GetUtcNow(); + _taskQueueManager.Enqueue(async () => { - var enqueueTime = TimestampHelper.GetUtcNow(); - _taskQueueManager.Enqueue(async () => + try { - try - { - Logger.LogDebug($"Execute block sync job: {queueName}, enqueue time: {enqueueTime}"); + Logger.LogDebug($"Execute block sync job: {queueName}, enqueue time: {enqueueTime}"); - _blockSyncStateProvider.SetEnqueueTime(queueName, enqueueTime); - await task(); - } - finally - { - _blockSyncStateProvider.SetEnqueueTime(queueName, null); - } - }, queueName); - } - - private bool CheckAgeLimit(Timestamp enqueueTime, long ageLimit) - { - if (enqueueTime != null && TimestampHelper.GetUtcNow() > - enqueueTime + TimestampHelper.DurationFromMilliseconds(ageLimit)) + _blockSyncStateProvider.SetEnqueueTime(queueName, enqueueTime); + await task(); + } + finally { - Logger.LogDebug($"Enqueue time is more than limit : {enqueueTime}"); - return false; + _blockSyncStateProvider.SetEnqueueTime(queueName, null); } + }, queueName); + } - return true; + private bool CheckAgeLimit(Timestamp enqueueTime, long ageLimit) + { + if (enqueueTime != null && TimestampHelper.GetUtcNow() > + enqueueTime + TimestampHelper.DurationFromMilliseconds(ageLimit)) + { + Logger.LogDebug($"Enqueue time is more than limit : {enqueueTime}"); + return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockSyncService.cs b/src/AElf.OS/BlockSync/Application/BlockSyncService.cs index f3de407498..c369d096de 100644 --- a/src/AElf.OS/BlockSync/Application/BlockSyncService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockSyncService.cs @@ -7,115 +7,110 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncService : IBlockSyncService { - public class BlockSyncService : IBlockSyncService + private readonly IAnnouncementCacheProvider _announcementCacheProvider; + private readonly IBlockDownloadJobManager _blockDownloadJobManager; + private readonly IBlockFetchService _blockFetchService; + private readonly IBlockSyncAttachService _blockSyncAttachService; + private readonly IBlockSyncQueueService _blockSyncQueueService; + + public BlockSyncService(IBlockFetchService blockFetchService, + IBlockSyncAttachService blockSyncAttachService, + IBlockSyncQueueService blockSyncQueueService, + IBlockDownloadJobManager blockDownloadJobManager, IAnnouncementCacheProvider announcementCacheProvider) { - private readonly IBlockFetchService _blockFetchService; - private readonly IBlockSyncAttachService _blockSyncAttachService; - private readonly IBlockSyncQueueService _blockSyncQueueService; - private readonly IBlockDownloadJobManager _blockDownloadJobManager; - private readonly IAnnouncementCacheProvider _announcementCacheProvider; - - public ILogger Logger { get; set; } + Logger = NullLogger.Instance; - public BlockSyncService(IBlockFetchService blockFetchService, - IBlockSyncAttachService blockSyncAttachService, - IBlockSyncQueueService blockSyncQueueService, - IBlockDownloadJobManager blockDownloadJobManager, IAnnouncementCacheProvider announcementCacheProvider) - { - Logger = NullLogger.Instance; + _blockFetchService = blockFetchService; + _blockSyncAttachService = blockSyncAttachService; + _blockSyncQueueService = blockSyncQueueService; + _blockDownloadJobManager = blockDownloadJobManager; + _announcementCacheProvider = announcementCacheProvider; + } - _blockFetchService = blockFetchService; - _blockSyncAttachService = blockSyncAttachService; - _blockSyncQueueService = blockSyncQueueService; - _blockDownloadJobManager = blockDownloadJobManager; - _announcementCacheProvider = announcementCacheProvider; - } + public ILogger Logger { get; set; } - public async Task SyncByAnnouncementAsync(Chain chain, SyncAnnouncementDto syncAnnouncementDto) + public async Task SyncByAnnouncementAsync(Chain chain, SyncAnnouncementDto syncAnnouncementDto) + { + if (syncAnnouncementDto.SyncBlockHash != null && syncAnnouncementDto.SyncBlockHeight <= + chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset) { - if (syncAnnouncementDto.SyncBlockHash != null && syncAnnouncementDto.SyncBlockHeight <= - chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset) + if (!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName)) { - if(!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName)) - { - Logger.LogWarning("Block sync fetch queue is too busy."); - return; - } - - EnqueueFetchBlockJob(syncAnnouncementDto); - } - else - { - await _blockDownloadJobManager.EnqueueAsync(syncAnnouncementDto.SyncBlockHash, syncAnnouncementDto - .SyncBlockHeight, - syncAnnouncementDto.BatchRequestBlockCount, syncAnnouncementDto.SuggestedPeerPubkey); + Logger.LogWarning("Block sync fetch queue is too busy."); + return; } + + EnqueueFetchBlockJob(syncAnnouncementDto); } - - public async Task SyncByBlockAsync(Chain chain, SyncBlockDto syncBlockDto) + else { - if (syncBlockDto.BlockWithTransactions.Height <= - chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset) - { - EnqueueAttachBlockJob(syncBlockDto.BlockWithTransactions, syncBlockDto.SuggestedPeerPubkey); - } - else - { - await _blockDownloadJobManager.EnqueueAsync(syncBlockDto.BlockWithTransactions.GetHash(), syncBlockDto.BlockWithTransactions.Height, - syncBlockDto.BatchRequestBlockCount, syncBlockDto.SuggestedPeerPubkey); - } + await _blockDownloadJobManager.EnqueueAsync(syncAnnouncementDto.SyncBlockHash, syncAnnouncementDto + .SyncBlockHeight, + syncAnnouncementDto.BatchRequestBlockCount, syncAnnouncementDto.SuggestedPeerPubkey); } + } - private void EnqueueFetchBlockJob(SyncAnnouncementDto syncAnnouncementDto) - { - _blockSyncQueueService.Enqueue(async () => - { - Logger.LogDebug( - $"Block sync: Fetch block, block height: {syncAnnouncementDto.SyncBlockHeight}, block hash: {syncAnnouncementDto.SyncBlockHash}."); + public async Task SyncByBlockAsync(Chain chain, SyncBlockDto syncBlockDto) + { + if (syncBlockDto.BlockWithTransactions.Height <= + chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset) + EnqueueAttachBlockJob(syncBlockDto.BlockWithTransactions, syncBlockDto.SuggestedPeerPubkey); + else + await _blockDownloadJobManager.EnqueueAsync(syncBlockDto.BlockWithTransactions.GetHash(), + syncBlockDto.BlockWithTransactions.Height, + syncBlockDto.BatchRequestBlockCount, syncBlockDto.SuggestedPeerPubkey); + } - var fetchResult = false; - if (ValidateQueueAvailability()) - { - fetchResult = await _blockFetchService.FetchBlockAsync(syncAnnouncementDto.SyncBlockHash, - syncAnnouncementDto.SyncBlockHeight, syncAnnouncementDto.SuggestedPeerPubkey); - } + private void EnqueueFetchBlockJob(SyncAnnouncementDto syncAnnouncementDto) + { + _blockSyncQueueService.Enqueue(async () => + { + Logger.LogDebug( + $"Block sync: Fetch block, block height: {syncAnnouncementDto.SyncBlockHeight}, block hash: {syncAnnouncementDto.SyncBlockHash}."); - if (fetchResult) - return; - if (_announcementCacheProvider.TryGetAnnouncementNextSender(syncAnnouncementDto.SyncBlockHash, out var senderPubKey)) - { - syncAnnouncementDto.SuggestedPeerPubkey = senderPubKey; - EnqueueFetchBlockJob(syncAnnouncementDto); - } - }, OSConstants.BlockFetchQueueName); - } + var fetchResult = false; + if (ValidateQueueAvailability()) + fetchResult = await _blockFetchService.FetchBlockAsync(syncAnnouncementDto.SyncBlockHash, + syncAnnouncementDto.SyncBlockHeight, syncAnnouncementDto.SuggestedPeerPubkey); - private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey) - { - _blockSyncQueueService.Enqueue(async () => + if (fetchResult) + return; + if (_announcementCacheProvider.TryGetAnnouncementNextSender(syncAnnouncementDto.SyncBlockHash, + out var senderPubKey)) { - Logger.LogDebug($"Block sync: sync block, block: {blockWithTransactions}."); - await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey); - }, OSConstants.BlockSyncAttachQueueName); - } + syncAnnouncementDto.SuggestedPeerPubkey = senderPubKey; + EnqueueFetchBlockJob(syncAnnouncementDto); + } + }, OSConstants.BlockFetchQueueName); + } - private bool ValidateQueueAvailability() + private void EnqueueAttachBlockJob(BlockWithTransactions blockWithTransactions, string senderPubkey) + { + _blockSyncQueueService.Enqueue(async () => { - if(!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName)) - { - Logger.LogWarning("Block sync attach queue is too busy."); - return false; - } + Logger.LogDebug($"Block sync: sync block, block: {blockWithTransactions}."); + await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, senderPubkey); + }, OSConstants.BlockSyncAttachQueueName); + } - if(!_blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName)) - { - Logger.LogWarning("Block sync attach and execute queue is too busy."); - return false; - } + private bool ValidateQueueAvailability() + { + if (!_blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName)) + { + Logger.LogWarning("Block sync attach queue is too busy."); + return false; + } - return true; + if (!_blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName)) + { + Logger.LogWarning("Block sync attach and execute queue is too busy."); + return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/BlockSyncValidationService.cs b/src/AElf.OS/BlockSync/Application/BlockSyncValidationService.cs index 09f4aa4c42..7cbf1b03aa 100644 --- a/src/AElf.OS/BlockSync/Application/BlockSyncValidationService.cs +++ b/src/AElf.OS/BlockSync/Application/BlockSyncValidationService.cs @@ -8,110 +8,95 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncValidationService : IBlockSyncValidationService { - public class BlockSyncValidationService : IBlockSyncValidationService + private readonly IAnnouncementCacheProvider _announcementCacheProvider; + private readonly IBlockchainService _blockchainService; + private readonly IBlockValidationService _blockValidationService; + + private readonly ITransactionValidationService _transactionValidationService; + + public BlockSyncValidationService(IAnnouncementCacheProvider announcementCacheProvider, + IBlockValidationService blockValidationService, + ITransactionValidationService transactionValidationService, + IBlockchainService blockchainService) { - private readonly IAnnouncementCacheProvider _announcementCacheProvider; - private readonly IBlockValidationService _blockValidationService; - private readonly IBlockchainService _blockchainService; + Logger = NullLogger.Instance; - public ILogger Logger { get; set; } + _announcementCacheProvider = announcementCacheProvider; + _blockValidationService = blockValidationService; + _transactionValidationService = transactionValidationService; + _blockchainService = blockchainService; + } - private readonly ITransactionValidationService _transactionValidationService; + public ILogger Logger { get; set; } - public BlockSyncValidationService(IAnnouncementCacheProvider announcementCacheProvider, - IBlockValidationService blockValidationService, - ITransactionValidationService transactionValidationService, - IBlockchainService blockchainService) + public Task ValidateAnnouncementBeforeSyncAsync(Chain chain, BlockAnnouncement blockAnnouncement, + string senderPubKey) + { + if (blockAnnouncement.BlockHeight <= chain.LastIrreversibleBlockHeight) { - Logger = NullLogger.Instance; - - _announcementCacheProvider = announcementCacheProvider; - _blockValidationService = blockValidationService; - _transactionValidationService = transactionValidationService; - _blockchainService = blockchainService; + Logger.LogDebug( + $"Receive lower header {{ hash: {blockAnnouncement.BlockHash}, height: {blockAnnouncement.BlockHeight} }} ignore."); + return Task.FromResult(false); } - public Task ValidateAnnouncementBeforeSyncAsync(Chain chain, BlockAnnouncement blockAnnouncement, - string senderPubKey) - { - if (blockAnnouncement.BlockHeight <= chain.LastIrreversibleBlockHeight) - { - Logger.LogDebug( - $"Receive lower header {{ hash: {blockAnnouncement.BlockHash}, height: {blockAnnouncement.BlockHeight} }} ignore."); - return Task.FromResult(false); - } + if (!TryCacheNewAnnouncement(blockAnnouncement.BlockHash, blockAnnouncement.BlockHeight, senderPubKey)) + return Task.FromResult(false); - if (!TryCacheNewAnnouncement(blockAnnouncement.BlockHash, blockAnnouncement.BlockHeight, senderPubKey)) - { - return Task.FromResult(false); - } + return Task.FromResult(true); + } - return Task.FromResult(true); + public Task ValidateBlockBeforeSyncAsync(Chain chain, BlockWithTransactions blockWithTransactions, + string senderPubKey) + { + if (blockWithTransactions.Height <= chain.LastIrreversibleBlockHeight) + { + Logger.LogDebug($"Receive lower block {blockWithTransactions} ignore."); + return Task.FromResult(false); } - public Task ValidateBlockBeforeSyncAsync(Chain chain, BlockWithTransactions blockWithTransactions, - string senderPubKey) + if (blockWithTransactions.Header.SignerPubkey.ToHex() != senderPubKey) { - if (blockWithTransactions.Height <= chain.LastIrreversibleBlockHeight) - { - Logger.LogDebug($"Receive lower block {blockWithTransactions} ignore."); - return Task.FromResult(false); - } - - if (blockWithTransactions.Header.SignerPubkey.ToHex() != senderPubKey) - { - Logger.LogDebug($"Sender {senderPubKey} of block {blockWithTransactions} is incorrect."); - return Task.FromResult(false); - } - - return Task.FromResult(true); + Logger.LogDebug($"Sender {senderPubKey} of block {blockWithTransactions} is incorrect."); + return Task.FromResult(false); } - public async Task ValidateBlockBeforeAttachAsync(BlockWithTransactions blockWithTransactions) - { - if (!await _blockValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions)) - { - return false; - } + return Task.FromResult(true); + } - if (!await ValidateTransactionAsync(blockWithTransactions)) - { - return false; - } + public async Task ValidateBlockBeforeAttachAsync(BlockWithTransactions blockWithTransactions) + { + if (!await _blockValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions)) return false; - return true; - } + if (!await ValidateTransactionAsync(blockWithTransactions)) return false; - private bool TryCacheNewAnnouncement(Hash blockHash, long blockHeight, string senderPubkey) - { - return _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, senderPubkey); - } + return true; + } + + private bool TryCacheNewAnnouncement(Hash blockHash, long blockHeight, string senderPubkey) + { + return _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, senderPubkey); + } - private async Task ValidateTransactionAsync(BlockWithTransactions blockWithTransactions) + private async Task ValidateTransactionAsync(BlockWithTransactions blockWithTransactions) + { + foreach (var transaction in blockWithTransactions.Transactions) { - foreach (var transaction in blockWithTransactions.Transactions) + if (!transaction.VerifyExpiration(blockWithTransactions.Height - 1)) { - if (!transaction.VerifyExpiration(blockWithTransactions.Height - 1)) - { - Logger.LogDebug($"Transaction {transaction.GetHash()} expired."); - return false; - } - - // No need to validate again if this tx already in local database. - if (await _blockchainService.HasTransactionAsync(transaction.GetHash())) - { - continue; - } - - if (!await _transactionValidationService.ValidateTransactionWhileSyncingAsync(transaction)) - { - return false; - } + Logger.LogDebug($"Transaction {transaction.GetHash()} expired."); + return false; } - return true; + // No need to validate again if this tx already in local database. + if (await _blockchainService.HasTransactionAsync(transaction.GetHash())) continue; + + if (!await _transactionValidationService.ValidateTransactionWhileSyncingAsync(transaction)) return false; } + + return true; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockDownloadService.cs b/src/AElf.OS/BlockSync/Application/IBlockDownloadService.cs index 8c06d77833..b7613210cd 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockDownloadService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockDownloadService.cs @@ -3,16 +3,15 @@ using AElf.OS.BlockSync.Types; using AElf.Types; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public interface IBlockDownloadService { - public interface IBlockDownloadService - { - Task DownloadBlocksAsync(DownloadBlockDto downloadBlockDto); + Task DownloadBlocksAsync(DownloadBlockDto downloadBlockDto); - bool ValidateQueueAvailabilityBeforeDownload(); + bool ValidateQueueAvailabilityBeforeDownload(); - void RemoveDownloadJobTargetState(Hash targetBlockHash); + void RemoveDownloadJobTargetState(Hash targetBlockHash); - bool IsNotReachedDownloadTarget(Hash targetBlockHash); - } + bool IsNotReachedDownloadTarget(Hash targetBlockHash); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockFetchService.cs b/src/AElf.OS/BlockSync/Application/IBlockFetchService.cs index 15e2300b1c..adeb7af7cd 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockFetchService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockFetchService.cs @@ -1,10 +1,9 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public interface IBlockFetchService { - public interface IBlockFetchService - { - Task FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey); - } + Task FetchBlockAsync(Hash blockHash, long blockHeight, string suggestedPeerPubKey); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockSyncAttachService.cs b/src/AElf.OS/BlockSync/Application/IBlockSyncAttachService.cs index 479f9589a5..e0915ed277 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockSyncAttachService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockSyncAttachService.cs @@ -1,14 +1,11 @@ using System; using System.Threading.Tasks; using AElf.OS.Network; -using AElf.Types; -namespace AElf.OS.BlockSync.Application -{ - public interface IBlockSyncAttachService - { - Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions, - string senderPubkey, Func attachFinishedCallback = null); +namespace AElf.OS.BlockSync.Application; - } +public interface IBlockSyncAttachService +{ + Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions, + string senderPubkey, Func attachFinishedCallback = null); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockSyncQueueService.cs b/src/AElf.OS/BlockSync/Application/IBlockSyncQueueService.cs index ccdc8142a8..218b24b0af 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockSyncQueueService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockSyncQueueService.cs @@ -1,12 +1,11 @@ using System; using System.Threading.Tasks; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public interface IBlockSyncQueueService { - public interface IBlockSyncQueueService - { - bool ValidateQueueAvailability(string queueName); + bool ValidateQueueAvailability(string queueName); - void Enqueue(Func task, string queueName); - } + void Enqueue(Func task, string queueName); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockSyncService.cs b/src/AElf.OS/BlockSync/Application/IBlockSyncService.cs index 016b5ca622..302c89e793 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockSyncService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockSyncService.cs @@ -1,14 +1,12 @@ using System.Threading.Tasks; using AElf.Kernel; using AElf.OS.BlockSync.Dto; -using AElf.OS.Network; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public interface IBlockSyncService { - public interface IBlockSyncService - { - Task SyncByAnnouncementAsync(Chain chain, SyncAnnouncementDto syncAnnouncementDto); + Task SyncByAnnouncementAsync(Chain chain, SyncAnnouncementDto syncAnnouncementDto); - Task SyncByBlockAsync(Chain chain, SyncBlockDto syncBlockDto); - } + Task SyncByBlockAsync(Chain chain, SyncBlockDto syncBlockDto); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Application/IBlockSyncValidationService.cs b/src/AElf.OS/BlockSync/Application/IBlockSyncValidationService.cs index 48d4c14ef4..a1c54376d2 100644 --- a/src/AElf.OS/BlockSync/Application/IBlockSyncValidationService.cs +++ b/src/AElf.OS/BlockSync/Application/IBlockSyncValidationService.cs @@ -2,14 +2,15 @@ using AElf.Kernel; using AElf.OS.Network; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public interface IBlockSyncValidationService { - public interface IBlockSyncValidationService - { - Task ValidateAnnouncementBeforeSyncAsync(Chain chain, BlockAnnouncement blockAnnouncement, string senderPubKey); + Task ValidateAnnouncementBeforeSyncAsync(Chain chain, BlockAnnouncement blockAnnouncement, + string senderPubKey); - Task ValidateBlockBeforeSyncAsync(Chain chain, BlockWithTransactions blockWithTransactions, string senderPubKey); + Task ValidateBlockBeforeSyncAsync(Chain chain, BlockWithTransactions blockWithTransactions, + string senderPubKey); - Task ValidateBlockBeforeAttachAsync(BlockWithTransactions blockWithTransactions); - } + Task ValidateBlockBeforeAttachAsync(BlockWithTransactions blockWithTransactions); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/BlockSyncConstants.cs b/src/AElf.OS/BlockSync/BlockSyncConstants.cs index 88571f61e1..9548228735 100644 --- a/src/AElf.OS/BlockSync/BlockSyncConstants.cs +++ b/src/AElf.OS/BlockSync/BlockSyncConstants.cs @@ -1,15 +1,13 @@ +namespace AElf.OS.BlockSync; -namespace AElf.OS.BlockSync +public class BlockSyncConstants { - public class BlockSyncConstants - { - public const long BlockSyncFetchBlockAgeLimit = 1000; - public const long BlockSyncAttachBlockAgeLimit = 2000; - public const long BlockSyncAttachAndExecuteBlockAgeLimit = 4000; + public const long BlockSyncFetchBlockAgeLimit = 1000; + public const long BlockSyncAttachBlockAgeLimit = 2000; + public const long BlockSyncAttachAndExecuteBlockAgeLimit = 4000; - public const int BlockSyncModeHeightOffset = 12; - public const int DefaultBlockDownloadTimerPeriod = 1000; - public const int DefaultMaxBlockDownloadCount = 50; - public const int DefaultMaxBatchRequestBlockCount = 10; - } + public const int BlockSyncModeHeightOffset = 12; + public const int DefaultBlockDownloadTimerPeriod = 1000; + public const int DefaultMaxBlockDownloadCount = 50; + public const int DefaultMaxBatchRequestBlockCount = 10; } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/BlockSyncOptions.cs b/src/AElf.OS/BlockSync/BlockSyncOptions.cs index 007d4d44e3..4a99413d7d 100644 --- a/src/AElf.OS/BlockSync/BlockSyncOptions.cs +++ b/src/AElf.OS/BlockSync/BlockSyncOptions.cs @@ -1,20 +1,19 @@ -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +public class BlockSyncOptions { - public class BlockSyncOptions - { - /// - /// The timer period of download blocks (milliseconds). - /// - public int BlockDownloadTimerPeriod { get; set; } = BlockSyncConstants.DefaultBlockDownloadTimerPeriod; - - /// - /// The maximum number of download blocks per download task. - /// - public int MaxBlockDownloadCount { get; set; } = BlockSyncConstants.DefaultMaxBlockDownloadCount; + /// + /// The timer period of download blocks (milliseconds). + /// + public int BlockDownloadTimerPeriod { get; set; } = BlockSyncConstants.DefaultBlockDownloadTimerPeriod; + + /// + /// The maximum number of download blocks per download task. + /// + public int MaxBlockDownloadCount { get; set; } = BlockSyncConstants.DefaultMaxBlockDownloadCount; - /// - /// The maximum number of blocks per request. - /// - public int MaxBatchRequestBlockCount { get; set; } = BlockSyncConstants.DefaultMaxBatchRequestBlockCount; - } + /// + /// The maximum number of blocks per request. + /// + public int MaxBatchRequestBlockCount { get; set; } = BlockSyncConstants.DefaultMaxBatchRequestBlockCount; } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Domain/BlockDownloadJobManager.cs b/src/AElf.OS/BlockSync/Domain/BlockDownloadJobManager.cs index 9dd60ead6e..2167f384c8 100644 --- a/src/AElf.OS/BlockSync/Domain/BlockDownloadJobManager.cs +++ b/src/AElf.OS/BlockSync/Domain/BlockDownloadJobManager.cs @@ -4,32 +4,31 @@ using AElf.OS.BlockSync.Types; using AElf.Types; -namespace AElf.OS.BlockSync.Domain +namespace AElf.OS.BlockSync.Domain; + +public class BlockDownloadJobManager : IBlockDownloadJobManager { - public class BlockDownloadJobManager : IBlockDownloadJobManager - { - private readonly IBlockDownloadJobStore _blockDownloadJobStore; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; - public BlockDownloadJobManager(IBlockDownloadJobStore blockDownloadJobStore) - { - _blockDownloadJobStore = blockDownloadJobStore; - } + public BlockDownloadJobManager(IBlockDownloadJobStore blockDownloadJobStore) + { + _blockDownloadJobStore = blockDownloadJobStore; + } - public async Task EnqueueAsync(Hash syncBlockHash, long syncBlockHeight, int batchRequestBlockCount, - string suggestedPeerPubkey) + public async Task EnqueueAsync(Hash syncBlockHash, long syncBlockHeight, int batchRequestBlockCount, + string suggestedPeerPubkey) + { + var blockDownloadJobInfo = new BlockDownloadJobInfo { - var blockDownloadJobInfo = new BlockDownloadJobInfo - { - JobId = Guid.NewGuid().ToString(), - TargetBlockHash = syncBlockHash, - TargetBlockHeight = syncBlockHeight, - BatchRequestBlockCount = batchRequestBlockCount, - SuggestedPeerPubkey = suggestedPeerPubkey - }; + JobId = Guid.NewGuid().ToString(), + TargetBlockHash = syncBlockHash, + TargetBlockHeight = syncBlockHeight, + BatchRequestBlockCount = batchRequestBlockCount, + SuggestedPeerPubkey = suggestedPeerPubkey + }; - var addResult = await _blockDownloadJobStore.AddAsync(blockDownloadJobInfo); + var addResult = await _blockDownloadJobStore.AddAsync(blockDownloadJobInfo); - return addResult ? blockDownloadJobInfo.JobId : null; - } + return addResult ? blockDownloadJobInfo.JobId : null; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Domain/IBlockDownloadJobManager.cs b/src/AElf.OS/BlockSync/Domain/IBlockDownloadJobManager.cs index 58043a4072..8ff5a58389 100644 --- a/src/AElf.OS/BlockSync/Domain/IBlockDownloadJobManager.cs +++ b/src/AElf.OS/BlockSync/Domain/IBlockDownloadJobManager.cs @@ -1,11 +1,10 @@ using System.Threading.Tasks; using AElf.Types; -namespace AElf.OS.BlockSync.Domain +namespace AElf.OS.BlockSync.Domain; + +public interface IBlockDownloadJobManager { - public interface IBlockDownloadJobManager - { - Task EnqueueAsync(Hash syncBlockHash, long syncBlockHeight, int batchRequestBlockCount, - string suggestedPeerPubkey); - } + Task EnqueueAsync(Hash syncBlockHash, long syncBlockHeight, int batchRequestBlockCount, + string suggestedPeerPubkey); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Dto/DownloadBlockDto.cs b/src/AElf.OS/BlockSync/Dto/DownloadBlockDto.cs index a71fe3e85d..795449a147 100644 --- a/src/AElf.OS/BlockSync/Dto/DownloadBlockDto.cs +++ b/src/AElf.OS/BlockSync/Dto/DownloadBlockDto.cs @@ -1,19 +1,18 @@ using AElf.Types; -namespace AElf.OS.BlockSync.Dto +namespace AElf.OS.BlockSync.Dto; + +public class DownloadBlockDto { - public class DownloadBlockDto - { - public Hash PreviousBlockHash { get; set; } + public Hash PreviousBlockHash { get; set; } - public long PreviousBlockHeight { get; set; } + public long PreviousBlockHeight { get; set; } - public int BatchRequestBlockCount { get; set; } + public int BatchRequestBlockCount { get; set; } - public int MaxBlockDownloadCount { get; set; } + public int MaxBlockDownloadCount { get; set; } - public string SuggestedPeerPubkey { get; set; } + public string SuggestedPeerPubkey { get; set; } - public bool UseSuggestedPeer { get; set; } - } + public bool UseSuggestedPeer { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Dto/SyncAnnouncementDto.cs b/src/AElf.OS/BlockSync/Dto/SyncAnnouncementDto.cs index 218f532513..2a0b473157 100644 --- a/src/AElf.OS/BlockSync/Dto/SyncAnnouncementDto.cs +++ b/src/AElf.OS/BlockSync/Dto/SyncAnnouncementDto.cs @@ -1,15 +1,14 @@ using AElf.Types; -namespace AElf.OS.BlockSync.Dto +namespace AElf.OS.BlockSync.Dto; + +public class SyncAnnouncementDto { - public class SyncAnnouncementDto - { - public Hash SyncBlockHash { get; set; } + public Hash SyncBlockHash { get; set; } + + public long SyncBlockHeight { get; set; } - public long SyncBlockHeight { get; set; } + public string SuggestedPeerPubkey { get; set; } - public string SuggestedPeerPubkey { get; set; } - - public int BatchRequestBlockCount { get; set; } - } + public int BatchRequestBlockCount { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Dto/SyncBlockDto.cs b/src/AElf.OS/BlockSync/Dto/SyncBlockDto.cs index 23fab1414e..f8d25a5551 100644 --- a/src/AElf.OS/BlockSync/Dto/SyncBlockDto.cs +++ b/src/AElf.OS/BlockSync/Dto/SyncBlockDto.cs @@ -1,13 +1,12 @@ using AElf.OS.Network; -namespace AElf.OS.BlockSync.Dto +namespace AElf.OS.BlockSync.Dto; + +public class SyncBlockDto { - public class SyncBlockDto - { - public BlockWithTransactions BlockWithTransactions { get; set; } - - public string SuggestedPeerPubkey { get; set; } - - public int BatchRequestBlockCount { get; set; } - } + public BlockWithTransactions BlockWithTransactions { get; set; } + + public string SuggestedPeerPubkey { get; set; } + + public int BatchRequestBlockCount { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Events/AbnormalPeerFoundEventData.cs b/src/AElf.OS/BlockSync/Events/AbnormalPeerFoundEventData.cs index ffd56bcde9..2e4ce344dd 100644 --- a/src/AElf.OS/BlockSync/Events/AbnormalPeerFoundEventData.cs +++ b/src/AElf.OS/BlockSync/Events/AbnormalPeerFoundEventData.cs @@ -1,11 +1,10 @@ using AElf.Types; -namespace AElf.OS.BlockSync.Events +namespace AElf.OS.BlockSync.Events; + +public class AbnormalPeerFoundEventData { - public class AbnormalPeerFoundEventData - { - public Hash BlockHash { get; set;} - public long BlockHeight { get; set;} - public string PeerPubkey { get; set; } - } + public Hash BlockHash { get; set; } + public long BlockHeight { get; set; } + public string PeerPubkey { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Exceptions/BlockDownloadException.cs b/src/AElf.OS/BlockSync/Exceptions/BlockDownloadException.cs index 130b572266..d11c325459 100644 --- a/src/AElf.OS/BlockSync/Exceptions/BlockDownloadException.cs +++ b/src/AElf.OS/BlockSync/Exceptions/BlockDownloadException.cs @@ -1,32 +1,31 @@ using System; using AElf.Types; -namespace AElf.OS.BlockSync.Exceptions +namespace AElf.OS.BlockSync.Exceptions; + +public class BlockDownloadException : Exception { - public class BlockDownloadException : Exception + public BlockDownloadException() { - public Hash BlockHash { get; } - public long BlockHeight { get; } - public string PeerPubkey { get; } - - public BlockDownloadException() - { - } + } - public BlockDownloadException(string message) : base(message) - { - } + public BlockDownloadException(string message) : base(message) + { + } - public BlockDownloadException(string message, Exception inner) : base(message, inner) - { - } + public BlockDownloadException(string message, Exception inner) : base(message, inner) + { + } - public BlockDownloadException(Hash blockHash, long blockHeight, string peerPubkey) : this( - $"Download block exception, block hash = {blockHash}, block height = {blockHeight}, peer pubkey = {peerPubkey}.") - { - BlockHash = blockHash; - BlockHeight = blockHeight; - PeerPubkey = peerPubkey; - } + public BlockDownloadException(Hash blockHash, long blockHeight, string peerPubkey) : this( + $"Download block exception, block hash = {blockHash}, block height = {blockHeight}, peer pubkey = {peerPubkey}.") + { + BlockHash = blockHash; + BlockHeight = blockHeight; + PeerPubkey = peerPubkey; } + + public Hash BlockHash { get; } + public long BlockHeight { get; } + public string PeerPubkey { get; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/AnnouncementCacheProvider.cs b/src/AElf.OS/BlockSync/Infrastructure/AnnouncementCacheProvider.cs index 811502c910..2da1dc076f 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/AnnouncementCacheProvider.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/AnnouncementCacheProvider.cs @@ -2,69 +2,64 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class AnnouncementCacheProvider : IAnnouncementCacheProvider, ISingletonDependency { - public class AnnouncementCacheProvider : IAnnouncementCacheProvider, ISingletonDependency - { - private ConcurrentDictionary _cache = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _cache = new(); - private ConcurrentQueue _toBeCleanedKeys = new ConcurrentQueue(); + private readonly ConcurrentQueue _toBeCleanedKeys = new(); - /// - /// Cache received announcement if it is new one. If not, update sender public key collection. - /// - /// - /// - /// - /// - /// Return true if it is a new announcement, otherwise return false. - /// - public bool TryAddOrUpdateAnnouncementCache(Hash blockHash, long blockHeight, string senderPubKey) + /// + /// Cache received announcement if it is new one. If not, update sender public key collection. + /// + /// + /// + /// + /// + /// Return true if it is a new announcement, otherwise return false. + /// + public bool TryAddOrUpdateAnnouncementCache(Hash blockHash, long blockHeight, string senderPubKey) + { + if (_cache.TryGetValue(blockHash, out var announcementCache)) { - if (_cache.TryGetValue(blockHash, out var announcementCache)) - { - var res = announcementCache.SenderPubKeys.IsEmpty; - announcementCache.SenderPubKeys.Enqueue(senderPubKey); - return res; - } - - _toBeCleanedKeys.Enqueue(blockHash); - while (_toBeCleanedKeys.Count > 100) - { - if (_toBeCleanedKeys.TryDequeue(out var cleanKey)) - _cache.TryRemove(cleanKey, out _); - } - - _cache.AddOrUpdate(blockHash, new AnnouncementCache - { - BlockHash = blockHash, - BlockHeight = blockHeight, - SenderPubKeys = new ConcurrentQueue(new[] {senderPubKey}) - }, (hash, cache) => - { - cache.SenderPubKeys.Enqueue(senderPubKey); - return cache; - }); - - return true; + var res = announcementCache.SenderPubKeys.IsEmpty; + announcementCache.SenderPubKeys.Enqueue(senderPubKey); + return res; } - public bool TryGetAnnouncementNextSender(Hash blockHash, out string senderPubKey) + _toBeCleanedKeys.Enqueue(blockHash); + while (_toBeCleanedKeys.Count > 100) + if (_toBeCleanedKeys.TryDequeue(out var cleanKey)) + _cache.TryRemove(cleanKey, out _); + + _cache.AddOrUpdate(blockHash, new AnnouncementCache + { + BlockHash = blockHash, + BlockHeight = blockHeight, + SenderPubKeys = new ConcurrentQueue(new[] { senderPubKey }) + }, (hash, cache) => { - if (_cache.TryGetValue(blockHash, out var announcementCache)) - { - return announcementCache.SenderPubKeys.TryDequeue(out senderPubKey); - } + cache.SenderPubKeys.Enqueue(senderPubKey); + return cache; + }); - senderPubKey = null; - return false; - } + return true; } - class AnnouncementCache + public bool TryGetAnnouncementNextSender(Hash blockHash, out string senderPubKey) { - public Hash BlockHash { get; set; } - public long BlockHeight { get; set; } - public ConcurrentQueue SenderPubKeys { get; set; } + if (_cache.TryGetValue(blockHash, out var announcementCache)) + return announcementCache.SenderPubKeys.TryDequeue(out senderPubKey); + + senderPubKey = null; + return false; } +} + +internal class AnnouncementCache +{ + public Hash BlockHash { get; set; } + public long BlockHeight { get; set; } + public ConcurrentQueue SenderPubKeys { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/BlockSyncStateProvider.cs b/src/AElf.OS/BlockSync/Infrastructure/BlockSyncStateProvider.cs index 9e2ff67206..3041c49f2a 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/BlockSyncStateProvider.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/BlockSyncStateProvider.cs @@ -3,55 +3,50 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.DependencyInjection; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class BlockSyncStateProvider : IBlockSyncStateProvider, ISingletonDependency { - public class BlockSyncStateProvider : IBlockSyncStateProvider, ISingletonDependency + private readonly ConcurrentDictionary _downloadJobTargetState; + private readonly ConcurrentDictionary _enqueueTimes; + + public BlockSyncStateProvider() + { + _enqueueTimes = new ConcurrentDictionary(); + _downloadJobTargetState = new ConcurrentDictionary(); + } + + public string LastRequestPeerPubkey { get; set; } + + public Timestamp GetEnqueueTime(string queueName) + { + if (_enqueueTimes.TryGetValue(queueName, out var enqueueTime)) return enqueueTime; + + return null; + } + + public void SetEnqueueTime(string queueName, Timestamp enqueueTime) + { + _enqueueTimes[queueName] = enqueueTime; + } + + public bool TryUpdateDownloadJobTargetState(Hash targetHash, bool value) + { + return _downloadJobTargetState.TryUpdate(targetHash, value, !value); + } + + public void SetDownloadJobTargetState(Hash targetHash, bool value) + { + _downloadJobTargetState[targetHash] = value; + } + + public bool TryGetDownloadJobTargetState(Hash targetHash, out bool value) + { + return _downloadJobTargetState.TryGetValue(targetHash, out value); + } + + public bool TryRemoveDownloadJobTargetState(Hash targetHash) { - private readonly ConcurrentDictionary _enqueueTimes; - - private readonly ConcurrentDictionary _downloadJobTargetState; - - public string LastRequestPeerPubkey { get; set; } - - public BlockSyncStateProvider() - { - _enqueueTimes = new ConcurrentDictionary(); - _downloadJobTargetState = new ConcurrentDictionary(); - } - - public Timestamp GetEnqueueTime(string queueName) - { - if (_enqueueTimes.TryGetValue(queueName, out var enqueueTime)) - { - return enqueueTime; - } - - return null; - } - - public void SetEnqueueTime(string queueName, Timestamp enqueueTime) - { - _enqueueTimes[queueName] = enqueueTime; - } - - public bool TryUpdateDownloadJobTargetState(Hash targetHash, bool value) - { - return _downloadJobTargetState.TryUpdate(targetHash, value, !value); - } - - public void SetDownloadJobTargetState(Hash targetHash, bool value) - { - _downloadJobTargetState[targetHash] = value; - } - - public bool TryGetDownloadJobTargetState(Hash targetHash, out bool value) - { - return _downloadJobTargetState.TryGetValue(targetHash, out value); - } - - public bool TryRemoveDownloadJobTargetState(Hash targetHash) - { - return _downloadJobTargetState.TryRemove(targetHash, out _); - } + return _downloadJobTargetState.TryRemove(targetHash, out _); } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/IAnnouncementCacheProvider.cs b/src/AElf.OS/BlockSync/Infrastructure/IAnnouncementCacheProvider.cs index fd84b3655b..10d75c5638 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/IAnnouncementCacheProvider.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/IAnnouncementCacheProvider.cs @@ -1,10 +1,9 @@ using AElf.Types; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public interface IAnnouncementCacheProvider { - public interface IAnnouncementCacheProvider - { - bool TryAddOrUpdateAnnouncementCache(Hash blockHash, long blockHeight, string senderPubKey); - bool TryGetAnnouncementNextSender(Hash blockHash, out string senderPubKey); - } + bool TryAddOrUpdateAnnouncementCache(Hash blockHash, long blockHeight, string senderPubKey); + bool TryGetAnnouncementNextSender(Hash blockHash, out string senderPubKey); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/IBlockDownloadJobStore.cs b/src/AElf.OS/BlockSync/Infrastructure/IBlockDownloadJobStore.cs index d8820ddf75..0c525c3d11 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/IBlockDownloadJobStore.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/IBlockDownloadJobStore.cs @@ -1,16 +1,15 @@ using System.Threading.Tasks; using AElf.OS.BlockSync.Types; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public interface IBlockDownloadJobStore { - public interface IBlockDownloadJobStore - { - Task AddAsync(BlockDownloadJobInfo blockDownloadJobInfo); + Task AddAsync(BlockDownloadJobInfo blockDownloadJobInfo); - Task GetFirstWaitingJobAsync(); + Task GetFirstWaitingJobAsync(); - Task UpdateAsync(BlockDownloadJobInfo blockDownloadJobInfo); + Task UpdateAsync(BlockDownloadJobInfo blockDownloadJobInfo); - Task RemoveAsync(string jobId); - } + Task RemoveAsync(string jobId); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/IBlockSyncStateProvider.cs b/src/AElf.OS/BlockSync/Infrastructure/IBlockSyncStateProvider.cs index 85fd9e2b25..c647bd55fa 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/IBlockSyncStateProvider.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/IBlockSyncStateProvider.cs @@ -1,23 +1,20 @@ -using System.Collections.Concurrent; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.BlockSync.Infrastructure -{ - public interface IBlockSyncStateProvider - { - Timestamp GetEnqueueTime(string queueName); +namespace AElf.OS.BlockSync.Infrastructure; - void SetEnqueueTime(string queueName, Timestamp enqueueTime); +public interface IBlockSyncStateProvider +{ + string LastRequestPeerPubkey { get; set; } + Timestamp GetEnqueueTime(string queueName); - bool TryUpdateDownloadJobTargetState(Hash targetHash, bool value); + void SetEnqueueTime(string queueName, Timestamp enqueueTime); - void SetDownloadJobTargetState(Hash targetHash, bool value); + bool TryUpdateDownloadJobTargetState(Hash targetHash, bool value); - bool TryGetDownloadJobTargetState(Hash targetHash, out bool value); + void SetDownloadJobTargetState(Hash targetHash, bool value); - bool TryRemoveDownloadJobTargetState(Hash targetHash); + bool TryGetDownloadJobTargetState(Hash targetHash, out bool value); - string LastRequestPeerPubkey { get; set; } - } + bool TryRemoveDownloadJobTargetState(Hash targetHash); } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Infrastructure/InMemoryBlockDownloadJobStore.cs b/src/AElf.OS/BlockSync/Infrastructure/InMemoryBlockDownloadJobStore.cs index 9f9df6bc5b..43cef6f83c 100644 --- a/src/AElf.OS/BlockSync/Infrastructure/InMemoryBlockDownloadJobStore.cs +++ b/src/AElf.OS/BlockSync/Infrastructure/InMemoryBlockDownloadJobStore.cs @@ -3,54 +3,46 @@ using AElf.OS.BlockSync.Types; using Volo.Abp.DependencyInjection; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class InMemoryBlockDownloadJobStore : IBlockDownloadJobStore, ISingletonDependency { - public class InMemoryBlockDownloadJobStore : IBlockDownloadJobStore, ISingletonDependency - { - private readonly ConcurrentQueue _jobIds = new ConcurrentQueue(); + private readonly ConcurrentQueue _jobIds = new(); - private readonly ConcurrentDictionary _jobs = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _jobs = new(); - public Task AddAsync(BlockDownloadJobInfo blockDownloadJobInfo) - { - if (_jobs.Count >= 100) - return Task.FromResult(false); + public Task AddAsync(BlockDownloadJobInfo blockDownloadJobInfo) + { + if (_jobs.Count >= 100) + return Task.FromResult(false); - _jobIds.Enqueue(blockDownloadJobInfo.JobId); - _jobs[blockDownloadJobInfo.JobId] = blockDownloadJobInfo; + _jobIds.Enqueue(blockDownloadJobInfo.JobId); + _jobs[blockDownloadJobInfo.JobId] = blockDownloadJobInfo; - return Task.FromResult(true); - } + return Task.FromResult(true); + } - public Task GetFirstWaitingJobAsync() + public Task GetFirstWaitingJobAsync() + { + while (true) { - while (true) - { - if (!_jobIds.TryPeek(out var jobId)) - { - return Task.FromResult(null); - } - - if (_jobs.TryGetValue(jobId, out var blockDownloadJobInfo)) - { - return Task.FromResult(blockDownloadJobInfo); - } - - _jobIds.TryDequeue(out _); - } - } + if (!_jobIds.TryPeek(out var jobId)) return Task.FromResult(null); - public Task UpdateAsync(BlockDownloadJobInfo blockDownloadJobInfo) - { - _jobs[blockDownloadJobInfo.JobId] = blockDownloadJobInfo; - return Task.CompletedTask; - } + if (_jobs.TryGetValue(jobId, out var blockDownloadJobInfo)) return Task.FromResult(blockDownloadJobInfo); - public Task RemoveAsync(string jobId) - { - _jobs.TryRemove(jobId, out _); - return Task.CompletedTask; + _jobIds.TryDequeue(out _); } } + + public Task UpdateAsync(BlockDownloadJobInfo blockDownloadJobInfo) + { + _jobs[blockDownloadJobInfo.JobId] = blockDownloadJobInfo; + return Task.CompletedTask; + } + + public Task RemoveAsync(string jobId) + { + _jobs.TryRemove(jobId, out _); + return Task.CompletedTask; + } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Types/BlockDownloadJobInfo.cs b/src/AElf.OS/BlockSync/Types/BlockDownloadJobInfo.cs index 57827478e8..a47d9740f6 100644 --- a/src/AElf.OS/BlockSync/Types/BlockDownloadJobInfo.cs +++ b/src/AElf.OS/BlockSync/Types/BlockDownloadJobInfo.cs @@ -1,26 +1,25 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.OS.BlockSync.Types +namespace AElf.OS.BlockSync.Types; + +public class BlockDownloadJobInfo { - public class BlockDownloadJobInfo - { - public string JobId { get; set; } - - public Hash TargetBlockHash { get; set; } + public string JobId { get; set; } + + public Hash TargetBlockHash { get; set; } - public long TargetBlockHeight { get; set; } + public long TargetBlockHeight { get; set; } - public string SuggestedPeerPubkey { get; set; } + public string SuggestedPeerPubkey { get; set; } - public int BatchRequestBlockCount { get; set; } + public int BatchRequestBlockCount { get; set; } - public Hash CurrentTargetBlockHash { get; set; } + public Hash CurrentTargetBlockHash { get; set; } - public long CurrentTargetBlockHeight { get; set; } + public long CurrentTargetBlockHeight { get; set; } - public Timestamp Deadline { get; set; } + public Timestamp Deadline { get; set; } - public bool IsFinished { get; set; } - } + public bool IsFinished { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Types/DownloadBlocksResult.cs b/src/AElf.OS/BlockSync/Types/DownloadBlocksResult.cs index 3343910d9b..4600e8c9cc 100644 --- a/src/AElf.OS/BlockSync/Types/DownloadBlocksResult.cs +++ b/src/AElf.OS/BlockSync/Types/DownloadBlocksResult.cs @@ -1,15 +1,14 @@ using AElf.Types; -namespace AElf.OS.BlockSync.Types +namespace AElf.OS.BlockSync.Types; + +public class DownloadBlocksResult { - public class DownloadBlocksResult - { - public bool Success { get; set; } - - public int DownloadBlockCount { get; set; } + public bool Success { get; set; } + + public int DownloadBlockCount { get; set; } - public Hash LastDownloadBlockHash { get; set; } + public Hash LastDownloadBlockHash { get; set; } - public long LastDownloadBlockHeight { get; set; } - } + public long LastDownloadBlockHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.OS/BlockSync/Worker/BlockDownloadWorker.cs b/src/AElf.OS/BlockSync/Worker/BlockDownloadWorker.cs index d488644048..d5abecbcdc 100644 --- a/src/AElf.OS/BlockSync/Worker/BlockDownloadWorker.cs +++ b/src/AElf.OS/BlockSync/Worker/BlockDownloadWorker.cs @@ -7,198 +7,191 @@ using AElf.OS.BlockSync.Dto; using AElf.OS.BlockSync.Infrastructure; using AElf.OS.BlockSync.Types; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Microsoft.Extensions.DependencyInjection; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Threading; -namespace AElf.OS.BlockSync.Worker +namespace AElf.OS.BlockSync.Worker; + +public class BlockDownloadWorker : AsyncPeriodicBackgroundWorkerBase { - public class BlockDownloadWorker : AsyncPeriodicBackgroundWorkerBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + private readonly IBlockDownloadService _blockDownloadService; + private readonly BlockSyncOptions _blockSyncOptions; + + public BlockDownloadWorker(AbpAsyncTimer timer, + IBlockchainService blockchainService, + IBlockDownloadService blockDownloadService, + IBlockDownloadJobStore blockDownloadJobStore, + IServiceScopeFactory serviceScopeFactory, + IOptionsSnapshot blockSyncOptions) + : base(timer, serviceScopeFactory) { - private readonly IBlockchainService _blockchainService; - private readonly IBlockDownloadService _blockDownloadService; - private readonly IBlockDownloadJobStore _blockDownloadJobStore; - private readonly BlockSyncOptions _blockSyncOptions; - - public BlockDownloadWorker(AbpAsyncTimer timer, - IBlockchainService blockchainService, - IBlockDownloadService blockDownloadService, - IBlockDownloadJobStore blockDownloadJobStore, - IServiceScopeFactory serviceScopeFactory, - IOptionsSnapshot blockSyncOptions) - : base(timer, serviceScopeFactory) - { - _blockchainService = blockchainService; - _blockDownloadService = blockDownloadService; - _blockDownloadJobStore = blockDownloadJobStore; - _blockSyncOptions = blockSyncOptions.Value; - - Timer.Period = _blockSyncOptions.BlockDownloadTimerPeriod; - } + _blockchainService = blockchainService; + _blockDownloadService = blockDownloadService; + _blockDownloadJobStore = blockDownloadJobStore; + _blockSyncOptions = blockSyncOptions.Value; - protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) - { - await ProcessDownloadJobAsync(); - } + Timer.Period = _blockSyncOptions.BlockDownloadTimerPeriod; + } + + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await ProcessDownloadJobAsync(); + } - internal async Task ProcessDownloadJobAsync() + internal async Task ProcessDownloadJobAsync() + { + while (true) { - while (true) + var chain = await _blockchainService.GetChainAsync(); + var jobInfo = await GetFirstAvailableWaitingJobAsync(chain); + + try { - var chain = await _blockchainService.GetChainAsync(); - var jobInfo = await GetFirstAvailableWaitingJobAsync(chain); + if (!ValidateBeforeDownload(jobInfo)) return; - try + if (jobInfo.IsFinished) { - if (!ValidateBeforeDownload(jobInfo)) - { - return; - } + await RemoveJobAndTargetStateAsync(jobInfo); + continue; + } - if (jobInfo.IsFinished) - { - await RemoveJobAndTargetStateAsync(jobInfo); - continue; - } + Logger.LogDebug( + $"Execute download job: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}, TargetBlockHeight:{jobInfo.TargetBlockHeight}, SuggestedPeerPubkey:{jobInfo.SuggestedPeerPubkey}."); - Logger.LogDebug( - $"Execute download job: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}, TargetBlockHeight:{jobInfo.TargetBlockHeight}, SuggestedPeerPubkey:{jobInfo.SuggestedPeerPubkey}."); - - var downloadResult = await DownloadBlocksAsync(chain, jobInfo); - - if (downloadResult.DownloadBlockCount == 0) - { - Logger.LogDebug( - $"Download block job finished: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}, TargetBlockHeight:{jobInfo.TargetBlockHeight}."); - await RemoveJobAndTargetStateAsync(jobInfo); - continue; - } - - _blockDownloadService.RemoveDownloadJobTargetState(jobInfo.CurrentTargetBlockHash); - - jobInfo.Deadline = TimestampHelper.GetUtcNow().AddMilliseconds(downloadResult.DownloadBlockCount * 300); - jobInfo.CurrentTargetBlockHash = downloadResult.LastDownloadBlockHash; - jobInfo.CurrentTargetBlockHeight = downloadResult.LastDownloadBlockHeight; - jobInfo.IsFinished = downloadResult.DownloadBlockCount < _blockSyncOptions.MaxBlockDownloadCount; - await _blockDownloadJobStore.UpdateAsync(jobInfo); + var downloadResult = await DownloadBlocksAsync(chain, jobInfo); - Logger.LogDebug( - $"Current download block job finished: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}."); - return; - } - catch (Exception e) + if (downloadResult.DownloadBlockCount == 0) { + Logger.LogDebug( + $"Download block job finished: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}, TargetBlockHeight:{jobInfo.TargetBlockHeight}."); await RemoveJobAndTargetStateAsync(jobInfo); - Logger.LogError(e,"Handle download job failed."); - throw; + continue; } - } - } - - private async Task GetFirstAvailableWaitingJobAsync(Chain chain) - { - while (true) - { - var blockDownloadJob = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - if (blockDownloadJob == null) - return null; + _blockDownloadService.RemoveDownloadJobTargetState(jobInfo.CurrentTargetBlockHash); - if (blockDownloadJob.CurrentTargetBlockHeight == 0 && - blockDownloadJob.TargetBlockHeight <= chain.BestChainHeight) - { - await _blockDownloadJobStore.RemoveAsync(blockDownloadJob.JobId); - continue; - } + jobInfo.Deadline = TimestampHelper.GetUtcNow().AddMilliseconds(downloadResult.DownloadBlockCount * 300); + jobInfo.CurrentTargetBlockHash = downloadResult.LastDownloadBlockHash; + jobInfo.CurrentTargetBlockHeight = downloadResult.LastDownloadBlockHeight; + jobInfo.IsFinished = downloadResult.DownloadBlockCount < _blockSyncOptions.MaxBlockDownloadCount; + await _blockDownloadJobStore.UpdateAsync(jobInfo); - return blockDownloadJob; + Logger.LogDebug( + $"Current download block job finished: CurrentTargetBlockHeight: {jobInfo.CurrentTargetBlockHeight}."); + return; + } + catch (Exception e) + { + await RemoveJobAndTargetStateAsync(jobInfo); + Logger.LogError(e, "Handle download job failed."); + throw; } } + } - private bool ValidateBeforeDownload(BlockDownloadJobInfo blockDownloadJobInfo) + private async Task GetFirstAvailableWaitingJobAsync(Chain chain) + { + while (true) { - if (blockDownloadJobInfo == null) - return false; + var blockDownloadJob = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - if (!_blockDownloadService.ValidateQueueAvailabilityBeforeDownload()) - return false; + if (blockDownloadJob == null) + return null; - if (blockDownloadJobInfo.CurrentTargetBlockHash != null - && _blockDownloadService.IsNotReachedDownloadTarget(blockDownloadJobInfo.CurrentTargetBlockHash) - && TimestampHelper.GetUtcNow() < blockDownloadJobInfo.Deadline) - return false; + if (blockDownloadJob.CurrentTargetBlockHeight == 0 && + blockDownloadJob.TargetBlockHeight <= chain.BestChainHeight) + { + await _blockDownloadJobStore.RemoveAsync(blockDownloadJob.JobId); + continue; + } - return true; + return blockDownloadJob; } + } - private async Task DownloadBlocksAsync(Chain chain, BlockDownloadJobInfo jobInfo) + private bool ValidateBeforeDownload(BlockDownloadJobInfo blockDownloadJobInfo) + { + if (blockDownloadJobInfo == null) + return false; + + if (!_blockDownloadService.ValidateQueueAvailabilityBeforeDownload()) + return false; + + if (blockDownloadJobInfo.CurrentTargetBlockHash != null + && _blockDownloadService.IsNotReachedDownloadTarget(blockDownloadJobInfo.CurrentTargetBlockHash) + && TimestampHelper.GetUtcNow() < blockDownloadJobInfo.Deadline) + return false; + + return true; + } + + private async Task DownloadBlocksAsync(Chain chain, BlockDownloadJobInfo jobInfo) + { + var downloadResult = new DownloadBlocksResult(); + if (jobInfo.CurrentTargetBlockHeight == 0) { - var downloadResult = new DownloadBlocksResult(); - if (jobInfo.CurrentTargetBlockHeight == 0) + // Download blocks from longest chain + downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - // Download blocks from longest chain + PreviousBlockHash = chain.LongestChainHash, + PreviousBlockHeight = chain.LongestChainHeight, + BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, + SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, + UseSuggestedPeer = true + }); + // Download blocks from best chain + if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - PreviousBlockHash = chain.LongestChainHash, - PreviousBlockHeight = chain.LongestChainHeight, + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, UseSuggestedPeer = true }); - // Download blocks from best chain - if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) - { - downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, - SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - UseSuggestedPeer = true - }); - } - // Download blocks from LIB - if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) - { - Logger.LogDebug($"Resynchronize from lib, lib height: {chain.LastIrreversibleBlockHeight}."); - downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.LastIrreversibleBlockHash, - PreviousBlockHeight = chain.LastIrreversibleBlockHeight, - BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, - SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - UseSuggestedPeer = true - }); - } - - } - // If last target block didn't become the longest chain, stop this job. - else if (jobInfo.CurrentTargetBlockHeight <= chain.LongestChainHeight + 8) + // Download blocks from LIB + if (downloadResult.Success && downloadResult.DownloadBlockCount == 0) { + Logger.LogDebug($"Resynchronize from lib, lib height: {chain.LastIrreversibleBlockHeight}."); downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - PreviousBlockHash = jobInfo.CurrentTargetBlockHash, - PreviousBlockHeight = jobInfo.CurrentTargetBlockHeight, + PreviousBlockHash = chain.LastIrreversibleBlockHash, + PreviousBlockHeight = chain.LastIrreversibleBlockHeight, BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - UseSuggestedPeer = false + UseSuggestedPeer = true }); } - - return downloadResult; } - - private async Task RemoveJobAndTargetStateAsync(BlockDownloadJobInfo blockDownloadJobInfo) + // If last target block didn't become the longest chain, stop this job. + else if (jobInfo.CurrentTargetBlockHeight <= chain.LongestChainHeight + 8) { - await _blockDownloadJobStore.RemoveAsync(blockDownloadJobInfo.JobId); - _blockDownloadService.RemoveDownloadJobTargetState(blockDownloadJobInfo.CurrentTargetBlockHash); + downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto + { + PreviousBlockHash = jobInfo.CurrentTargetBlockHash, + PreviousBlockHeight = jobInfo.CurrentTargetBlockHeight, + BatchRequestBlockCount = jobInfo.BatchRequestBlockCount, + SuggestedPeerPubkey = jobInfo.SuggestedPeerPubkey, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, + UseSuggestedPeer = false + }); } + + return downloadResult; + } + + private async Task RemoveJobAndTargetStateAsync(BlockDownloadJobInfo blockDownloadJobInfo) + { + await _blockDownloadJobStore.RemoveAsync(blockDownloadJobInfo.JobId); + _blockDownloadService.RemoveDownloadJobTargetState(blockDownloadJobInfo.CurrentTargetBlockHash); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/AbnormalPeerEventHandler.cs b/src/AElf.OS/Handlers/AbnormalPeerEventHandler.cs index 6b3778c37a..6ef4f3d272 100644 --- a/src/AElf.OS/Handlers/AbnormalPeerEventHandler.cs +++ b/src/AElf.OS/Handlers/AbnormalPeerEventHandler.cs @@ -6,27 +6,26 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class AbnormalPeerEventHandler : ILocalEventHandler, ITransientDependency { - public class AbnormalPeerEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly INetworkService _networkService; + private readonly INetworkService _networkService; - public ILogger Logger { get; set; } + public AbnormalPeerEventHandler(INetworkService networkService) + { + Logger = NullLogger.Instance; - public AbnormalPeerEventHandler(INetworkService networkService) - { - Logger = NullLogger.Instance; + _networkService = networkService; + } - _networkService = networkService; - } + public ILogger Logger { get; set; } - public async Task HandleEventAsync(AbnormalPeerFoundEventData eventData) - { - Logger.LogDebug( - $"Remove abnormal peer: {eventData.PeerPubkey}, block hash: {eventData.BlockHash}, block height: {eventData.BlockHeight}"); + public async Task HandleEventAsync(AbnormalPeerFoundEventData eventData) + { + Logger.LogDebug( + $"Remove abnormal peer: {eventData.PeerPubkey}, block hash: {eventData.BlockHash}, block height: {eventData.BlockHeight}"); - await _networkService.RemovePeerByPubkeyAsync(eventData.PeerPubkey); - } + await _networkService.RemovePeerByPubkeyAsync(eventData.PeerPubkey); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/BlockAcceptedEventHandler.cs b/src/AElf.OS/Handlers/BlockAcceptedEventHandler.cs index ec8d159653..01072ff1e4 100644 --- a/src/AElf.OS/Handlers/BlockAcceptedEventHandler.cs +++ b/src/AElf.OS/Handlers/BlockAcceptedEventHandler.cs @@ -1,45 +1,36 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Events; -using AElf.OS.BlockSync.Application; -using AElf.OS.BlockSync.Infrastructure; using AElf.OS.Network.Application; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class BlockAcceptedEventHandler : ILocalEventHandler, ITransientDependency { - public class BlockAcceptedEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly INetworkService _networkService; - private readonly ISyncStateService _syncStateService; - private readonly ITaskQueueManager _taskQueueManager; + private readonly INetworkService _networkService; + private readonly ISyncStateService _syncStateService; + private readonly ITaskQueueManager _taskQueueManager; - public BlockAcceptedEventHandler(INetworkService networkService, ISyncStateService syncStateService, - ITaskQueueManager taskQueueManager) - { - _taskQueueManager = taskQueueManager; - _networkService = networkService; - _syncStateService = syncStateService; - } + public BlockAcceptedEventHandler(INetworkService networkService, ISyncStateService syncStateService, + ITaskQueueManager taskQueueManager) + { + _taskQueueManager = taskQueueManager; + _networkService = networkService; + _syncStateService = syncStateService; + } - public Task HandleEventAsync(BlockAcceptedEvent eventData) - { - if (_syncStateService.SyncState == SyncState.Finished) - { - // if sync is finished we announce the block - _networkService.BroadcastAnnounceAsync(eventData.Block.Header); - } - else if (_syncStateService.SyncState == SyncState.Syncing) - { - // if syncing and the block is higher the current target, try and update. - if (_syncStateService.GetCurrentSyncTarget() <= eventData.Block.Header.Height) - { - _taskQueueManager.Enqueue(async () => { await _syncStateService.UpdateSyncStateAsync(); }, - OSConstants.InitialSyncQueueName); - } - } + public Task HandleEventAsync(BlockAcceptedEvent eventData) + { + if (_syncStateService.SyncState == SyncState.Finished) + // if sync is finished we announce the block + _networkService.BroadcastAnnounceAsync(eventData.Block.Header); + else if (_syncStateService.SyncState == SyncState.Syncing) + // if syncing and the block is higher the current target, try and update. + if (_syncStateService.GetCurrentSyncTarget() <= eventData.Block.Header.Height) + _taskQueueManager.Enqueue(async () => { await _syncStateService.UpdateSyncStateAsync(); }, + OSConstants.InitialSyncQueueName); - return Task.CompletedTask; - } + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/BlockMinedEventHandler.cs b/src/AElf.OS/Handlers/BlockMinedEventHandler.cs index 8ce6cf6cc1..dfd717c4e4 100644 --- a/src/AElf.OS/Handlers/BlockMinedEventHandler.cs +++ b/src/AElf.OS/Handlers/BlockMinedEventHandler.cs @@ -8,51 +8,44 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class BlockMinedEventHandler : ILocalEventHandler, ITransientDependency { - public class BlockMinedEventHandler : ILocalEventHandler, ITransientDependency - { - private readonly INetworkService _networkService; - private readonly IBlockchainService _blockchainService; - private readonly ISyncStateService _syncStateService; + private readonly IBlockchainService _blockchainService; + private readonly INetworkService _networkService; + private readonly ISyncStateService _syncStateService; - public ILogger Logger { get; set; } + public BlockMinedEventHandler(INetworkService networkService, IBlockchainService blockchainService, + ISyncStateService syncStateService) + { + _networkService = networkService; + _blockchainService = blockchainService; + _syncStateService = syncStateService; - public BlockMinedEventHandler(INetworkService networkService, IBlockchainService blockchainService, - ISyncStateService syncStateService) - { - _networkService = networkService; - _blockchainService = blockchainService; - _syncStateService = syncStateService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public async Task HandleEventAsync(BlockMinedEventData eventData) - { - if (_syncStateService.SyncState != SyncState.Finished) - { - return; - } + public async Task HandleEventAsync(BlockMinedEventData eventData) + { + if (_syncStateService.SyncState != SyncState.Finished) return; - if (eventData?.BlockHeader == null) - { - return; - } + if (eventData?.BlockHeader == null) return; - var blockWithTransactions = - await _blockchainService.GetBlockWithTransactionsByHashAsync(eventData.BlockHeader.GetHash()); + var blockWithTransactions = + await _blockchainService.GetBlockWithTransactionsByHashAsync(eventData.BlockHeader.GetHash()); - if (blockWithTransactions == null) - { - Logger.LogWarning($"Could not find {eventData.BlockHeader.GetHash()}."); - return; - } + if (blockWithTransactions == null) + { + Logger.LogWarning($"Could not find {eventData.BlockHeader.GetHash()}."); + return; + } - Logger.LogDebug( - $"Got full block hash {eventData.BlockHeader.GetHash()}, height {eventData.BlockHeader.Height}"); + Logger.LogDebug( + $"Got full block hash {eventData.BlockHeader.GetHash()}, height {eventData.BlockHeader.Height}"); - var _ = _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions); - } + var _ = _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/Network/AnnouncementReceivedEventHandler.cs b/src/AElf.OS/Handlers/Network/AnnouncementReceivedEventHandler.cs index 56bd44e52e..9176b4200b 100644 --- a/src/AElf.OS/Handlers/Network/AnnouncementReceivedEventHandler.cs +++ b/src/AElf.OS/Handlers/Network/AnnouncementReceivedEventHandler.cs @@ -11,52 +11,50 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class AnnouncementReceivedEventHandler : ILocalEventHandler, ITransientDependency { - public class AnnouncementReceivedEventHandler : ILocalEventHandler, ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly BlockSyncOptions _blockSyncOptions; + + private readonly IBlockSyncService _blockSyncService; + private readonly IBlockSyncValidationService _blockSyncValidationService; + + public AnnouncementReceivedEventHandler(IBlockSyncService blockSyncService, + IBlockSyncValidationService blockSyncValidationService, + IBlockchainService blockchainService, + IOptionsSnapshot blockSyncOptions) { - public ILogger Logger { get; set; } + _blockSyncService = blockSyncService; + _blockSyncValidationService = blockSyncValidationService; + _blockchainService = blockchainService; + _blockSyncOptions = blockSyncOptions.Value; - private readonly IBlockSyncService _blockSyncService; - private readonly IBlockSyncValidationService _blockSyncValidationService; - private readonly IBlockchainService _blockchainService; - private readonly BlockSyncOptions _blockSyncOptions; + Logger = NullLogger.Instance; + } - public AnnouncementReceivedEventHandler(IBlockSyncService blockSyncService, - IBlockSyncValidationService blockSyncValidationService, - IBlockchainService blockchainService, - IOptionsSnapshot blockSyncOptions) - { - _blockSyncService = blockSyncService; - _blockSyncValidationService = blockSyncValidationService; - _blockchainService = blockchainService; - _blockSyncOptions = blockSyncOptions.Value; - - Logger = NullLogger.Instance; - } - - public Task HandleEventAsync(AnnouncementReceivedEventData eventData) - { - var _ = ProcessNewBlockAsync(eventData.Announce, eventData.SenderPubKey); - return Task.CompletedTask; - } + public ILogger Logger { get; set; } + + public Task HandleEventAsync(AnnouncementReceivedEventData eventData) + { + var _ = ProcessNewBlockAsync(eventData.Announce, eventData.SenderPubKey); + return Task.CompletedTask; + } + + private async Task ProcessNewBlockAsync(BlockAnnouncement blockAnnouncement, string senderPubkey) + { + var chain = await _blockchainService.GetChainAsync(); + + if (!await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, + senderPubkey)) return; - private async Task ProcessNewBlockAsync(BlockAnnouncement blockAnnouncement, string senderPubkey) + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - var chain = await _blockchainService.GetChainAsync(); - - if (!await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, senderPubkey)) - { - return; - } - - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = blockAnnouncement.BlockHash, - SyncBlockHeight = blockAnnouncement.BlockHeight, - SuggestedPeerPubkey = senderPubkey, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount - }); - } + SyncBlockHash = blockAnnouncement.BlockHash, + SyncBlockHeight = blockAnnouncement.BlockHeight, + SuggestedPeerPubkey = senderPubkey, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount + }); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/Network/BlockReceivedEventHandler.cs b/src/AElf.OS/Handlers/Network/BlockReceivedEventHandler.cs index 319665b5e8..381a5dbec0 100644 --- a/src/AElf.OS/Handlers/Network/BlockReceivedEventHandler.cs +++ b/src/AElf.OS/Handlers/Network/BlockReceivedEventHandler.cs @@ -11,55 +11,52 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class BlockReceivedEventHandler : ILocalEventHandler, ITransientDependency { - public class BlockReceivedEventHandler : ILocalEventHandler, ITransientDependency + private readonly IBlockchainService _blockchainService; + private readonly BlockSyncOptions _blockSyncOptions; + private readonly IBlockSyncService _blockSyncService; + private readonly IBlockSyncValidationService _blockSyncValidationService; + + public BlockReceivedEventHandler(IBlockSyncService blockSyncService, + IBlockSyncValidationService blockSyncValidationService, + IBlockchainService blockchainService, + IOptionsSnapshot blockSyncOptions) { - private readonly IBlockSyncService _blockSyncService; - private readonly IBlockSyncValidationService _blockSyncValidationService; - private readonly IBlockchainService _blockchainService; - private readonly BlockSyncOptions _blockSyncOptions; - - public ILogger Logger { get; set; } + _blockSyncService = blockSyncService; + _blockSyncValidationService = blockSyncValidationService; + _blockchainService = blockchainService; + _blockSyncOptions = blockSyncOptions.Value; - public BlockReceivedEventHandler(IBlockSyncService blockSyncService, - IBlockSyncValidationService blockSyncValidationService, - IBlockchainService blockchainService, - IOptionsSnapshot blockSyncOptions) - { - _blockSyncService = blockSyncService; - _blockSyncValidationService = blockSyncValidationService; - _blockchainService = blockchainService; - _blockSyncOptions = blockSyncOptions.Value; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public Task HandleEventAsync(BlockReceivedEvent eventData) - { - var _ = ProcessNewBlockAsync(eventData.BlockWithTransactions, eventData.SenderPubkey); - return Task.CompletedTask; - } + public Task HandleEventAsync(BlockReceivedEvent eventData) + { + var _ = ProcessNewBlockAsync(eventData.BlockWithTransactions, eventData.SenderPubkey); + return Task.CompletedTask; + } - private async Task ProcessNewBlockAsync(BlockWithTransactions blockWithTransactions, string senderPubkey) - { - var chain = await _blockchainService.GetChainAsync(); + private async Task ProcessNewBlockAsync(BlockWithTransactions blockWithTransactions, string senderPubkey) + { + var chain = await _blockchainService.GetChainAsync(); - Logger.LogDebug( - $"About to process new block: {blockWithTransactions.Header.GetHash()} of height {blockWithTransactions.Height}"); + Logger.LogDebug( + $"About to process new block: {blockWithTransactions.Header.GetHash()} of height {blockWithTransactions.Height}"); - if (!await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, blockWithTransactions, + if (!await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, blockWithTransactions, senderPubkey)) - { - return; - } + return; - await _blockSyncService.SyncByBlockAsync(chain, new SyncBlockDto - { - BlockWithTransactions = blockWithTransactions, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - SuggestedPeerPubkey = senderPubkey - }); - } + await _blockSyncService.SyncByBlockAsync(chain, new SyncBlockDto + { + BlockWithTransactions = blockWithTransactions, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + SuggestedPeerPubkey = senderPubkey + }); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/Network/NetworkInitializedEventHandler.cs b/src/AElf.OS/Handlers/Network/NetworkInitializedEventHandler.cs index e5989ff75e..7e179a280a 100644 --- a/src/AElf.OS/Handlers/Network/NetworkInitializedEventHandler.cs +++ b/src/AElf.OS/Handlers/Network/NetworkInitializedEventHandler.cs @@ -4,20 +4,19 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class NetworkInitializedEventHandler : ILocalEventHandler, ITransientDependency { - public class NetworkInitializedEventHandler : ILocalEventHandler, ITransientDependency + private readonly ISyncStateService _syncStateService; + + public NetworkInitializedEventHandler(ISyncStateService syncStateService) { - private readonly ISyncStateService _syncStateService; + _syncStateService = syncStateService; + } - public NetworkInitializedEventHandler(ISyncStateService syncStateService) - { - _syncStateService = syncStateService; - } - - public async Task HandleEventAsync(NetworkInitializedEvent eventData) - { - await _syncStateService.StartSyncAsync(); - } + public async Task HandleEventAsync(NetworkInitializedEvent eventData) + { + await _syncStateService.StartSyncAsync(); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/Network/PeerConnectedEventHandler.cs b/src/AElf.OS/Handlers/Network/PeerConnectedEventHandler.cs index b47129c52e..806d5fbdcc 100644 --- a/src/AElf.OS/Handlers/Network/PeerConnectedEventHandler.cs +++ b/src/AElf.OS/Handlers/Network/PeerConnectedEventHandler.cs @@ -7,34 +7,34 @@ using Volo.Abp.EventBus; using Volo.Abp.EventBus.Local; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class PeerConnectedEventHandler : ILocalEventHandler, ITransientDependency { - public class PeerConnectedEventHandler : ILocalEventHandler, ITransientDependency + private readonly IPeerDiscoveryService _peerDiscoveryService; + + public PeerConnectedEventHandler(IPeerDiscoveryService peerDiscoveryService) { - public ILogger Logger { get; set; } - public ILocalEventBus LocalEventBus { get; set; } + _peerDiscoveryService = peerDiscoveryService; + } - private readonly IPeerDiscoveryService _peerDiscoveryService; + public ILogger Logger { get; set; } + public ILocalEventBus LocalEventBus { get; set; } - public PeerConnectedEventHandler(IPeerDiscoveryService peerDiscoveryService) - { - _peerDiscoveryService = peerDiscoveryService; - } + public async Task HandleEventAsync(PeerConnectedEventData eventData) + { + Logger.LogDebug($"Peer connection event {eventData.NodeInfo}"); + + await _peerDiscoveryService.AddNodeAsync(eventData.NodeInfo); - public async Task HandleEventAsync(PeerConnectedEventData eventData) + var blockAnnouncement = new BlockAnnouncement { - Logger.LogDebug($"Peer connection event {eventData.NodeInfo}"); - - await _peerDiscoveryService.AddNodeAsync(eventData.NodeInfo); - - var blockAnnouncement = new BlockAnnouncement { - BlockHash = eventData.BestChainHash, - BlockHeight = eventData.BestChainHeight - }; - - var announcement = new AnnouncementReceivedEventData(blockAnnouncement, eventData.NodeInfo.Pubkey.ToHex()); - - await LocalEventBus.PublishAsync(announcement); - } + BlockHash = eventData.BestChainHash, + BlockHeight = eventData.BestChainHeight + }; + + var announcement = new AnnouncementReceivedEventData(blockAnnouncement, eventData.NodeInfo.Pubkey.ToHex()); + + await LocalEventBus.PublishAsync(announcement); } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/Network/TransactionAcceptedEventHandler.cs b/src/AElf.OS/Handlers/Network/TransactionAcceptedEventHandler.cs index e2522dad40..26f7d2f2ef 100644 --- a/src/AElf.OS/Handlers/Network/TransactionAcceptedEventHandler.cs +++ b/src/AElf.OS/Handlers/Network/TransactionAcceptedEventHandler.cs @@ -4,16 +4,15 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class TransactionAcceptedEventHandler : ILocalEventHandler, ITransientDependency { - public class TransactionAcceptedEventHandler : ILocalEventHandler, ITransientDependency - { - public INetworkService NetworkService { get; set; } + public INetworkService NetworkService { get; set; } - public Task HandleEventAsync(TransactionAcceptedEvent eventData) - { - _ = NetworkService.BroadcastTransactionAsync(eventData.Transaction); - return Task.CompletedTask; - } + public Task HandleEventAsync(TransactionAcceptedEvent eventData) + { + _ = NetworkService.BroadcastTransactionAsync(eventData.Transaction); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/NewIrreversibleBlockFoundEventHandler.cs b/src/AElf.OS/Handlers/NewIrreversibleBlockFoundEventHandler.cs index 6dbede4bca..4a95c3397a 100644 --- a/src/AElf.OS/Handlers/NewIrreversibleBlockFoundEventHandler.cs +++ b/src/AElf.OS/Handlers/NewIrreversibleBlockFoundEventHandler.cs @@ -4,29 +4,25 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, + ITransientDependency { - public class NewIrreversibleBlockFoundEventHandler : ILocalEventHandler, - ITransientDependency - { - private readonly INetworkService _networkService; - private readonly ISyncStateService _syncStateService; + private readonly INetworkService _networkService; + private readonly ISyncStateService _syncStateService; - public NewIrreversibleBlockFoundEventHandler(INetworkService networkService, ISyncStateService syncStateService) - { - _networkService = networkService; - _syncStateService = syncStateService; - } + public NewIrreversibleBlockFoundEventHandler(INetworkService networkService, ISyncStateService syncStateService) + { + _networkService = networkService; + _syncStateService = syncStateService; + } - public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) - { - if (_syncStateService.SyncState != SyncState.Finished) - { - return Task.CompletedTask; - } + public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData) + { + if (_syncStateService.SyncState != SyncState.Finished) return Task.CompletedTask; - var _ = _networkService.BroadcastLibAnnounceAsync(eventData.BlockHash, eventData.BlockHeight); - return Task.CompletedTask; - } + var _ = _networkService.BroadcastLibAnnounceAsync(eventData.BlockHash, eventData.BlockHeight); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.OS/Handlers/TransactionExecutionValidationFailedEventHandler.cs b/src/AElf.OS/Handlers/TransactionExecutionValidationFailedEventHandler.cs index 31340438ee..f6b2e88115 100644 --- a/src/AElf.OS/Handlers/TransactionExecutionValidationFailedEventHandler.cs +++ b/src/AElf.OS/Handlers/TransactionExecutionValidationFailedEventHandler.cs @@ -6,30 +6,29 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class TransactionExecutionValidationFailedEventHandler : + ILocalEventHandler, + ITransientDependency { - public class TransactionExecutionValidationFailedEventHandler : - ILocalEventHandler, - ITransientDependency - { - private readonly IPeerInvalidTransactionProcessingService _peerInvalidTransactionProcessingService; + private readonly IPeerInvalidTransactionProcessingService _peerInvalidTransactionProcessingService; - public ILogger Logger { get; set; } + public TransactionExecutionValidationFailedEventHandler( + IPeerInvalidTransactionProcessingService peerInvalidTransactionProcessingService) + { + _peerInvalidTransactionProcessingService = peerInvalidTransactionProcessingService; - public TransactionExecutionValidationFailedEventHandler( - IPeerInvalidTransactionProcessingService peerInvalidTransactionProcessingService) - { - _peerInvalidTransactionProcessingService = peerInvalidTransactionProcessingService; + Logger = NullLogger.Instance; + } - Logger = NullLogger.Instance; - } + public ILogger Logger { get; set; } - public Task HandleEventAsync(TransactionExecutionValidationFailedEvent eventData) - { - Logger.LogDebug($"Received a transaction that failed to verify: {eventData.TransactionId}"); - _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(eventData.TransactionId); + public Task HandleEventAsync(TransactionExecutionValidationFailedEvent eventData) + { + Logger.LogDebug($"Received a transaction that failed to verify: {eventData.TransactionId}"); + _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(eventData.TransactionId); - return Task.CompletedTask; - } + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.OS/OSConstants.cs b/src/AElf.OS/OSConstants.cs index 523d5d698f..64296ce219 100644 --- a/src/AElf.OS/OSConstants.cs +++ b/src/AElf.OS/OSConstants.cs @@ -1,11 +1,8 @@ -using System; +namespace AElf.OS; -namespace AElf.OS +public class OSConstants { - public class OSConstants - { - public const string BlockFetchQueueName = "BlockFetchQueue"; - public const string BlockSyncAttachQueueName = "BlockSyncAttachQueue"; - public const string InitialSyncQueueName = "InitialSyncQueue"; - } + public const string BlockFetchQueueName = "BlockFetchQueue"; + public const string BlockSyncAttachQueueName = "BlockSyncAttachQueue"; + public const string InitialSyncQueueName = "InitialSyncQueue"; } \ No newline at end of file diff --git a/src/AElf.OS/Worker/PeerDiscoveryWorker.cs b/src/AElf.OS/Worker/PeerDiscoveryWorker.cs index bfaffaa0d9..4bf14e302e 100644 --- a/src/AElf.OS/Worker/PeerDiscoveryWorker.cs +++ b/src/AElf.OS/Worker/PeerDiscoveryWorker.cs @@ -8,77 +8,71 @@ using Volo.Abp.BackgroundWorkers; using Volo.Abp.Threading; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +public class PeerDiscoveryWorker : AsyncPeriodicBackgroundWorkerBase { - public class PeerDiscoveryWorker : AsyncPeriodicBackgroundWorkerBase + private readonly INetworkService _networkService; + private readonly IPeerDiscoveryService _peerDiscoveryService; + private readonly IReconnectionService _reconnectionService; + + public PeerDiscoveryWorker(AbpAsyncTimer timer, IPeerDiscoveryService peerDiscoveryService, + INetworkService networkService, + IReconnectionService reconnectionService, + IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory) { - private readonly IPeerDiscoveryService _peerDiscoveryService; - private readonly INetworkService _networkService; - private readonly IReconnectionService _reconnectionService; + _peerDiscoveryService = peerDiscoveryService; + Timer.Period = NetworkConstants.DefaultDiscoveryPeriod; - public new ILogger Logger { get; set; } + _networkService = networkService; + _reconnectionService = reconnectionService; - public PeerDiscoveryWorker(AbpAsyncTimer timer, IPeerDiscoveryService peerDiscoveryService, - INetworkService networkService, - IReconnectionService reconnectionService, - IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory) - { - _peerDiscoveryService = peerDiscoveryService; - Timer.Period = NetworkConstants.DefaultDiscoveryPeriod; + Logger = NullLogger.Instance; + } - _networkService = networkService; - _reconnectionService = reconnectionService; + public new ILogger Logger { get; set; } - Logger = NullLogger.Instance; - } + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await ProcessPeerDiscoveryJobAsync(); + } - protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) - { - await ProcessPeerDiscoveryJobAsync(); - } + internal async Task ProcessPeerDiscoveryJobAsync() + { + await _peerDiscoveryService.RefreshNodeAsync(); - internal async Task ProcessPeerDiscoveryJobAsync() - { - await _peerDiscoveryService.RefreshNodeAsync(); + await _peerDiscoveryService.DiscoverNodesAsync(); - await _peerDiscoveryService.DiscoverNodesAsync(); + if (_networkService.IsPeerPoolFull()) return; - if (_networkService.IsPeerPoolFull()) + var nodes = await _peerDiscoveryService.GetNodesAsync(10); + foreach (var node in nodes.Nodes) + try { - return; - } - - var nodes = await _peerDiscoveryService.GetNodesAsync(10); - foreach (var node in nodes.Nodes) - { - try + if (_networkService.IsPeerPoolFull()) { - if (_networkService.IsPeerPoolFull()) - { - Logger.LogTrace("Peer pool is full, aborting add."); - break; - } - - var reconnectingPeer = _reconnectionService.GetReconnectingPeer(node.Endpoint); - if (reconnectingPeer != null) - { - Logger.LogDebug($"Peer {node.Endpoint} is already in the reconnection queue."); - continue; - } - - if (_networkService.GetPeerByPubkey(node.Pubkey.ToHex()) != null) - { - Logger.LogDebug($"Peer {node} is already in the peer pool."); - continue; - } + Logger.LogTrace("Peer pool is full, aborting add."); + break; + } - await _networkService.AddPeerAsync(node.Endpoint); + var reconnectingPeer = _reconnectionService.GetReconnectingPeer(node.Endpoint); + if (reconnectingPeer != null) + { + Logger.LogDebug($"Peer {node.Endpoint} is already in the reconnection queue."); + continue; } - catch (Exception e) + + if (_networkService.GetPeerByPubkey(node.Pubkey.ToHex()) != null) { - Logger.LogError(e, $"Exception connecting to {node.Endpoint}."); + Logger.LogDebug($"Peer {node} is already in the peer pool."); + continue; } + + await _networkService.AddPeerAsync(node.Endpoint); + } + catch (Exception e) + { + Logger.LogError(e, $"Exception connecting to {node.Endpoint}."); } - } } } \ No newline at end of file diff --git a/src/AElf.OS/Worker/PeerReconnectionWorker.cs b/src/AElf.OS/Worker/PeerReconnectionWorker.cs index 332d0804d9..d70b2cac6e 100644 --- a/src/AElf.OS/Worker/PeerReconnectionWorker.cs +++ b/src/AElf.OS/Worker/PeerReconnectionWorker.cs @@ -6,134 +6,134 @@ using AElf.OS.Network.Application; using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Threading; -using Microsoft.Extensions.DependencyInjection; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +public class PeerReconnectionWorker : AsyncPeriodicBackgroundWorkerBase { - public class PeerReconnectionWorker : AsyncPeriodicBackgroundWorkerBase + private readonly NetworkOptions _networkOptions; + private readonly INetworkService _networkService; + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public PeerReconnectionWorker(AbpAsyncTimer timer, IOptionsSnapshot networkOptions, + INetworkService networkService, IPeerPool peerPool, IReconnectionService reconnectionService, + IServiceScopeFactory serviceScopeFactory) + : base(timer, serviceScopeFactory) { - private readonly IPeerPool _peerPool; - private readonly IReconnectionService _reconnectionService; - private readonly INetworkService _networkService; + _peerPool = peerPool; + _reconnectionService = reconnectionService; + _networkService = networkService; + _networkOptions = networkOptions.Value; - private readonly NetworkOptions _networkOptions; + timer.Period = _networkOptions.PeerReconnectionPeriod; + } - public new ILogger Logger { get; set; } + public new ILogger Logger { get; set; } - public PeerReconnectionWorker(AbpAsyncTimer timer, IOptionsSnapshot networkOptions, - INetworkService networkService, IPeerPool peerPool, IReconnectionService reconnectionService, - IServiceScopeFactory serviceScopeFactory) - : base(timer, serviceScopeFactory) - { - _peerPool = peerPool; - _reconnectionService = reconnectionService; - _networkService = networkService; - _networkOptions = networkOptions.Value; + protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) + { + await DoReconnectionJobAsync(); + } - timer.Period = _networkOptions.PeerReconnectionPeriod; - } - - protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) - { - await DoReconnectionJobAsync(); - } + internal async Task DoReconnectionJobAsync() + { + CheckNtpClockDrift(); + + await _networkService.CheckPeersHealthAsync(); - internal async Task DoReconnectionJobAsync() + var peersToConnect = _reconnectionService.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow()); + + if (peersToConnect.Count <= 0) + return; + + foreach (var peerToConnect in peersToConnect) { - CheckNtpClockDrift(); - - await _networkService.CheckPeersHealthAsync(); - - var peersToConnect = _reconnectionService.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow()); + var peerEndpoint = peerToConnect.Endpoint; + if (!AElfPeerEndpointHelper.TryParse(peerEndpoint, out var parsed)) + { + if (!_reconnectionService.CancelReconnection(peerEndpoint)) + Logger.LogDebug($"Invalid {peerEndpoint}."); - if (peersToConnect.Count <= 0) - return; + continue; + } - foreach (var peerToConnect in peersToConnect) + // check that we haven't already reconnected to this node + if (_peerPool.FindPeerByEndpoint(parsed) != null) { - string peerEndpoint = peerToConnect.Endpoint; - if (!AElfPeerEndpointHelper.TryParse(peerEndpoint, out var parsed)) - { - if (!_reconnectionService.CancelReconnection(peerEndpoint)) - Logger.LogDebug($"Invalid {peerEndpoint}."); + Logger.LogDebug($"Peer {peerEndpoint} already in the pool, no need to reconnect."); - continue; - } + if (!_reconnectionService.CancelReconnection(peerEndpoint)) + Logger.LogDebug($"Could not find to {peerEndpoint}."); - // check that we haven't already reconnected to this node - if (_peerPool.FindPeerByEndpoint(parsed) != null) - { - Logger.LogDebug($"Peer {peerEndpoint} already in the pool, no need to reconnect."); + continue; + } - if (!_reconnectionService.CancelReconnection(peerEndpoint)) - Logger.LogDebug($"Could not find to {peerEndpoint}."); - - continue; - } + Logger.LogDebug($"Starting reconnection to {peerToConnect.Endpoint}."); - Logger.LogDebug($"Starting reconnection to {peerToConnect.Endpoint}."); + var connected = false; - var connected = false; - - try - { - connected = await _networkService.AddPeerAsync(peerEndpoint); - } - catch (Exception ex) - { - // down the stack the AddPeerAsync rethrows any exception, - // in order to continue this job, Exception has to be catched for now. - Logger.LogDebug(ex, $"Could not re-connect to {peerEndpoint}."); - } + try + { + connected = await _networkService.AddPeerAsync(peerEndpoint); + } + catch (Exception ex) + { + // down the stack the AddPeerAsync rethrows any exception, + // in order to continue this job, Exception has to be catched for now. + Logger.LogDebug(ex, $"Could not re-connect to {peerEndpoint}."); + } - if (connected) - { - Logger.LogDebug($"Reconnection to {peerEndpoint} succeeded."); + if (connected) + { + Logger.LogDebug($"Reconnection to {peerEndpoint} succeeded."); - if (!_reconnectionService.CancelReconnection(peerEndpoint)) - Logger.LogDebug($"Could not find {peerEndpoint}."); - } - else + if (!_reconnectionService.CancelReconnection(peerEndpoint)) + Logger.LogDebug($"Could not find {peerEndpoint}."); + } + else + { + var timeExtension = _networkOptions.PeerReconnectionPeriod * + (int)Math.Pow(2, ++peerToConnect.RetryCount); + peerToConnect.NextAttempt = TimestampHelper.GetUtcNow().AddMilliseconds(timeExtension); + + // if the option is set, verify that the next attempt does not exceed + // the maximum reconnection time. + if (_networkOptions.MaximumReconnectionTime != 0) { - var timeExtension = _networkOptions.PeerReconnectionPeriod * (int)Math.Pow(2, ++peerToConnect.RetryCount); - peerToConnect.NextAttempt = TimestampHelper.GetUtcNow().AddMilliseconds(timeExtension); + var maxReconnectionDate = peerToConnect.DisconnectionTime + + TimestampHelper.DurationFromMilliseconds(_networkOptions + .MaximumReconnectionTime); - // if the option is set, verify that the next attempt does not exceed - // the maximum reconnection time. - if (_networkOptions.MaximumReconnectionTime != 0) + if (peerToConnect.NextAttempt > maxReconnectionDate) { - var maxReconnectionDate = peerToConnect.DisconnectionTime + - TimestampHelper.DurationFromMilliseconds(_networkOptions.MaximumReconnectionTime); - - if (peerToConnect.NextAttempt > maxReconnectionDate) - { - _reconnectionService.CancelReconnection(peerEndpoint); - Logger.LogDebug($"Maximum reconnection time reached {peerEndpoint}, " + - $"next was {peerToConnect.NextAttempt}."); - - continue; - } - } + _reconnectionService.CancelReconnection(peerEndpoint); + Logger.LogDebug($"Maximum reconnection time reached {peerEndpoint}, " + + $"next was {peerToConnect.NextAttempt}."); - Logger.LogDebug($"Could not connect to {peerEndpoint}, next attempt {peerToConnect.NextAttempt}, " + - $"current retries {peerToConnect.RetryCount}."); + continue; + } } + + Logger.LogDebug($"Could not connect to {peerEndpoint}, next attempt {peerToConnect.NextAttempt}, " + + $"current retries {peerToConnect.RetryCount}."); } + } - void CheckNtpClockDrift() + void CheckNtpClockDrift() + { + try { - try - { - _networkService.CheckNtpDrift(); - } - catch (Exception) - { - // swallow any exception, we are not interested in anything else than valid checks. - } + _networkService.CheckNtpDrift(); + } + catch (Exception) + { + // swallow any exception, we are not interested in anything else than valid checks. } } } diff --git a/src/AElf.Runtime.CSharp.Core/AElf.Runtime.CSharp.Core.csproj b/src/AElf.Runtime.CSharp.Core/AElf.Runtime.CSharp.Core.csproj index a8dda100f0..8002eb8277 100644 --- a/src/AElf.Runtime.CSharp.Core/AElf.Runtime.CSharp.Core.csproj +++ b/src/AElf.Runtime.CSharp.Core/AElf.Runtime.CSharp.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,10 +10,10 @@ - - - + + + - + diff --git a/src/AElf.Runtime.CSharp.Core/ContractCodeLoadContext.cs b/src/AElf.Runtime.CSharp.Core/ContractCodeLoadContext.cs index c35306fd88..507ef7bdcc 100644 --- a/src/AElf.Runtime.CSharp.Core/ContractCodeLoadContext.cs +++ b/src/AElf.Runtime.CSharp.Core/ContractCodeLoadContext.cs @@ -1,41 +1,40 @@ -using System.Runtime.Loader; -using System.Reflection; +using System.Reflection; +using System.Runtime.Loader; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +/// +/// Smart contract running context which contains the contract assembly with a unique Api singleton. +/// +public class ContractCodeLoadContext : AssemblyLoadContext { - /// - /// Smart contract running context which contains the contract assembly with a unique Api singleton. - /// - public class ContractCodeLoadContext : AssemblyLoadContext + private readonly ISdkStreamManager _sdkStreamManager; + + public ContractCodeLoadContext(ISdkStreamManager sdkStreamManager) : base(true) { - private readonly ISdkStreamManager _sdkStreamManager; + _sdkStreamManager = sdkStreamManager; + } - public ContractCodeLoadContext(ISdkStreamManager sdkStreamManager) : base(isCollectible: true) - { - _sdkStreamManager = sdkStreamManager; - } + protected override Assembly Load(AssemblyName assemblyName) + { + return LoadFromFolderOrDefault(assemblyName); + } - protected override Assembly Load(AssemblyName assemblyName) + /// + /// Will trying to load every dll located in certain dir, + /// but only dlls start with "AElf.Sdk" will be loaded. + /// + /// + /// + private Assembly LoadFromFolderOrDefault(AssemblyName assemblyName) + { + if (assemblyName.Name.StartsWith("AElf.Sdk")) { - return LoadFromFolderOrDefault(assemblyName); + // Sdk assembly should NOT be shared + using var stream = _sdkStreamManager.GetStream(assemblyName); + return LoadFromStream(stream); } - /// - /// Will trying to load every dll located in certain dir, - /// but only dlls start with "AElf.Sdk" will be loaded. - /// - /// - /// - private Assembly LoadFromFolderOrDefault(AssemblyName assemblyName) - { - if (assemblyName.Name.StartsWith("AElf.Sdk")) - { - // Sdk assembly should NOT be shared - using var stream = _sdkStreamManager.GetStream(assemblyName); - return LoadFromStream(stream); - } - - return null; - } + return null; } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp.Core/Exceptions.cs b/src/AElf.Runtime.CSharp.Core/Exceptions.cs index 241e7f14e7..383144cb2f 100644 --- a/src/AElf.Runtime.CSharp.Core/Exceptions.cs +++ b/src/AElf.Runtime.CSharp.Core/Exceptions.cs @@ -1,26 +1,25 @@ using System; -namespace AElf.Runtime.CSharp.Core +namespace AElf.Runtime.CSharp.Core; + +public class InvalidMethodNameException : Exception { - public class InvalidMethodNameException : Exception + public InvalidMethodNameException() { - public InvalidMethodNameException() : base() - { - } + } - public InvalidMethodNameException(string message) : base(message) - { - } + public InvalidMethodNameException(string message) : base(message) + { } +} - public class RuntimeException : Exception +public class RuntimeException : Exception +{ + public RuntimeException() { - public RuntimeException() : base() - { - } + } - public RuntimeException(string message) : base(message) - { - } + public RuntimeException(string message) : base(message) + { } -} +} \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp.Core/ISdkStreamManager.cs b/src/AElf.Runtime.CSharp.Core/ISdkStreamManager.cs index 840bc52c12..c3bdc40a4a 100644 --- a/src/AElf.Runtime.CSharp.Core/ISdkStreamManager.cs +++ b/src/AElf.Runtime.CSharp.Core/ISdkStreamManager.cs @@ -1,10 +1,9 @@ using System.IO; using System.Reflection; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public interface ISdkStreamManager { - public interface ISdkStreamManager - { - Stream GetStream(AssemblyName assemblyName); - } + Stream GetStream(AssemblyName assemblyName); } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp.Core/RunnerOptions.cs b/src/AElf.Runtime.CSharp.Core/RunnerOptions.cs index eb7cbd1da5..c41cbb0536 100644 --- a/src/AElf.Runtime.CSharp.Core/RunnerOptions.cs +++ b/src/AElf.Runtime.CSharp.Core/RunnerOptions.cs @@ -1,15 +1,13 @@ -using System.Collections.Generic; using System.IO; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class RunnerOptions { - public class RunnerOptions + public RunnerOptions() { - public string SdkDir { get; set; } - - public RunnerOptions() - { - SdkDir = Path.GetDirectoryName(typeof(RunnerOptions).Assembly.Location); - } + SdkDir = Path.GetDirectoryName(typeof(RunnerOptions).Assembly.Location); } + + public string SdkDir { get; set; } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp.Core/SdkStreamManager.cs b/src/AElf.Runtime.CSharp.Core/SdkStreamManager.cs index 23c04bc4bc..5845eb432a 100644 --- a/src/AElf.Runtime.CSharp.Core/SdkStreamManager.cs +++ b/src/AElf.Runtime.CSharp.Core/SdkStreamManager.cs @@ -2,41 +2,39 @@ using System.IO; using System.Reflection; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class SdkStreamManager : ISdkStreamManager { - public class SdkStreamManager : ISdkStreamManager - { - private readonly ConcurrentDictionary _cachedSdkStreams = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _cachedSdkStreams = new(); - private readonly string _sdkDir; + private readonly string _sdkDir; + + public SdkStreamManager(string sdkDir) + { + _sdkDir = sdkDir; + } - public SdkStreamManager(string sdkDir) + public Stream GetStream(AssemblyName assemblyName) + { + // TODO: Handle version + var path = Path.Combine(_sdkDir, assemblyName.Name + ".dll"); + if (!File.Exists(path)) { - _sdkDir = sdkDir; + var assembly = Assembly.Load(assemblyName); + + path = assembly.Location; } - public Stream GetStream(AssemblyName assemblyName) + if (!_cachedSdkStreams.TryGetValue(path, out var buffer)) { - // TODO: Handle version - var path = Path.Combine(_sdkDir, assemblyName.Name + ".dll"); - if (!File.Exists(path)) - { - var assembly = Assembly.Load(assemblyName); - - path = assembly.Location; - } - - if (!_cachedSdkStreams.TryGetValue(path, out var buffer)) - { - using var fs = new FileStream(path, FileMode.Open, FileAccess.Read); - var length = (int)fs.Length; - buffer = new byte[length]; - fs.Read(buffer, 0, length); - _cachedSdkStreams.TryAdd(path, buffer); - } - - return new MemoryStream(buffer); + using var fs = new FileStream(path, FileMode.Open, FileAccess.Read); + var length = (int)fs.Length; + buffer = new byte[length]; + fs.Read(buffer, 0, length); + _cachedSdkStreams.TryAdd(path, buffer); } + + return new MemoryStream(buffer); } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj b/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj index de6f1feeab..ab7eccbf55 100644 --- a/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj +++ b/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/AElf.Runtime.CSharp.ExecutiveTokenPlugin.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,7 +9,7 @@ - + diff --git a/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/ExecutiveTokenPluginCSharpRuntimeAElfModule.cs b/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/ExecutiveTokenPluginCSharpRuntimeAElfModule.cs index 7c33fc1c8d..232889459a 100644 --- a/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/ExecutiveTokenPluginCSharpRuntimeAElfModule.cs +++ b/src/AElf.Runtime.CSharp.ExecutiveTokenPlugin/ExecutiveTokenPluginCSharpRuntimeAElfModule.cs @@ -2,10 +2,9 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Runtime.CSharp.ExecutiveTokenPlugin +namespace AElf.Runtime.CSharp.ExecutiveTokenPlugin; + +[DependsOn(typeof(SmartContractAElfModule))] +public class ExecutiveTokenPluginCSharpRuntimeAElfModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule))] - public class ExecutiveTokenPluginCSharpRuntimeAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/AElf.Runtime.CSharp.csproj b/src/AElf.Runtime.CSharp/AElf.Runtime.CSharp.csproj index 80ea220189..ff12b9c90d 100644 --- a/src/AElf.Runtime.CSharp/AElf.Runtime.CSharp.csproj +++ b/src/AElf.Runtime.CSharp/AElf.Runtime.CSharp.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,18 +10,18 @@ - TRACE;UNIT_TEST + TRACE;UNIT_TEST - - - - + + + + - + diff --git a/src/AElf.Runtime.CSharp/CSharpRuntimeAElfModule.cs b/src/AElf.Runtime.CSharp/CSharpRuntimeAElfModule.cs index 06f5589fe5..b4eec565a0 100644 --- a/src/AElf.Runtime.CSharp/CSharpRuntimeAElfModule.cs +++ b/src/AElf.Runtime.CSharp/CSharpRuntimeAElfModule.cs @@ -5,38 +5,37 @@ using Microsoft.Extensions.Options; using Volo.Abp.Modularity; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +[DependsOn(typeof(SmartContractAElfModule))] +public class CSharpRuntimeAElfModule : AElfModule { - [DependsOn(typeof(SmartContractAElfModule))] - public class CSharpRuntimeAElfModule : AElfModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - Configure(configuration.GetSection("Runner")); - } + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("Runner")); + } - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(provider => { - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new CSharpSmartContractRunner( - option.Value.SdkDir); - }); + var option = provider.GetService>(); + return new CSharpSmartContractRunner( + option.Value.SdkDir); + }); #if DEBUG - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new UnitTestCSharpSmartContractRunner( - option.Value.SdkDir); - }); + context.Services.AddSingleton(provider => + { + var option = provider.GetService>(); + return new UnitTestCSharpSmartContractRunner( + option.Value.SdkDir); + }); #endif - } + } - public override void PostConfigureServices(ServiceConfigurationContext context) - { - //context.Services.RemoveAll(sd => sd.ImplementationType == typeof(CachedStateManager)); - } + public override void PostConfigureServices(ServiceConfigurationContext context) + { + //context.Services.RemoveAll(sd => sd.ImplementationType == typeof(CachedStateManager)); } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/CSharpSmartContractProxy.cs b/src/AElf.Runtime.CSharp/CSharpSmartContractProxy.cs index c3bd65cc9b..3a86bbd4a5 100644 --- a/src/AElf.Runtime.CSharp/CSharpSmartContractProxy.cs +++ b/src/AElf.Runtime.CSharp/CSharpSmartContractProxy.cs @@ -1,119 +1,115 @@ using System; using System.Reflection; using AElf.CSharp.CodeOps; -using AElf.Types; using AElf.Kernel.SmartContract; +using AElf.Types; +namespace AElf.Runtime.CSharp; -namespace AElf.Runtime.CSharp +public class CSharpSmartContractProxy { - public class CSharpSmartContractProxy + private readonly Action _methodCleanup; + private readonly Func _methodGetChanges; + private readonly Action _methodInternalInitialize; + + + private readonly Action _methodResetFields; // can be null + private readonly Action _methodSetExecutionObserver; // can be null + + public CSharpSmartContractProxy(object instance, Type counterType) + { + var instanceType = instance.GetType(); + + _methodCleanup = CreateDelegate(instance, instanceType, nameof(Cleanup)); + + _methodGetChanges = + CreateDelegate>(instance, instanceType, nameof(GetChanges)); + + _methodInternalInitialize = + CreateDelegate>(instance, instanceType, + nameof(InternalInitialize)); + + _methodResetFields = CreateDelegate(instance, instanceType, nameof(ResetFields)); + + _methodSetExecutionObserver = counterType == null + ? null + : CreateDelegate>(null, + counterType?.GetMethod(nameof(ExecutionObserverProxy.SetObserver), + new[] { typeof(IExecutionObserver) })); + } + + private static MethodInfo GetMethodInfo(Type type, string name) + { + return type.GetMethod(name, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); + } + + // private static Delegate CreateDelegate(object instance, MethodInfo method) + // { + // return Delegate.CreateDelegate + // ( + // Expression.GetDelegateType + // ( + // method.GetParameters() + // .Select(p => p.ParameterType) + // .Concat(new Type[] {method.ReturnType}) + // .ToArray() + // ), + // instance, + // method + // ); + // } + // + // + // private static Delegate CreateDelegate(object instance, Type type, string name) + // { + // var methodInfo = GetMethodInfo(type, name); + // return methodInfo == null ? null : CreateDelegate(instance, methodInfo); + // } + + private static T CreateDelegate(object instance, MethodInfo method) + where T : Delegate + { + return (T)Delegate.CreateDelegate + ( + typeof(T), + instance, + method + ); + } + + private static T CreateDelegate(object instance, Type type, string name) + where T : Delegate + { + var methodInfo = GetMethodInfo(type, name); + + return methodInfo == null ? null : CreateDelegate(instance, methodInfo); + } + + public void InternalInitialize(ISmartContractBridgeContext context) + { + _methodInternalInitialize(context); + } + + public TransactionExecutingStateSet GetChanges() + { + return _methodGetChanges(); + } + + internal void Cleanup() + { + _methodSetExecutionObserver?.Invoke(null); + _methodCleanup(); + ResetFields(); + } + + private void ResetFields() + { + _methodResetFields?.Invoke(); + } + + internal void SetExecutionObserver(IExecutionObserver observer) { - private static MethodInfo GetMethodInfo(Type type, string name) - { - return type.GetMethod(name, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); - } - - // private static Delegate CreateDelegate(object instance, MethodInfo method) - // { - // return Delegate.CreateDelegate - // ( - // Expression.GetDelegateType - // ( - // method.GetParameters() - // .Select(p => p.ParameterType) - // .Concat(new Type[] {method.ReturnType}) - // .ToArray() - // ), - // instance, - // method - // ); - // } - // - // - // private static Delegate CreateDelegate(object instance, Type type, string name) - // { - // var methodInfo = GetMethodInfo(type, name); - // return methodInfo == null ? null : CreateDelegate(instance, methodInfo); - // } - - private static T CreateDelegate(object instance, MethodInfo method) - where T : Delegate - { - return (T) Delegate.CreateDelegate - ( - typeof(T), - instance, - method - ); - } - - private static T CreateDelegate(object instance, Type type, string name) - where T : Delegate - { - var methodInfo = GetMethodInfo(type, name); - - return methodInfo == null ? null : CreateDelegate(instance, methodInfo); - } - - - - private readonly Action _methodCleanup; - private readonly Func _methodGetChanges; - private readonly Action _methodInternalInitialize; - - - private readonly Action _methodResetFields; // can be null - private readonly Action _methodSetExecutionObserver; // can be null - - public CSharpSmartContractProxy(object instance, Type counterType) - { - var instanceType = instance.GetType(); - - _methodCleanup = CreateDelegate(instance, instanceType, nameof(Cleanup)); - - _methodGetChanges = - CreateDelegate>(instance, instanceType, nameof(GetChanges)); - - _methodInternalInitialize = - CreateDelegate>(instance, instanceType, - nameof(InternalInitialize)); - - _methodResetFields = CreateDelegate(instance, instanceType, nameof(ResetFields)); - - _methodSetExecutionObserver = counterType == null - ? null - : CreateDelegate>(null, - counterType?.GetMethod(nameof(ExecutionObserverProxy.SetObserver), - new[] {typeof(IExecutionObserver)})); - } - - public void InternalInitialize(ISmartContractBridgeContext context) - { - _methodInternalInitialize(context); - } - - public TransactionExecutingStateSet GetChanges() - { - return _methodGetChanges(); - } - - internal void Cleanup() - { - _methodSetExecutionObserver?.Invoke(null); - _methodCleanup(); - ResetFields(); - } - - void ResetFields() - { - _methodResetFields?.Invoke(); - } - - internal void SetExecutionObserver(IExecutionObserver observer) - { - _methodSetExecutionObserver?.Invoke(observer); - } + _methodSetExecutionObserver?.Invoke(observer); } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/CSharpSmartContractRunner.cs b/src/AElf.Runtime.CSharp/CSharpSmartContractRunner.cs index 92359d78c9..84e4805821 100644 --- a/src/AElf.Runtime.CSharp/CSharpSmartContractRunner.cs +++ b/src/AElf.Runtime.CSharp/CSharpSmartContractRunner.cs @@ -5,65 +5,62 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class CSharpSmartContractRunner : ISmartContractRunner { - public class CSharpSmartContractRunner : ISmartContractRunner + private readonly ISdkStreamManager _sdkStreamManager; + + public CSharpSmartContractRunner( + string sdkDir) { - public int Category { get; protected set; } - private readonly ISdkStreamManager _sdkStreamManager; + var sdkDir1 = Path.GetFullPath(sdkDir); + _sdkStreamManager = new SdkStreamManager(sdkDir1); + } - public CSharpSmartContractRunner( - string sdkDir) - { - var sdkDir1 = Path.GetFullPath(sdkDir); - _sdkStreamManager = new SdkStreamManager(sdkDir1); - } + public int Category { get; protected set; } - /// - /// Creates an isolated context for the smart contract residing with an Api singleton. - /// - /// - protected virtual AssemblyLoadContext GetLoadContext() - { - // To make sure each smart contract resides in an isolated context with an Api singleton - return new ContractCodeLoadContext(_sdkStreamManager); - } + public virtual async Task RunAsync(SmartContractRegistration reg) + { + var code = reg.Code.ToByteArray(); - public virtual async Task RunAsync(SmartContractRegistration reg) - { - var code = reg.Code.ToByteArray(); + var loadContext = GetLoadContext(); - var loadContext = GetLoadContext(); + var assembly = LoadAssembly(code, loadContext); - var assembly = LoadAssembly(code, loadContext); + if (assembly == null) throw new InvalidAssemblyException("Invalid binary code."); - if (assembly == null) - { - throw new InvalidAssemblyException("Invalid binary code."); - } + ContractVersion = assembly.GetName().Version?.ToString(); - ContractVersion = assembly.GetName().Version?.ToString(); + var executive = new Executive(assembly) + { + ContractHash = reg.CodeHash, + ContractVersion = ContractVersion + }; - var executive = new Executive(assembly) - { - ContractHash = reg.CodeHash, - ContractVersion = ContractVersion - }; - - // AssemblyLoadContext needs to be called after initializing the Executive - // to ensure that it is not unloaded early in release mode. - loadContext.Unload(); + // AssemblyLoadContext needs to be called after initializing the Executive + // to ensure that it is not unloaded early in release mode. + loadContext.Unload(); - return await Task.FromResult(executive); - } + return await Task.FromResult(executive); + } - protected virtual Assembly LoadAssembly(byte[] code, AssemblyLoadContext loadContext) - { - using Stream stream = new MemoryStream(code); - var assembly = loadContext.LoadFromStream(stream); - return assembly; - } + public string ContractVersion { get; protected set; } - public string ContractVersion { get; protected set; } + /// + /// Creates an isolated context for the smart contract residing with an Api singleton. + /// + /// + protected virtual AssemblyLoadContext GetLoadContext() + { + // To make sure each smart contract resides in an isolated context with an Api singleton + return new ContractCodeLoadContext(_sdkStreamManager); + } + + protected virtual Assembly LoadAssembly(byte[] code, AssemblyLoadContext loadContext) + { + using Stream stream = new MemoryStream(code); + var assembly = loadContext.LoadFromStream(stream); + return assembly; } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/CSharpSmartContractRuntimeException.cs b/src/AElf.Runtime.CSharp/CSharpSmartContractRuntimeException.cs index 1bf308de46..713c3e3ce8 100644 --- a/src/AElf.Runtime.CSharp/CSharpSmartContractRuntimeException.cs +++ b/src/AElf.Runtime.CSharp/CSharpSmartContractRuntimeException.cs @@ -1,15 +1,14 @@ using System; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class InvalidAssemblyException : Exception { - public class InvalidAssemblyException : Exception + public InvalidAssemblyException() { - public InvalidAssemblyException() - { - } + } - public InvalidAssemblyException(string message) : base(message) - { - } + public InvalidAssemblyException(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/Executive.cs b/src/AElf.Runtime.CSharp/Executive.cs index c433b22491..6cb47187c6 100644 --- a/src/AElf.Runtime.CSharp/Executive.cs +++ b/src/AElf.Runtime.CSharp/Executive.cs @@ -5,242 +5,213 @@ using System.Reflection; using System.Threading.Tasks; using AElf.CSharp.CodeOps; +using AElf.CSharp.Core; using AElf.Kernel; using AElf.Kernel.Infrastructure; -using AElf.CSharp.Core; -using Google.Protobuf; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Runtime.CSharp.Core; using AElf.Sdk.CSharp; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class Executive : IExecutive { - public class Executive : IExecutive + private readonly ReadOnlyDictionary _callHandlers; + private readonly object _contractInstance; + private readonly ServerServiceDefinition _serverServiceDefinition; + + private IHostSmartContractBridgeContext _hostSmartContractBridgeContext; + + private readonly CSharpSmartContractProxy _smartContractProxy; + + public Executive(Assembly assembly) { - private readonly object _contractInstance; - private readonly ReadOnlyDictionary _callHandlers; - private readonly ServerServiceDefinition _serverServiceDefinition; + _contractInstance = Activator.CreateInstance(assembly.FindContractType()); + _smartContractProxy = + new CSharpSmartContractProxy(_contractInstance, assembly.FindExecutionObserverProxyType()); + _serverServiceDefinition = GetServerServiceDefinition(assembly); + _callHandlers = _serverServiceDefinition.GetCallHandlers(); + Descriptors = _serverServiceDefinition.GetDescriptors(); + } - private CSharpSmartContractProxy _smartContractProxy; - private ITransactionContext CurrentTransactionContext => _hostSmartContractBridgeContext.TransactionContext; + private ITransactionContext CurrentTransactionContext => _hostSmartContractBridgeContext.TransactionContext; + public IReadOnlyList Descriptors { get; } - private IHostSmartContractBridgeContext _hostSmartContractBridgeContext; - public IReadOnlyList Descriptors { get; } + public string ContractVersion { get; set; } + public Timestamp LastUsedTime { get; set; } - public string ContractVersion { get; set; } - public Timestamp LastUsedTime { get; set; } + public IExecutive SetHostSmartContractBridgeContext(IHostSmartContractBridgeContext smartContractBridgeContext) + { + _hostSmartContractBridgeContext = smartContractBridgeContext; + _smartContractProxy.InternalInitialize(_hostSmartContractBridgeContext); + return this; + } - private ServerServiceDefinition GetServerServiceDefinition(Assembly assembly) + public Task ApplyAsync(ITransactionContext transactionContext) + { + try { - var methodInfo = assembly.FindContractContainer().GetMethod("BindService", - new[] {assembly.FindContractBaseType()}); - return methodInfo.Invoke(null, new[] {_contractInstance}) as ServerServiceDefinition; - } + _hostSmartContractBridgeContext.TransactionContext = transactionContext; + if (CurrentTransactionContext.CallDepth > CurrentTransactionContext.MaxCallDepth) + { + CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ExceededMaxCallDepth; + CurrentTransactionContext.Trace.Error = "\n" + "ExceededMaxCallDepth"; + return Task.CompletedTask; + } - public Executive(Assembly assembly) - { - _contractInstance = Activator.CreateInstance(assembly.FindContractType()); - _smartContractProxy = - new CSharpSmartContractProxy(_contractInstance, assembly.FindExecutionObserverProxyType()); - _serverServiceDefinition = GetServerServiceDefinition(assembly); - _callHandlers = _serverServiceDefinition.GetCallHandlers(); - Descriptors = _serverServiceDefinition.GetDescriptors(); + Execute(); } - - public IExecutive SetHostSmartContractBridgeContext(IHostSmartContractBridgeContext smartContractBridgeContext) + finally { - _hostSmartContractBridgeContext = smartContractBridgeContext; - _smartContractProxy.InternalInitialize(_hostSmartContractBridgeContext); - return this; + _hostSmartContractBridgeContext.TransactionContext = null; } - private void Cleanup() - { - _smartContractProxy.Cleanup(); - } + return Task.CompletedTask; + } - public Task ApplyAsync(ITransactionContext transactionContext) - { - try - { - _hostSmartContractBridgeContext.TransactionContext = transactionContext; - if (CurrentTransactionContext.CallDepth > CurrentTransactionContext.MaxCallDepth) - { - CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ExceededMaxCallDepth; - CurrentTransactionContext.Trace.Error = "\n" + "ExceededMaxCallDepth"; - return Task.CompletedTask; - } - - Execute(); - } - finally - { - _hostSmartContractBridgeContext.TransactionContext = null; - } + public string GetJsonStringOfParameters(string methodName, byte[] paramsBytes) + { + if (!_callHandlers.TryGetValue(methodName, out var handler)) return ""; - return Task.CompletedTask; - } + return handler.InputBytesToString(paramsBytes); + } - public void Execute() - { - var s = CurrentTransactionContext.Trace.StartTime = TimestampHelper.GetUtcNow().ToDateTime(); - var methodName = CurrentTransactionContext.Transaction.MethodName; - var observer = - new ExecutionObserver(CurrentTransactionContext.ExecutionObserverThreshold.ExecutionCallThreshold, - CurrentTransactionContext.ExecutionObserverThreshold.ExecutionBranchThreshold); - - try - { - if (!_callHandlers.TryGetValue(methodName, out var handler)) - { - throw new RuntimeException( - $"Failed to find handler for {methodName}. We have {_callHandlers.Count} handlers: " + - string.Join(", ", _callHandlers.Keys.OrderBy(k => k)) - ); - } - - _smartContractProxy.SetExecutionObserver(observer); - - ExecuteTransaction(handler); - - if (!handler.IsView()) - { - CurrentTransactionContext.Trace.StateSet = GetChanges(); - } - else - { - CurrentTransactionContext.Trace.StateSet = new TransactionExecutingStateSet(); - } - } - catch (Exception ex) - { - CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.SystemError; - CurrentTransactionContext.Trace.Error += ex + "\n"; - } - finally - { - Cleanup(); - } + public bool IsView(string methodName) + { + if (!_callHandlers.TryGetValue(methodName, out var handler)) + throw new RuntimeException( + $"Failed to find handler for {methodName}. We have {_callHandlers.Count} handlers: " + + string.Join(", ", _callHandlers.Keys.OrderBy(k => k)) + ); - var e = CurrentTransactionContext.Trace.EndTime = TimestampHelper.GetUtcNow().ToDateTime(); - CurrentTransactionContext.Trace.Elapsed = (e - s).Ticks; - } + return handler.IsView(); + } - public string GetJsonStringOfParameters(string methodName, byte[] paramsBytes) - { - if (!_callHandlers.TryGetValue(methodName, out var handler)) - { - return ""; - } + public byte[] GetFileDescriptorSet() + { + var descriptor = Descriptors.Last(); + var output = new FileDescriptorSet(); + output.File.AddRange(GetSelfAndDependency(descriptor.File).Select(x => x.SerializedData)); + return output.ToByteArray(); + } - return handler.InputBytesToString(paramsBytes); - } + public IEnumerable GetFileDescriptors() + { + var descriptor = Descriptors.Last(); + return GetSelfAndDependency(descriptor.File); + } + + public Hash ContractHash { get; set; } + + private ServerServiceDefinition GetServerServiceDefinition(Assembly assembly) + { + var methodInfo = assembly.FindContractContainer().GetMethod("BindService", + new[] { assembly.FindContractBaseType() }); + return methodInfo.Invoke(null, new[] { _contractInstance }) as ServerServiceDefinition; + } + + private void Cleanup() + { + _smartContractProxy.Cleanup(); + } + + public void Execute() + { + var s = CurrentTransactionContext.Trace.StartTime = TimestampHelper.GetUtcNow().ToDateTime(); + var methodName = CurrentTransactionContext.Transaction.MethodName; + var observer = + new ExecutionObserver(CurrentTransactionContext.ExecutionObserverThreshold.ExecutionCallThreshold, + CurrentTransactionContext.ExecutionObserverThreshold.ExecutionBranchThreshold); - public bool IsView(string methodName) + try { if (!_callHandlers.TryGetValue(methodName, out var handler)) - { throw new RuntimeException( $"Failed to find handler for {methodName}. We have {_callHandlers.Count} handlers: " + string.Join(", ", _callHandlers.Keys.OrderBy(k => k)) ); - } - return handler.IsView(); - } + _smartContractProxy.SetExecutionObserver(observer); - private IEnumerable GetSelfAndDependency(FileDescriptor fileDescriptor, - HashSet known = null) - { - known = known ?? new HashSet(); - if (known.Contains(fileDescriptor.Name)) - { - return new List(); - } + ExecuteTransaction(handler); - var fileDescriptors = new List(); - fileDescriptors.AddRange(fileDescriptor.Dependencies.SelectMany(x => GetSelfAndDependency(x, known))); - fileDescriptors.Add(fileDescriptor); - known.Add(fileDescriptor.Name); - return fileDescriptors; + if (!handler.IsView()) + CurrentTransactionContext.Trace.StateSet = GetChanges(); + else + CurrentTransactionContext.Trace.StateSet = new TransactionExecutingStateSet(); } - - public byte[] GetFileDescriptorSet() + catch (Exception ex) { - var descriptor = Descriptors.Last(); - var output = new FileDescriptorSet(); - output.File.AddRange(GetSelfAndDependency(descriptor.File).Select(x => x.SerializedData)); - return output.ToByteArray(); + CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.SystemError; + CurrentTransactionContext.Trace.Error += ex + "\n"; } - - public IEnumerable GetFileDescriptors() + finally { - var descriptor = Descriptors.Last(); - return GetSelfAndDependency(descriptor.File); + Cleanup(); } - public Hash ContractHash { get; set; } + var e = CurrentTransactionContext.Trace.EndTime = TimestampHelper.GetUtcNow().ToDateTime(); + CurrentTransactionContext.Trace.Elapsed = (e - s).Ticks; + } + + private IEnumerable GetSelfAndDependency(FileDescriptor fileDescriptor, + HashSet known = null) + { + known = known ?? new HashSet(); + if (known.Contains(fileDescriptor.Name)) return new List(); + + var fileDescriptors = new List(); + fileDescriptors.AddRange(fileDescriptor.Dependencies.SelectMany(x => GetSelfAndDependency(x, known))); + fileDescriptors.Add(fileDescriptor); + known.Add(fileDescriptor.Name); + return fileDescriptors; + } - private void ExecuteTransaction(IServerCallHandler handler) + private void ExecuteTransaction(IServerCallHandler handler) + { + try { - try - { - var tx = CurrentTransactionContext.Transaction; - var retVal = handler.Execute(tx.Params.ToByteArray()); - if (retVal != null) - { - CurrentTransactionContext.Trace.ReturnValue = ByteString.CopyFrom(retVal); - } - - CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.Executed; - } - catch (Exception ex) - { - CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; - CurrentTransactionContext.Trace.Error += ex + "\n"; - } + var tx = CurrentTransactionContext.Transaction; + var retVal = handler.Execute(tx.Params.ToByteArray()); + if (retVal != null) CurrentTransactionContext.Trace.ReturnValue = ByteString.CopyFrom(retVal); + + CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.Executed; } - - private TransactionExecutingStateSet GetChanges() + catch (Exception ex) { - var changes = _smartContractProxy.GetChanges(); + CurrentTransactionContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; + CurrentTransactionContext.Trace.Error += ex + "\n"; + } + } - var address = _hostSmartContractBridgeContext.Self.ToStorageKey(); - foreach (var key in changes.Writes.Keys) - { - if (!key.StartsWith(address)) - { - throw new InvalidOperationException("a contract cannot access other contracts data"); - } - } - - foreach (var (key, value) in changes.Deletes) - { - if (!key.StartsWith(address)) - { - throw new InvalidOperationException("a contract cannot access other contracts data"); - } - } + private TransactionExecutingStateSet GetChanges() + { + var changes = _smartContractProxy.GetChanges(); - foreach (var key in changes.Reads.Keys) - { - if (!key.StartsWith(address)) - { - throw new InvalidOperationException("a contract cannot access other contracts data"); - } - } + var address = _hostSmartContractBridgeContext.Self.ToStorageKey(); + foreach (var key in changes.Writes.Keys) + if (!key.StartsWith(address)) + throw new InvalidOperationException("a contract cannot access other contracts data"); - if (!CurrentTransactionContext.Trace.IsSuccessful()) - { - changes.Writes.Clear(); - changes.Deletes.Clear(); - } + foreach (var (key, value) in changes.Deletes) + if (!key.StartsWith(address)) + throw new InvalidOperationException("a contract cannot access other contracts data"); + + foreach (var key in changes.Reads.Keys) + if (!key.StartsWith(address)) + throw new InvalidOperationException("a contract cannot access other contracts data"); - return changes; + if (!CurrentTransactionContext.Trace.IsSuccessful()) + { + changes.Writes.Clear(); + changes.Deletes.Clear(); } + + return changes; } } \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/ServerCallHandler.cs b/src/AElf.Runtime.CSharp/ServerCallHandler.cs index 0182b16e60..bff9f09e5a 100644 --- a/src/AElf.Runtime.CSharp/ServerCallHandler.cs +++ b/src/AElf.Runtime.CSharp/ServerCallHandler.cs @@ -16,67 +16,62 @@ #endregion -using System; -using System.Threading; -using System.Threading.Tasks; using AElf.CSharp.Core; -using Google.Protobuf.WellKnownTypes; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +internal interface IServerCallHandler { - internal interface IServerCallHandler + bool IsView(); + byte[] Execute(byte[] input); + object ReturnBytesToObject(byte[] returnBytes); + string ReturnBytesToString(byte[] returnBytes); + object InputBytesToObject(byte[] inputBytes); + string InputBytesToString(byte[] inputBytes); +} + +internal class UnaryServerCallHandler : IServerCallHandler + where TRequest : class + where TResponse : class +{ + private readonly UnaryServerMethod handler; + private readonly Method method; + + public UnaryServerCallHandler(Method method, UnaryServerMethod handler) { - bool IsView(); - byte[] Execute(byte[] input); - object ReturnBytesToObject(byte[] returnBytes); - string ReturnBytesToString(byte[] returnBytes); - object InputBytesToObject(byte[] inputBytes); - string InputBytesToString(byte[] inputBytes); + this.method = method; + this.handler = handler; } - internal class UnaryServerCallHandler : IServerCallHandler - where TRequest : class - where TResponse : class + public bool IsView() { - readonly Method method; - readonly UnaryServerMethod handler; - - public UnaryServerCallHandler(Method method, UnaryServerMethod handler) - { - this.method = method; - this.handler = handler; - } - - public bool IsView() - { - return method.Type == MethodType.View; - } + return method.Type == MethodType.View; + } - public byte[] Execute(byte[] input) - { - var inputObj = method.RequestMarshaller.Deserializer(input); - var response = handler(inputObj); - return response != null ? method.ResponseMarshaller.Serializer(response) : null; - } + public byte[] Execute(byte[] input) + { + var inputObj = method.RequestMarshaller.Deserializer(input); + var response = handler(inputObj); + return response != null ? method.ResponseMarshaller.Serializer(response) : null; + } - public object ReturnBytesToObject(byte[] returnBytes) - { - return method.ResponseMarshaller.Deserializer(returnBytes); - } + public object ReturnBytesToObject(byte[] returnBytes) + { + return method.ResponseMarshaller.Deserializer(returnBytes); + } - public string ReturnBytesToString(byte[] returnBytes) - { - return method.ResponseMarshaller.Deserializer(returnBytes).ToString(); - } + public string ReturnBytesToString(byte[] returnBytes) + { + return method.ResponseMarshaller.Deserializer(returnBytes).ToString(); + } - public object InputBytesToObject(byte[] inputBytes) - { - return method.RequestMarshaller.Deserializer(inputBytes); - } + public object InputBytesToObject(byte[] inputBytes) + { + return method.RequestMarshaller.Deserializer(inputBytes); + } - public string InputBytesToString(byte[] inputBytes) - { - return method.RequestMarshaller.Deserializer(inputBytes).ToString(); - } + public string InputBytesToString(byte[] inputBytes) + { + return method.RequestMarshaller.Deserializer(inputBytes).ToString(); } -} +} \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/ServerCalls.cs b/src/AElf.Runtime.CSharp/ServerCalls.cs index 65e8ba84e4..f4cfae2a32 100644 --- a/src/AElf.Runtime.CSharp/ServerCalls.cs +++ b/src/AElf.Runtime.CSharp/ServerCalls.cs @@ -18,15 +18,15 @@ using AElf.CSharp.Core; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +internal static class ServerCalls { - internal static class ServerCalls + public static IServerCallHandler UnaryCall(Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class { - public static IServerCallHandler UnaryCall(Method method, UnaryServerMethod handler) - where TRequest : class - where TResponse : class - { - return new UnaryServerCallHandler(method, handler); - } + return new UnaryServerCallHandler(method, handler); } -} +} \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/ServerServiceDefinitionExtensions.cs b/src/AElf.Runtime.CSharp/ServerServiceDefinitionExtensions.cs index b9ab372b43..be12aecb63 100644 --- a/src/AElf.Runtime.CSharp/ServerServiceDefinitionExtensions.cs +++ b/src/AElf.Runtime.CSharp/ServerServiceDefinitionExtensions.cs @@ -21,56 +21,56 @@ using AElf.CSharp.Core; using Google.Protobuf.Reflection; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +internal static class ServerServiceDefinitionExtensions { - internal static class ServerServiceDefinitionExtensions + /// + /// Maps methods from ServerServiceDefinition to server call handlers. + /// + internal static ReadOnlyDictionary GetCallHandlers( + this ServerServiceDefinition serviceDefinition) + { + var binder = new DefaultServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetCallHandlers(); + } + + internal static IReadOnlyList GetDescriptors(this ServerServiceDefinition serviceDefinition) + { + var binder = new DefaultServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetDescriptors(); + } + + /// + /// Helper for converting ServerServiceDefinition to server call handlers. + /// + private class DefaultServiceBinder : ServiceBinderBase { - /// - /// Maps methods from ServerServiceDefinition to server call handlers. - /// - internal static ReadOnlyDictionary GetCallHandlers(this ServerServiceDefinition serviceDefinition) + private readonly Dictionary callHandlers = new(); + private readonly List descriptors = new(); + + internal ReadOnlyDictionary GetCallHandlers() { - var binder = new DefaultServiceBinder(); - serviceDefinition.BindService(binder); - return binder.GetCallHandlers(); + return new ReadOnlyDictionary(callHandlers); } - internal static IReadOnlyList GetDescriptors(this ServerServiceDefinition serviceDefinition) + internal IReadOnlyList GetDescriptors() { - var binder = new DefaultServiceBinder(); - serviceDefinition.BindService(binder); - return binder.GetDescriptors(); + return descriptors.AsReadOnly(); } - /// - /// Helper for converting ServerServiceDefinition to server call handlers. - /// - private class DefaultServiceBinder : ServiceBinderBase + public override void AddMethod( + Method method, + UnaryServerMethod handler) { - readonly List descriptors = new List(); - readonly Dictionary callHandlers = new Dictionary(); - - internal ReadOnlyDictionary GetCallHandlers() - { - return new ReadOnlyDictionary(this.callHandlers); - } - - internal IReadOnlyList GetDescriptors() - { - return descriptors.AsReadOnly(); - } - - public override void AddMethod( - Method method, - UnaryServerMethod handler) - { - callHandlers.Add(method.Name, ServerCalls.UnaryCall(method, handler)); - } + callHandlers.Add(method.Name, ServerCalls.UnaryCall(method, handler)); + } - public override void AddDescriptor(ServiceDescriptor descriptor) - { - descriptors.Add(descriptor); - } + public override void AddDescriptor(ServiceDescriptor descriptor) + { + descriptors.Add(descriptor); } } -} +} \ No newline at end of file diff --git a/src/AElf.Runtime.CSharp/UnitTestCSharpSmartContractRunner.cs b/src/AElf.Runtime.CSharp/UnitTestCSharpSmartContractRunner.cs index 7401b92dec..5273d2677e 100644 --- a/src/AElf.Runtime.CSharp/UnitTestCSharpSmartContractRunner.cs +++ b/src/AElf.Runtime.CSharp/UnitTestCSharpSmartContractRunner.cs @@ -5,37 +5,32 @@ using System.Runtime.Loader; using AElf.Kernel; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class UnitTestCSharpSmartContractRunner : CSharpSmartContractRunner { - public class UnitTestCSharpSmartContractRunner : CSharpSmartContractRunner + public UnitTestCSharpSmartContractRunner(string sdkDir) + : base(sdkDir) { - public UnitTestCSharpSmartContractRunner(string sdkDir) - : base(sdkDir) + Category = KernelConstants.CodeCoverageRunnerCategory; + } + + protected override Assembly LoadAssembly(byte[] code, AssemblyLoadContext loadContext) + { + var assembly = base.LoadAssembly(code, loadContext); + + Assembly assembly2 = null; + try { - Category = KernelConstants.CodeCoverageRunnerCategory; + assembly2 = Assembly.Load(assembly.FullName); } - - protected override Assembly LoadAssembly(byte[] code, AssemblyLoadContext loadContext) + catch (Exception) { - var assembly = base.LoadAssembly(code, loadContext); - - Assembly assembly2 = null; - try - { - assembly2 = Assembly.Load(assembly.FullName); - } - catch (Exception) - { - //may cannot find assembly in local - } - - if (assembly2 != null && code.SequenceEqual(File.ReadAllBytes(assembly2.Location))) - { - assembly = assembly2; - } - - return assembly; + //may cannot find assembly in local } + if (assembly2 != null && code.SequenceEqual(File.ReadAllBytes(assembly2.Location))) assembly = assembly2; + + return assembly; } } \ No newline at end of file diff --git a/src/AElf.RuntimeSetup/AElf.RuntimeSetup.csproj b/src/AElf.RuntimeSetup/AElf.RuntimeSetup.csproj index bfc20707fa..75a439494b 100644 --- a/src/AElf.RuntimeSetup/AElf.RuntimeSetup.csproj +++ b/src/AElf.RuntimeSetup/AElf.RuntimeSetup.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,12 +9,12 @@ - + - - + + diff --git a/src/AElf.RuntimeSetup/RuntimeSetupAElfModule.cs b/src/AElf.RuntimeSetup/RuntimeSetupAElfModule.cs index ff648b54fb..d982043f92 100644 --- a/src/AElf.RuntimeSetup/RuntimeSetupAElfModule.cs +++ b/src/AElf.RuntimeSetup/RuntimeSetupAElfModule.cs @@ -1,28 +1,23 @@ -using System; -using System.IO; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp.Modularity; -using System.Linq; -using Microsoft.Extensions.Configuration; -namespace AElf.RuntimeSetup +namespace AElf.RuntimeSetup; + +[DependsOn( + typeof(CoreAElfModule) +)] +public class RuntimeSetupAElfModule : AElfModule { - [DependsOn( - typeof(CoreAElfModule) - )] - public class RuntimeSetupAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddLogging(builder => { - context.Services.AddLogging(builder => - { - builder.AddConfiguration(context.Services.GetConfiguration().GetSection("Logging")); + builder.AddConfiguration(context.Services.GetConfiguration().GetSection("Logging")); - builder.AddLog4Net(); - builder.SetMinimumLevel(LogLevel.Debug); - }); - } + builder.AddLog4Net(); + builder.SetMinimumLevel(LogLevel.Debug); + }); } } \ No newline at end of file diff --git a/src/AElf.RuntimeSetup/log4net.config b/src/AElf.RuntimeSetup/log4net.config index 82b6b21e23..b1faa1a858 100644 --- a/src/AElf.RuntimeSetup/log4net.config +++ b/src/AElf.RuntimeSetup/log4net.config @@ -1,50 +1,51 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - - - - - - + + + + + + + - + - - - + + + \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/AElf.Sdk.CSharp.csproj b/src/AElf.Sdk.CSharp/AElf.Sdk.CSharp.csproj index 646d9ee58c..1138bc5cc3 100644 --- a/src/AElf.Sdk.CSharp/AElf.Sdk.CSharp.csproj +++ b/src/AElf.Sdk.CSharp/AElf.Sdk.CSharp.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -10,9 +10,9 @@ - - - + + + diff --git a/src/AElf.Sdk.CSharp/AElfString.cs b/src/AElf.Sdk.CSharp/AElfString.cs index 7ea0864a57..27306de041 100644 --- a/src/AElf.Sdk.CSharp/AElfString.cs +++ b/src/AElf.Sdk.CSharp/AElfString.cs @@ -1,69 +1,69 @@ -namespace AElf.Sdk.CSharp +namespace AElf.Sdk.CSharp; + +public class AElfString { - public class AElfString + public static string Concat(string[] values) + { + return ValidatedString(string.Concat(values)); + } + + public static string Concat(object[] args) + { + return ValidatedString(string.Concat(args)); + } + + public static string Concat(string str0, string str1) { - public static string Concat(string[] values) - { - return ValidatedString(string.Concat(values)); - } - - public static string Concat(object[] args) - { - return ValidatedString(string.Concat(args)); - } + return ValidatedString(string.Concat(str0, str1)); + } + + public static string Concat(string str0, string str1, string str2) + { + return ValidatedString(string.Concat(str0, str1, str2)); + } + + public static string Concat(string str0, string str1, string str2, string str3) + { + return ValidatedString(string.Concat(str0, str1, str2, str3)); + } - public static string Concat(string str0, string str1) - { - return ValidatedString(string.Concat(str0, str1)); - } + public static string Concat(object arg0, object arg1) + { + return ValidatedString(string.Concat(arg0, arg1)); + } - public static string Concat(string str0, string str1, string str2) - { - return ValidatedString(string.Concat(str0, str1, str2)); - } - - public static string Concat(string str0, string str1, string str2, string str3) - { - return ValidatedString(string.Concat(str0, str1, str2, str3)); - } + public static string Concat(object arg0, object arg1, object arg2) + { + return ValidatedString(string.Concat(arg0, arg1, arg2)); + } - public static string Concat(object arg0, object arg1) - { - return ValidatedString(string.Concat(arg0, arg1)); - } - - public static string Concat(object arg0, object arg1, object arg2) - { - return ValidatedString(string.Concat(arg0, arg1, arg2)); - } - - public static string Concat(object arg0, object arg1, object arg2, object arg3) - { - return ValidatedString(string.Concat(arg0, arg1, arg2, arg3)); - } + public static string Concat(object arg0, object arg1, object arg2, object arg3) + { + return ValidatedString(string.Concat(arg0, arg1, arg2, arg3)); + } - public static string ValidatedString(string str) - { - var limit = SmartContractConstants.AElfStringLengthLimitInContract; + public static string ValidatedString(string str) + { + var limit = SmartContractConstants.AElfStringLengthLimitInContract; #if DEBUG - // for debug logs - limit = int.MaxValue; + // for debug logs + limit = int.MaxValue; #endif - if (str.Length > limit) - throw new AssertionException($"String size {str.Length} is too big to concatenate further!"); - return str; - } + if (str.Length > limit) + throw new AssertionException($"String size {str.Length} is too big to concatenate further!"); + return str; } - - public static class StringExtensions +} + +public static class StringExtensions +{ + public static string Append(this string s1, string s2) { - public static string Append(this string s1, string s2) - { - return AElfString.ValidatedString(s1 + s2); - } - public static string AppendLine(this string s1, string s2) - { - return AElfString.ValidatedString(s1 + "\n" + s2); - } + return AElfString.ValidatedString(s1 + s2); } -} + + public static string AppendLine(this string s1, string s2) + { + return AElfString.ValidatedString(s1 + "\n" + s2); + } +} \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContract.cs b/src/AElf.Sdk.CSharp/CSharpSmartContract.cs index c616f5133c..1ec0604734 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContract.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContract.cs @@ -1,8 +1,5 @@ -using AElf.Kernel.SmartContract; +namespace AElf.Sdk.CSharp; -namespace AElf.Sdk.CSharp +public class CSharpSmartContract : ISmartContract { - public class CSharpSmartContract : ISmartContract - { - } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractAbstract.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractAbstract.cs index c8ab76e107..31d642fdf0 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractAbstract.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractAbstract.cs @@ -1,27 +1,23 @@ -using AElf.Types; using AElf.Kernel.SmartContract; +using AElf.Types; + +namespace AElf.Sdk.CSharp; -namespace AElf.Sdk.CSharp +public abstract class CSharpSmartContractAbstract : CSharpSmartContract { - public abstract class CSharpSmartContractAbstract : CSharpSmartContract - { - internal abstract TransactionExecutingStateSet GetChanges(); - internal abstract void Cleanup(); + /// + /// Represents the transaction execution context in a smart contract. It provides access inside the contract to + /// properties and methods useful for implementing the smart contracts action logic. + /// + public CSharpSmartContractContext Context { get; set; } - protected void Assert(bool asserted, string message = "Assertion failed!") - { - if (!asserted) - { - throw new AssertionException(message); - } - } + internal abstract TransactionExecutingStateSet GetChanges(); + internal abstract void Cleanup(); - internal abstract void InternalInitialize(ISmartContractBridgeContext bridgeContext); - - /// - /// Represents the transaction execution context in a smart contract. It provides access inside the contract to - /// properties and methods useful for implementing the smart contracts action logic. - /// - public CSharpSmartContractContext Context { get; set; } + protected void Assert(bool asserted, string message = "Assertion failed!") + { + if (!asserted) throw new AssertionException(message); } + + internal abstract void InternalInitialize(ISmartContractBridgeContext bridgeContext); } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index ab4f3c6e57..4237b8a14f 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -1,342 +1,347 @@ using System; using System.Collections.Generic; -using AElf.CSharp.Core; +using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using AElf.Kernel.SmartContract; +namespace AElf.Sdk.CSharp; -namespace AElf.Sdk.CSharp +/// +/// Represents the transaction execution context in a smart contract. An instance of this class is present in the +/// base class for smart contracts (Context property). It provides access to properties and methods useful for +/// implementing the logic in smart contracts. +/// +public class CSharpSmartContractContext : ISmartContractBridgeContext { + public CSharpSmartContractContext(ISmartContractBridgeContext smartContractBridgeContextImplementation) + { + SmartContractBridgeContextImplementation = smartContractBridgeContextImplementation; + } + + public ISmartContractBridgeContext SmartContractBridgeContextImplementation { get; } + + /// + /// Provides access to the underlying state provider. + /// + public IStateProvider StateProvider => SmartContractBridgeContextImplementation.StateProvider; + + /// + /// The chain id of the chain on which the contract is currently running. + /// + public int ChainId => SmartContractBridgeContextImplementation.ChainId; + + /// + /// Application logging - when writing a contract it is useful to be able to log some elements in the + /// applications log file to simplify development. Note that these logs are only visible when the node + /// executing the transaction is build in debug mode. + /// + /// The logic that will be executed for logging purposes. + public void LogDebug(Func func) + { + SmartContractBridgeContextImplementation.LogDebug(func); + } + + /// + /// This method is used to produce logs that can be found in the transaction result after execution. + /// + /// The event to fire. + public void FireLogEvent(LogEvent logEvent) + { + SmartContractBridgeContextImplementation.FireLogEvent(logEvent); + } + + /// + /// The ID of the transaction that's currently executing. + /// + public Hash TransactionId => SmartContractBridgeContextImplementation.TransactionId; + + /// + /// The Sender of the transaction that is executing. + /// + public Address Sender => SmartContractBridgeContextImplementation.Sender; + + /// + /// The address of the contract currently being executed. This changes for every transaction and inline transaction. + /// + public Address Self => SmartContractBridgeContextImplementation.Self; + + /// + /// The address of the sender (signer) of the transaction being executed. It’s type is an AElf address. It + /// corresponds to the From field of the transaction. This value never changes, even for nested inline calls. + /// This means that when you access this property in your contract, it’s value will be the entity that created + /// the transaction (user or smart contract through an inline call). + /// + public Address Origin => SmartContractBridgeContextImplementation.Origin; + + public Hash OriginTransactionId => SmartContractBridgeContextImplementation.OriginTransactionId; + + /// + /// The height of the block that contains the transaction currently executing. + /// + public long CurrentHeight => SmartContractBridgeContextImplementation.CurrentHeight; + + /// + /// The time included in the current blocks header. + /// + public Timestamp CurrentBlockTime => SmartContractBridgeContextImplementation.CurrentBlockTime; + + /// + /// The hash of the block that precedes the current in the blockchain structure. + /// + public Hash PreviousBlockHash => SmartContractBridgeContextImplementation.PreviousBlockHash; + + /// + /// Provides access to variable of the bridge. + /// + public ContextVariableDictionary Variables => SmartContractBridgeContextImplementation.Variables; + + /// + /// Recovers the public key of the transaction Sender. + /// + /// A byte array representing the public key. + public byte[] RecoverPublicKey() + { + return SmartContractBridgeContextImplementation.RecoverPublicKey(); + } + + /// + /// Returns the transaction included in the previous block (previous to the one currently executing). + /// + /// A list of transaction. + public List GetPreviousBlockTransactions() + { + return SmartContractBridgeContextImplementation.GetPreviousBlockTransactions(); + } + + /// + /// Returns whether or not the given transaction is well formed and the signature is correct. + /// + /// The transaction to verify. + /// The verification results. + public bool VerifySignature(Transaction tx) + { + return SmartContractBridgeContextImplementation.VerifySignature(tx); + } + + /// + /// Deploy a new smart contract (only the genesis contract can call it). + /// + /// The address of new smart contract. + /// The registration of the new smart contract. + /// The hash value of the smart contract name. + public void DeployContract(Address address, SmartContractRegistration registration, Hash name) + { + SmartContractBridgeContextImplementation.DeployContract(address, registration, name); + } + + /// + /// Update a smart contract (only the genesis contract can call it). + /// + /// The address of smart contract to update. + /// The registration of the smart contract to update. + /// The hash value of the smart contract name to update. + public void UpdateContract(Address address, SmartContractRegistration registration, Hash name) + { + SmartContractBridgeContextImplementation.UpdateContract(address, registration, name); + } + + /// + /// Calls a method on another contract. + /// + /// The address to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to call. + /// + /// The input arguments for calling that method. This is usually generated from the protobuf + /// definition of the input type + /// + /// The type of the return message. + /// The result of the call. + public T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) + where T : IMessage, new() + { + return SmartContractBridgeContextImplementation.Call(fromAddress, toAddress, methodName, args); + } + + /// + /// Sends an inline transaction to another contract. + /// + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// + /// The input arguments for calling that method. This is usually generated from the protobuf + /// definition of the input type. + /// + public void SendInline(Address toAddress, string methodName, ByteString args) + { + SmartContractBridgeContextImplementation.SendInline(toAddress, methodName, args); + } + + /// + /// Sends a virtual inline transaction to another contract. + /// + /// The virtual address to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// + /// The input arguments for calling that method. This is usually generated from the protobuf + /// definition of the input type. + /// + public void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args) + { + SmartContractBridgeContextImplementation.SendVirtualInline(fromVirtualAddress, toAddress, methodName, + args); + } + + /// + /// Sends a virtual inline transaction to another contract. This method is only available to system smart contract. + /// + /// The virtual address of the system contract to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// + /// The input arguments for calling that method. This is usually generated from the protobuf + /// definition of the input type. + /// + public void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, + ByteString args) + { + SmartContractBridgeContextImplementation.SendVirtualInlineBySystemContract(fromVirtualAddress, toAddress, + methodName, args); + } + + /// + /// Converts a virtual address to a contract address with the contract address. + /// + /// The virtual address that want to convert. + /// The contract address. + /// The converted address. + public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress) + { + return SmartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddress(virtualAddress, + contractAddress); + } + + /// + /// Converts a virtual address to a contract address with the contract hash name. + /// + /// The virtual address that want to convert. + /// The contract address. + /// + public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, + Address contractAddress) + { + return SmartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddressWithContractHashName( + virtualAddress, contractAddress); + } + + /// + /// This method returns the address of the Genesis contract (smart contract zero) of the current chain. + /// + /// The address of the genesis contract. + public Address GetZeroSmartContractAddress() + { + return SmartContractBridgeContextImplementation.GetZeroSmartContractAddress(); + } + + /// + /// This method returns the address of the Genesis contract (smart contract zero) of the specified chain. + /// + /// The chain's ID. + /// The address of the genesis contract, for the given chain. + public Address GetZeroSmartContractAddress(int chainId) + { + return SmartContractBridgeContextImplementation.GetZeroSmartContractAddress(chainId); + } + + /// + /// It's sometimes useful to get the address of a system contract. The input is a hash of the system contracts + /// name. These hashes are easily accessible through the constants in the SmartContractConstants.cs file of the + /// C# SDK. + /// + /// The hash of the name. + /// The address of the system contract. + public Address GetContractAddressByName(string hash) + { + return SmartContractBridgeContextImplementation.GetContractAddressByName(hash); + } + + /// + /// Get the mapping that associates the system contract addresses and their name's hash. + /// + /// The addresses with their hashes. + public IReadOnlyDictionary GetSystemContractNameToAddressMapping() + { + return SmartContractBridgeContextImplementation.GetSystemContractNameToAddressMapping(); + } + + /// + /// Generate a hash type id based on the contract address and the bytes. + /// + /// The contract address on which the id generation is based. + /// The bytes on which the id generation is based. + /// The generated hash type id. + public Hash GenerateId(Address contractAddress, IEnumerable bytes) + { + return SmartContractBridgeContextImplementation.GenerateId(contractAddress, bytes); + } + + /// + /// Verify that the state size is within the valid value. + /// + /// The state. + /// The state. + /// The state size exceeds the limit. + public object ValidateStateSize(object obj) + { + return SmartContractBridgeContextImplementation.ValidateStateSize(obj); + } + + /// + /// Gets a random hash based on the input hash. + /// + /// Hash. + /// Random hash. + public Hash GetRandomHash(Hash fromHash) + { + return SmartContractBridgeContextImplementation.GetRandomHash(fromHash); + } + + /// + /// Converts the input hash to a 64-bit signed integer. + /// + /// The hash. + /// The inclusive lower bound of the number returned. + /// + /// The exclusive upper bound of the number returned. endValue must be greater than or equal to + /// startValue. + /// + /// The 64-bit signed integer. + /// startValue is less than 0 or greater than endValue. + public long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue) + { + return SmartContractBridgeContextImplementation.ConvertHashToInt64(hash, start, end); + } + + /// + /// Converts a virtual address to a contract address. + /// + /// The virtual address that want to convert. + /// The converted address. + public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress) + { + return SmartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddress(virtualAddress); + } + /// - /// Represents the transaction execution context in a smart contract. An instance of this class is present in the - /// base class for smart contracts (Context property). It provides access to properties and methods useful for - /// implementing the logic in smart contracts. + /// Converts a virtual address to a contract address with the current contract hash name. /// - public class CSharpSmartContractContext : ISmartContractBridgeContext + /// The virtual address that want to convert. + /// The converted address. + public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress) { - private readonly ISmartContractBridgeContext _smartContractBridgeContextImplementation; - - public ISmartContractBridgeContext SmartContractBridgeContextImplementation => - _smartContractBridgeContextImplementation; - - public CSharpSmartContractContext(ISmartContractBridgeContext smartContractBridgeContextImplementation) - { - _smartContractBridgeContextImplementation = smartContractBridgeContextImplementation; - } - - /// - /// Provides access to the underlying state provider. - /// - public IStateProvider StateProvider => _smartContractBridgeContextImplementation.StateProvider; - - /// - /// The chain id of the chain on which the contract is currently running. - /// - public int ChainId => _smartContractBridgeContextImplementation.ChainId; - - /// - /// Application logging - when writing a contract it is useful to be able to log some elements in the - /// applications log file to simplify development. Note that these logs are only visible when the node - /// executing the transaction is build in debug mode. - /// - /// The logic that will be executed for logging purposes. - public void LogDebug(Func func) - { - _smartContractBridgeContextImplementation.LogDebug(func); - } - - /// - /// This method is used to produce logs that can be found in the transaction result after execution. - /// - /// The event to fire. - public void FireLogEvent(LogEvent logEvent) - { - _smartContractBridgeContextImplementation.FireLogEvent(logEvent); - } - - /// - /// The ID of the transaction that's currently executing. - /// - public Hash TransactionId => _smartContractBridgeContextImplementation.TransactionId; - - /// - /// The Sender of the transaction that is executing. - /// - public Address Sender => _smartContractBridgeContextImplementation.Sender; - - /// - /// The address of the contract currently being executed. This changes for every transaction and inline transaction. - /// - public Address Self => _smartContractBridgeContextImplementation.Self; - - /// - /// The address of the sender (signer) of the transaction being executed. It’s type is an AElf address. It - /// corresponds to the From field of the transaction. This value never changes, even for nested inline calls. - /// This means that when you access this property in your contract, it’s value will be the entity that created - /// the transaction (user or smart contract through an inline call). - /// - public Address Origin => _smartContractBridgeContextImplementation.Origin; - - public Hash OriginTransactionId => _smartContractBridgeContextImplementation.OriginTransactionId; - - /// - /// The height of the block that contains the transaction currently executing. - /// - public long CurrentHeight => _smartContractBridgeContextImplementation.CurrentHeight; - - /// - /// The time included in the current blocks header. - /// - public Timestamp CurrentBlockTime => _smartContractBridgeContextImplementation.CurrentBlockTime; - - /// - /// The hash of the block that precedes the current in the blockchain structure. - /// - public Hash PreviousBlockHash => _smartContractBridgeContextImplementation.PreviousBlockHash; - - /// - /// Provides access to variable of the bridge. - /// - public ContextVariableDictionary Variables => _smartContractBridgeContextImplementation.Variables; - - /// - /// Recovers the public key of the transaction Sender. - /// - /// A byte array representing the public key. - public byte[] RecoverPublicKey() - { - return _smartContractBridgeContextImplementation.RecoverPublicKey(); - } - - /// - /// Returns the transaction included in the previous block (previous to the one currently executing). - /// - /// A list of transaction. - public List GetPreviousBlockTransactions() - { - return _smartContractBridgeContextImplementation.GetPreviousBlockTransactions(); - } - - /// - /// Returns whether or not the given transaction is well formed and the signature is correct. - /// - /// The transaction to verify. - /// The verification results. - public bool VerifySignature(Transaction tx) - { - return _smartContractBridgeContextImplementation.VerifySignature(tx); - } - - /// - /// Deploy a new smart contract (only the genesis contract can call it). - /// - /// The address of new smart contract. - /// The registration of the new smart contract. - /// The hash value of the smart contract name. - public void DeployContract(Address address, SmartContractRegistration registration, Hash name) - { - _smartContractBridgeContextImplementation.DeployContract(address, registration, name); - } - - /// - /// Update a smart contract (only the genesis contract can call it). - /// - /// The address of smart contract to update. - /// The registration of the smart contract to update. - /// The hash value of the smart contract name to update. - public void UpdateContract(Address address, SmartContractRegistration registration, Hash name) - { - _smartContractBridgeContextImplementation.UpdateContract(address, registration, name); - } - - /// - /// Calls a method on another contract. - /// - /// The address to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to call. - /// The input arguments for calling that method. This is usually generated from the protobuf - /// definition of the input type - /// The type of the return message. - /// The result of the call. - public T Call(Address fromAddress, Address toAddress, string methodName, ByteString args) - where T : IMessage, new() - { - return _smartContractBridgeContextImplementation.Call(fromAddress, toAddress, methodName, args); - } - - /// - /// Sends an inline transaction to another contract. - /// - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The input arguments for calling that method. This is usually generated from the protobuf - /// definition of the input type. - public void SendInline(Address toAddress, string methodName, ByteString args) - { - _smartContractBridgeContextImplementation.SendInline(toAddress, methodName, args); - } - - /// - /// Sends a virtual inline transaction to another contract. - /// - /// The virtual address to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The input arguments for calling that method. This is usually generated from the protobuf - /// definition of the input type. - public void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args) - { - _smartContractBridgeContextImplementation.SendVirtualInline(fromVirtualAddress, toAddress, methodName, - args); - } - - /// - /// Sends a virtual inline transaction to another contract. This method is only available to system smart contract. - /// - /// The virtual address of the system contract to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The input arguments for calling that method. This is usually generated from the protobuf - /// definition of the input type. - public void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, - ByteString args) - { - _smartContractBridgeContextImplementation.SendVirtualInlineBySystemContract(fromVirtualAddress, toAddress, - methodName, args); - } - - /// - /// Converts a virtual address to a contract address. - /// - /// The virtual address that want to convert. - /// The converted address. - public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress) - { - return _smartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddress(virtualAddress); - } - - /// - /// Converts a virtual address to a contract address with the current contract hash name. - /// - /// The virtual address that want to convert. - /// The converted address. - public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress) - { - return _smartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddressWithContractHashName( - virtualAddress); - } - - /// - /// Converts a virtual address to a contract address with the contract address. - /// - /// The virtual address that want to convert. - /// The contract address. - /// The converted address. - public Address ConvertVirtualAddressToContractAddress(Hash virtualAddress, Address contractAddress) - { - return _smartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddress(virtualAddress, - contractAddress); - } - - /// - /// Converts a virtual address to a contract address with the contract hash name. - /// - /// The virtual address that want to convert. - /// The contract address. - /// - public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualAddress, - Address contractAddress) - { - return _smartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddressWithContractHashName( - virtualAddress, contractAddress); - } - - /// - /// This method returns the address of the Genesis contract (smart contract zero) of the current chain. - /// - /// The address of the genesis contract. - public Address GetZeroSmartContractAddress() - { - return _smartContractBridgeContextImplementation.GetZeroSmartContractAddress(); - } - - /// - /// This method returns the address of the Genesis contract (smart contract zero) of the specified chain. - /// - /// The chain's ID. - /// The address of the genesis contract, for the given chain. - public Address GetZeroSmartContractAddress(int chainId) - { - return _smartContractBridgeContextImplementation.GetZeroSmartContractAddress(chainId); - } - - /// - /// It's sometimes useful to get the address of a system contract. The input is a hash of the system contracts - /// name. These hashes are easily accessible through the constants in the SmartContractConstants.cs file of the - /// C# SDK. - /// - /// The hash of the name. - /// The address of the system contract. - public Address GetContractAddressByName(string hash) - { - return _smartContractBridgeContextImplementation.GetContractAddressByName(hash); - } - - /// - /// Get the mapping that associates the system contract addresses and their name's hash. - /// - /// The addresses with their hashes. - public IReadOnlyDictionary GetSystemContractNameToAddressMapping() - { - return _smartContractBridgeContextImplementation.GetSystemContractNameToAddressMapping(); - } - - /// - /// Generate a hash type id based on the contract address and the bytes. - /// - /// The contract address on which the id generation is based. - /// The bytes on which the id generation is based. - /// The generated hash type id. - public Hash GenerateId(Address contractAddress, IEnumerable bytes) - { - return _smartContractBridgeContextImplementation.GenerateId(contractAddress, bytes); - } - - /// - /// Verify that the state size is within the valid value. - /// - /// The state. - /// The state. - /// The state size exceeds the limit. - public object ValidateStateSize(object obj) - { - return _smartContractBridgeContextImplementation.ValidateStateSize(obj); - } - - /// - /// Gets a random hash based on the input hash. - /// - /// Hash. - /// Random hash. - public Hash GetRandomHash(Hash fromHash) - { - return _smartContractBridgeContextImplementation.GetRandomHash(fromHash); - } - - /// - /// Converts the input hash to a 64-bit signed integer. - /// - /// The hash. - /// The inclusive lower bound of the number returned. - /// The exclusive upper bound of the number returned. endValue must be greater than or equal to startValue. - /// The 64-bit signed integer. - /// startValue is less than 0 or greater than endValue. - public long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue) - { - return _smartContractBridgeContextImplementation.ConvertHashToInt64(hash, start, end); - } + return SmartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddressWithContractHashName( + virtualAddress); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContract`.cs b/src/AElf.Sdk.CSharp/CSharpSmartContract`.cs index 58f3757ef7..ee05c91e19 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContract`.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContract`.cs @@ -1,18 +1,17 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Sdk.CSharp +namespace AElf.Sdk.CSharp; + +/// +/// This class represents a base class for contracts written in the C# language. The generated code from the +/// protobuf definitions will inherit from this class. +/// +/// +public partial class CSharpSmartContract where TContractState : ContractState, new() { /// - /// This class represents a base class for contracts written in the C# language. The generated code from the - /// protobuf definitions will inherit from this class. + /// Provides access to the State class instance. TContractState is the type of the state class defined by the + /// contract author. /// - /// - public partial class CSharpSmartContract where TContractState : ContractState, new() - { - /// - /// Provides access to the State class instance. TContractState is the type of the state class defined by the - /// contract author. - /// - public TContractState State { get; internal set; } - } + public TContractState State { get; internal set; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContract`_Internal.cs b/src/AElf.Sdk.CSharp/CSharpSmartContract`_Internal.cs index 4bf2fc2a7a..b40cccad5b 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContract`_Internal.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContract`_Internal.cs @@ -1,39 +1,38 @@ using System; -using AElf.Types; using AElf.Kernel.SmartContract; +using AElf.Types; + +namespace AElf.Sdk.CSharp; -namespace AElf.Sdk.CSharp +public partial class CSharpSmartContract : CSharpSmartContractAbstract { - public partial class CSharpSmartContract : CSharpSmartContractAbstract + public CSharpSmartContract() { + State = new TContractState(); + State.Path = new StatePath(); + ; + } - public CSharpSmartContract() - { - State = new TContractState(); - State.Path = new StatePath();; - } - internal override TransactionExecutingStateSet GetChanges() - { - return State.GetChanges(); - } + internal override TransactionExecutingStateSet GetChanges() + { + return State.GetChanges(); + } - internal override void Cleanup() - { - State.Clear(); - } + internal override void Cleanup() + { + State.Clear(); + } - internal override void InternalInitialize(ISmartContractBridgeContext bridgeContext) - { - if (Context != null) - throw new InvalidOperationException(); - Context = new CSharpSmartContractContext(bridgeContext); - State.Context = Context; - OnInitialized(); - } + internal override void InternalInitialize(ISmartContractBridgeContext bridgeContext) + { + if (Context != null) + throw new InvalidOperationException(); + Context = new CSharpSmartContractContext(bridgeContext); + State.Context = Context; + OnInitialized(); + } - protected virtual void OnInitialized() - { - - } + protected virtual void OnInitialized() + { } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/Exceptions.cs b/src/AElf.Sdk.CSharp/Exceptions.cs index fe71bc2822..8d09d83a58 100644 --- a/src/AElf.Sdk.CSharp/Exceptions.cs +++ b/src/AElf.Sdk.CSharp/Exceptions.cs @@ -1,87 +1,86 @@ using System; using System.Runtime.Serialization; -namespace AElf.Sdk.CSharp -{ - [Serializable] - public class BaseAElfException : Exception - { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // +namespace AElf.Sdk.CSharp; - public BaseAElfException() - { - } +[Serializable] +public class BaseAElfException : Exception +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // - public BaseAElfException(string message) : base(message) - { - } + public BaseAElfException() + { + } - public BaseAElfException(string message, Exception inner) : base(message, inner) - { - } + public BaseAElfException(string message) : base(message) + { + } - protected BaseAElfException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + public BaseAElfException(string message, Exception inner) : base(message, inner) + { } - [Serializable] - public class AssertionException : Exception + protected BaseAElfException( + SerializationInfo info, + StreamingContext context) : base(info, context) { - // - // For guidelines regarding the creation of new exception types, see - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp - // and - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp - // + } +} + +[Serializable] +public class AssertionException : Exception +{ + // + // For guidelines regarding the creation of new exception types, see + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp + // and + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp + // - public AssertionException() - { - } + public AssertionException() + { + } - public AssertionException(string message) : base(message) - { - } + public AssertionException(string message) : base(message) + { + } - public AssertionException(string message, Exception inner) : base(message, inner) - { - } + public AssertionException(string message, Exception inner) : base(message, inner) + { + } - protected AssertionException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } + protected AssertionException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { } - - [Serializable] - public class RuntimeCallThresholdExceededException : BaseAElfException +} + +[Serializable] +public class RuntimeCallThresholdExceededException : BaseAElfException +{ + public RuntimeCallThresholdExceededException() { - public RuntimeCallThresholdExceededException() - { - } + } - public RuntimeCallThresholdExceededException(string message) : base(message) - { - } + public RuntimeCallThresholdExceededException(string message) : base(message) + { } - - [Serializable] - public class RuntimeBranchThresholdExceededException : BaseAElfException +} + +[Serializable] +public class RuntimeBranchThresholdExceededException : BaseAElfException +{ + public RuntimeBranchThresholdExceededException() { - public RuntimeBranchThresholdExceededException() - { - } + } - public RuntimeBranchThresholdExceededException(string message) : base(message) - { - } + public RuntimeBranchThresholdExceededException(string message) : base(message) + { } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/ExecutionObserver.cs b/src/AElf.Sdk.CSharp/ExecutionObserver.cs index 8e84def38b..9e47aa6906 100644 --- a/src/AElf.Sdk.CSharp/ExecutionObserver.cs +++ b/src/AElf.Sdk.CSharp/ExecutionObserver.cs @@ -1,52 +1,47 @@ using AElf.Kernel.SmartContract; -namespace AElf.Sdk.CSharp +namespace AElf.Sdk.CSharp; + +// Instantiated for every transaction +public sealed class ExecutionObserver : IExecutionObserver { - // Instantiated for every transaction - public sealed class ExecutionObserver : IExecutionObserver + private readonly int _branchThreshold; + private readonly int _callThreshold; + private int _branchCount; + private int _callCount; + + public ExecutionObserver(int callThreshold, int branchThreshold) + { + _callCount = 0; + _branchCount = 0; + _callThreshold = callThreshold; + _branchThreshold = branchThreshold; + } + + public void CallCount() + { + if (_callThreshold != -1 && _callCount == _callThreshold) + throw new RuntimeCallThresholdExceededException($"Contract call threshold {_callThreshold} exceeded."); + + _callCount++; + } + + public void BranchCount() + { + if (_branchThreshold != -1 && _branchCount == _branchThreshold) + throw new RuntimeBranchThresholdExceededException( + $"Contract branch threshold {_branchThreshold} exceeded."); + + _branchCount++; + } + + public int GetCallCount() + { + return _callCount; + } + + public int GetBranchCount() { - private int _callCount; - private int _branchCount; - private readonly int _callThreshold; - private readonly int _branchThreshold; - - public ExecutionObserver(int callThreshold, int branchThreshold) - { - _callCount = 0; - _branchCount = 0; - _callThreshold = callThreshold; - _branchThreshold = branchThreshold; - } - - public void CallCount() - { - if (_callThreshold != -1 && _callCount == _callThreshold) - { - throw new RuntimeCallThresholdExceededException($"Contract call threshold {_callThreshold} exceeded."); - } - - _callCount++; - } - - public void BranchCount() - { - if (_branchThreshold != -1 && _branchCount == _branchThreshold) - { - throw new RuntimeBranchThresholdExceededException( - $"Contract branch threshold {_branchThreshold} exceeded."); - } - - _branchCount++; - } - - public int GetCallCount() - { - return _callCount; - } - - public int GetBranchCount() - { - return _branchCount; - } + return _branchCount; } -} +} \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/Properties/InternalVisibleTo.cs b/src/AElf.Sdk.CSharp/Properties/InternalVisibleTo.cs index 1824acd2fd..749d356eb6 100644 --- a/src/AElf.Sdk.CSharp/Properties/InternalVisibleTo.cs +++ b/src/AElf.Sdk.CSharp/Properties/InternalVisibleTo.cs @@ -1,4 +1,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("AElf.Runtime.CSharp")] -[assembly: InternalsVisibleTo("AElf.Sdk.CSharp.Tests")] +[assembly: InternalsVisibleTo("AElf.Sdk.CSharp.Tests")] \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs b/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs index 38ae8fa516..d6799d09fa 100644 --- a/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs +++ b/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs @@ -1,235 +1,233 @@ using System.Collections.Generic; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf; -using AElf.Kernel.SmartContract; +namespace AElf.Sdk.CSharp; -namespace AElf.Sdk.CSharp +/// +/// Extension methods that help with the interactions with the smart contract execution context. +/// +public static class SmartContractBridgeContextExtensions { /// - /// Extension methods that help with the interactions with the smart contract execution context. - /// - public static class SmartContractBridgeContextExtensions - { - /// - /// Logs an event during the execution of a transaction. The event type is defined in the AElf.CSharp.core - /// project. - /// - /// An instance of . - /// The event to log. - /// The type of the event. - public static void Fire(this CSharpSmartContractContext context, T eventData) where T : IEvent - { - context.FireLogEvent(eventData.ToLogEvent(context.Self)); - } - - /// - /// Calls a method on another contract. - /// - /// An instance of . - /// The address of the contract you're seeking to interact with. - /// The name of method you want to call. - /// The protobuf message that will be the input to the call. - /// The return type of the call. - /// The return value of the call. - public static T Call(this ISmartContractBridgeContext context, Address address, - string methodName, IMessage message) where T : IMessage, new() - { - return context.Call(context.Self, address, methodName, ConvertToByteString(message)); - } - - /// - /// Sends an inline transaction to another contract. - /// - /// An instance of . - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The protobuf message that will be the input to the call. - public static void SendInline(this ISmartContractBridgeContext context, Address toAddress, string methodName, - IMessage message) - { - context.SendInline(toAddress, methodName, ConvertToByteString(message)); - } - - /// - /// Sends a virtual inline transaction to another contract. - /// - /// An instance of . - /// The virtual address to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The protobuf message that will be the input to the call. - public static void SendVirtualInline(this ISmartContractBridgeContext context, Hash fromVirtualAddress, - Address toAddress, string methodName, IMessage message) - { - context.SendVirtualInline(fromVirtualAddress, toAddress, methodName, - ConvertToByteString(message)); - } - - /// - /// Calls a method on another contract. - /// - /// An instance of . - /// The address of the contract you're seeking to interact with. - /// The name of method you want to call. - /// The protobuf message that will be the input to the call. - /// The type of the return message. - /// The result of the call. - public static T Call(this CSharpSmartContractContext context, Address address, - string methodName, IMessage message) where T : IMessage, new() - { - return context.Call(context.Self, address, methodName, ConvertToByteString(message)); - } - - /// - /// Calls a method on another contract. - /// - /// An instance of . - /// The address to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to call. - /// The protobuf message that will be the input to the call. - /// The type of the return message. - /// The result of the call. - public static T Call(this CSharpSmartContractContext context, Address fromAddress, Address toAddress, - string methodName, IMessage message) where T : IMessage, new() - { - return context.Call(fromAddress, toAddress, methodName, ConvertToByteString(message)); - } - - /// - /// Calls a method on another contract. - /// - /// An instance of . - /// The address of the contract you're seeking to interact with. - /// The name of method you want to call. - /// The protobuf message that will be the input to the call. - /// The type of the return message. - /// The result of the call. - public static T Call(this CSharpSmartContractContext context, Address address, - string methodName, ByteString message) where T : IMessage, new() - { - return context.Call(context.Self, address, methodName, message); - } - - /// - /// Sends a virtual inline transaction to another contract. - /// - /// An instance of . - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The protobuf message that will be the input to the call. - public static void SendInline(this CSharpSmartContractContext context, Address toAddress, string methodName, - IMessage message) - { - context.SendInline(toAddress, methodName, ConvertToByteString(message)); - } - - /// - /// Sends a virtual inline transaction to another contract. - /// - /// An instance of . - /// The virtual address to use as sender. - /// The address of the contract you're seeking to interact with. - /// The name of method you want to invoke. - /// The protobuf message that will be the input to the call. - public static void SendVirtualInline(this CSharpSmartContractContext context, Hash fromVirtualAddress, - Address toAddress, string methodName, IMessage message) - { - context.SendVirtualInline(fromVirtualAddress, toAddress, methodName, - ConvertToByteString(message)); - } - - /// - /// Serializes a protobuf message to a protobuf ByteString. - /// - /// The message to serialize. - /// ByteString.Empty if the message is null - public static ByteString ConvertToByteString(IMessage message) - { - return message?.ToByteString() ?? ByteString.Empty; - //return ByteString.CopyFrom(ParamsPacker.Pack(message)); - } - - /// - /// Generate a hash type id based on the currently running contract address and the bytes. - /// - /// An instance of . - /// The bytes on which the id generation is based. - /// The generated hash type id. - public static Hash GenerateId(this ISmartContractBridgeContext @this, IEnumerable bytes) - { - return @this.GenerateId(@this.Self, bytes); - } - - /// - /// Generate a hash type id based on the currently running contract address and the token. - /// - /// An instance of . - /// The token on which the id generation is based. - /// The generated hash type id. - public static Hash GenerateId(this ISmartContractBridgeContext @this, string token) - { - return @this.GenerateId(@this.Self, token.GetBytes()); - } - - /// - /// Generate a hash type id based on the currently running contract address and the hash type token. - /// - /// An instance of . - /// The hash type token on which the id generation is based. - /// The generated hash type id. - public static Hash GenerateId(this ISmartContractBridgeContext @this, Hash token) - { - return @this.GenerateId(@this.Self, token.Value); - } - - /// - /// Generate a hash type id based on the currently running contract address. - /// - /// An instance of . - /// The generated hash type id. - public static Hash GenerateId(this ISmartContractBridgeContext @this) - { - return @this.GenerateId(@this.Self, null); - } - - /// - /// Generate a hash type id based on the address and the bytes. - /// - /// An instance of . - /// The address on which the id generation is based. - /// The hash type token on which the id generation is based. - /// The generated hash type id. - public static Hash GenerateId(this ISmartContractBridgeContext @this, Address address, Hash token) - { - return @this.GenerateId(address, token); - } - - /// - /// Converts a virtual address to a contract address. - /// - /// An instance of . - /// The virtual address that want to convert. - /// - public static Address ConvertVirtualAddressToContractAddress(this ISmartContractBridgeContext @this, - Hash virtualAddress) - { - return @this.ConvertVirtualAddressToContractAddress(virtualAddress, @this.Self); - } - - /// - /// Converts a virtual address to a contract address with the currently running contract address. - /// - /// An instance of . - /// The virtual address that want to convert. - /// - public static Address ConvertVirtualAddressToContractAddressWithContractHashName( - this ISmartContractBridgeContext @this, Hash virtualAddress) - { - return @this.ConvertVirtualAddressToContractAddressWithContractHashName(virtualAddress, @this.Self); - } + /// Logs an event during the execution of a transaction. The event type is defined in the AElf.CSharp.core + /// project. + /// + /// An instance of . + /// The event to log. + /// The type of the event. + public static void Fire(this CSharpSmartContractContext context, T eventData) where T : IEvent + { + context.FireLogEvent(eventData.ToLogEvent(context.Self)); + } + + /// + /// Calls a method on another contract. + /// + /// An instance of . + /// The address of the contract you're seeking to interact with. + /// The name of method you want to call. + /// The protobuf message that will be the input to the call. + /// The return type of the call. + /// The return value of the call. + public static T Call(this ISmartContractBridgeContext context, Address address, + string methodName, IMessage message) where T : IMessage, new() + { + return context.Call(context.Self, address, methodName, ConvertToByteString(message)); + } + + /// + /// Sends an inline transaction to another contract. + /// + /// An instance of . + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// The protobuf message that will be the input to the call. + public static void SendInline(this ISmartContractBridgeContext context, Address toAddress, string methodName, + IMessage message) + { + context.SendInline(toAddress, methodName, ConvertToByteString(message)); + } + + /// + /// Sends a virtual inline transaction to another contract. + /// + /// An instance of . + /// The virtual address to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// The protobuf message that will be the input to the call. + public static void SendVirtualInline(this ISmartContractBridgeContext context, Hash fromVirtualAddress, + Address toAddress, string methodName, IMessage message) + { + context.SendVirtualInline(fromVirtualAddress, toAddress, methodName, + ConvertToByteString(message)); + } + + /// + /// Calls a method on another contract. + /// + /// An instance of . + /// The address of the contract you're seeking to interact with. + /// The name of method you want to call. + /// The protobuf message that will be the input to the call. + /// The type of the return message. + /// The result of the call. + public static T Call(this CSharpSmartContractContext context, Address address, + string methodName, IMessage message) where T : IMessage, new() + { + return context.Call(context.Self, address, methodName, ConvertToByteString(message)); + } + + /// + /// Calls a method on another contract. + /// + /// An instance of . + /// The address to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to call. + /// The protobuf message that will be the input to the call. + /// The type of the return message. + /// The result of the call. + public static T Call(this CSharpSmartContractContext context, Address fromAddress, Address toAddress, + string methodName, IMessage message) where T : IMessage, new() + { + return context.Call(fromAddress, toAddress, methodName, ConvertToByteString(message)); + } + + /// + /// Calls a method on another contract. + /// + /// An instance of . + /// The address of the contract you're seeking to interact with. + /// The name of method you want to call. + /// The protobuf message that will be the input to the call. + /// The type of the return message. + /// The result of the call. + public static T Call(this CSharpSmartContractContext context, Address address, + string methodName, ByteString message) where T : IMessage, new() + { + return context.Call(context.Self, address, methodName, message); + } + + /// + /// Sends a virtual inline transaction to another contract. + /// + /// An instance of . + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// The protobuf message that will be the input to the call. + public static void SendInline(this CSharpSmartContractContext context, Address toAddress, string methodName, + IMessage message) + { + context.SendInline(toAddress, methodName, ConvertToByteString(message)); + } + + /// + /// Sends a virtual inline transaction to another contract. + /// + /// An instance of . + /// The virtual address to use as sender. + /// The address of the contract you're seeking to interact with. + /// The name of method you want to invoke. + /// The protobuf message that will be the input to the call. + public static void SendVirtualInline(this CSharpSmartContractContext context, Hash fromVirtualAddress, + Address toAddress, string methodName, IMessage message) + { + context.SendVirtualInline(fromVirtualAddress, toAddress, methodName, + ConvertToByteString(message)); + } + + /// + /// Serializes a protobuf message to a protobuf ByteString. + /// + /// The message to serialize. + /// ByteString.Empty if the message is null + public static ByteString ConvertToByteString(IMessage message) + { + return message?.ToByteString() ?? ByteString.Empty; + //return ByteString.CopyFrom(ParamsPacker.Pack(message)); + } + + /// + /// Generate a hash type id based on the currently running contract address and the bytes. + /// + /// An instance of . + /// The bytes on which the id generation is based. + /// The generated hash type id. + public static Hash GenerateId(this ISmartContractBridgeContext @this, IEnumerable bytes) + { + return @this.GenerateId(@this.Self, bytes); + } + + /// + /// Generate a hash type id based on the currently running contract address and the token. + /// + /// An instance of . + /// The token on which the id generation is based. + /// The generated hash type id. + public static Hash GenerateId(this ISmartContractBridgeContext @this, string token) + { + return @this.GenerateId(@this.Self, token.GetBytes()); + } + + /// + /// Generate a hash type id based on the currently running contract address and the hash type token. + /// + /// An instance of . + /// The hash type token on which the id generation is based. + /// The generated hash type id. + public static Hash GenerateId(this ISmartContractBridgeContext @this, Hash token) + { + return @this.GenerateId(@this.Self, token.Value); + } + + /// + /// Generate a hash type id based on the currently running contract address. + /// + /// An instance of . + /// The generated hash type id. + public static Hash GenerateId(this ISmartContractBridgeContext @this) + { + return @this.GenerateId(@this.Self, null); + } + + /// + /// Generate a hash type id based on the address and the bytes. + /// + /// An instance of . + /// The address on which the id generation is based. + /// The hash type token on which the id generation is based. + /// The generated hash type id. + public static Hash GenerateId(this ISmartContractBridgeContext @this, Address address, Hash token) + { + return @this.GenerateId(address, token); + } + + /// + /// Converts a virtual address to a contract address. + /// + /// An instance of . + /// The virtual address that want to convert. + /// + public static Address ConvertVirtualAddressToContractAddress(this ISmartContractBridgeContext @this, + Hash virtualAddress) + { + return @this.ConvertVirtualAddressToContractAddress(virtualAddress, @this.Self); + } + + /// + /// Converts a virtual address to a contract address with the currently running contract address. + /// + /// An instance of . + /// The virtual address that want to convert. + /// + public static Address ConvertVirtualAddressToContractAddressWithContractHashName( + this ISmartContractBridgeContext @this, Hash virtualAddress) + { + return @this.ConvertVirtualAddressToContractAddressWithContractHashName(virtualAddress, @this.Self); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/SmartContractConstants.cs b/src/AElf.Sdk.CSharp/SmartContractConstants.cs index 99259c03d5..04e527785b 100644 --- a/src/AElf.Sdk.CSharp/SmartContractConstants.cs +++ b/src/AElf.Sdk.CSharp/SmartContractConstants.cs @@ -1,49 +1,69 @@ using AElf.Types; -namespace AElf.Sdk.CSharp +namespace AElf.Sdk.CSharp; + +/// +/// Static class containing the hashes built from the names of the contracts. +/// +public static class SmartContractConstants { - /// - /// Static class containing the hashes built from the names of the contracts. - /// - public static class SmartContractConstants + public static readonly Hash ElectionContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Election"); + public static readonly Hash TreasuryContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Treasury"); + + public static readonly Hash ConsensusContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); + + public static readonly Hash TokenContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Token"); + + public static readonly Hash ParliamentContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); + + public static readonly Hash VoteContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); + public static readonly Hash ProfitContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Profit"); + + public static readonly Hash CrossChainContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.CrossChain"); + + public static readonly Hash TokenConverterContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.TokenConverter"); + + public static readonly Hash EconomicContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); + + public static readonly Hash ReferendumContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.Referendum"); + + public static readonly Hash AssociationContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.Association"); + + public static readonly Hash ConfigurationContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.Configuration"); + + public static readonly Hash TokenHolderContractSystemHashName = + HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); + + public static readonly string ElectionContractSystemName = GetStringName(ElectionContractSystemHashName); + public static readonly string TreasuryContractSystemName = GetStringName(TreasuryContractSystemHashName); + public static readonly string ConsensusContractSystemName = GetStringName(ConsensusContractSystemHashName); + public static readonly string TokenContractSystemName = GetStringName(TokenContractSystemHashName); + public static readonly string ParliamentContractSystemName = GetStringName(ParliamentContractSystemHashName); + public static readonly string VoteContractSystemName = GetStringName(VoteContractSystemHashName); + public static readonly string ProfitContractSystemName = GetStringName(ProfitContractSystemHashName); + public static readonly string CrossChainContractSystemName = GetStringName(CrossChainContractSystemHashName); + + public static readonly string TokenConverterContractSystemName = + GetStringName(TokenConverterContractSystemHashName); + + public static readonly string EconomicContractSystemName = GetStringName(EconomicContractSystemHashName); + public static readonly string ReferendumContractSystemName = GetStringName(ReferendumContractSystemHashName); + public static readonly string AssociationContractSystemName = GetStringName(AssociationContractSystemHashName); + public static readonly string ConfigurationContractSystemName = GetStringName(ConfigurationContractSystemHashName); + public static readonly string TokenHolderContractSystemName = GetStringName(TokenHolderContractSystemHashName); + + + public static readonly int AElfStringLengthLimitInContract = 20000; + + private static string GetStringName(Hash hash) { - public static readonly Hash ElectionContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Election"); - public static readonly Hash TreasuryContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Treasury"); - public static readonly Hash ConsensusContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); - public static readonly Hash TokenContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Token"); - public static readonly Hash ParliamentContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); - public static readonly Hash VoteContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); - public static readonly Hash ProfitContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Profit"); - public static readonly Hash CrossChainContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.CrossChain"); - public static readonly Hash TokenConverterContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.TokenConverter"); - public static readonly Hash EconomicContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); - public static readonly Hash ReferendumContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Referendum"); - public static readonly Hash AssociationContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Association"); - public static readonly Hash ConfigurationContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.Configuration"); - public static readonly Hash TokenHolderContractSystemHashName = HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); - - public static readonly string ElectionContractSystemName = GetStringName(ElectionContractSystemHashName); - public static readonly string TreasuryContractSystemName = GetStringName(TreasuryContractSystemHashName); - public static readonly string ConsensusContractSystemName = GetStringName(ConsensusContractSystemHashName); - public static readonly string TokenContractSystemName = GetStringName(TokenContractSystemHashName); - public static readonly string ParliamentContractSystemName = GetStringName(ParliamentContractSystemHashName); - public static readonly string VoteContractSystemName = GetStringName(VoteContractSystemHashName); - public static readonly string ProfitContractSystemName = GetStringName(ProfitContractSystemHashName); - public static readonly string CrossChainContractSystemName = GetStringName(CrossChainContractSystemHashName); - public static readonly string TokenConverterContractSystemName = GetStringName(TokenConverterContractSystemHashName); - public static readonly string EconomicContractSystemName = GetStringName(EconomicContractSystemHashName); - public static readonly string ReferendumContractSystemName = GetStringName(ReferendumContractSystemHashName); - public static readonly string AssociationContractSystemName = GetStringName(AssociationContractSystemHashName); - public static readonly string ConfigurationContractSystemName = GetStringName(ConfigurationContractSystemHashName); - public static readonly string TokenHolderContractSystemName = GetStringName(TokenHolderContractSystemHashName); - - - - public static readonly int AElfStringLengthLimitInContract = 20000; - - private static string GetStringName(Hash hash) - { - return hash.Value.ToBase64(); - } + return hash.Value.ToBase64(); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/ContractReferenceState.cs b/src/AElf.Sdk.CSharp/State/ContractReferenceState.cs index 5cda6752ab..fb0db0be1f 100644 --- a/src/AElf.Sdk.CSharp/State/ContractReferenceState.cs +++ b/src/AElf.Sdk.CSharp/State/ContractReferenceState.cs @@ -4,36 +4,35 @@ using System.Reflection; using AElf.Types; -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +public class ContractReferenceState : SingletonState
{ - public class ContractReferenceState : SingletonState
- { - private Dictionary _methodReferenceProperties; + private Dictionary _methodReferenceProperties; - public ContractReferenceState() - { - DetectPropertyInfos(); - InitializeProperties(); - } + public ContractReferenceState() + { + DetectPropertyInfos(); + InitializeProperties(); + } - private void DetectPropertyInfos() - { - _methodReferenceProperties = this.GetType() - .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - .Where(x => x.PropertyType.IsMethodReference()) - .ToDictionary(x => x.Name, x => x); - } + private void DetectPropertyInfos() + { + _methodReferenceProperties = GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(x => x.PropertyType.IsMethodReference()) + .ToDictionary(x => x.Name, x => x); + } - private void InitializeProperties() + private void InitializeProperties() + { + foreach (var kv in _methodReferenceProperties) { - foreach (var kv in _methodReferenceProperties) - { - var name = kv.Key; - var propertyInfo = kv.Value; - var propertyType = kv.Value.PropertyType; - var instance = Activator.CreateInstance(propertyType, this, name); - propertyInfo.SetValue(this, instance); - } + var name = kv.Key; + var propertyInfo = kv.Value; + var propertyType = kv.Value.PropertyType; + var instance = Activator.CreateInstance(propertyType, this, name); + propertyInfo.SetValue(this, instance); } } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/ContractState.cs b/src/AElf.Sdk.CSharp/State/ContractState.cs index 13c35b4249..c8e2f870da 100644 --- a/src/AElf.Sdk.CSharp/State/ContractState.cs +++ b/src/AElf.Sdk.CSharp/State/ContractState.cs @@ -1,9 +1,8 @@ -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +/// +/// Base class for the state class in smart contracts. +/// +public class ContractState : StructuredState { - /// - /// Base class for the state class in smart contracts. - /// - public class ContractState : StructuredState - { - } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/MappedState.cs b/src/AElf.Sdk.CSharp/State/MappedState.cs index 48cb36eb8b..0cb8133b6d 100644 --- a/src/AElf.Sdk.CSharp/State/MappedState.cs +++ b/src/AElf.Sdk.CSharp/State/MappedState.cs @@ -2,60 +2,40 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +public class MappedState : StateBase { - public class MappedState : StateBase + internal StatePath GetSubStatePath(string key) { - internal StatePath GetSubStatePath(string key) - { - var statePath = this.Path.Clone(); - statePath.Parts.Add(key); - return statePath; - } + var statePath = Path.Clone(); + statePath.Parts.Add(key); + return statePath; } +} + +/// +/// Key-value pair data structure used for representing state in contracts. +/// +/// The type of the key. +/// The type of the value. +public class MappedState : MappedState +{ + internal Dictionary Cache = new(); - /// - /// Key-value pair data structure used for representing state in contracts. - /// - /// The type of the key. - /// The type of the value. - public class MappedState : MappedState + public TEntity this[TKey key] { - internal class ValuePair - { - internal TEntity OriginalValue; - internal TEntity Value; - internal bool IsDeleted; - } - - internal Dictionary Cache = new Dictionary(); - - public TEntity this[TKey key] + get { - get + if (!Cache.TryGetValue(key, out var valuePair)) { - if (!Cache.TryGetValue(key, out var valuePair)) - { - valuePair = LoadKey(key); - Cache[key] = valuePair; - } - - return valuePair.IsDeleted ? SerializationHelper.Deserialize(null) : valuePair.Value; + valuePair = LoadKey(key); + Cache[key] = valuePair; } - set - { - if (!Cache.TryGetValue(key, out var valuePair)) - { - valuePair = LoadKey(key); - Cache[key] = valuePair; - } - valuePair.IsDeleted = false; - valuePair.Value = value; - } + return valuePair.IsDeleted ? SerializationHelper.Deserialize(null) : valuePair.Value; } - - public void Remove(TKey key) + set { if (!Cache.TryGetValue(key, out var valuePair)) { @@ -63,245 +43,221 @@ public void Remove(TKey key) Cache[key] = valuePair; } - valuePair.IsDeleted = true; - } - - public void Set(TKey key, TEntity value) - { - var valuePair = new ValuePair - { - OriginalValue = default(TEntity), - Value = default(TEntity) - }; - Cache[key] = valuePair; + valuePair.IsDeleted = false; valuePair.Value = value; } + } - internal override void Clear() + public void Remove(TKey key) + { + if (!Cache.TryGetValue(key, out var valuePair)) { - Cache = new Dictionary(); + valuePair = LoadKey(key); + Cache[key] = valuePair; } - internal override TransactionExecutingStateSet GetChanges() - { - var stateSet = new TransactionExecutingStateSet(); - foreach (var kv in Cache) - { - var key = GetSubStatePath(kv.Key.ToString()).ToStateKey(Context.Self); - if (kv.Value.IsDeleted) - { - stateSet.Deletes[key] = true; - } - else if (!Equals(kv.Value.OriginalValue, kv.Value.Value)) - { - stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(kv.Value.Value)); - } + valuePair.IsDeleted = true; + } - stateSet.Reads[key] = true; - } + public void Set(TKey key, TEntity value) + { + var valuePair = new ValuePair + { + OriginalValue = default, + Value = default + }; + Cache[key] = valuePair; + valuePair.Value = value; + } - return stateSet; - } + internal override void Clear() + { + Cache = new Dictionary(); + } - private ValuePair LoadKey(TKey key) + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + foreach (var kv in Cache) { - var path = GetSubStatePath(key.ToString()); - var bytes = Provider.Get(path); - var value = SerializationHelper.Deserialize(bytes); - var originalValue = SerializationHelper.Deserialize(bytes); + var key = GetSubStatePath(kv.Key.ToString()).ToStateKey(Context.Self); + if (kv.Value.IsDeleted) + stateSet.Deletes[key] = true; + else if (!Equals(kv.Value.OriginalValue, kv.Value.Value)) + stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(kv.Value.Value)); - return new ValuePair - { - OriginalValue = originalValue, - Value = value, - IsDeleted = false - }; + stateSet.Reads[key] = true; } + + return stateSet; } - public class MappedState : MappedState + private ValuePair LoadKey(TKey key) { - internal Dictionary> Cache = - new Dictionary>(); + var path = GetSubStatePath(key.ToString()); + var bytes = Provider.Get(path); + var value = SerializationHelper.Deserialize(bytes); + var originalValue = SerializationHelper.Deserialize(bytes); - public MappedState this[TKey1 key1] + return new ValuePair { - get - { - if (!Cache.TryGetValue(key1, out var child)) - { - child = new MappedState() - { - Context = Context, - Path = GetSubStatePath(key1.ToString()) - }; - Cache[key1] = child; - } - - return child; - } - } + OriginalValue = originalValue, + Value = value, + IsDeleted = false + }; + } - internal override void OnContextSet() - { - foreach (var v in Cache.Values) - { - v.Context = Context; - } - } + internal class ValuePair + { + internal bool IsDeleted; + internal TEntity OriginalValue; + internal TEntity Value; + } +} - internal override void Clear() - { - Cache = new Dictionary>(); - } +public class MappedState : MappedState +{ + internal Dictionary> Cache = new(); - internal override TransactionExecutingStateSet GetChanges() + public MappedState this[TKey1 key1] + { + get { - var stateSet = new TransactionExecutingStateSet(); - foreach (var kv in Cache) + if (!Cache.TryGetValue(key1, out var child)) { - var changes = kv.Value.GetChanges(); - foreach (var kv1 in changes.Deletes) - { - stateSet.Deletes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Writes) + child = new MappedState { - stateSet.Writes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Reads) - { - stateSet.Reads[kv1.Key] = kv1.Value; - } + Context = Context, + Path = GetSubStatePath(key1.ToString()) + }; + Cache[key1] = child; } - return stateSet; + return child; } } - public class MappedState : MappedState + internal override void OnContextSet() { - internal Dictionary> Cache = - new Dictionary>(); + foreach (var v in Cache.Values) v.Context = Context; + } - public MappedState this[TKey1 key1] - { - get - { - if (!Cache.TryGetValue(key1, out var child)) - { - child = new MappedState() - { - Context = Context, - Path = GetSubStatePath(key1.ToString()) - }; - Cache[key1] = child; - } - - return child; - } - } + internal override void Clear() + { + Cache = new Dictionary>(); + } - internal override void OnContextSet() + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + foreach (var kv in Cache) { - foreach (var v in Cache.Values) - { - v.Context = Context; - } - } + var changes = kv.Value.GetChanges(); + foreach (var kv1 in changes.Deletes) stateSet.Deletes[kv1.Key] = kv1.Value; - internal override void Clear() - { - Cache = new Dictionary>(); + foreach (var kv1 in changes.Writes) stateSet.Writes[kv1.Key] = kv1.Value; + + foreach (var kv1 in changes.Reads) stateSet.Reads[kv1.Key] = kv1.Value; } - internal override TransactionExecutingStateSet GetChanges() + return stateSet; + } +} + +public class MappedState : MappedState +{ + internal Dictionary> Cache = new(); + + public MappedState this[TKey1 key1] + { + get { - var stateSet = new TransactionExecutingStateSet(); - foreach (var kv in Cache) + if (!Cache.TryGetValue(key1, out var child)) { - var changes = kv.Value.GetChanges(); - foreach (var kv1 in changes.Deletes) - { - stateSet.Deletes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Writes) + child = new MappedState { - stateSet.Writes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Reads) - { - stateSet.Reads[kv1.Key] = kv1.Value; - } + Context = Context, + Path = GetSubStatePath(key1.ToString()) + }; + Cache[key1] = child; } - return stateSet; + return child; } } - public class MappedState : MappedState + internal override void OnContextSet() { - internal Dictionary> Cache = - new Dictionary>(); + foreach (var v in Cache.Values) v.Context = Context; + } - public MappedState this[TKey1 key1] + internal override void Clear() + { + Cache = new Dictionary>(); + } + + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + foreach (var kv in Cache) { - get - { - if (!Cache.TryGetValue(key1, out var child)) - { - child = new MappedState() - { - Context = Context, - Path = GetSubStatePath(key1.ToString()) - }; - Cache[key1] = child; - } - - return child; - } + var changes = kv.Value.GetChanges(); + foreach (var kv1 in changes.Deletes) stateSet.Deletes[kv1.Key] = kv1.Value; + + foreach (var kv1 in changes.Writes) stateSet.Writes[kv1.Key] = kv1.Value; + + foreach (var kv1 in changes.Reads) stateSet.Reads[kv1.Key] = kv1.Value; } - internal override void OnContextSet() + return stateSet; + } +} + +public class MappedState : MappedState +{ + internal Dictionary> Cache = new(); + + public MappedState this[TKey1 key1] + { + get { - foreach (var v in Cache.Values) + if (!Cache.TryGetValue(key1, out var child)) { - v.Context = Context; + child = new MappedState + { + Context = Context, + Path = GetSubStatePath(key1.ToString()) + }; + Cache[key1] = child; } - } - internal override void Clear() - { - Cache = new Dictionary>(); + return child; } + } - internal override TransactionExecutingStateSet GetChanges() + internal override void OnContextSet() + { + foreach (var v in Cache.Values) v.Context = Context; + } + + internal override void Clear() + { + Cache = new Dictionary>(); + } + + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + foreach (var kv in Cache) { - var stateSet = new TransactionExecutingStateSet(); - foreach (var kv in Cache) - { - var changes = kv.Value.GetChanges(); - foreach (var kv1 in changes.Deletes) - { - stateSet.Deletes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Writes) - { - stateSet.Writes[kv1.Key] = kv1.Value; - } + var changes = kv.Value.GetChanges(); + foreach (var kv1 in changes.Deletes) stateSet.Deletes[kv1.Key] = kv1.Value; - foreach (var kv1 in changes.Reads) - { - stateSet.Reads[kv1.Key] = kv1.Value; - } - } + foreach (var kv1 in changes.Writes) stateSet.Writes[kv1.Key] = kv1.Value; - return stateSet; + foreach (var kv1 in changes.Reads) stateSet.Reads[kv1.Key] = kv1.Value; } + + return stateSet; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/MethodReference.cs b/src/AElf.Sdk.CSharp/State/MethodReference.cs index 15967ddf96..70b1614eb8 100644 --- a/src/AElf.Sdk.CSharp/State/MethodReference.cs +++ b/src/AElf.Sdk.CSharp/State/MethodReference.cs @@ -1,44 +1,43 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +public class MethodReference where TInput : class, IMessage, new() + where TOutput : class, IMessage, new() { - public class MethodReference where TInput : class, IMessage, new() - where TOutput : class, IMessage, new() + private readonly string _name; + private readonly ContractReferenceState _parent; + + public MethodReference(ContractReferenceState parent, string name) + { + _parent = parent; + _name = name; + } + + public void Send(TInput input) + { + _parent.Context.SendInline(_parent.Value, _name, input); + } + + public TOutput Call(TInput input) + { + return _parent.Context.Call(_parent.Value, _name, input); + } + + public TOutput Call(Address fromAddress, TInput input) + { + return _parent.Context.Call(fromAddress, _parent.Value, _name, input); + } + + public void VirtualSend(Hash virtualAddress, TInput input) + { + _parent.Context.SendVirtualInline(virtualAddress, _parent.Value, _name, input); + } + + public TOutput VirtualCall(Hash virtualAddress, TInput input) { - private readonly ContractReferenceState _parent; - private readonly string _name; - - public MethodReference(ContractReferenceState parent, string name) - { - _parent = parent; - _name = name; - } - - public void Send(TInput input) - { - _parent.Context.SendInline(_parent.Value, _name, input); - } - - public TOutput Call(TInput input) - { - return _parent.Context.Call(_parent.Value, _name, input); - } - - public TOutput Call(Address fromAddress, TInput input) - { - return _parent.Context.Call(fromAddress, _parent.Value, _name, input); - } - - public void VirtualSend(Hash virtualAddress, TInput input) - { - _parent.Context.SendVirtualInline(virtualAddress, _parent.Value, _name, input); - } - - public TOutput VirtualCall(Hash virtualAddress, TInput input) - { - return _parent.Context.Call(_parent.Context.ConvertVirtualAddressToContractAddress(virtualAddress), - _parent.Value, _name, input); - } + return _parent.Context.Call(_parent.Context.ConvertVirtualAddressToContractAddress(virtualAddress), + _parent.Value, _name, input); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/MethodReferenceExtensions.cs b/src/AElf.Sdk.CSharp/State/MethodReferenceExtensions.cs index ba3a1476c6..f1972d9b2c 100644 --- a/src/AElf.Sdk.CSharp/State/MethodReferenceExtensions.cs +++ b/src/AElf.Sdk.CSharp/State/MethodReferenceExtensions.cs @@ -1,17 +1,13 @@ using System; -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +public static class MethodReferenceExtensions { - public static class MethodReferenceExtensions + public static bool IsMethodReference(this Type type) { - public static bool IsMethodReference(this Type type) - { - if (type.IsConstructedGenericType) - { - return type.GetGenericTypeDefinition() == typeof(MethodReference<,>); - } + if (type.IsConstructedGenericType) return type.GetGenericTypeDefinition() == typeof(MethodReference<,>); - return type == typeof(MethodReference<,>); - } + return type == typeof(MethodReference<,>); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/ReadonlyState.cs b/src/AElf.Sdk.CSharp/State/ReadonlyState.cs index cbd5be2750..e3bbedf1a8 100644 --- a/src/AElf.Sdk.CSharp/State/ReadonlyState.cs +++ b/src/AElf.Sdk.CSharp/State/ReadonlyState.cs @@ -1,69 +1,55 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Sdk.CSharp.State -{ - public class ReadonlyState : StateBase - { - } +namespace AElf.Sdk.CSharp.State; - public class ReadonlyState : ReadonlyState - { - internal bool Loaded; +public class ReadonlyState : StateBase +{ +} - private TEntity _value; +public class ReadonlyState : ReadonlyState +{ + private TEntity _value; + internal bool Loaded; - // If the target of current ReadonlyState is default(TEntity), it maybe not proper to use ReadonlyState. - private bool NotSetBefore => Equals(_value, default(TEntity)); + // If the target of current ReadonlyState is default(TEntity), it maybe not proper to use ReadonlyState. + private bool NotSetBefore => Equals(_value, default(TEntity)); - public TEntity Value + public TEntity Value + { + get { - get - { - if (!Loaded) - { - Load(); - } - - return _value; - } - set - { - if (!Loaded) - { - Load(); - } + if (!Loaded) Load(); - if (NotSetBefore) - { - _value = value; - } - } + return _value; } - - internal override void Clear() + set { - Loaded = false; - _value = default; - } + if (!Loaded) Load(); - internal override TransactionExecutingStateSet GetChanges() - { - var stateSet = new TransactionExecutingStateSet(); - var key = Path.ToStateKey(Context.Self); - if (!NotSetBefore) - { - stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(_value)); - } - - return stateSet; + if (NotSetBefore) _value = value; } + } - private void Load() - { - var bytes = Provider.Get(Path); - _value = SerializationHelper.Deserialize(bytes); - Loaded = true; - } + internal override void Clear() + { + Loaded = false; + _value = default; + } + + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + var key = Path.ToStateKey(Context.Self); + if (!NotSetBefore) stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(_value)); + + return stateSet; + } + + private void Load() + { + var bytes = Provider.Get(Path); + _value = SerializationHelper.Deserialize(bytes); + Loaded = true; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/SingletonState.cs b/src/AElf.Sdk.CSharp/State/SingletonState.cs index 7c481ecedf..cf13c3d05e 100644 --- a/src/AElf.Sdk.CSharp/State/SingletonState.cs +++ b/src/AElf.Sdk.CSharp/State/SingletonState.cs @@ -1,72 +1,61 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Sdk.CSharp.State -{ - public class SingletonState : StateBase - { - } +namespace AElf.Sdk.CSharp.State; - /// - /// Represents single values of a given type, for use in smart contract state. - /// - public class SingletonState : SingletonState - { - internal bool Loaded; - internal bool Modified => !Equals(_originalValue, _value); +public class SingletonState : StateBase +{ +} - private TEntity _originalValue; - private TEntity _value; +/// +/// Represents single values of a given type, for use in smart contract state. +/// +public class SingletonState : SingletonState +{ + private TEntity _originalValue; + private TEntity _value; + internal bool Loaded; + internal bool Modified => !Equals(_originalValue, _value); - public TEntity Value + public TEntity Value + { + get { - get - { - if (!Loaded) - { - Load(); - } - - return _value; - } - set - { - if (!Loaded) - { - Load(); - } + if (!Loaded) Load(); - _value = value; - } + return _value; } - - internal override void Clear() + set { - Loaded = false; - _originalValue = default; - _value = _originalValue; + if (!Loaded) Load(); + + _value = value; } + } - internal override TransactionExecutingStateSet GetChanges() - { - var stateSet = new TransactionExecutingStateSet(); - var key = Path.ToStateKey(Context.Self); - if (Modified) - { - stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(_value)); - } + internal override void Clear() + { + Loaded = false; + _originalValue = default; + _value = _originalValue; + } - if (Loaded) stateSet.Reads[key] = true; + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + var key = Path.ToStateKey(Context.Self); + if (Modified) stateSet.Writes[key] = ByteString.CopyFrom(SerializationHelper.Serialize(_value)); - return stateSet; - } + if (Loaded) stateSet.Reads[key] = true; - private void Load() - { - var bytes = Provider.Get(Path); - _originalValue = SerializationHelper.Deserialize(bytes); - _value = SerializationHelper.Deserialize(bytes); - Loaded = true; - } + return stateSet; + } + + private void Load() + { + var bytes = Provider.Get(Path); + _originalValue = SerializationHelper.Deserialize(bytes); + _value = SerializationHelper.Deserialize(bytes); + Loaded = true; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/SingletonState_Aliases.cs b/src/AElf.Sdk.CSharp/State/SingletonState_Aliases.cs index 49a9c776c8..d4f988eef5 100644 --- a/src/AElf.Sdk.CSharp/State/SingletonState_Aliases.cs +++ b/src/AElf.Sdk.CSharp/State/SingletonState_Aliases.cs @@ -1,58 +1,57 @@ using Google.Protobuf; -namespace AElf.Sdk.CSharp.State -{ - /// - /// Wrapper around boolean values for use in smart contract state. - /// - public class BoolState : SingletonState - { - } - - /// - /// Wrapper around 32-bit integer values for use in smart contract state. - /// - public class Int32State : SingletonState - { - } - - /// - /// Wrapper around unsigned 32-bit integer values for use in smart contract state. - /// - public class UInt32State : SingletonState - { - } - - /// - /// Wrapper around 64-bit integer values for use in smart contract state. - /// - public class Int64State : SingletonState - { - } - - /// - /// Wrapper around unsigned 64-bit integer values for use in smart contract state. - /// - public class UInt64State : SingletonState - { - } - - /// - /// Wrapper around string values for use in smart contract state. - /// - public class StringState : SingletonState - { - } - - /// - /// Wrapper around byte arrays for use in smart contract state. - /// - public class BytesState : SingletonState - { - } - - // ReSharper disable once IdentifierTypo - public class ProtobufState : SingletonState where TEntity : IMessage, new() - { - } +namespace AElf.Sdk.CSharp.State; + +/// +/// Wrapper around boolean values for use in smart contract state. +/// +public class BoolState : SingletonState +{ +} + +/// +/// Wrapper around 32-bit integer values for use in smart contract state. +/// +public class Int32State : SingletonState +{ +} + +/// +/// Wrapper around unsigned 32-bit integer values for use in smart contract state. +/// +public class UInt32State : SingletonState +{ +} + +/// +/// Wrapper around 64-bit integer values for use in smart contract state. +/// +public class Int64State : SingletonState +{ +} + +/// +/// Wrapper around unsigned 64-bit integer values for use in smart contract state. +/// +public class UInt64State : SingletonState +{ +} + +/// +/// Wrapper around string values for use in smart contract state. +/// +public class StringState : SingletonState +{ +} + +/// +/// Wrapper around byte arrays for use in smart contract state. +/// +public class BytesState : SingletonState +{ +} + +// ReSharper disable once IdentifierTypo +public class ProtobufState : SingletonState where TEntity : IMessage, new() +{ } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/StateBase.cs b/src/AElf.Sdk.CSharp/State/StateBase.cs index 32f85ceea6..84e7e810cb 100644 --- a/src/AElf.Sdk.CSharp/State/StateBase.cs +++ b/src/AElf.Sdk.CSharp/State/StateBase.cs @@ -1,48 +1,48 @@ -using AElf.Types; using AElf.Kernel.SmartContract; -namespace AElf.Sdk.CSharp.State +using AElf.Types; + +namespace AElf.Sdk.CSharp.State; + +public class StateBase { - public class StateBase - { - private StatePath _path; - private CSharpSmartContractContext _context; - internal IStateProvider Provider => _context.StateProvider; + private CSharpSmartContractContext _context; + private StatePath _path; + internal IStateProvider Provider => _context.StateProvider; - internal StatePath Path + internal StatePath Path + { + get => _path; + set { - get => _path; - set - { - _path = value; - OnPathSet(); - } + _path = value; + OnPathSet(); } + } - internal CSharpSmartContractContext Context + internal CSharpSmartContractContext Context + { + get => _context; + set { - get => _context; - set - { - _context = value; - OnContextSet(); - } + _context = value; + OnContextSet(); } + } - internal virtual void OnPathSet() - { - } + internal virtual void OnPathSet() + { + } - internal virtual void OnContextSet() - { - } + internal virtual void OnContextSet() + { + } - internal virtual void Clear() - { - } + internal virtual void Clear() + { + } - internal virtual TransactionExecutingStateSet GetChanges() - { - return new TransactionExecutingStateSet(); - } + internal virtual TransactionExecutingStateSet GetChanges() + { + return new TransactionExecutingStateSet(); } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/State/StructuredState.cs b/src/AElf.Sdk.CSharp/State/StructuredState.cs index 2687155176..6232f92e6f 100644 --- a/src/AElf.Sdk.CSharp/State/StructuredState.cs +++ b/src/AElf.Sdk.CSharp/State/StructuredState.cs @@ -4,109 +4,99 @@ using System.Reflection; using AElf.Types; -namespace AElf.Sdk.CSharp.State +namespace AElf.Sdk.CSharp.State; + +public class StructuredState : StateBase { - public class StructuredState : StateBase - { - private Dictionary _propertyInfos; + private Dictionary _propertyInfos; - //private Dictionary _states; + //private Dictionary _states; - public StructuredState() + public StructuredState() + { + DetectPropertyInfos(); + InitializeProperties(); + } + + private void DetectPropertyInfos() + { + _propertyInfos = GetType() + .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .Where(x => x.PropertyType.IsSubclassOf(typeof(StateBase))) + .ToDictionary(x => x.Name, x => x); + /*_states = this.GetType() + .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .Where(x => x.PropertyType.IsSubclassOf(typeof(StateBase))) + .ToDictionary(x => x.Name, x => + { + var method = x.GetGetMethod(); + var func = (Func) Delegate.CreateDelegate(typeof(Func), + this, + x.GetGetMethod()); + return func(); + });*/ + } + + private void InitializeProperties() + { + foreach (var kv in _propertyInfos) { - DetectPropertyInfos(); - InitializeProperties(); + var propertyInfo = kv.Value; + var type = propertyInfo.PropertyType; + var instance = Activator.CreateInstance(type); + propertyInfo.SetValue(this, instance); } + } - private void DetectPropertyInfos() + internal override void OnPathSet() + { + foreach (var kv in _propertyInfos) { - _propertyInfos = this.GetType() - .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .Where(x => x.PropertyType.IsSubclassOf(typeof(StateBase))) - .ToDictionary(x => x.Name, x => x); - /*_states = this.GetType() - .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .Where(x => x.PropertyType.IsSubclassOf(typeof(StateBase))) - .ToDictionary(x => x.Name, x => - { - var method = x.GetGetMethod(); - var func = (Func) Delegate.CreateDelegate(typeof(Func), - this, - x.GetGetMethod()); - return func(); - });*/ + var propertyInfo = kv.Value; + var path = Path.Clone(); + path.Parts.Add(kv.Key); + ((StateBase)propertyInfo.GetValue(this)).Path = path; } - private void InitializeProperties() + base.OnPathSet(); + } + + internal override void OnContextSet() + { + foreach (var kv in _propertyInfos) { - foreach (var kv in _propertyInfos) - { - var propertyInfo = kv.Value; - var type = propertyInfo.PropertyType; - var instance = Activator.CreateInstance(type); - propertyInfo.SetValue(this, instance); - } + var propertyInfo = kv.Value; + ((StateBase)propertyInfo.GetValue(this)).Context = Context; } - internal override void OnPathSet() - { - foreach (var kv in _propertyInfos) - { - var propertyInfo = kv.Value; - var path = this.Path.Clone(); - path.Parts.Add(kv.Key); - ((StateBase) propertyInfo.GetValue(this)).Path = path; - } + base.OnContextSet(); + } - base.OnPathSet(); + internal override void Clear() + { + foreach (var kv in _propertyInfos) + { + var propertyInfo = kv.Value; + ((StateBase)propertyInfo.GetValue(this)).Clear(); } + } - internal override void OnContextSet() + internal override TransactionExecutingStateSet GetChanges() + { + var stateSet = new TransactionExecutingStateSet(); + foreach (var kv in _propertyInfos) { - foreach (var kv in _propertyInfos) - { - var propertyInfo = kv.Value; - ((StateBase) propertyInfo.GetValue(this)).Context = Context; - } + var propertyInfo = kv.Value; + var propertyValue = (StateBase)propertyInfo.GetValue(this); + var changes = propertyValue.GetChanges(); + foreach (var kv1 in changes.Writes) stateSet.Writes[kv1.Key] = kv1.Value; - base.OnContextSet(); - } + foreach (var kv1 in changes.Deletes) stateSet.Deletes[kv1.Key] = kv1.Value; - internal override void Clear() - { - foreach (var kv in _propertyInfos) - { - var propertyInfo = kv.Value; - ((StateBase) propertyInfo.GetValue(this)).Clear(); - } + foreach (var kv1 in changes.Reads) stateSet.Reads[kv1.Key] = kv1.Value; } - internal override TransactionExecutingStateSet GetChanges() - { - var stateSet = new TransactionExecutingStateSet(); - foreach (var kv in _propertyInfos) - { - var propertyInfo = kv.Value; - var propertyValue = (StateBase) propertyInfo.GetValue(this); - var changes = propertyValue.GetChanges(); - foreach (var kv1 in changes.Writes) - { - stateSet.Writes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Deletes) - { - stateSet.Deletes[kv1.Key] = kv1.Value; - } - - foreach (var kv1 in changes.Reads) - { - stateSet.Reads[kv1.Key] = kv1.Value; - } - } - - return stateSet; - } + return stateSet; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/ViewAttribute.cs b/src/AElf.Sdk.CSharp/ViewAttribute.cs index 75d6b5c2be..c129375dba 100644 --- a/src/AElf.Sdk.CSharp/ViewAttribute.cs +++ b/src/AElf.Sdk.CSharp/ViewAttribute.cs @@ -1,9 +1,8 @@ using System; -namespace AElf.Sdk.CSharp +namespace AElf.Sdk.CSharp; + +[AttributeUsage(AttributeTargets.Method)] +public class ViewAttribute : Attribute { - [AttributeUsage(AttributeTargets.Method)] - public class ViewAttribute : Attribute - { - } } \ No newline at end of file diff --git a/src/AElf.Types/AElf.Types.csproj b/src/AElf.Types/AElf.Types.csproj index fed6f6a209..789898c95f 100644 --- a/src/AElf.Types/AElf.Types.csproj +++ b/src/AElf.Types/AElf.Types.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf @@ -11,7 +11,7 @@ true - + diff --git a/src/AElf.Types/AElfConstants.cs b/src/AElf.Types/AElfConstants.cs index a1ca1c7986..1d46330b17 100644 --- a/src/AElf.Types/AElfConstants.cs +++ b/src/AElf.Types/AElfConstants.cs @@ -1,9 +1,8 @@ -namespace AElf +namespace AElf; + +public static class AElfConstants { - public static class AElfConstants - { - public const long GenesisBlockHeight = 1; - public const int HashByteArrayLength = 32; - public const int AddressHashLength = 32; - } + public const long GenesisBlockHeight = 1; + public const int HashByteArrayLength = 32; + public const int AddressHashLength = 32; } \ No newline at end of file diff --git a/src/AElf.Types/Base58.cs b/src/AElf.Types/Base58.cs index f5dfc0ad79..f02afd7fce 100644 --- a/src/AElf.Types/Base58.cs +++ b/src/AElf.Types/Base58.cs @@ -1,188 +1,173 @@ -using System.Collections.Generic; using System; +using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Security.Cryptography; using Google.Protobuf; -namespace AElf +namespace AElf; + +/// +/// From https://github.com/adamcaudill/Base58Check, for NOT dotnet core version +/// Base58Check Encoding / Decoding (Bitcoin-style) +/// +/// +/// See here for more details: https://en.bitcoin.it/wiki/Base58Check_encoding +/// +public static class Base58CheckEncoding { + private const int CheckSumSize = 4; + private const string Digits = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + private static readonly HashSet DigitsHash = new(Digits.ToCharArray()); + /// - /// From https://github.com/adamcaudill/Base58Check, for NOT dotnet core version - /// Base58Check Encoding / Decoding (Bitcoin-style) + /// Encodes data with a 4-byte checksum /// - /// - /// See here for more details: https://en.bitcoin.it/wiki/Base58Check_encoding - /// - public static class Base58CheckEncoding + /// Data to be encoded + /// + public static string Encode(byte[] data) { - private const int CheckSumSize = 4; - private const string Digits = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - private static HashSet DigitsHash = new HashSet(Digits.ToCharArray()); - - /// - /// Encodes data with a 4-byte checksum - /// - /// Data to be encoded - /// - public static string Encode(byte[] data) - { - return EncodePlain(_AddCheckSum(data)); - } + return EncodePlain(_AddCheckSum(data)); + } - /// - /// Encodes data in plain Base58, without any checksum. - /// - /// The data to be encoded - /// - public static string EncodePlain(byte[] data) + /// + /// Encodes data in plain Base58, without any checksum. + /// + /// The data to be encoded + /// + public static string EncodePlain(byte[] data) + { + // Decode byte[] to BigInteger + var intData = data.Aggregate(0, (current, t) => current * 256 + t); + + // Encode BigInteger to Base58 string + var result = string.Empty; + while (intData > 0) { - // Decode byte[] to BigInteger - var intData = data.Aggregate(0, (current, t) => current * 256 + t); - - // Encode BigInteger to Base58 string - var result = string.Empty; - while (intData > 0) - { - var remainder = (int) (intData % 58); - intData /= 58; - result = Digits[remainder] + result; - } - - // Append `1` for each leading 0 byte - for (var i = 0; i < data.Length && data[i] == 0; i++) - { - result = '1' + result; - } - - return result; + var remainder = (int)(intData % 58); + intData /= 58; + result = Digits[remainder] + result; } - /// - /// Encodes data in plain Base58, without any checksum. - /// - /// The data to be encoded - /// - public static string EncodePlain(ByteString data) + // Append `1` for each leading 0 byte + for (var i = 0; i < data.Length && data[i] == 0; i++) result = '1' + result; + + return result; + } + + /// + /// Encodes data in plain Base58, without any checksum. + /// + /// The data to be encoded + /// + public static string EncodePlain(ByteString data) + { + // Decode byte[] to BigInteger + var intData = data.Aggregate(0, (current, t) => current * 256 + t); + + // Encode BigInteger to Base58 string + var result = string.Empty; + while (intData > 0) { - // Decode byte[] to BigInteger - var intData = data.Aggregate(0, (current, t) => current * 256 + t); - - // Encode BigInteger to Base58 string - var result = string.Empty; - while (intData > 0) - { - var remainder = (int) (intData % 58); - intData /= 58; - result = Digits[remainder] + result; - } - - // Append `1` for each leading 0 byte - for (var i = 0; i < data.Length && data[i] == 0; i++) - { - result = '1' + result; - } - - return result; + var remainder = (int)(intData % 58); + intData /= 58; + result = Digits[remainder] + result; } + // Append `1` for each leading 0 byte + for (var i = 0; i < data.Length && data[i] == 0; i++) result = '1' + result; - /// - /// Decodes data in Base58Check format (with 4 byte checksum) - /// - /// Data to be decoded - /// Returns decoded data if valid; throws FormatException if invalid - public static byte[] Decode(string data) - { - var dataWithCheckSum = DecodePlain(data); - var dataWithoutCheckSum = _VerifyAndRemoveCheckSum(dataWithCheckSum); + return result; + } - if (dataWithoutCheckSum == null) - { - throw new FormatException("Base58 checksum is invalid"); - } - return dataWithoutCheckSum; - } + /// + /// Decodes data in Base58Check format (with 4 byte checksum) + /// + /// Data to be decoded + /// Returns decoded data if valid; throws FormatException if invalid + public static byte[] Decode(string data) + { + var dataWithCheckSum = DecodePlain(data); + var dataWithoutCheckSum = _VerifyAndRemoveCheckSum(dataWithCheckSum); + + if (dataWithoutCheckSum == null) throw new FormatException("Base58 checksum is invalid"); - /// - /// Decodes data in plain Base58, without any checksum. - /// - /// Data to be decoded - /// Returns decoded data if valid; throws FormatException if invalid - public static byte[] DecodePlain(string data) + return dataWithoutCheckSum; + } + + /// + /// Decodes data in plain Base58, without any checksum. + /// + /// Data to be decoded + /// Returns decoded data if valid; throws FormatException if invalid + public static byte[] DecodePlain(string data) + { + // Decode Base58 string to BigInteger + BigInteger intData = 0; + for (var i = 0; i < data.Length; i++) { - // Decode Base58 string to BigInteger - BigInteger intData = 0; - for (var i = 0; i < data.Length; i++) - { - var digit = Digits.IndexOf(data[i]); //Slow - - if (digit < 0) - { - throw new FormatException($"Invalid Base58 character `{data[i]}` at position {i}"); - } - - intData = intData * 58 + digit; - } - - // Encode BigInteger to byte[] - // Leading zero bytes get encoded as leading `1` characters - var leadingZeroCount = data.TakeWhile(c => c == '1').Count(); - var leadingZeros = Enumerable.Repeat((byte) 0, leadingZeroCount); - var bytesWithoutLeadingZeros = - intData.ToByteArray() - .Reverse() // to big endian - .SkipWhile(b => b == 0); //strip sign byte - var result = leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray(); - - return result; + var digit = Digits.IndexOf(data[i]); //Slow + + if (digit < 0) throw new FormatException($"Invalid Base58 character `{data[i]}` at position {i}"); + + intData = intData * 58 + digit; } - public static bool Verify(string data) - { - for (var i = 0; i < data.Length; i++) - { - if (!DigitsHash.Contains(data[i])) - return false; - } - - var dataWithCheckSum = DecodePlain(data); - var dataWithoutCheckSum = _VerifyAndRemoveCheckSum(dataWithCheckSum); - if (dataWithoutCheckSum == null) + // Encode BigInteger to byte[] + // Leading zero bytes get encoded as leading `1` characters + var leadingZeroCount = data.TakeWhile(c => c == '1').Count(); + var leadingZeros = Enumerable.Repeat((byte)0, leadingZeroCount); + var bytesWithoutLeadingZeros = + intData.ToByteArray() + .Reverse() // to big endian + .SkipWhile(b => b == 0); //strip sign byte + var result = leadingZeros.Concat(bytesWithoutLeadingZeros).ToArray(); + + return result; + } + + public static bool Verify(string data) + { + for (var i = 0; i < data.Length; i++) + if (!DigitsHash.Contains(data[i])) return false; - return true; - } - private static byte[] _AddCheckSum(byte[] data) - { - var checkSum = _GetCheckSum(data); - var dataWithCheckSum = ByteArrayHelper.ConcatArrays(data, checkSum); + var dataWithCheckSum = DecodePlain(data); + var dataWithoutCheckSum = _VerifyAndRemoveCheckSum(dataWithCheckSum); + if (dataWithoutCheckSum == null) + return false; + return true; + } - return dataWithCheckSum; - } + private static byte[] _AddCheckSum(byte[] data) + { + var checkSum = _GetCheckSum(data); + var dataWithCheckSum = ByteArrayHelper.ConcatArrays(data, checkSum); - //Returns null if the checksum is invalid - private static byte[] _VerifyAndRemoveCheckSum(byte[] data) - { - var result = ByteArrayHelper.SubArray(data, 0, data.Length - CheckSumSize); - var givenCheckSum = ByteArrayHelper.SubArray(data, data.Length - CheckSumSize); - var correctCheckSum = _GetCheckSum(result); + return dataWithCheckSum; + } - return givenCheckSum.SequenceEqual(correctCheckSum) ? result : null; - } + //Returns null if the checksum is invalid + private static byte[] _VerifyAndRemoveCheckSum(byte[] data) + { + var result = ByteArrayHelper.SubArray(data, 0, data.Length - CheckSumSize); + var givenCheckSum = ByteArrayHelper.SubArray(data, data.Length - CheckSumSize); + var correctCheckSum = _GetCheckSum(result); + + return givenCheckSum.SequenceEqual(correctCheckSum) ? result : null; + } - private static byte[] _GetCheckSum(byte[] data) + private static byte[] _GetCheckSum(byte[] data) + { + var result = new byte[CheckSumSize]; + using (var sha256 = SHA256.Create()) { - var result = new byte[CheckSumSize]; - using (SHA256 sha256 = SHA256.Create()) - { - var hash1 = sha256.ComputeHash(data); - var hash2 = sha256.ComputeHash(hash1); - Buffer.BlockCopy(hash2, 0, result, 0, result.Length); - } - - return result; + var hash1 = sha256.ComputeHash(data); + var hash2 = sha256.ComputeHash(hash1); + Buffer.BlockCopy(hash2, 0, result, 0, result.Length); } + + return result; } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/ByteExtensions.cs b/src/AElf.Types/Extensions/ByteExtensions.cs index 010686244d..ac0eb20be0 100644 --- a/src/AElf.Types/Extensions/ByteExtensions.cs +++ b/src/AElf.Types/Extensions/ByteExtensions.cs @@ -3,126 +3,119 @@ using System.Security.Cryptography; using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class ByteExtensions { - public static class ByteExtensions + public static string ToPlainBase58(this byte[] value) { - public static string ToPlainBase58(this byte[] value) - { - return Base58CheckEncoding.EncodePlain(value); - } + return Base58CheckEncoding.EncodePlain(value); + } - public static string ToPlainBase58(this ByteString value) + public static string ToPlainBase58(this ByteString value) + { + return Base58CheckEncoding.EncodePlain(value); + } + + public static string ToHex(this byte[] bytes, bool withPrefix = false) + { + var offset = withPrefix ? 2 : 0; + var length = bytes.Length * 2 + offset; + var c = new char[length]; + + byte b; + + if (withPrefix) { - return Base58CheckEncoding.EncodePlain(value); + c[0] = '0'; + c[1] = 'x'; } - public static string ToHex(this byte[] bytes, bool withPrefix = false) + for (int bx = 0, cx = offset; bx < bytes.Length; ++bx, ++cx) { - int offset = withPrefix ? 2 : 0; - int length = bytes.Length * 2 + offset; - char[] c = new char[length]; + b = (byte)(bytes[bx] >> 4); + c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); - byte b; - - if (withPrefix) - { - c[0] = '0'; - c[1] = 'x'; - } + b = (byte)(bytes[bx] & 0x0F); + c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); + } - for (int bx = 0, cx = offset; bx < bytes.Length; ++bx, ++cx) - { - b = ((byte) (bytes[bx] >> 4)); - c[cx] = (char) (b > 9 ? b + 0x37 + 0x20 : b + 0x30); + return new string(c); + } - b = ((byte) (bytes[bx] & 0x0F)); - c[++cx] = (char) (b > 9 ? b + 0x37 + 0x20 : b + 0x30); - } + public static int ToInt32(this byte[] bytes, bool bigEndian) + { + var needReverse = !bigEndian ^ BitConverter.IsLittleEndian; + return BitConverter.ToInt32(needReverse ? bytes.Reverse().ToArray() : bytes, 0); + } - return new string(c); - } + public static long ToInt64(this byte[] bytes, bool bigEndian) + { + var needReverse = !bigEndian ^ BitConverter.IsLittleEndian; + return BitConverter.ToInt64(needReverse ? bytes.Reverse().ToArray() : bytes, 0); + } - public static int ToInt32(this byte[] bytes, bool bigEndian) - { - var needReverse = !bigEndian ^ BitConverter.IsLittleEndian; - return BitConverter.ToInt32(needReverse ? bytes.Reverse().ToArray() : bytes, 0); - } - - public static long ToInt64(this byte[] bytes, bool bigEndian) + /// + /// Calculates the hash for a byte array. + /// + /// + /// + public static byte[] ComputeHash(this byte[] bytes) + { + using (var sha256 = SHA256.Create()) { - var needReverse = !bigEndian ^ BitConverter.IsLittleEndian; - return BitConverter.ToInt64(needReverse ? bytes.Reverse().ToArray() : bytes, 0); + return sha256.ComputeHash(bytes); } + } - /// - /// Calculates the hash for a byte array. - /// - /// - /// - public static byte[] ComputeHash(this byte[] bytes) - { - using (SHA256 sha256 = SHA256.Create()) - { - return sha256.ComputeHash(bytes); - } - } + public static byte[] LeftPad(this byte[] bytes, int length) + { + if (length <= bytes.Length) + return bytes; - public static byte[] LeftPad(this byte[] bytes, int length) - { - if (length <= bytes.Length) - return bytes; + var paddedBytes = new byte[length]; + Buffer.BlockCopy(bytes, 0, paddedBytes, length - bytes.Length, bytes.Length); + return paddedBytes; + } - var paddedBytes = new byte[length]; - Buffer.BlockCopy(bytes, 0, paddedBytes, length - bytes.Length, bytes.Length); - return paddedBytes; - } + /// + /// Find subarray in the source array. + /// + /// Source array to search for needle. + /// Needle we are searching for. + /// Start index in source array. + /// Number of bytes in source array, where the needle is searched for. + /// Returns starting position of the needle if it was found or -1 otherwise. + public static int Find(this byte[] array, byte[] needle, int startIndex = 0) + { + var needleLen = needle.Length; + var sourceLength = array.Length; + int index; - /// - /// Find subarray in the source array. - /// - /// Source array to search for needle. - /// Needle we are searching for. - /// Start index in source array. - /// Number of bytes in source array, where the needle is searched for. - /// Returns starting position of the needle if it was found or -1 otherwise. - public static int Find(this byte[] array, byte[] needle, int startIndex = 0) + while (sourceLength >= needleLen) { - int needleLen = needle.Length; - var sourceLength = array.Length; - int index; - - while (sourceLength >= needleLen) - { - // find needle's starting element - index = Array.IndexOf(array, needle[0], startIndex, sourceLength - needleLen + 1); - - // if we did not find even the first element of the needls, then the search is failed - if (index == -1) - return -1; - - int i, p; - // check for needle - for (i = 0, p = index; i < needleLen; i++, p++) - { - if (array[p] != needle[i]) - { - break; - } - } - - if (i == needleLen) - { - // needle was found - return index; - } - - // continue to search for needle - sourceLength -= (index - startIndex + 1); - startIndex = index + 1; - } - - return -1; + // find needle's starting element + index = Array.IndexOf(array, needle[0], startIndex, sourceLength - needleLen + 1); + + // if we did not find even the first element of the needls, then the search is failed + if (index == -1) + return -1; + + int i, p; + // check for needle + for (i = 0, p = index; i < needleLen; i++, p++) + if (array[p] != needle[i]) + break; + + if (i == needleLen) + // needle was found + return index; + + // continue to search for needle + sourceLength -= index - startIndex + 1; + startIndex = index + 1; } + + return -1; } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/ByteStringExtensions.cs b/src/AElf.Types/Extensions/ByteStringExtensions.cs index 3951d05966..552f347085 100644 --- a/src/AElf.Types/Extensions/ByteStringExtensions.cs +++ b/src/AElf.Types/Extensions/ByteStringExtensions.cs @@ -1,38 +1,37 @@ -using Google.Protobuf; +using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class ByteStringExtensions { - public static class ByteStringExtensions + public static string ToHex(this ByteString bytes, bool withPrefix = false) { - public static string ToHex(this ByteString bytes, bool withPrefix = false) - { - int offset = withPrefix ? 2 : 0; - int length = bytes.Length * 2 + offset; - char[] c = new char[length]; - - byte b; + var offset = withPrefix ? 2 : 0; + var length = bytes.Length * 2 + offset; + var c = new char[length]; - if (withPrefix) - { - c[0] = '0'; - c[1] = 'x'; - } + byte b; - for (int bx = 0, cx = offset; bx < bytes.Length; ++bx, ++cx) - { - b = ((byte) (bytes[bx] >> 4)); - c[cx] = (char) (b > 9 ? b + 0x37 + 0x20 : b + 0x30); - - b = ((byte) (bytes[bx] & 0x0F)); - c[++cx] = (char) (b > 9 ? b + 0x37 + 0x20 : b + 0x30); - } - - return new string(c); + if (withPrefix) + { + c[0] = '0'; + c[1] = 'x'; } - public static bool IsNullOrEmpty(this ByteString byteString) + for (int bx = 0, cx = offset; bx < bytes.Length; ++bx, ++cx) { - return byteString == null || byteString.IsEmpty; + b = (byte)(bytes[bx] >> 4); + c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); + + b = (byte)(bytes[bx] & 0x0F); + c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); } + + return new string(c); + } + + public static bool IsNullOrEmpty(this ByteString byteString) + { + return byteString == null || byteString.IsEmpty; } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/HexStringExtensions.cs b/src/AElf.Types/Extensions/HexStringExtensions.cs index d75e954a39..7865dbbb63 100644 --- a/src/AElf.Types/Extensions/HexStringExtensions.cs +++ b/src/AElf.Types/Extensions/HexStringExtensions.cs @@ -1,14 +1,13 @@ using System; using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class HexStringExtensions { - public static class HexStringExtensions + [Obsolete("Use ByteStringHelper.FromHexString instead.")] + public static ByteString ToByteString(this string hexString) { - [Obsolete("Use ByteStringHelper.FromHexString instead.")] - public static ByteString ToByteString(this string hexString) - { - return ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(hexString)); - } + return ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(hexString)); } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/IMessageExtensions.cs b/src/AElf.Types/Extensions/IMessageExtensions.cs index 36597fda3f..aaa4509c5e 100644 --- a/src/AElf.Types/Extensions/IMessageExtensions.cs +++ b/src/AElf.Types/Extensions/IMessageExtensions.cs @@ -1,13 +1,12 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf +namespace AElf; + +public static class IMessageExtensions { - public static class IMessageExtensions + public static BytesValue ToBytesValue(this IMessage message) { - public static BytesValue ToBytesValue(this IMessage message) - { - return new BytesValue {Value = message.ToByteString()}; - } + return new BytesValue { Value = message.ToByteString() }; } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/MerklePathExtensions.cs b/src/AElf.Types/Extensions/MerklePathExtensions.cs index e5d3a60177..72ec34c1e2 100644 --- a/src/AElf.Types/Extensions/MerklePathExtensions.cs +++ b/src/AElf.Types/Extensions/MerklePathExtensions.cs @@ -1,15 +1,14 @@ using System.Linq; using AElf.Types; -namespace AElf +namespace AElf; + +public static class MerklePathExtensions { - public static class MerklePathExtensions + public static Hash ComputeRootWithLeafNode(this MerklePath path, Hash leaf) { - public static Hash ComputeRootWithLeafNode(this MerklePath path, Hash leaf) - { - return path.MerklePathNodes.Aggregate(leaf, (current, node) => node.IsLeftChildNode - ? HashHelper.ConcatAndCompute(node.Hash, current) - : HashHelper.ConcatAndCompute(current, node.Hash)); - } + return path.MerklePathNodes.Aggregate(leaf, (current, node) => node.IsLeftChildNode + ? HashHelper.ConcatAndCompute(node.Hash, current) + : HashHelper.ConcatAndCompute(current, node.Hash)); } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/NumericExtensions.cs b/src/AElf.Types/Extensions/NumericExtensions.cs index 270387a860..c4750004d5 100644 --- a/src/AElf.Types/Extensions/NumericExtensions.cs +++ b/src/AElf.Types/Extensions/NumericExtensions.cs @@ -1,39 +1,38 @@ using System; using System.Linq; -namespace AElf +namespace AElf; + +public static class NumericExtensions { - public static class NumericExtensions + public static byte[] ToBytes(this long n, bool bigEndian = true) { - public static byte[] ToBytes(this long n, bool bigEndian = true) - { - var bytes = BitConverter.GetBytes(n); - return GetBytesWithEndian(bytes, bigEndian); - } - - public static byte[] ToBytes(this ulong n, bool bigEndian = true) - { - var bytes = BitConverter.GetBytes(n); - return GetBytesWithEndian(bytes, bigEndian); - } + var bytes = BitConverter.GetBytes(n); + return GetBytesWithEndian(bytes, bigEndian); + } - public static byte[] ToBytes(this int n, bool bigEndian = true) - { - var bytes = BitConverter.GetBytes(n); - return GetBytesWithEndian(bytes, bigEndian); - } - - public static byte[] ToBytes(this uint n, bool bigEndian = true) - { - var bytes = BitConverter.GetBytes(n); - return GetBytesWithEndian(bytes, bigEndian); - } + public static byte[] ToBytes(this ulong n, bool bigEndian = true) + { + var bytes = BitConverter.GetBytes(n); + return GetBytesWithEndian(bytes, bigEndian); + } - private static byte[] GetBytesWithEndian(byte[] bytes, bool bigEndian) - { - if (bigEndian ^ BitConverter.IsLittleEndian) - return bytes; - return bytes.Reverse().ToArray(); - } + public static byte[] ToBytes(this int n, bool bigEndian = true) + { + var bytes = BitConverter.GetBytes(n); + return GetBytesWithEndian(bytes, bigEndian); + } + + public static byte[] ToBytes(this uint n, bool bigEndian = true) + { + var bytes = BitConverter.GetBytes(n); + return GetBytesWithEndian(bytes, bigEndian); + } + + private static byte[] GetBytesWithEndian(byte[] bytes, bool bigEndian) + { + if (bigEndian ^ BitConverter.IsLittleEndian) + return bytes; + return bytes.Reverse().ToArray(); } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/StateKeyExtensions.cs b/src/AElf.Types/Extensions/StateKeyExtensions.cs index 34db15dfa9..7cbff5b979 100644 --- a/src/AElf.Types/Extensions/StateKeyExtensions.cs +++ b/src/AElf.Types/Extensions/StateKeyExtensions.cs @@ -1,23 +1,22 @@ using System.Linq; using AElf.Types; -namespace AElf +namespace AElf; + +public static class StateKeyExtensions { - public static class StateKeyExtensions + public static string ToStateKey(this StatePath statePath, Address address) { - public static string ToStateKey(this StatePath statePath, Address address) + return new ScopedStatePath { - return new ScopedStatePath() - { - Address = address, - Path = statePath - }.ToStateKey(); - } + Address = address, + Path = statePath + }.ToStateKey(); + } - public static string ToStateKey(this ScopedStatePath scopedStatePath) - { - return string.Join("/", - new[] {scopedStatePath.Address.ToBase58()}.Concat(scopedStatePath.Path.Parts)); - } + public static string ToStateKey(this ScopedStatePath scopedStatePath) + { + return string.Join("/", + new[] { scopedStatePath.Address.ToBase58() }.Concat(scopedStatePath.Path.Parts)); } } \ No newline at end of file diff --git a/src/AElf.Types/Extensions/StringExtensions.cs b/src/AElf.Types/Extensions/StringExtensions.cs index ba8af4a018..459602c52d 100644 --- a/src/AElf.Types/Extensions/StringExtensions.cs +++ b/src/AElf.Types/Extensions/StringExtensions.cs @@ -1,13 +1,11 @@ using System.Text; -using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class StringExtensions { - public static class StringExtensions + public static byte[] GetBytes(this string value) { - public static byte[] GetBytes(this string value) - { - return Encoding.UTF8.GetBytes(value); - } + return Encoding.UTF8.GetBytes(value); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/AddressHelper.cs b/src/AElf.Types/Helper/AddressHelper.cs index 3f8d3d99c4..5269bd504c 100644 --- a/src/AElf.Types/Helper/AddressHelper.cs +++ b/src/AElf.Types/Helper/AddressHelper.cs @@ -1,12 +1,11 @@ -namespace AElf +namespace AElf; + +public static class AddressHelper { - public static class AddressHelper + public static bool VerifyFormattedAddress(string formattedAddress) { - public static bool VerifyFormattedAddress(string formattedAddress) - { - if (string.IsNullOrEmpty(formattedAddress)) - return false; - return Base58CheckEncoding.Verify(formattedAddress); - } + if (string.IsNullOrEmpty(formattedAddress)) + return false; + return Base58CheckEncoding.Verify(formattedAddress); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/BlockHelper.cs b/src/AElf.Types/Helper/BlockHelper.cs index 1495d93984..067802f38e 100644 --- a/src/AElf.Types/Helper/BlockHelper.cs +++ b/src/AElf.Types/Helper/BlockHelper.cs @@ -2,14 +2,13 @@ using AElf.Types; using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class BlockHelper { - public static class BlockHelper + public static ByteString GetRefBlockPrefix(Hash blockHash) { - public static ByteString GetRefBlockPrefix(Hash blockHash) - { - var refBlockPrefix = ByteString.CopyFrom(blockHash.Value.Take(4).ToArray()); - return refBlockPrefix; - } + var refBlockPrefix = ByteString.CopyFrom(blockHash.Value.Take(4).ToArray()); + return refBlockPrefix; } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/ByteArrayHelper.cs b/src/AElf.Types/Helper/ByteArrayHelper.cs index dec693ad9b..e6bdc73f08 100644 --- a/src/AElf.Types/Helper/ByteArrayHelper.cs +++ b/src/AElf.Types/Helper/ByteArrayHelper.cs @@ -1,62 +1,59 @@ using System; -using System.Linq; -namespace AElf +namespace AElf; + +public static class ByteArrayHelper { - public static class ByteArrayHelper + public static byte[] HexStringToByteArray(string hex) { - public static byte[] HexStringToByteArray(string hex) - { - if (hex.Length >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) - hex = hex.Substring(2); - int numberChars = hex.Length; - byte[] bytes = new byte[numberChars / 2]; + if (hex.Length >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) + hex = hex.Substring(2); + var numberChars = hex.Length; + var bytes = new byte[numberChars / 2]; - for (int i = 0; i < numberChars; i += 2) - bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + for (var i = 0; i < numberChars; i += 2) + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); - return bytes; - } + return bytes; + } - public static bool BytesEqual(this byte[] b1, byte[] b2) - { - if (b1 == b2) - return true; + public static bool BytesEqual(this byte[] b1, byte[] b2) + { + if (b1 == b2) + return true; - if (b1 == null || b2 == null) - return false; + if (b1 == null || b2 == null) + return false; - if (b1.Length != b2.Length) - return false; + if (b1.Length != b2.Length) + return false; - for (var i = 0; i < b1.Length; i++) - { - if (b1[i] != b2[i]) return false; - } + for (var i = 0; i < b1.Length; i++) + if (b1[i] != b2[i]) + return false; - return true; - } + return true; + } - public static byte[] ConcatArrays(byte[] arr1, byte[] arr2) - { - var result = new byte[arr1.Length + arr2.Length]; - Buffer.BlockCopy(arr1, 0, result, 0, arr1.Length); - Buffer.BlockCopy(arr2, 0, result, arr1.Length, arr2.Length); + public static byte[] ConcatArrays(byte[] arr1, byte[] arr2) + { + var result = new byte[arr1.Length + arr2.Length]; + Buffer.BlockCopy(arr1, 0, result, 0, arr1.Length); + Buffer.BlockCopy(arr2, 0, result, arr1.Length, arr2.Length); - return result; - } + return result; + } - public static byte[] SubArray(byte[] arr, int start, int length) - { - var result = new byte[length]; - Buffer.BlockCopy(arr, start, result, 0, length); + public static byte[] SubArray(byte[] arr, int start, int length) + { + var result = new byte[length]; + Buffer.BlockCopy(arr, start, result, 0, length); - return result; - } + return result; + } - public static byte[] SubArray(byte[] arr, int start) - { - return SubArray(arr, start, arr.Length - start); - } + public static byte[] SubArray(byte[] arr, int start) + { + return SubArray(arr, start, arr.Length - start); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/ByteStringHelper.cs b/src/AElf.Types/Helper/ByteStringHelper.cs index 1d55984f16..b323e0f371 100644 --- a/src/AElf.Types/Helper/ByteStringHelper.cs +++ b/src/AElf.Types/Helper/ByteStringHelper.cs @@ -1,30 +1,24 @@ using System; using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class ByteStringHelper { - public static class ByteStringHelper + public static int Compare(ByteString xValue, ByteString yValue) { - public static int Compare(ByteString xValue, ByteString yValue) + for (var i = 0; i < Math.Min(xValue.Length, yValue.Length); i++) { - for (var i = 0; i < Math.Min(xValue.Length, yValue.Length); i++) - { - if (xValue[i] > yValue[i]) - { - return 1; - } - - if (xValue[i] < yValue[i]) - { - return -1; - } - } + if (xValue[i] > yValue[i]) return 1; - return 0; - } - public static ByteString FromHexString(string hexString) - { - return ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(hexString)); + if (xValue[i] < yValue[i]) return -1; } + + return 0; + } + + public static ByteString FromHexString(string hexString) + { + return ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(hexString)); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/ChainHelper.cs b/src/AElf.Types/Helper/ChainHelper.cs index b9bd208c55..ac2666e290 100644 --- a/src/AElf.Types/Helper/ChainHelper.cs +++ b/src/AElf.Types/Helper/ChainHelper.cs @@ -1,43 +1,42 @@ using System; using System.Linq; -namespace AElf +namespace AElf; + +public static class ChainHelper { - public static class ChainHelper + public static int GetChainId(long serialNumber) { - public static int GetChainId(long serialNumber) - { - // For 4 base58 chars use following range (2111 ~ zzzz): - // Max: 57*58*58*58+57*58*58+57*58+57 = 11316496 (zzzz) - // Min: 1*58*58*58+0*58*58+0*58+0 = 195112 (2111) - var validNUmber = (uint) serialNumber.GetHashCode() % 11316496; - if (validNUmber < 195112) - validNUmber += 195112; - - var validNUmberBytes = validNUmber.ToBytes().Skip(1).ToArray(); - - // Use BigInteger(BigEndian) format (bytes size = 3) - Array.Resize(ref validNUmberBytes, 4); - - return validNUmberBytes.ToInt32(false); - } - - public static string ConvertChainIdToBase58(int chainId) - { - // Default chain id is 4 base58 chars, bytes size is 3 - var bytes = chainId.ToBytes(false); - Array.Resize(ref bytes, 3); - return bytes.ToPlainBase58(); - } - - public static int ConvertBase58ToChainId(string base58String) - { - // Use int type to save chain id (4 base58 chars, default is 3 bytes) - var bytes = Base58CheckEncoding.DecodePlain(base58String); - if (bytes.Length < 4) - Array.Resize(ref bytes, 4); - - return bytes.ToInt32(false); - } + // For 4 base58 chars use following range (2111 ~ zzzz): + // Max: 57*58*58*58+57*58*58+57*58+57 = 11316496 (zzzz) + // Min: 1*58*58*58+0*58*58+0*58+0 = 195112 (2111) + var validNUmber = (uint)serialNumber.GetHashCode() % 11316496; + if (validNUmber < 195112) + validNUmber += 195112; + + var validNUmberBytes = validNUmber.ToBytes().Skip(1).ToArray(); + + // Use BigInteger(BigEndian) format (bytes size = 3) + Array.Resize(ref validNUmberBytes, 4); + + return validNUmberBytes.ToInt32(false); + } + + public static string ConvertChainIdToBase58(int chainId) + { + // Default chain id is 4 base58 chars, bytes size is 3 + var bytes = chainId.ToBytes(false); + Array.Resize(ref bytes, 3); + return bytes.ToPlainBase58(); + } + + public static int ConvertBase58ToChainId(string base58String) + { + // Use int type to save chain id (4 base58 chars, default is 3 bytes) + var bytes = Base58CheckEncoding.DecodePlain(base58String); + if (bytes.Length < 4) + Array.Resize(ref bytes, 4); + + return bytes.ToInt32(false); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/HashHelper.cs b/src/AElf.Types/Helper/HashHelper.cs index f649e54fc3..3f830075ce 100644 --- a/src/AElf.Types/Helper/HashHelper.cs +++ b/src/AElf.Types/Helper/HashHelper.cs @@ -1,89 +1,85 @@ -using AElf.Types; using System.Text; +using AElf.Types; using Google.Protobuf; -namespace AElf +namespace AElf; + +public class HashHelper { - public class HashHelper + /// + /// Computes hash from a byte array. + /// + /// + /// + public static Hash ComputeFrom(byte[] bytes) + { + return Hash.LoadFromByteArray(bytes.ComputeHash()); + } + + /// + /// Computes hash from a string encoded in UTF8. + /// + /// + /// + public static Hash ComputeFrom(string str) + { + return ComputeFrom(Encoding.UTF8.GetBytes(str)); + } + + /// + /// Computes hash from int32 value. + /// + /// + /// + public static Hash ComputeFrom(int intValue) + { + return ComputeFrom(intValue.ToBytes(false)); + } + + /// + /// Computes hash from int64 value. + /// + /// + /// + public static Hash ComputeFrom(long intValue) { - /// - /// Computes hash from a byte array. - /// - /// - /// - public static Hash ComputeFrom(byte[] bytes) - { - return Hash.LoadFromByteArray(bytes.ComputeHash()); - } + return ComputeFrom(intValue.ToBytes(false)); + } - /// - /// Computes hash from a string encoded in UTF8. - /// - /// - /// - public static Hash ComputeFrom(string str) - { - return ComputeFrom(Encoding.UTF8.GetBytes(str)); - } + /// + /// Gets the hash from a Protobuf Message. Its serialized byte array is used for hash calculation. + /// + /// + /// + public static Hash ComputeFrom(IMessage message) + { + return ComputeFrom(message.ToByteArray()); + } - /// - /// Computes hash from int32 value. - /// - /// - /// - public static Hash ComputeFrom(int intValue) - { - return ComputeFrom(intValue.ToBytes(false)); - } - - /// - /// Computes hash from int64 value. - /// - /// - /// - public static Hash ComputeFrom(long intValue) - { - return ComputeFrom(intValue.ToBytes(false)); - } + /// + /// Computes a new hash from two input hashes with bitwise xor operation. + /// + /// + /// + /// + public static Hash XorAndCompute(Hash h1, Hash h2) + { + var newBytes = new byte[AElfConstants.HashByteArrayLength]; + for (var i = 0; i < newBytes.Length; i++) newBytes[i] = (byte)(h1.Value[i] ^ h2.Value[i]); - /// - /// Gets the hash from a Protobuf Message. Its serialized byte array is used for hash calculation. - /// - /// - /// - public static Hash ComputeFrom(IMessage message) - { - return ComputeFrom(message.ToByteArray()); - } - - /// - /// Computes a new hash from two input hashes with bitwise xor operation. - /// - /// - /// - /// - public static Hash XorAndCompute(Hash h1, Hash h2) - { - var newBytes = new byte[AElfConstants.HashByteArrayLength]; - for (var i = 0; i < newBytes.Length; i++) - { - newBytes[i] = (byte) (h1.Value[i] ^ h2.Value[i]); - } + return ComputeFrom(newBytes); + } - return ComputeFrom(newBytes); - } + public static Hash ConcatAndCompute(Hash hash1, Hash hash2) + { + var bytes = ByteArrayHelper.ConcatArrays(hash1.ToByteArray(), hash2.ToByteArray()); + return ComputeFrom(bytes); + } - public static Hash ConcatAndCompute(Hash hash1, Hash hash2) - { - var bytes = ByteArrayHelper.ConcatArrays(hash1.ToByteArray(), hash2.ToByteArray()); - return ComputeFrom(bytes); - } - - public static Hash ConcatAndCompute(Hash hash1, Hash hash2, Hash hash3) - { - var bytes = ByteArrayHelper.ConcatArrays( - ByteArrayHelper.ConcatArrays(hash1.ToByteArray(), hash2.ToByteArray()), hash3.ToByteArray()); - return ComputeFrom(bytes); - } + public static Hash ConcatAndCompute(Hash hash1, Hash hash2, Hash hash3) + { + var bytes = ByteArrayHelper.ConcatArrays( + ByteArrayHelper.ConcatArrays(hash1.ToByteArray(), hash2.ToByteArray()), hash3.ToByteArray()); + return ComputeFrom(bytes); } } \ No newline at end of file diff --git a/src/AElf.Types/Helper/SerializationHelper.cs b/src/AElf.Types/Helper/SerializationHelper.cs index 89274ff054..3ded44e6b0 100644 --- a/src/AElf.Types/Helper/SerializationHelper.cs +++ b/src/AElf.Types/Helper/SerializationHelper.cs @@ -4,137 +4,111 @@ using System.Text; using Google.Protobuf; -namespace AElf +namespace AElf; + +public static class SerializationHelper { - public static class SerializationHelper + private static readonly Dictionary> _primitiveWriters = + new() + { + { typeof(bool), (stream, value) => stream.WriteBool((bool)value) }, + { typeof(int), (stream, value) => stream.WriteSInt32((int)value) }, + { typeof(uint), (stream, value) => stream.WriteUInt32((uint)value) }, + { typeof(long), (stream, value) => stream.WriteSInt64((long)value) }, + { typeof(ulong), (stream, value) => stream.WriteUInt64((ulong)value) }, + { typeof(byte[]), (stream, value) => stream.WriteBytes(ByteString.CopyFrom((byte[])value)) } + }; + + private static readonly Dictionary> _primitiveReaders = + new() + { + { typeof(bool), stream => stream.ReadBool() }, + { typeof(int), stream => stream.ReadSInt32() }, + { typeof(uint), stream => stream.ReadUInt32() }, + { typeof(long), stream => stream.ReadSInt64() }, + { typeof(ulong), stream => stream.ReadUInt64() }, + { typeof(byte[]), stream => stream.ReadBytes().ToByteArray() } + }; + + private static Func GetPrimitiveSerializer(Type type) { - private static readonly Dictionary> _primitiveWriters = - new Dictionary>() - { - {typeof(bool), (stream, value) => stream.WriteBool((bool) value)}, - {typeof(int), (stream, value) => stream.WriteSInt32((int) value)}, - {typeof(uint), (stream, value) => stream.WriteUInt32((uint) value)}, - {typeof(long), (stream, value) => stream.WriteSInt64((long) value)}, - {typeof(ulong), (stream, value) => stream.WriteUInt64((ulong) value)}, - {typeof(byte[]), (stream, value) => stream.WriteBytes(ByteString.CopyFrom((byte[]) value))}, - }; - - private static readonly Dictionary> _primitiveReaders = - new Dictionary>() + if (_primitiveWriters.TryGetValue(type, out var writer)) + return value => { - {typeof(bool), stream => stream.ReadBool()}, - {typeof(int), stream => stream.ReadSInt32()}, - {typeof(uint), stream => stream.ReadUInt32()}, - {typeof(long), stream => stream.ReadSInt64()}, - {typeof(ulong), stream => stream.ReadUInt64()}, - {typeof(byte[]), stream => stream.ReadBytes().ToByteArray()} + using (var mm = new MemoryStream()) + using (var cos = new CodedOutputStream(mm)) + { + writer(cos, value); + cos.Flush(); + mm.Position = 0; + return mm.ToArray(); + } }; - private static Func GetPrimitiveSerializer(Type type) - { - if (_primitiveWriters.TryGetValue(type, out var writer)) - { - return value => - { - using (var mm = new MemoryStream()) - using (var cos = new CodedOutputStream(mm)) - { - writer(cos, value); - cos.Flush(); - mm.Position = 0; - return mm.ToArray(); - } - }; - } - - return null; - } + return null; + } - private static Func GetPrimitiveDeserializer(Type type) - { - if (_primitiveReaders.TryGetValue(type, out var reader)) + private static Func GetPrimitiveDeserializer(Type type) + { + if (_primitiveReaders.TryGetValue(type, out var reader)) + return bytes => { - return bytes => + using (var cis = new CodedInputStream(bytes)) { - using (var cis = new CodedInputStream(bytes)) - { - return reader(cis); - } - }; - } - - return null; - } + return reader(cis); + } + }; - //Done: make a unit test to test Serialize / Deserialize different types such as int,string,long,Block,Hash.... - public static byte[] Serialize(object value) - { - if (value == null) - { - return null; - } + return null; + } - var type = value.GetType(); - var primitiveSerializer = GetPrimitiveSerializer(type); - if (primitiveSerializer != null) - { - return primitiveSerializer(value); - } + //Done: make a unit test to test Serialize / Deserialize different types such as int,string,long,Block,Hash.... + public static byte[] Serialize(object value) + { + if (value == null) return null; - if (type == typeof(string)) - { - return Encoding.UTF8.GetBytes((string) value); - } + var type = value.GetType(); + var primitiveSerializer = GetPrimitiveSerializer(type); + if (primitiveSerializer != null) return primitiveSerializer(value); - if (type.IsEnum) - { - return Serialize((int) value); - } + if (type == typeof(string)) return Encoding.UTF8.GetBytes((string)value); - if (typeof(IMessage).IsAssignableFrom(type)) - { - var v = (IMessage) value; - return v.ToByteArray(); - } + if (type.IsEnum) return Serialize((int)value); - throw new InvalidOperationException($"Invalid type {type}."); + if (typeof(IMessage).IsAssignableFrom(type)) + { + var v = (IMessage)value; + return v.ToByteArray(); } - public static T Deserialize(byte[] bytes) - { - if (bytes == null) - return default; + throw new InvalidOperationException($"Invalid type {type}."); + } - var type = typeof(T); - var primitiveDeserializer = GetPrimitiveDeserializer(type); - if (primitiveDeserializer != null) - { - if (bytes.Length > 0) - { - return (T) primitiveDeserializer(bytes); - } + public static T Deserialize(byte[] bytes) + { + if (bytes == null) + return default; - return default; - } + var type = typeof(T); + var primitiveDeserializer = GetPrimitiveDeserializer(type); + if (primitiveDeserializer != null) + { + if (bytes.Length > 0) return (T)primitiveDeserializer(bytes); - if (type == typeof(string)) - { - return (T) (object) Encoding.UTF8.GetString(bytes); - } + return default; + } - if (type.IsEnum) - { - return (T) (object) Deserialize(bytes); - } + if (type == typeof(string)) return (T)(object)Encoding.UTF8.GetString(bytes); - if (typeof(IMessage).IsAssignableFrom(type)) - { - var instance = (IMessage) Activator.CreateInstance(type); - instance.MergeFrom(bytes); - return (T) instance; - } + if (type.IsEnum) return (T)(object)Deserialize(bytes); - throw new InvalidOperationException($"Invalid type {type}."); + if (typeof(IMessage).IsAssignableFrom(type)) + { + var instance = (IMessage)Activator.CreateInstance(type); + instance.MergeFrom(bytes); + return (T)instance; } + + throw new InvalidOperationException($"Invalid type {type}."); } } \ No newline at end of file diff --git a/src/AElf.Types/IBlockBase.cs b/src/AElf.Types/IBlockBase.cs index 5605935c79..c10b81678e 100644 --- a/src/AElf.Types/IBlockBase.cs +++ b/src/AElf.Types/IBlockBase.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using AElf.Types; -namespace AElf +namespace AElf; + +public interface IBlockBase : IHashProvider { - public interface IBlockBase : IHashProvider - { - IEnumerable TransactionIds { get; } - } + IEnumerable TransactionIds { get; } } \ No newline at end of file diff --git a/src/AElf.Types/IHashProvider.cs b/src/AElf.Types/IHashProvider.cs index 02cf4640db..28f6e34690 100644 --- a/src/AElf.Types/IHashProvider.cs +++ b/src/AElf.Types/IHashProvider.cs @@ -1,9 +1,8 @@ using AElf.Types; -namespace AElf +namespace AElf; + +public interface IHashProvider { - public interface IHashProvider - { - Hash GetHash(); - } + Hash GetHash(); } \ No newline at end of file diff --git a/src/AElf.Types/ISmartContract.cs b/src/AElf.Types/ISmartContract.cs index 91b135941f..ec5faa9ea7 100644 --- a/src/AElf.Types/ISmartContract.cs +++ b/src/AElf.Types/ISmartContract.cs @@ -1,6 +1,5 @@ -namespace AElf +namespace AElf; + +public interface ISmartContract { - public interface ISmartContract - { - } } \ No newline at end of file diff --git a/src/AElf.Types/Protobuf/FileDescriptorExtensions.cs b/src/AElf.Types/Protobuf/FileDescriptorExtensions.cs index de3f731b3e..5de747a13a 100644 --- a/src/AElf.Types/Protobuf/FileDescriptorExtensions.cs +++ b/src/AElf.Types/Protobuf/FileDescriptorExtensions.cs @@ -1,17 +1,13 @@ using Google.Protobuf.Reflection; -namespace AElf +namespace AElf; + +public static class FileDescriptorExtensions { - public static class FileDescriptorExtensions + public static string GetIdentity(this FileDescriptor descriptor) { - public static string GetIdentity(this FileDescriptor descriptor) - { - if (descriptor.CustomOptions.TryGetString(500001, out var id)) - { - return id; - } + if (descriptor.CustomOptions.TryGetString(500001, out var id)) return id; - return ""; - } + return ""; } } \ No newline at end of file diff --git a/src/AElf.Types/Types/Address.cs b/src/AElf.Types/Types/Address.cs index f04bd059fd..a54df92259 100644 --- a/src/AElf.Types/Types/Address.cs +++ b/src/AElf.Types/Types/Address.cs @@ -1,169 +1,156 @@ using System; using Google.Protobuf; -namespace AElf.Types +namespace AElf.Types; + +public partial class Address : ICustomDiagnosticMessage, IComparable
{ - public partial class Address : ICustomDiagnosticMessage, IComparable
+ private string _formattedAddress; + + // Make private to avoid confusion + private Address(byte[] bytes) { - /// - /// Used to override IMessage's default string representation. - /// - /// - public string ToDiagnosticString() - { - return $@"""{ToBase58()}"""; - } + if (bytes.Length != AElfConstants.AddressHashLength) + throw new ArgumentException("Invalid bytes.", nameof(bytes)); - // Make private to avoid confusion - private Address(byte[] bytes) - { - if (bytes.Length != AElfConstants.AddressHashLength) - throw new ArgumentException("Invalid bytes.", nameof(bytes)); + Value = ByteString.CopyFrom(bytes); + } - Value = ByteString.CopyFrom(bytes); - } + public int CompareTo(Address that) + { + if (that == null) throw new InvalidOperationException("Cannot compare address when address is null."); - // TODO: It should be an address generation method of KeyPair, instead of Address.FromPublicKey - public static Address FromPublicKey(byte[] bytes) - { - var hash = bytes.ComputeHash().ComputeHash(); - return new Address(hash); - } - - /// - /// Loads the content value from 32-byte long byte array. - /// - /// - /// - /// - public static Address FromBytes(byte[] bytes) - { - if (bytes.Length != AElfConstants.AddressHashLength) - throw new ArgumentException("Invalid bytes.", nameof(bytes)); - - return new Address - { - Value = ByteString.CopyFrom(bytes) - }; - } - - /// - /// Dumps the content value to byte array. - /// - /// - public byte[] ToByteArray() - { - return Value.ToByteArray(); - } - - /// - /// Construct address from base58 encoded string. - /// - /// - /// - public static Address FromBase58(string inputStr) - { - return FromBytes(Base58CheckEncoding.Decode(inputStr)); - } - - /// - /// Converts address into base58 representation. - /// - /// - /// - public string ToBase58() - { - if (_formattedAddress != null) - return _formattedAddress; + return CompareAddress(this, that); + } - if (Value.Length != AElfConstants.AddressHashLength) - throw new ArgumentException("Invalid address", nameof(Value)); + /// + /// Used to override IMessage's default string representation. + /// + /// + public string ToDiagnosticString() + { + return $@"""{ToBase58()}"""; + } - var pubKeyHash = Base58CheckEncoding.Encode(Value.ToByteArray()); - return _formattedAddress = pubKeyHash; - } - - public int CompareTo(Address that) - { - if (that == null) - { - throw new InvalidOperationException("Cannot compare address when address is null."); - } + // TODO: It should be an address generation method of KeyPair, instead of Address.FromPublicKey + public static Address FromPublicKey(byte[] bytes) + { + var hash = bytes.ComputeHash().ComputeHash(); + return new Address(hash); + } - return CompareAddress(this, that); - } + /// + /// Loads the content value from 32-byte long byte array. + /// + /// + /// + /// + public static Address FromBytes(byte[] bytes) + { + if (bytes.Length != AElfConstants.AddressHashLength) + throw new ArgumentException("Invalid bytes.", nameof(bytes)); - public static bool operator ==(Address address1, Address address2) + return new Address { - return address1?.Equals(address2) ?? ReferenceEquals(address2, null); - } + Value = ByteString.CopyFrom(bytes) + }; + } - public static bool operator !=(Address address1, Address address2) - { - return !(address1 == address2); - } + /// + /// Dumps the content value to byte array. + /// + /// + public byte[] ToByteArray() + { + return Value.ToByteArray(); + } - public static bool operator <(Address address1, Address address2) - { - return CompareAddress(address1, address2) < 0; - } + /// + /// Construct address from base58 encoded string. + /// + /// + /// + public static Address FromBase58(string inputStr) + { + return FromBytes(Base58CheckEncoding.Decode(inputStr)); + } - public static bool operator >(Address address1, Address address2) - { - return CompareAddress(address1, address2) > 0; - } + /// + /// Converts address into base58 representation. + /// + /// + /// + public string ToBase58() + { + if (_formattedAddress != null) + return _formattedAddress; - private static int CompareAddress(Address address1, Address address2) - { - if (address1 != null) - { - return address2 == null ? 1 : ByteStringHelper.Compare(address1.Value, address2.Value); - } + if (Value.Length != AElfConstants.AddressHashLength) + throw new ArgumentException("Invalid address", nameof(Value)); - if (address2 == null) - { - return 0; - } + var pubKeyHash = Base58CheckEncoding.Encode(Value.ToByteArray()); + return _formattedAddress = pubKeyHash; + } - return -1; - } + public static bool operator ==(Address address1, Address address2) + { + return address1?.Equals(address2) ?? ReferenceEquals(address2, null); + } - private string _formattedAddress; + public static bool operator !=(Address address1, Address address2) + { + return !(address1 == address2); } - public class ChainAddress + public static bool operator <(Address address1, Address address2) { - public Address Address { get; } - public int ChainId { get; } + return CompareAddress(address1, address2) < 0; + } - public ChainAddress(Address address, int chainId) - { - Address = address; - ChainId = chainId; - } + public static bool operator >(Address address1, Address address2) + { + return CompareAddress(address1, address2) > 0; + } - public static ChainAddress Parse(string chainAddressString, string symbol) - { - var arr = chainAddressString.Split('_'); - if (arr[0] != symbol) - { - throw new ArgumentException("invalid chain address", nameof(chainAddressString)); - } + private static int CompareAddress(Address address1, Address address2) + { + if (address1 != null) return address2 == null ? 1 : ByteStringHelper.Compare(address1.Value, address2.Value); - var address = Address.FromBase58(arr[1]); - var chainId = Base58CheckEncoding.Decode(arr[2]).ToInt32(false); + if (address2 == null) return 0; - return new ChainAddress(address, chainId); - } + return -1; + } +} - private string _formatted; +public class ChainAddress +{ + private string _formatted; - public string GetFormatted(string addressPrefix, int chainId) - { - if (_formatted != null) return _formatted; - var addressSuffix = Base58CheckEncoding.Encode(chainId.ToBytes(false)); - _formatted = $"{addressPrefix}_{Address.ToBase58()}_{addressSuffix}"; - return _formatted; - } + public ChainAddress(Address address, int chainId) + { + Address = address; + ChainId = chainId; + } + + public Address Address { get; } + public int ChainId { get; } + + public static ChainAddress Parse(string chainAddressString, string symbol) + { + var arr = chainAddressString.Split('_'); + if (arr[0] != symbol) throw new ArgumentException("invalid chain address", nameof(chainAddressString)); + + var address = Address.FromBase58(arr[1]); + var chainId = Base58CheckEncoding.Decode(arr[2]).ToInt32(false); + + return new ChainAddress(address, chainId); + } + + public string GetFormatted(string addressPrefix, int chainId) + { + if (_formatted != null) return _formatted; + var addressSuffix = Base58CheckEncoding.Encode(chainId.ToBytes(false)); + _formatted = $"{addressPrefix}_{Address.ToBase58()}_{addressSuffix}"; + return _formatted; } } \ No newline at end of file diff --git a/src/AElf.Types/Types/BigIntValue.cs b/src/AElf.Types/Types/BigIntValue.cs index 06e4edffd5..0a7423f2d4 100644 --- a/src/AElf.Types/Types/BigIntValue.cs +++ b/src/AElf.Types/Types/BigIntValue.cs @@ -3,166 +3,149 @@ using System.Numerics; using Google.Protobuf.WellKnownTypes; -namespace AElf.Types +namespace AElf.Types; + +public partial class BigIntValue : IComparable, IComparable { - public partial class BigIntValue : IComparable, IComparable + public int CompareTo(object obj) { - public static implicit operator BigIntValue(string str) - { - if (str.All(c => '0' <= c || c <= '9' || c == '_' || c == '-')) - { - if (str.Contains('-')) - { - if (!str.StartsWith("-") || str.Count(c => c == '-') > 1) - { - throw new ArgumentException("Invalid big integer string."); - } - } - - str = str.Replace("_", string.Empty); - return new BigIntValue - { - Value = str - }; - } - - throw new ArgumentException("Invalid big integer string."); - } + if (!(obj is BigIntValue bigInt)) throw new InvalidOperationException(); - public static implicit operator BigIntValue(ushort value) - { - return new BigIntValue - { - Value = value.ToString() - }; - } + return CompareTo(bigInt); + } - public static implicit operator BigIntValue(short value) - { - return new BigIntValue - { - Value = value.ToString() - }; - } + public int CompareTo(BigIntValue other) + { + if (LessThan(this, other)) return -1; - public static implicit operator BigIntValue(uint value) - { - return new BigIntValue - { - Value = value.ToString() - }; - } + if (Value == other.Value) return 0; - public static implicit operator BigIntValue(int value) - { - return new BigIntValue - { - Value = value.ToString() - }; - } + return 1; + } - public static implicit operator BigIntValue(ulong value) + public static implicit operator BigIntValue(string str) + { + if (str.All(c => '0' <= c || c <= '9' || c == '_' || c == '-')) { - return new BigIntValue - { - Value = value.ToString() - }; - } + if (str.Contains('-')) + if (!str.StartsWith("-") || str.Count(c => c == '-') > 1) + throw new ArgumentException("Invalid big integer string."); - public static implicit operator BigIntValue(long value) - { + str = str.Replace("_", string.Empty); return new BigIntValue { - Value = value.ToString() + Value = str }; } - public static implicit operator BigIntValue(Int32Value value) - { - return new BigIntValue - { - Value = value.Value.ToString() - }; - } + throw new ArgumentException("Invalid big integer string."); + } - public static implicit operator BigIntValue(Int64Value value) + public static implicit operator BigIntValue(ushort value) + { + return new BigIntValue { - return new BigIntValue - { - Value = value.Value.ToString() - }; - } + Value = value.ToString() + }; + } - public static implicit operator BigInteger(BigIntValue value) + public static implicit operator BigIntValue(short value) + { + return new BigIntValue { - return ConvertStringToBigInteger(value.Value); - } + Value = value.ToString() + }; + } - private static BigInteger ConvertStringToBigInteger(string str) + public static implicit operator BigIntValue(uint value) + { + return new BigIntValue { - str = str.Replace("_", string.Empty); - if (BigInteger.TryParse(str, out var bigInteger)) - { - return bigInteger; - } - - throw new ArgumentException("Incorrect arguments."); - } + Value = value.ToString() + }; + } - #region < <= > >= + public static implicit operator BigIntValue(int value) + { + return new BigIntValue + { + Value = value.ToString() + }; + } - public static bool operator <(in BigIntValue a, in BigIntValue b) + public static implicit operator BigIntValue(ulong value) + { + return new BigIntValue { - return LessThan(in a, in b); - } + Value = value.ToString() + }; + } - public static bool operator >(in BigIntValue a, in BigIntValue b) + public static implicit operator BigIntValue(long value) + { + return new BigIntValue { - return LessThan(in b, in a); - } + Value = value.ToString() + }; + } - public static bool operator >=(in BigIntValue a, in BigIntValue b) + public static implicit operator BigIntValue(Int32Value value) + { + return new BigIntValue { - return !LessThan(in a, in b); - } + Value = value.Value.ToString() + }; + } - public static bool operator <=(in BigIntValue a, in BigIntValue b) + public static implicit operator BigIntValue(Int64Value value) + { + return new BigIntValue { - return !LessThan(in b, in a); - } + Value = value.Value.ToString() + }; + } - #endregion + public static implicit operator BigInteger(BigIntValue value) + { + return ConvertStringToBigInteger(value.Value); + } - public int CompareTo(object obj) - { - if (!(obj is BigIntValue bigInt)) - { - throw new InvalidOperationException(); - } + private static BigInteger ConvertStringToBigInteger(string str) + { + str = str.Replace("_", string.Empty); + if (BigInteger.TryParse(str, out var bigInteger)) return bigInteger; - return CompareTo(bigInt); - } + throw new ArgumentException("Incorrect arguments."); + } - public int CompareTo(BigIntValue other) - { - if (LessThan(this, other)) - { - return -1; - } + private static bool LessThan(in BigIntValue a, in BigIntValue b) + { + var aBigInt = ConvertStringToBigInteger(a.Value); + var bBigInt = ConvertStringToBigInteger(b.Value); + return aBigInt < bBigInt; + } - if (Value == other.Value) - { - return 0; - } + #region < <= > >= - return 1; - } + public static bool operator <(in BigIntValue a, in BigIntValue b) + { + return LessThan(in a, in b); + } - private static bool LessThan(in BigIntValue a, in BigIntValue b) - { - var aBigInt = ConvertStringToBigInteger(a.Value); - var bBigInt = ConvertStringToBigInteger(b.Value); - return aBigInt < bBigInt; - } + public static bool operator >(in BigIntValue a, in BigIntValue b) + { + return LessThan(in b, in a); } + + public static bool operator >=(in BigIntValue a, in BigIntValue b) + { + return !LessThan(in a, in b); + } + + public static bool operator <=(in BigIntValue a, in BigIntValue b) + { + return !LessThan(in b, in a); + } + + #endregion } \ No newline at end of file diff --git a/src/AElf.Types/Types/BinaryMerkleTree.cs b/src/AElf.Types/Types/BinaryMerkleTree.cs index 2a171c22bc..664566c6be 100644 --- a/src/AElf.Types/Types/BinaryMerkleTree.cs +++ b/src/AElf.Types/Types/BinaryMerkleTree.cs @@ -2,103 +2,99 @@ using System.Collections.Generic; using System.Linq; -namespace AElf.Types +namespace AElf.Types; + +public partial class BinaryMerkleTree { - public partial class BinaryMerkleTree + public static BinaryMerkleTree FromLeafNodes(IEnumerable leafNodes) { - public static BinaryMerkleTree FromLeafNodes(IEnumerable leafNodes) - { - var binaryMerkleTree = new BinaryMerkleTree(); - binaryMerkleTree.Nodes.AddRange(leafNodes); - binaryMerkleTree.LeafCount = binaryMerkleTree.Nodes.Count; - GenerateBinaryMerkleTreeNodesWithLeafNodes(binaryMerkleTree.Nodes); - binaryMerkleTree.Root = binaryMerkleTree.Nodes.Any() ? binaryMerkleTree.Nodes.Last() : Hash.Empty; - return binaryMerkleTree; - } + var binaryMerkleTree = new BinaryMerkleTree(); + binaryMerkleTree.Nodes.AddRange(leafNodes); + binaryMerkleTree.LeafCount = binaryMerkleTree.Nodes.Count; + GenerateBinaryMerkleTreeNodesWithLeafNodes(binaryMerkleTree.Nodes); + binaryMerkleTree.Root = binaryMerkleTree.Nodes.Any() ? binaryMerkleTree.Nodes.Last() : Hash.Empty; + return binaryMerkleTree; + } + + /// + /// Calculate merkle tree root from leaf node list. + /// + /// + /// For leave {0,1,2,3,4}, the tree should be like + /// 12 + /// 10 ------ 11 + /// 6 -- 7 8 -- 9 + /// 0-1 2-3 4-5 + /// in which {5,9} are copied from {4,8}, and {6,7,8,10,11,12} are calculated. + /// [12] is merkle tree root. + /// + private static void GenerateBinaryMerkleTreeNodesWithLeafNodes(IList leafNodes) + { + if (!leafNodes.Any()) return; - /// - /// Calculate merkle tree root from leaf node list. - /// - /// - /// For leave {0,1,2,3,4}, the tree should be like - /// 12 - /// 10 ------ 11 - /// 6 -- 7 8 -- 9 - /// 0-1 2-3 4-5 - /// in which {5,9} are copied from {4,8}, and {6,7,8,10,11,12} are calculated. - /// [12] is merkle tree root. - /// - private static void GenerateBinaryMerkleTreeNodesWithLeafNodes(IList leafNodes) + if (leafNodes.Count % 2 == 1) + leafNodes.Add(leafNodes.Last()); + var nodeToAdd = leafNodes.Count / 2; + var newAdded = 0; + var i = 0; + while (i < leafNodes.Count - 1) { - if (!leafNodes.Any()) - { - return; - } + var left = leafNodes[i++]; + var right = leafNodes[i++]; + leafNodes.Add(HashHelper.ConcatAndCompute(left, right)); + if (++newAdded != nodeToAdd) + continue; - if (leafNodes.Count % 2 == 1) - leafNodes.Add(leafNodes.Last()); - var nodeToAdd = leafNodes.Count / 2; - var newAdded = 0; - var i = 0; - while (i < leafNodes.Count - 1) + // complete this row + if (nodeToAdd % 2 == 1 && nodeToAdd != 1) { - var left = leafNodes[i++]; - var right = leafNodes[i++]; - leafNodes.Add(HashHelper.ConcatAndCompute(left, right)); - if (++newAdded != nodeToAdd) - continue; - - // complete this row - if (nodeToAdd % 2 == 1 && nodeToAdd != 1) - { - nodeToAdd++; - leafNodes.Add(leafNodes.Last()); - } - - // start a new row - nodeToAdd /= 2; - newAdded = 0; + nodeToAdd++; + leafNodes.Add(leafNodes.Last()); } + + // start a new row + nodeToAdd /= 2; + newAdded = 0; } + } - public MerklePath GenerateMerklePath(int index) + public MerklePath GenerateMerklePath(int index) + { + if (Root == null || index >= LeafCount) + throw new InvalidOperationException("Cannot generate merkle path from incomplete binary merkle tree."); + var path = new MerklePath(); + var indexOfFirstNodeInRow = 0; + var nodeCountInRow = LeafCount; + while (index < Nodes.Count - 1) { - if (Root == null || index >= LeafCount) - throw new InvalidOperationException("Cannot generate merkle path from incomplete binary merkle tree."); - MerklePath path = new MerklePath(); - int indexOfFirstNodeInRow = 0; - int nodeCountInRow = LeafCount; - while (index < Nodes.Count - 1) + Hash neighbor; + bool isLeftNeighbor; + if (index % 2 == 0) { - Hash neighbor; - bool isLeftNeighbor; - if (index % 2 == 0) - { - // add right neighbor node - neighbor = Nodes[index + 1]; - isLeftNeighbor = false; - } - else - { - // add left neighbor node - neighbor = Nodes[index - 1]; - isLeftNeighbor = true; - } - - path.MerklePathNodes.Add(new MerklePathNode - { - Hash = Hash.LoadFromByteArray(neighbor.ToByteArray()), - IsLeftChildNode = isLeftNeighbor - }); - - nodeCountInRow = nodeCountInRow % 2 == 0 ? nodeCountInRow : nodeCountInRow + 1; - int shift = (index - indexOfFirstNodeInRow) / 2; - indexOfFirstNodeInRow += nodeCountInRow; - index = indexOfFirstNodeInRow + shift; - nodeCountInRow /= 2; + // add right neighbor node + neighbor = Nodes[index + 1]; + isLeftNeighbor = false; + } + else + { + // add left neighbor node + neighbor = Nodes[index - 1]; + isLeftNeighbor = true; } - return path; + path.MerklePathNodes.Add(new MerklePathNode + { + Hash = Hash.LoadFromByteArray(neighbor.ToByteArray()), + IsLeftChildNode = isLeftNeighbor + }); + + nodeCountInRow = nodeCountInRow % 2 == 0 ? nodeCountInRow : nodeCountInRow + 1; + var shift = (index - indexOfFirstNodeInRow) / 2; + indexOfFirstNodeInRow += nodeCountInRow; + index = indexOfFirstNodeInRow + shift; + nodeCountInRow /= 2; } + + return path; } } \ No newline at end of file diff --git a/src/AElf.Types/Types/Hash.cs b/src/AElf.Types/Types/Hash.cs index 21ebf917de..04502710ea 100644 --- a/src/AElf.Types/Types/Hash.cs +++ b/src/AElf.Types/Types/Hash.cs @@ -5,140 +5,133 @@ using Google.Protobuf; // ReSharper disable once CheckNamespace -namespace AElf.Types +namespace AElf.Types; + +public partial class Hash : ICustomDiagnosticMessage, IComparable, IEnumerable { - public partial class Hash : ICustomDiagnosticMessage, IComparable, IEnumerable + public static readonly Hash Empty = LoadFromByteArray(Enumerable.Range(0, AElfConstants.HashByteArrayLength) + .Select(x => byte.MinValue).ToArray()); + + public int CompareTo(Hash that) { - public static readonly Hash Empty = LoadFromByteArray(Enumerable.Range(0, AElfConstants.HashByteArrayLength) - .Select(x => byte.MinValue).ToArray()); - - /// - /// Used to override IMessage's default string representation. - /// - /// - public string ToDiagnosticString() - { - return $@"""{ToHex()}"""; - } - - /// - /// Loads the content value from 32-byte long byte array. - /// - /// - /// - /// - public static Hash LoadFromByteArray(byte[] bytes) - { - if (bytes.Length != AElfConstants.HashByteArrayLength) - throw new ArgumentException("Invalid bytes.", nameof(bytes)); - - return new Hash - { - Value = ByteString.CopyFrom(bytes) - }; - } - - /// - /// Loads the content value represented in base64. - /// - /// - /// - public static Hash LoadFromBase64(string base64) - { - var bytes = Convert.FromBase64String(base64); - return LoadFromByteArray(bytes); - } - - /// - /// Loads the content value represented in hex string. - /// - /// - /// - /// - public static Hash LoadFromHex(string hex) - { - var bytes = ByteArrayHelper.HexStringToByteArray(hex); - return LoadFromByteArray(bytes); - } - - /// - /// Dumps the content value to byte array. - /// - /// - public byte[] ToByteArray() - { - return Value.ToByteArray(); - } - - /// - /// Converts hash into hexadecimal representation. - /// - /// - public string ToHex() - { - return Value.ToHex(); - } - - /// - /// Converts hash into int64 value. - /// - /// - public Int64 ToInt64() - { - return ToByteArray().ToInt64(true); - } + if (that == null) + throw new InvalidOperationException("Cannot compare hash when hash is null"); - public static bool operator ==(Hash h1, Hash h2) - { - return h1?.Equals(h2) ?? ReferenceEquals(h2, null); - } + return CompareHash(this, that); + } - public static bool operator !=(Hash h1, Hash h2) - { - return !(h1 == h2); - } + /// + /// Used to override IMessage's default string representation. + /// + /// + public string ToDiagnosticString() + { + return $@"""{ToHex()}"""; + } - public static bool operator <(Hash h1, Hash h2) - { - return CompareHash(h1, h2) < 0; - } + public IEnumerator GetEnumerator() + { + return Value.GetEnumerator(); + } - public static bool operator >(Hash h1, Hash h2) - { - return CompareHash(h1, h2) > 0; - } + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } - public int CompareTo(Hash that) + /// + /// Loads the content value from 32-byte long byte array. + /// + /// + /// + /// + public static Hash LoadFromByteArray(byte[] bytes) + { + if (bytes.Length != AElfConstants.HashByteArrayLength) + throw new ArgumentException("Invalid bytes.", nameof(bytes)); + + return new Hash { - if (that == null) - throw new InvalidOperationException("Cannot compare hash when hash is null"); + Value = ByteString.CopyFrom(bytes) + }; + } - return CompareHash(this, that); - } + /// + /// Loads the content value represented in base64. + /// + /// + /// + public static Hash LoadFromBase64(string base64) + { + var bytes = Convert.FromBase64String(base64); + return LoadFromByteArray(bytes); + } - private static int CompareHash(Hash hash1, Hash hash2) - { - if (hash1 != null) - { - return hash2 == null ? 1 : ByteStringHelper.Compare(hash1.Value, hash2.Value); - } + /// + /// Loads the content value represented in hex string. + /// + /// + /// + /// + public static Hash LoadFromHex(string hex) + { + var bytes = ByteArrayHelper.HexStringToByteArray(hex); + return LoadFromByteArray(bytes); + } - if (hash2 == null) - { - return 0; - } + /// + /// Dumps the content value to byte array. + /// + /// + public byte[] ToByteArray() + { + return Value.ToByteArray(); + } - return -1; - } + /// + /// Converts hash into hexadecimal representation. + /// + /// + public string ToHex() + { + return Value.ToHex(); + } - public IEnumerator GetEnumerator() - { - return Value.GetEnumerator(); - } + /// + /// Converts hash into int64 value. + /// + /// + public long ToInt64() + { + return ToByteArray().ToInt64(true); + } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public static bool operator ==(Hash h1, Hash h2) + { + return h1?.Equals(h2) ?? ReferenceEquals(h2, null); + } + + public static bool operator !=(Hash h1, Hash h2) + { + return !(h1 == h2); + } + + public static bool operator <(Hash h1, Hash h2) + { + return CompareHash(h1, h2) < 0; + } + + public static bool operator >(Hash h1, Hash h2) + { + return CompareHash(h1, h2) > 0; + } + + private static int CompareHash(Hash hash1, Hash hash2) + { + if (hash1 != null) return hash2 == null ? 1 : ByteStringHelper.Compare(hash1.Value, hash2.Value); + + if (hash2 == null) return 0; + + return -1; } } \ No newline at end of file diff --git a/src/AElf.Types/Types/Transaction.cs b/src/AElf.Types/Types/Transaction.cs index 3e7297c160..4ba3613afa 100644 --- a/src/AElf.Types/Types/Transaction.cs +++ b/src/AElf.Types/Types/Transaction.cs @@ -1,45 +1,44 @@ using System; using Google.Protobuf; -namespace AElf.Types +namespace AElf.Types; + +public partial class Transaction { - public partial class Transaction - { - private Hash _transactionId; + private Hash _transactionId; - public Hash GetHash() - { - if (_transactionId == null) - _transactionId = HashHelper.ComputeFrom(GetSignatureData()); + public Hash GetHash() + { + if (_transactionId == null) + _transactionId = HashHelper.ComputeFrom(GetSignatureData()); - return _transactionId; - } + return _transactionId; + } - public bool VerifyFields() - { - if (To == null || From == null) - return false; + public bool VerifyFields() + { + if (To == null || From == null) + return false; - if (RefBlockNumber < 0) - return false; + if (RefBlockNumber < 0) + return false; - if (string.IsNullOrEmpty(MethodName)) - return false; + if (string.IsNullOrEmpty(MethodName)) + return false; - return true; - } + return true; + } - private byte[] GetSignatureData() - { - if (!VerifyFields()) - throw new InvalidOperationException($"Invalid transaction: {this}"); + private byte[] GetSignatureData() + { + if (!VerifyFields()) + throw new InvalidOperationException($"Invalid transaction: {this}"); - if (Signature.IsEmpty) - return this.ToByteArray(); + if (Signature.IsEmpty) + return this.ToByteArray(); - var transaction = Clone(); - transaction.Signature = ByteString.Empty; - return transaction.ToByteArray(); - } + var transaction = Clone(); + transaction.Signature = ByteString.Empty; + return transaction.ToByteArray(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/AElf.WebApp.Application.Chain.csproj b/src/AElf.WebApp.Application.Chain/AElf.WebApp.Application.Chain.csproj index 0c52b0f744..25f7baeb7f 100644 --- a/src/AElf.WebApp.Application.Chain/AElf.WebApp.Application.Chain.csproj +++ b/src/AElf.WebApp.Application.Chain/AElf.WebApp.Application.Chain.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -12,13 +12,13 @@ - - - + + + - + - + diff --git a/src/AElf.WebApp.Application.Chain/Application/TransactionValidationStatusChangedEventHandler.cs b/src/AElf.WebApp.Application.Chain/Application/TransactionValidationStatusChangedEventHandler.cs index a14d7981a9..890740441c 100644 --- a/src/AElf.WebApp.Application.Chain/Application/TransactionValidationStatusChangedEventHandler.cs +++ b/src/AElf.WebApp.Application.Chain/Application/TransactionValidationStatusChangedEventHandler.cs @@ -4,29 +4,28 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; -namespace AElf.WebApp.Application.Chain.Application +namespace AElf.WebApp.Application.Chain.Application; + +public class TransactionValidationStatusChangedEventHandler : + ILocalEventHandler, + ITransientDependency { - public class TransactionValidationStatusChangedEventHandler : - ILocalEventHandler, - ITransientDependency - { - private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; + private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; - public TransactionValidationStatusChangedEventHandler( - ITransactionResultStatusCacheProvider transactionResultStatusCacheProvider) - { - _transactionResultStatusCacheProvider = transactionResultStatusCacheProvider; - } + public TransactionValidationStatusChangedEventHandler( + ITransactionResultStatusCacheProvider transactionResultStatusCacheProvider) + { + _transactionResultStatusCacheProvider = transactionResultStatusCacheProvider; + } - public Task HandleEventAsync(TransactionValidationStatusChangedEvent eventData) - { - _transactionResultStatusCacheProvider.ChangeTransactionResultStatus(eventData.TransactionId, - new TransactionValidateStatus - { - TransactionResultStatus = eventData.TransactionResultStatus, - Error = eventData.Error - }); - return Task.CompletedTask; - } + public Task HandleEventAsync(TransactionValidationStatusChangedEvent eventData) + { + _transactionResultStatusCacheProvider.ChangeTransactionResultStatus(eventData.TransactionId, + new TransactionValidateStatus + { + TransactionResultStatus = eventData.TransactionResultStatus, + Error = eventData.Error + }); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/BlockchainServiceExtensions.cs b/src/AElf.WebApp.Application.Chain/BlockchainServiceExtensions.cs index dcd62b5e3f..36d8301c82 100644 --- a/src/AElf.WebApp.Application.Chain/BlockchainServiceExtensions.cs +++ b/src/AElf.WebApp.Application.Chain/BlockchainServiceExtensions.cs @@ -1,20 +1,19 @@ +using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Types; -using System.Threading.Tasks; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public static class BlockchainServiceExtensions { - public static class BlockchainServiceExtensions + internal static async Task GetBlockAsync(this IBlockchainService blockchainService, Hash blockHash) { - internal static async Task GetBlockAsync(this IBlockchainService blockchainService, Hash blockHash) - { - return await blockchainService.GetBlockByHashAsync(blockHash); - } + return await blockchainService.GetBlockByHashAsync(blockHash); + } - internal static async Task GetBlockAtHeightAsync(this IBlockchainService blockchainService, long height) - { - return await blockchainService.GetBlockByHeightInBestChainBranchAsync(height); - } + internal static async Task GetBlockAtHeightAsync(this IBlockchainService blockchainService, long height) + { + return await blockchainService.GetBlockByHeightInBestChainBranchAsync(height); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/ChainApplicationWebAppAElfModule.cs b/src/AElf.WebApp.Application.Chain/ChainApplicationWebAppAElfModule.cs index e7442085eb..d5820e1828 100644 --- a/src/AElf.WebApp.Application.Chain/ChainApplicationWebAppAElfModule.cs +++ b/src/AElf.WebApp.Application.Chain/ChainApplicationWebAppAElfModule.cs @@ -2,29 +2,25 @@ using AElf.Modularity; using AElf.WebApp.Application.Chain.Infrastructure; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +[DependsOn( + typeof(CoreKernelAElfModule), + typeof(CoreApplicationWebAppAElfModule), + typeof(AbpAutoMapperModule) +)] +public class ChainApplicationWebAppAElfModule : AElfModule { - [DependsOn( - typeof(CoreKernelAElfModule), - typeof(CoreApplicationWebAppAElfModule), - typeof(AbpAutoMapperModule) - )] - public class ChainApplicationWebAppAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAutoMapperObjectMapper(); + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => { options.AddMaps(); }); - Configure(options => - { - options.AddMaps(); - }); - - context.Services - .AddSingleton(); - } + context.Services + .AddSingleton(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/BlockBodyDto.cs b/src/AElf.WebApp.Application.Chain/Dto/BlockBodyDto.cs index 0035347d49..cfc2a1d5ee 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/BlockBodyDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/BlockBodyDto.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class BlockBodyDto { - public class BlockBodyDto - { - public int TransactionsCount { get; set; } - - public List Transactions { get; set; } - } + public int TransactionsCount { get; set; } + + public List Transactions { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/BlockDto.cs b/src/AElf.WebApp.Application.Chain/Dto/BlockDto.cs index e9cd099d02..de63a38e35 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/BlockDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/BlockDto.cs @@ -1,13 +1,12 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class BlockDto { - public class BlockDto - { - public string BlockHash { get; set; } - - public BlockHeaderDto Header { get; set; } - - public BlockBodyDto Body { get; set; } - - public int BlockSize { get; set; } - } + public string BlockHash { get; set; } + + public BlockHeaderDto Header { get; set; } + + public BlockBodyDto Body { get; set; } + + public int BlockSize { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/BlockHeaderDto.cs b/src/AElf.WebApp.Application.Chain/Dto/BlockHeaderDto.cs index 2f065add1e..cdf73927c5 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/BlockHeaderDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/BlockHeaderDto.cs @@ -1,27 +1,26 @@ using System; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class BlockHeaderDto { - public class BlockHeaderDto - { - public string PreviousBlockHash { get; set; } + public string PreviousBlockHash { get; set; } - public string MerkleTreeRootOfTransactions { get; set; } + public string MerkleTreeRootOfTransactions { get; set; } - public string MerkleTreeRootOfWorldState { get; set; } + public string MerkleTreeRootOfWorldState { get; set; } - public string MerkleTreeRootOfTransactionState { get; set; } + public string MerkleTreeRootOfTransactionState { get; set; } - public string Extra { get; set; } + public string Extra { get; set; } - public long Height { get; set; } + public long Height { get; set; } - public DateTime Time { get; set; } + public DateTime Time { get; set; } - public string ChainId { get; set; } + public string ChainId { get; set; } - public string Bloom { get; set; } + public string Bloom { get; set; } - public string SignerPubkey { get; set; } - } + public string SignerPubkey { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/BlockStateDto.cs b/src/AElf.WebApp.Application.Chain/Dto/BlockStateDto.cs index 39da396d41..302ddc34e8 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/BlockStateDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/BlockStateDto.cs @@ -1,17 +1,16 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class BlockStateDto { - public class BlockStateDto - { - public string BlockHash { get; set; } + public string BlockHash { get; set; } - public string PreviousHash { get; set; } + public string PreviousHash { get; set; } - public long BlockHeight { get; set; } + public long BlockHeight { get; set; } - public Dictionary Changes { get; set; } + public Dictionary Changes { get; set; } - public List Deletes { get; set; } - } + public List Deletes { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/ChainStatusDto.cs b/src/AElf.WebApp.Application.Chain/Dto/ChainStatusDto.cs index 8a0114dee5..b375d19340 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/ChainStatusDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/ChainStatusDto.cs @@ -1,29 +1,28 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class ChainStatusDto { - public class ChainStatusDto - { - public string ChainId { get; set; } - - public Dictionary Branches { get; set; } - - public Dictionary NotLinkedBlocks { get; set; } - - public long LongestChainHeight { get; set; } - - public string LongestChainHash { get; set; } - - public string GenesisBlockHash { get; set; } - - public string GenesisContractAddress { get; set; } - - public string LastIrreversibleBlockHash { get; set; } - - public long LastIrreversibleBlockHeight { get; set; } - - public string BestChainHash { get; set; } - - public long BestChainHeight { get; set; } - } + public string ChainId { get; set; } + + public Dictionary Branches { get; set; } + + public Dictionary NotLinkedBlocks { get; set; } + + public long LongestChainHeight { get; set; } + + public string LongestChainHash { get; set; } + + public string GenesisBlockHash { get; set; } + + public string GenesisContractAddress { get; set; } + + public string LastIrreversibleBlockHash { get; set; } + + public long LastIrreversibleBlockHeight { get; set; } + + public string BestChainHash { get; set; } + + public long BestChainHeight { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionInput.cs b/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionInput.cs index 04a864b532..2ab4dec1c8 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionInput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionInput.cs @@ -2,81 +2,80 @@ using System.ComponentModel.DataAnnotations; using AElf.Types; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +[Display] +public class CreateRawTransactionInput : IValidatableObject { - [Display] - public class CreateRawTransactionInput : IValidatableObject - { - /// - /// from address - /// - [Required] - public string From { get; set; } + /// + /// from address + /// + [Required] + public string From { get; set; } - /// - /// to address - /// - [Required] - public string To { get; set; } + /// + /// to address + /// + [Required] + public string To { get; set; } - /// - /// refer block height - /// - [Required] - public long RefBlockNumber { get; set; } + /// + /// refer block height + /// + [Required] + public long RefBlockNumber { get; set; } - /// - /// refer block hash - /// - [Required] - public string RefBlockHash { get; set; } + /// + /// refer block hash + /// + [Required] + public string RefBlockHash { get; set; } - /// - /// contract method name - /// - [Required] - public string MethodName { get; set; } + /// + /// contract method name + /// + [Required] + public string MethodName { get; set; } - /// - /// contract method parameters - /// - [Required] - public string Params { get; set; } + /// + /// contract method parameters + /// + [Required] + public string Params { get; set; } - public IEnumerable Validate(ValidationContext validationContext) + public IEnumerable Validate(ValidationContext validationContext) + { + var validationResults = new List(); + try + { + Address.FromBase58(From); + } + catch { - var validationResults = new List(); - try - { - Address.FromBase58(From); - } - catch - { - validationResults.Add(new ValidationResult(Error.Message[Error.InvalidAddress], - new[] {nameof(From)})); - } + validationResults.Add(new ValidationResult(Error.Message[Error.InvalidAddress], + new[] { nameof(From) })); + } - try - { - Address.FromBase58(To); - } - catch - { - validationResults.Add( - new ValidationResult(Error.Message[Error.InvalidAddress], new[] {nameof(To)})); - } + try + { + Address.FromBase58(To); + } + catch + { + validationResults.Add( + new ValidationResult(Error.Message[Error.InvalidAddress], new[] { nameof(To) })); + } - try - { - Hash.LoadFromHex(RefBlockHash); - } - catch - { - validationResults.Add( - new ValidationResult(Error.Message[Error.InvalidBlockHash], new[] {nameof(RefBlockHash)})); - } - return validationResults; + try + { + Hash.LoadFromHex(RefBlockHash); + } + catch + { + validationResults.Add( + new ValidationResult(Error.Message[Error.InvalidBlockHash], new[] { nameof(RefBlockHash) })); } - } + return validationResults; + } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionOutput.cs b/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionOutput.cs index 5425ec1304..f0aa1e1b90 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionOutput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/CreateRawTransactionOutput.cs @@ -1,7 +1,6 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class CreateRawTransactionOutput { - public class CreateRawTransactionOutput - { - public string RawTransaction { get; set; } - } + public string RawTransaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/ExecuteRawTransactionDto.cs b/src/AElf.WebApp.Application.Chain/Dto/ExecuteRawTransactionDto.cs index cdc055ff99..6dd6cced13 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/ExecuteRawTransactionDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/ExecuteRawTransactionDto.cs @@ -1,15 +1,14 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class ExecuteRawTransactionDto { - public class ExecuteRawTransactionDto - { - /// - /// raw transaction - /// - public string RawTransaction { get; set; } - - /// - /// signature - /// - public string Signature { get; set; } - } + /// + /// raw transaction + /// + public string RawTransaction { get; set; } + + /// + /// signature + /// + public string Signature { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/ExecuteTransactionDto.cs b/src/AElf.WebApp.Application.Chain/Dto/ExecuteTransactionDto.cs index e937409a59..8d05e22337 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/ExecuteTransactionDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/ExecuteTransactionDto.cs @@ -1,10 +1,9 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class ExecuteTransactionDto { - public class ExecuteTransactionDto - { - /// - /// raw transaction - /// - public string RawTransaction { get; set; } - } + /// + /// raw transaction + /// + public string RawTransaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/GetTransactionPoolStatusOutput.cs b/src/AElf.WebApp.Application.Chain/Dto/GetTransactionPoolStatusOutput.cs index c13899d77d..aed24bd45d 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/GetTransactionPoolStatusOutput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/GetTransactionPoolStatusOutput.cs @@ -1,8 +1,7 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class GetTransactionPoolStatusOutput { - public class GetTransactionPoolStatusOutput - { - public int Queued { get; set; } - public int Validated { get; set; } - } + public int Queued { get; set; } + public int Validated { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/LogEventDto.cs b/src/AElf.WebApp.Application.Chain/Dto/LogEventDto.cs index 74bf2dd726..068811e1cd 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/LogEventDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/LogEventDto.cs @@ -1,13 +1,12 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class LogEventDto { - public class LogEventDto - { - public string Address { get; set; } - - public string Name { get; set; } - - public string[] Indexed { get; set; } - - public string NonIndexed { get; set; } - } + public string Address { get; set; } + + public string Name { get; set; } + + public string[] Indexed { get; set; } + + public string NonIndexed { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/MerklePathDto.cs b/src/AElf.WebApp.Application.Chain/Dto/MerklePathDto.cs index a345b1ac69..0158322c89 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/MerklePathDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/MerklePathDto.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class MerklePathDto { - public class MerklePathDto - { - public List MerklePathNodes { get; set; } - } + public List MerklePathNodes { get; set; } +} - public class MerklePathNodeDto - { - public string Hash { get; set; } - public bool IsLeftChildNode { get; set; } - } +public class MerklePathNodeDto +{ + public string Hash { get; set; } + public bool IsLeftChildNode { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/MiningSequenceDto.cs b/src/AElf.WebApp.Application.Chain/Dto/MiningSequenceDto.cs index cc9e9b2262..7e4e1be65a 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/MiningSequenceDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/MiningSequenceDto.cs @@ -1,14 +1,12 @@ -using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class MiningSequenceDto { - public class MiningSequenceDto - { - public string Pubkey { get; set; } - public Timestamp MiningTime { get; set; } - public string Behaviour { get; set; } - public long BlockHeight { get; set; } - public string PreviousBlockHash { get; set; } - } + public string Pubkey { get; set; } + public Timestamp MiningTime { get; set; } + public string Behaviour { get; set; } + public long BlockHeight { get; set; } + public string PreviousBlockHash { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionInput.cs b/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionInput.cs index 20ed79b38a..1f76919eb9 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionInput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionInput.cs @@ -1,20 +1,19 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class SendRawTransactionInput { - public class SendRawTransactionInput - { - /// - /// raw transaction - /// - public string Transaction { get; set; } - - /// - /// signature - /// - public string Signature { get; set; } - - /// - /// return transaction detail or not - /// - public bool ReturnTransaction { get; set; } - } + /// + /// raw transaction + /// + public string Transaction { get; set; } + + /// + /// signature + /// + public string Signature { get; set; } + + /// + /// return transaction detail or not + /// + public bool ReturnTransaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionOutput.cs b/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionOutput.cs index 3842140bfc..1e9fc6e763 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionOutput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/SendRawTransactionOutput.cs @@ -1,9 +1,8 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class SendRawTransactionOutput { - public class SendRawTransactionOutput - { - public string TransactionId { get; set; } - - public TransactionDto Transaction { get; set; } - } + public string TransactionId { get; set; } + + public TransactionDto Transaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionInput.cs b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionInput.cs index 17da9dafb1..3ce2d9b888 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionInput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionInput.cs @@ -1,10 +1,9 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class SendTransactionInput { - public class SendTransactionInput - { - /// - /// raw transaction - /// - public string RawTransaction { get; set; } - } + /// + /// raw transaction + /// + public string RawTransaction { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionOutput.cs b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionOutput.cs index ba805fe1dd..e4357925cb 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionOutput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionOutput.cs @@ -1,7 +1,6 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class SendTransactionOutput { - public class SendTransactionOutput - { - public string TransactionId { get; set; } - } + public string TransactionId { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionsInput.cs b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionsInput.cs index 8367e0abd2..4e7ddbf27f 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/SendTransactionsInput.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/SendTransactionsInput.cs @@ -1,10 +1,9 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class SendTransactionsInput { - public class SendTransactionsInput - { - /// - /// raw transactions - /// - public string RawTransactions { get; set; } - } + /// + /// raw transactions + /// + public string RawTransactions { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/TaskQueueStatusInfoDto.cs b/src/AElf.WebApp.Application.Chain/Dto/TaskQueueStatusInfoDto.cs index 46dc94b639..3c3940e032 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/TaskQueueStatusInfoDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/TaskQueueStatusInfoDto.cs @@ -1,9 +1,8 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class TaskQueueInfoDto { - public class TaskQueueInfoDto - { - public string Name { get; set; } - - public int Size { get; set; } - } + public string Name { get; set; } + + public int Size { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/TransactionDto.cs b/src/AElf.WebApp.Application.Chain/Dto/TransactionDto.cs index 34e5be1b18..f983b7c958 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/TransactionDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/TransactionDto.cs @@ -1,19 +1,18 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class TransactionDto { - public class TransactionDto - { - public string From { get; set; } - - public string To { get; set; } - - public long RefBlockNumber { get; set; } - - public string RefBlockPrefix { get; set; } - - public string MethodName { get; set; } - - public string Params { get; set; } - - public string Signature { get; set; } - } + public string From { get; set; } + + public string To { get; set; } + + public long RefBlockNumber { get; set; } + + public string RefBlockPrefix { get; set; } + + public string MethodName { get; set; } + + public string Params { get; set; } + + public string Signature { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs b/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs index 4fa7442813..e76f92a941 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs @@ -1,25 +1,24 @@ -namespace AElf.WebApp.Application.Chain.Dto +namespace AElf.WebApp.Application.Chain.Dto; + +public class TransactionResultDto { - public class TransactionResultDto - { - public string TransactionId { get; set; } + public string TransactionId { get; set; } + + public string Status { get; set; } - public string Status { get; set; } + public LogEventDto[] Logs { get; set; } - public LogEventDto[] Logs { get; set; } + public string Bloom { get; set; } - public string Bloom { get; set; } + public long BlockNumber { get; set; } - public long BlockNumber { get; set; } + public string BlockHash { get; set; } - public string BlockHash { get; set; } + public TransactionDto Transaction { get; set; } - public TransactionDto Transaction { get; set; } + public string ReturnValue { get; set; } - public string ReturnValue { get; set; } + public string Error { get; set; } - public string Error { get; set; } - - public int TransactionSize { get; set; } - } + public int TransactionSize { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Error.cs b/src/AElf.WebApp.Application.Chain/Error.cs index 08945f4ff7..e194dacbad 100644 --- a/src/AElf.WebApp.Application.Chain/Error.cs +++ b/src/AElf.WebApp.Application.Chain/Error.cs @@ -1,35 +1,34 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public static class Error { - public static class Error - { - public const int NotFound = 20001; - public const int InvalidAddress = 20002; - public const int InvalidBlockHash = 20003; - public const int InvalidTransactionId = 20004; - public const int InvalidOffset = 20006; - public const int InvalidLimit = 20007; - public const int InvalidTransaction = 20008; - public const int InvalidContractAddress = 20010; - public const int NoMatchMethodInContractAddress = 20011; - public const int InvalidParams = 20012; - public const int InvalidSignature = 20013; - public const string NeedBasicAuth = "User name and password for basic auth should be set"; + public const int NotFound = 20001; + public const int InvalidAddress = 20002; + public const int InvalidBlockHash = 20003; + public const int InvalidTransactionId = 20004; + public const int InvalidOffset = 20006; + public const int InvalidLimit = 20007; + public const int InvalidTransaction = 20008; + public const int InvalidContractAddress = 20010; + public const int NoMatchMethodInContractAddress = 20011; + public const int InvalidParams = 20012; + public const int InvalidSignature = 20013; + public const string NeedBasicAuth = "User name and password for basic auth should be set"; - public static readonly Dictionary Message = new Dictionary - { - {NotFound, "Not found"}, - {InvalidAddress, "Invalid address format"}, - {InvalidBlockHash, "Invalid block hash format"}, - {InvalidTransactionId, "Invalid Transaction id format"}, - {InvalidOffset, "Offset must greater than or equal to 0"}, - {InvalidLimit, "Limit must between 0 and 100"}, - {InvalidTransaction, "Invalid transaction information"}, - {InvalidContractAddress, "Invalid contract address"}, - {NoMatchMethodInContractAddress, "No match method in contract address"}, - {InvalidParams, "Invalid params"}, - {InvalidSignature, "Invalid signature"} - }; - } + public static readonly Dictionary Message = new() + { + { NotFound, "Not found" }, + { InvalidAddress, "Invalid address format" }, + { InvalidBlockHash, "Invalid block hash format" }, + { InvalidTransactionId, "Invalid Transaction id format" }, + { InvalidOffset, "Offset must greater than or equal to 0" }, + { InvalidLimit, "Limit must between 0 and 100" }, + { InvalidTransaction, "Invalid transaction information" }, + { InvalidContractAddress, "Invalid contract address" }, + { NoMatchMethodInContractAddress, "No match method in contract address" }, + { InvalidParams, "Invalid params" }, + { InvalidSignature, "Invalid signature" } + }; } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Infrastructure/ITransactionResultStatusCacheProvider.cs b/src/AElf.WebApp.Application.Chain/Infrastructure/ITransactionResultStatusCacheProvider.cs index eccfca0895..63bb7a23e2 100644 --- a/src/AElf.WebApp.Application.Chain/Infrastructure/ITransactionResultStatusCacheProvider.cs +++ b/src/AElf.WebApp.Application.Chain/Infrastructure/ITransactionResultStatusCacheProvider.cs @@ -6,61 +6,58 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -namespace AElf.WebApp.Application.Chain.Infrastructure +namespace AElf.WebApp.Application.Chain.Infrastructure; + +public interface ITransactionResultStatusCacheProvider { - public interface ITransactionResultStatusCacheProvider - { - void AddTransactionResultStatus(Hash transactionId); - void ChangeTransactionResultStatus(Hash transactionId, TransactionValidateStatus status); - TransactionValidateStatus GetTransactionResultStatus(Hash transactionId); - } + void AddTransactionResultStatus(Hash transactionId); + void ChangeTransactionResultStatus(Hash transactionId, TransactionValidateStatus status); + TransactionValidateStatus GetTransactionResultStatus(Hash transactionId); +} - public class TransactionResultStatusCacheProvider : ITransactionResultStatusCacheProvider - { - private readonly MemoryCache _validateResultsCache; - private readonly WebAppOptions _webAppOptions; +public class TransactionResultStatusCacheProvider : ITransactionResultStatusCacheProvider +{ + private readonly MemoryCache _validateResultsCache; + private readonly WebAppOptions _webAppOptions; - public ILogger Logger { get; set; } + public TransactionResultStatusCacheProvider(IOptionsSnapshot webAppOptions) + { + _webAppOptions = webAppOptions.Value; - public TransactionResultStatusCacheProvider(IOptionsSnapshot webAppOptions) + _validateResultsCache = new MemoryCache(new MemoryCacheOptions { - _webAppOptions = webAppOptions.Value; - - _validateResultsCache = new MemoryCache(new MemoryCacheOptions - { - ExpirationScanFrequency = - TimeSpan.FromMilliseconds(_webAppOptions.TransactionResultStatusCacheSeconds.Mul(1000).Div(10)) - }); + ExpirationScanFrequency = + TimeSpan.FromMilliseconds(_webAppOptions.TransactionResultStatusCacheSeconds.Mul(1000).Div(10)) + }); - Logger = NullLogger.Instance; - } + Logger = NullLogger.Instance; + } - public void AddTransactionResultStatus(Hash transactionId) - { - _validateResultsCache.Set(transactionId, new TransactionValidateStatus(), - TimeSpan.FromSeconds(_webAppOptions.TransactionResultStatusCacheSeconds)); - } + public ILogger Logger { get; set; } - public void ChangeTransactionResultStatus(Hash transactionId, TransactionValidateStatus status) - { - if (_validateResultsCache.TryGetValue(transactionId, out _)) - { - //_validateResultsCache.Remove(transactionId); - _validateResultsCache.Set(transactionId, status, - TimeSpan.FromSeconds(_webAppOptions.TransactionResultStatusCacheSeconds)); - } - } + public void AddTransactionResultStatus(Hash transactionId) + { + _validateResultsCache.Set(transactionId, new TransactionValidateStatus(), + TimeSpan.FromSeconds(_webAppOptions.TransactionResultStatusCacheSeconds)); + } - public TransactionValidateStatus GetTransactionResultStatus(Hash transactionId) - { - _validateResultsCache.TryGetValue(transactionId, out var status); - return status as TransactionValidateStatus; - } + public void ChangeTransactionResultStatus(Hash transactionId, TransactionValidateStatus status) + { + if (_validateResultsCache.TryGetValue(transactionId, out _)) + //_validateResultsCache.Remove(transactionId); + _validateResultsCache.Set(transactionId, status, + TimeSpan.FromSeconds(_webAppOptions.TransactionResultStatusCacheSeconds)); } - public class TransactionValidateStatus + public TransactionValidateStatus GetTransactionResultStatus(Hash transactionId) { - public TransactionResultStatus TransactionResultStatus { get; set; } - public string Error { get; set; } + _validateResultsCache.TryGetValue(transactionId, out var status); + return status as TransactionValidateStatus; } +} + +public class TransactionValidateStatus +{ + public TransactionResultStatus TransactionResultStatus { get; set; } + public string Error { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/BlockProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/BlockProfile.cs index 4154162b48..16396c2824 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/BlockProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/BlockProfile.cs @@ -5,44 +5,44 @@ using AutoMapper; using Google.Protobuf; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class BlockProfile : Profile { - public class BlockProfile : Profile + public const string IncludeTransactions = "IncludeTransactions"; + + public BlockProfile() { - public const string IncludeTransactions = "IncludeTransactions"; - - public BlockProfile() - { - CreateMap() - .ForMember(d => d.BlockHash, opt => opt.MapFrom(s => s.GetHash())) - .ForMember(destination => destination.BlockSize, opt => opt.MapFrom(source => source.CalculateSize())); + CreateMap() + .ForMember(d => d.BlockHash, opt => opt.MapFrom(s => s.GetHash())) + .ForMember(destination => destination.BlockSize, opt => opt.MapFrom(source => source.CalculateSize())); - CreateMap() - .ForMember(d => d.MerkleTreeRootOfTransactionState, - opt => opt.MapFrom(s => s.MerkleTreeRootOfTransactionStatus.ToHex())) - .ForMember(d => d.Extra, opt => opt.MapFrom(s => s.ExtraData.ToString())) - .ForMember(d => d.Time, opt => opt.MapFrom(s => s.Time.ToDateTime())) - .ForMember(d => d.ChainId, - opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.ChainId))) - .ForMember(d => d.Bloom, - opt => opt.MapFrom(s => - s.Bloom.Length == 0 - ? ByteString.CopyFrom(new byte[256]).ToBase64() - : s.Bloom.ToBase64())) - .ForMember(d => d.SignerPubkey, - opt => opt.MapFrom(s => s.SignerPubkey.ToByteArray().ToHex(false))); + CreateMap() + .ForMember(d => d.MerkleTreeRootOfTransactionState, + opt => opt.MapFrom(s => s.MerkleTreeRootOfTransactionStatus.ToHex())) + .ForMember(d => d.Extra, opt => opt.MapFrom(s => s.ExtraData.ToString())) + .ForMember(d => d.Time, opt => opt.MapFrom(s => s.Time.ToDateTime())) + .ForMember(d => d.ChainId, + opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.ChainId))) + .ForMember(d => d.Bloom, + opt => opt.MapFrom(s => + s.Bloom.Length == 0 + ? ByteString.CopyFrom(new byte[256]).ToBase64() + : s.Bloom.ToBase64())) + .ForMember(d => d.SignerPubkey, + opt => opt.MapFrom(s => s.SignerPubkey.ToByteArray().ToHex(false))); - CreateMap() - .ForMember(d => d.Transactions, opt => opt.MapFrom()); - } + CreateMap() + .ForMember(d => d.Transactions, opt => opt.MapFrom()); } - - public class BlockBodyResolver : IValueResolver> +} + +public class BlockBodyResolver : IValueResolver> +{ + public List Resolve(BlockBody source, BlockBodyDto destination, List destMember, + ResolutionContext context) { - public List Resolve(BlockBody source, BlockBodyDto destination, List destMember, ResolutionContext context) - { - var includeTransactions = (bool) context.Items[BlockProfile.IncludeTransactions]; - return includeTransactions ? source.TransactionIds.Select(t => t.ToHex()).ToList() : null; - } + var includeTransactions = (bool)context.Items[BlockProfile.IncludeTransactions]; + return includeTransactions ? source.TransactionIds.Select(t => t.ToHex()).ToList() : null; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/BlockStateSetProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/BlockStateSetProfile.cs index a11a5c96ec..0c880a7241 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/BlockStateSetProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/BlockStateSetProfile.cs @@ -2,13 +2,12 @@ using AElf.WebApp.Application.Chain.Dto; using AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class BlockStateSetProfile : Profile { - public class BlockStateSetProfile: Profile + public BlockStateSetProfile() { - public BlockStateSetProfile() - { - CreateMap(); - } + CreateMap(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/ChainProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/ChainProfile.cs index a100919858..797e201aad 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/ChainProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/ChainProfile.cs @@ -4,22 +4,21 @@ using AutoMapper; using Volo.Abp.AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class ChainProfile : Profile { - public class ChainProfile : Profile + public ChainProfile() { - public ChainProfile() - { - CreateMap() - .ForMember(d => d.ChainId, opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.Id))) - .ForMember(d => d.Branches, - opt => opt.MapFrom(s => - s.Branches.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(), b => b.Value))) - .ForMember(d => d.NotLinkedBlocks, - opt => opt.MapFrom(s => - s.NotLinkedBlocks.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(), - b => Hash.LoadFromBase64(b.Value).ToHex()))) - .Ignore(d=>d.GenesisContractAddress); - } + CreateMap() + .ForMember(d => d.ChainId, opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.Id))) + .ForMember(d => d.Branches, + opt => opt.MapFrom(s => + s.Branches.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(), b => b.Value))) + .ForMember(d => d.NotLinkedBlocks, + opt => opt.MapFrom(s => + s.NotLinkedBlocks.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(), + b => Hash.LoadFromBase64(b.Value).ToHex()))) + .Ignore(d => d.GenesisContractAddress); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/CommonProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/CommonProfile.cs index af5a7343e8..ddd85823c9 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/CommonProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/CommonProfile.cs @@ -1,20 +1,20 @@ using AElf.Types; +using AutoMapper; using Google.Protobuf; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class CommonProfile : Profile { - public class CommonProfile : AutoMapper.Profile + public CommonProfile() { - public CommonProfile() - { - CreateMap() - .ConvertUsing(s => s == null ? null : s.ToHex()); + CreateMap() + .ConvertUsing(s => s == null ? null : s.ToHex()); + + CreateMap() + .ConvertUsing(s => s.ToBase58()); - CreateMap() - .ConvertUsing(s => s.ToBase58()); - - CreateMap() - .ConvertUsing(s => s.ToBase64()); - } + CreateMap() + .ConvertUsing(s => s.ToBase64()); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/MerklePathProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/MerklePathProfile.cs index b8c70d0076..fe04fe10a5 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/MerklePathProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/MerklePathProfile.cs @@ -2,15 +2,14 @@ using AElf.WebApp.Application.Chain.Dto; using AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class MerklePathProfile : Profile { - public class MerklePathProfile : Profile + public MerklePathProfile() { - public MerklePathProfile() - { - CreateMap(); + CreateMap(); - CreateMap(); - } + CreateMap(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/TaskQueueInfoProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/TaskQueueInfoProfile.cs index a909938524..bc396d61e4 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/TaskQueueInfoProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/TaskQueueInfoProfile.cs @@ -1,13 +1,12 @@ using AElf.WebApp.Application.Chain.Dto; using AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class TaskQueueInfoProfile : Profile { - public class TaskQueueInfoProfile : Profile + public TaskQueueInfoProfile() { - public TaskQueueInfoProfile() - { - CreateMap(); - } + CreateMap(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/TransactionPoolStatusProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/TransactionPoolStatusProfile.cs index 16d6d4d6c1..0de9ee8224 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/TransactionPoolStatusProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/TransactionPoolStatusProfile.cs @@ -2,16 +2,14 @@ using AElf.WebApp.Application.Chain.Dto; using AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class TransactionPoolStatusProfile : Profile { - public class TransactionPoolStatusProfile : Profile + public TransactionPoolStatusProfile() { - public TransactionPoolStatusProfile() - { - CreateMap() - .ForMember(d => d.Queued, opt => opt.MapFrom(s => s.AllTransactionCount)) - .ForMember(d => d.Validated, opt => opt.MapFrom(s => s.ValidatedTransactionCount)); - - } + CreateMap() + .ForMember(d => d.Queued, opt => opt.MapFrom(s => s.AllTransactionCount)) + .ForMember(d => d.Validated, opt => opt.MapFrom(s => s.ValidatedTransactionCount)); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Profile/TransactionProfile.cs b/src/AElf.WebApp.Application.Chain/Profile/TransactionProfile.cs index 741bbbdb62..5f27a28cde 100644 --- a/src/AElf.WebApp.Application.Chain/Profile/TransactionProfile.cs +++ b/src/AElf.WebApp.Application.Chain/Profile/TransactionProfile.cs @@ -3,56 +3,54 @@ using AElf.WebApp.Application.Chain.Dto; using AutoMapper; using Google.Protobuf; -using Microsoft.Extensions.Options; using Volo.Abp.AutoMapper; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class TransactionProfile : Profile +{ + public const string ErrorTrace = "WithMetrics"; + + public TransactionProfile() + { + CreateMap(); + + CreateMap() + .ForMember(d => d.ReturnValue, opt => opt.MapFrom(s => s.ReturnValue.ToHex(false))) + .ForMember(d => d.Bloom, + opt => opt.MapFrom(s => + s.Status == TransactionResultStatus.NotExisted + ? null + : s.Bloom.Length == 0 + ? ByteString.CopyFrom(new byte[256]).ToBase64() + : s.Bloom.ToBase64())) + .ForMember(d => d.Status, opt => opt.MapFrom(s => s.Status.ToString().ToUpper())) + .ForMember(d => d.Error, opt => opt.MapFrom()) + .Ignore(d => d.Transaction) + .Ignore(d => d.TransactionSize); + + CreateMap(); + } +} + +public class TransactionErrorResolver : IValueResolver { - public class TransactionProfile : Profile + public string Resolve(TransactionResult source, TransactionResultDto destination, string destMember, + ResolutionContext context) { - public const string ErrorTrace = "WithMetrics"; - - public TransactionProfile() - { - CreateMap(); - - CreateMap() - .ForMember(d => d.ReturnValue, opt => opt.MapFrom(s => s.ReturnValue.ToHex(false))) - .ForMember(d => d.Bloom, - opt => opt.MapFrom(s => - s.Status == TransactionResultStatus.NotExisted - ? null - : s.Bloom.Length == 0 - ? ByteString.CopyFrom(new byte[256]).ToBase64() - : s.Bloom.ToBase64())) - .ForMember(d => d.Status, opt => opt.MapFrom(s => s.Status.ToString().ToUpper())) - .ForMember(d => d.Error, opt => opt.MapFrom()) - .Ignore(d => d.Transaction) - .Ignore(d => d.TransactionSize); - - CreateMap(); - } + var errorTraceNeeded = (bool)context.Items[TransactionProfile.ErrorTrace]; + return TakeErrorMessage(source.Error, errorTraceNeeded); } - public class TransactionErrorResolver : IValueResolver + public static string TakeErrorMessage(string transactionResultError, bool errorTraceNeeded) { - public string Resolve(TransactionResult source, TransactionResultDto destination, string destMember, - ResolutionContext context) - { - var errorTraceNeeded = (bool) context.Items[TransactionProfile.ErrorTrace]; - return TakeErrorMessage(source.Error, errorTraceNeeded); - } - - public static string TakeErrorMessage(string transactionResultError, bool errorTraceNeeded) - { - if (string.IsNullOrWhiteSpace(transactionResultError)) - return null; - - if (errorTraceNeeded) - return transactionResultError; - - using var stringReader = new StringReader(transactionResultError); - return stringReader.ReadLine(); - } + if (string.IsNullOrWhiteSpace(transactionResultError)) + return null; + + if (errorTraceNeeded) + return transactionResultError; + + using var stringReader = new StringReader(transactionResultError); + return stringReader.ReadLine(); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Services/BlockChainAppService.cs b/src/AElf.WebApp.Application.Chain/Services/BlockChainAppService.cs index 78630e0799..fc837afe12 100644 --- a/src/AElf.WebApp.Application.Chain/Services/BlockChainAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/BlockChainAppService.cs @@ -1,12 +1,12 @@ +using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; +using AElf.Kernel.TransactionPool.Application; using AElf.Types; using AElf.WebApp.Application.Chain.Dto; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using System.Threading.Tasks; -using AElf.Kernel.TransactionPool.Application; using Volo.Abp; using Volo.Abp.EventBus.Local; using Volo.Abp.ObjectMapping; @@ -29,13 +29,9 @@ public interface IBlockChainAppService public class BlockChainAppService : AElfAppService, IBlockChainAppService { private readonly IBlockchainService _blockchainService; - private readonly ITransactionPoolService _transactionPoolService; private readonly IBlockStateSetManger _blockStateSetManger; private readonly IObjectMapper _objectMapper; - - public ILogger Logger { get; set; } - - public ILocalEventBus LocalEventBus { get; set; } + private readonly ITransactionPoolService _transactionPoolService; public BlockChainAppService(IBlockchainService blockchainService, IBlockStateSetManger blockStateSetManger, @@ -51,8 +47,12 @@ public BlockChainAppService(IBlockchainService blockchainService, LocalEventBus = NullLocalEventBus.Instance; } + public ILogger Logger { get; set; } + + public ILocalEventBus LocalEventBus { get; set; } + /// - /// Get the height of the current chain. + /// Get the height of the current chain. /// /// public async Task GetBlockHeightAsync() @@ -62,7 +62,7 @@ public async Task GetBlockHeightAsync() } /// - /// Get information about a given block by block hash. Otionally with the list of its transactions. + /// Get information about a given block by block hash. Otionally with the list of its transactions. /// /// block hash /// include transactions or not @@ -88,7 +88,7 @@ public async Task GetBlockAsync(string blockHash, bool includeTransact } /// - /// Get information about a given block by block height. Optionally with the list of its transactions. + /// Get information about a given block by block height. Optionally with the list of its transactions. /// /// block height /// include transactions or not @@ -104,7 +104,7 @@ public async Task GetBlockByHeightAsync(long blockHeight, bool include } /// - /// Get the transaction pool status. + /// Get the transaction pool status. /// /// public async Task GetTransactionPoolStatusAsync() @@ -114,7 +114,7 @@ public async Task GetTransactionPoolStatusAsync( } /// - /// Get the current state about a given block + /// Get the current state about a given block /// /// block hash /// @@ -139,10 +139,7 @@ private async Task GetBlockAtHeightAsync(long height) private BlockDto CreateBlockDto(Block block, bool includeTransactions) { - if (block == null) - { - throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); - } + if (block == null) throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); return _objectMapper.GetMapper().Map(block, opt => opt.Items[BlockProfile.IncludeTransactions] = includeTransactions); diff --git a/src/AElf.WebApp.Application.Chain/Services/ChainStatusAppService.cs b/src/AElf.WebApp.Application.Chain/Services/ChainStatusAppService.cs index 6df5aa3773..805db69a53 100644 --- a/src/AElf.WebApp.Application.Chain/Services/ChainStatusAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/ChainStatusAppService.cs @@ -1,7 +1,7 @@ +using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.WebApp.Application.Chain.Dto; -using System.Threading.Tasks; using Volo.Abp.ObjectMapping; namespace AElf.WebApp.Application.Chain; @@ -13,11 +13,10 @@ public interface IChainStatusAppService public class ChainStatusAppService : AElfAppService, IChainStatusAppService { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainService _blockchainService; private readonly IObjectMapper _objectMapper; + private readonly ISmartContractAddressService _smartContractAddressService; public ChainStatusAppService(ISmartContractAddressService smartContractAddressService, IBlockchainService blockchainService, @@ -29,7 +28,7 @@ public ChainStatusAppService(ISmartContractAddressService smartContractAddressSe } /// - /// Get the current status of the block chain. + /// Get the current status of the block chain. /// /// public async Task GetChainStatusAsync() diff --git a/src/AElf.WebApp.Application.Chain/Services/ContractFileDescriptorSetAppService.cs b/src/AElf.WebApp.Application.Chain/Services/ContractFileDescriptorSetAppService.cs index 6730bb9a07..2f999853d5 100644 --- a/src/AElf.WebApp.Application.Chain/Services/ContractFileDescriptorSetAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/ContractFileDescriptorSetAppService.cs @@ -1,9 +1,9 @@ using System; +using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Types; -using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Volo.Abp; using Volo.Abp.Application.Services; @@ -20,8 +20,6 @@ public class ContractFileDescriptorSetAppService : ApplicationService, IContract private static IBlockchainService _blockchainService; private static ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - public ILogger Logger { get; set; } - public ContractFileDescriptorSetAppService(IBlockchainService blockchainService, ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService) { @@ -29,8 +27,10 @@ public ContractFileDescriptorSetAppService(IBlockchainService blockchainService, _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; } + public ILogger Logger { get; set; } + /// - /// Get the protobuf definitions related to a contract + /// Get the protobuf definitions related to a contract /// /// contract address /// @@ -51,7 +51,7 @@ public async Task GetContractFileDescriptorSetAsync(string address) private async Task GetFileDescriptorSetAsync(Address address) { var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext() + var chainContext = new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight diff --git a/src/AElf.WebApp.Application.Chain/Services/TaskQueueStatusAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TaskQueueStatusAppService.cs index 3783cf031f..fbb00bb26d 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TaskQueueStatusAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TaskQueueStatusAppService.cs @@ -1,5 +1,5 @@ -using AElf.WebApp.Application.Chain.Dto; using System.Collections.Generic; +using AElf.WebApp.Application.Chain.Dto; using Volo.Abp.ObjectMapping; namespace AElf.WebApp.Application.Chain; @@ -11,8 +11,8 @@ public interface ITaskQueueStatusAppService public class TaskQueueStatusAppService : AElfAppService, ITaskQueueStatusAppService { - private readonly ITaskQueueManager _taskQueueManager; private readonly IObjectMapper _objectMapper; + private readonly ITaskQueueManager _taskQueueManager; public TaskQueueStatusAppService(ITaskQueueManager taskQueueManager, IObjectMapper objectMapper) diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionAppService.cs index 90b3d7027e..2e557e711d 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionAppService.cs @@ -1,17 +1,17 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Kernel.TransactionPool; using AElf.Types; using AElf.WebApp.Application.Chain.Dto; +using AElf.WebApp.Application.Chain.Infrastructure; using Google.Protobuf; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using AElf.Kernel.TransactionPool; -using AElf.WebApp.Application.Chain.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp; @@ -37,15 +37,11 @@ public interface ITransactionAppService public class TransactionAppService : AElfAppService, ITransactionAppService { - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; private readonly IBlockchainService _blockchainService; private readonly IObjectMapper _objectMapper; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; - public ILocalEventBus LocalEventBus { get; set; } - - public ILogger Logger { get; set; } - public TransactionAppService(ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, IBlockchainService blockchainService, IObjectMapper objectMapper, ITransactionResultStatusCacheProvider transactionResultStatusCacheProvider) @@ -59,8 +55,12 @@ public TransactionAppService(ITransactionReadOnlyExecutionService transactionRea Logger = NullLogger.Instance; } + public ILocalEventBus LocalEventBus { get; set; } + + public ILogger Logger { get; set; } + /// - /// Call a read-only method on a contract. + /// Call a read-only method on a contract. /// /// public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) @@ -74,16 +74,14 @@ public async Task ExecuteTransactionAsync(ExecuteTransactionDto input) } catch (Exception e) { - Logger.LogError(e, e.Message); //for debug + Logger.LogError(e, "{ErrorMessage}", e.Message); //for debug throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); } if (!transaction.VerifySignature()) - { throw new UserFriendlyException(Error.Message[Error.InvalidSignature], Error.InvalidSignature.ToString()); - } try { @@ -110,16 +108,14 @@ public async Task ExecuteRawTransactionAsync(ExecuteRawTransactionDto in } catch (Exception e) { - Logger.LogError(e, e.Message); //for debug + Logger.LogError(e, "{ErrorMessage}", e.Message); //for debug throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); } if (!transaction.VerifySignature()) - { throw new UserFriendlyException(Error.Message[Error.InvalidSignature], Error.InvalidSignature.ToString()); - } try { @@ -145,7 +141,7 @@ public async Task ExecuteRawTransactionAsync(ExecuteRawTransactionDto in } /// - /// Creates an unsigned serialized transaction + /// Creates an unsigned serialized transaction /// /// /// @@ -182,7 +178,7 @@ public async Task CreateRawTransactionAsync(CreateRa } /// - /// send a transaction + /// send a transaction /// /// /// @@ -203,16 +199,12 @@ public async Task SendRawTransactionAsync(SendRawTrans var contractMethodDescriptor = await GetContractMethodDescriptorAsync(transaction.To, transaction.MethodName); if (contractMethodDescriptor == null) - { throw new UserFriendlyException(Error.Message[Error.NoMatchMethodInContractAddress], Error.NoMatchMethodInContractAddress.ToString()); - } var parameters = contractMethodDescriptor.InputType.Parser.ParseFrom(transaction.Params); if (!IsValidMessage(parameters)) - { throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - } transactionDto.Params = JsonFormatter.ToDiagnosticString(parameters); output.Transaction = transactionDto; @@ -221,7 +213,7 @@ public async Task SendRawTransactionAsync(SendRawTrans } /// - /// Broadcast a transaction + /// Broadcast a transaction /// /// public async Task SendTransactionAsync(SendTransactionInput input) @@ -234,7 +226,7 @@ public async Task SendTransactionAsync(SendTransactionInp } /// - /// Broadcast multiple transactions + /// Broadcast multiple transactions /// /// public async Task SendTransactionsAsync(SendTransactionsInput input) @@ -275,24 +267,18 @@ private async Task PublishTransactionsAsync(string[] rawTransactions) var parameters = contractMethodDescriptor.InputType.Parser.ParseFrom(transaction.Params); if (!IsValidMessage(parameters)) - { throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - } if (!transaction.VerifySignature()) - { throw new UserFriendlyException(Error.Message[Error.InvalidSignature], Error.InvalidSignature.ToString()); - } transactions.Add(transaction); txIds[i] = transaction.GetHash().ToHex(); } foreach (var transaction in transactions) - { _transactionResultStatusCacheProvider.AddTransactionResultStatus(transaction.GetHash()); - } await LocalEventBus.PublishAsync(new TransactionsReceivedEvent { @@ -332,7 +318,7 @@ private async Task CallReadOnlyAsync(Transaction tx) private async Task GetChainContextAsync() { var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext() + var chainContext = new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs index b647f21d97..1c5fdabe4c 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs @@ -1,17 +1,17 @@ -using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.SmartContract.Application; -using AElf.Types; -using AElf.WebApp.Application.Chain.Dto; -using Google.Protobuf; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AElf.Kernel; -using Google.Protobuf.Reflection; +using AElf.Kernel.Blockchain.Application; +using AElf.Kernel.Blockchain.Domain; +using AElf.Kernel.SmartContract.Application; +using AElf.Types; +using AElf.WebApp.Application.Chain.Dto; using AElf.WebApp.Application.Chain.Infrastructure; +using Google.Protobuf; +using Google.Protobuf.Reflection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; @@ -32,16 +32,14 @@ Task> GetTransactionResultsAsync(string blockHash, in public class TransactionResultAppService : AElfAppService, ITransactionResultAppService { - private readonly ITransactionResultProxyService _transactionResultProxyService; - private readonly ITransactionManager _transactionManager; private readonly IBlockchainService _blockchainService; - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; private readonly IObjectMapper _objectMapper; + private readonly ITransactionManager _transactionManager; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + private readonly ITransactionResultProxyService _transactionResultProxyService; private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; private readonly WebAppOptions _webAppOptions; - public ILogger Logger { get; set; } - public TransactionResultAppService(ITransactionResultProxyService transactionResultProxyService, ITransactionManager transactionManager, IBlockchainService blockchainService, @@ -57,12 +55,14 @@ public TransactionResultAppService(ITransactionResultProxyService transactionRes _objectMapper = objectMapper; _transactionResultStatusCacheProvider = transactionResultStatusCacheProvider; _webAppOptions = optionsSnapshot.CurrentValue; - + Logger = NullLogger.Instance; } + public ILogger Logger { get; set; } + /// - /// Get the current status of a transaction + /// Get the current status of a transaction /// /// transaction id /// @@ -83,11 +83,11 @@ public async Task GetTransactionResultAsync(string transac var output = _objectMapper.GetMapper() .Map(transactionResult, opt => opt.Items[TransactionProfile.ErrorTrace] = _webAppOptions.IsDebugMode); - + var transaction = await _transactionManager.GetTransactionAsync(transactionResult.TransactionId); output.Transaction = _objectMapper.Map(transaction); output.TransactionSize = transaction?.CalculateSize() ?? 0; - + if (transactionResult.Status == TransactionResultStatus.NotExisted) { var validationStatus = @@ -109,9 +109,7 @@ public async Task GetTransactionResultAsync(string transac { var parameters = methodDescriptor.InputType.Parser.ParseFrom(transaction.Params); if (!IsValidMessage(parameters)) - { throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - } output.Transaction.Params = JsonFormatter.ToDiagnosticString(parameters); } @@ -120,7 +118,7 @@ public async Task GetTransactionResultAsync(string transac } /// - /// Get multiple transaction results. + /// Get multiple transaction results. /// /// block hash /// offset @@ -131,14 +129,10 @@ public async Task> GetTransactionResultsAsync(string int limit = 10) { if (offset < 0) - { throw new UserFriendlyException(Error.Message[Error.InvalidOffset], Error.InvalidOffset.ToString()); - } if (limit <= 0 || limit > 100) - { throw new UserFriendlyException(Error.Message[Error.InvalidLimit], Error.InvalidLimit.ToString()); - } Hash realBlockHash; try @@ -152,10 +146,7 @@ public async Task> GetTransactionResultsAsync(string } var block = await _blockchainService.GetBlockAsync(realBlockHash); - if (block == null) - { - throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); - } + if (block == null) throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); var output = new List(); if (offset <= block.Body.TransactionIds.Count - 1) @@ -173,7 +164,7 @@ public async Task> GetTransactionResultsAsync(string } /// - /// Get the merkle path of a transaction. + /// Get the merkle path of a transaction. /// /// /// @@ -195,10 +186,7 @@ public async Task GetMerklePathByTransactionIdAsync(string transa var blockInfo = await _blockchainService.GetBlockByHashAsync(blockHash); var transactionIds = blockInfo.Body.TransactionIds; var index = transactionIds.IndexOf(transactionIdHash); - if (index == -1) - { - throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); - } + if (index == -1) throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString()); var leafNodes = await GetLeafNodesAsync(blockInfo.TransactionIds); var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(leafNodes); @@ -214,33 +202,24 @@ private async Task GetTransactionResultAsync(Hash transaction var queuedTransaction = await _transactionResultProxyService.TransactionPoolService.GetQueuedTransactionAsync(transactionId); if (queuedTransaction != null) - { return new TransactionResult { TransactionId = queuedTransaction.TransactionId, Status = TransactionResultStatus.Pending }; - } // in storage TransactionResult result; if (blockHash != null) - { result = await _transactionResultProxyService.TransactionResultQueryService.GetTransactionResultAsync( transactionId, blockHash); - } else - { result = await _transactionResultProxyService.TransactionResultQueryService.GetTransactionResultAsync( transactionId); - } - if (result != null) - { - return result; - } + if (result != null) return result; // not existed return new TransactionResult @@ -249,15 +228,16 @@ await _transactionResultProxyService.TransactionResultQueryService.GetTransactio Status = TransactionResultStatus.NotExisted }; } - - private async Task GetTransactionResultDto(Hash transactionId, Hash realBlockHash, Hash blockHash) + + private async Task GetTransactionResultDto(Hash transactionId, Hash realBlockHash, + Hash blockHash) { var transactionResult = await GetTransactionResultAsync(transactionId, realBlockHash); var transactionResultDto = _objectMapper.GetMapper() .Map(transactionResult, opt => opt.Items[TransactionProfile.ErrorTrace] = _webAppOptions.IsDebugMode); - + var transaction = await _transactionManager.GetTransactionAsync(transactionResult.TransactionId); transactionResultDto.BlockHash = blockHash.ToHex(); @@ -271,13 +251,11 @@ private async Task GetTransactionResultDto(Hash transactio { var parameters = methodDescriptor.InputType.Parser.ParseFrom(transaction.Params); if (!IsValidMessage(parameters)) - { throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - } transactionResultDto.Transaction.Params = JsonFormatter.ToDiagnosticString(parameters); } - + return transactionResultDto; } @@ -312,9 +290,7 @@ private async Task> GetLeafNodesAsync(IEnumerable transactionId var transactionResultSet = transactionResultList.Select(txResult => (txResult.TransactionId, txResult.Status)); var leafNodes = new List(); foreach (var (txId, status) in transactionResultSet) - { leafNodes.Add(GetHashCombiningTransactionAndStatus(txId, status)); - } return leafNodes; } @@ -327,7 +303,7 @@ private Hash GetHashCombiningTransactionAndStatus(Hash txId, .ToArray(); return HashHelper.ComputeFrom(rawBytes); } - + private bool IsValidMessage(IMessage message) { try @@ -341,7 +317,7 @@ private bool IsValidMessage(IMessage message) return true; } - + private async Task GetContractMethodDescriptorAsync(Address contractAddress, string methodName, bool throwException = true) { diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionResultProxyService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionResultProxyService.cs index cafae774cb..5ebfcc8598 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionResultProxyService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionResultProxyService.cs @@ -11,13 +11,13 @@ public interface ITransactionResultProxyService public class TransactionResultProxyService : ITransactionResultProxyService { - public ITransactionPoolService TransactionPoolService { get; set; } - public ITransactionResultQueryService TransactionResultQueryService { get; set; } - public TransactionResultProxyService(ITransactionPoolService transactionPoolService, ITransactionResultQueryService transactionResultQueryService) { TransactionPoolService = transactionPoolService; TransactionResultQueryService = transactionResultQueryService; } + + public ITransactionPoolService TransactionPoolService { get; set; } + public ITransactionResultQueryService TransactionResultQueryService { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/TransactionReadOnlyExecutionServiceExtensions.cs b/src/AElf.WebApp.Application.Chain/TransactionReadOnlyExecutionServiceExtensions.cs index e231f8b906..3db67f7e2c 100644 --- a/src/AElf.WebApp.Application.Chain/TransactionReadOnlyExecutionServiceExtensions.cs +++ b/src/AElf.WebApp.Application.Chain/TransactionReadOnlyExecutionServiceExtensions.cs @@ -7,33 +7,32 @@ using Google.Protobuf.Reflection; using Volo.Abp; -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public static class TransactionReadOnlyExecutionServiceExtensions { - public static class TransactionReadOnlyExecutionServiceExtensions + public static async Task GetContractMethodDescriptorAsync( + this ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, IChainContext chainContext, + Address contractAddress, string methodName, bool throwException = true) { - public static async Task GetContractMethodDescriptorAsync( - this ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, IChainContext chainContext, - Address contractAddress, string methodName, bool throwException = true) - { - IEnumerable fileDescriptors; + IEnumerable fileDescriptors; - try - { - fileDescriptors = - await transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, contractAddress); - } - catch - { - if (throwException) - throw new UserFriendlyException(Error.Message[Error.InvalidContractAddress], - Error.InvalidContractAddress.ToString()); - return null; - } - - return fileDescriptors - .Select(fileDescriptor => - fileDescriptor.Services.Select(s => s.FindMethodByName(methodName)).FirstOrDefault()) - .FirstOrDefault(method => method != null); + try + { + fileDescriptors = + await transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, contractAddress); } + catch + { + if (throwException) + throw new UserFriendlyException(Error.Message[Error.InvalidContractAddress], + Error.InvalidContractAddress.ToString()); + return null; + } + + return fileDescriptors + .Select(fileDescriptor => + fileDescriptor.Services.Select(s => s.FindMethodByName(methodName)).FirstOrDefault()) + .FirstOrDefault(method => method != null); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/WebAppOptions.cs b/src/AElf.WebApp.Application.Chain/WebAppOptions.cs index f15b1b328a..9263b5c07f 100644 --- a/src/AElf.WebApp.Application.Chain/WebAppOptions.cs +++ b/src/AElf.WebApp.Application.Chain/WebAppOptions.cs @@ -1,9 +1,8 @@ -namespace AElf.WebApp.Application.Chain +namespace AElf.WebApp.Application.Chain; + +public class WebAppOptions { - public class WebAppOptions - { - public int TransactionResultStatusCacheSeconds { get; set; } = 180; + public int TransactionResultStatusCacheSeconds { get; set; } = 180; - public bool IsDebugMode { get; set; } - } + public bool IsDebugMode { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Core/AElf.WebApp.Application.Core.csproj b/src/AElf.WebApp.Application.Core/AElf.WebApp.Application.Core.csproj index 4c450be07c..b85df20afb 100644 --- a/src/AElf.WebApp.Application.Core/AElf.WebApp.Application.Core.csproj +++ b/src/AElf.WebApp.Application.Core/AElf.WebApp.Application.Core.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -11,12 +11,12 @@ - - + + - + diff --git a/src/AElf.WebApp.Application.Core/AElfAppService.cs b/src/AElf.WebApp.Application.Core/AElfAppService.cs index 982a9d77ba..b887b7d926 100644 --- a/src/AElf.WebApp.Application.Core/AElfAppService.cs +++ b/src/AElf.WebApp.Application.Core/AElfAppService.cs @@ -4,5 +4,4 @@ namespace AElf.WebApp.Application; public abstract class AElfAppService : ApplicationService { - } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Core/CoreApplicationWebAppAElfModule.cs b/src/AElf.WebApp.Application.Core/CoreApplicationWebAppAElfModule.cs index fcd3f16921..339b10b68f 100644 --- a/src/AElf.WebApp.Application.Core/CoreApplicationWebAppAElfModule.cs +++ b/src/AElf.WebApp.Application.Core/CoreApplicationWebAppAElfModule.cs @@ -5,7 +5,7 @@ namespace AElf.WebApp.Application; /// -/// Add summary to disable 'Missing XML Comment' warning. +/// Add summary to disable 'Missing XML Comment' warning. /// [DependsOn( typeof(CoreAElfModule), diff --git a/src/AElf.WebApp.Application.Net/AElf.WebApp.Application.Net.csproj b/src/AElf.WebApp.Application.Net/AElf.WebApp.Application.Net.csproj index 7f6d092f2d..d2d0066780 100644 --- a/src/AElf.WebApp.Application.Net/AElf.WebApp.Application.Net.csproj +++ b/src/AElf.WebApp.Application.Net/AElf.WebApp.Application.Net.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -11,12 +11,12 @@ - - + + - + diff --git a/src/AElf.WebApp.Application.Net/Dto/AddPeerInput.cs b/src/AElf.WebApp.Application.Net/Dto/AddPeerInput.cs index 58deac219b..cee12c23a2 100644 --- a/src/AElf.WebApp.Application.Net/Dto/AddPeerInput.cs +++ b/src/AElf.WebApp.Application.Net/Dto/AddPeerInput.cs @@ -1,10 +1,9 @@ -namespace AElf.WebApp.Application.Net.Dto +namespace AElf.WebApp.Application.Net.Dto; + +public class AddPeerInput { - public class AddPeerInput - { - /// - /// ip address - /// - public string Address { get; set; } - } + /// + /// ip address + /// + public string Address { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Net/Dto/GetNetworkInfoOutput.cs b/src/AElf.WebApp.Application.Net/Dto/GetNetworkInfoOutput.cs index d9514ce23c..691c58ff85 100644 --- a/src/AElf.WebApp.Application.Net/Dto/GetNetworkInfoOutput.cs +++ b/src/AElf.WebApp.Application.Net/Dto/GetNetworkInfoOutput.cs @@ -1,20 +1,19 @@ -namespace AElf.WebApp.Application.Net.Dto +namespace AElf.WebApp.Application.Net.Dto; + +public class GetNetworkInfoOutput { - public class GetNetworkInfoOutput - { - /// - /// node version - /// - public string Version { get; set; } - - /// - /// network protocol version - /// - public int ProtocolVersion { get; set; } - - /// - /// total number of open connections between this node and other nodes - /// - public int Connections { get; set; } - } + /// + /// node version + /// + public string Version { get; set; } + + /// + /// network protocol version + /// + public int ProtocolVersion { get; set; } + + /// + /// total number of open connections between this node and other nodes + /// + public int Connections { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Net/Dto/PeerDto.cs b/src/AElf.WebApp.Application.Net/Dto/PeerDto.cs index 32510e159e..2b5b09fa46 100644 --- a/src/AElf.WebApp.Application.Net/Dto/PeerDto.cs +++ b/src/AElf.WebApp.Application.Net/Dto/PeerDto.cs @@ -1,19 +1,17 @@ using System.Collections.Generic; -using AElf.OS.Network; using AElf.OS.Network.Metrics; -namespace AElf.WebApp.Application.Net.Dto +namespace AElf.WebApp.Application.Net.Dto; + +public class PeerDto { - public class PeerDto - { - public string IpAddress { get; set; } - public int ProtocolVersion { get; set; } - public long ConnectionTime { get; set; } - public string ConnectionStatus { get; set; } - public bool Inbound { get; set; } - public int BufferedTransactionsCount { get; set; } - public int BufferedBlocksCount { get; set; } - public int BufferedAnnouncementsCount { get; set; } - public List RequestMetrics { get; set; } - } + public string IpAddress { get; set; } + public int ProtocolVersion { get; set; } + public long ConnectionTime { get; set; } + public string ConnectionStatus { get; set; } + public bool Inbound { get; set; } + public int BufferedTransactionsCount { get; set; } + public int BufferedBlocksCount { get; set; } + public int BufferedAnnouncementsCount { get; set; } + public List RequestMetrics { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Net/NetAppService.cs b/src/AElf.WebApp.Application.Net/NetAppService.cs index 68e6c03ba4..49ed266fff 100644 --- a/src/AElf.WebApp.Application.Net/NetAppService.cs +++ b/src/AElf.WebApp.Application.Net/NetAppService.cs @@ -22,13 +22,13 @@ public interface INetAppService public class NetAppService : AElfAppService, INetAppService { - private readonly INetworkService _networkService; - private readonly IReconnectionService _reconnectionService; - private readonly IObjectMapper _objectMapper; - private static readonly string Version = typeof(NetApplicationWebAppAElfModule).Assembly.GetName().Version.ToString(); + private readonly INetworkService _networkService; + private readonly IObjectMapper _objectMapper; + private readonly IReconnectionService _reconnectionService; + public NetAppService(INetworkService networkService, IReconnectionService reconnectionService, IObjectMapper objectMapper) { @@ -38,7 +38,7 @@ public NetAppService(INetworkService networkService, IReconnectionService reconn } /// - /// Attempts to add a node to the connected network nodes + /// Attempts to add a node to the connected network nodes /// /// true/false [Authorize] @@ -48,7 +48,7 @@ public async Task AddPeerAsync(AddPeerInput input) } /// - /// Attempts to remove a node from the connected network nodes + /// Attempts to remove a node from the connected network nodes /// /// ip address /// @@ -60,7 +60,7 @@ public async Task RemovePeerAsync(string address) } /// - /// Get peer info about the connected network nodes + /// Get peer info about the connected network nodes /// /// public List GetPeers(bool withMetrics = false) @@ -72,7 +72,7 @@ public List GetPeers(bool withMetrics = false) } /// - /// Get information about the node’s connection to the network. + /// Get information about the node’s connection to the network. /// /// public Task GetNetworkInfoAsync() diff --git a/src/AElf.WebApp.Application.Net/Profile/PeerInfoProfile.cs b/src/AElf.WebApp.Application.Net/Profile/PeerInfoProfile.cs index 2347d70cf4..a9630fb2f7 100644 --- a/src/AElf.WebApp.Application.Net/Profile/PeerInfoProfile.cs +++ b/src/AElf.WebApp.Application.Net/Profile/PeerInfoProfile.cs @@ -9,19 +9,20 @@ namespace AElf.WebApp.Application.Net; public class PeerInfoProfile : Profile { public const string WithMetrics = "WithMetrics"; - + public PeerInfoProfile() { CreateMap() .ForMember(d => d.RequestMetrics, opt => opt.MapFrom()); } } - + public class PeerInfoResolver : IValueResolver> { - public List Resolve(PeerInfo source, PeerDto destination, List destMember, ResolutionContext context) + public List Resolve(PeerInfo source, PeerDto destination, List destMember, + ResolutionContext context) { - var withMetrics = (bool) context.Items[PeerInfoProfile.WithMetrics]; + var withMetrics = (bool)context.Items[PeerInfoProfile.WithMetrics]; return withMetrics ? source.RequestMetrics : null; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/AElf.WebApp.Web.csproj b/src/AElf.WebApp.Web/AElf.WebApp.Web.csproj index 33a752255d..773c76850f 100644 --- a/src/AElf.WebApp.Web/AElf.WebApp.Web.csproj +++ b/src/AElf.WebApp.Web/AElf.WebApp.Web.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -9,18 +9,18 @@ - - + + - - - - - - - + + + + + + + diff --git a/src/AElf.WebApp.Web/AElfConventionalRouteBuilder.cs b/src/AElf.WebApp.Web/AElfConventionalRouteBuilder.cs index e956d558b4..640b9be177 100644 --- a/src/AElf.WebApp.Web/AElfConventionalRouteBuilder.cs +++ b/src/AElf.WebApp.Web/AElfConventionalRouteBuilder.cs @@ -8,32 +8,27 @@ namespace AElf.WebApp.Web; public class AElfConventionalRouteBuilder : ConventionalRouteBuilder { - protected AbpConventionalControllerOptions Options { get; } - public AElfConventionalRouteBuilder(IOptions options) : base(options) { Options = options.Value; } + protected AbpConventionalControllerOptions Options { get; } + public override string Build(string rootPath, string controllerName, ActionModel action, string httpMethod, ConventionalControllerSetting configuration) { - var controllerNameInUrl = NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration); + var controllerNameInUrl = + NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration); var url = $"api/{controllerNameInUrl.ToCamelCase()}"; //Add {id} path if needed - if (action.Parameters.Any(p => p.ParameterName == "id")) - { - url += "/{id}"; - } + if (action.Parameters.Any(p => p.ParameterName == "id")) url += "/{id}"; //Add action name if needed var actionNameInUrl = NormalizeUrlActionName(rootPath, controllerName, action, httpMethod, configuration); - if (!actionNameInUrl.IsNullOrEmpty()) - { - url += $"/{actionNameInUrl.ToCamelCase()}"; - } + if (!actionNameInUrl.IsNullOrEmpty()) url += $"/{actionNameInUrl.ToCamelCase()}"; return url; } diff --git a/src/AElf.WebApp.Web/ApiOptionFilter.cs b/src/AElf.WebApp.Web/ApiOptionFilter.cs index d308b44e5b..f4257ddd76 100644 --- a/src/AElf.WebApp.Web/ApiOptionFilter.cs +++ b/src/AElf.WebApp.Web/ApiOptionFilter.cs @@ -1,33 +1,24 @@ using System; using System.Linq; -using System.Reflection; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace AElf.WebApp.Web +namespace AElf.WebApp.Web; + +/// +/// To hide api of ABP. +/// +internal class ApiOptionFilter : IDocumentFilter { - /// - /// To hide api of ABP. - /// - internal class ApiOptionFilter : IDocumentFilter + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) - { - foreach (var apiDescription in context.ApiDescriptions) - { - if (apiDescription.TryGetMethodInfo(out var method)) + foreach (var apiDescription in context.ApiDescriptions) + if (apiDescription.TryGetMethodInfo(out var method)) + if (method.ReflectedType != null && method.ReflectedType.CustomAttributes.Any()) { - if (method.ReflectedType != null && method.ReflectedType.CustomAttributes.Any()) - { - var pathToRemove = swaggerDoc.Paths - .Where(p => p.Key.Contains("Abp", StringComparison.CurrentCultureIgnoreCase)).ToList(); - foreach (var item in pathToRemove) - { - swaggerDoc.Paths.Remove(item.Key); - } - } + var pathToRemove = swaggerDoc.Paths + .Where(p => p.Key.Contains("Abp", StringComparison.CurrentCultureIgnoreCase)).ToList(); + foreach (var item in pathToRemove) swaggerDoc.Paths.Remove(item.Key); } - } - } } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/BasicAuthOptions.cs b/src/AElf.WebApp.Web/BasicAuthOptions.cs index b64c4da1e9..cffaf2c7a8 100644 --- a/src/AElf.WebApp.Web/BasicAuthOptions.cs +++ b/src/AElf.WebApp.Web/BasicAuthOptions.cs @@ -1,8 +1,7 @@ -namespace AElf.WebApp.Web +namespace AElf.WebApp.Web; + +public class BasicAuthOptions { - public class BasicAuthOptions - { - public string UserName { get; set; } - public string Password { get; set; } - } + public string UserName { get; set; } + public string Password { get; set; } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/BasicAuthenticationHandler.cs b/src/AElf.WebApp.Web/BasicAuthenticationHandler.cs index 1a1ec6282f..814f07108f 100644 --- a/src/AElf.WebApp.Web/BasicAuthenticationHandler.cs +++ b/src/AElf.WebApp.Web/BasicAuthenticationHandler.cs @@ -12,61 +12,62 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace AElf.WebApp.Web +namespace AElf.WebApp.Web; + +public class BasicAuthenticationHandler : AuthenticationHandler { - public class BasicAuthenticationHandler : AuthenticationHandler + private readonly BasicAuthOptions _basicAuthOptions; + + public BasicAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, + UrlEncoder encoder, ISystemClock clock, IOptionsMonitor basicAuthOptions) : base(options, + logger, encoder, clock) { - private readonly BasicAuthOptions _basicAuthOptions; - - public BasicAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IOptionsMonitor basicAuthOptions) : base(options, logger, encoder, clock) + _basicAuthOptions = basicAuthOptions.CurrentValue; + } + + protected override Task HandleAuthenticateAsync() + { + var endpoint = Context.GetEndpoint(); + if (endpoint?.Metadata?.GetMetadata() == null) + return Task.FromResult(AuthenticateResult.NoResult()); + + if (string.IsNullOrWhiteSpace(_basicAuthOptions.UserName) || + string.IsNullOrWhiteSpace(_basicAuthOptions.Password)) { - _basicAuthOptions = basicAuthOptions.CurrentValue; + Response.HttpContext.Features.Get().ReasonPhrase = Error.NeedBasicAuth; + return Task.FromResult(AuthenticateResult.Fail(Error.NeedBasicAuth)); } - protected override Task HandleAuthenticateAsync() - { - var endpoint = Context.GetEndpoint(); - if (endpoint?.Metadata?.GetMetadata() == null) - { - return Task.FromResult(AuthenticateResult.NoResult()); - } - - if (string.IsNullOrWhiteSpace(_basicAuthOptions.UserName) || string.IsNullOrWhiteSpace(_basicAuthOptions.Password)) - { - Response.HttpContext.Features.Get().ReasonPhrase = Error.NeedBasicAuth; - return Task.FromResult(AuthenticateResult.Fail(Error.NeedBasicAuth)); - } - - if (!Request.Headers.ContainsKey("Authorization")) - return Task.FromResult(AuthenticateResult.Fail("Missing Authorization Header")); + if (!Request.Headers.ContainsKey("Authorization")) + return Task.FromResult(AuthenticateResult.Fail("Missing Authorization Header")); - string userName; - string password; - try - { - var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); - var credentialBytes = Convert.FromBase64String(authHeader.Parameter); - var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2); - userName = credentials[0]; - password = credentials[1]; - } - catch - { - return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header")); - } + string userName; + string password; + try + { + var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]); + var credentialBytes = Convert.FromBase64String(authHeader.Parameter); + var credentials = Encoding.UTF8.GetString(credentialBytes).Split(new[] { ':' }, 2); + userName = credentials[0]; + password = credentials[1]; + } + catch + { + return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header")); + } - if (userName != _basicAuthOptions.UserName || password != _basicAuthOptions.Password) - return Task.FromResult(AuthenticateResult.Fail("Invalid Username or Password")); + if (userName != _basicAuthOptions.UserName || password != _basicAuthOptions.Password) + return Task.FromResult(AuthenticateResult.Fail("Invalid Username or Password")); - var claims = new[] { - new Claim(ClaimTypes.NameIdentifier, userName), - new Claim(ClaimTypes.Name, userName), - }; - var identity = new ClaimsIdentity(claims, Scheme.Name); - var principal = new ClaimsPrincipal(identity); - var ticket = new AuthenticationTicket(principal, Scheme.Name); + var claims = new[] + { + new Claim(ClaimTypes.NameIdentifier, userName), + new Claim(ClaimTypes.Name, userName) + }; + var identity = new ClaimsIdentity(claims, Scheme.Name); + var principal = new ClaimsPrincipal(identity); + var ticket = new AuthenticationTicket(principal, Scheme.Name); - return Task.FromResult(AuthenticateResult.Success(ticket)); - } + return Task.FromResult(AuthenticateResult.Success(ticket)); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/ConfigureSwaggerOptions.cs b/src/AElf.WebApp.Web/ConfigureSwaggerOptions.cs index b2680924ba..8fff20b18c 100644 --- a/src/AElf.WebApp.Web/ConfigureSwaggerOptions.cs +++ b/src/AElf.WebApp.Web/ConfigureSwaggerOptions.cs @@ -12,19 +12,27 @@ namespace AElf.WebApp.Web; /// -/// Configures the Swagger generation options. +/// Configures the Swagger generation options. /// -/// This allows API versioning to define a Swagger document per API version after the -/// service has been resolved from the service container. +/// +/// This allows API versioning to define a Swagger document per API version after the +/// service has been resolved from the service container. +/// public class ConfigureSwaggerOptions : IConfigureOptions { private readonly IApiVersionDescriptionProvider _provider; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The provider used to generate Swagger documents. - public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => _provider = provider; + /// + /// The provider used to generate Swagger + /// documents. + /// + public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) + { + _provider = provider; + } /// public void Configure(SwaggerGenOptions options) @@ -32,9 +40,7 @@ public void Configure(SwaggerGenOptions options) // add a swagger document for each discovered API version // note: you might choose to skip or document deprecated API versions differently foreach (var description in _provider.ApiVersionDescriptions) - { options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); - } options.IncludeXmlComments(() => { @@ -49,18 +55,15 @@ public void Configure(SwaggerGenOptions options) }); } - static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) + private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) { - var info = new OpenApiInfo() + var info = new OpenApiInfo { Title = $"AELF API {description.ApiVersion.ToString()}", Version = description.ApiVersion.ToString() }; - if (description.IsDeprecated) - { - info.Description += " This API version has been deprecated."; - } + if (description.IsDeprecated) info.Description += " This API version has been deprecated."; return info; } diff --git a/src/AElf.WebApp.Web/WebAppAbpAspNetCoreMvcModule.cs b/src/AElf.WebApp.Web/WebAppAbpAspNetCoreMvcModule.cs index 4257ffed47..72f17f64ee 100644 --- a/src/AElf.WebApp.Web/WebAppAbpAspNetCoreMvcModule.cs +++ b/src/AElf.WebApp.Web/WebAppAbpAspNetCoreMvcModule.cs @@ -2,18 +2,17 @@ using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; -namespace AElf.WebApp.Web +namespace AElf.WebApp.Web; + +public class WebAppAbpAspNetCoreMvcModule : AbpAspNetCoreMvcModule { - public class WebAppAbpAspNetCoreMvcModule : AbpAspNetCoreMvcModule + public override void PreConfigureServices(ServiceConfigurationContext context) { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - } + } - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - base.ConfigureServices(context); - } + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAssemblyOf(); + base.ConfigureServices(context); } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/WebAppAbpServiceConvention.cs b/src/AElf.WebApp.Web/WebAppAbpServiceConvention.cs index 7a6d68f98f..28c4cff6fa 100644 --- a/src/AElf.WebApp.Web/WebAppAbpServiceConvention.cs +++ b/src/AElf.WebApp.Web/WebAppAbpServiceConvention.cs @@ -9,6 +9,5 @@ public class WebAppAbpServiceConvention : AbpServiceConvention public WebAppAbpServiceConvention(IOptions options, IConventionalRouteBuilder conventionalRouteBuilder) : base(options, conventionalRouteBuilder) { - } } \ No newline at end of file diff --git a/src/AElf.WebApp.Web/WebWebAppAElfModule.cs b/src/AElf.WebApp.Web/WebWebAppAElfModule.cs index 3a17d94abb..237a9c3a36 100644 --- a/src/AElf.WebApp.Web/WebWebAppAElfModule.cs +++ b/src/AElf.WebApp.Web/WebWebAppAElfModule.cs @@ -30,239 +30,227 @@ using Volo.Abp.Castle.DynamicProxy; using Volo.Abp.Modularity; -namespace AElf.WebApp.Web +namespace AElf.WebApp.Web; + +[DependsOn( + typeof(ChainApplicationWebAppAElfModule), + typeof(NetApplicationWebAppAElfModule), + typeof(AbpCastleCoreModule), + typeof(WebAppAbpAspNetCoreMvcModule))] +public class WebWebAppAElfModule : AElfModule { - [DependsOn( - typeof(ChainApplicationWebAppAElfModule), - typeof(NetApplicationWebAppAElfModule), - typeof(AbpCastleCoreModule), - typeof(WebAppAbpAspNetCoreMvcModule))] - public class WebWebAppAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); + var configuration = context.Services.GetConfiguration(); - context.Services.Replace( - ServiceDescriptor.Transient()); + context.Services.Replace( + ServiceDescriptor.Transient()); - context.Services.AddTransient(typeof(AbpAsyncDeterminationInterceptor)); + context.Services.AddTransient(typeof(AbpAsyncDeterminationInterceptor)); - ConfigureAutoApiControllers(); + ConfigureAutoApiControllers(); - context.Services.AddApiVersioning(options => - { - options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options); - options.AssumeDefaultVersionWhenUnspecified = true; - options.ApiVersionReader = new MediaTypeApiVersionReader(); - options.UseApiBehavior = false; - }); - context.Services.AddVersionedApiExplorer(); + context.Services.AddApiVersioning(options => + { + options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options); + options.AssumeDefaultVersionWhenUnspecified = true; + options.ApiVersionReader = new MediaTypeApiVersionReader(); + options.UseApiBehavior = false; + }); + context.Services.AddVersionedApiExplorer(); - ConfigureSwaggerServices(context.Services); + ConfigureSwaggerServices(context.Services); - context.Services.AddControllers(options => - { - options.InputFormatters.Add(new ProtobufInputFormatter()); - options.OutputFormatters.Add(new ProtobufOutputFormatter()); - }).AddNewtonsoftJson(options => + context.Services.AddControllers(options => + { + options.InputFormatters.Add(new ProtobufInputFormatter()); + options.OutputFormatters.Add(new ProtobufOutputFormatter()); + }).AddNewtonsoftJson(options => + { + options.SerializerSettings.ContractResolver = new DefaultContractResolver { - options.SerializerSettings.ContractResolver = new DefaultContractResolver - { - NamingStrategy = new UpperCamelCaseNamingStrategy() - }; - options.SerializerSettings.Converters.Add(new ProtoMessageConverter()); - }); - - context.Services.AddAuthentication("BasicAuthentication") - .AddScheme("BasicAuthentication", null); + NamingStrategy = new UpperCamelCaseNamingStrategy() + }; + options.SerializerSettings.Converters.Add(new ProtoMessageConverter()); + }); - Configure(options => { configuration.GetSection("BasicAuth").Bind(options); }); - } + context.Services.AddAuthentication("BasicAuthentication") + .AddScheme("BasicAuthentication", null); - private void ConfigureAutoApiControllers() - { - Configure(options => - { - options.ConventionalControllers.Create(typeof(ChainApplicationWebAppAElfModule).Assembly, - setting => - { - setting.UrlControllerNameNormalizer = _ => "blockChain"; - }); - - options.ConventionalControllers.Create(typeof(NetApplicationWebAppAElfModule).Assembly, - setting => - { - setting.UrlControllerNameNormalizer = _ => "net"; - }); - }); - } + Configure(options => { configuration.GetSection("BasicAuth").Bind(options); }); + } - private void ConfigureSwaggerServices(IServiceCollection services) + private void ConfigureAutoApiControllers() + { + Configure(options => { - services.AddAbpSwaggerGen( - options => - { - options.SwaggerDoc("v1", new OpenApiInfo { Title = "AElf API", Version = "v1" }); - options.DocInclusionPredicate((docName, description) => true); - options.CustomSchemaIds(type => type.FullName); - options.DocumentFilter(); - options.HideAbpEndpoints(); - } - ); - services.AddTransient, ConfigureSwaggerOptions>(); - } + options.ConventionalControllers.Create(typeof(ChainApplicationWebAppAElfModule).Assembly, + setting => { setting.UrlControllerNameNormalizer = _ => "blockChain"; }); - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var app = context.GetApplicationBuilder(); + options.ConventionalControllers.Create(typeof(NetApplicationWebAppAElfModule).Assembly, + setting => { setting.UrlControllerNameNormalizer = _ => "net"; }); + }); + } - app.UseSwagger(); - app.UseSwaggerUI(options => + private void ConfigureSwaggerServices(IServiceCollection services) + { + services.AddAbpSwaggerGen( + options => { - var provider = context.ServiceProvider.GetRequiredService(); - foreach (var description in provider.ApiVersionDescriptions) - { - options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", - $"AELF API {description.GroupName.ToUpperInvariant()}"); - } - }); - - app.UseConfiguredEndpoints(); - } + options.SwaggerDoc("v1", new OpenApiInfo { Title = "AElf API", Version = "v1" }); + options.DocInclusionPredicate((docName, description) => true); + options.CustomSchemaIds(type => type.FullName); + options.DocumentFilter(); + options.HideAbpEndpoints(); + } + ); + services.AddTransient, ConfigureSwaggerOptions>(); } - // Thanks to https://tero.teelahti.fi/using-google-proto3-with-aspnet-mvc/ - // The input formatter reading request body and mapping it to given data object. - public class ProtobufInputFormatter : InputFormatter + public override void OnApplicationInitialization(ApplicationInitializationContext context) { - private static readonly MediaTypeHeaderValue ProtoMediaType = - MediaTypeHeaderValue.Parse((StringSegment) "application/x-protobuf"); + var app = context.GetApplicationBuilder(); - public ProtobufInputFormatter() + app.UseSwagger(); + app.UseSwaggerUI(options => { - SupportedMediaTypes.Add(ProtoMediaType); - } + var provider = context.ServiceProvider.GetRequiredService(); + foreach (var description in provider.ApiVersionDescriptions) + options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", + $"AELF API {description.GroupName.ToUpperInvariant()}"); + }); - public override bool CanRead(InputFormatterContext context) - { - var request = context.HttpContext.Request; - MediaTypeHeaderValue.TryParse(request.ContentType, out var requestContentType); - - return requestContentType != null && requestContentType.IsSubsetOf(ProtoMediaType); - } + app.UseConfiguredEndpoints(); + } +} - public override Task ReadRequestBodyAsync(InputFormatterContext context) - { - try - { - var request = context.HttpContext.Request; - var obj = (IMessage) Activator.CreateInstance(context.ModelType); - obj.MergeFrom(request.Body); +// Thanks to https://tero.teelahti.fi/using-google-proto3-with-aspnet-mvc/ +// The input formatter reading request body and mapping it to given data object. +public class ProtobufInputFormatter : InputFormatter +{ + private static readonly MediaTypeHeaderValue ProtoMediaType = + MediaTypeHeaderValue.Parse((StringSegment)"application/x-protobuf"); - return InputFormatterResult.SuccessAsync(obj); - } - catch (Exception ex) - { - Console.WriteLine("Exception: " + ex); - return InputFormatterResult.FailureAsync(); - } - } + public ProtobufInputFormatter() + { + SupportedMediaTypes.Add(ProtoMediaType); } - // The output object mapping returned object to Protobuf-serialized response body. - public class ProtobufOutputFormatter : OutputFormatter + public override bool CanRead(InputFormatterContext context) { - private static readonly MediaTypeHeaderValue ProtoMediaType = - MediaTypeHeaderValue.Parse((StringSegment) "application/x-protobuf"); + var request = context.HttpContext.Request; + MediaTypeHeaderValue.TryParse(request.ContentType, out var requestContentType); + + return requestContentType != null && requestContentType.IsSubsetOf(ProtoMediaType); + } - public ProtobufOutputFormatter() + public override Task ReadRequestBodyAsync(InputFormatterContext context) + { + try { - SupportedMediaTypes.Add(ProtoMediaType); - } + var request = context.HttpContext.Request; + var obj = (IMessage)Activator.CreateInstance(context.ModelType); + obj.MergeFrom(request.Body); - public override bool CanWriteResult(OutputFormatterCanWriteContext context) + return InputFormatterResult.SuccessAsync(obj); + } + catch (Exception ex) { - MediaTypeHeaderValue.TryParse(context.ContentType, out var parsedContentType); + Console.WriteLine("Exception: " + ex); + return InputFormatterResult.FailureAsync(); + } + } +} - if (context.Object == null || parsedContentType == null || !parsedContentType.IsSubsetOf(ProtoMediaType)) - { - return false; - } +// The output object mapping returned object to Protobuf-serialized response body. +public class ProtobufOutputFormatter : OutputFormatter +{ + private static readonly MediaTypeHeaderValue ProtoMediaType = + MediaTypeHeaderValue.Parse((StringSegment)"application/x-protobuf"); - // Check whether the given object is a proto-generated object - return context.ObjectType.GetTypeInfo() - .ImplementedInterfaces - .Where(i => i.GetTypeInfo().IsGenericType) - .Any(i => i.GetGenericTypeDefinition() == typeof(IMessage<>)); - } + public ProtobufOutputFormatter() + { + SupportedMediaTypes.Add(ProtoMediaType); + } - public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) - { - var response = context.HttpContext.Response; + public override bool CanWriteResult(OutputFormatterCanWriteContext context) + { + MediaTypeHeaderValue.TryParse(context.ContentType, out var parsedContentType); - // Proto-encode - var protoObj = context.Object as IMessage; - var serialized = protoObj.ToByteArray(); + if (context.Object == null || parsedContentType == null || + !parsedContentType.IsSubsetOf(ProtoMediaType)) return false; - return response.Body.WriteAsync(serialized, 0, serialized.Length); - } + // Check whether the given object is a proto-generated object + return context.ObjectType.GetTypeInfo() + .ImplementedInterfaces + .Where(i => i.GetTypeInfo().IsGenericType) + .Any(i => i.GetGenericTypeDefinition() == typeof(IMessage<>)); } + public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) + { + var response = context.HttpContext.Response; + + // Proto-encode + var protoObj = context.Object as IMessage; + var serialized = protoObj.ToByteArray(); - //Thanks to https://medium.com/google-cloud/making-newtonsoft-json-and-protocol-buffers-play-nicely-together-fe92079cc91c + return response.Body.WriteAsync(serialized, 0, serialized.Length); + } +} + +//Thanks to https://medium.com/google-cloud/making-newtonsoft-json-and-protocol-buffers-play-nicely-together-fe92079cc91c +/// +/// Lets Newtonsoft.Json and Protobuf's json converters play nicely +/// together. The default Netwtonsoft.Json Deserialize method will +/// not correctly deserialize proto messages. +/// +public class ProtoMessageConverter : JsonConverter +{ /// - /// Lets Newtonsoft.Json and Protobuf's json converters play nicely - /// together. The default Netwtonsoft.Json Deserialize method will - /// not correctly deserialize proto messages. + /// Called by NewtonSoft.Json's method to ask if this object can serialize + /// an object of a given type. /// - public class ProtoMessageConverter : JsonConverter + /// True if the objectType is a Protocol Message. + public override bool CanConvert(Type objectType) { - /// - /// Called by NewtonSoft.Json's method to ask if this object can serialize - /// an object of a given type. - /// - /// True if the objectType is a Protocol Message. - public override bool CanConvert(Type objectType) - { - return typeof(IMessage) - .IsAssignableFrom(objectType); - } + return typeof(IMessage) + .IsAssignableFrom(objectType); + } - /// - /// Reads the json representation of a Protocol Message and reconstructs - /// the Protocol Message. - /// - /// The Protocol Message type. - /// An instance of objectType. - public override object ReadJson(JsonReader reader, - Type objectType, object existingValue, - JsonSerializer serializer) - { - // The only way to find where this json object begins and ends is by - // reading it in as a generic ExpandoObject. - // Read an entire object from the reader. - var converter = new ExpandoObjectConverter(); - object o = converter.ReadJson(reader, objectType, existingValue, - serializer); - // Convert it back to json text. - string text = JsonConvert.SerializeObject(o); - // And let protobuf's parser parse the text. - IMessage message = (IMessage) Activator - .CreateInstance(objectType); - return JsonParser.Default.Parse(text, - message.Descriptor); - } + /// + /// Reads the json representation of a Protocol Message and reconstructs + /// the Protocol Message. + /// + /// The Protocol Message type. + /// An instance of objectType. + public override object ReadJson(JsonReader reader, + Type objectType, object existingValue, + JsonSerializer serializer) + { + // The only way to find where this json object begins and ends is by + // reading it in as a generic ExpandoObject. + // Read an entire object from the reader. + var converter = new ExpandoObjectConverter(); + var o = converter.ReadJson(reader, objectType, existingValue, + serializer); + // Convert it back to json text. + var text = JsonConvert.SerializeObject(o); + // And let protobuf's parser parse the text. + var message = (IMessage)Activator + .CreateInstance(objectType); + return JsonParser.Default.Parse(text, + message.Descriptor); + } - /// - /// Writes the json representation of a Protocol Message. - /// - public override void WriteJson(JsonWriter writer, object value, - JsonSerializer serializer) - { - // Let Protobuf's JsonFormatter do all the work. - writer.WriteRawValue(JsonFormatter.Default - .Format((IMessage) value)); - } + /// + /// Writes the json representation of a Protocol Message. + /// + public override void WriteJson(JsonWriter writer, object value, + JsonSerializer serializer) + { + // Let Protobuf's JsonFormatter do all the work. + writer.WriteRawValue(JsonFormatter.Default + .Format((IMessage)value)); } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/AElf.CSharp.CodeOps.Tests.csproj b/test/AElf.CSharp.CodeOps.Tests/AElf.CSharp.CodeOps.Tests.csproj index 6b1c5fdbeb..7b1783fcc3 100644 --- a/test/AElf.CSharp.CodeOps.Tests/AElf.CSharp.CodeOps.Tests.csproj +++ b/test/AElf.CSharp.CodeOps.Tests/AElf.CSharp.CodeOps.Tests.csproj @@ -9,37 +9,37 @@ TRACE;UNIT_TEST - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/test/AElf.CSharp.CodeOps.Tests/CSharpCodeOpsTestBase.cs b/test/AElf.CSharp.CodeOps.Tests/CSharpCodeOpsTestBase.cs index 1188ded5f8..9bbc4bb590 100644 --- a/test/AElf.CSharp.CodeOps.Tests/CSharpCodeOpsTestBase.cs +++ b/test/AElf.CSharp.CodeOps.Tests/CSharpCodeOpsTestBase.cs @@ -4,56 +4,55 @@ using AElf.TestBase; using Mono.Cecil; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class CSharpCodeOpsTestBase : AElfIntegratedTest { - public class CSharpCodeOpsTestBase : AElfIntegratedTest + private const string ContractDllDir = "../../../../../src/AElf.Launcher/contracts/"; + protected const string ContractPatchedDllDir = "../../../../patched/"; + + protected byte[] ReadContractCode(Type contractType) + { + var location = Path.Combine(ContractDllDir, Assembly.GetAssembly(contractType).ManifestModule.Name); + return ReadCode(location); + } + + protected byte[] ReadContractCode(string moduleName) + { + var location = Path.Combine(ContractDllDir, moduleName); + return ReadCode(location); + } + + protected byte[] ReadPatchedContractCode(Type contractType) + { + return ReadCode(ContractPatchedDllDir + contractType.Module + ".patched"); + } + + protected ModuleDefinition GetContractModule(Type contractType) + { + var code = ReadContractCode(contractType); + var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); + return modDef; + } + + protected ModuleDefinition GetPatchedContractModule(Type contractType) + { + var code = ReadPatchedContractCode(contractType); + var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); + return modDef; + } + + protected ModuleDefinition GetModule(Type type) + { + var code = ReadCode(Assembly.GetAssembly(type).Location); + var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); + return modDef; + } + + protected byte[] ReadCode(string path) { - private const string ContractDllDir = "../../../../../src/AElf.Launcher/contracts/"; - protected const string ContractPatchedDllDir = "../../../../patched/"; - - protected byte[] ReadContractCode(Type contractType) - { - var location = Path.Combine(ContractDllDir, Assembly.GetAssembly(contractType).ManifestModule.Name); - return ReadCode( location); - } - - protected byte[] ReadContractCode(string moduleName) - { - var location = Path.Combine(ContractDllDir, moduleName); - return ReadCode(location); - } - - protected byte[] ReadPatchedContractCode(Type contractType) - { - return ReadCode(ContractPatchedDllDir + contractType.Module + ".patched"); - } - - protected ModuleDefinition GetContractModule(Type contractType) - { - var code = ReadContractCode(contractType); - var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); - return modDef; - } - - protected ModuleDefinition GetPatchedContractModule(Type contractType) - { - var code = ReadPatchedContractCode(contractType); - var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); - return modDef; - } - - protected ModuleDefinition GetModule(Type type) - { - var code = ReadCode(Assembly.GetAssembly(type).Location); - var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); - return modDef; - } - - protected byte[] ReadCode(string path) - { - return File.Exists(path) - ? File.ReadAllBytes(path) - : throw new FileNotFoundException("DLL cannot be found. " + path); - } + return File.Exists(path) + ? File.ReadAllBytes(path) + : throw new FileNotFoundException("DLL cannot be found. " + path); } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/ContractAuditorTests.cs b/test/AElf.CSharp.CodeOps.Tests/ContractAuditorTests.cs index e0206d7cfc..b5dbb7366f 100644 --- a/test/AElf.CSharp.CodeOps.Tests/ContractAuditorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/ContractAuditorTests.cs @@ -17,7 +17,6 @@ using AElf.Contracts.TestContract.TransactionFees; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; -using AElf.CSharp.CodeOps.Patchers.Module; using AElf.CSharp.CodeOps.Validators; using AElf.CSharp.CodeOps.Validators.Assembly; using AElf.CSharp.CodeOps.Validators.Method; @@ -25,393 +24,393 @@ using AElf.Kernel.CodeCheck.Infrastructure; using AElf.Kernel.SmartContract; using AElf.Runtime.CSharp.Tests.BadContract; -using AElf.Sdk.CSharp; using Microsoft.Extensions.Options; +using Mono.Cecil; using Mono.Cecil.Cil; using Shouldly; using Xunit; -using MethodDefinition = Mono.Cecil.MethodDefinition; -namespace AElf.CSharp.CodeOps -{ - public class ContractAuditor : IDisposable - { - private CSharpContractAuditor _auditor; - private readonly RequiredAcs _requiredAcs; - - public ContractAuditor(CSharpContractAuditor contractAuditor) - { - _auditor = contractAuditor; - _requiredAcs = new RequiredAcs - { - AcsList = new[] {"acs1", "acs8"}.ToList(), - RequireAll = false - }; - } - - public void Audit(byte[] code, bool isSystemContract) - { - _auditor.Audit(code, _requiredAcs, isSystemContract); - } +namespace AElf.CSharp.CodeOps; - public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) - { - _auditor.Audit(code, requiredAcs, isSystemContract); - } +public class ContractAuditor : IDisposable +{ + private readonly RequiredAcs _requiredAcs; + private CSharpContractAuditor _auditor; - public void Dispose() + public ContractAuditor(CSharpContractAuditor contractAuditor) + { + _auditor = contractAuditor; + _requiredAcs = new RequiredAcs { - _auditor = null; - } + AcsList = new[] { "acs1", "acs8" }.ToList(), + RequireAll = false + }; } - public class ContractAuditorTests : CSharpCodeOpsTestBase + public void Dispose() { - private readonly ContractAuditor _auditor; - private readonly IContractPatcher _patcher; - - public ContractAuditorTests() - { - // Use fixture to instantiate auditor only once - _auditor = GetRequiredService(); - _patcher = GetRequiredService(); - } - - #region Positive Cases - - [Theory] - [InlineData(typeof(AssociationContract), false, "acs3", "acs5")] - [InlineData(typeof(ConfigurationContract))] - [InlineData(typeof(AEDPoSContract), true, "acs1", "acs6", "acs10")] - [InlineData(typeof(CrossChainContract), true, "acs6")] - [InlineData(typeof(EconomicContract))] - [InlineData(typeof(ElectionContract))] - [InlineData(typeof(BasicContractZero))] - [InlineData(typeof(TokenContract))] - [InlineData(typeof(ParliamentContract))] - [InlineData(typeof(ProfitContract))] - [InlineData(typeof(ReferendumContract))] - [InlineData(typeof(TokenConverterContract))] - [InlineData(typeof(TreasuryContract))] - public void CheckSystemContracts_AllShouldPass(Type contractType, bool acsAllRequired = false, params string[] acsList) - { - var requiredAcs = new RequiredAcs - { - RequireAll = acsAllRequired, - AcsList = new List(acsList) - }; - _auditor.Audit(ReadPatchedContractCode(contractType), true); - Should.Throw(() => - _auditor.Audit(ReadPatchedContractCode(contractType), requiredAcs, false)); - } - - [Fact] - public void AuditTimeout() - { - Should.NotThrow(() => _auditor.Audit(ReadPatchedContractCode(typeof(TokenContract)), true)); - var codeOpsOptions = GetRequiredService>(); - codeOpsOptions.CurrentValue.AuditTimeoutDuration = 0; - Should.Throw(() => - _auditor.Audit(ReadPatchedContractCode(typeof(TokenContract)), true)); - } - - [Fact] - public void ContractPatcher_Test() - { - var code = ReadContractCode(typeof(TokenContract)); - var updateCode = _patcher.Patch(code, false); - code.ShouldNotBe(updateCode); - var exception = Record.Exception(() => _auditor.Audit(updateCode, true)); - exception.ShouldBeNull(); - } - - [Fact] - public void ContractAudit_SystemPolicy_Test() - { - var code = ReadPatchedContractCode(typeof(TokenContract)); + _auditor = null; + } - Should.NotThrow(() => _auditor.Audit(code, true)); + public void Audit(byte[] code, bool isSystemContract) + { + _auditor.Audit(code, _requiredAcs, isSystemContract); + } - Should.Throw(() => _auditor.Audit(code, false)) - .Findings.Count(f => f is ObserverProxyValidationResult) - .ShouldBeGreaterThan(0); - } + public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) + { + _auditor.Audit(code, requiredAcs, isSystemContract); + } +} - #endregion +public class ContractAuditorTests : CSharpCodeOpsTestBase +{ + private readonly ContractAuditor _auditor; + private readonly IContractPatcher _patcher; - #region Negative Cases + public ContractAuditorTests() + { + // Use fixture to instantiate auditor only once + _auditor = GetRequiredService(); + _patcher = GetRequiredService(); + } - [Fact] - public void CheckBadContract_ForFindings() + #region Positive Cases + + [Theory] + [InlineData(typeof(AssociationContract), false, "acs3", "acs5")] + [InlineData(typeof(ConfigurationContract))] + [InlineData(typeof(AEDPoSContract), true, "acs1", "acs6", "acs10")] + [InlineData(typeof(CrossChainContract), true, "acs6")] + [InlineData(typeof(EconomicContract))] + [InlineData(typeof(ElectionContract))] + [InlineData(typeof(BasicContractZero))] + [InlineData(typeof(TokenContract))] + [InlineData(typeof(ParliamentContract))] + [InlineData(typeof(ProfitContract))] + [InlineData(typeof(ReferendumContract))] + [InlineData(typeof(TokenConverterContract))] + [InlineData(typeof(TreasuryContract))] + public void CheckSystemContracts_AllShouldPass(Type contractType, bool acsAllRequired = false, + params string[] acsList) + { + var requiredAcs = new RequiredAcs { - var findings = Should.Throw( - () => _auditor.Audit(ReadContractCode(typeof(BadContract)), false)) - .Findings; - - // Should have identified that ACS1 or ACS8 is not there - findings.FirstOrDefault(f => f is AcsValidationResult).ShouldNotBeNull(); - - // Random usage - LookFor(findings, - "UpdateStateWithRandom", - i => i.Namespace == "System" && i.Type == "Random") - .ShouldNotBeNull(); - - // DateTime UtcNow usage - LookFor(findings, - "UpdateStateWithCurrentTime", - i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_UtcNow") - .ShouldNotBeNull(); + RequireAll = acsAllRequired, + AcsList = new List(acsList) + }; + _auditor.Audit(ReadPatchedContractCode(contractType), true); + Should.Throw(() => + _auditor.Audit(ReadPatchedContractCode(contractType), requiredAcs, false)); + } - // DateTime Now usage - LookFor(findings, - "UpdateStateWithCurrentTime", - i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") - .ShouldNotBeNull(); + [Fact] + public void AuditTimeout() + { + Should.NotThrow(() => _auditor.Audit(ReadPatchedContractCode(typeof(TokenContract)), true)); + var codeOpsOptions = GetRequiredService>(); + codeOpsOptions.CurrentValue.AuditTimeoutDuration = 0; + Should.Throw(() => + _auditor.Audit(ReadPatchedContractCode(typeof(TokenContract)), true)); + } - // DateTime Today usage - LookFor(findings, - "UpdateStateWithCurrentTime", - i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Today") - .ShouldNotBeNull(); + [Fact] + public void ContractPatcher_Test() + { + var code = ReadContractCode(typeof(TokenContract)); + var updateCode = _patcher.Patch(code, false); + code.ShouldNotBe(updateCode); + var exception = Record.Exception(() => _auditor.Audit(updateCode, true)); + exception.ShouldBeNull(); + } - // Double type usage - LookFor(findings, - "UpdateDoubleState", - i => i.Namespace == "System" && i.Type == "Double") - .ShouldNotBeNull(); + [Fact] + public void ContractAudit_SystemPolicy_Test() + { + var code = ReadPatchedContractCode(typeof(TokenContract)); - // Float type usage - LookFor(findings, - "UpdateFloatState", - i => i.Namespace == "System" && i.Type == "Single") - .ShouldNotBeNull(); + Should.NotThrow(() => _auditor.Audit(code, true)); - // Disk Ops usage - LookFor(findings, - "WriteFileToNode", - i => i.Namespace == "System.IO") - .ShouldNotBeNull(); + Should.Throw(() => _auditor.Audit(code, false)) + .Findings.Count(f => f is ObserverProxyValidationResult) + .ShouldBeGreaterThan(0); + } - // String constructor usage - LookFor(findings, - "InitLargeStringDynamic", - i => i.Namespace == "System" && i.Type == "String" && i.Member == ".ctor") - .ShouldNotBeNull(); + #endregion - // Denied member use in nested class - LookFor(findings, - "UseDeniedMemberInNestedClass", - i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") - .ShouldNotBeNull(); + #region Negative Cases - // Denied member use in separate class - LookFor(findings, - "UseDeniedMemberInSeparateClass", - i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") - .ShouldNotBeNull(); + [Fact] + public void CheckBadContract_ForFindings() + { + var findings = Should.Throw( + () => _auditor.Audit(ReadContractCode(typeof(BadContract)), false)) + .Findings; + + // Should have identified that ACS1 or ACS8 is not there + findings.FirstOrDefault(f => f is AcsValidationResult).ShouldNotBeNull(); + + // Random usage + LookFor(findings, + "UpdateStateWithRandom", + i => i.Namespace == "System" && i.Type == "Random") + .ShouldNotBeNull(); + + // DateTime UtcNow usage + LookFor(findings, + "UpdateStateWithCurrentTime", + i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_UtcNow") + .ShouldNotBeNull(); + + // DateTime Now usage + LookFor(findings, + "UpdateStateWithCurrentTime", + i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") + .ShouldNotBeNull(); + + // DateTime Today usage + LookFor(findings, + "UpdateStateWithCurrentTime", + i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Today") + .ShouldNotBeNull(); + + // Double type usage + LookFor(findings, + "UpdateDoubleState", + i => i.Namespace == "System" && i.Type == "Double") + .ShouldNotBeNull(); + + // Float type usage + LookFor(findings, + "UpdateFloatState", + i => i.Namespace == "System" && i.Type == "Single") + .ShouldNotBeNull(); + + // Disk Ops usage + LookFor(findings, + "WriteFileToNode", + i => i.Namespace == "System.IO") + .ShouldNotBeNull(); + + // String constructor usage + LookFor(findings, + "InitLargeStringDynamic", + i => i.Namespace == "System" && i.Type == "String" && i.Member == ".ctor") + .ShouldNotBeNull(); + + // Denied member use in nested class + LookFor(findings, + "UseDeniedMemberInNestedClass", + i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") + .ShouldNotBeNull(); + + // Denied member use in separate class + LookFor(findings, + "UseDeniedMemberInSeparateClass", + i => i.Namespace == "System" && i.Type == "DateTime" && i.Member == "get_Now") + .ShouldNotBeNull(); + + // Large array initialization + findings.FirstOrDefault(f => f is ArrayValidationResult && f.Info.ReferencingMethod == "InitLargeArray") + .ShouldNotBeNull(); + + // Float operations + findings.FirstOrDefault(f => f is FloatOpsValidationResult) + .ShouldNotBeNull(); + + var getHashCodeFindings = findings.Where(f => f is GetHashCodeValidationResult).ToList(); + // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(BadContract)).ShouldNotBeNull(); + // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(DoubleInput)).ShouldNotBeNull(); + // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(FloatInput)).ShouldNotBeNull(); + // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(IMessageInheritedClass)).ShouldNotBeNull(); + + LookFor(getHashCodeFindings, "TestGetHashCodeCall", f => f != null).ShouldNotBeNull(); + LookFor(getHashCodeFindings, "GetHashCode", f => f != null).ShouldNotBeNull(); + + // FileDescriptor type field not allowed to be set outside of its declaring type constructor + findings + .FirstOrDefault(f => f is DescriptorAccessValidationResult && + f.Info.Type == "BadCase1" && f.Info.ReferencingMethod == "SetFileDescriptor") + .ShouldNotBeNull(); + + // Initialization value not allowed for resettable members, in regular type + findings + .FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadCase2" && f.Info.ReferencingMethod == ".cctor" && + f.Info.Member == "Number").ShouldNotBeNull(); + + // Initialization value not allowed for resettable members, in contract + findings + .FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadContract" && f.Info.ReferencingMethod == ".ctor" && + f.Info.Member == "i").ShouldNotBeNull(); + + // findings.FirstOrDefault(f => f is ContractStructureValidationResult && + // f.Info.Type == "BadContract" && f.Info.Member == "staticNotAllowedTypeField").ShouldBeNull(); + // findings.FirstOrDefault(f => f is ContractStructureValidationResult && + // f.Info.Type == "BadContract" && f.Info.Member == "staticAllowedTypeField").ShouldBeNull(); + // + // A type that is not allowed as a static readonly field + findings.FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadCase3" && f.Info.Member == "field").ShouldNotBeNull(); + + // Not allowed as readonly if a type has a field with its own type and has instance field + findings.FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadCase4" && f.Info.Member == "field").ShouldNotBeNull(); + + // Non primitive type is not allowed as an argument in ReadOnly GenericInstanceType type in static readonly fields + findings.FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadCase5" && f.Info.Member == "collection").ShouldNotBeNull(); + + // A type that is not allowed to be used as a field in contract state + findings + .FirstOrDefault(f => f is ContractStructureValidationResult && + f.Info.Type == "BadContractState" && f.Info.Member == "i").ShouldNotBeNull(); + } - // Large array initialization - findings.FirstOrDefault(f => f is ArrayValidationResult && f.Info.ReferencingMethod == "InitLargeArray") + [Fact] + public void CheckContractStruct_ForComponentsMissing() + { + { + var module = GetModule(typeof(ArrayValidator)); + var contractStructure = new ContractStructureValidator(); + var validationResults = contractStructure.Validate(module, CancellationToken.None); + validationResults + .FirstOrDefault(f => + f is ContractStructureValidationResult && f.Message == "Contract base not found.") .ShouldNotBeNull(); + } + } - // Float operations - findings.FirstOrDefault(f => f is FloatOpsValidationResult) - .ShouldNotBeNull(); + [Fact] + public void CheckResetField_ForMissingReset() + { + var code = ReadContractCode(typeof(BadContract)); + var module = ModuleDefinition.ReadModule(new MemoryStream(code)); + var resetFieldsMethod = module.Types + .Single(t => t.IsContractImplementation()) + .Methods.Single(m => m.Name == "ResetFields"); - var getHashCodeFindings = findings.Where(f => f is GetHashCodeValidationResult).ToList(); - // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(BadContract)).ShouldNotBeNull(); - // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(DoubleInput)).ShouldNotBeNull(); - // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(FloatInput)).ShouldNotBeNull(); - // getHashCodeFindings.FirstOrDefault(f => f.Info.Type == nameof(IMessageInheritedClass)).ShouldNotBeNull(); - - LookFor(getHashCodeFindings, "TestGetHashCodeCall", f => f != null).ShouldNotBeNull(); - LookFor(getHashCodeFindings, "GetHashCode", f => f != null).ShouldNotBeNull(); - - // FileDescriptor type field not allowed to be set outside of its declaring type constructor - findings - .FirstOrDefault(f => f is DescriptorAccessValidationResult && - f.Info.Type == "BadCase1" && f.Info.ReferencingMethod == "SetFileDescriptor") - .ShouldNotBeNull(); - - // Initialization value not allowed for resettable members, in regular type - findings - .FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadCase2" && f.Info.ReferencingMethod == ".cctor" && - f.Info.Member == "Number").ShouldNotBeNull(); - - // Initialization value not allowed for resettable members, in contract - findings - .FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadContract" && f.Info.ReferencingMethod == ".ctor" && - f.Info.Member == "i").ShouldNotBeNull(); - - // findings.FirstOrDefault(f => f is ContractStructureValidationResult && - // f.Info.Type == "BadContract" && f.Info.Member == "staticNotAllowedTypeField").ShouldBeNull(); - // findings.FirstOrDefault(f => f is ContractStructureValidationResult && - // f.Info.Type == "BadContract" && f.Info.Member == "staticAllowedTypeField").ShouldBeNull(); - // - // A type that is not allowed as a static readonly field - findings.FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadCase3" && f.Info.Member == "field").ShouldNotBeNull(); - - // Not allowed as readonly if a type has a field with its own type and has instance field - findings.FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadCase4" && f.Info.Member == "field").ShouldNotBeNull(); - - // Non primitive type is not allowed as an argument in ReadOnly GenericInstanceType type in static readonly fields - findings.FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadCase5" && f.Info.Member == "collection").ShouldNotBeNull(); - - // A type that is not allowed to be used as a field in contract state - findings - .FirstOrDefault(f => f is ContractStructureValidationResult && - f.Info.Type == "BadContractState" && f.Info.Member == "i").ShouldNotBeNull(); - } + RemoveInstruction(resetFieldsMethod, i => i.OpCode == OpCodes.Stfld); // Remove field reset + RemoveInstruction(resetFieldsMethod, i => + i.OpCode == OpCodes.Call && // Remove call to other type's ResetFields + i.Operand is MethodDefinition method && + method.Name == "ResetFields"); - [Fact] - public void CheckContractStruct_ForComponentsMissing() - { - { - var module = GetModule(typeof(ArrayValidator)); - var contractStructure = new ContractStructureValidator(); - var validationResults = contractStructure.Validate(module, CancellationToken.None); - validationResults - .FirstOrDefault(f => - f is ContractStructureValidationResult && f.Message == "Contract base not found.") - .ShouldNotBeNull(); - } - } - - [Fact] - public void CheckResetField_ForMissingReset() - { - var code = ReadContractCode(typeof(BadContract)); - var module = Mono.Cecil.ModuleDefinition.ReadModule(new MemoryStream(code)); - var resetFieldsMethod = module.Types - .Single(t => t.IsContractImplementation()) - .Methods.Single(m => m.Name == "ResetFields"); + var instruction = ReplaceInstruction(resetFieldsMethod, OpCodes.Ldc_I4_1, i => i.OpCode == OpCodes.Ldc_I4_0); - RemoveInstruction(resetFieldsMethod, i => i.OpCode == OpCodes.Stfld); // Remove field reset - RemoveInstruction(resetFieldsMethod, i => - i.OpCode == OpCodes.Call && // Remove call to other type's ResetFields - i.Operand is MethodDefinition method && - method.Name == "ResetFields"); + var tamperedContract = new MemoryStream(); + module.Write(tamperedContract); - var instruction = ReplaceInstruction(resetFieldsMethod, OpCodes.Ldc_I4_1, i => i.OpCode == OpCodes.Ldc_I4_0); + var findings = Should.Throw( + () => _auditor.Audit(tamperedContract.ToArray(), false)) + .Findings; - var tamperedContract = new MemoryStream(); - module.Write(tamperedContract); + findings.FirstOrDefault(f => f is ResetFieldsValidationResult && + f.Message.Contains("missing reset for certain fields")).ShouldNotBeNull(); - var findings = Should.Throw( - () => _auditor.Audit(tamperedContract.ToArray(), false)) - .Findings; + findings.FirstOrDefault(f => f is ResetFieldsValidationResult && + f.Message.Contains("missing certain method calls")).ShouldNotBeNull(); - findings.FirstOrDefault(f => f is ResetFieldsValidationResult && - f.Message.Contains("missing reset for certain fields")).ShouldNotBeNull(); + findings.FirstOrDefault(f => f is ResetFieldsValidationResult && + f.Message.Contains( + $"Unexpected instruction {instruction} found in ResetFields method.")) + .ShouldNotBeNull(); + } - findings.FirstOrDefault(f => f is ResetFieldsValidationResult && - f.Message.Contains("missing certain method calls")).ShouldNotBeNull(); + [Fact] + public void CheckPatchAudit_ForUncheckedMathOpcodes() + { + // Here, we use any contract that contains unchecked math OpCode even with "Check for arithmetic overflow" + // checked in the project. If first section of below test case fails, need to create another contract + // that iterates an array with foreach loop. + var contractCode = ReadContractCode(typeof(TransactionFeesContract)); - findings.FirstOrDefault(f => f is ResetFieldsValidationResult && - f.Message.Contains( - $"Unexpected instruction {instruction} found in ResetFields method.")) - .ShouldNotBeNull(); - } + var findings = Should.Throw( + () => _auditor.Audit(contractCode, false)) + .Findings; - [Fact] - public void CheckPatchAudit_ForUncheckedMathOpcodes() - { - // Here, we use any contract that contains unchecked math OpCode even with "Check for arithmetic overflow" - // checked in the project. If first section of below test case fails, need to create another contract - // that iterates an array with foreach loop. - var contractCode = ReadContractCode(typeof(TransactionFeesContract)); + findings.FirstOrDefault(f => f is UncheckedMathValidationResult) + .ShouldNotBeNull(); - var findings = Should.Throw( - () => _auditor.Audit(contractCode, false)) - .Findings; + // After patching, all unchecked arithmetic OpCodes should be cleared. + Should.NotThrow(() => _auditor.Audit(_patcher.Patch(contractCode, false), false)); + } - findings.FirstOrDefault(f => f is UncheckedMathValidationResult) - .ShouldNotBeNull(); + [Fact] + public void CheckPatchAudit_ForMethodCallInjection() + { + var contractCode = ReadContractCode(typeof(TransactionFeesContract)); + + var findings = Should.Throw( + () => _auditor.Audit(contractCode, false)) + .Findings; + + findings.Count(f => f is MethodCallInjectionValidationResult).ShouldBe(3); + findings.Count(f => f is ObserverProxyValidationResult).ShouldBe(1); + + // After patching, all unchecked arithmetic OpCodes should be cleared. + Should.NotThrow(() => _auditor.Audit(_patcher.Patch(contractCode, false), false)); + + var badContractModule = GetModule(typeof(BadContract)); + var validator = new ObserverProxyValidator(); + var validationResults = validator.Validate(badContractModule, CancellationToken.None); + validationResults.ShouldContain(v => v.Message.Contains("BranchCount proxy method body is tampered.")); + validationResults.ShouldContain(v => v.Message.Contains("CallCount proxy method body is tampered.")); + validationResults.ShouldContain(v => + v.Message.Contains("Missing execution observer call count call detected.")); + validationResults.ShouldContain(v => + v.Message.Contains("Missing execution observer branch count call detected.")); + validationResults.ShouldContain(v => + v.Message.Contains("Proxy initialize call detected from within the contract.")); + } - // After patching, all unchecked arithmetic OpCodes should be cleared. - Should.NotThrow(() => _auditor.Audit(_patcher.Patch(contractCode, false), false)); - } - - [Fact] - public void CheckPatchAudit_ForMethodCallInjection() - { - var contractCode = ReadContractCode(typeof(TransactionFeesContract)); - - var findings = Should.Throw( - () => _auditor.Audit(contractCode, false)) - .Findings; - - findings.Count(f => f is MethodCallInjectionValidationResult).ShouldBe(3); - findings.Count(f => f is ObserverProxyValidationResult).ShouldBe(1); - - // After patching, all unchecked arithmetic OpCodes should be cleared. - Should.NotThrow(() => _auditor.Audit(_patcher.Patch(contractCode, false), false)); - - var badContractModule = GetModule(typeof(BadContract)); - var validator = new ObserverProxyValidator(); - var validationResults = validator.Validate(badContractModule, CancellationToken.None); - validationResults.ShouldContain(v => v.Message.Contains("BranchCount proxy method body is tampered.")); - validationResults.ShouldContain(v => v.Message.Contains("CallCount proxy method body is tampered.")); - validationResults.ShouldContain(v => - v.Message.Contains("Missing execution observer call count call detected.")); - validationResults.ShouldContain(v => - v.Message.Contains("Missing execution observer branch count call detected.")); - validationResults.ShouldContain(v => - v.Message.Contains("Proxy initialize call detected from within the contract.")); - } - - [Fact] - public void ContractAuditor_AcsRequired_Test() - { - var requireAcs = new RequiredAcs(); - requireAcs.AcsList = new List {"acs1"}; - var badContractCode = ReadContractCode(typeof(BadContract)); - Should.Throw(() => _auditor.Audit(badContractCode, requireAcs, false)); + [Fact] + public void ContractAuditor_AcsRequired_Test() + { + var requireAcs = new RequiredAcs(); + requireAcs.AcsList = new List { "acs1" }; + var badContractCode = ReadContractCode(typeof(BadContract)); + Should.Throw(() => _auditor.Audit(badContractCode, requireAcs, false)); - var systemContractCode = ReadPatchedContractCode(typeof(BasicContractZero)); + var systemContractCode = ReadPatchedContractCode(typeof(BasicContractZero)); - Should.NotThrow(() => _auditor.Audit(systemContractCode, requireAcs, true)); + Should.NotThrow(() => _auditor.Audit(systemContractCode, requireAcs, true)); - requireAcs.AcsList.Add("acs8"); - Should.NotThrow(() => _auditor.Audit(systemContractCode, requireAcs, true)); + requireAcs.AcsList.Add("acs8"); + Should.NotThrow(() => _auditor.Audit(systemContractCode, requireAcs, true)); - requireAcs.RequireAll = true; - Should.Throw(() => _auditor.Audit(systemContractCode, requireAcs, true)); - } + requireAcs.RequireAll = true; + Should.Throw(() => _auditor.Audit(systemContractCode, requireAcs, true)); + } - #endregion + #endregion - #region Test Helpers + #region Test Helpers - Info LookFor(IEnumerable findings, string referencingMethod, Func criteria) - { - return findings.Select(f => f.Info) - .FirstOrDefault(i => i != null && i.ReferencingMethod == referencingMethod && criteria(i)); - } + private Info LookFor(IEnumerable findings, string referencingMethod, Func criteria) + { + return findings.Select(f => f.Info) + .FirstOrDefault(i => i != null && i.ReferencingMethod == referencingMethod && criteria(i)); + } - void RemoveInstruction(MethodDefinition method, Func where) - { - var il = method.Body.GetILProcessor(); + private void RemoveInstruction(MethodDefinition method, Func where) + { + var il = method.Body.GetILProcessor(); - il.Remove(method.Body.Instructions.First(where)); - } + il.Remove(method.Body.Instructions.First(where)); + } - Mono.Cecil.Cil.Instruction ReplaceInstruction(MethodDefinition method, OpCode opCode, Func where) - { - var il = method.Body.GetILProcessor(); + private Mono.Cecil.Cil.Instruction ReplaceInstruction(MethodDefinition method, OpCode opCode, + Func where) + { + var il = method.Body.GetILProcessor(); - var instruction = il.Create(opCode); - il.Replace(method.Body.Instructions.First(where), instruction); - return instruction; - } - - #endregion + var instruction = il.Create(opCode); + il.Replace(method.Body.Instructions.First(where), instruction); + return instruction; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/ContractPolicyTests.cs b/test/AElf.CSharp.CodeOps.Tests/ContractPolicyTests.cs index e57d338325..b9956367b9 100644 --- a/test/AElf.CSharp.CodeOps.Tests/ContractPolicyTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/ContractPolicyTests.cs @@ -8,117 +8,113 @@ using AElf.CSharp.CodeOps.Validators; using AElf.CSharp.CodeOps.Validators.Method; using AElf.CSharp.CodeOps.Validators.Module; -using AElf.Kernel.SmartContract.Application; using AElf.Runtime.CSharp.Tests.BadContract; using AElf.Runtime.CSharp.Tests.TestContract; using Mono.Cecil; using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +public class ContractPolicyTests : CSharpCodeOpsTestBase { - public class ContractPolicyTests : CSharpCodeOpsTestBase + private readonly byte[] _badContractCode; + private readonly byte[] _systemContractCode; + private CSharpContractAuditor _auditor; + + public ContractPolicyTests() { - private CSharpContractAuditor _auditor; - private readonly byte[] _systemContractCode; - private readonly byte[] _badContractCode; + _systemContractCode = ReadPatchedContractCode(typeof(BasicContractZero)); + _badContractCode = ReadContractCode(typeof(BadContract)); + } - public ContractPolicyTests() - { - _systemContractCode = ReadPatchedContractCode(typeof(BasicContractZero)); - _badContractCode = ReadContractCode(typeof(BadContract)); - } + [Fact] + public void Policy_ArrayValidator_Test() + { + var validator = new ArrayValidator(); + var validateResult1 = ValidateContractCode(_badContractCode, validator); + validateResult1.Count.ShouldBeGreaterThan(0); + var messages = validateResult1.Select(res => res.Message).ToArray(); + messages.ShouldContain("Array size is too large that causes overflow when estimating memory usage."); + messages.ShouldContain("Array of AElf.Runtime.CSharp.Tests.BadContract.BadCase3 type is not allowed."); - [Fact] - public void Policy_ArrayValidator_Test() - { - var validator = new ArrayValidator(); - var validateResult1 = ValidateContractCode(_badContractCode, validator); - validateResult1.Count.ShouldBeGreaterThan(0); - var messages = validateResult1.Select(res => res.Message).ToArray(); - messages.ShouldContain("Array size is too large that causes overflow when estimating memory usage."); - messages.ShouldContain("Array of AElf.Runtime.CSharp.Tests.BadContract.BadCase3 type is not allowed."); - - var validateResult2 = ValidateContractCode(_systemContractCode, validator); - validateResult2.Count.ShouldBe(0); - } + var validateResult2 = ValidateContractCode(_systemContractCode, validator); + validateResult2.Count.ShouldBe(0); + } - [Fact] - public void Policy_FloatOpsValidator_Test() - { - var validator = new FloatOpsValidator(); - var validateResult1 = ValidateContractCode(_badContractCode, validator); - validateResult1.Count.ShouldBeGreaterThan(0); - validateResult1.First().Message.ShouldContain("contains ldc.r8 float OpCode"); + [Fact] + public void Policy_FloatOpsValidator_Test() + { + var validator = new FloatOpsValidator(); + var validateResult1 = ValidateContractCode(_badContractCode, validator); + validateResult1.Count.ShouldBeGreaterThan(0); + validateResult1.First().Message.ShouldContain("contains ldc.r8 float OpCode"); - var validateResult2 = ValidateContractCode(_systemContractCode, validator); - validateResult2.Count.ShouldBe(0); - } + var validateResult2 = ValidateContractCode(_systemContractCode, validator); + validateResult2.Count.ShouldBe(0); + } - [Fact] - public void Policy_MultiDimArrayValidator_Test() - { - var validator = new MultiDimArrayValidator(); - var validateResult1 = ValidateContractCode(_badContractCode, validator); - validateResult1.Count.ShouldBe(1); + [Fact] + public void Policy_MultiDimArrayValidator_Test() + { + var validator = new MultiDimArrayValidator(); + var validateResult1 = ValidateContractCode(_badContractCode, validator); + validateResult1.Count.ShouldBe(1); - var validateResult2 = ValidateContractCode(_systemContractCode, validator); - validateResult2.Count.ShouldBe(0); - } + var validateResult2 = ValidateContractCode(_systemContractCode, validator); + validateResult2.Count.ShouldBe(0); + } - [Fact] - public void Policy_UncheckedMathValidator_Test() - { - var validator = new UncheckedMathValidator(); - var validateResult1 = ValidateContractCode(ReadContractCode(typeof(TestContract)), validator); - validateResult1.Count.ShouldBeGreaterThan(0); - validateResult1.First().Message.ShouldContain("contains unsafe OpCode add"); - } + [Fact] + public void Policy_UncheckedMathValidator_Test() + { + var validator = new UncheckedMathValidator(); + var validateResult1 = ValidateContractCode(ReadContractCode(typeof(TestContract)), validator); + validateResult1.Count.ShouldBeGreaterThan(0); + validateResult1.First().Message.ShouldContain("contains unsafe OpCode add"); + } - [Fact] - public void ContractAudit_NotInjectAndCheckObserverProxy_Test() - { - var code = ReadCode(typeof(TokenContract).Assembly.Location); - var changedCode = InjectCallReplacerCode(code); - var md = ModuleDefinition.ReadModule(new MemoryStream(changedCode)); + [Fact] + public void ContractAudit_NotInjectAndCheckObserverProxy_Test() + { + var code = ReadCode(typeof(TokenContract).Assembly.Location); + var changedCode = InjectCallReplacerCode(code); + var md = ModuleDefinition.ReadModule(new MemoryStream(changedCode)); - var observerValidator = new ObserverProxyValidator(); - var validateResult = observerValidator.Validate(md, new CancellationToken()); - validateResult.Count().ShouldBeGreaterThan(0); - } - - private static List ValidateContractCode(byte[] code, IValidator validator) - { - var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); - var validateList = new List(); - foreach (var typeInfo in modDef.Types) - { - foreach (var method in typeInfo.Methods) - { - var validateResult = validator.Validate(method, new CancellationToken()).ToList(); - var count = validateResult.Count(); - if (count != 0) - validateList.AddRange(validateResult); - } - } - - return validateList; - } + var observerValidator = new ObserverProxyValidator(); + var validateResult = observerValidator.Validate(md, new CancellationToken()); + validateResult.Count().ShouldBeGreaterThan(0); + } - private static byte[] ReadCode(string path) + private static List ValidateContractCode(byte[] code, IValidator validator) + { + var modDef = ModuleDefinition.ReadModule(new MemoryStream(code)); + var validateList = new List(); + foreach (var typeInfo in modDef.Types) + foreach (var method in typeInfo.Methods) { - return File.ReadAllBytes(path); + var validateResult = validator.Validate(method, new CancellationToken()).ToList(); + var count = validateResult.Count(); + if (count != 0) + validateList.AddRange(validateResult); } - - private static byte[] InjectCallReplacerCode(byte[] code) - { - var asm = AssemblyDefinition.ReadAssembly(new MemoryStream(code)); - var patcher = new MethodCallReplacer(); - patcher.Patch(asm.MainModule); - var newCode = new MemoryStream(); - asm.Write(newCode); - return newCode.ToArray(); - } + return validateList; + } + + private static byte[] ReadCode(string path) + { + return File.ReadAllBytes(path); + } + + private static byte[] InjectCallReplacerCode(byte[] code) + { + var asm = AssemblyDefinition.ReadAssembly(new MemoryStream(code)); + var patcher = new MethodCallReplacer(); + patcher.Patch(asm.MainModule); + + var newCode = new MemoryStream(); + asm.Write(newCode); + return newCode.ToArray(); } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Extensions/ExtensionTests.cs b/test/AElf.CSharp.CodeOps.Tests/Extensions/ExtensionTests.cs index ec8072cf4a..808d5ebf9b 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Extensions/ExtensionTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Extensions/ExtensionTests.cs @@ -6,81 +6,80 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Extensions +namespace AElf.CSharp.CodeOps.Extensions; + +public class ExtensionTests : CSharpCodeOpsTestBase { - public class ExtensionTests : CSharpCodeOpsTestBase + [Fact] + public void HasSameBodyTests() { - [Fact] - public void HasSameBodyTests() - { - var contractModule = GetModule(typeof(TestContract)); - var sdkModule = GetModule(typeof(StructuredState)); - var type1 = sdkModule.Types.First(t => t.Name == nameof(StructuredState)); - var type2 = contractModule.Types.First(t => t.Name == nameof(TestContractState)).BaseType.Resolve() - .BaseType.Resolve(); + var contractModule = GetModule(typeof(TestContract)); + var sdkModule = GetModule(typeof(StructuredState)); + var type1 = sdkModule.Types.First(t => t.Name == nameof(StructuredState)); + var type2 = contractModule.Types.First(t => t.Name == nameof(TestContractState)).BaseType.Resolve() + .BaseType.Resolve(); - // has same field - type1.HasSameFields(type2).ShouldBeTrue(); + // has same field + type1.HasSameFields(type2).ShouldBeTrue(); - for (int i = 0; i < type1.Methods.Count; i++) - { - type1.Methods[i].HasSameBody(type1.Methods[i]).ShouldBeTrue(); - type1.Methods[i].HasSameParameters(type1.Methods[i]).ShouldBeTrue(); - } - - var stateType = contractModule.Types.First(t => t.Name == nameof(TestContractState)); - stateType.IsStateImplementation().ShouldBeTrue(); - - var contractType = contractModule.Types.First(t => t.Name == nameof(TestContract)); - contractType.IsContractImplementation().ShouldBeTrue(); + for (var i = 0; i < type1.Methods.Count; i++) + { + type1.Methods[i].HasSameBody(type1.Methods[i]).ShouldBeTrue(); + type1.Methods[i].HasSameParameters(type1.Methods[i]).ShouldBeTrue(); } - [Fact] - public void GetFieldsTests() + var stateType = contractModule.Types.First(t => t.Name == nameof(TestContractState)); + stateType.IsStateImplementation().ShouldBeTrue(); + + var contractType = contractModule.Types.First(t => t.Name == nameof(TestContract)); + contractType.IsContractImplementation().ShouldBeTrue(); + } + + [Fact] + public void GetFieldsTests() + { + var contractModule = GetModule(typeof(TestContract)); + var type = contractModule.Types.First(t => t.Name == nameof(TestContract)); + var staticFields = type.GetResetableStaticFields(); + staticFields.Count().ShouldBe(2); + staticFields.ShouldContain(f => f.DeclaringType.Name == nameof(TestContract) && f.Name == "i"); + staticFields.ShouldContain(f => + f.DeclaringType.Name.Contains("TestNestClass") && f.Name == "k"); + + var contractType = contractModule.Types.First(t => t.Name == nameof(TestContract)); + var fields = contractType.GetAllFields(f => true); + fields.Count().ShouldBe(1); + fields.ShouldContain(f => f.Name == "i"); + } + + [Fact] + public void FindContractTests() + { { - var contractModule = GetModule(typeof(TestContract)); - var type = contractModule.Types.First(t => t.Name == nameof(TestContract)); - var staticFields = type.GetResetableStaticFields(); - staticFields.Count().ShouldBe(2); - staticFields.ShouldContain(f => f.DeclaringType.Name == nameof(TestContract) && f.Name == "i"); - staticFields.ShouldContain(f => - f.DeclaringType.Name.Contains("TestNestClass") && f.Name == "k"); - - var contractType = contractModule.Types.First(t => t.Name == nameof(TestContract)); - var fields = contractType.GetAllFields(f => true); - fields.Count().ShouldBe(1); - fields.ShouldContain(f => f.Name == "i"); + var code = ReadCode(Assembly.GetAssembly(typeof(StructuredState)).Location); + var asm = Assembly.Load(code); + Should.Throw(() => asm.FindContractContainer()); + asm.FindContractBaseType().ShouldBeNull(); + Should.Throw(() => asm.FindContractType().ShouldBeNull()); + asm.FindExecutionObserverProxyType().ShouldBeNull(); } - [Fact] - public void FindContractTests() { - { - var code = ReadCode(Assembly.GetAssembly(typeof(StructuredState)).Location); - var asm = Assembly.Load(code); - Should.Throw(() => asm.FindContractContainer()); - asm.FindContractBaseType().ShouldBeNull(); - Should.Throw(() => asm.FindContractType().ShouldBeNull()); - asm.FindExecutionObserverProxyType().ShouldBeNull(); - } - - { - var code = ReadContractCode(typeof(TestContract)); - var asm = Assembly.Load(code); - asm.FindContractContainer().ShouldNotBeNull(); - asm.FindContractBaseType().ShouldNotBeNull(); - asm.FindContractType().ShouldNotBeNull(); - asm.FindExecutionObserverProxyType().ShouldBeNull(); - } + var code = ReadContractCode(typeof(TestContract)); + var asm = Assembly.Load(code); + asm.FindContractContainer().ShouldNotBeNull(); + asm.FindContractBaseType().ShouldNotBeNull(); + asm.FindContractType().ShouldNotBeNull(); + asm.FindExecutionObserverProxyType().ShouldBeNull(); + } - { - var code = ReadPatchedContractCode(typeof(TestContract)); - var asm = Assembly.Load(code); - asm.FindContractContainer().ShouldNotBeNull(); - asm.FindContractBaseType().ShouldNotBeNull(); - asm.FindContractType().ShouldNotBeNull(); - asm.FindExecutionObserverProxyType().ShouldNotBeNull(); - } + { + var code = ReadPatchedContractCode(typeof(TestContract)); + var asm = Assembly.Load(code); + asm.FindContractContainer().ShouldNotBeNull(); + asm.FindContractBaseType().ShouldNotBeNull(); + asm.FindContractType().ShouldNotBeNull(); + asm.FindExecutionObserverProxyType().ShouldNotBeNull(); } } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Helper/AssemblyCompiler.cs b/test/AElf.CSharp.CodeOps.Tests/Helper/AssemblyCompiler.cs index c015a9f7f2..7f009e567b 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Helper/AssemblyCompiler.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Helper/AssemblyCompiler.cs @@ -5,37 +5,37 @@ using Microsoft.CodeAnalysis.CSharp; using Mono.Cecil; -namespace AElf.CSharp.CodeOps.Helper +namespace AElf.CSharp.CodeOps.Helper; + +public static class AssemblyCompiler { - public static class AssemblyCompiler + private static readonly Assembly[] References = + { + Assembly.Load("System.Runtime"), + typeof(object).Assembly + }; + + public static AssemblyDefinition Compile(string assemblyName, string code) { - private static readonly Assembly[] References = { - Assembly.Load("System.Runtime"), - typeof(object).Assembly - }; + var compilation = CSharpCompilation.Create( + assemblyName, + new[] { CSharpSyntaxTree.ParseText(code) }, + References.Select(r => MetadataReference.CreateFromFile(r.Location)), + new CSharpCompilationOptions( + OutputKind.DynamicallyLinkedLibrary, + checkOverflow: true, + optimizationLevel: OptimizationLevel.Release, + deterministic: true) + ); + + var dllStream = new MemoryStream(); + var emitResult = compilation.Emit(dllStream); - public static AssemblyDefinition Compile(string assemblyName, string code) - { - var compilation = CSharpCompilation.Create( - assemblyName, - new [] { CSharpSyntaxTree.ParseText(code)}, - References.Select(r => MetadataReference.CreateFromFile(r.Location)), - new CSharpCompilationOptions( - OutputKind.DynamicallyLinkedLibrary, - checkOverflow: true, - optimizationLevel: OptimizationLevel.Release, - deterministic: true) - ); - - var dllStream = new MemoryStream(); - var emitResult = compilation.Emit(dllStream); + if (!emitResult.Success) + return null; - if (!emitResult.Success) - return null; - - dllStream.Position = 0; + dllStream.Position = 0; - return AssemblyDefinition.ReadAssembly(dllStream); - } + return AssemblyDefinition.ReadAssembly(dllStream); } -} +} \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Instruction/InstructionInjectionValidatorTests.cs b/test/AElf.CSharp.CodeOps.Tests/Instruction/InstructionInjectionValidatorTests.cs index 15ab16be10..bc4db34e68 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Instruction/InstructionInjectionValidatorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Instruction/InstructionInjectionValidatorTests.cs @@ -5,33 +5,32 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Instruction +namespace AElf.CSharp.CodeOps.Instruction; + +public class InstructionInjectionValidatorTests : CSharpCodeOpsTestBase { - public class InstructionInjectionValidatorTests : CSharpCodeOpsTestBase + [Fact] + public void TestInstructionInjectionTest() { - [Fact] - public void TestInstructionInjectionTest() + // not patched + { + var instructionInjectionValidator = + new InstructionInjectionValidator(new StateWrittenInstructionInjector()); + var tokenContractModule = GetContractModule(typeof(TestContract)); + var validationResults = + instructionInjectionValidator.Validate(tokenContractModule, CancellationToken.None); + validationResults.ShouldContain(v => v.Info.Type == typeof(TestContract).FullName); + validationResults.ShouldContain(v => v.Info.Type.Contains(nameof(TestContract.TestNestClass))); + } + + // patched { - // not patched - { - var instructionInjectionValidator = - new InstructionInjectionValidator(new StateWrittenInstructionInjector()); - var tokenContractModule = GetContractModule(typeof(TestContract)); - var validationResults = - instructionInjectionValidator.Validate(tokenContractModule, CancellationToken.None); - validationResults.ShouldContain(v => v.Info.Type == typeof(TestContract).FullName); - validationResults.ShouldContain(v => v.Info.Type.Contains(nameof(TestContract.TestNestClass))); - } - - // patched - { - var instructionInjectionValidator = - new InstructionInjectionValidator(new StateWrittenInstructionInjector()); - var tokenContractModule = GetPatchedContractModule(typeof(TestContract)); - var validationResults = - instructionInjectionValidator.Validate(tokenContractModule, CancellationToken.None); - validationResults.ShouldBeEmpty(); - } + var instructionInjectionValidator = + new InstructionInjectionValidator(new StateWrittenInstructionInjector()); + var tokenContractModule = GetPatchedContractModule(typeof(TestContract)); + var validationResults = + instructionInjectionValidator.Validate(tokenContractModule, CancellationToken.None); + validationResults.ShouldBeEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Instruction/StateWrittenInstructionInjectorTests.cs b/test/AElf.CSharp.CodeOps.Tests/Instruction/StateWrittenInstructionInjectorTests.cs index 1e88e0b5ef..de351519d8 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Instruction/StateWrittenInstructionInjectorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Instruction/StateWrittenInstructionInjectorTests.cs @@ -7,92 +7,92 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Instruction +namespace AElf.CSharp.CodeOps.Instruction; + +public class StateWrittenInstructionInjectorTests : CSharpCodeOpsTestBase { - public class StateWrittenInstructionInjectorTests : CSharpCodeOpsTestBase + private readonly StateWrittenInstructionInjector _stateWrittenInstructionInjector; + + public StateWrittenInstructionInjectorTests() + { + _stateWrittenInstructionInjector = GetRequiredService(); + } + + [Fact] + public void IdentifyInstruction_Tests() { - private readonly StateWrittenInstructionInjector _stateWrittenInstructionInjector; + var testContractModule = GetContractModule(typeof(TestContract)); + var tokenContractTypeDef = + testContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); + var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); - public StateWrittenInstructionInjectorTests() + var identifyResult = createMethod.Body.Instructions + .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); + identifyResult.Count.ShouldBe(3); { - _stateWrittenInstructionInjector = GetRequiredService(); + var methodReference = (MethodReference)identifyResult[0].Operand; + ((GenericInstanceType)methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName + .ShouldBe(typeof(ProtobufMessage).FullName); } - [Fact] - public void IdentifyInstruction_Tests() { - var testContractModule = GetContractModule(typeof(TestContract)); - var tokenContractTypeDef = testContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); - var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); - - var identifyResult = createMethod.Body.Instructions - .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); - identifyResult.Count.ShouldBe(3); - { - var methodReference = (MethodReference) identifyResult[0].Operand; - ((GenericInstanceType) methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName - .ShouldBe(typeof(ProtobufMessage).FullName); - } - - { - var methodReference = (MethodReference) identifyResult[1].Operand; - ((GenericInstanceType) methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName - .ShouldBe(typeof(Address).FullName); - } - - { - var methodReference = (MethodReference) identifyResult[2].Operand; - ((GenericInstanceType) methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName - .ShouldBe(typeof(string).FullName); - } + var methodReference = (MethodReference)identifyResult[1].Operand; + ((GenericInstanceType)methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName + .ShouldBe(typeof(Address).FullName); } - - [Fact] - public void InjectInstruction_Tests() { - var tokenContractModule = GetContractModule(typeof(TestContract)); - var tokenContractTypeDef = - tokenContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); - var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); + var methodReference = (MethodReference)identifyResult[2].Operand; + ((GenericInstanceType)methodReference.DeclaringType).GenericArguments.Last().Resolve().FullName + .ShouldBe(typeof(string).FullName); + } + } - var identifyResult = createMethod.Body.Instructions - .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); - var ilProcessor = createMethod.Body.GetILProcessor(); - var instructionToInject = identifyResult.First(); - _stateWrittenInstructionInjector.InjectInstruction(ilProcessor, instructionToInject, tokenContractModule); + [Fact] + public void InjectInstruction_Tests() + { + var tokenContractModule = GetContractModule(typeof(TestContract)); + var tokenContractTypeDef = + tokenContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); + var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); - var callInstruction = instructionToInject.Previous; - ((MethodReference) callInstruction.Operand).Name.ShouldBe(nameof(CSharpSmartContractContext - .ValidateStateSize)); - } + var identifyResult = createMethod.Body.Instructions + .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); - [Fact] - public void ValidateInstruction_Tests() + var ilProcessor = createMethod.Body.GetILProcessor(); + var instructionToInject = identifyResult.First(); + _stateWrittenInstructionInjector.InjectInstruction(ilProcessor, instructionToInject, tokenContractModule); + + var callInstruction = instructionToInject.Previous; + ((MethodReference)callInstruction.Operand).Name.ShouldBe(nameof(CSharpSmartContractContext + .ValidateStateSize)); + } + + [Fact] + public void ValidateInstruction_Tests() + { + var tokenContractModule = GetContractModule(typeof(TestContract)); + var tokenContractTypeDef = + tokenContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); + var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); + + var identifyResult = createMethod.Body.Instructions + .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); + + var ilProcessor = createMethod.Body.GetILProcessor(); + var instructionToInject = identifyResult.First(); + + { + var validationResult = + _stateWrittenInstructionInjector.ValidateInstruction(tokenContractModule, instructionToInject); + validationResult.ShouldBeFalse(); + } + _stateWrittenInstructionInjector.InjectInstruction(ilProcessor, instructionToInject, tokenContractModule); { - var tokenContractModule = GetContractModule(typeof(TestContract)); - var tokenContractTypeDef = - tokenContractModule.GetType("AElf.Runtime.CSharp.Tests.TestContract", nameof(TestContract)); - var createMethod = tokenContractTypeDef.Methods.First(m => m.Name == nameof(TestContract.TestStateType)); - - var identifyResult = createMethod.Body.Instructions - .Where(i => _stateWrittenInstructionInjector.IdentifyInstruction(i)).ToList(); - - var ilProcessor = createMethod.Body.GetILProcessor(); - var instructionToInject = identifyResult.First(); - - { - var validationResult = - _stateWrittenInstructionInjector.ValidateInstruction(tokenContractModule, instructionToInject); - validationResult.ShouldBeFalse(); - } - _stateWrittenInstructionInjector.InjectInstruction(ilProcessor, instructionToInject, tokenContractModule); - { - var validationResult = - _stateWrittenInstructionInjector.ValidateInstruction(tokenContractModule, instructionToInject); - validationResult.ShouldBeTrue(); - } + var validationResult = + _stateWrittenInstructionInjector.ValidateInstruction(tokenContractModule, instructionToInject); + validationResult.ShouldBeTrue(); } } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Patch/ExecutionObserverInjectorTests.cs b/test/AElf.CSharp.CodeOps.Tests/Patch/ExecutionObserverInjectorTests.cs index 79dc7537dd..af6642a175 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Patch/ExecutionObserverInjectorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Patch/ExecutionObserverInjectorTests.cs @@ -5,51 +5,48 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Patch +namespace AElf.CSharp.CodeOps.Patch; + +public class ExecutionObserverInjectorTests : CSharpCodeOpsTestBase { - public class ExecutionObserverInjectorTests : CSharpCodeOpsTestBase + [Fact] + public void ConstructCounterProxyTest() { - [Fact] - public void ConstructCounterProxyTest() - { - var module = GetContractModule(typeof(TestContract)); - var ns = "AElf.CSharp.CodeOps"; - var typeDefinition = ExecutionObserverInjector.ConstructCounterProxy(module, ns); - typeDefinition.Methods.Count.ShouldBe(3); - typeDefinition.Methods.Select(method => method.DeclaringType.FullName) - .ShouldAllBe(name => name == string.Concat(ns, ".", nameof(ExecutionObserverProxy))); - new[] - { - nameof(ExecutionObserverProxy.SetObserver), nameof(ExecutionObserverProxy.BranchCount), - nameof(ExecutionObserverProxy.CallCount) - }.ShouldAllBe(name => typeDefinition.Methods.Select(method => method.Name).Contains(name)); - } - - [Fact] - public void ExecutionObserverInjectorPatchTest() - { - var module = GetContractModule(typeof(TestContract)); - - var typeDefinition = ExecutionObserverInjector.ConstructCounterProxy(module, "AElf.Test"); - - var executionObserverInjector = new ExecutionObserverInjector(); - executionObserverInjector.Patch(module); - var typePatched = module.Types.Single(t => t.Name == nameof(ExecutionObserverProxy)); - typePatched.HasSameFields(typeDefinition).ShouldBeTrue(); - - foreach (var method in typePatched.Methods) - { - method.HasSameBody(typeDefinition.Methods.Single(m => m.Name == method.Name)).ShouldBeTrue(); - } - } - - [Fact] - public void ExecutionObserverInjectorPatchTest2() + var module = GetContractModule(typeof(TestContract)); + var ns = "AElf.CSharp.CodeOps"; + var typeDefinition = ExecutionObserverInjector.ConstructCounterProxy(module, ns); + typeDefinition.Methods.Count.ShouldBe(3); + typeDefinition.Methods.Select(method => method.DeclaringType.FullName) + .ShouldAllBe(name => name == string.Concat(ns, ".", nameof(ExecutionObserverProxy))); + new[] { - var module = GetContractModule(typeof(BadContract)); + nameof(ExecutionObserverProxy.SetObserver), nameof(ExecutionObserverProxy.BranchCount), + nameof(ExecutionObserverProxy.CallCount) + }.ShouldAllBe(name => typeDefinition.Methods.Select(method => method.Name).Contains(name)); + } + + [Fact] + public void ExecutionObserverInjectorPatchTest() + { + var module = GetContractModule(typeof(TestContract)); + + var typeDefinition = ExecutionObserverInjector.ConstructCounterProxy(module, "AElf.Test"); + + var executionObserverInjector = new ExecutionObserverInjector(); + executionObserverInjector.Patch(module); + var typePatched = module.Types.Single(t => t.Name == nameof(ExecutionObserverProxy)); + typePatched.HasSameFields(typeDefinition).ShouldBeTrue(); + + foreach (var method in typePatched.Methods) + method.HasSameBody(typeDefinition.Methods.Single(m => m.Name == method.Name)).ShouldBeTrue(); + } + + [Fact] + public void ExecutionObserverInjectorPatchTest2() + { + var module = GetContractModule(typeof(BadContract)); - var executionObserverInjector = new ExecutionObserverInjector(); - executionObserverInjector.Patch(module); - } + var executionObserverInjector = new ExecutionObserverInjector(); + executionObserverInjector.Patch(module); } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Patch/MethodCallReplacerTests.cs b/test/AElf.CSharp.CodeOps.Tests/Patch/MethodCallReplacerTests.cs index f584d66517..33bb7fb0c4 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Patch/MethodCallReplacerTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Patch/MethodCallReplacerTests.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using AElf.CSharp.CodeOps.Patchers.Module; using AElf.Runtime.CSharp.Tests.TestContract; @@ -9,75 +8,75 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Patch +namespace AElf.CSharp.CodeOps.Patch; + +public class MethodCallReplacerTests : CSharpCodeOpsTestBase { - public class MethodCallReplacerTests : CSharpCodeOpsTestBase + [Fact] + public void MethodCallReplacer_StringConcat_Test() { - [Fact] - public void MethodCallReplacer_StringConcat_Test() + var module = GetContractModule(typeof(TestContract)); { - var module = GetContractModule(typeof(TestContract)); - { - var m = module.Types.Single(t => t.Name == nameof(TestContractReflection)).GetStaticConstructor(); - var res = ContainsMethodCall(m, - GetModule(typeof(AElfString)).Types.Single(t => t.FullName == typeof(AElfString).FullName).Methods - .First(m => m.Name == nameof(string.Concat))); - res.ShouldBeFalse(); - } - - var replacer = new MethodCallReplacer(); - replacer.Patch(module); - - { - var m = module.Types.Single(t => t.Name == nameof(TestContractReflection)).GetStaticConstructor(); - var res = ContainsMethodCall(m, - GetModule(typeof(AElfString)).Types.Single(t => t.FullName == typeof(AElfString).FullName).Methods - .First(m => m.Name == nameof(string.Concat))); - res.ShouldBeTrue(); - } + var m = module.Types.Single(t => t.Name == nameof(TestContractReflection)).GetStaticConstructor(); + var res = ContainsMethodCall(m, + GetModule(typeof(AElfString)).Types.Single(t => t.FullName == typeof(AElfString).FullName).Methods + .First(m => m.Name == nameof(string.Concat))); + res.ShouldBeFalse(); } - [Fact] - public void MethodCallReplacer_MathOperator_Test() + var replacer = new MethodCallReplacer(); + replacer.Patch(module); + + { + var m = module.Types.Single(t => t.Name == nameof(TestContractReflection)).GetStaticConstructor(); + var res = ContainsMethodCall(m, + GetModule(typeof(AElfString)).Types.Single(t => t.FullName == typeof(AElfString).FullName).Methods + .First(m => m.Name == nameof(string.Concat))); + res.ShouldBeTrue(); + } + } + + [Fact] + public void MethodCallReplacer_MathOperator_Test() + { + var module = GetContractModule(typeof(TestContract)); { - var module = GetContractModule(typeof(TestContract)); - { - var res = ContainsMathOpCode( - GetModule(typeof(TestContract)).Types.Single(t => t.FullName == typeof(TestContract).FullName) - .Methods - .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add); - res.ShouldBeTrue(); - } - - var replacer = new MethodCallReplacer(); - replacer.Patch(module); - - { - var res = ContainsMathOpCode( - module.Types.Single(t => t.FullName == typeof(TestContract).FullName) - .Methods - .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add); - res.ShouldBeFalse(); - } - - { - var res = ContainsMathOpCode( - module.Types.Single(t => t.FullName == typeof(TestContract).FullName) - .Methods - .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add_Ovf); - res.ShouldBeTrue(); - } + var res = ContainsMathOpCode( + GetModule(typeof(TestContract)).Types.Single(t => t.FullName == typeof(TestContract).FullName) + .Methods + .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add); + res.ShouldBeTrue(); } - private bool ContainsMethodCall(MethodDefinition methodDefinition, MethodDefinition expected) + var replacer = new MethodCallReplacer(); + replacer.Patch(module); + { - return methodDefinition.Body.Instructions.Any(i => - i.Operand is MethodReference method && method.DeclaringType.FullName == expected.DeclaringType.FullName && method.Name == expected.Name); + var res = ContainsMathOpCode( + module.Types.Single(t => t.FullName == typeof(TestContract).FullName) + .Methods + .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add); + res.ShouldBeFalse(); } - private bool ContainsMathOpCode(MethodDefinition methodDefinition, OpCode opCode) { - return methodDefinition.Body.Instructions.Any(i => i.OpCode == opCode); + var res = ContainsMathOpCode( + module.Types.Single(t => t.FullName == typeof(TestContract).FullName) + .Methods + .First(m => m.Name == nameof(TestContract.TestStateType)), OpCodes.Add_Ovf); + res.ShouldBeTrue(); } } + + private bool ContainsMethodCall(MethodDefinition methodDefinition, MethodDefinition expected) + { + return methodDefinition.Body.Instructions.Any(i => + i.Operand is MethodReference method && method.DeclaringType.FullName == expected.DeclaringType.FullName && + method.Name == expected.Name); + } + + private bool ContainsMathOpCode(MethodDefinition methodDefinition, OpCode opCode) + { + return methodDefinition.Body.Instructions.Any(i => i.OpCode == opCode); + } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Patch/ResetFieldsMethodInjectorTests.cs b/test/AElf.CSharp.CodeOps.Tests/Patch/ResetFieldsMethodInjectorTests.cs index 2d42fb77bf..f840ed177c 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Patch/ResetFieldsMethodInjectorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Patch/ResetFieldsMethodInjectorTests.cs @@ -6,93 +6,94 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Patch +namespace AElf.CSharp.CodeOps.Patch; + +public class ResetFieldsMethodInjectorTests : CSharpCodeOpsTestBase { - public class ResetFieldsMethodInjectorTests : CSharpCodeOpsTestBase + [Fact] + public void ResetFields_Static_Test() { - [Fact] - public void ResetFields_Static_Test() + var module = GetContractModule(typeof(TestContract)); + { + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); + var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeFalse(); + } + + { + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); + var nestTypeDefinition = + typeDefinition.NestedTypes.Single(t => t.Name == nameof(TestContract.TestNestClass)); + var resetMethodExists = nestTypeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeFalse(); + } + + { + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContractState)); + var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeFalse(); + } + + var resetMethodInjector = new ResetFieldsMethodInjector(); + resetMethodInjector.Patch(module); + { - var module = GetContractModule(typeof(TestContract)); + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); + var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeTrue(); + var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); + var instructions = method.Body.Instructions; { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); - var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeFalse(); + var resetFiled = instructions.Any(i => + i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && + fieldDefinition.Name == "i"); + resetFiled.ShouldBeTrue(); } - + } + + { + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); + var nestTypeDefinition = + typeDefinition.NestedTypes.Single(t => t.Name == nameof(TestContract.TestNestClass)); + var resetMethodExists = nestTypeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeTrue(); + var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); + var instructions = method.Body.Instructions; + { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); - var nestTypeDefinition = typeDefinition.NestedTypes.Single(t => t.Name == nameof(TestContract.TestNestClass)); - var resetMethodExists = nestTypeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeFalse(); + var resetFiled = instructions.Any(i => + i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && + fieldDefinition.Name == "i"); + resetFiled.ShouldBeTrue(); } - + { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContractState)); - var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeFalse(); + var resetFiled = instructions.Any(i => + i.OpCode == OpCodes.Stfld && i.Operand is FieldDefinition fieldDefinition && + fieldDefinition.Name == "j"); + resetFiled.ShouldBeFalse(); } - - var resetMethodInjector = new ResetFieldsMethodInjector(); - resetMethodInjector.Patch(module); - + } + + { + var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContractState)); + var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); + resetMethodExists.ShouldBeTrue(); + var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); + var instructions = method.Body.Instructions; + { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); - var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeTrue(); - var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); - var instructions = method.Body.Instructions; - { - var resetFiled = instructions.Any(i => - i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && - fieldDefinition.Name == "i"); - resetFiled.ShouldBeTrue(); - } + var resetFiled = instructions.Any(i => + i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && + fieldDefinition.Name == "boolState"); + resetFiled.ShouldBeTrue(); } - - { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContract)); - var nestTypeDefinition = typeDefinition.NestedTypes.Single(t => t.Name == nameof(TestContract.TestNestClass)); - var resetMethodExists = nestTypeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeTrue(); - var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); - var instructions = method.Body.Instructions; - { - var resetFiled = instructions.Any(i => - i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && - fieldDefinition.Name == "i"); - resetFiled.ShouldBeTrue(); - } - - { - var resetFiled = instructions.Any(i => - i.OpCode == OpCodes.Stfld && i.Operand is FieldDefinition fieldDefinition && - fieldDefinition.Name == "j"); - resetFiled.ShouldBeFalse(); - } - } - { - var typeDefinition = module.Types.Single(t => t.Name == nameof(TestContractState)); - var resetMethodExists = typeDefinition.Methods.Any(m => m.Name == "ResetFields"); - resetMethodExists.ShouldBeTrue(); - var method = typeDefinition.Methods.Single(m => m.Name == "ResetFields"); - var instructions = method.Body.Instructions; - - { - var resetFiled = instructions.Any(i => - i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && - fieldDefinition.Name == "boolState"); - resetFiled.ShouldBeTrue(); - } - - { - var resetFiled = instructions.Any(i => - i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && - fieldDefinition.Name == "boolState2"); - resetFiled.ShouldBeFalse(); - } + var resetFiled = instructions.Any(i => + i.OpCode == OpCodes.Stsfld && i.Operand is FieldDefinition fieldDefinition && + fieldDefinition.Name == "boolState2"); + resetFiled.ShouldBeFalse(); } } } diff --git a/test/AElf.CSharp.CodeOps.Tests/TestCSharpCodeOpsAElfModule.cs b/test/AElf.CSharp.CodeOps.Tests/TestCSharpCodeOpsAElfModule.cs index e610e7eacb..3d967e90f6 100644 --- a/test/AElf.CSharp.CodeOps.Tests/TestCSharpCodeOpsAElfModule.cs +++ b/test/AElf.CSharp.CodeOps.Tests/TestCSharpCodeOpsAElfModule.cs @@ -4,19 +4,18 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.CSharp.CodeOps +namespace AElf.CSharp.CodeOps; + +[DependsOn( + typeof(CSharpRuntimeAElfModule), + typeof(SmartContractTestAElfModule), + typeof(CSharpCodeOpsAElfModule) +)] +public class TestCSharpCodeOpsAElfModule : AElfModule { - [DependsOn( - typeof(CSharpRuntimeAElfModule), - typeof(SmartContractTestAElfModule), - typeof(CSharpCodeOpsAElfModule) - )] - public class TestCSharpCodeOpsAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); } -} +} \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/Validators/Method/ArrayValidatorTests.cs b/test/AElf.CSharp.CodeOps.Tests/Validators/Method/ArrayValidatorTests.cs index 4c3c526d6d..c8e0a5a40d 100644 --- a/test/AElf.CSharp.CodeOps.Tests/Validators/Method/ArrayValidatorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/Validators/Method/ArrayValidatorTests.cs @@ -1,45 +1,40 @@ using System.Collections.Generic; -using System.Linq; using System.Threading; using AElf.Runtime.CSharp.Tests.BadContract; using Mono.Cecil; using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.Validators.Method +namespace AElf.CSharp.CodeOps.Validators.Method; + +public class ArrayValidatorTests : CSharpCodeOpsTestBase { - public class ArrayValidatorTests : CSharpCodeOpsTestBase + [Fact] + public void Validate_Test() { - [Fact] - public void Validate_Test() - { - var badContractModule = GetContractModule(typeof(BadContract)); - var validationResults = new List(); - - var cts = new CancellationTokenSource(); - cts.Cancel(); - Assert.Throws(() => Validate(badContractModule, validationResults, cts.Token)); + var badContractModule = GetContractModule(typeof(BadContract)); + var validationResults = new List(); + + var cts = new CancellationTokenSource(); + cts.Cancel(); + Assert.Throws(() => Validate(badContractModule, validationResults, cts.Token)); - Validate(badContractModule, validationResults, CancellationToken.None); - - validationResults.ShouldContain(r=>r.Message.Contains("Array size can not be larger than 40960 bytes")); - validationResults.ShouldContain(r=>r.Message.Contains("Array size is too large that causes overflow when estimating memory usage")); - validationResults.ShouldContain(r=>r.Message.Contains("Array size can not be larger than 5 elements")); - validationResults.ShouldContain(r=>r.Message.Contains("Array of System.Int32[] type is not allowed.")); - validationResults.ShouldContain(r=>r.Message.Contains("Array size could not be identified for System.Int32")); - } + Validate(badContractModule, validationResults, CancellationToken.None); - private void Validate(ModuleDefinition moduleDefinition, List validationResults, - CancellationToken token) - { - var validator = new ArrayValidator(); - foreach (var type in moduleDefinition.Types) - { - foreach (var method in type.Methods) - { - validationResults.AddRange(validator.Validate(method, token)); - } - } - } + validationResults.ShouldContain(r => r.Message.Contains("Array size can not be larger than 40960 bytes")); + validationResults.ShouldContain(r => + r.Message.Contains("Array size is too large that causes overflow when estimating memory usage")); + validationResults.ShouldContain(r => r.Message.Contains("Array size can not be larger than 5 elements")); + validationResults.ShouldContain(r => r.Message.Contains("Array of System.Int32[] type is not allowed.")); + validationResults.ShouldContain(r => r.Message.Contains("Array size could not be identified for System.Int32")); + } + + private void Validate(ModuleDefinition moduleDefinition, List validationResults, + CancellationToken token) + { + var validator = new ArrayValidator(); + foreach (var type in moduleDefinition.Types) + foreach (var method in type.Methods) + validationResults.AddRange(validator.Validate(method, token)); } } \ No newline at end of file diff --git a/test/AElf.CSharp.CodeOps.Tests/whitelist/WhitelistValidatorTests.cs b/test/AElf.CSharp.CodeOps.Tests/whitelist/WhitelistValidatorTests.cs index de30ed553c..ebf80aebac 100644 --- a/test/AElf.CSharp.CodeOps.Tests/whitelist/WhitelistValidatorTests.cs +++ b/test/AElf.CSharp.CodeOps.Tests/whitelist/WhitelistValidatorTests.cs @@ -8,54 +8,54 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.CodeOps.whitelist +namespace AElf.CSharp.CodeOps.whitelist; + +public class WhitelistValidatorTests : CSharpCodeOpsTestBase { - public class WhitelistValidatorTests : CSharpCodeOpsTestBase + [Fact] + public void TestWhitelistValidationTest() { - [Fact] - public void TestWhitelistValidationTest() - { - var badContractModule = GetContractModule(typeof(BadContract)); - var validator = new WhitelistValidator(new WhitelistProvider()); - var validationResults = validator.Validate(badContractModule, CancellationToken.None); - // assembly - validationResults.ShouldContain(v => - v.Message == "Assembly AElf.Kernel.Core is not allowed."); - - validationResults.ShouldNotContain(v => v.Info != null && - v.Info.ReferencingMethod.Contains("get_AllowedListField")); - - validationResults.ShouldContain(v => v.Info != null && - v.Info.ReferencingMethod.Contains("get_DeniedListField")); - validationResults.ShouldContain(v => v.Info != null && - v.Info.Namespace == "System.Reflection" && - v.Info.Type.Contains(nameof(Assembly)) && - v.Info.ReferencingMethod.Contains("get_AssemblyField")); - validationResults.ShouldNotContain(v => v.Info != null && - v.Info.Namespace == "System.Reflection" && - v.Info.Type.Contains(nameof(AssemblyCompanyAttribute))); - - validationResults.ShouldContain(v => - v.Info != null && v.Info.ReferencingMethod.Contains("get_RandomArray")); - - validationResults.ShouldContain(v => - v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(DateTime)) && - v.Info.Member.Contains("get_Today")); - - validationResults.ShouldNotContain(v => - v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(Encoding)) && - v.Info.Member.Contains("get_UTF8")); - - validationResults.ShouldContain(v => - v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(Environment)) && - v.Info.Member.Contains("get_CurrentManagedThreadId")); - - validationResults.ShouldContain(v => v.Info != null && - v.Info.Namespace == "System.Reflection" && - v.Info.Type.Contains(nameof(Assembly))); - - validationResults.ShouldContain(v => - v.Info != null && v.Info.Member == nameof(SecretSharingHelper.DecodeSecret) && v.Info.Type == (nameof(SecretSharingHelper))); - } + var badContractModule = GetContractModule(typeof(BadContract)); + var validator = new WhitelistValidator(new WhitelistProvider()); + var validationResults = validator.Validate(badContractModule, CancellationToken.None); + // assembly + validationResults.ShouldContain(v => + v.Message == "Assembly AElf.Kernel.Core is not allowed."); + + validationResults.ShouldNotContain(v => v.Info != null && + v.Info.ReferencingMethod.Contains("get_AllowedListField")); + + validationResults.ShouldContain(v => v.Info != null && + v.Info.ReferencingMethod.Contains("get_DeniedListField")); + validationResults.ShouldContain(v => v.Info != null && + v.Info.Namespace == "System.Reflection" && + v.Info.Type.Contains(nameof(Assembly)) && + v.Info.ReferencingMethod.Contains("get_AssemblyField")); + validationResults.ShouldNotContain(v => v.Info != null && + v.Info.Namespace == "System.Reflection" && + v.Info.Type.Contains(nameof(AssemblyCompanyAttribute))); + + validationResults.ShouldContain(v => + v.Info != null && v.Info.ReferencingMethod.Contains("get_RandomArray")); + + validationResults.ShouldContain(v => + v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(DateTime)) && + v.Info.Member.Contains("get_Today")); + + validationResults.ShouldNotContain(v => + v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(Encoding)) && + v.Info.Member.Contains("get_UTF8")); + + validationResults.ShouldContain(v => + v.Info != null && v.Info.Member != null && v.Info.Type.Contains(nameof(Environment)) && + v.Info.Member.Contains("get_CurrentManagedThreadId")); + + validationResults.ShouldContain(v => v.Info != null && + v.Info.Namespace == "System.Reflection" && + v.Info.Type.Contains(nameof(Assembly))); + + validationResults.ShouldContain(v => + v.Info != null && v.Info.Member == nameof(SecretSharingHelper.DecodeSecret) && + v.Info.Type == nameof(SecretSharingHelper)); } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/AElf.CSharp.Core.Tests.csproj b/test/AElf.CSharp.Core.Tests/AElf.CSharp.Core.Tests.csproj index 8aaf7fe410..d39e167f0c 100644 --- a/test/AElf.CSharp.Core.Tests/AElf.CSharp.Core.Tests.csproj +++ b/test/AElf.CSharp.Core.Tests/AElf.CSharp.Core.Tests.csproj @@ -4,15 +4,15 @@ false - - + + - - - - - - + + + + + + \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/Extension/TimestampExtensionsTests.cs b/test/AElf.CSharp.Core.Tests/Extension/TimestampExtensionsTests.cs index c8868fda9f..309d1d934a 100644 --- a/test/AElf.CSharp.Core.Tests/Extension/TimestampExtensionsTests.cs +++ b/test/AElf.CSharp.Core.Tests/Extension/TimestampExtensionsTests.cs @@ -2,18 +2,17 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.Core.Extension +namespace AElf.CSharp.Core.Extension; + +public class TimestampExtensionsTests { - public class TimestampExtensionsTests + [Fact] + public void Milliseconds_Test() { - [Fact] - public void Milliseconds_Test() - { - var duration = new Duration {Seconds = long.MaxValue / 1000 + 1}; - duration.Milliseconds().ShouldBe(long.MaxValue); + var duration = new Duration { Seconds = long.MaxValue / 1000 + 1 }; + duration.Milliseconds().ShouldBe(long.MaxValue); - duration = new Duration {Seconds = 10, Nanos = 1000000}; - duration.Milliseconds().ShouldBe(10001); - } + duration = new Duration { Seconds = 10, Nanos = 1000000 }; + duration.Milliseconds().ShouldBe(10001); } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/MarshallerTests.cs b/test/AElf.CSharp.Core.Tests/MarshallerTests.cs index 4a55a4d8e1..4d160f6e12 100644 --- a/test/AElf.CSharp.Core.Tests/MarshallerTests.cs +++ b/test/AElf.CSharp.Core.Tests/MarshallerTests.cs @@ -1,20 +1,19 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public class MarshallerTests : TypesCSharpTestBase { - public class MarshallerTests : TypesCSharpTestBase + [Fact] + public void StringMarshall_Test() { - [Fact] - public void StringMarshall_Test() - { - var stringMarshall = Marshallers.StringMarshaller; - var stringValue = "test"; - var byteArray = stringMarshall.Serializer(stringValue); - byteArray.ShouldNotBeNull(); - - var result = stringMarshall.Deserializer(byteArray); - result.ShouldBe(stringValue); - } + var stringMarshall = Marshallers.StringMarshaller; + var stringValue = "test"; + var byteArray = stringMarshall.Serializer(stringValue); + byteArray.ShouldNotBeNull(); + + var result = stringMarshall.Deserializer(byteArray); + result.ShouldBe(stringValue); } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/MethodTests.cs b/test/AElf.CSharp.Core.Tests/MethodTests.cs index 87657a8ced..39de46c797 100644 --- a/test/AElf.CSharp.Core.Tests/MethodTests.cs +++ b/test/AElf.CSharp.Core.Tests/MethodTests.cs @@ -4,29 +4,30 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public class MethodTests : TypesCSharpTestBase { - public class MethodTests : TypesCSharpTestBase + [Fact] + public void Method_Test() { - [Fact] - public void Method_Test() - { - var method = CreateMethod(); - - method.ServiceName.ShouldBe(nameof(TestContract)); - method.Type.ShouldBe(MethodType.Action); - } - - private Method CreateMethod() - { - Func serializer = input => input.ToByteArray(); - Func deserializer = input => StringInput.Parser.ParseFrom(input); - - Func serializer1 = input => input.ToByteArray(); - Func deserializer1 = input => StringOutput.Parser.ParseFrom(input); - - return new Method(MethodType.Action, nameof(TestContract), nameof(TestContract.TestStringState), - new Marshaller(serializer, deserializer), new Marshaller(serializer1, deserializer1)); - } + var method = CreateMethod(); + + method.ServiceName.ShouldBe(nameof(TestContract)); + method.Type.ShouldBe(MethodType.Action); + } + + private Method CreateMethod() + { + Func serializer = input => input.ToByteArray(); + Func deserializer = input => StringInput.Parser.ParseFrom(input); + + Func serializer1 = input => input.ToByteArray(); + Func deserializer1 = input => StringOutput.Parser.ParseFrom(input); + + return new Method(MethodType.Action, nameof(TestContract), + nameof(TestContract.TestStringState), + new Marshaller(serializer, deserializer), + new Marshaller(serializer1, deserializer1)); } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/PreconditionsTests.cs b/test/AElf.CSharp.Core.Tests/PreconditionsTests.cs index 36e9c6011e..2382379a5f 100644 --- a/test/AElf.CSharp.Core.Tests/PreconditionsTests.cs +++ b/test/AElf.CSharp.Core.Tests/PreconditionsTests.cs @@ -3,21 +3,20 @@ using Shouldly; using Xunit; -namespace AElf.CSharp.Core.Utils +namespace AElf.CSharp.Core.Utils; + +public class PreconditionsTests { - public class PreconditionsTests + [Fact] + public void PreCondition_Check_Test() { - [Fact] - public void PreCondition_Check_Test() - { - Func func = null; - Should.Throw(() => Preconditions.CheckNotNull(func)); - Should.Throw(() => Preconditions.CheckNotNull(func, nameof(func))).Message - .ShouldContain(nameof(func)); - - func = address => address.ToBase58(); - Preconditions.CheckNotNull(func).ShouldBe(func); - Preconditions.CheckNotNull(func, nameof(func)).ShouldBe(func); - } + Func func = null; + Should.Throw(() => Preconditions.CheckNotNull(func)); + Should.Throw(() => Preconditions.CheckNotNull(func, nameof(func))).Message + .ShouldContain(nameof(func)); + + func = address => address.ToBase58(); + Preconditions.CheckNotNull(func).ShouldBe(func); + Preconditions.CheckNotNull(func, nameof(func)).ShouldBe(func); } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/TypesCSharpTestAElfModule.cs b/test/AElf.CSharp.Core.Tests/TypesCSharpTestAElfModule.cs index 07220c4c4c..c1785cc30a 100644 --- a/test/AElf.CSharp.Core.Tests/TypesCSharpTestAElfModule.cs +++ b/test/AElf.CSharp.Core.Tests/TypesCSharpTestAElfModule.cs @@ -1,8 +1,7 @@ using AElf.Modularity; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public class TypesCSharpTestAElfModule : AElfModule { - public class TypesCSharpTestAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/test/AElf.CSharp.Core.Tests/TypesCSharpTestBase.cs b/test/AElf.CSharp.Core.Tests/TypesCSharpTestBase.cs index 4e9c0e58db..a9117d814a 100644 --- a/test/AElf.CSharp.Core.Tests/TypesCSharpTestBase.cs +++ b/test/AElf.CSharp.Core.Tests/TypesCSharpTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.CSharp.Core +namespace AElf.CSharp.Core; + +public class TypesCSharpTestBase : AElfIntegratedTest { - public class TypesCSharpTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.ContractDeployer.Tests/AElf.ContractDeployer.Tests.csproj b/test/AElf.ContractDeployer.Tests/AElf.ContractDeployer.Tests.csproj index b937b1d4fe..997ea691c8 100644 --- a/test/AElf.ContractDeployer.Tests/AElf.ContractDeployer.Tests.csproj +++ b/test/AElf.ContractDeployer.Tests/AElf.ContractDeployer.Tests.csproj @@ -5,16 +5,16 @@ AElf.ContractDeployer - - - - - - + + + + + + - - + + diff --git a/test/AElf.ContractDeployer.Tests/ContractDeployerTestAElfModule.cs b/test/AElf.ContractDeployer.Tests/ContractDeployerTestAElfModule.cs index a7fcf0dafb..593414a5ae 100644 --- a/test/AElf.ContractDeployer.Tests/ContractDeployerTestAElfModule.cs +++ b/test/AElf.ContractDeployer.Tests/ContractDeployerTestAElfModule.cs @@ -1,10 +1,9 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.ContractDeployer +namespace AElf.ContractDeployer; + +[DependsOn(typeof(ContractDeployerModule))] +public class ContractDeployerTestAElfModule : AElfModule { - [DependsOn(typeof(ContractDeployerModule))] - public class ContractDeployerTestAElfModule : AElfModule - { - } } \ No newline at end of file diff --git a/test/AElf.ContractDeployer.Tests/ContractDeployerTestBase.cs b/test/AElf.ContractDeployer.Tests/ContractDeployerTestBase.cs index ba7664a9a8..58fdb36bbb 100644 --- a/test/AElf.ContractDeployer.Tests/ContractDeployerTestBase.cs +++ b/test/AElf.ContractDeployer.Tests/ContractDeployerTestBase.cs @@ -1,9 +1,7 @@ using AElf.TestBase; -namespace AElf.ContractDeployer -{ - public class ContractDeployerTestBase : AElfIntegratedTest - { +namespace AElf.ContractDeployer; - } +public class ContractDeployerTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.ContractDeployer.Tests/ContractsDeployerTests.cs b/test/AElf.ContractDeployer.Tests/ContractsDeployerTests.cs index 414222b8a6..7c5b696527 100644 --- a/test/AElf.ContractDeployer.Tests/ContractsDeployerTests.cs +++ b/test/AElf.ContractDeployer.Tests/ContractsDeployerTests.cs @@ -5,75 +5,74 @@ using Shouldly; using Xunit; -namespace AElf.ContractDeployer +namespace AElf.ContractDeployer; + +public class ContractsDeployerTests : ContractDeployerTestBase { - public class ContractsDeployerTests : ContractDeployerTestBase + private readonly IContractPatcher _contractPatcher; + + public ContractsDeployerTests() + { + _contractPatcher = GetRequiredService(); + } + + [Fact] + public void GetContractCodes_WithoutContractManifest_Test() + { + Assert.Throws(() => + ContractsDeployer.GetContractCodes()); + } + + [Fact] + public void GetContractCodes_WithContractManifest_Test() + { + var codes = ContractsDeployer.GetContractCodes(); + + CheckResult(codes); + } + + [Fact] + public void GetContractCodes_ContractFolder_Test() + { + var folder = "/NotExist"; + var codes = ContractsDeployer.GetContractCodes(folder); + + CheckResult(codes); + + folder = Environment.CurrentDirectory; + codes = ContractsDeployer.GetContractCodes(folder); + + CheckResult(codes); + } + + [Fact] + public void GetContractCodes_PatchedContract_Test() + { + PatchContractCode("AElf.Contracts.MultiToken"); + PatchContractCode("AElf.Contracts.TokenConverter"); + + var codes = ContractsDeployer.GetContractCodes(isPatched: true); + + CheckResult(codes); + } + + private void CheckResult(IReadOnlyDictionary codes) + { + codes.Count.ShouldBe(2); + codes["AElf.Contracts.MultiToken"].ShouldBe(GetContactCode("AElf.Contracts.MultiToken")); + codes["AElf.Contracts.TokenConverter"].ShouldBe(GetContactCode("AElf.Contracts.TokenConverter")); + } + + private byte[] GetContactCode(string name) + { + var path = Path.Combine(Environment.CurrentDirectory, name + ".dll"); + return File.ReadAllBytes(path); + } + + private void PatchContractCode(string name) { - private readonly IContractPatcher _contractPatcher; - - public ContractsDeployerTests() - { - _contractPatcher = GetRequiredService(); - } - - [Fact] - public void GetContractCodes_WithoutContractManifest_Test() - { - Assert.Throws(() => - ContractsDeployer.GetContractCodes()); - } - - [Fact] - public void GetContractCodes_WithContractManifest_Test() - { - var codes = ContractsDeployer.GetContractCodes(); - - CheckResult(codes); - } - - [Fact] - public void GetContractCodes_ContractFolder_Test() - { - var folder = "/NotExist"; - var codes = ContractsDeployer.GetContractCodes(folder); - - CheckResult(codes); - - folder = Environment.CurrentDirectory; - codes = ContractsDeployer.GetContractCodes(folder); - - CheckResult(codes); - } - - [Fact] - public void GetContractCodes_PatchedContract_Test() - { - PatchContractCode("AElf.Contracts.MultiToken"); - PatchContractCode("AElf.Contracts.TokenConverter"); - - var codes = ContractsDeployer.GetContractCodes(isPatched: true); - - CheckResult(codes); - } - - private void CheckResult(IReadOnlyDictionary codes) - { - codes.Count.ShouldBe(2); - codes["AElf.Contracts.MultiToken"].ShouldBe(GetContactCode("AElf.Contracts.MultiToken")); - codes["AElf.Contracts.TokenConverter"].ShouldBe(GetContactCode("AElf.Contracts.TokenConverter")); - } - - private byte[] GetContactCode(string name) - { - var path = Path.Combine(Environment.CurrentDirectory, name + ".dll"); - return File.ReadAllBytes(path); - } - - private void PatchContractCode(string name) - { - var patchedCode = _contractPatcher.Patch(GetContactCode(name), true); - var path = Path.Combine(Environment.CurrentDirectory, name + ".dll.patched"); - File.WriteAllBytes(path, patchedCode); - } + var patchedCode = _contractPatcher.Patch(GetContactCode(name), true); + var path = Path.Combine(Environment.CurrentDirectory, name + ".dll.patched"); + File.WriteAllBytes(path, patchedCode); } } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/AElf.ContractTestBase.Tests.csproj b/test/AElf.ContractTestBase.Tests/AElf.ContractTestBase.Tests.csproj index 00b2417a71..ff4fd8d3b6 100644 --- a/test/AElf.ContractTestBase.Tests/AElf.ContractTestBase.Tests.csproj +++ b/test/AElf.ContractTestBase.Tests/AElf.ContractTestBase.Tests.csproj @@ -8,9 +8,9 @@ 0436 - + - + @@ -156,13 +156,13 @@ - - - - - - - + + + + + + + diff --git a/test/AElf.ContractTestBase.Tests/MainChainTestBase.cs b/test/AElf.ContractTestBase.Tests/MainChainTestBase.cs index d48e9eee54..978e6abb41 100644 --- a/test/AElf.ContractTestBase.Tests/MainChainTestBase.cs +++ b/test/AElf.ContractTestBase.Tests/MainChainTestBase.cs @@ -1,7 +1,5 @@ -namespace AElf.ContractTestBase.Tests -{ - public class MainChainTestBase : MainChainContractTestBase - { +namespace AElf.ContractTestBase.Tests; - } +public class MainChainTestBase : MainChainContractTestBase +{ } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/MainChainTestModule.cs b/test/AElf.ContractTestBase.Tests/MainChainTestModule.cs index 8998702353..9ce505a021 100644 --- a/test/AElf.ContractTestBase.Tests/MainChainTestModule.cs +++ b/test/AElf.ContractTestBase.Tests/MainChainTestModule.cs @@ -3,17 +3,16 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.ContractTestBase.Tests +namespace AElf.ContractTestBase.Tests; + +[DependsOn( + typeof(MainChainContractTestModule) +)] +public class MainChainTestModule : MainChainContractTestModule { - [DependsOn( - typeof(MainChainContractTestModule) - )] - public class MainChainTestModule : MainChainContractTestModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/MainChainTests.cs b/test/AElf.ContractTestBase.Tests/MainChainTests.cs index 7a7c5f5202..e145d22e5d 100644 --- a/test/AElf.ContractTestBase.Tests/MainChainTests.cs +++ b/test/AElf.ContractTestBase.Tests/MainChainTests.cs @@ -1,52 +1,48 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AElf.Contracts.Election; using AElf.Contracts.MultiToken; using AElf.GovernmentSystem; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.ContractTestBase.Tests +namespace AElf.ContractTestBase.Tests; + +public sealed class MainChainTests : MainChainTestBase { - public sealed class MainChainTests : MainChainTestBase + private readonly IBlockchainService _blockchainService; + + public MainChainTests() + { + _blockchainService = GetRequiredService(); + } + + [Fact] + public async Task Test() { - private readonly IBlockchainService _blockchainService; - - public MainChainTests() + var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + var chainContext = new ChainContext { - _blockchainService = GetRequiredService(); - } + BlockHash = preBlockHeader.GetHash(), + BlockHeight = preBlockHeader.Height + }; + var contractMapping = await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - [Fact] - public async Task Test() + var tokenStub = GetTester( + contractMapping[TokenSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); + var balance = await tokenStub.GetBalance.CallAsync(new GetBalanceInput { - var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - var chainContext = new ChainContext - { - BlockHash = preBlockHeader.GetHash(), - BlockHeight = preBlockHeader.Height - }; - var contractMapping = await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - - var tokenStub = GetTester( - contractMapping[TokenSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); - var balance = await tokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Accounts[0].Address, - Symbol = "ELF" - }); - balance.Balance.ShouldBe(88000000000000000L); + Owner = Accounts[0].Address, + Symbol = "ELF" + }); + balance.Balance.ShouldBe(88000000000000000L); - var electionStub = GetTester( - contractMapping[ElectionSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); - var minerCount = await electionStub.GetMinersCount.CallAsync(new Empty()); - minerCount.Value.ShouldBe(1); - } + var electionStub = GetTester( + contractMapping[ElectionSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); + var minerCount = await electionStub.GetMinersCount.CallAsync(new Empty()); + minerCount.Value.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/SideChainTestBase.cs b/test/AElf.ContractTestBase.Tests/SideChainTestBase.cs index 42a905856b..3825d2c10a 100644 --- a/test/AElf.ContractTestBase.Tests/SideChainTestBase.cs +++ b/test/AElf.ContractTestBase.Tests/SideChainTestBase.cs @@ -1,7 +1,5 @@ -namespace AElf.ContractTestBase.Tests -{ - public class SideChainTestBase : SideChainContractTestBase - { +namespace AElf.ContractTestBase.Tests; - } +public class SideChainTestBase : SideChainContractTestBase +{ } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/SideChainTestModule.cs b/test/AElf.ContractTestBase.Tests/SideChainTestModule.cs index 714e719229..f33d67a1b6 100644 --- a/test/AElf.ContractTestBase.Tests/SideChainTestModule.cs +++ b/test/AElf.ContractTestBase.Tests/SideChainTestModule.cs @@ -3,17 +3,16 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.ContractTestBase.Tests +namespace AElf.ContractTestBase.Tests; + +[DependsOn( + typeof(SideChainContractTestModule) +)] +public class SideChainTestModule : SideChainContractTestModule { - [DependsOn( - typeof(SideChainContractTestModule) - )] - public class SideChainTestModule : SideChainContractTestModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.ContractTestBase.Tests/SideChainTests.cs b/test/AElf.ContractTestBase.Tests/SideChainTests.cs index 6b80956851..33e6ee2ca5 100644 --- a/test/AElf.ContractTestBase.Tests/SideChainTests.cs +++ b/test/AElf.ContractTestBase.Tests/SideChainTests.cs @@ -1,43 +1,37 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using AElf.Contracts.CrossChain; -using AElf.Contracts.MultiToken; using AElf.CrossChain; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.Token; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.ContractTestBase.Tests +namespace AElf.ContractTestBase.Tests; + +public sealed class SideChainTests : SideChainTestBase { - public sealed class SideChainTests : SideChainTestBase - { - private readonly IBlockchainService _blockchainService; + private readonly IBlockchainService _blockchainService; - public SideChainTests() - { - _blockchainService = GetRequiredService(); - } + public SideChainTests() + { + _blockchainService = GetRequiredService(); + } - [Fact] - public async Task Test() + [Fact] + public async Task Test() + { + var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + var chainContext = new ChainContext { - var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - var chainContext = new ChainContext - { - BlockHash = preBlockHeader.GetHash(), - BlockHeight = preBlockHeader.Height - }; - var contractMapping = await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); + BlockHash = preBlockHeader.GetHash(), + BlockHeight = preBlockHeader.Height + }; + var contractMapping = await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - var crossChainStub = GetTester( - contractMapping[CrossChainSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); - var parentChainId = await crossChainStub.GetParentChainId.CallAsync(new Empty()); - ChainHelper.ConvertChainIdToBase58(parentChainId.Value).ShouldBe("AELF"); - } + var crossChainStub = GetTester( + contractMapping[CrossChainSmartContractAddressNameProvider.Name], Accounts[0].KeyPair); + var parentChainId = await crossChainStub.GetParentChainId.CallAsync(new Empty()); + ChainHelper.ConvertChainIdToBase58(parentChainId.Value).ShouldBe("AELF"); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoModule.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoModule.cs index 1b3685c343..8eb35c0d3b 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoModule.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoModule.cs @@ -1,23 +1,21 @@ using AElf.ContractTestKit.AEDPoSExtension; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Kernel.Consensus.Application; using AElf.Kernel.SmartContract; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +[DependsOn(typeof(ContractTestAEDPoSExtensionModule))] +// ReSharper disable once InconsistentNaming +public class AEDPoSExtensionDemoModule : ContractTestAEDPoSExtensionModule { - [DependsOn(typeof(ContractTestAEDPoSExtensionModule))] - // ReSharper disable once InconsistentNaming - public class AEDPoSExtensionDemoModule : ContractTestAEDPoSExtensionModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddAssemblyOf(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs index d2eb1a42a2..669a451723 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs @@ -1,16 +1,14 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS3; using AElf.ContractDeployer; using AElf.Contracts.Association; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Economic; using AElf.Contracts.Election; +using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -using AElf.Contracts.Genesis; using AElf.Contracts.TestContract.RandomNumberProvider; using AElf.Contracts.Treasury; using AElf.ContractTestKit.AEDPoSExtension; @@ -20,113 +18,108 @@ using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Volo.Abp.Threading; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +// ReSharper disable once InconsistentNaming +public class AEDPoSExtensionDemoTestBase : AEDPoSExtensionTestBase { - // ReSharper disable once InconsistentNaming - public class AEDPoSExtensionDemoTestBase : AEDPoSExtensionTestBase + internal readonly List ParliamentStubs = new(); + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => + GetTester( + ContractZeroAddress, Accounts[0].KeyPair); + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal ElectionContractContainer.ElectionContractStub ElectionStub => + GetTester( + ContractAddresses[ElectionSmartContractAddressNameProvider.Name], + Accounts[10].KeyPair); + + internal EconomicContractContainer.EconomicContractStub EconomicStub => + GetTester( + ContractAddresses[EconomicSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal TreasuryContractContainer.TreasuryContractStub TreasuryStub => + GetTester( + ContractAddresses[TreasurySmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal TokenContractImplContainer.TokenContractImplStub TokenStub => + GetTester( + ContractAddresses[TokenSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal AssociationContractImplContainer.AssociationContractImplStub AssociationStub => + GetTester( + ContractAddresses[AssociationSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal void InitialContracts() { - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => - GetTester( - ContractZeroAddress, Accounts[0].KeyPair); - - internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal ElectionContractContainer.ElectionContractStub ElectionStub => - GetTester( - ContractAddresses[ElectionSmartContractAddressNameProvider.Name], - Accounts[10].KeyPair); - - internal EconomicContractContainer.EconomicContractStub EconomicStub => - GetTester( - ContractAddresses[EconomicSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal TreasuryContractContainer.TreasuryContractStub TreasuryStub => - GetTester( - ContractAddresses[TreasurySmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal TokenContractImplContainer.TokenContractImplStub TokenStub => - GetTester( - ContractAddresses[TokenSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal AssociationContractImplContainer.AssociationContractImplStub AssociationStub => - GetTester( - ContractAddresses[AssociationSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal readonly List ParliamentStubs = - new List(); - - internal void InitialContracts() - { - ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List - { - // You can deploy more system contracts by adding system contract name to current list. - TokenSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ElectionSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name - })); - } - - internal void InitialAcs3Stubs() + ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List { - foreach (var initialKeyPair in MissionedECKeyPairs.InitialKeyPairs) - { - ParliamentStubs.Add(GetTester( - ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair)); - } - } - - internal async Task - DeployRandomNumberProviderContract() - { - var address = (await BasicContractZeroStub.DeploySmartContract.SendAsync(new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(ContractsDeployer.GetContractCodes() - .Single(kv => kv.Key.EndsWith("RandomNumberProvider")) - .Value) - })).Output; - - return GetTester(address, - Accounts[0].KeyPair); - } - - internal async Task ParliamentReachAnAgreementAsync(CreateProposalInput createProposalInput) + // You can deploy more system contracts by adding system contract name to current list. + TokenSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ElectionSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name + })); + } + + internal void InitialAcs3Stubs() + { + foreach (var initialKeyPair in MissionedECKeyPairs.InitialKeyPairs) + ParliamentStubs.Add(GetTester( + ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair)); + } + + internal async Task + DeployRandomNumberProviderContract() + { + var address = (await BasicContractZeroStub.DeploySmartContract.SendAsync(new ContractDeploymentInput { - var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); - await BlockMiningService.MineBlockAsync(new List - { - createProposalTx - }); - var proposalId = new Hash(); - proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); - var approvals = new List(); - foreach (var stub in ParliamentStubs) - { - approvals.Add(stub.Approve.GetTransaction(proposalId)); - } - - await BlockMiningService.MineBlockAsync(approvals); - - await ParliamentStubs.First().Release.SendAsync(proposalId); - } - - internal void SetToSideChain() + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(ContractsDeployer.GetContractCodes() + .Single(kv => kv.Key.EndsWith("RandomNumberProvider")) + .Value) + })).Output; + + return GetTester(address, + Accounts[0].KeyPair); + } + + internal async Task ParliamentReachAnAgreementAsync(CreateProposalInput createProposalInput) + { + var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); + await BlockMiningService.MineBlockAsync(new List { - var chainTypeProvider = GetRequiredService(); - chainTypeProvider.IsSideChain = true; - } + createProposalTx + }); + var proposalId = new Hash(); + proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); + var approvals = new List(); + foreach (var stub in ParliamentStubs) approvals.Add(stub.Approve.GetTransaction(proposalId)); + + await BlockMiningService.MineBlockAsync(approvals); + + await ParliamentStubs.First().Release.SendAsync(proposalId); + } + + internal void SetToSideChain() + { + var chainTypeProvider = GetRequiredService(); + chainTypeProvider.IsSideChain = true; } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs index 2adf1e9a01..8840133e89 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs @@ -2,15 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.Economic; -using AElf.Contracts.Election; using AElf.Contracts.MultiToken; using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; -using AElf.CSharp.Core.Extension; -using AElf.GovernmentSystem; using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Types; @@ -19,161 +14,146 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +// ReSharper disable once InconsistentNaming +public class AEDPoSExtensionTests : AEDPoSExtensionDemoTestBase { - // ReSharper disable once InconsistentNaming - public class AEDPoSExtensionTests : AEDPoSExtensionDemoTestBase + [Fact] + public async Task Demo_Test() { - [Fact] - public async Task Demo_Test() + InitialContracts(); + + // Check round information after initialization. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.RoundNumber.ShouldBe(1); + round.TermNumber.ShouldBe(1); + round.RealTimeMinersInformation.Count.ShouldBe(AEDPoSExtensionConstants.InitialKeyPairCount); + + TestDataProvider.SetBlockTime( + round.RealTimeMinersInformation.Single(m => m.Value.Order == 1).Value.ExpectedMiningTime + + new Duration { Seconds = 1 }); + } + + // We can use this method process testing. + // Basically this will produce one block with no transaction. + await BlockMiningService.MineBlockAsync(); + + // And this will produce one block with one transaction. + // This transaction will call Create method of Token Contract. + var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput + { + Symbol = "ELF", + Decimals = 8, + TokenName = "Test", + Issuer = Accounts[0].Address, + IsBurnable = true, + TotalSupply = 1_000_000_000_00000000 + }); + const long issueTokenAmount = 10_0000_00000000; + var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); + var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput + { + Symbol = "ELF", + Amount = issueTokenAmount, + To = issueToAddress + }); + await BlockMiningService.MineBlockAsync(new List + { + createTokenTransaction, + issueTokenTransaction + }); + + var createTokenTransactionTrace = + TransactionTraceProvider.GetTransactionTrace(createTokenTransaction.GetHash()); + createTokenTransactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + + // Check whether previous Create transaction successfully executed. + { + var tokenInfo = await TokenStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = "ELF" }); + tokenInfo.Symbol.ShouldBe("ELF"); + } + + for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber; i++) await BlockMiningService.MineBlockAsync(); + + var getBalanceTransaction = TokenStub.GetBalance.GetTransaction(new GetBalanceInput + { + Owner = issueToAddress, + Symbol = "ELF" + }); + // Miner of order 2 produce his first block. + await BlockMiningService.MineBlockAsync(new List { getBalanceTransaction }); + + var getBalanceTransactionTrace = + TransactionTraceProvider.GetTransactionTrace(getBalanceTransaction.GetHash()); + getBalanceTransactionTrace.ReturnValue.ShouldNotBeNull(); + var output = GetBalanceOutput.Parser.ParseFrom(getBalanceTransactionTrace.ReturnValue); + output.Balance.ShouldBe(issueTokenAmount); + + // Next steps will check whether the AEDPoS process is correct. + // Now 2 miners produced block during first round, so there should be 2 miners' OutValue isn't null. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.RealTimeMinersInformation.Values.Count(m => m.OutValue != null).ShouldBe(2); + } + + for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber - 1; i++) + await BlockMiningService.MineBlockAsync(); + + // Miner of order 3 produce his first block. { - InitialContracts(); - - // Check round information after initialization. - { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.RoundNumber.ShouldBe(1); - round.TermNumber.ShouldBe(1); - round.RealTimeMinersInformation.Count.ShouldBe(AEDPoSExtensionConstants.InitialKeyPairCount); - - TestDataProvider.SetBlockTime( - round.RealTimeMinersInformation.Single(m => m.Value.Order == 1).Value.ExpectedMiningTime + - new Duration {Seconds = 1}); - } - - // We can use this method process testing. - // Basically this will produce one block with no transaction. await BlockMiningService.MineBlockAsync(); + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.RealTimeMinersInformation.Values.Count(m => m.OutValue != null).ShouldBe(3); + } - // And this will produce one block with one transaction. - // This transaction will call Create method of Token Contract. - var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput - { - Symbol = "ELF", - Decimals = 8, - TokenName = "Test", - Issuer = Accounts[0].Address, - IsBurnable = true, - TotalSupply = 1_000_000_000_00000000 - }); - const long issueTokenAmount = 10_0000_00000000; - var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); - var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput - { - Symbol = "ELF", - Amount = issueTokenAmount, - To = issueToAddress - }); - await BlockMiningService.MineBlockAsync(new List - { - createTokenTransaction, - issueTokenTransaction - }); - - var createTokenTransactionTrace = - TransactionTraceProvider.GetTransactionTrace(createTokenTransaction.GetHash()); - createTokenTransactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); - - // Check whether previous Create transaction successfully executed. - { - var tokenInfo = await TokenStub.GetTokenInfo.CallAsync(new GetTokenInfoInput {Symbol = "ELF"}); - tokenInfo.Symbol.ShouldBe("ELF"); - } - - for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber; i++) - { - await BlockMiningService.MineBlockAsync(); - } - - var getBalanceTransaction = TokenStub.GetBalance.GetTransaction(new GetBalanceInput - { - Owner = issueToAddress, - Symbol = "ELF" - }); - // Miner of order 2 produce his first block. - await BlockMiningService.MineBlockAsync(new List {getBalanceTransaction}); - - var getBalanceTransactionTrace = - TransactionTraceProvider.GetTransactionTrace(getBalanceTransaction.GetHash()); - getBalanceTransactionTrace.ReturnValue.ShouldNotBeNull(); - var output = GetBalanceOutput.Parser.ParseFrom(getBalanceTransactionTrace.ReturnValue); - output.Balance.ShouldBe(issueTokenAmount); - - // Next steps will check whether the AEDPoS process is correct. - // Now 2 miners produced block during first round, so there should be 2 miners' OutValue isn't null. - { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.RealTimeMinersInformation.Values.Count(m => m.OutValue != null).ShouldBe(2); - } - - for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber - 1; i++) - { - await BlockMiningService.MineBlockAsync(); - } - - // Miner of order 3 produce his first block. - { - await BlockMiningService.MineBlockAsync(); - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.RealTimeMinersInformation.Values.Count(m => m.OutValue != null).ShouldBe(3); - } - - for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber - 1; i++) - { - await BlockMiningService.MineBlockAsync(); - } - - // Currently we have 5 miners, and before this line, 3 miners already produced blocks. - // 3 more blocks will end current round. - for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber * 3; i++) - { - await BlockMiningService.MineBlockAsync(new List()); - } - - // Check round number. - { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - if (round.RoundNumber != 2) - { - throw new Exception(round.ToString()); - } - - round.RoundNumber.ShouldBe(2); - } - - var countDown = await ConsensusStub.GetNextElectCountDown.CallAsync(new Empty()); - countDown.Value.ShouldBePositive(); - - // 5 more blocks will end second round. - for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber * 6; i++) - { - await BlockMiningService.MineBlockAsync(new List()); - } - - // Check round number. - { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.RoundNumber.ShouldBe(3); - } - - var randomHash = await ConsensusStub.GetRandomHash.CallAsync(new Int64Value {Value = 100}); - randomHash.ShouldNotBe(Hash.Empty); + for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber - 1; i++) + await BlockMiningService.MineBlockAsync(); + + // Currently we have 5 miners, and before this line, 3 miners already produced blocks. + // 3 more blocks will end current round. + for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber * 3; i++) + await BlockMiningService.MineBlockAsync(new List()); + + // Check round number. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + if (round.RoundNumber != 2) throw new Exception(round.ToString()); + + round.RoundNumber.ShouldBe(2); } - [Fact] - public async Task NotMinerTest() + var countDown = await ConsensusStub.GetNextElectCountDown.CallAsync(new Empty()); + countDown.Value.ShouldBePositive(); + + // 5 more blocks will end second round. + for (var i = 0; i < AEDPoSExtensionConstants.TinyBlocksNumber * 6; i++) + await BlockMiningService.MineBlockAsync(new List()); + + // Check round number. { - InitialContracts(); - var keyPair = SampleAccount.Accounts.Last().KeyPair; - var stub = GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - keyPair); - var command = await stub.GetConsensusCommand.CallAsync(new BytesValue - {Value = ByteString.CopyFrom(keyPair.PublicKey)}); - command.Hint.ShouldBe(ByteString.CopyFrom(new AElfConsensusHint - { - Behaviour = AElfConsensusBehaviour.Nothing - }.ToByteArray())); + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.RoundNumber.ShouldBe(3); } + + var randomHash = await ConsensusStub.GetRandomHash.CallAsync(new Int64Value { Value = 100 }); + randomHash.ShouldNotBe(Hash.Empty); + } + + [Fact] + public async Task NotMinerTest() + { + InitialContracts(); + var keyPair = SampleAccount.Accounts.Last().KeyPair; + var stub = GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + keyPair); + var command = await stub.GetConsensusCommand.CallAsync(new BytesValue + { Value = ByteString.CopyFrom(keyPair.PublicKey) }); + command.Hint.ShouldBe(ByteString.CopyFrom(new AElfConsensusHint + { + Behaviour = AElfConsensusBehaviour.Nothing + }.ToByteArray())); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj index 74f9456b05..fb3357fe15 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AElf.Contracts.AEDPoSExtension.Demo.Tests.csproj @@ -6,18 +6,18 @@ - - - - - - + + + + + + - - + + - + false @@ -25,7 +25,7 @@ PreserveNewest - + diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/BroadcastPrivilegedPubkeyListTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/BroadcastPrivilegedPubkeyListTest.cs index 77b693739f..67c924413b 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/BroadcastPrivilegedPubkeyListTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/BroadcastPrivilegedPubkeyListTest.cs @@ -4,21 +4,20 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class BroadcastPrivilegedPubkeyListTest : AEDPoSExtensionDemoTestBase { - public class BroadcastPrivilegedPubkeyListTest : AEDPoSExtensionDemoTestBase + // Just test very basic logic of GetPubkeyList method because currently there's no consensus extra data in block header. + [Fact] + public async Task BroadcastPrivilegedPubkeyListProviderTest() { - // Just test very basic logic of GetPubkeyList method because currently there's no consensus extra data in block header. - [Fact] - public async Task BroadcastPrivilegedPubkeyListProviderTest() - { - await BlockMiningService.MineBlockAsync(); - var broadcastPrivilegedPubkeyListProvider = GetRequiredService(); - var blockchainService = GetRequiredService(); - var chain = await blockchainService.GetChainAsync(); - var blockHeader = await blockchainService.GetBlockHeaderByHashAsync(chain.BestChainHash); - var pubkeyList = await broadcastPrivilegedPubkeyListProvider.GetPubkeyList(blockHeader); - pubkeyList.ShouldNotBeNull(); - } + await BlockMiningService.MineBlockAsync(); + var broadcastPrivilegedPubkeyListProvider = GetRequiredService(); + var blockchainService = GetRequiredService(); + var chain = await blockchainService.GetChainAsync(); + var blockHeader = await blockchainService.GetBlockHeaderByHashAsync(chain.BestChainHash); + var pubkeyList = await broadcastPrivilegedPubkeyListProvider.GetPubkeyList(blockHeader); + pubkeyList.ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs index 86e298a993..a8fb662cee 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs @@ -1,96 +1,96 @@ using System; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; +using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; +using AElf.Standards.ACS3; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class MaximumMinersCountTests : AEDPoSExtensionDemoTestBase { - public class MaximumMinersCountTests : AEDPoSExtensionDemoTestBase + [Theory] + [InlineData(7)] + [InlineData(3)] + public async Task SetMaximumMinersCountTest(int targetMinersCount) { - [Theory] - [InlineData(7)] - [InlineData(3)] - public async Task SetMaximumMinersCountTest(int targetMinersCount) - { - InitialContracts(); - await BlockMiningService.MineBlockToNextTermAsync(); + InitialContracts(); + await BlockMiningService.MineBlockToNextTermAsync(); - InitialAcs3Stubs(); - await ParliamentStubs.First().Initialize.SendAsync(new Parliament.InitializeInput()); - var defaultOrganizationAddress = - await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); - await ParliamentReachAnAgreementAsync(new CreateProposalInput + InitialAcs3Stubs(); + await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput()); + var defaultOrganizationAddress = + await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + await ParliamentReachAnAgreementAsync(new CreateProposalInput + { + ToAddress = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + ContractMethodName = nameof(ConsensusStub.SetMaximumMinersCount), + Params = new Int32Value { - ToAddress = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - ContractMethodName = nameof(ConsensusStub.SetMaximumMinersCount), - Params = new Int32Value - { - Value = targetMinersCount - }.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = defaultOrganizationAddress - }); + Value = targetMinersCount + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultOrganizationAddress + }); - { - var currentMinersCount = (await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty())).Pubkeys.Count; - currentMinersCount.ShouldBe(5); - var currentTermNumber = await BlockMiningService.MineBlockToNextTermAsync(); - currentTermNumber.ShouldBe(3); - } + { + var currentMinersCount = (await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty())).Pubkeys.Count; + currentMinersCount.ShouldBe(5); + var currentTermNumber = await BlockMiningService.MineBlockToNextTermAsync(); + currentTermNumber.ShouldBe(3); + } - { - var currentMinersCount = (await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty())).Pubkeys.Count; - currentMinersCount.ShouldBe(Math.Min(targetMinersCount, 5)); - var currentTermNumber = await BlockMiningService.MineBlockToNextTermAsync(); - currentTermNumber.ShouldBe(4); - } - - var maxMinersCount = await ConsensusStub.GetMaximumMinersCount.CallAsync(new Empty()); - maxMinersCount.Value.ShouldBe(targetMinersCount); + { + var currentMinersCount = (await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty())).Pubkeys.Count; + currentMinersCount.ShouldBe(Math.Min(targetMinersCount, 5)); + var currentTermNumber = await BlockMiningService.MineBlockToNextTermAsync(); + currentTermNumber.ShouldBe(4); + } - var minedBlocksOfPreviousTerm = await ConsensusStub.GetMinedBlocksOfPreviousTerm.CallAsync(new Empty()); - minedBlocksOfPreviousTerm.Value.ShouldBeGreaterThan(200); + var maxMinersCount = await ConsensusStub.GetMaximumMinersCount.CallAsync(new Empty()); + maxMinersCount.Value.ShouldBe(targetMinersCount); - var previousMinerList = await ConsensusStub.GetPreviousMinerList.CallAsync(new Empty()); - previousMinerList.Pubkeys.Count.ShouldBePositive(); - } + var minedBlocksOfPreviousTerm = await ConsensusStub.GetMinedBlocksOfPreviousTerm.CallAsync(new Empty()); + minedBlocksOfPreviousTerm.Value.ShouldBeGreaterThan(200); - [Fact] - public async Task ChangeMaximumMinersCountControllerTest() - { - InitialContracts(); + var previousMinerList = await ConsensusStub.GetPreviousMinerList.CallAsync(new Empty()); + previousMinerList.Pubkeys.Count.ShouldBePositive(); + } - await BlockMiningService.MineBlockToNextTermAsync(); + [Fact] + public async Task ChangeMaximumMinersCountControllerTest() + { + InitialContracts(); + + await BlockMiningService.MineBlockToNextTermAsync(); - InitialAcs3Stubs(); - await ParliamentStubs.First().Initialize.SendAsync(new Parliament.InitializeInput()); - var targetAddress = await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + InitialAcs3Stubs(); + await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput()); + var targetAddress = await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); - var defaultOrganizationAddress = - await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); - await ParliamentReachAnAgreementAsync(new CreateProposalInput + var defaultOrganizationAddress = + await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + await ParliamentReachAnAgreementAsync(new CreateProposalInput + { + ToAddress = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + ContractMethodName = nameof(ConsensusStub.ChangeMaximumMinersCountController), + Params = new AuthorityInfo { - ToAddress = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - ContractMethodName = nameof(ConsensusStub.ChangeMaximumMinersCountController), - Params = new AuthorityInfo - { - OwnerAddress = targetAddress, - ContractAddress = ContractAddresses[ParliamentSmartContractAddressNameProvider.Name] - }.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = defaultOrganizationAddress - }); + OwnerAddress = targetAddress, + ContractAddress = ContractAddresses[ParliamentSmartContractAddressNameProvider.Name] + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultOrganizationAddress + }); - var newMinersCountController = await ConsensusStub.GetMaximumMinersCountController.CallAsync(new Empty()); - newMinersCountController.OwnerAddress.ShouldBe(targetAddress); - } + var newMinersCountController = await ConsensusStub.GetMaximumMinersCountController.CallAsync(new Empty()); + newMinersCountController.OwnerAddress.ShouldBe(targetAddress); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/README.md b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/README.md index 5bef327d25..2ec075e8e9 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/README.md +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/README.md @@ -1,11 +1,16 @@ # What's this -Since `AElf.Contracts.TestKit` is a contract testing framework for testing AElf smart contracts, `AElf.Contract.TestKit.AEDPoSExtension` is an extension for `AElf.Contracts.TestKit` with which contract developers can test their contract in a more reality environment as AElf Main Chain. + +Since `AElf.Contracts.TestKit` is a contract testing framework for testing AElf smart +contracts, `AElf.Contract.TestKit.AEDPoSExtension` is an extension for `AElf.Contracts.TestKit` with which contract +developers can test their contract in a more reality environment as AElf Main Chain. # How to build a contract test project with AEDPoS extension + 1. Create a XUnit project. 2. Modify csproj file. -Basically add bellowing references: + Basically add bellowing references: + ```MSBUILD @@ -21,9 +26,12 @@ Basically add bellowing references: ``` + Import `AllContracts.props` will actually reference all system contracts. At the same time, you need to reference the contract you are about to test to this testing project. -Meanwhile if you want to test `AElf.Contracts.TestContract.BasicFunction`, what you need is to add bellowing lines to csproj file: +Meanwhile if you want to test `AElf.Contracts.TestContract.BasicFunction`, what you need is to add bellowing lines to +csproj file: + ```MSBUILD @@ -33,10 +41,12 @@ Meanwhile if you want to test `AElf.Contracts.TestContract.BasicFunction`, what ``` + Because this contract isn't a system contract, you need to add this reference separately. 3. Link necessary proto files for generating contract stub for testing. -In Demo project, we choose these proto files. + In Demo project, we choose these proto files. + ```MSBUILD @@ -60,13 +70,14 @@ In Demo project, we choose these proto files. ``` 4. Create a `Module` -See `AEDPoSExtensionDemoModule`. -Config ContractOptions.ContractDeploymentAuthorityRequired as false is necessary currently. + See `AEDPoSExtensionDemoModule`. + Config ContractOptions.ContractDeploymentAuthorityRequired as false is necessary currently. 5. Create a `TestBase` -Inherit from AEDPoSExtensionTestBase. -Then Deploy system smart contracts in ctor of `TestBase`. -See `AEDPoSExtensionDemoTestBase`. -Note: AEDPoS Contract will deploy anyway because AEDPoS processes is of vital importance exactly for this testing framework. + Inherit from AEDPoSExtensionTestBase. + Then Deploy system smart contracts in ctor of `TestBase`. + See `AEDPoSExtensionDemoTestBase`. + Note: AEDPoS Contract will deploy anyway because AEDPoS processes is of vital importance exactly for this testing + framework. 6. For writing test cases, you can check code in this demo project. \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/RandomNumberProviderTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/RandomNumberProviderTests.cs index d6cb922527..b031858ed9 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/RandomNumberProviderTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/RandomNumberProviderTests.cs @@ -7,52 +7,51 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class RandomNumberProviderTests : AEDPoSExtensionDemoTestBase { - public class RandomNumberProviderTests : AEDPoSExtensionDemoTestBase + [Fact] + public async Task GetRandomBytesTest_Hash() { - [Fact] - public async Task GetRandomBytesTest_Hash() + var stub = await DeployRandomNumberProviderContract(); + var randomBytes = await stub.GetRandomBytes.CallAsync(new GetRandomBytesInput { - var stub = await DeployRandomNumberProviderContract(); - var randomBytes = await stub.GetRandomBytes.CallAsync(new GetRandomBytesInput - { - Kind = 1, - Value = HashHelper.ComputeFrom("Test1").ToByteString() - }.ToBytesValue()); - var randomHash = new Hash(); - randomHash.MergeFrom(randomBytes.Value); - randomHash.ShouldNotBeNull(); - } + Kind = 1, + Value = HashHelper.ComputeFrom("Test1").ToByteString() + }.ToBytesValue()); + var randomHash = new Hash(); + randomHash.MergeFrom(randomBytes.Value); + randomHash.ShouldNotBeNull(); + } - [Fact] - public async Task GetRandomBytesTest_Int64() - { - var stub = await DeployRandomNumberProviderContract(); + [Fact] + public async Task GetRandomBytesTest_Int64() + { + var stub = await DeployRandomNumberProviderContract(); - var randomIntegers = new List(); + var randomIntegers = new List(); - for (var i = 0; i < 5; i++) + for (var i = 0; i < 5; i++) + { + var randomBytes = await stub.GetRandomBytes.CallAsync(new GetRandomBytesInput { - var randomBytes = await stub.GetRandomBytes.CallAsync(new GetRandomBytesInput - { - Kind = 2, - Value = HashHelper.ComputeFrom("Test2").ToByteString() - }.ToBytesValue()); - var randomNumber = new Int64Value(); - randomNumber.MergeFrom(randomBytes.Value); - randomNumber.Value.ShouldBePositive(); - randomNumber.Value.ShouldBeLessThan(10000); - await stub.GetRandomBytes.SendAsync(new GetRandomBytesInput - { - Kind = 2, - Value = HashHelper.ComputeFrom("Test2").ToByteString() - }.ToBytesValue()); - - randomIntegers.Add(randomNumber.Value); - } + Kind = 2, + Value = HashHelper.ComputeFrom("Test2").ToByteString() + }.ToBytesValue()); + var randomNumber = new Int64Value(); + randomNumber.MergeFrom(randomBytes.Value); + randomNumber.Value.ShouldBePositive(); + randomNumber.Value.ShouldBeLessThan(10000); + await stub.GetRandomBytes.SendAsync(new GetRandomBytesInput + { + Kind = 2, + Value = HashHelper.ComputeFrom("Test2").ToByteString() + }.ToBytesValue()); - randomIntegers.Count.ShouldBe(5); + randomIntegers.Add(randomNumber.Value); } + + randomIntegers.Count.ShouldBe(5); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs index 28ae2e560b..dd1ef0f753 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs @@ -13,128 +13,127 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class SideChainConsensusInformationTest : AEDPoSExtensionDemoTestBase { - public class SideChainConsensusInformationTest : AEDPoSExtensionDemoTestBase + [Fact] + public async Task SideChainDividendPoolTest() { - [Fact] - public async Task SideChainDividendPoolTest() - { - InitialContracts(); + InitialContracts(); - await ConsensusStub.SetSymbolList.SendWithExceptionAsync(new SymbolList()); - await ConsensusStub.GetDividends.CallAsync(new Int64Value {Value = 1}); - } + await ConsensusStub.SetSymbolList.SendWithExceptionAsync(new SymbolList()); + await ConsensusStub.GetDividends.CallAsync(new Int64Value { Value = 1 }); + } - [Fact] - public async Task UpdateInformationFromCrossChainTest() - { - SetToSideChain(); - InitialContracts(); - var mockedCrossChain = SampleAccount.Accounts.Last(); - var mockedCrossChainStub = - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - mockedCrossChain.KeyPair); + [Fact] + public async Task UpdateInformationFromCrossChainTest() + { + SetToSideChain(); + InitialContracts(); + var mockedCrossChain = SampleAccount.Accounts.Last(); + var mockedCrossChainStub = + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + mockedCrossChain.KeyPair); - var headerInformation = new AElfConsensusHeaderInformation + var headerInformation = new AElfConsensusHeaderInformation + { + Round = new Round { - Round = new Round + RoundNumber = 2, + RealTimeMinersInformation = { - RoundNumber = 2, - RealTimeMinersInformation = - { - {Accounts[0].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - {Accounts[1].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - {Accounts[2].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - } + { Accounts[0].KeyPair.PublicKey.ToHex(), new MinerInRound() }, + { Accounts[1].KeyPair.PublicKey.ToHex(), new MinerInRound() }, + { Accounts[2].KeyPair.PublicKey.ToHex(), new MinerInRound() } } - }; + } + }; - await CreateAndIssueToken("ELF"); - await CreateAndIssueToken("READ"); - await TokenStub.Transfer.SendAsync(new TransferInput - { - Symbol = "READ", - Amount = 10_00000000, - To = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name] - }); - - await mockedCrossChainStub.UpdateInformationFromCrossChain.SendAsync(new BytesValue - { - Value = headerInformation.ToByteString() - }); + await CreateAndIssueToken("ELF"); + await CreateAndIssueToken("READ"); + await TokenStub.Transfer.SendAsync(new TransferInput + { + Symbol = "READ", + Amount = 10_00000000, + To = ContractAddresses[ConsensusSmartContractAddressNameProvider.Name] + }); - var minerList = await ConsensusStub.GetMainChainCurrentMinerList.CallAsync(new Empty()); - minerList.Pubkeys.Select(m => m.ToHex()).ShouldBe(headerInformation.Round.RealTimeMinersInformation.Keys); + await mockedCrossChainStub.UpdateInformationFromCrossChain.SendAsync(new BytesValue + { + Value = headerInformation.ToByteString() + }); - var balance = await TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.Skip(1).First().PublicKey), - Symbol = "READ" - }); - balance.Balance.ShouldBe(2_00000000); - } + var minerList = await ConsensusStub.GetMainChainCurrentMinerList.CallAsync(new Empty()); + minerList.Pubkeys.Select(m => m.ToHex()).ShouldBe(headerInformation.Round.RealTimeMinersInformation.Keys); - private async Task CreateAndIssueToken(string symbol) + var balance = await TokenStub.GetBalance.CallAsync(new GetBalanceInput { - var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput - { - Symbol = symbol, - Decimals = 8, - TokenName = "Test", - Issuer = Accounts[0].Address, - IsBurnable = true, - TotalSupply = 1_000_000_000_00000000 - }); - const long issueTokenAmount = 10_0000_00000000; - var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); - var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput - { - Symbol = symbol, - Amount = issueTokenAmount, - To = issueToAddress - }); - await BlockMiningService.MineBlockAsync(new List - { - createTokenTransaction, - issueTokenTransaction - }); - } + Owner = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.Skip(1).First().PublicKey), + Symbol = "READ" + }); + balance.Balance.ShouldBe(2_00000000); + } - [Fact] - public async Task UpdateInformationFromCrossChainTest_LowRoundNumber() + private async Task CreateAndIssueToken(string symbol) + { + var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput + { + Symbol = symbol, + Decimals = 8, + TokenName = "Test", + Issuer = Accounts[0].Address, + IsBurnable = true, + TotalSupply = 1_000_000_000_00000000 + }); + const long issueTokenAmount = 10_0000_00000000; + var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); + var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput + { + Symbol = symbol, + Amount = issueTokenAmount, + To = issueToAddress + }); + await BlockMiningService.MineBlockAsync(new List { - SetToSideChain(); - InitialContracts(); - var mockedCrossChain = SampleAccount.Accounts.Last(); - var mockedCrossChainStub = - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - mockedCrossChain.KeyPair); + createTokenTransaction, + issueTokenTransaction + }); + } + + [Fact] + public async Task UpdateInformationFromCrossChainTest_LowRoundNumber() + { + SetToSideChain(); + InitialContracts(); + var mockedCrossChain = SampleAccount.Accounts.Last(); + var mockedCrossChainStub = + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + mockedCrossChain.KeyPair); - var headerInformation = new AElfConsensusHeaderInformation + var headerInformation = new AElfConsensusHeaderInformation + { + Round = new Round { - Round = new Round + RoundNumber = 0, + RealTimeMinersInformation = { - RoundNumber = 0, - RealTimeMinersInformation = - { - {Accounts[0].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - {Accounts[1].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - {Accounts[2].KeyPair.PublicKey.ToHex(), new MinerInRound()}, - } + { Accounts[0].KeyPair.PublicKey.ToHex(), new MinerInRound() }, + { Accounts[1].KeyPair.PublicKey.ToHex(), new MinerInRound() }, + { Accounts[2].KeyPair.PublicKey.ToHex(), new MinerInRound() } } - }; + } + }; - await mockedCrossChainStub.UpdateInformationFromCrossChain.SendAsync(new BytesValue - { - Value = headerInformation.ToByteString() - }); + await mockedCrossChainStub.UpdateInformationFromCrossChain.SendAsync(new BytesValue + { + Value = headerInformation.ToByteString() + }); - var minerList = await ConsensusStub.GetMainChainCurrentMinerList.CallAsync(new Empty()); - minerList.Pubkeys.Select(m => m.ToHex()) - .ShouldNotBe(headerInformation.Round.RealTimeMinersInformation.Keys); - } + var minerList = await ConsensusStub.GetMainChainCurrentMinerList.CallAsync(new Empty()); + minerList.Pubkeys.Select(m => m.ToHex()) + .ShouldNotBe(headerInformation.Round.RealTimeMinersInformation.Keys); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeModule.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeModule.cs index 25644e9cce..556e3afee2 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeModule.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeModule.cs @@ -6,43 +6,43 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee; using Google.Protobuf.WellKnownTypes; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -using ServiceDescriptor = Microsoft.Extensions.DependencyInjection.ServiceDescriptor; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +[DependsOn(typeof(ContractTestModule), + typeof(ExecutionPluginForResourceFeeModule))] +public class SideChainRentFeeModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule), - typeof(ExecutionPluginForResourceFeeModule))] - public class SideChainRentFeeModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - context.Services.Replace(ServiceDescriptor - .Singleton()); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); + context.Services.Replace(ServiceDescriptor + .Singleton()); } - - public class DelayBlockTimeProvider : IBlockTimeProvider +} + +public class DelayBlockTimeProvider : IBlockTimeProvider +{ + private const int DelaySeconds = 10; + private Timestamp _blockTime; + + public Timestamp GetBlockTime() { - private Timestamp _blockTime; - private const int DelaySeconds = 10; - public Timestamp GetBlockTime() - { - return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime.AddSeconds(DelaySeconds); - } + return _blockTime == null ? TimestampHelper.GetUtcNow() : _blockTime.AddSeconds(DelaySeconds); + } - public void SetBlockTime(Timestamp blockTime) - { - Debug.WriteLine($"Update block time: {blockTime}"); - _blockTime = blockTime; - } + public void SetBlockTime(Timestamp blockTime) + { + Debug.WriteLine($"Update block time: {blockTime}"); + _blockTime = blockTime; + } - public void SetBlockTime(int offsetMilliseconds) - { - SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); - } + public void SetBlockTime(int offsetMilliseconds) + { + SetBlockTime(_blockTime.AddMilliseconds(offsetMilliseconds)); } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs index 88520b29b7..9d505d89d1 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs @@ -21,205 +21,203 @@ using Volo.Abp.Threading; using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class SideChainRentFeeTestBase : ContractTestBase where T : ContractTestModule { - public class SideChainRentFeeTestBase : ContractTestBase where T : ContractTestModule + protected const string NativeTokenSymbol = "ELF"; + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(1).Select(a => a.KeyPair).ToList(); + + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); + + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected Address TokenContractAddress { get; set; } + protected Address AssociationContractAddress { get; set; } + protected Address ParliamentContractAddress { get; set; } + protected Address ConsensusContractAddress { get; set; } + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } + internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + private byte[] AssociationContractCode => Codes.Single(kv => kv.Key.Contains("Association")).Value; + private byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + private byte[] ParliamentContractCode => Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + private byte[] ConsensusContractCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; + + private byte[] ElectionContractCode => Codes.Single(kv => kv.Key.Contains("Election")).Value; + private byte[] ReferendumContractCode => Codes.Single(kv => kv.Key.Contains("Referendum")).Value; + + protected void DeployContracts() { - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(1).Select(a => a.KeyPair).ToList(); - - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); - - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - protected Address TokenContractAddress { get; set; } - protected Address AssociationContractAddress { get; set; } - protected Address ParliamentContractAddress { get; set; } - protected Address ConsensusContractAddress { get; set; } - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } - internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } - - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } - private byte[] AssociationContractCode => Codes.Single(kv => kv.Key.Contains("Association")).Value; - private byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - private byte[] ParliamentContractCode => Codes.Single(kv => kv.Key.Contains("Parliament")).Value; - private byte[] ConsensusContractCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; - - private byte[] ElectionContractCode => Codes.Single(kv => kv.Key.Contains("Election")).Value; - private byte[] ReferendumContractCode => Codes.Single(kv => kv.Key.Contains("Referendum")).Value; - - protected void DeployContracts() - { - BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - - //deploy Association contract - AssociationContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - AssociationContractCode, - AssociationSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair - )); - - AssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); - TokenContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - TokenContractCode, - TokenSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair)); - TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeTokenAsync()); - - ParliamentContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - ParliamentContractCode, - ParliamentSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair - )); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeParliamentContract()); - - ConsensusContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - ConsensusContractCode, - HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), - DefaultSenderKeyPair - )); - AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeAElfConsensus()); - - AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - ElectionContractCode, - ElectionSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair)); - - AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - ReferendumContractCode, - ReferendumSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair)); - } + BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); + + //deploy Association contract + AssociationContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + AssociationContractCode, + AssociationSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair + )); + + AssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + TokenContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + TokenContractCode, + TokenSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair)); + TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeTokenAsync()); + + ParliamentContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + ParliamentContractCode, + ParliamentSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair + )); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeParliamentContract()); + + ConsensusContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + ConsensusContractCode, + HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), + DefaultSenderKeyPair + )); + AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeAElfConsensus()); + + AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + ElectionContractCode, + ElectionSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair)); + + AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + ReferendumContractCode, + ReferendumSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair)); + } - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractTester(ECKeyPair keyPair) - { - return GetTester(AssociationContractAddress, keyPair); - } + internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractTester( + ECKeyPair keyPair) + { + return GetTester(AssociationContractAddress, + keyPair); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + private async Task InitializeTokenAsync() + { + const long totalSupply = 100_000_000; + await TokenContractStub.Create.SendAsync(new CreateInput { - return GetTester(ConsensusContractAddress, keyPair); - } + Symbol = NativeTokenSymbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = NativeTokenSymbol, + Amount = totalSupply - 20 * 100_000L, + To = DefaultSender, + Memo = "Issue token to default user." + }); + } - protected const string NativeTokenSymbol = "ELF"; - private async Task InitializeTokenAsync() + private async Task InitializeParliamentContract() + { + var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput { - const long totalSupply = 100_000_000; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = NativeTokenSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = NativeTokenSymbol, - Amount = totalSupply - 20 * 100_000L, - To = DefaultSender, - Memo = "Issue token to default user.", - }); - } + PrivilegedProposer = DefaultSender, + ProposerAuthorityRequired = true + }); + if (!string.IsNullOrEmpty(initializeResult.TransactionResult.Error)) + throw new Exception(initializeResult.TransactionResult.Error); + } - private async Task InitializeParliamentContract() + protected async Task InitializeAElfConsensus() + { { - var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput - { - PrivilegedProposer = DefaultSender, - ProposerAuthorityRequired = true - }); - if (!string.IsNullOrEmpty(initializeResult.TransactionResult.Error)) - { - throw new Exception(initializeResult.TransactionResult.Error); - } + await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput + { + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000 + }); } - - protected async Task InitializeAElfConsensus() { - { - await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000 - }); - } - { - await AEDPoSContractStub.FirstRound.SendAsync( - GenerateFirstRoundOfNewTerm( - new MinerList - {Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))}}, - 4000, TimestampHelper.GetUtcNow())); - } + await AEDPoSContractStub.FirstRound.SendAsync( + GenerateFirstRoundOfNewTerm( + new MinerList + { Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } }, + 4000, TimestampHelper.GetUtcNow())); } - private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + } + + private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); - var round = new Round(); + var minerInRound = new MinerInRound(); - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); + // The third miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; - // The third miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; - - return round; + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs index 4c3a51cb9b..e9b625eb32 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs @@ -1,454 +1,447 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Association; using AElf.Contracts.MultiToken; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS3; using AElf.Types; -using CommandLine; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.AEDPoSExtension.Demo.Tests +namespace AElf.Contracts.AEDPoSExtension.Demo.Tests; + +public class SideChainSideChainRentFeeTest : SideChainRentFeeTestBase { - public class SideChainSideChainRentFeeTest : SideChainRentFeeTestBase + private const int CpuAmount = 4; + private const int RamAmount = 8; + private const int DiskAmount = 512; + private const int NetAmount = 1000; + + private const long ResourceSupply = 1_0000_0000_00000000; + + private const long Rental = 100; + + public SideChainSideChainRentFeeTest() + { + DeployContracts(); + } + + private Address Creator => Accounts[0].Address; + + private static List Symbols => new() { "CPU", "RAM", "DISK", "NET" }; + + [Fact] + public async Task SideChainRentalController_Test() { - private const int CpuAmount = 4; - private const int RamAmount = 8; - private const int DiskAmount = 512; - private const int NetAmount = 1000; - - private const long ResourceSupply = 1_0000_0000_00000000; + var rentalControllerRet = + await TokenContractStub.GetSideChainRentalControllerCreateInfo.SendWithExceptionAsync(new Empty()); + rentalControllerRet.TransactionResult.Error.ShouldContain("side chain creator dose not exist"); + await InitialTokenContractAsync(); + var rentalController = + await TokenContractStub.GetSideChainRentalControllerCreateInfo.CallAsync(new Empty()); + rentalController.ShouldNotBeNull(); + } - private Address Creator => Accounts[0].Address; - - private static List Symbols => new List {"CPU", "RAM", "DISK", "NET"}; + [Fact] + public async Task GetRentalInfo_Test() + { + await InitialTokenContractAsync(); + var rentalUnitPriceInfo = await TokenContractStub.GetOwningRentalUnitValue.CallAsync(new Empty()); + rentalUnitPriceInfo.ResourceUnitValue.All(x => x.Value == Rental).ShouldBeTrue(); + var resourceUsageInfo = (await TokenContractStub.GetResourceUsage.CallAsync(new Empty())).Value; + resourceUsageInfo["CPU"].ShouldBe(CpuAmount); + resourceUsageInfo["RAM"].ShouldBe(RamAmount); + resourceUsageInfo["DISK"].ShouldBe(DiskAmount); + resourceUsageInfo["NET"].ShouldBe(NetAmount); + } - private const long Rental = 100; + [Fact] + public async Task ChargeRentalTest() + { + await InitialTokenContractAsync(); - public SideChainSideChainRentFeeTest() + // Check balance before mining { - DeployContracts(); + var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); + cpuBalance.ShouldBe(ResourceSupply); + var ramBalance = await GetCreatorBalanceOfAsync("RAM"); + ramBalance.ShouldBe(ResourceSupply); + var diskBalance = await GetCreatorBalanceOfAsync("DISK"); + diskBalance.ShouldBe(ResourceSupply); + var netBalance = await GetCreatorBalanceOfAsync("NET"); + netBalance.ShouldBe(ResourceSupply); } - [Fact] - public async Task SideChainRentalController_Test() + // charge every 1 minute + await DelayOneMinuteAsync(); + + // Check balance before mining { - var rentalControllerRet = - await TokenContractStub.GetSideChainRentalControllerCreateInfo.SendWithExceptionAsync(new Empty()); - rentalControllerRet.TransactionResult.Error.ShouldContain("side chain creator dose not exist"); - await InitialTokenContractAsync(); - var rentalController = - await TokenContractStub.GetSideChainRentalControllerCreateInfo.CallAsync(new Empty()); - rentalController.ShouldNotBeNull(); + var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); + cpuBalance.ShouldBe(ResourceSupply - CpuAmount * Rental); + var ramBalance = await GetCreatorBalanceOfAsync("RAM"); + ramBalance.ShouldBe(ResourceSupply - RamAmount * Rental); + var diskBalance = await GetCreatorBalanceOfAsync("DISK"); + diskBalance.ShouldBe(ResourceSupply - DiskAmount * Rental); + var netBalance = await GetCreatorBalanceOfAsync("NET"); + netBalance.ShouldBe(ResourceSupply - NetAmount * Rental); } + } + + [Fact] + public async Task OwnResourceTest() + { + await InitialTokenContractAsync(false); - [Fact] - public async Task GetRentalInfo_Test() + // Check balance before mining { - await InitialTokenContractAsync(); - var rentalUnitPriceInfo = await TokenContractStub.GetOwningRentalUnitValue.CallAsync(new Empty()); - rentalUnitPriceInfo.ResourceUnitValue.All(x => x.Value == Rental).ShouldBeTrue(); - var resourceUsageInfo = (await TokenContractStub.GetResourceUsage.CallAsync(new Empty())).Value; - resourceUsageInfo["CPU"].ShouldBe(CpuAmount); - resourceUsageInfo["RAM"].ShouldBe(RamAmount); - resourceUsageInfo["DISK"].ShouldBe(DiskAmount); - resourceUsageInfo["NET"].ShouldBe(NetAmount); + var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); + cpuBalance.ShouldBe(0); + var ramBalance = await GetCreatorBalanceOfAsync("RAM"); + ramBalance.ShouldBe(0); + var diskBalance = await GetCreatorBalanceOfAsync("DISK"); + diskBalance.ShouldBe(0); + var netBalance = await GetCreatorBalanceOfAsync("NET"); + netBalance.ShouldBe(0); } - [Fact] - public async Task ChargeRentalTest() - { - await InitialTokenContractAsync(); + await DelayOneMinuteAsync(); - // Check balance before mining - { - var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); - cpuBalance.ShouldBe(ResourceSupply); - var ramBalance = await GetCreatorBalanceOfAsync("RAM"); - ramBalance.ShouldBe(ResourceSupply); - var diskBalance = await GetCreatorBalanceOfAsync("DISK"); - diskBalance.ShouldBe(ResourceSupply); - var netBalance = await GetCreatorBalanceOfAsync("NET"); - netBalance.ShouldBe(ResourceSupply); - } - - // charge every 1 minute - await DelayOneMinuteAsync(); + var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); + owningRental.ResourceAmount["CPU"].ShouldBe(CpuAmount * Rental); + owningRental.ResourceAmount["RAM"].ShouldBe(RamAmount * Rental); + owningRental.ResourceAmount["DISK"].ShouldBe(DiskAmount * Rental); + owningRental.ResourceAmount["NET"].ShouldBe(NetAmount * Rental); + } + + [Fact] + public async Task PayDebtTest() + { + await OwnResourceTest(); - // Check balance before mining + // Charge + foreach (var symbol in Symbols) + await TokenContractStub.Issue.SendAsync(new IssueInput { - var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); - cpuBalance.ShouldBe(ResourceSupply - CpuAmount * Rental); - var ramBalance = await GetCreatorBalanceOfAsync("RAM"); - ramBalance.ShouldBe(ResourceSupply - RamAmount * Rental); - var diskBalance = await GetCreatorBalanceOfAsync("DISK"); - diskBalance.ShouldBe(ResourceSupply - DiskAmount * Rental); - var netBalance = await GetCreatorBalanceOfAsync("NET"); - netBalance.ShouldBe(ResourceSupply - NetAmount * Rental); - } + Symbol = symbol, + To = Creator, + Amount = ResourceSupply + }); + + var beforeConsensusCpuBalance = await GetBalanceOfConsensusAsync("CPU"); + var beforeConsensusRamBalance = await GetBalanceOfConsensusAsync("RAM"); + var beforeConsensusDiskBalance = await GetBalanceOfConsensusAsync("DISK"); + var beforeConsensusNetBalance = await GetBalanceOfConsensusAsync("NET"); + await DelayOneMinuteAsync(); + + var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); + owningRental.ResourceAmount["CPU"].ShouldBe(0); + owningRental.ResourceAmount["RAM"].ShouldBe(0); + owningRental.ResourceAmount["DISK"].ShouldBe(0); + owningRental.ResourceAmount["NET"].ShouldBe(0); + + // Check balance before mining + { + var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); + cpuBalance.ShouldBe(ResourceSupply - CpuAmount * Rental * 2); + var ramBalance = await GetCreatorBalanceOfAsync("RAM"); + ramBalance.ShouldBe(ResourceSupply - RamAmount * Rental * 2); + var diskBalance = await GetCreatorBalanceOfAsync("DISK"); + diskBalance.ShouldBe(ResourceSupply - DiskAmount * Rental * 2); + var netBalance = await GetCreatorBalanceOfAsync("NET"); + netBalance.ShouldBe(ResourceSupply - NetAmount * Rental * 2); } - [Fact] - public async Task OwnResourceTest() { - await InitialTokenContractAsync(false); + var afterConsensusCpuBalance = await GetBalanceOfConsensusAsync("CPU"); + var afterConsensusRamBalance = await GetBalanceOfConsensusAsync("RAM"); + var afterConsensusDiskBalance = await GetBalanceOfConsensusAsync("DISK"); + var afterConsensusNetBalance = await GetBalanceOfConsensusAsync("NET"); - // Check balance before mining - { - var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); - cpuBalance.ShouldBe(0); - var ramBalance = await GetCreatorBalanceOfAsync("RAM"); - ramBalance.ShouldBe(0); - var diskBalance = await GetCreatorBalanceOfAsync("DISK"); - diskBalance.ShouldBe(0); - var netBalance = await GetCreatorBalanceOfAsync("NET"); - netBalance.ShouldBe(0); - } - - await DelayOneMinuteAsync(); - - var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); - owningRental.ResourceAmount["CPU"].ShouldBe(CpuAmount * Rental); - owningRental.ResourceAmount["RAM"].ShouldBe(RamAmount * Rental); - owningRental.ResourceAmount["DISK"].ShouldBe(DiskAmount * Rental); - owningRental.ResourceAmount["NET"].ShouldBe(NetAmount * Rental); + (afterConsensusCpuBalance - beforeConsensusCpuBalance).ShouldBe(CpuAmount * Rental * 2); + (afterConsensusRamBalance - beforeConsensusRamBalance).ShouldBe(RamAmount * Rental * 2); + (afterConsensusDiskBalance - beforeConsensusDiskBalance).ShouldBe(DiskAmount * Rental * 2); + (afterConsensusNetBalance - beforeConsensusNetBalance).ShouldBe(NetAmount * Rental * 2); } + } - [Fact] - public async Task PayDebtTest() - { - await OwnResourceTest(); + [Fact] + public async Task PayDebtTest_NotEnough() + { + await OwnResourceTest(); - // Charge - foreach (var symbol in Symbols) - { - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - To = Creator, - Amount = ResourceSupply - }); - } - - var beforeConsensusCpuBalance = await GetBalanceOfConsensusAsync("CPU"); - var beforeConsensusRamBalance = await GetBalanceOfConsensusAsync("RAM"); - var beforeConsensusDiskBalance = await GetBalanceOfConsensusAsync("DISK"); - var beforeConsensusNetBalance = await GetBalanceOfConsensusAsync("NET"); - await DelayOneMinuteAsync(); - - var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); - owningRental.ResourceAmount["CPU"].ShouldBe(0); - owningRental.ResourceAmount["RAM"].ShouldBe(0); - owningRental.ResourceAmount["DISK"].ShouldBe(0); - owningRental.ResourceAmount["NET"].ShouldBe(0); - - // Check balance before mining + // Charge + foreach (var symbol in Symbols) + await TokenContractStub.Issue.SendAsync(new IssueInput { - var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); - cpuBalance.ShouldBe(ResourceSupply - CpuAmount * Rental * 2); - var ramBalance = await GetCreatorBalanceOfAsync("RAM"); - ramBalance.ShouldBe(ResourceSupply - RamAmount * Rental * 2); - var diskBalance = await GetCreatorBalanceOfAsync("DISK"); - diskBalance.ShouldBe(ResourceSupply - DiskAmount * Rental * 2); - var netBalance = await GetCreatorBalanceOfAsync("NET"); - netBalance.ShouldBe(ResourceSupply - NetAmount * Rental * 2); - } + Symbol = symbol, + To = Creator, + Amount = 1 + }); - { - var afterConsensusCpuBalance = await GetBalanceOfConsensusAsync("CPU"); - var afterConsensusRamBalance = await GetBalanceOfConsensusAsync("RAM"); - var afterConsensusDiskBalance = await GetBalanceOfConsensusAsync("DISK"); - var afterConsensusNetBalance = await GetBalanceOfConsensusAsync("NET"); - - (afterConsensusCpuBalance - beforeConsensusCpuBalance).ShouldBe(CpuAmount * Rental * 2); - (afterConsensusRamBalance - beforeConsensusRamBalance).ShouldBe(RamAmount * Rental * 2); - (afterConsensusDiskBalance - beforeConsensusDiskBalance).ShouldBe(DiskAmount * Rental * 2); - (afterConsensusNetBalance - beforeConsensusNetBalance).ShouldBe(NetAmount * Rental * 2); - } - } + await DelayOneMinuteAsync(); - [Fact] - public async Task PayDebtTest_NotEnough() - { - await OwnResourceTest(); + var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); + owningRental.ResourceAmount["CPU"].ShouldBe(CpuAmount * Rental * 2 - 1); + owningRental.ResourceAmount["RAM"].ShouldBe(RamAmount * Rental * 2 - 1); + owningRental.ResourceAmount["DISK"].ShouldBe(DiskAmount * Rental * 2 - 1); + owningRental.ResourceAmount["NET"].ShouldBe(NetAmount * Rental * 2 - 1); - // Charge - foreach (var symbol in Symbols) - { - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - To = Creator, - Amount = 1 - }); - } - - await DelayOneMinuteAsync(); - - var owningRental = await TokenContractStub.GetOwningRental.CallAsync(new Empty()); - owningRental.ResourceAmount["CPU"].ShouldBe(CpuAmount * Rental * 2 - 1); - owningRental.ResourceAmount["RAM"].ShouldBe(RamAmount * Rental * 2 - 1); - owningRental.ResourceAmount["DISK"].ShouldBe(DiskAmount * Rental * 2 - 1); - owningRental.ResourceAmount["NET"].ShouldBe(NetAmount * Rental * 2 - 1); - - // Check balance before mining - { - var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); - cpuBalance.ShouldBe(0); - var ramBalance = await GetCreatorBalanceOfAsync("RAM"); - ramBalance.ShouldBe(0); - var diskBalance = await GetCreatorBalanceOfAsync("DISK"); - diskBalance.ShouldBe(0); - var netBalance = await GetCreatorBalanceOfAsync("NET"); - netBalance.ShouldBe(0); - } + // Check balance before mining + { + var cpuBalance = await GetCreatorBalanceOfAsync("CPU"); + cpuBalance.ShouldBe(0); + var ramBalance = await GetCreatorBalanceOfAsync("RAM"); + ramBalance.ShouldBe(0); + var diskBalance = await GetCreatorBalanceOfAsync("DISK"); + diskBalance.ShouldBe(0); + var netBalance = await GetCreatorBalanceOfAsync("NET"); + netBalance.ShouldBe(0); } + } - [Fact] - public async Task ChangeSIdeChainRentalController_Fail() + [Fact] + public async Task ChangeSIdeChainRentalController_Fail() + { + await InitialTokenContractAsync(); + var updateRet = + await TokenContractStub.ChangeSideChainRentalController.SendWithExceptionAsync(new AuthorityInfo()); + updateRet.TransactionResult.Error.ShouldContain("no permission"); + + var authority = new AuthorityInfo { - await InitialTokenContractAsync(); - var updateRet = - await TokenContractStub.ChangeSideChainRentalController.SendWithExceptionAsync(new AuthorityInfo()); - updateRet.TransactionResult.Error.ShouldContain("no permission"); - - var authority = new AuthorityInfo - { - ContractAddress = AssociationContractAddress, - OwnerAddress = ConsensusContractAddress - }; + ContractAddress = AssociationContractAddress, + OwnerAddress = ConsensusContractAddress + }; - var invalidInputRet = await UpdateSideChainRentalDefaultProposalWithExceptionAsync( - nameof(TokenContractImplContainer.TokenContractImplStub.ChangeSideChainRentalController), authority); - invalidInputRet.Error.ShouldContain("new controller does not exist"); - } - - [Fact] - public async Task ChangeSIdeChainRentalController_Success() + var invalidInputRet = await UpdateSideChainRentalDefaultProposalWithExceptionAsync( + nameof(TokenContractImplContainer.TokenContractImplStub.ChangeSideChainRentalController), authority); + invalidInputRet.Error.ShouldContain("new controller does not exist"); + } + + [Fact] + public async Task ChangeSIdeChainRentalController_Success() + { + await InitialTokenContractAsync(); + var member = Accounts[0].Address; + var proposers = new List
{ member }; + var newOrganizationCreationInput = new CreateOrganizationInput { - await InitialTokenContractAsync(); - var member = Accounts[0].Address; - var proposers = new List
{member}; - var newOrganizationCreationInput = new CreateOrganizationInput + OrganizationMemberList = new OrganizationMemberList { - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {proposers} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = proposers.Count, - MinimalVoteThreshold = proposers.Count, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } - }; - var createNewAssociationOrganization = - await AssociationContractStub.CreateOrganization.SendAsync(newOrganizationCreationInput); - var newControllerAddress = new Address(); - newControllerAddress.MergeFrom(createNewAssociationOrganization.TransactionResult.ReturnValue); - var authority = new AuthorityInfo + OrganizationMembers = { proposers } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ContractAddress = AssociationContractAddress, - OwnerAddress = newControllerAddress - }; - - await UpdateSideChainRentalDefaultProposalAsync( - nameof(TokenContractImplContainer.TokenContractImplStub.ChangeSideChainRentalController), authority); - var updateParam = new UpdateRentedResourcesInput(); - var symbolDic = new Dictionary {["CPU"] = 101}; - updateParam.ResourceAmount.Add(symbolDic); - var updateProposal = new CreateProposalInput + MinimalApprovalThreshold = proposers.Count, + MinimalVoteThreshold = proposers.Count, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList { - ToAddress = TokenContractAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.UpdateRentedResources), - Params = updateParam.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = newControllerAddress - }; - var updateProposalRet = (await AssociationContractStub.CreateProposal.SendAsync(updateProposal)) - .TransactionResult; - var updateProposalId = new Hash(); - updateProposalId.MergeFrom(updateProposalRet.ReturnValue); - await AssociationContractStub.Approve.SendAsync(updateProposalId); - await AssociationContractStub.Release.SendAsync(updateProposalId); - var resourceUsage = await TokenContractStub.GetResourceUsage.CallAsync(new Empty()); - resourceUsage.Value["CPU"].ShouldBe(101); - } - private async Task DelayOneMinuteAsync() - { - var times = 6; - while (times-- > 0) - { - await TokenContractStub.GetBalance.SendAsync(new GetBalanceInput // each tx set 10 seconds - { - Owner = Creator, - Symbol = "CPU" - }); + Proposers = { proposers } } - } - - private async Task InitialTokenContractAsync(bool issueToken = true) - { - await CreateTokenAsync("CPU", ResourceSupply, issueToken); - await CreateTokenAsync("RAM", ResourceSupply, issueToken); - await CreateTokenAsync("DISK", ResourceSupply, issueToken); - await CreateTokenAsync("NET", ResourceSupply, issueToken); - var defaultParliamentOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var setSideChainCreatorProposalInput = new InitializeFromParentChainInput - { - ResourceAmount = - { - {"CPU", CpuAmount}, - {"RAM", RamAmount}, - {"DISK", DiskAmount}, - {"NET", NetAmount} - }, - Creator = Creator - }; - await ParliamentReachAnAgreementAsync(TokenContractAddress, defaultParliamentOrganization, - nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), - setSideChainCreatorProposalInput); - - var updateRentalInput = new UpdateRentalInput - { - Rental = - { - {"CPU", Rental}, - {"RAM", Rental}, - {"DISK", Rental}, - {"NET", Rental}, - } - }; - await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput{Symbol = NativeTokenSymbol}); - await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - await UpdateSideChainRentalDefaultProposalAsync( - nameof(TokenContractImplContainer.TokenContractImplStub.UpdateRental), updateRentalInput); - } - private async Task CreateTokenAsync(string symbol, long supply, bool issueToken) + }; + var createNewAssociationOrganization = + await AssociationContractStub.CreateOrganization.SendAsync(newOrganizationCreationInput); + var newControllerAddress = new Address(); + newControllerAddress.MergeFrom(createNewAssociationOrganization.TransactionResult.ReturnValue); + var authority = new AuthorityInfo { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Decimals = 8, - Issuer = Creator, - Symbol = symbol, - TotalSupply = supply, - IsBurnable = true, - TokenName = $"{symbol} token." - }); + ContractAddress = AssociationContractAddress, + OwnerAddress = newControllerAddress + }; - if (!issueToken) - { - return; - } + await UpdateSideChainRentalDefaultProposalAsync( + nameof(TokenContractImplContainer.TokenContractImplStub.ChangeSideChainRentalController), authority); + var updateParam = new UpdateRentedResourcesInput(); + var symbolDic = new Dictionary { ["CPU"] = 101 }; + updateParam.ResourceAmount.Add(symbolDic); + var updateProposal = new CreateProposalInput + { + ToAddress = TokenContractAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.UpdateRentedResources), + Params = updateParam.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = newControllerAddress + }; + var updateProposalRet = (await AssociationContractStub.CreateProposal.SendAsync(updateProposal)) + .TransactionResult; + var updateProposalId = new Hash(); + updateProposalId.MergeFrom(updateProposalRet.ReturnValue); + await AssociationContractStub.Approve.SendAsync(updateProposalId); + await AssociationContractStub.Release.SendAsync(updateProposalId); + var resourceUsage = await TokenContractStub.GetResourceUsage.CallAsync(new Empty()); + resourceUsage.Value["CPU"].ShouldBe(101); + } - await TokenContractStub.Issue.SendAsync(new IssueInput + private async Task DelayOneMinuteAsync() + { + var times = 6; + while (times-- > 0) + await TokenContractStub.GetBalance.SendAsync(new GetBalanceInput // each tx set 10 seconds { - Symbol = symbol, - To = Creator, - Amount = supply + Owner = Creator, + Symbol = "CPU" }); - } + } - private async Task GetCreatorBalanceOfAsync(string symbol) + private async Task InitialTokenContractAsync(bool issueToken = true) + { + await CreateTokenAsync("CPU", ResourceSupply, issueToken); + await CreateTokenAsync("RAM", ResourceSupply, issueToken); + await CreateTokenAsync("DISK", ResourceSupply, issueToken); + await CreateTokenAsync("NET", ResourceSupply, issueToken); + var defaultParliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var setSideChainCreatorProposalInput = new InitializeFromParentChainInput { - return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + ResourceAmount = { - Owner = Creator, - Symbol = symbol - })).Balance; - } - - private async Task GetBalanceOfConsensusAsync(string symbol) + { "CPU", CpuAmount }, + { "RAM", RamAmount }, + { "DISK", DiskAmount }, + { "NET", NetAmount } + }, + Creator = Creator + }; + await ParliamentReachAnAgreementAsync(TokenContractAddress, defaultParliamentOrganization, + nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), + setSideChainCreatorProposalInput); + + var updateRentalInput = new UpdateRentalInput { - return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + Rental = { - Owner = ConsensusContractAddress, - Symbol = symbol - })).Balance; - } + { "CPU", Rental }, + { "RAM", Rental }, + { "DISK", Rental }, + { "NET", Rental } + } + }; + await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput + { Symbol = NativeTokenSymbol }); + await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + await UpdateSideChainRentalDefaultProposalAsync( + nameof(TokenContractImplContainer.TokenContractImplStub.UpdateRental), updateRentalInput); + } - private async Task ParliamentReachAnAgreementAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task CreateTokenAsync(string symbol, long supply, bool issueToken) + { + await TokenContractStub.Create.SendAsync(new CreateInput { - var proposalId = await CreateFeeProposalAsync(contractAddress, organizationAddress, methodName, input); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - } + Decimals = 8, + Issuer = Creator, + Symbol = symbol, + TotalSupply = supply, + IsBurnable = true, + TokenName = $"{symbol} token." + }); - private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + if (!issueToken) return; + + await TokenContractStub.Issue.SendAsync(new IssueInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; - - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; - return proposalId; - } + Symbol = symbol, + To = Creator, + Amount = supply + }); + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task GetCreatorBalanceOfAsync(string symbol) + { + return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } - } - - private async Task CreateApproveAndToSideChainRentalDefaultProposalAsync(string methodName, - IMessage message) + Owner = Creator, + Symbol = symbol + })).Balance; + } + + private async Task GetBalanceOfConsensusAsync(string symbol) + { + return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var defaultController = - await TokenContractStub.GetSideChainRentalControllerCreateInfo.CallAsync(new Empty()); - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var toAssociationProposal = new CreateProposalInput - { - ToAddress = TokenContractAddress, - ContractMethodName = methodName, - Params = message.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = defaultController.OwnerAddress - }; - var associationProposalRet = (await AssociationContractStub.CreateProposal.SendAsync(toAssociationProposal)) - .TransactionResult; - var associationProposalId = new Hash(); - associationProposalId.MergeFrom(associationProposalRet.ReturnValue); - await ParliamentReachAnAgreementAsync(AssociationContractAddress, defaultParliamentAddress, - nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), associationProposalId); - await AssociationContractStub.Approve.SendAsync(associationProposalId); - return associationProposalId; - } + Owner = ConsensusContractAddress, + Symbol = symbol + })).Balance; + } - private async Task UpdateSideChainRentalDefaultProposalAsync(string methodName, - IMessage message) + private async Task ParliamentReachAnAgreementAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposalId = await CreateFeeProposalAsync(contractAddress, organizationAddress, methodName, input); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + } + + private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var associationProposalId = await CreateApproveAndToSideChainRentalDefaultProposalAsync(methodName, message); - await AssociationContractStub.Release.SendAsync(associationProposalId); - } - private async Task UpdateSideChainRentalDefaultProposalWithExceptionAsync(string methodName, - IMessage message) + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + return proposalId; + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - var associationProposalId = await CreateApproveAndToSideChainRentalDefaultProposalAsync(methodName, message); - return (await AssociationContractStub.Release.SendWithExceptionAsync(associationProposalId)).TransactionResult; + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } + + private async Task CreateApproveAndToSideChainRentalDefaultProposalAsync(string methodName, + IMessage message) + { + var defaultController = + await TokenContractStub.GetSideChainRentalControllerCreateInfo.CallAsync(new Empty()); + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var toAssociationProposal = new CreateProposalInput + { + ToAddress = TokenContractAddress, + ContractMethodName = methodName, + Params = message.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultController.OwnerAddress + }; + var associationProposalRet = (await AssociationContractStub.CreateProposal.SendAsync(toAssociationProposal)) + .TransactionResult; + var associationProposalId = new Hash(); + associationProposalId.MergeFrom(associationProposalRet.ReturnValue); + await ParliamentReachAnAgreementAsync(AssociationContractAddress, defaultParliamentAddress, + nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), associationProposalId); + await AssociationContractStub.Approve.SendAsync(associationProposalId); + return associationProposalId; + } + + private async Task UpdateSideChainRentalDefaultProposalAsync(string methodName, + IMessage message) + { + var associationProposalId = await CreateApproveAndToSideChainRentalDefaultProposalAsync(methodName, message); + await AssociationContractStub.Release.SendAsync(associationProposalId); + } + + private async Task UpdateSideChainRentalDefaultProposalWithExceptionAsync(string methodName, + IMessage message) + { + var associationProposalId = await CreateApproveAndToSideChainRentalDefaultProposalAsync(methodName, message); + return (await AssociationContractStub.Release.SendWithExceptionAsync(associationProposalId)).TransactionResult; + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/AElf.Contracts.Association.Tests.csproj b/test/AElf.Contracts.Association.Tests/AElf.Contracts.Association.Tests.csproj index 2017ab30bb..a4dda3f67f 100644 --- a/test/AElf.Contracts.Association.Tests/AElf.Contracts.Association.Tests.csproj +++ b/test/AElf.Contracts.Association.Tests/AElf.Contracts.Association.Tests.csproj @@ -10,16 +10,16 @@ 0436 - - - - - - + + + + + + - + @@ -77,5 +77,5 @@ - + diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTestAElfModule.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTestAElfModule.cs index c7311e9566..07e57a2412 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTestAElfModule.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTestAElfModule.cs @@ -14,49 +14,48 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(GovernmentSystemAElfModule))] +public class AssociationContractTestAElfModule : AbpModule { - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(GovernmentSystemAElfModule))] - public class AssociationContractTestAElfModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = - SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); - }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.RemoveAll(s => s.ImplementationType == typeof(TokenContractInitializationProvider)); - } - - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + Configure(options => { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + options.MiningInterval = 4000; + options.InitialMinerList = + SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); + }); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.RemoveAll(s => s.ImplementationType == typeof(TokenContractInitializationProvider)); } - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(GovernmentSystemAElfModule))] - public class AssociationContractTestAElfModuleWithSpecificChainId : AssociationContractTestAElfModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - base.ConfigureServices(context); - Configure(options => options.ChainId = 1); - } + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); + } +} + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(GovernmentSystemAElfModule))] +public class AssociationContractTestAElfModuleWithSpecificChainId : AssociationContractTestAElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + base.ConfigureServices(context); + Configure(options => options.ChainId = 1); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTestBase.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTestBase.cs index f2555ba529..f2694bdd5e 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTestBase.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTestBase.cs @@ -8,53 +8,54 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public class AssociationContractTestBase : ContractTestBase where T : AbpModule { - public class AssociationContractTestBase : ContractTestBase where T : AbpModule + public AssociationContractTestBase() + { + AssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + + TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); + + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + } + + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected ECKeyPair Reviewer1KeyPair => Accounts[1].KeyPair; + protected ECKeyPair Reviewer2KeyPair => Accounts[2].KeyPair; + protected ECKeyPair Reviewer3KeyPair => Accounts[3].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + protected Address Reviewer1 => Accounts[1].Address; + protected Address Reviewer2 => Accounts[2].Address; + protected Address Reviewer3 => Accounts[3].Address; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); + + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; } + internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub { get; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; } + + internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractTester( + ECKeyPair keyPair) + { + return GetTester(AssociationContractAddress, + keyPair); + } + + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) { - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected ECKeyPair Reviewer1KeyPair => Accounts[1].KeyPair; - protected ECKeyPair Reviewer2KeyPair => Accounts[2].KeyPair; - protected ECKeyPair Reviewer3KeyPair => Accounts[3].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - protected Address Reviewer1 => Accounts[1].Address; - protected Address Reviewer2 => Accounts[2].Address; - protected Address Reviewer3 => Accounts[3].Address; - - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); - - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; } - internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub { get; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; } - - public AssociationContractTestBase() - { - AssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); - - TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - } - - internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractTester(ECKeyPair keyPair) - { - return GetTester(AssociationContractAddress, keyPair); - } - - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + return GetTester(ParliamentContractAddress, + keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs index 5ce732415b..ad6ff414d9 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs @@ -1,7 +1,5 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.ContractTestBase.ContractTestKit; using AElf.Cryptography.ECDSA; @@ -10,40 +8,89 @@ using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public class AssociationContractTests : AssociationContractTestBase { - public class AssociationContractTests : AssociationContractTestBase + private readonly IBlockchainService _blockchainService; + private readonly TestDemoSmartContractAddressNameProvider _smartContractAddressNameProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + + public AssociationContractTests() { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainService _blockchainService; - private readonly TestDemoSmartContractAddressNameProvider _smartContractAddressNameProvider; + _smartContractAddressService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _smartContractAddressNameProvider = GetRequiredService(); + } - public AssociationContractTests() + [Fact] + public async Task Get_Organization_Test() + { + //failed case { - _smartContractAddressService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _smartContractAddressNameProvider = GetRequiredService(); + var organization = + await AssociationContractStub.GetOrganization.CallAsync(Accounts[0].Address); + organization.ShouldBe(new Organization()); } + } - [Fact] - public async Task Get_Organization_Test() + [Fact] + public async Task CreateOrganization_Success_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var createOrganizationInput = new CreateOrganizationInput { - //failed case + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { Reviewer1, Reviewer2, Reviewer3 } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList { - var organization = - await AssociationContractStub.GetOrganization.CallAsync(Accounts[0].Address); - organization.ShouldBe(new Organization()); + Proposers = { Reviewer1 } } + }; + var transactionResult = + await AssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = transactionResult.Output; + var getOrganization = await AssociationContractStub.GetOrganization.CallAsync(organizationAddress); + + getOrganization.OrganizationAddress.ShouldBe(organizationAddress); + getOrganization.ProposerWhiteList.ShouldBe(createOrganizationInput.ProposerWhiteList); + getOrganization.ProposalReleaseThreshold.ShouldBe(createOrganizationInput.ProposalReleaseThreshold); + getOrganization.OrganizationMemberList.ShouldBe(createOrganizationInput.OrganizationMemberList); + getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); + } + + [Fact] + public async Task Create_OrganizationOnMultiChains_Test() + { + //failed case + { + var organization = + await AssociationContractStub.GetOrganization.CallAsync(Accounts[0].Address); + organization.ShouldBe(new Organization()); } - [Fact] - public async Task CreateOrganization_Success_Test() + //normal case { var minimalApproveThreshold = 2; var minimalVoteThreshold = 3; @@ -53,7 +100,7 @@ public async Task CreateOrganization_Success_Test() { OrganizationMemberList = new OrganizationMemberList { - OrganizationMembers = {Reviewer1, Reviewer2, Reviewer3} + OrganizationMembers = { Reviewer1, Reviewer2, Reviewer3 } }, ProposalReleaseThreshold = new ProposalReleaseThreshold { @@ -64,1357 +111,1311 @@ public async Task CreateOrganization_Success_Test() }, ProposerWhiteList = new ProposerWhiteList { - Proposers = {Reviewer1} + Proposers = { Reviewer1 } } }; var transactionResult = await AssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var organizationAddress = transactionResult.Output; - var getOrganization = await AssociationContractStub.GetOrganization.CallAsync(organizationAddress); - getOrganization.OrganizationAddress.ShouldBe(organizationAddress); - getOrganization.ProposerWhiteList.ShouldBe(createOrganizationInput.ProposerWhiteList); - getOrganization.ProposalReleaseThreshold.ShouldBe(createOrganizationInput.ProposalReleaseThreshold); - getOrganization.OrganizationMemberList.ShouldBe(createOrganizationInput.OrganizationMemberList); - getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); + var testKit = CreateContractTestKit(new ChainInitializationDto + { + ChainId = 1 + }); + SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name] + .ShouldNotBe(testKit.SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name]); + var otherChainAssociationContractStub = + testKit.GetTester( + testKit.SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name], + DefaultSenderKeyPair); + var executionResult = + await otherChainAssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); + var organizationAddressOnAnotherChain = executionResult.Output; + organizationAddressOnAnotherChain.ShouldBe(organizationAddress); } + } - [Fact] - public async Task Create_OrganizationOnMultiChains_Test() + [Fact] + public async Task Get_Proposal_Test() + { + //failed case { - //failed case - { - var organization = - await AssociationContractStub.GetOrganization.CallAsync(Accounts[0].Address); - organization.ShouldBe(new Organization()); - } + var proposal = await AssociationContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); + proposal.ShouldBe(new ProposalOutput()); + } - //normal case + //normal case + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var transferInput = new TransferInput { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var createOrganizationInput = new CreateOrganizationInput - { - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {Reviewer1, Reviewer2, Reviewer3} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {Reviewer1} - } - }; - var transactionResult = - await AssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var organizationAddress = transactionResult.Output; - - var testKit = CreateContractTestKit(new ChainInitializationDto - { - ChainId = 1 - }); - SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name] - .ShouldNotBe(testKit.SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name]); - var otherChainAssociationContractStub = - testKit.GetTester( - testKit.SystemContractAddresses[AssociationSmartContractAddressNameProvider.Name], - DefaultSenderKeyPair); - var executionResult = - await otherChainAssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); - var organizationAddressOnAnotherChain = executionResult.Output; - organizationAddressOnAnotherChain.ShouldBe(organizationAddress); - } + Symbol = "ELF", + Amount = 100, + To = Reviewer1, + Memo = "Transfer" + }; + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + var getProposal = await AssociationContractStub.GetProposal.SendAsync(proposalId); + + getProposal.Output.Proposer.ShouldBe(Reviewer1); + getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContractStub.Transfer)); + getProposal.Output.ProposalId.ShouldBe(proposalId); + getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); + getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); + getProposal.Output.Params.ShouldBe(transferInput.ToByteString()); } + } - [Fact] - public async Task Get_Proposal_Test() + [Fact] + public async Task Create_Organization_Failed_Test() + { + //invalid MinimalApprovalThreshold { - //failed case - { - var proposal = await AssociationContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); - proposal.ShouldBe(new ProposalOutput()); - } + var minimalApproveThreshold = 0; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - //normal case - { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transferInput = new TransferInput() - { - Symbol = "ELF", - Amount = 100, - To = Reviewer1, - Memo = "Transfer" - }; - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - var getProposal = await AssociationContractStub.GetProposal.SendAsync(proposalId); - - getProposal.Output.Proposer.ShouldBe(Reviewer1); - getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContractStub.Transfer)); - getProposal.Output.ProposalId.ShouldBe(proposalId); - getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); - getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); - getProposal.Output.Params.ShouldBe(transferInput.ToByteString()); - } + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Create_Organization_Failed_Test() + //invalid MinimalApprovalThreshold { - //invalid MinimalApprovalThreshold - { - var minimalApproveThreshold = 0; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } - - //invalid MinimalApprovalThreshold - { - var minimalApproveThreshold = 4; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; + var minimalApproveThreshold = 4; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } - //invalid MinimalApprovalThreshold - { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 1; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + //invalid MinimalApprovalThreshold + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 1; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - //invalid minimalVoteThreshold - { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 0; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - //invalid maximalAbstentionThreshold - { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 4; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } - //invalid minimalVoteThreshold + maximalAbstentionThreshold - { - var minimalApproveThreshold = 3; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + //invalid minimalVoteThreshold + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 0; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - //invalid minimalVoteThreshold + maximalRejectionThreshold - { - var minimalApproveThreshold = 3; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 1; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } - // empty proposer white list - { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 2; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + //invalid maximalAbstentionThreshold + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 4; + var maximalRejectionThreshold = 0; - // empty organization members - { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 2; - var maximalAbstentionThreshold = 0; - var maximalRejectionThreshold = 0; - - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, - minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - createOrganizationInput.OrganizationMemberList = new OrganizationMemberList(); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Create_Proposal_Failed_Test() + //invalid minimalVoteThreshold + maximalAbstentionThreshold { - var minimalApproveThreshold = 2; + var minimalApproveThreshold = 3; var minimalVoteThreshold = 3; var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 0; + + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } + + //invalid minimalVoteThreshold + maximalRejectionThreshold + { + var minimalApproveThreshold = 3; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 0; var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var blockTime = BlockTimeProvider.GetBlockTime(); - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = blockTime.AddDays(1), - OrganizationAddress = organizationAddress - }; - //"Invalid proposal." - //ContractMethodName is null or white space - { - var transactionResult = - await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //ToAddress is null - { - createProposalInput.ContractMethodName = "Test"; - createProposalInput.ToAddress = null; + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } - var transactionResult = - await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //ExpiredTime is null - { - createProposalInput.ExpiredTime = null; - createProposalInput.ToAddress = Accounts[0].Address; + // empty proposer white list + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 2; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - var transactionResult = - await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //"Expired proposal." - { - createProposalInput.ExpiredTime = blockTime.AddMilliseconds(5); - BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(10)); + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } - var transactionResult = - await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - //"No registered organization." - { - createProposalInput.ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1); - createProposalInput.OrganizationAddress = Accounts[1].Address; + // empty organization members + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 2; + var maximalAbstentionThreshold = 0; + var maximalRejectionThreshold = 0; - var transactionResult = - await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("No registered organization.").ShouldBeTrue(); - } - //"Unable to propose." - //Reviewer is not permission to propose - { - createProposalInput.OrganizationAddress = organizationAddress; - var anotherAssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, + minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + createOrganizationInput.OrganizationMemberList = new OrganizationMemberList(); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); + } + } - var transactionResult = - await anotherAssociationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } + [Fact] + public async Task Create_Proposal_Failed_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var blockTime = BlockTimeProvider.GetBlockTime(); + var createProposalInput = new CreateProposalInput + { + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = blockTime.AddDays(1), + OrganizationAddress = organizationAddress + }; + //"Invalid proposal." + //ContractMethodName is null or white space + { + var transactionResult = + await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); + } + //ToAddress is null + { + createProposalInput.ContractMethodName = "Test"; + createProposalInput.ToAddress = null; - //"Proposal with same input." - { - var transactionResult1 = - await associationContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionResult = + await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); + } + //ExpiredTime is null + { + createProposalInput.ExpiredTime = null; + createProposalInput.ToAddress = Accounts[0].Address; - var transactionResult2 = - await associationContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var transactionResult = + await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); + } + //"Expired proposal." + { + createProposalInput.ExpiredTime = blockTime.AddMilliseconds(5); + BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(10)); - // "Proposal with invalid url" - { - var anotherAssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); - createProposalInput.ProposalDescriptionUrl = "test.com"; - var transactionResult = - await anotherAssociationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - createProposalInput.ProposalDescriptionUrl = "https://test.com/test%abcd%&wxyz"; - var transactionResult2 = - await associationContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var transactionResult = + await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); } + //"No registered organization." + { + createProposalInput.ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1); + createProposalInput.OrganizationAddress = Accounts[1].Address; - [Fact] - public async Task Approve_Proposal_NotFoundProposal_Test() + var transactionResult = + await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("No registered organization.").ShouldBeTrue(); + } + //"Unable to propose." + //Reviewer is not permission to propose { + createProposalInput.OrganizationAddress = organizationAddress; + var anotherAssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + var transactionResult = - await AssociationContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + await anotherAssociationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); } - [Fact] - public async Task Approve_Proposal_NotAuthorizedApproval_Test() + //"Proposal with same input." { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var transactionResult1 = + await associationContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - var associationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); - var transactionResult = await associationContractStub.Approve.SendWithExceptionAsync(proposalId); + var transactionResult2 = + await associationContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + // "Proposal with invalid url" + { + var anotherAssociationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + createProposalInput.ProposalDescriptionUrl = "test.com"; + var transactionResult = + await anotherAssociationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + createProposalInput.ProposalDescriptionUrl = "https://test.com/test%abcd%&wxyz"; + var transactionResult2 = + await associationContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - [Fact] - public async Task ClearProposal_Fail_Test() + [Fact] + public async Task Approve_Proposal_NotFoundProposal_Test() + { + var transactionResult = + await AssociationContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } + + [Fact] + public async Task Approve_Proposal_NotAuthorizedApproval_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + var associationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + var transactionResult = await associationContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } + + [Fact] + public async Task ClearProposal_Fail_Test() + { + // proposal does not exist { - // proposal does not exist - { - var ret = await AssociationContractStub.ClearProposal.SendWithExceptionAsync(new Hash()); - ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } - - //proposal does not expire - { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var ret = await AssociationContractStub.ClearProposal.SendWithExceptionAsync(proposalId); - ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } + var ret = await AssociationContractStub.ClearProposal.SendWithExceptionAsync(new Hash()); + ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); } - [Fact] - public async Task Approve_Proposal_ExpiredTime_Test() + //proposal does not expire { var minimalApproveThreshold = 2; var minimalVoteThreshold = 3; var maximalAbstentionThreshold = 1; var maximalRejectionThreshold = 1; var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var ret = await AssociationContractStub.ClearProposal.SendWithExceptionAsync(proposalId); + ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); + } + } + + [Fact] + public async Task Approve_Proposal_ExpiredTime_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var error = await associationContractStub.Approve.CallWithExceptionAsync(proposalId); + error.Value.ShouldContain("Invalid proposal."); + + //Clear expire proposal + var result = await associationContractStub.ClearProposal.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var queryProposal = await AssociationContractStub.GetProposal.CallAsync(proposalId); + queryProposal.ShouldBe(new ProposalOutput()); + } + + [Fact] + public async Task Approve_Proposal_ApprovalAlreadyExists_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + + var transactionResult1 = + await associationContractStub.Approve.SendAsync(proposalId); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transactionResult2 = + await associationContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } + + [Fact] + public async Task Approve_Proposal_Failed_Test() + { + //not found + { + var transactionResult = + await AssociationContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } + + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + + //not authorize + { + var associationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); + var transactionResult = await associationContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } + + //expired time + { var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); var error = await associationContractStub.Approve.CallWithExceptionAsync(proposalId); error.Value.ShouldContain("Invalid proposal."); - - //Clear expire proposal - var result = await associationContractStub.ClearProposal.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var queryProposal = await AssociationContractStub.GetProposal.CallAsync(proposalId); - queryProposal.ShouldBe(new ProposalOutput()); } - [Fact] - public async Task Approve_Proposal_ApprovalAlreadyExists_Test() + //already exist { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(-5)); var transactionResult1 = await associationContractStub.Approve.SendAsync(proposalId); transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var transactionResult2 = - await associationContractStub.Approve.SendWithExceptionAsync(proposalId); + await associationContractStub.Reject.SendWithExceptionAsync(proposalId); transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult2.TransactionResult.Error.Contains("Sender already voted").ShouldBeTrue(); + + var transactionResult3 = + await associationContractStub.Abstain.SendWithExceptionAsync(proposalId); + transactionResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult3.TransactionResult.Error.Contains("Sender already voted").ShouldBeTrue(); } + } - [Fact] - public async Task Approve_Proposal_Failed_Test() + [Fact] + public async Task Check_Proposal_ToBeRelease() + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + //Abstain probability >= maximalAbstentionThreshold { - //not found - { - var transactionResult = - await AssociationContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - - //not authorize - { - var associationContractStub = GetAssociationContractTester(DefaultSenderKeyPair); - var transactionResult = await associationContractStub.Approve.SendWithExceptionAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - - //expired time - { - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var error = await associationContractStub.Approve.CallWithExceptionAsync(proposalId); - error.Value.ShouldContain("Invalid proposal."); - } - - //already exist - { - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(-5)); - var transactionResult1 = - await associationContractStub.Approve.SendAsync(proposalId); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transactionResult2 = - await associationContractStub.Reject.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult2.TransactionResult.Error.Contains("Sender already voted").ShouldBeTrue(); - - var transactionResult3 = - await associationContractStub.Abstain.SendWithExceptionAsync(proposalId); - transactionResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult3.TransactionResult.Error.Contains("Sender already voted").ShouldBeTrue(); - } + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + await AbstainAsync(Reviewer2KeyPair, proposalId); + await AbstainAsync(Reviewer3KeyPair, proposalId); + await ApproveAsync(Reviewer1KeyPair, proposalId); + var result = await associationContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeFalse(); } - - [Fact] - public async Task Check_Proposal_ToBeRelease() + //Rejection probability > maximalRejectionThreshold { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - //Abstain probability >= maximalAbstentionThreshold - { - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - await AbstainAsync(Reviewer2KeyPair, proposalId); - await AbstainAsync(Reviewer3KeyPair, proposalId); - await ApproveAsync(Reviewer1KeyPair, proposalId); - var result = await associationContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeFalse(); - } - //Rejection probability > maximalRejectionThreshold - { - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - await RejectAsync(Reviewer1KeyPair, proposalId); - await RejectAsync(Reviewer2KeyPair, proposalId); - await ApproveAsync(Reviewer3KeyPair, proposalId); - var result = await associationContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeFalse(); - } - //Approve probability > minimalApprovalThreshold && voted count >= minimalVoteThreshold - { - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - await AbstainAsync(Reviewer1KeyPair, proposalId); - await RejectAsync(Reviewer2KeyPair, proposalId); - await ApproveAsync(Reviewer3KeyPair, proposalId); - var result = await associationContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeTrue(); - } + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + await RejectAsync(Reviewer1KeyPair, proposalId); + await RejectAsync(Reviewer2KeyPair, proposalId); + await ApproveAsync(Reviewer3KeyPair, proposalId); + var result = await associationContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeFalse(); } - - [Fact] - public async Task Release_Proposal_Failed_Test() + //Approve probability > minimalApprovalThreshold && voted count >= minimalVoteThreshold { - //not found - { - var fakeId = HashHelper.ComputeFrom("test"); - var associationContractStub = GetAssociationContractTester(Reviewer2KeyPair); - var result = await associationContractStub.Release.SendWithExceptionAsync(fakeId); - //Proposal not found - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Invalid proposal id.").ShouldBeTrue(); - } - - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + await AbstainAsync(Reviewer1KeyPair, proposalId); + await RejectAsync(Reviewer2KeyPair, proposalId); + await ApproveAsync(Reviewer3KeyPair, proposalId); + var result = await associationContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeTrue(); + } + } - { - await ApproveAsync(Reviewer1KeyPair, proposalId); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var result = await associationContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); - } + [Fact] + public async Task Release_Proposal_Failed_Test() + { + //not found + { + var fakeId = HashHelper.ComputeFrom("test"); + var associationContractStub = GetAssociationContractTester(Reviewer2KeyPair); + var result = await associationContractStub.Release.SendWithExceptionAsync(fakeId); + //Proposal not found + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Invalid proposal id.").ShouldBeTrue(); + } - //wrong sender - { - await ApproveAsync(Reviewer3KeyPair, proposalId); + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); - var associationContractStub = GetAssociationContractTester(Reviewer2KeyPair); - var result = await associationContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("No permission."); - } + { + await ApproveAsync(Reviewer1KeyPair, proposalId); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var result = await associationContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); } - [Fact] - public async Task Release_Proposal_Success_Test() + //wrong sender { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); await ApproveAsync(Reviewer3KeyPair, proposalId); - await ApproveAsync(Reviewer2KeyPair, proposalId); - await ApproveAsync(Reviewer1KeyPair, proposalId); - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var result = await associationContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Check inline transaction result - var getBalance = TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = "ELF", - Owner = Reviewer1 - }).Result.Balance; - getBalance.ShouldBe(100); + var associationContractStub = GetAssociationContractTester(Reviewer2KeyPair); + var result = await associationContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("No permission."); } + } - [Fact] - public async Task Release_Proposal_AlreadyReleased_Test() + [Fact] + public async Task Release_Proposal_Success_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + await ApproveAsync(Reviewer3KeyPair, proposalId); + await ApproveAsync(Reviewer2KeyPair, proposalId); + await ApproveAsync(Reviewer1KeyPair, proposalId); + + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var result = await associationContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // Check inline transaction result + var getBalance = TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - await ApproveAsync(Reviewer3KeyPair, proposalId); - await ApproveAsync(Reviewer2KeyPair, proposalId); - await ApproveAsync(Reviewer1KeyPair, proposalId); + Symbol = "ELF", + Owner = Reviewer1 + }).Result.Balance; + getBalance.ShouldBe(100); + } - { - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var result = await associationContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalReleased = ProposalReleased.Parser.ParseFrom(result.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed) - .ProposalId; - proposalReleased.ShouldBe(proposalId); - - //After release,the proposal will be deleted - var getProposal = await associationContractStub.GetProposal.CallAsync(proposalId); - getProposal.ShouldBe(new ProposalOutput()); - } + [Fact] + public async Task Release_Proposal_AlreadyReleased_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + await ApproveAsync(Reviewer3KeyPair, proposalId); + await ApproveAsync(Reviewer2KeyPair, proposalId); + await ApproveAsync(Reviewer1KeyPair, proposalId); - //approve the same proposal again - { - var associationContractStub1 = GetAssociationContractTester(Reviewer3KeyPair); - var transactionResult = - await associationContractStub1.Approve.SendWithExceptionAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Invalid proposal"); - - //release the same proposal again - var associationContractStub2 = GetAssociationContractTester(Reviewer2KeyPair); - var transactionResult2 = await associationContractStub2.Release.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult2.TransactionResult.Error.ShouldContain("Invalid proposal id."); - } - } - - [Fact] - public async Task ChangeOrganizationThreshold_With_Invalid_Sender_Test() { - var ret = - await AssociationContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( - new ProposalReleaseThreshold()); - ret.TransactionResult.Error.ShouldContain("Organization not found"); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var result = await associationContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalReleased = ProposalReleased.Parser.ParseFrom(result.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed) + .ProposalId; + proposalReleased.ShouldBe(proposalId); + + //After release,the proposal will be deleted + var getProposal = await associationContractStub.GetProposal.CallAsync(proposalId); + getProposal.ShouldBe(new ProposalOutput()); } - [Fact] - public async Task Change_OrganizationThreshold_Test() + //approve the same proposal again { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 1; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); - await ApproveAsync(Reviewer1KeyPair, proposalId); - var proposal = await AssociationContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); + var associationContractStub1 = GetAssociationContractTester(Reviewer3KeyPair); + var transactionResult = + await associationContractStub1.Approve.SendWithExceptionAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Invalid proposal"); + //release the same proposal again + var associationContractStub2 = GetAssociationContractTester(Reviewer2KeyPair); + var transactionResult2 = await associationContractStub2.Release.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult2.TransactionResult.Error.ShouldContain("Invalid proposal id."); + } + } - { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 2 - }; - - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, - proposalReleaseThresholdInput, - nameof(associationContractStub.ChangeOrganizationThreshold), organizationAddress); - await ApproveAsync(Reviewer1KeyPair, changeProposalId); - var result = await associationContractStub.Release.SendWithExceptionAsync(changeProposalId); - result.TransactionResult.Error.ShouldContain("Invalid organization."); - } + [Fact] + public async Task ChangeOrganizationThreshold_With_Invalid_Sender_Test() + { + var ret = + await AssociationContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( + new ProposalReleaseThreshold()); + ret.TransactionResult.Error.ShouldContain("Organization not found"); + } - { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 2, - MinimalApprovalThreshold = minimalApproveThreshold - }; - - var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, - proposalReleaseThresholdInput, - nameof(associationContractStub.ChangeOrganizationThreshold), organizationAddress); - await ApproveAsync(Reviewer1KeyPair, changeProposalId); - var result = await associationContractStub.Release.SendAsync(changeProposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - proposal = await associationContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - } - } + [Fact] + public async Task Change_OrganizationThreshold_Test() + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 1; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + var proposalId = await CreateProposalAsync(Reviewer1KeyPair, organizationAddress); + await ApproveAsync(Reviewer1KeyPair, proposalId); + var proposal = await AssociationContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); - [Fact] - public async Task Change_OrganizationProposalWhitelist_Test() - { - var minimalApproveThreshold = 1; - var minimalVoteThreshold = 1; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); - var proposerWhiteList = new ProposerWhiteList + { + var proposalReleaseThresholdInput = new ProposalReleaseThreshold { - Proposers = {Reviewer2} + MinimalVoteThreshold = 2 }; var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, proposerWhiteList, - nameof(associationContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); + var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, + proposalReleaseThresholdInput, + nameof(associationContractStub.ChangeOrganizationThreshold), organizationAddress); await ApproveAsync(Reviewer1KeyPair, changeProposalId); - var releaseResult = await associationContractStub.Release.SendAsync(changeProposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await TransferToOrganizationAddressAsync(organizationAddress); - var transferInput = new TransferInput() - { - Symbol = "ELF", - Amount = 100, - To = Reviewer1, - Memo = "Transfer" - }; - associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); - var createProposalInput = new CreateProposalInput + var result = await associationContractStub.Release.SendWithExceptionAsync(changeProposalId); + result.TransactionResult.Error.ShouldContain("Invalid organization."); + } + + { + var proposalReleaseThresholdInput = new ProposalReleaseThreshold { - ContractMethodName = nameof(TokenContractStub.Approve), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress + MinimalVoteThreshold = 2, + MinimalApprovalThreshold = minimalApproveThreshold }; - var result = await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Unauthorized to propose."); - //Verify association proposal - var verifyResult = await associationContractStub.ValidateProposerInWhiteList.CallAsync( - new ValidateProposerInWhiteListInput - { - OrganizationAddress = organizationAddress, - Proposer = Reviewer2 - }); - verifyResult.Value.ShouldBeTrue(); + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, + proposalReleaseThresholdInput, + nameof(associationContractStub.ChangeOrganizationThreshold), organizationAddress); + await ApproveAsync(Reviewer1KeyPair, changeProposalId); + var result = await associationContractStub.Release.SendAsync(changeProposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + proposal = await associationContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); } + } - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() + [Fact] + public async Task Change_OrganizationProposalWhitelist_Test() + { + var minimalApproveThreshold = 1; + var minimalVoteThreshold = 1; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, Reviewer1); + + var proposerWhiteList = new ProposerWhiteList + { + Proposers = { Reviewer2 } + }; + + var associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var changeProposalId = await CreateAssociationProposalAsync(Reviewer1KeyPair, proposerWhiteList, + nameof(associationContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); + await ApproveAsync(Reviewer1KeyPair, changeProposalId); + var releaseResult = await associationContractStub.Release.SendAsync(changeProposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await TransferToOrganizationAddressAsync(organizationAddress); + var transferInput = new TransferInput + { + Symbol = "ELF", + Amount = 100, + To = Reviewer1, + Memo = "Transfer" + }; + associationContractStub = GetAssociationContractTester(Reviewer1KeyPair); + var createProposalInput = new CreateProposalInput { - var methodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); + ContractMethodName = nameof(TokenContractStub.Approve), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var result = await associationContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Unauthorized to propose."); + + //Verify association proposal + var verifyResult = await associationContractStub.ValidateProposerInWhiteList.CallAsync( + new ValidateProposerInWhiteListInput + { + OrganizationAddress = organizationAddress, + Proposer = Reviewer2 + }); + verifyResult.Value.ShouldBeTrue(); + } - const string proposalCreationMethodName = nameof(AssociationContractStub.ChangeMethodFeeController); + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() + { + var methodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - var proposalId = await CreateFeeProposalAsync(AssociationContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = ParliamentContractAddress, - ContractAddress = ParliamentContractAddress - }); + const string proposalCreationMethodName = nameof(AssociationContractStub.ChangeMethodFeeController); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); - } + var proposalId = await CreateFeeProposalAsync(AssociationContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + { + OwnerAddress = ParliamentContractAddress, + ContractAddress = ParliamentContractAddress + }); - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new Parliament.CreateOrganizationInput() - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(AssociationContractStub.ChangeMethodFeeController); - - var proposalId = await CreateFeeProposalAsync(AssociationContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new Parliament.CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var methodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - var newMethodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); - } + const string proposalCreationMethodName = nameof(AssociationContractStub.ChangeMethodFeeController); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new Parliament.CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await AssociationContractStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo + var proposalId = await CreateFeeProposalAsync(AssociationContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMethodFeeController = await AssociationContractStub.GetMethodFeeController.CallAsync(new Empty()); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new Parliament.CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await AssociationContractStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task SetMethodFee_Fail_Test() + { + // fee < 0 + { + var invalidMethodFees = GetValidMethodFees(); + invalidMethodFees.Fees[0].BasicFee = -1; + var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); + ret.TransactionResult.Error.ShouldContain("Invalid amount"); } - [Fact] - public async Task SetMethodFee_Fail_Test() + // token does not exist { - // fee < 0 - { - var invalidMethodFees = GetValidMethodFees(); - invalidMethodFees.Fees[0].BasicFee = -1; - var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); - ret.TransactionResult.Error.ShouldContain("Invalid amount"); - } - - // token does not exist - { - var invalidMethodFees = GetValidMethodFees(); - invalidMethodFees.Fees[0].Symbol = "NOTEXIST"; - var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); - ret.TransactionResult.Error.ShouldContain("Token is not found"); - } - - // token is not profitable - { - var tokenSymbol = "DLS"; - var invalidMethodFees = GetValidMethodFees(); - invalidMethodFees.Fees[0].Symbol = tokenSymbol; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "name", - Issuer = DefaultSender, - TotalSupply = 1000_000, - }); - var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); - ret.TransactionResult.Error.ShouldContain($"Token {tokenSymbol} cannot set as method fee."); - } - - // without authority - { - var invalidMethodFees = GetValidMethodFees(); - var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); - ret.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); - } + var invalidMethodFees = GetValidMethodFees(); + invalidMethodFees.Fees[0].Symbol = "NOTEXIST"; + var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); + ret.TransactionResult.Error.ShouldContain("Token is not found"); } - [Fact] - public async Task SetMethodFee_Test() + // token is not profitable { - var input = new MethodFees - { - MethodName = nameof(AssociationContractStub.CreateOrganization), - Fees = - { - new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - } - } - }; - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(AssociationContractStub.SetMethodFee), - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1), - OrganizationAddress = defaultOrganization + var tokenSymbol = "DLS"; + var invalidMethodFees = GetValidMethodFees(); + invalidMethodFees.Fees[0].Symbol = tokenSymbol; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = tokenSymbol, + TokenName = "name", + Issuer = DefaultSender, + TotalSupply = 1000_000 }); - var proposalId = proposal.Output; - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); + var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); + ret.TransactionResult.Error.ShouldContain($"Token {tokenSymbol} cannot set as method fee."); + } - //Query result - var transactionFee = await AssociationContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(AssociationContractStub.CreateOrganization) - }); - var feeItem = transactionFee.Fees.First(); - feeItem.Symbol.ShouldBe("ELF"); - feeItem.BasicFee.ShouldBe(5000_0000L); + // without authority + { + var invalidMethodFees = GetValidMethodFees(); + var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); + ret.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); } + } - [Fact] - public async Task CreateOrganizationBySystemContract_Test() + [Fact] + public async Task SetMethodFee_Test() + { + var input = new MethodFees { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var createOrganizationInput = new CreateOrganizationInput + MethodName = nameof(AssociationContractStub.CreateOrganization), + Fees = { - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {DefaultSender, Reviewer1, Reviewer2, Reviewer3} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold + new MethodFee { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {DefaultSender} + Symbol = "ELF", + BasicFee = 5000_0000L } - }; - var input = new CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = createOrganizationInput, - OrganizationAddressFeedbackMethod = "" - }; - //Unauthorized to create organization - var addressByCalculate = - await AssociationContractStub.CalculateOrganizationAddress.SendAsync(createOrganizationInput); - var transactionResult = - await AssociationContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized"); - //success - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - - var transactionResult1 = - await AssociationContractStub.CreateOrganizationBySystemContract.SendAsync(input); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - transactionResult1.Output.ShouldBe(addressByCalculate.Output); - var boolResult = - await AssociationContractStub.ValidateOrganizationExist.SendAsync(addressByCalculate.Output); - boolResult.Output.Value.ShouldBeTrue(); - //invalid contract - var method = "OrganizationAddressFeedbackMethodName"; - var input2 = new CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = createOrganizationInput, - OrganizationAddressFeedbackMethod = method - }; - var transactionResult2 = - await AssociationContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input2); - transactionResult2.TransactionResult.Error.ShouldContain("invalid"); - } + } + }; + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ContractMethodName = nameof(AssociationContractStub.SetMethodFee), + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1), + OrganizationAddress = defaultOrganization + }); + var proposalId = proposal.Output; + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + + //Query result + var transactionFee = await AssociationContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(AssociationContractStub.CreateOrganization) + }); + var feeItem = transactionFee.Fees.First(); + feeItem.Symbol.ShouldBe("ELF"); + feeItem.BasicFee.ShouldBe(5000_0000L); + } - [Fact] - public async Task CreateProposalBySystemContract_With_Invalid_Organization_Test() + [Fact] + public async Task CreateOrganizationBySystemContract_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var createOrganizationInput = new CreateOrganizationInput { - var input = new CreateProposalBySystemContractInput + OrganizationMemberList = new OrganizationMemberList { - OriginProposer = DefaultSender - }; - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex + OrganizationMembers = { DefaultSender, Reviewer1, Reviewer2, Reviewer3 } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - // invalid organization address + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList { - var proposalInput = GetValidProposalInput(AssociationContractAddress); - input.ProposalInput = proposalInput; - var ret = - await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("No registered organization"); + Proposers = { DefaultSender } } - - //invalid organization proposer - { - var proposer = Address.FromPublicKey(Accounts[2].KeyPair.PublicKey); - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, proposer); - var proposalInput = GetValidProposalInput(organizationAddress); - input.ProposalInput = proposalInput; - var ret = - await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Unauthorized to propose"); - } - } + }; + var input = new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = createOrganizationInput, + OrganizationAddressFeedbackMethod = "" + }; + //Unauthorized to create organization + var addressByCalculate = + await AssociationContractStub.CalculateOrganizationAddress.SendAsync(createOrganizationInput); + var transactionResult = + await AssociationContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input); + transactionResult.TransactionResult.Error.ShouldContain("Unauthorized"); + //success + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + + var transactionResult1 = + await AssociationContractStub.CreateOrganizationBySystemContract.SendAsync(input); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + transactionResult1.Output.ShouldBe(addressByCalculate.Output); + var boolResult = + await AssociationContractStub.ValidateOrganizationExist.SendAsync(addressByCalculate.Output); + boolResult.Output.Value.ShouldBeTrue(); + //invalid contract + var method = "OrganizationAddressFeedbackMethodName"; + var input2 = new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = createOrganizationInput, + OrganizationAddressFeedbackMethod = method + }; + var transactionResult2 = + await AssociationContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input2); + transactionResult2.TransactionResult.Error.ShouldContain("invalid"); + } - [Fact] - public async Task CreateProposalBySystemContract_With_Invalid_Proposal_Test() + [Fact] + public async Task CreateProposalBySystemContract_With_Invalid_Organization_Test() + { + var input = new CreateProposalBySystemContractInput { - var input = new CreateProposalBySystemContractInput - { - OriginProposer = DefaultSender - }; - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); - - // invalid contract method name - { - var proposalInput = GetValidProposalInput(organizationAddress); - proposalInput.ContractMethodName = string.Empty; - input.ProposalInput = proposalInput; - var ret = - await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } - - // invalid expire time - { - var proposalInput = GetValidProposalInput(organizationAddress); - proposalInput.ExpiredTime = new Timestamp(); - input.ProposalInput = proposalInput; - var ret = - await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } - - // invalid url - { - var proposalInput = GetValidProposalInput(organizationAddress); - proposalInput.ProposalDescriptionUrl = "TPP.og"; - input.ProposalInput = proposalInput; - var ret = - await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } + OriginProposer = DefaultSender + }; + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + // invalid organization address + { + var proposalInput = GetValidProposalInput(AssociationContractAddress); + input.ProposalInput = proposalInput; + var ret = + await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("No registered organization"); } - - [Fact] - public async Task CreateProposalBySystemContract_Test() + + //invalid organization proposer { + var proposer = Address.FromPublicKey(Accounts[2].KeyPair.PublicKey); var minimalApproveThreshold = 2; var minimalVoteThreshold = 3; var maximalAbstentionThreshold = 1; var maximalRejectionThreshold = 1; var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); - - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = Reviewer1, - Memo = "Transfer" - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var input = new CreateProposalBySystemContractInput - { - ProposalInput = createProposalInput, OriginProposer = DefaultSender - }; - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - //Unauthorized to propose - var transactionResult = + maximalAbstentionThreshold, maximalRejectionThreshold, proposer); + var proposalInput = GetValidProposalInput(organizationAddress); + input.ProposalInput = proposalInput; + var ret = await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - transactionResult.TransactionResult.Error.ShouldContain("Not authorized to propose"); - //success - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - var transactionResult2 = - await AssociationContractStub.CreateProposalBySystemContract.SendAsync(input); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + ret.TransactionResult.Error.ShouldContain("Unauthorized to propose"); } + } - private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress) + [Fact] + public async Task CreateProposalBySystemContract_With_Invalid_Proposal_Test() + { + var input = new CreateProposalBySystemContractInput { - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = Reviewer1, - Memo = "Transfer" - }; - var associationContractStub = GetAssociationContractTester(proposalKeyPair); - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var proposal = await associationContractStub.CreateProposal.SendAsync(createProposalInput); - var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposal.Output.ShouldBe(proposalCreated); - - return proposal.Output; + OriginProposer = DefaultSender + }; + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); + + // invalid contract method name + { + var proposalInput = GetValidProposalInput(organizationAddress); + proposalInput.ContractMethodName = string.Empty; + input.ProposalInput = proposalInput; + var ret = + await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } - private async Task CreateAssociationProposalAsync(ECKeyPair proposalKeyPair, IMessage input, - string method, Address organizationAddress) + // invalid expire time { - var associationContractStub = GetAssociationContractTester(proposalKeyPair); - var createProposalInput = new CreateProposalInput - { - ContractMethodName = method, - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var proposal = await associationContractStub.CreateProposal.SendAsync(createProposalInput); - var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposal.Output.ShouldBe(proposalCreated); - - return proposal.Output; + var proposalInput = GetValidProposalInput(organizationAddress); + proposalInput.ExpiredTime = new Timestamp(); + input.ProposalInput = proposalInput; + var ret = + await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } - private async Task
CreateOrganizationAsync(int minimalApproveThreshold, int minimalVoteThreshold, - int maximalAbstentionThreshold, int maximalRejectionThreshold, params Address[] proposers) + // invalid url { - var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, proposers); - var transactionResult = - await AssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - return transactionResult.Output; + var proposalInput = GetValidProposalInput(organizationAddress); + proposalInput.ProposalDescriptionUrl = "TPP.og"; + input.ProposalInput = proposalInput; + var ret = + await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } + } - private CreateOrganizationInput GenerateCreateOrganizationInput(int minimalApproveThreshold, - int minimalVoteThreshold, - int maximalAbstentionThreshold, int maximalRejectionThreshold, params Address[] proposers) + [Fact] + public async Task CreateProposalBySystemContract_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, DefaultSender); + + var transferInput = new TransferInput { - var createOrganizationInput = new CreateOrganizationInput - { - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {Reviewer1, Reviewer2, Reviewer3} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposers} - } - }; - return createOrganizationInput; - } + Symbol = "ELF", + Amount = 100, + To = Reviewer1, + Memo = "Transfer" + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var input = new CreateProposalBySystemContractInput + { + ProposalInput = createProposalInput, OriginProposer = DefaultSender + }; + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + //Unauthorized to propose + var transactionResult = + await AssociationContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + transactionResult.TransactionResult.Error.ShouldContain("Not authorized to propose"); + //success + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + var transactionResult2 = + await AssociationContractStub.CreateProposalBySystemContract.SendAsync(input); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - private async Task TransferToOrganizationAddressAsync(Address organizationAddress) + private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress) + { + var transferInput = new TransferInput { - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "ELF", - Amount = 200, - To = organizationAddress, - Memo = "transfer organization address" - }); - } + Symbol = "ELF", + Amount = 100, + To = Reviewer1, + Memo = "Transfer" + }; + var associationContractStub = GetAssociationContractTester(proposalKeyPair); + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var proposal = await associationContractStub.CreateProposal.SendAsync(createProposalInput); + var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposal.Output.ShouldBe(proposalCreated); + + return proposal.Output; + } - private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) + private async Task CreateAssociationProposalAsync(ECKeyPair proposalKeyPair, IMessage input, + string method, Address organizationAddress) + { + var associationContractStub = GetAssociationContractTester(proposalKeyPair); + var createProposalInput = new CreateProposalInput { - var associationContractStub = GetAssociationContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = - await associationContractStub.Approve.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(associationContractStub.Approve)); - } + ContractMethodName = method, + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var proposal = await associationContractStub.CreateProposal.SendAsync(createProposalInput); + var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposal.Output.ShouldBe(proposalCreated); + + return proposal.Output; + } + + private async Task
CreateOrganizationAsync(int minimalApproveThreshold, int minimalVoteThreshold, + int maximalAbstentionThreshold, int maximalRejectionThreshold, params Address[] proposers) + { + var createOrganizationInput = GenerateCreateOrganizationInput(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, proposers); + var transactionResult = + await AssociationContractStub.CreateOrganization.SendAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + return transactionResult.Output; + } - private async Task RejectAsync(ECKeyPair reviewer, Hash proposalId) + private CreateOrganizationInput GenerateCreateOrganizationInput(int minimalApproveThreshold, + int minimalVoteThreshold, + int maximalAbstentionThreshold, int maximalRejectionThreshold, params Address[] proposers) + { + var createOrganizationInput = new CreateOrganizationInput { - var associationContractStub = GetAssociationContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = - await associationContractStub.Reject.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(associationContractStub.Reject)); - } + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { Reviewer1, Reviewer2, Reviewer3 } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { proposers } + } + }; + return createOrganizationInput; + } - private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) + private async Task TransferToOrganizationAddressAsync(Address organizationAddress) + { + await TokenContractStub.Transfer.SendAsync(new TransferInput { - var associationContractStub = GetAssociationContractTester(reviewer); + Symbol = "ELF", + Amount = 200, + To = organizationAddress, + Memo = "transfer organization address" + }); + } - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = - await associationContractStub.Abstain.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(associationContractStub.Abstain)); - } + private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) + { + var associationContractStub = GetAssociationContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = + await associationContractStub.Approve.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(associationContractStub.Approve)); + } - private void ValidateReceiptCreated(ReceiptCreated receiptCreated, Address sender, Hash proposalId, - Timestamp blockTime, string receiptType) - { - receiptCreated.Address.ShouldBe(sender); - receiptCreated.ProposalId.ShouldBe(proposalId); - receiptCreated.Time.ShouldBe(blockTime); - receiptCreated.ReceiptType.ShouldBe(receiptType); - } + private async Task RejectAsync(ECKeyPair reviewer, Hash proposalId) + { + var associationContractStub = GetAssociationContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = + await associationContractStub.Reject.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(associationContractStub.Reject)); + } - protected async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) + { + var associationContractStub = GetAssociationContractTester(reviewer); + + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = + await associationContractStub.Abstain.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(associationContractStub.Abstain)); + } + + private void ValidateReceiptCreated(ReceiptCreated receiptCreated, Address sender, Hash proposalId, + Timestamp blockTime, string receiptType) + { + receiptCreated.Address.ShouldBe(sender); + receiptCreated.ProposalId.ShouldBe(proposalId); + receiptCreated.Time.ShouldBe(blockTime); + receiptCreated.ReceiptType.ShouldBe(receiptType); + } + + protected async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + return proposalId; + } - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; - return proposalId; + protected async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } + } - protected async Task ApproveWithMinersAsync(Hash proposalId) + private CreateProposalInput GetValidProposalInput(Address organizationAddress) + { + var transferInput = new TransferInput { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } - } - - private CreateProposalInput GetValidProposalInput(Address organizationAddress) + Symbol = "ELF", + Amount = 100, + To = Reviewer1, + Memo = "Transfer" + }; + return new CreateProposalInput { - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = Reviewer1, - Memo = "Transfer" - }; - return new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - } - - private MethodFees GetValidMethodFees() + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + } + + private MethodFees GetValidMethodFees() + { + return new MethodFees { - return new MethodFees + MethodName = "Test", + Fees = { - MethodName = "Test", - Fees = { new MethodFee + new MethodFee { Symbol = "ELF", BasicFee = 10 - }} - }; - } - + } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/ContractDeploymentListProvider.cs b/test/AElf.Contracts.Association.Tests/ContractDeploymentListProvider.cs index 580e8918ec..d9f668635d 100644 --- a/test/AElf.Contracts.Association.Tests/ContractDeploymentListProvider.cs +++ b/test/AElf.Contracts.Association.Tests/ContractDeploymentListProvider.cs @@ -6,19 +6,18 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public class ContractDeploymentListProvider : IContractDeploymentListProvider { - public class ContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - AssociationSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name - }; - } + AssociationSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/TestDemoSmartContractAddressNameProvider.cs b/test/AElf.Contracts.Association.Tests/TestDemoSmartContractAddressNameProvider.cs index fb6632701f..416843fd1b 100644 --- a/test/AElf.Contracts.Association.Tests/TestDemoSmartContractAddressNameProvider.cs +++ b/test/AElf.Contracts.Association.Tests/TestDemoSmartContractAddressNameProvider.cs @@ -2,13 +2,13 @@ using AElf.Kernel.SmartContract; using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.Association + +namespace AElf.Contracts.Association; + +public class TestDemoSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TestDemoSmartContractAddressNameProvider:ISmartContractAddressNameProvider,ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TestDemo"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TestDemo"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/Types/MinerList.cs b/test/AElf.Contracts.Association.Tests/Types/MinerList.cs index 2b5371bd69..ed9c3082b5 100644 --- a/test/AElf.Contracts.Association.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.Association.Tests/Types/MinerList.cs @@ -4,45 +4,41 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs index cda63e565b..aa110100ca 100644 --- a/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs @@ -9,54 +9,53 @@ using Google.Protobuf; using Microsoft.Extensions.Options; -namespace AElf.Contracts.Association +namespace AElf.Contracts.Association; + +public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider { - public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider - { - private readonly EconomicOptions _economicOptions; - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; + private readonly EconomicOptions _economicOptions; - public UnitTestTokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, - IOptionsSnapshot economicOptions,IOptionsSnapshot consensusOptions) : base( - tokenContractInitializationDataProvider) - { - _economicOptions = economicOptions.Value; - _consensusOptions = consensusOptions.Value; - } + public UnitTestTokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, + IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) : base( + tokenContractInitializationDataProvider) + { + _economicOptions = economicOptions.Value; + _consensusOptions = consensusOptions.Value; + } - public override List GetInitializeMethodList(byte[] contractCode) + public override List GetInitializeMethodList(byte[] contractCode) + { + var address = Address.FromPublicKey( + ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); + var list = new List { - var address = Address.FromPublicKey( - ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); - var list = new List + new() { - new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = new CreateInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = new CreateInput - { - Decimals = _economicOptions.Decimals, - Issuer = address, - IsBurnable = _economicOptions.IsBurnable, - Symbol = _economicOptions.Symbol, - TokenName = _economicOptions.TokenName, - TotalSupply = _economicOptions.TotalSupply, - }.ToByteString(), - }, - new ContractInitializationMethodCall + Decimals = _economicOptions.Decimals, + Issuer = address, + IsBurnable = _economicOptions.IsBurnable, + Symbol = _economicOptions.Symbol, + TokenName = _economicOptions.TokenName, + TotalSupply = _economicOptions.TotalSupply + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), + Params = new IssueInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), - Params = new IssueInput - { - Symbol = _economicOptions.Symbol, - Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), - To = address, - Memo = "Issue native token" - }.ToByteString() - } - }; - return list; - } + Symbol = _economicOptions.Symbol, + Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), + To = address, + Memo = "Issue native token" + }.ToByteString() + } + }; + return list; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Configuration.Tests/AElf.Contracts.Configuration.Tests.csproj b/test/AElf.Contracts.Configuration.Tests/AElf.Contracts.Configuration.Tests.csproj index 77ef6bde86..7de00e9189 100644 --- a/test/AElf.Contracts.Configuration.Tests/AElf.Contracts.Configuration.Tests.csproj +++ b/test/AElf.Contracts.Configuration.Tests/AElf.Contracts.Configuration.Tests.csproj @@ -7,7 +7,7 @@ - + false Contract @@ -41,13 +41,13 @@ - - - - - + + + + + - + diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs index 326e70e686..2fb4b58217 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs @@ -1,426 +1,440 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.Kernel; -using AElf.Types; using AElf.Contracts.Configuration; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; +using AElf.Kernel; using AElf.Kernel.CodeCheck; -using AElf.Kernel.Configuration; -using AElf.Kernel.SmartContractExecution.Application; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; using Xunit.Abstractions; -namespace AElf.Contracts.ConfigurationContract.Tests +namespace AElf.Contracts.ConfigurationContract.Tests; + +public class ConfigurationContractTest : ConfigurationContractTestBase { - public class ConfigurationContractTest : ConfigurationContractTestBase + private readonly ITestOutputHelper _testOutputHelper; + + public ConfigurationContractTest(ITestOutputHelper testOutputHelper) { - private readonly ITestOutputHelper _testOutputHelper; + _testOutputHelper = testOutputHelper; + } - public ConfigurationContractTest(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } + [Fact] + public async Task Set_Block_Transaction_Limit_Authorized() + { + var proposalId = await SetBlockTransactionLimitProposalAsync(100); + await ApproveWithMinersAsync(proposalId); + var transactionResult = await ReleaseProposalAsync(proposalId); - [Fact] - public async Task Set_Block_Transaction_Limit_Authorized() - { - var proposalId = await SetBlockTransactionLimitProposalAsync(100); - await ApproveWithMinersAsync(proposalId); - var transactionResult = await ReleaseProposalAsync(proposalId); + Assert.True(transactionResult.Status == TransactionResultStatus.Mined); - Assert.True(transactionResult.Status == TransactionResultStatus.Mined); + var limitFromResult = new Int32Value(); + limitFromResult.MergeFrom(ConfigurationSet.Parser.ParseFrom(transactionResult.Logs[1].NonIndexed).Value); + limitFromResult.Value.ShouldBe(100); + } - var limitFromResult = new Int32Value(); - limitFromResult.MergeFrom(ConfigurationSet.Parser.ParseFrom(transactionResult.Logs[1].NonIndexed).Value); - limitFromResult.Value.ShouldBe(100); - } + [Fact] + public async Task Set_Block_Transaction_Limit_NotAuthorized() + { + var transactionResult = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration), + new SetConfigurationInput + { + Key = "BlockTransactionLimit", + Value = new Int32Value { Value = 100 }.ToByteString() + }); + var status = transactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("No permission.", transactionResult.Error); + } - [Fact] - public async Task Set_Block_Transaction_Limit_NotAuthorized() - { - var transactionResult = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration), - new SetConfigurationInput - { - Key = "BlockTransactionLimit", - Value = new Int32Value {Value = 100}.ToByteString() - }); - var status = transactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("No permission.", transactionResult.Error); - } - - [Fact] - public async Task GetConfiguration_Of_Not_Exist_Key_Test() - { - var transactionResult = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), - new StringValue {Value = "BlockTransactionLimit"}); - Assert.True(transactionResult.Status == TransactionResultStatus.Mined); - transactionResult.ReturnValue.Length.ShouldBe(0); - } + [Fact] + public async Task GetConfiguration_Of_Not_Exist_Key_Test() + { + var transactionResult = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), + new StringValue { Value = "BlockTransactionLimit" }); + Assert.True(transactionResult.Status == TransactionResultStatus.Mined); + transactionResult.ReturnValue.Length.ShouldBe(0); + } - [Fact] - public async Task Get_Block_Transaction_Limit() - { - var proposalId = await SetBlockTransactionLimitProposalAsync(100); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); - - var transactionResult = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), - new StringValue {Value = "BlockTransactionLimit"}); - Assert.True(transactionResult.Status == TransactionResultStatus.Mined); - var limitFromResult = new Int32Value(); - limitFromResult.MergeFrom(BytesValue.Parser.ParseFrom(transactionResult.ReturnValue).Value); - limitFromResult.Value.ShouldBe(100); - } + [Fact] + public async Task Get_Block_Transaction_Limit() + { + var proposalId = await SetBlockTransactionLimitProposalAsync(100); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); + + var transactionResult = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), + new StringValue { Value = "BlockTransactionLimit" }); + Assert.True(transactionResult.Status == TransactionResultStatus.Mined); + var limitFromResult = new Int32Value(); + limitFromResult.MergeFrom(BytesValue.Parser.ParseFrom(transactionResult.ReturnValue).Value); + limitFromResult.Value.ShouldBe(100); + } - [Fact] - public async Task Change_Owner_Address_Authorized() + [Fact] + public async Task Change_Owner_Address_Authorized() + { + var sender = SampleAddress.AddressList[0]; + _testOutputHelper.WriteLine(sender.ToBase58()); + var newOrganization = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = true + })).ReturnValue); + var proposalId = await SetTransactionOwnerAddressProposalAsync(new AuthorityInfo { - var sender = SampleAddress.AddressList[0]; - _testOutputHelper.WriteLine(sender.ToBase58()); - var newOrganization = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), - new CreateOrganizationInput + ContractAddress = ParliamentAddress, + OwnerAddress = newOrganization + }); + await ApproveWithMinersAsync(proposalId); + var transactionResult = await ReleaseProposalAsync(proposalId); + Assert.True(transactionResult.Status == TransactionResultStatus.Mined); + + var transactionResult2 = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfigurationController), + new Empty()); + var authorityInfo = AuthorityInfo.Parser.ParseFrom(transactionResult2.ReturnValue); + Assert.True(newOrganization == authorityInfo.OwnerAddress); + } + + [Fact] + public async Task Change_Owner_Address_NotAuthorized() + { + var transactionResult = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.ChangeConfigurationController), + new AuthorityInfo { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = true - })).ReturnValue); - var proposalId = await SetTransactionOwnerAddressProposalAsync(new AuthorityInfo + ContractAddress = ParliamentAddress, + OwnerAddress = SampleAddress.AddressList[0] + }); + var status = transactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("No permission.", transactionResult.Error); + } + + [Fact] + public async Task ChangeConfigurationController_With_Invalid_Authority() + { + var proposalId = await SetTransactionOwnerAddressProposalAsync(new AuthorityInfo + { + ContractAddress = ParliamentAddress, + OwnerAddress = ParliamentAddress + }); + await ApproveWithMinersAsync(proposalId); + var transactionResult = await ReleaseProposalAsync(proposalId); + transactionResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task GetConfigurationController_Default_Authority() + { + var transactionResult = + await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfigurationController), + new Empty()); + var defaultAuthority = AuthorityInfo.Parser.ParseFrom(transactionResult.ReturnValue); + var defaultParliament = await GetParliamentDefaultOrganizationAddressAsync(); + defaultAuthority.ContractAddress.ShouldBe(ParliamentAddress); + defaultAuthority.OwnerAddress.ShouldBe(defaultParliament); + } + + [Fact] + public async Task SetRequiredAcsInContracts_NoPermission() + { + var transactionResult = await ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration), + new SetConfigurationInput { - ContractAddress = ParliamentAddress, - OwnerAddress = newOrganization + Key = "RequiredAcsInContracts", + Value = new RequiredAcsInContracts().ToByteString() }); - await ApproveWithMinersAsync(proposalId); - var transactionResult = await ReleaseProposalAsync(proposalId); - Assert.True(transactionResult.Status == TransactionResultStatus.Mined); - - var transactionResult2 = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfigurationController), - new Empty()); - var authorityInfo = AuthorityInfo.Parser.ParseFrom(transactionResult2.ReturnValue); - Assert.True(newOrganization == authorityInfo.OwnerAddress); - } - [Fact] - public async Task Change_Owner_Address_NotAuthorized() + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("No permission."); + } + + [Fact] + public async Task SetConfiguration_With_Invalid_Input_Test() + { + var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); + var parameter = new Int32Value { - var transactionResult = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.ChangeConfigurationController), - new AuthorityInfo - { - ContractAddress = ParliamentAddress, - OwnerAddress = SampleAddress.AddressList[0] - }); - var status = transactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("No permission.", transactionResult.Error); - } - - [Fact] - public async Task ChangeConfigurationController_With_Invalid_Authority() + Value = 1 + }.ToByteString(); + var inputWithInvalidKey = new SetConfigurationInput { - var proposalId = await SetTransactionOwnerAddressProposalAsync(new AuthorityInfo - { - ContractAddress = ParliamentAddress, - OwnerAddress = ParliamentAddress - }); - await ApproveWithMinersAsync(proposalId); - var transactionResult = await ReleaseProposalAsync(proposalId); - transactionResult.Error.ShouldContain("Invalid authority input"); - } + Value = parameter + }; + var proposalId = await CreateProposalAsync(organizationAddress, inputWithInvalidKey, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); + proposalId.ShouldNotBeNull(); + await ApproveWithMinersAsync(proposalId); + var releaseTxResult = await ReleaseProposalAsync(proposalId); + releaseTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseTxResult.Error.ShouldContain("Invalid set config input"); - [Fact] - public async Task GetConfigurationController_Default_Authority() + var inputWithInvalidValue = new SetConfigurationInput { - var transactionResult = - await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfigurationController), - new Empty()); - var defaultAuthority = AuthorityInfo.Parser.ParseFrom(transactionResult.ReturnValue); - var defaultParliament = await GetParliamentDefaultOrganizationAddressAsync(); - defaultAuthority.ContractAddress.ShouldBe(ParliamentAddress); - defaultAuthority.OwnerAddress.ShouldBe(defaultParliament); - } + Key = "key1" + }; + proposalId = await CreateProposalAsync(organizationAddress, inputWithInvalidValue, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); + proposalId.ShouldNotBeNull(); + await ApproveWithMinersAsync(proposalId); + releaseTxResult = await ReleaseProposalAsync(proposalId); + releaseTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseTxResult.Error.ShouldContain("Invalid set config input"); + } - [Fact] - public async Task SetRequiredAcsInContracts_NoPermission() + [Fact] + public async Task SetRequiredAcsInContracts_Test() + { + var contractFeeChargingPolicy = new RequiredAcsInContracts { - var transactionResult = await ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration), - new SetConfigurationInput + AcsList = { "acsx", "acsy" } + }; + var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); + var proposalId = await CreateProposalAsync(organizationAddress, new SetConfigurationInput + { + Key = "RequiredAcsInContracts", + Value = contractFeeChargingPolicy.ToByteString() + }, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); + proposalId.ShouldNotBeNull(); + await ApproveWithMinersAsync(proposalId); + var releaseTxResult = await ReleaseProposalAsync(proposalId); + releaseTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var actual = await Tester.CallContractMethodAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), + new StringValue + { + Value = "RequiredAcsInContracts" + }); + RequiredAcsInContracts.Parser.ParseFrom(BytesValue.Parser.ParseFrom(actual).Value) + .ShouldBe(contractFeeChargingPolicy); + } + + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - Key = "RequiredAcsInContracts", - Value = new RequiredAcsInContracts().ToByteString() - }); + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("No permission."); - } + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - [Fact] - public async Task SetConfiguration_With_Invalid_Input_Test() - { - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var parameter = new Int32Value + var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); + const string proposalCreationMethodName = + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo { - Value = 1 - }.ToByteString(); - var inputWithInvalidKey = new SetConfigurationInput + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var txResult2 = await ReleaseProposalAsync(proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMethodFeeController = await GetMethodFeeController(ConfigurationContractAddress); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController), + new AuthorityInfo { - Value = parameter - }; - var proposalId = await CreateProposalAsync(organizationAddress, inputWithInvalidKey, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); - proposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(proposalId); - var releaseTxResult = await ReleaseProposalAsync(proposalId); - releaseTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseTxResult.Error.ShouldContain("Invalid set config input"); - - var inputWithInvalidValue = new SetConfigurationInput + OwnerAddress = Tester.GetCallOwnerAddress(), + ContractAddress = ParliamentAddress + }); + + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + + // Invalid organization address + var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); + const string proposalCreationMethodName = + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo { - Key = "key1" - }; - proposalId = await CreateProposalAsync(organizationAddress, inputWithInvalidValue, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); - proposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(proposalId); - releaseTxResult = await ReleaseProposalAsync(proposalId); - releaseTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseTxResult.Error.ShouldContain("Invalid set config input"); - } + OwnerAddress = SampleAddress.AddressList[4], + ContractAddress = methodFeeController.ContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var txResult2 = await ReleaseProposalAsync(proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Failed); + txResult2.Error.Contains("Invalid authority input.").ShouldBeTrue(); + } - [Fact] - public async Task SetRequiredAcsInContracts_Test() + [Fact] + public async Task SetMethodFee_Failed_Test() + { + var methodName = "Name"; + //invalid token { - var contractFeeChargingPolicy = new RequiredAcsInContracts - { - AcsList = {"acsx", "acsy"} - }; - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = await CreateProposalAsync(organizationAddress, new SetConfigurationInput - { - Key = "RequiredAcsInContracts", - Value = contractFeeChargingPolicy.ToByteString() - }, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetConfiguration)); - proposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(proposalId); - var releaseTxResult = await ReleaseProposalAsync(proposalId); - releaseTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var actual = await Tester.CallContractMethodAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetConfiguration), - new StringValue + var invalidToken = "NOTEXIST"; + var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), + new MethodFees { - Value = "RequiredAcsInContracts" + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = invalidToken, BasicFee = 2 + } + } }); - RequiredAcsInContracts.Parser.ParseFrom(BytesValue.Parser.ParseFrom(actual).Value) - .ShouldBe(contractFeeChargingPolicy); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Token is not found").ShouldBeTrue(); } - [Fact] - public async Task ChangeMethodFeeController_Test() + //invalid token amount { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), - new CreateOrganizationInput + var invalidAmount = -1; + var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), + new MethodFees { - ProposalReleaseThreshold = new ProposalReleaseThreshold + MethodName = methodName, + Fees = { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 + new MethodFee + { + Symbol = "ELF", BasicFee = invalidAmount + } } }); - - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - - var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); - const string proposalCreationMethodName = - nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var txResult2 = await ReleaseProposalAsync(proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - - var newMethodFeeController = await GetMethodFeeController(ConfigurationContractAddress); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Invalid amount").ShouldBeTrue(); } - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() + // token is not profitable { - var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController), - new AuthorityInfo() + var tokenSymbol = "DLS"; + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput { - OwnerAddress = Tester.GetCallOwnerAddress(), - ContractAddress = ParliamentAddress + Symbol = tokenSymbol, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 1000_000 }); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - - // Invalid organization address - var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); - const string proposalCreationMethodName = - nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo + var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), + new MethodFees { - OwnerAddress = SampleAddress.AddressList[4], - ContractAddress = methodFeeController.ContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var txResult2 = await ReleaseProposalAsync(proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Failed); - txResult2.Error.Contains("Invalid authority input.").ShouldBeTrue(); - } - [Fact] - public async Task SetMethodFee_Failed_Test() - { - var methodName = "Name"; - //invalid token - { - var invalidToken = "NOTEXIST"; - var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), - new MethodFees - { - MethodName = methodName, - Fees = {new MethodFee - { - Symbol =invalidToken ,BasicFee = 2 - }} - }); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Token is not found").ShouldBeTrue(); - } - - //invalid token amount - { - var invalidAmount = -1; - var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), - new MethodFees - { - MethodName = methodName, - Fees = {new MethodFee - { - Symbol = "ELF" ,BasicFee = invalidAmount - }} - }); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Invalid amount").ShouldBeTrue(); - } - - // token is not profitable - { - var tokenSymbol = "DLS"; - await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput - { - Symbol = tokenSymbol, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 1000_000, - }); - - var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), - new MethodFees - { - MethodName = methodName, - Fees = {new MethodFee - { - Symbol =tokenSymbol ,BasicFee = 2 - }} - }); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains($"Token {tokenSymbol} cannot set as method fee.").ShouldBeTrue(); - } - - // unauthorized - { - var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), - new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = {new MethodFee + new MethodFee { - Symbol ="ELF" ,BasicFee = 2 - }} - }); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized").ShouldBeTrue(); - } - } - [Fact] - public async Task SetMethodFee_Success_Test() - { - var methodName = "name"; - //SetMethodFee Test - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 + Symbol = tokenSymbol, BasicFee = 2 + } } }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); - const string proposalCreationMethodName = - nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains($"Token {tokenSymbol} cannot set as method fee.").ShouldBeTrue(); + } + + // unauthorized + { + var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee), new MethodFees { MethodName = methodName, - Fees = {new MethodFee + Fees = { - Symbol ="ELF" ,BasicFee = 2 - }} - }); - await ApproveWithMinersAsync(proposalId); - var txResult = await ReleaseProposalAsync(proposalId); - txResult.Status.ShouldBe(TransactionResultStatus.Mined); - //GetMethodFee Test - var methodFeeByteString = await Tester.CallContractMethodAsync(ConfigurationContractAddress, - nameof(ConfigurationImplContainer.ConfigurationImplStub.GetMethodFee), new StringValue - { - Value = methodName + new MethodFee + { + Symbol = "ELF", BasicFee = 2 + } + } }); - var methodFee = MethodFees.Parser.ParseFrom(methodFeeByteString); - methodFee.Fees.Count.ShouldBe(1); - methodFee.Fees[0].Symbol.ShouldBe("ELF"); - methodFee.Fees[0].BasicFee.ShouldBe(2); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized").ShouldBeTrue(); } } -} + + [Fact] + public async Task SetMethodFee_Success_Test() + { + var methodName = "name"; + //SetMethodFee Test + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractContainer.ParliamentContractStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); + var methodFeeController = await GetMethodFeeController(ConfigurationContractAddress); + const string proposalCreationMethodName = + nameof(ConfigurationImplContainer.ConfigurationImplStub.SetMethodFee); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = "ELF", BasicFee = 2 + } + } + }); + await ApproveWithMinersAsync(proposalId); + var txResult = await ReleaseProposalAsync(proposalId); + txResult.Status.ShouldBe(TransactionResultStatus.Mined); + //GetMethodFee Test + var methodFeeByteString = await Tester.CallContractMethodAsync(ConfigurationContractAddress, + nameof(ConfigurationImplContainer.ConfigurationImplStub.GetMethodFee), new StringValue + { + Value = methodName + }); + var methodFee = MethodFees.Parser.ParseFrom(methodFeeByteString); + methodFee.Fees.Count.ShouldBe(1); + methodFee.Fees[0].Symbol.ShouldBe("ELF"); + methodFee.Fees[0].BasicFee.ShouldBe(2); + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestAElfModule.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestAElfModule.cs index f6d8079caa..deef7964a4 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestAElfModule.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestAElfModule.cs @@ -1,11 +1,9 @@ using AElf.Contracts.TestBase; using Volo.Abp.Modularity; -namespace AElf.Contracts.ConfigurationContract.Tests +namespace AElf.Contracts.ConfigurationContract.Tests; + +[DependsOn(typeof(ContractTestAElfModule))] +public class ConfigurationContractTestAElfModule : ContractTestAElfModule { - [DependsOn(typeof(ContractTestAElfModule))] - public class ConfigurationContractTestAElfModule: ContractTestAElfModule - { - - } } \ No newline at end of file diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs index ed7a956306..aa42ed0d40 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Configuration; using AElf.Contracts.Parliament; using AElf.Contracts.TestBase; @@ -12,160 +10,162 @@ using AElf.Kernel.Configuration; using AElf.Kernel.Proposal; using AElf.Kernel.Token; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -namespace AElf.Contracts.ConfigurationContract.Tests +namespace AElf.Contracts.ConfigurationContract.Tests; + +public class ConfigurationContractTestBase : ContractTestBase { - public class ConfigurationContractTestBase : ContractTestBase + protected long _balanceOfStarter; + + protected long _totalSupply; + protected Address ConfigurationContractAddress; + protected Address ParliamentAddress; + protected Address TokenContractAddress; + + public ConfigurationContractTestBase() { - protected Address ParliamentAddress; - protected Address ConfigurationContractAddress; - protected Address TokenContractAddress; + AsyncHelper.RunSync(() => + Tester.InitialChainAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), out _totalSupply, + out _, out _balanceOfStarter, true))); + ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); + ConfigurationContractAddress = + Tester.GetContractAddress(ConfigurationSmartContractAddressNameProvider.Name); + TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + } - protected long _totalSupply; - protected long _balanceOfStarter; + protected async Task ExecuteContractWithMiningAsync(Address contractAddress, + string methodName, IMessage input) + { + return await Tester.ExecuteContractWithMiningAsync(contractAddress, methodName, input); + } - public ConfigurationContractTestBase() - { - AsyncHelper.RunSync(() => - Tester.InitialChainAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), out _totalSupply, - out _, out _balanceOfStarter, true))); - ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); - ConfigurationContractAddress = - Tester.GetContractAddress(ConfigurationSmartContractAddressNameProvider.Name); - TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); - } - - protected async Task ExecuteContractWithMiningAsync(Address contractAddress, - string methodName, IMessage input) - { - return await Tester.ExecuteContractWithMiningAsync(contractAddress, methodName, input); - } + protected async Task GenerateTransactionAsync(Address contractAddress, string methodName, + ECKeyPair ecKeyPair, IMessage input) + { + return ecKeyPair == null + ? await Tester.GenerateTransactionAsync(contractAddress, methodName, input) + : await Tester.GenerateTransactionAsync(contractAddress, methodName, ecKeyPair, input); + } - protected async Task GenerateTransactionAsync(Address contractAddress, string methodName, - ECKeyPair ecKeyPair, IMessage input) + internal SetConfigurationInput SetBlockTransactionLimitRequest(int amount) + { + return new SetConfigurationInput { - return ecKeyPair == null - ? await Tester.GenerateTransactionAsync(contractAddress, methodName, input) - : await Tester.GenerateTransactionAsync(contractAddress, methodName, ecKeyPair, input); - } + Key = "BlockTransactionLimit", + Value = new Int32Value { Value = amount }.ToByteString() + }; + } - internal SetConfigurationInput SetBlockTransactionLimitRequest(int amount) - { - return new SetConfigurationInput + internal async Task SetBlockTransactionLimitProposalAsync(int amount) + { + var createProposalInput = SetBlockTransactionLimitRequest(amount); + var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); + var proposalId = + await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); + return proposalId; + } + + internal async Task
GetParliamentDefaultOrganizationAddressAsync() + { + var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( + ParliamentAddress, + nameof(ParliamentContractContainer.ParliamentContractStub.GetDefaultOrganizationAddress), + new Empty())) + .ReturnValue); + return organizationAddress; + } + + internal async Task CreateProposalAsync(Address organizationAddress, IMessage input, string methodName) + { + var proposal = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), + new CreateProposalInput { - Key = "BlockTransactionLimit", - Value = new Int32Value{Value = amount}.ToByteString() - }; - } + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = input.ToByteString(), + ToAddress = ConfigurationContractAddress, + OrganizationAddress = organizationAddress + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + return proposalId; + } - internal async Task SetBlockTransactionLimitProposalAsync(int amount) - { - var createProposalInput = SetBlockTransactionLimitRequest(amount); - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = - await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); - return proposalId; - } - - internal async Task
GetParliamentDefaultOrganizationAddressAsync() - { - var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( - ParliamentAddress, - nameof(ParliamentContractContainer.ParliamentContractStub.GetDefaultOrganizationAddress), - new Empty())) - .ReturnValue); - return organizationAddress; - } - - internal async Task CreateProposalAsync(Address organizationAddress, IMessage input, string methodName) - { - var proposal = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = input.ToByteString(), - ToAddress = ConfigurationContractAddress, - OrganizationAddress = organizationAddress - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - return proposalId; - } - - protected async Task ApproveWithMinersAsync(Hash proposalId) - { - var approveTransaction1 = await GenerateTransactionAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[0], - proposalId); - var approveTransaction2 = await GenerateTransactionAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[1], - proposalId); - var approveTransaction3 = await GenerateTransactionAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[2], - proposalId); - - // Mine a block with given normal txs and system txs. - await Tester.MineAsync( - new List {approveTransaction1, approveTransaction2, approveTransaction3}); - } - - protected async Task ReleaseProposalAsync(Hash proposalId) - { - var transactionResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), proposalId); - return transactionResult; - } + protected async Task ApproveWithMinersAsync(Hash proposalId) + { + var approveTransaction1 = await GenerateTransactionAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[0], + proposalId); + var approveTransaction2 = await GenerateTransactionAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[1], + proposalId); + var approveTransaction3 = await GenerateTransactionAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), Tester.InitialMinerList[2], + proposalId); - internal async Task SetTransactionOwnerAddressProposalAsync(AuthorityInfo authorityInfo) - { - var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( - ParliamentAddress, - nameof(ParliamentContractContainer.ParliamentContractStub.GetDefaultOrganizationAddress), - new Empty())) - .ReturnValue); - var proposal = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = nameof(ConfigurationImplContainer.ConfigurationImplStub.ChangeConfigurationController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = authorityInfo.ToByteString(), - ToAddress = ConfigurationContractAddress, - OrganizationAddress = organizationAddress - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - return proposalId; - } - - protected async Task CreateProposalAsync(ContractTester tester, - Address contractAddress, Address organizationAddress, string methodName, IMessage input) - { - var configContract = tester.GetContractAddress(HashHelper.ComputeFrom("AElf.ContractNames.Configuration")); - var proposal = await tester.ExecuteContractWithMiningAsync(contractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = methodName, - ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), - Params = input.ToByteString(), - ToAddress = configContract, - OrganizationAddress = organizationAddress - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - return proposalId; - } - - protected async Task GetMethodFeeController(Address configurationContractAddress) - { - var methodFeeControllerByteString = await Tester.CallContractMethodAsync(configurationContractAddress, - nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.GetMethodFeeController), new Empty()); - return AuthorityInfo.Parser.ParseFrom(methodFeeControllerByteString); - } + // Mine a block with given normal txs and system txs. + await Tester.MineAsync( + new List { approveTransaction1, approveTransaction2, approveTransaction3 }); + } + + protected async Task ReleaseProposalAsync(Hash proposalId) + { + var transactionResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), proposalId); + return transactionResult; + } + + internal async Task SetTransactionOwnerAddressProposalAsync(AuthorityInfo authorityInfo) + { + var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( + ParliamentAddress, + nameof(ParliamentContractContainer.ParliamentContractStub.GetDefaultOrganizationAddress), + new Empty())) + .ReturnValue); + var proposal = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), + new CreateProposalInput + { + ContractMethodName = + nameof(ConfigurationImplContainer.ConfigurationImplStub.ChangeConfigurationController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = authorityInfo.ToByteString(), + ToAddress = ConfigurationContractAddress, + OrganizationAddress = organizationAddress + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + return proposalId; + } + + protected async Task CreateProposalAsync(ContractTester tester, + Address contractAddress, Address organizationAddress, string methodName, IMessage input) + { + var configContract = tester.GetContractAddress(HashHelper.ComputeFrom("AElf.ContractNames.Configuration")); + var proposal = await tester.ExecuteContractWithMiningAsync(contractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), + new CreateProposalInput + { + ContractMethodName = methodName, + ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), + Params = input.ToByteString(), + ToAddress = configContract, + OrganizationAddress = organizationAddress + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + return proposalId; + } + + protected async Task GetMethodFeeController(Address configurationContractAddress) + { + var methodFeeControllerByteString = await Tester.CallContractMethodAsync(configurationContractAddress, + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.GetMethodFeeController), + new Empty()); + return AuthorityInfo.Parser.ParseFrom(methodFeeControllerByteString); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractConstants.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractConstants.cs index b40d9df34c..704eb7eb60 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractConstants.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public static class AEDPoSContractConstants { - public static class AEDPoSContractConstants - { - public const int TinyBlocksNumber = 8; - public const int LimitBlockExecutionTimeTotalShares = 5; - public const int LimitBlockExecutionTimeWeight = 3; - } + public const int TinyBlocksNumber = 8; + public const int LimitBlockExecutionTimeTotalShares = 5; + public const int LimitBlockExecutionTimeWeight = 3; } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestAElfModule.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestAElfModule.cs index eda70fa994..d0c7843ede 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestAElfModule.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestAElfModule.cs @@ -5,15 +5,14 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +[DependsOn(typeof(EconomicContractsTestModule))] +public class AEDPoSContractTestAElfModule : EconomicContractsTestModule { - [DependsOn(typeof(EconomicContractsTestModule))] - public class AEDPoSContractTestAElfModule : EconomicContractsTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(); - context.Services.AddSingleton(); - } + context.Services.RemoveAll(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs index e933151701..6cc536f844 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs @@ -1,6 +1,5 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Economic; using AElf.Contracts.Economic.TestBase; using AElf.Contracts.Election; @@ -9,7 +8,6 @@ using AElf.Contracts.Profit; using AElf.Contracts.Treasury; using AElf.Contracts.Vote; -using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; @@ -17,7 +15,7 @@ using AElf.Kernel.Account.Infrastructure; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus.Application; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -25,163 +23,166 @@ using Shouldly; using Volo.Abp.Threading; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class AEDPoSContractTestBase : EconomicContractsTestBase { - public class AEDPoSContractTestBase : EconomicContractsTestBase - { - private new void DeployAllContracts() - { - _ = TokenContractAddress; - _ = VoteContractAddress; - _ = ProfitContractAddress; - _ = EconomicContractAddress; - _ = ElectionContractAddress; - _ = TreasuryContractAddress; - _ = TransactionFeeChargingContractAddress; - _ = ParliamentContractAddress; - _ = TokenConverterContractAddress; - _ = ConsensusContractAddress; - _ = ReferendumContractAddress; - _ = TokenHolderContractAddress; - _ = AssociationContractAddress; - } - protected void InitializeContracts() - { - DeployAllContracts(); - - AsyncHelper.RunSync(InitializeParliamentContract); - AsyncHelper.RunSync(InitializeTreasuryConverter); - AsyncHelper.RunSync(InitializeElection); - AsyncHelper.RunSync(InitializeEconomicContract); - AsyncHelper.RunSync(InitializeToken); - AsyncHelper.RunSync(InitializeAElfConsensus); - } + protected IAElfAsymmetricCipherKeyPairProvider KeyPairProvider => + Application.ServiceProvider.GetRequiredService(); - protected IAElfAsymmetricCipherKeyPairProvider KeyPairProvider => - Application.ServiceProvider.GetRequiredService(); + protected ITriggerInformationProvider TriggerInformationProvider => + Application.ServiceProvider.GetRequiredService(); - protected ITriggerInformationProvider TriggerInformationProvider => - Application.ServiceProvider.GetRequiredService(); + protected Timestamp BlockchainStartTimestamp => TimestampHelper.GetUtcNow(); - protected Timestamp BlockchainStartTimestamp => TimestampHelper.GetUtcNow(); + protected IBlockchainService BlockchainService => + Application.ServiceProvider.GetRequiredService(); - protected IBlockchainService BlockchainService => - Application.ServiceProvider.GetRequiredService(); + internal TokenContractContainer.TokenContractStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); - internal TokenContractContainer.TokenContractStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); + internal VoteContractContainer.VoteContractStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); - internal VoteContractContainer.VoteContractStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); + internal ProfitContractContainer.ProfitContractStub ProfitContractStub => + GetProfitContractTester(BootMinerKeyPair); - internal ProfitContractContainer.ProfitContractStub ProfitContractStub => - GetProfitContractTester(BootMinerKeyPair); + internal ElectionContractContainer.ElectionContractStub ElectionContractStub => + GetElectionContractTester(BootMinerKeyPair); - internal ElectionContractContainer.ElectionContractStub ElectionContractStub => - GetElectionContractTester(BootMinerKeyPair); + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => + GetAEDPoSContractStub(BootMinerKeyPair); - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => - GetAEDPoSContractStub(BootMinerKeyPair); + internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub => + GetTreasuryContractTester(BootMinerKeyPair); - internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub => - GetTreasuryContractTester(BootMinerKeyPair); + internal EconomicContractContainer.EconomicContractStub EconomicContractStub => + GetEconomicContractTester(BootMinerKeyPair); - internal EconomicContractContainer.EconomicContractStub EconomicContractStub => - GetEconomicContractTester(BootMinerKeyPair); - - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetParliamentContractTester(BootMinerKeyPair); - - internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetParliamentContractTester(BootMinerKeyPair); - internal VoteContractContainer.VoteContractStub GetVoteContractTester(ECKeyPair keyPair) - { - return GetTester(VoteContractAddress, keyPair); - } + private new void DeployAllContracts() + { + _ = TokenContractAddress; + _ = VoteContractAddress; + _ = ProfitContractAddress; + _ = EconomicContractAddress; + _ = ElectionContractAddress; + _ = TreasuryContractAddress; + _ = TransactionFeeChargingContractAddress; + _ = ParliamentContractAddress; + _ = TokenConverterContractAddress; + _ = ConsensusContractAddress; + _ = ReferendumContractAddress; + _ = TokenHolderContractAddress; + _ = AssociationContractAddress; + } - internal ProfitContractContainer.ProfitContractStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } + protected void InitializeContracts() + { + DeployAllContracts(); + + AsyncHelper.RunSync(InitializeParliamentContract); + AsyncHelper.RunSync(InitializeTreasuryConverter); + AsyncHelper.RunSync(InitializeElection); + AsyncHelper.RunSync(InitializeEconomicContract); + AsyncHelper.RunSync(InitializeToken); + AsyncHelper.RunSync(InitializeAElfConsensus); + } - internal ElectionContractContainer.ElectionContractStub GetElectionContractTester(ECKeyPair keyPair) - { - return GetTester(ElectionContractAddress, keyPair); - } + internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSContractStub(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } - - internal TreasuryContractContainer.TreasuryContractStub GetTreasuryContractTester(ECKeyPair keyPair) - { - return GetTester(TreasuryContractAddress, keyPair); - } + internal VoteContractContainer.VoteContractStub GetVoteContractTester(ECKeyPair keyPair) + { + return GetTester(VoteContractAddress, keyPair); + } - internal EconomicContractContainer.EconomicContractStub GetEconomicContractTester(ECKeyPair keyPair) - { - return GetTester(EconomicContractAddress, keyPair); - } - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, keyPair); - } - - protected async Task InitializeCandidates(int take = EconomicContractsTestConstants.ValidateDataCenterCount) - { - foreach (var candidatesKeyPair in ValidationDataCenterKeyPairs.Take(take)) - { - var electionTester = GetElectionContractTester(candidatesKeyPair); - var announceResult = await electionTester.AnnounceElection.SendAsync(Address.FromPublicKey(candidatesKeyPair.PublicKey)); - announceResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //query candidates - var candidates = await electionTester.GetCandidates.CallAsync(new Empty()); - candidates.Value.Select(o=>o.ToByteArray().ToHex()).Contains(candidatesKeyPair.PublicKey.ToHex()).ShouldBeTrue(); - } - } - - protected async Task BootMinerChangeRoundAsync(long nextRoundNumber = 2) + internal ProfitContractContainer.ProfitContractStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } + + internal ElectionContractContainer.ElectionContractStub GetElectionContractTester(ECKeyPair keyPair) + { + return GetTester(ElectionContractAddress, keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSContractStub(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + internal TreasuryContractContainer.TreasuryContractStub GetTreasuryContractTester(ECKeyPair keyPair) + { + return GetTester(TreasuryContractAddress, keyPair); + } + + internal EconomicContractContainer.EconomicContractStub GetEconomicContractTester(ECKeyPair keyPair) + { + return GetTester(EconomicContractAddress, keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + protected async Task InitializeCandidates(int take = EconomicContractsTestConstants.ValidateDataCenterCount) + { + foreach (var candidatesKeyPair in ValidationDataCenterKeyPairs.Take(take)) { - var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var expectedStartTime = BlockchainStartTimestamp.ToDateTime() - .AddMilliseconds( - ((long) currentRound.TotalMilliseconds(AEDPoSContractTestConstants.MiningInterval)).Mul( - nextRoundNumber.Sub(1))); - currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, - out var nextRound); - await AEDPoSContractStub.NextRound.SendAsync(nextRound); + var electionTester = GetElectionContractTester(candidatesKeyPair); + var announceResult = + await electionTester.AnnounceElection.SendAsync(Address.FromPublicKey(candidatesKeyPair.PublicKey)); + announceResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //query candidates + var candidates = await electionTester.GetCandidates.CallAsync(new Empty()); + candidates.Value.Select(o => o.ToByteArray().ToHex()).Contains(candidatesKeyPair.PublicKey.ToHex()) + .ShouldBeTrue(); } + } - protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + protected async Task BootMinerChangeRoundAsync(long nextRoundNumber = 2) + { + var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var expectedStartTime = BlockchainStartTimestamp.ToDateTime() + .AddMilliseconds( + ((long)currentRound.TotalMilliseconds(AEDPoSContractTestConstants.MiningInterval)).Mul( + nextRoundNumber.Sub(1))); + currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, + out var nextRound); + await AEDPoSContractStub.NextRound.SendAsync(nextRound); + } + + protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = ConsensusContractAddress - }; - - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; - - return proposalId; - } + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = ConsensusContractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - protected async Task ApproveWithMinersAsync(Hash proposalId) + return proposalId; + } + + protected async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestConstants.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestConstants.cs index e0a6c1dd86..32b70c5721 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestConstants.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestConstants.cs @@ -1,27 +1,25 @@ using System.Diagnostics.CodeAnalysis; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +[SuppressMessage("ReSharper", "InconsistentNaming")] +internal static class AEDPoSContractTestConstants { - [SuppressMessage("ReSharper", "InconsistentNaming")] - internal static class AEDPoSContractTestConstants - { - internal const int TinySlots = 8; + internal const int TinySlots = 8; - internal const int InitialMinersCount = 5; + internal const int InitialMinersCount = 5; - internal const int SupposedMinersCount = 17; + internal const int SupposedMinersCount = 17; - internal const int MiningInterval = 4000; + internal const int MiningInterval = 4000; - internal static readonly int SmallBlockMiningInterval = MiningInterval.Div(TinySlots) - .Mul(AEDPoSContractConstants.LimitBlockExecutionTimeWeight) - .Div(AEDPoSContractConstants.LimitBlockExecutionTimeTotalShares); + /// + /// 7 days. + /// + internal const long PeriodSeconds = 120; // 7 * 60 * 60 * 24 - /// - /// 7 days. - /// - internal const long PeriodSeconds = 120;// 7 * 60 * 60 * 24 - } + internal static readonly int SmallBlockMiningInterval = MiningInterval.Div(TinySlots) + .Mul(AEDPoSContractConstants.LimitBlockExecutionTimeWeight) + .Div(AEDPoSContractConstants.LimitBlockExecutionTimeTotalShares); } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj index 0fb4dcf9d8..d51f86f928 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj @@ -5,25 +5,25 @@ AElf.Contracts.Consensus.AEDPoS false - + 0436 - + - - - - - - + + + + + + - - - - + + + + false Contract @@ -34,7 +34,7 @@ Contract PreserveNewest - + @@ -106,6 +106,6 @@ Protobuf\Proto\parliament_contract_impl.proto - - + + diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs index cd5d20a592..17d18c9803 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs @@ -2,52 +2,50 @@ using AElf.Contracts.MultiToken; using AElf.Standards.ACS10; using AElf.Types; -using NSubstitute; using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + [Fact] + public async Task Consensus_Donate_With_Invalid_Token_Test() { - [Fact] - public async Task Consensus_Donate_With_Invalid_Token_Test() - { - var tokenSymbol = "SEP"; + var tokenSymbol = "SEP"; - // Donate with token which is not profitable will fail - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "name", - TotalSupply = 1000_000_000, - Issuer = BootMinerAddress - }); - var issueAmount = 1000_000; - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Amount = issueAmount, - Symbol = tokenSymbol, - To = BootMinerAddress - }); - var balanceBeforeDonate = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = BootMinerAddress, - Symbol = tokenSymbol - }); - balanceBeforeDonate.Balance.ShouldBe(issueAmount); - var donateRet = await AEDPoSContractStub.Donate.SendAsync(new DonateInput - { - Symbol = tokenSymbol, - Amount = 1000 - }); - donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var balanceAfterDonate = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = BootMinerAddress, - Symbol = tokenSymbol - }); - balanceAfterDonate.Balance.ShouldBe(issueAmount); - } + // Donate with token which is not profitable will fail + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = tokenSymbol, + TokenName = "name", + TotalSupply = 1000_000_000, + Issuer = BootMinerAddress + }); + var issueAmount = 1000_000; + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = issueAmount, + Symbol = tokenSymbol, + To = BootMinerAddress + }); + var balanceBeforeDonate = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = BootMinerAddress, + Symbol = tokenSymbol + }); + balanceBeforeDonate.Balance.ShouldBe(issueAmount); + var donateRet = await AEDPoSContractStub.Donate.SendAsync(new DonateInput + { + Symbol = tokenSymbol, + Amount = 1000 + }); + donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var balanceAfterDonate = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = BootMinerAddress, + Symbol = tokenSymbol + }); + balanceAfterDonate.Balance.ShouldBe(issueAmount); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs index 966cc4a22c..058f3afcd9 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs @@ -1,75 +1,73 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + [Fact] + public async Task ChangeMethodFeeController_Test() { - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = - nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); - } + var methodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var methodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); - var result = await AEDPoSContractStub.ChangeMethodFeeController.SendAsync(new AuthorityInfo + const string proposalCreationMethodName = + nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, ContractAddress = methodFeeController.ContractAddress }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMethodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var methodFeeController = await AEDPoSContractStub.GetMethodFeeController.CallAsync(new Empty()); + var result = await AEDPoSContractStub.ChangeMethodFeeController.SendAsync(new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index 262dbc9b04..f567de3d69 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -1,8 +1,7 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS4; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS4; using AElf.TestBase; using AElf.Types; using Google.Protobuf; @@ -11,437 +10,436 @@ using Xunit; using Xunit.Abstractions; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest : AEDPoSContractTestBase { - public partial class AEDPoSTest : AEDPoSContractTestBase + private readonly ITestOutputHelper _testOutputHelper; + + public AEDPoSTest(ITestOutputHelper testOutputHelper) { - private readonly ITestOutputHelper _testOutputHelper; + _testOutputHelper = testOutputHelper; + InitializeContracts(); + } - public AEDPoSTest(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - InitializeContracts(); - } + private async Task AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test() + { + KeyPairProvider.SetKeyPair(BootMinerKeyPair); + var triggerForCommand = + TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); - private async Task AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test() - { - KeyPairProvider.SetKeyPair(BootMinerKeyPair); - var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); + var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); - var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); + consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants + .SmallBlockMiningInterval); + var hint = new AElfConsensusHint + { + Behaviour = AElfConsensusBehaviour.UpdateValue + }.ToByteString(); + consensusCommand.Hint.ShouldBe(hint); - consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants - .SmallBlockMiningInterval); - var hint = new AElfConsensusHint - { - Behaviour = AElfConsensusBehaviour.UpdateValue - }.ToByteString(); - consensusCommand.Hint.ShouldBe(hint); + return consensusCommand; + } - return consensusCommand; - } + [Fact] + public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_BootMiner_Test() + { + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test(); - [Fact] - public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_BootMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) + }); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) - }); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + var extraData = extraDataBytes.ToConsensusHeaderInformation(); - var extraData = extraDataBytes.ToConsensusHeaderInformation(); + extraData.Round.RoundNumber.ShouldBe(1); + extraData.Round.RealTimeMinersInformation.Count.ShouldBe(InitialCoreDataCenterKeyPairs.Count); + extraData.Round.RealTimeMinersInformation[BootMinerKeyPair.PublicKey.ToHex()].OutValue + .ShouldNotBeNull(); + } - extraData.Round.RoundNumber.ShouldBe(1); - extraData.Round.RealTimeMinersInformation.Count.ShouldBe(InitialCoreDataCenterKeyPairs.Count); - extraData.Round.RealTimeMinersInformation[BootMinerKeyPair.PublicKey.ToHex()].OutValue - .ShouldNotBeNull(); - } + private async Task AEDPoSContract_GenerateConsensusTransactions_FirstRound_BootMiner() + { + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test(); - private async Task AEDPoSContract_GenerateConsensusTransactions_FirstRound_BootMiner() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_BootMiner_Test(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) + }); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) - }); + var triggerForCommand = + TriggerInformationProvider.GetTriggerInformationForConsensusTransactions( + consensusCommand.ToBytesValue()); - var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusTransactions( - consensusCommand.ToBytesValue()); + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + transactionList.Transactions.Count.ShouldBe(1); + transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); - transactionList.Transactions.Count.ShouldBe(1); - transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); + return transactionList; + } - return transactionList; - } + private async Task AEDPoSContract_FirstRound_BootMiner_Test() + { + var transaction = + (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_BootMiner()).Transactions.First(); - private async Task AEDPoSContract_FirstRound_BootMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var transaction = - (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_BootMiner()).Transactions.First(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) + }); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) - }); + var updateValueInput = new UpdateValueInput(); + updateValueInput.MergeFrom(transaction.Params); - var updateValueInput = new UpdateValueInput(); - updateValueInput.MergeFrom(transaction.Params); + await AEDPoSContractStub.UpdateValue.SendAsync(updateValueInput); - await AEDPoSContractStub.UpdateValue.SendAsync(updateValueInput); + var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + currentRound.RoundNumber.ShouldBe(1); + currentRound.RealTimeMinersInformation[BootMinerKeyPair.PublicKey.ToHex()].OutValue.ShouldNotBeNull(); + } - var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - currentRound.RoundNumber.ShouldBe(1); - currentRound.RealTimeMinersInformation[BootMinerKeyPair.PublicKey.ToHex()].OutValue.ShouldNotBeNull(); - } + private async Task AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test() + { + await AEDPoSContract_FirstRound_BootMiner_Test(); + // Now the first time slot of first round already filled by boot miner. - private async Task AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test() + var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; + KeyPairProvider.SetKeyPair(usingKeyPair); + + var blockchainStartTimestamp = BlockchainStartTimestamp; + BlockTimeProvider.SetBlockTime(blockchainStartTimestamp + new Duration { - await AEDPoSContract_FirstRound_BootMiner_Test(); - // Now the first time slot of first round already filled by boot miner. + Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) + }); - var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; - KeyPairProvider.SetKeyPair(usingKeyPair); + var triggerForCommand = + TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); - var blockchainStartTimestamp = BlockchainStartTimestamp; - BlockTimeProvider.SetBlockTime(blockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) - }); + var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); - var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); + consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants + .SmallBlockMiningInterval); + var hint = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.UpdateValue } + .ToByteString(); + consensusCommand.Hint.ShouldBe(hint); + consensusCommand.ArrangedMiningTime.ShouldBe(blockchainStartTimestamp + new Duration + { + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(7).Div(1000) + }); - var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); + return consensusCommand; + } - consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants - .SmallBlockMiningInterval); - var hint = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.UpdateValue} - .ToByteString(); - consensusCommand.Hint.ShouldBe(hint); - consensusCommand.ArrangedMiningTime.ShouldBe(blockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(7).Div(1000) - }); + [Fact] + public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_SecondMiner_Test() + { + var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; + KeyPairProvider.SetKeyPair(usingKeyPair); - return consensusCommand; - } + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test(); - [Fact] - public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_SecondMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; - KeyPairProvider.SetKeyPair(usingKeyPair); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) + }); - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test(); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) - }); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraData = extraDataBytes.ToConsensusHeaderInformation(); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + extraData.Round.RoundNumber.ShouldBe(1); + extraData.Round.RealTimeMinersInformation[usingKeyPair.PublicKey.ToHex()].OutValue + .ShouldNotBeNull(); + } - var extraData = extraDataBytes.ToConsensusHeaderInformation(); + private async Task AEDPoSContract_GenerateConsensusTransactions_FirstRound_SecondMiner_Test() + { + var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; + KeyPairProvider.SetKeyPair(usingKeyPair); - extraData.Round.RoundNumber.ShouldBe(1); - extraData.Round.RealTimeMinersInformation[usingKeyPair.PublicKey.ToHex()].OutValue - .ShouldNotBeNull(); - } + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test(); - private async Task AEDPoSContract_GenerateConsensusTransactions_FirstRound_SecondMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; - KeyPairProvider.SetKeyPair(usingKeyPair); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) + }); - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_SecondMiner_Test(); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) - }); + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + transactionList.Transactions.Count.ShouldBe(1); + transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + return transactionList; + } - transactionList.Transactions.Count.ShouldBe(1); - transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); + private async Task AEDPoSContract_FirstRound_SecondMiner_Test() + { + var transaction = + (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_SecondMiner_Test()).Transactions.First(); - return transactionList; - } + var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; + KeyPairProvider.SetKeyPair(usingKeyPair); - private async Task AEDPoSContract_FirstRound_SecondMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var transaction = - (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_SecondMiner_Test()).Transactions.First(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) + }); - var usingKeyPair = InitialCoreDataCenterKeyPairs[1]; - KeyPairProvider.SetKeyPair(usingKeyPair); + var updateValueInput = new UpdateValueInput(); + updateValueInput.MergeFrom(transaction.Params); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) - }); + var stub = GetAEDPoSContractStub(usingKeyPair); + await stub.UpdateValue.SendAsync(updateValueInput); - var updateValueInput = new UpdateValueInput(); - updateValueInput.MergeFrom(transaction.Params); + var currentRound = await stub.GetCurrentRoundInformation.CallAsync(new Empty()); + currentRound.RoundNumber.ShouldBe(1); + currentRound.RealTimeMinersInformation[usingKeyPair.PublicKey.ToHex()].OutValue.ShouldNotBeNull(); + } - var stub = GetAEDPoSContractStub(usingKeyPair); - await stub.UpdateValue.SendAsync(updateValueInput); + private async Task AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test() + { + await AEDPoSContract_FirstRound_SecondMiner_Test(); - var currentRound = await stub.GetCurrentRoundInformation.CallAsync(new Empty()); - currentRound.RoundNumber.ShouldBe(1); - currentRound.RealTimeMinersInformation[usingKeyPair.PublicKey.ToHex()].OutValue.ShouldNotBeNull(); - } + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); - private async Task AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - await AEDPoSContract_FirstRound_SecondMiner_Test(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) + }); - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + var triggerForCommand = + TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(2).Div(1000) - }); + var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); - var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); + consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants + .SmallBlockMiningInterval); + var hint = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.NextRound } + .ToByteString(); + consensusCommand.Hint.ShouldBe(hint); - var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); + return consensusCommand; + } - consensusCommand.LimitMillisecondsOfMiningBlock.ShouldBe(AEDPoSContractTestConstants - .SmallBlockMiningInterval); - var hint = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.NextRound} - .ToByteString(); - consensusCommand.Hint.ShouldBe(hint); + [Fact] + public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_ExtraBlockMiner_Test() + { + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); - return consensusCommand; - } + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - [Fact] - public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_ExtraBlockMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) + .Div(1000) + }); - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) - .Div(1000) - }); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraData = extraDataBytes.ToConsensusHeaderInformation(); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + extraData.Round.RoundNumber.ShouldBe(2); + } - var extraData = extraDataBytes.ToConsensusHeaderInformation(); + private async Task + AEDPoSContract_GenerateConsensusTransactions_FirstRound_ExtraBlockMiner_Test() + { + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); - extraData.Round.RoundNumber.ShouldBe(2); - } + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - private async Task - AEDPoSContract_GenerateConsensusTransactions_FirstRound_ExtraBlockMiner_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) + .Div(1000) + }); - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) - .Div(1000) - }); - - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + transactionList.Transactions.Count.ShouldBe(1); + transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextRound)); - transactionList.Transactions.Count.ShouldBe(1); - transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextRound)); + return transactionList; + } - return transactionList; - } + [Fact] + public async Task AEDPoSContract_FirstRound_Terminate_Test() + { + var transaction = + (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_ExtraBlockMiner_Test()).Transactions + .First(); - [Fact] - public async Task AEDPoSContract_FirstRound_Terminate_Test() + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var transaction = - (await AEDPoSContract_GenerateConsensusTransactions_FirstRound_ExtraBlockMiner_Test()).Transactions - .First(); + Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) + .Div(1000) + }); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval.Mul(AEDPoSContractTestConstants.InitialMinersCount) - .Div(1000) - }); + var nextRound = new Round(); + nextRound.MergeFrom(transaction.Params); - var nextRound = new Round(); - nextRound.MergeFrom(transaction.Params); + await AEDPoSContractStub.NextRound.SendAsync(nextRound); - await AEDPoSContractStub.NextRound.SendAsync(nextRound); + var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + currentRound.RoundNumber.ShouldBe(2); + } - var currentRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - currentRound.RoundNumber.ShouldBe(2); - } + [IgnoreOnCIFact] + public async Task AEDPoSContract_ConsensusTransactionValidation_Test() + { + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); + + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + + var validateBeforeResult = + await AEDPoSContractStub.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); + validateBeforeResult.Success.ShouldBeTrue(); + + var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + roundInfo.RoundNumber++; + roundInfo.IsMinerListJustChanged = false; + roundInfo.TermNumber++; + var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(roundInfo); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var validateAfterResult = + await AEDPoSContractStub.ValidateConsensusAfterExecution.CallAsync(roundInfo.ToBytesValue()); + validateAfterResult.Success.ShouldBeTrue(); + } - [IgnoreOnCIFact] - public async Task AEDPoSContract_ConsensusTransactionValidation_Test() - { - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + [Fact] + public async Task AEDPoSContract_ValidateConsensusBeforeExecution_UpdateValue_WithoutMiner_Test() + { + var usingKeyPair = ValidationDataCenterKeyPairs[0]; - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); - - var validateBeforeResult = - await AEDPoSContractStub.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); - validateBeforeResult.Success.ShouldBeTrue(); - - var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - roundInfo.RoundNumber++; - roundInfo.IsMinerListJustChanged = false; - roundInfo.TermNumber++; - var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(roundInfo); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var validateAfterResult = - await AEDPoSContractStub.ValidateConsensusAfterExecution.CallAsync(roundInfo.ToBytesValue()); - validateAfterResult.Success.ShouldBeTrue(); - } + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - [Fact] - public async Task AEDPoSContract_ValidateConsensusBeforeExecution_UpdateValue_WithoutMiner_Test() - { - var usingKeyPair = ValidationDataCenterKeyPairs[0]; + KeyPairProvider.SetKeyPair(usingKeyPair); - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var updateValue = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.UpdateValue } + .ToByteString(); + consensusCommand.Hint = updateValue; - KeyPairProvider.SetKeyPair(usingKeyPair); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); - var updateValue = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.UpdateValue} - .ToByteString(); - consensusCommand.Hint = updateValue; + await NextTerm(BootMinerKeyPair); - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + var otherUser = GetAEDPoSContractStub(usingKeyPair); + var validateBeforeResult = + await otherUser.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); + validateBeforeResult.Success.ShouldBeFalse(); + validateBeforeResult.Message.ShouldContain("is not a miner"); + } - await NextTerm(BootMinerKeyPair); + [Fact] + public async Task AEDPoSContract_ValidateConsensusBeforeExecution_UpdateValue_Test() + { + var usingKeyPair = InitialCoreDataCenterKeyPairs[0]; + KeyPairProvider.SetKeyPair(usingKeyPair); + + var triggerForCommand = + TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); + var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); + var updateValue = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.UpdateValue } + .ToByteString(); + consensusCommand.Hint = updateValue; + + triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + + var validateBeforeResult = + await AEDPoSContractStub.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); + validateBeforeResult.Success.ShouldBeTrue(); + } - var otherUser = GetAEDPoSContractStub(usingKeyPair); - var validateBeforeResult = - await otherUser.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); - validateBeforeResult.Success.ShouldBeFalse(); - validateBeforeResult.Message.ShouldContain("is not a miner"); - } + [Fact] + public async Task AEDPoSContract_GenerateConsensusTransaction_TinyBlock_Test() + { + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); - [Fact] - public async Task AEDPoSContract_ValidateConsensusBeforeExecution_UpdateValue_Test() + //Tiny block { - var usingKeyPair = InitialCoreDataCenterKeyPairs[0]; - KeyPairProvider.SetKeyPair(usingKeyPair); - - var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); - var consensusCommand = await AEDPoSContractStub.GetConsensusCommand.CallAsync(triggerForCommand); - var updateValue = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.UpdateValue} + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var tinyBlockBehavior = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.TinyBlock } .ToByteString(); - consensusCommand.Hint = updateValue; + consensusCommand.Hint = tinyBlockBehavior; + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration + { + Seconds = AEDPoSContractTestConstants.MiningInterval + .Mul(AEDPoSContractTestConstants.InitialMinersCount) + .Div(1000) + }); + + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + var transactionList = + await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - var validateBeforeResult = - await AEDPoSContractStub.ValidateConsensusBeforeExecution.CallAsync(extraDataBytes); - validateBeforeResult.Success.ShouldBeTrue(); + transactionList.Transactions.Count.ShouldBe(1); + transactionList.Transactions[0].MethodName + .ShouldBe(nameof(AEDPoSContractStub.UpdateTinyBlockInformation)); } + } - [Fact] - public async Task AEDPoSContract_GenerateConsensusTransaction_TinyBlock_Test() - { - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + [Fact] + public async Task AEDPoSContract_GenerateConsensusTransaction_NextTerm_Test() + { + var usingKeyPair = BootMinerKeyPair; + KeyPairProvider.SetKeyPair(usingKeyPair); - //Tiny block + //Next term + { + var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); + var nextTermBehavior = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.NextTerm } + .ToByteString(); + consensusCommand.Hint = nextTermBehavior; + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration { - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - var tinyBlockBehavior = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.TinyBlock} - .ToByteString(); - consensusCommand.Hint = tinyBlockBehavior; - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval - .Mul(AEDPoSContractTestConstants.InitialMinersCount) - .Div(1000) - }); - - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - - var transactionList = - await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - - transactionList.Transactions.Count.ShouldBe(1); - transactionList.Transactions[0].MethodName - .ShouldBe(nameof(AEDPoSContractStub.UpdateTinyBlockInformation)); - } - } + Seconds = AEDPoSContractTestConstants.MiningInterval + .Mul(AEDPoSContractTestConstants.InitialMinersCount) + .Div(1000) + }); - [Fact] - public async Task AEDPoSContract_GenerateConsensusTransaction_NextTerm_Test() - { - var usingKeyPair = BootMinerKeyPair; - KeyPairProvider.SetKeyPair(usingKeyPair); + var triggerForCommand = TriggerInformationProvider + .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - //Next term - { - var consensusCommand = await AEDPoSContract_GetConsensusCommand_FirstRound_ExtraBlockMiner_Test(); - var nextTermBehavior = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.NextTerm} - .ToByteString(); - consensusCommand.Hint = nextTermBehavior; - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration - { - Seconds = AEDPoSContractTestConstants.MiningInterval - .Mul(AEDPoSContractTestConstants.InitialMinersCount) - .Div(1000) - }); - - var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); - - var transactionList = - await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); - - transactionList.Transactions.Count.ShouldBe(1); - transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextTerm)); - } + var transactionList = + await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + + transactionList.Transactions.Count.ShouldBe(1); + transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextTerm)); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/InValueRecoveryTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/InValueRecoveryTest.cs index a93116e391..a013efe221 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/InValueRecoveryTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/InValueRecoveryTest.cs @@ -1,68 +1,63 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Contracts.Economic.TestBase; using AElf.Cryptography; using AElf.Cryptography.SecretSharing; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -using AElf.Types; -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + private static int MinimumCount => EconomicContractsTestConstants.InitialCoreDataCenterCount.Mul(2).Div(3); + + /// + /// Test the correctness of basic logic of secret sharing. + /// + /// + [Fact] + public void OffChain_DecryptMessage_Test() { - private static int MinimumCount => EconomicContractsTestConstants.InitialCoreDataCenterCount.Mul(2).Div(3); + var message = HashHelper.ComputeFrom("message").ToByteArray(); + var secrets = + SecretSharingHelper.EncodeSecret(message, MinimumCount, + EconomicContractsTestConstants.InitialCoreDataCenterCount); + var encryptedValues = new Dictionary(); + var decryptedValues = new Dictionary(); + var ownerKeyPair = InitialCoreDataCenterKeyPairs[0]; + var othersKeyPairs = InitialCoreDataCenterKeyPairs.Skip(1).ToList(); + var decryptResult = new byte[0]; - /// - /// Test the correctness of basic logic of secret sharing. - /// - /// - [Fact] - public void OffChain_DecryptMessage_Test() + var initial = 0; + foreach (var keyPair in othersKeyPairs) { - var message = HashHelper.ComputeFrom("message").ToByteArray(); - var secrets = - SecretSharingHelper.EncodeSecret(message, MinimumCount, EconomicContractsTestConstants.InitialCoreDataCenterCount); - var encryptedValues = new Dictionary(); - var decryptedValues = new Dictionary(); - var ownerKeyPair = InitialCoreDataCenterKeyPairs[0]; - var othersKeyPairs = InitialCoreDataCenterKeyPairs.Skip(1).ToList(); - var decryptResult=new byte[0]; + var encryptedMessage = CryptoHelper.EncryptMessage(ownerKeyPair.PrivateKey, keyPair.PublicKey, + secrets[initial++]); + encryptedValues.Add(keyPair.PublicKey.ToHex(), encryptedMessage); + } - var initial = 0; - foreach (var keyPair in othersKeyPairs) - { - var encryptedMessage = CryptoHelper.EncryptMessage(ownerKeyPair.PrivateKey, keyPair.PublicKey, - secrets[initial++]); - encryptedValues.Add(keyPair.PublicKey.ToHex(), encryptedMessage); - } + // Check encrypted values. + encryptedValues.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1); - // Check encrypted values. - encryptedValues.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1); + // Others try to recover. + foreach (var keyPair in othersKeyPairs) + { + var cipherMessage = encryptedValues[keyPair.PublicKey.ToHex()]; + var decryptMessage = + CryptoHelper.DecryptMessage(ownerKeyPair.PublicKey, keyPair.PrivateKey, cipherMessage); + decryptedValues.Add(keyPair.PublicKey.ToHex(), decryptMessage); - // Others try to recover. - foreach (var keyPair in othersKeyPairs) + if (decryptedValues.Count >= MinimumCount) { - var cipherMessage = encryptedValues[keyPair.PublicKey.ToHex()]; - var decryptMessage = - CryptoHelper.DecryptMessage(ownerKeyPair.PublicKey, keyPair.PrivateKey, cipherMessage); - decryptedValues.Add(keyPair.PublicKey.ToHex(), decryptMessage); - - if (decryptedValues.Count >= MinimumCount) - { - decryptResult = SecretSharingHelper.DecodeSecret( - decryptedValues.Values.ToList(), - Enumerable.Range(1, MinimumCount).ToList(), MinimumCount); - break; - } + decryptResult = SecretSharingHelper.DecodeSecret( + decryptedValues.Values.ToList(), + Enumerable.Range(1, MinimumCount).ToList(), MinimumCount); + break; } - - decryptResult.ShouldBe(message); } + + decryptResult.ShouldBe(message); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index ea6f6d5606..6015e070d8 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -6,131 +6,130 @@ using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.TestBase; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; -using Volo.Abp.Threading; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + /// + /// test:Change the number of miners when term changed + /// + /// + [IgnoreOnCIFact] + public async Task AEDPoSContract_ChangeMinersCount_Test() { - /// - /// test:Change the number of miners when term changed - /// - /// - [IgnoreOnCIFact] - public async Task AEDPoSContract_ChangeMinersCount_Test() - { - const int termIntervalMin = 31536000 / 60; - - var maxCount = ValidationDataCenterKeyPairs.Count; - await InitializeCandidates(maxCount); + const int termIntervalMin = 31536000 / 60; - var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var maxCount = ValidationDataCenterKeyPairs.Count; + await InitializeCandidates(maxCount); - var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Select(_ => HashHelper.ComputeFrom("randomHashes")).ToList(); - var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i => - new AElfConsensusTriggerInformation - { - Pubkey = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey), - InValue = randomHashes[i] - }).ToDictionary(t => t.Pubkey.ToHex(), t => t); + var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var voter = GetElectionContractTester(VoterKeyPairs[0]); - foreach (var candidateKeyPair in ValidationDataCenterKeyPairs) + var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Select(_ => HashHelper.ComputeFrom("randomHashes")).ToList(); + var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i => + new AElfConsensusTriggerInformation { - var voteResult = await voter.Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), - Amount = 10 + new Random().Next(1, 10), - EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100) - }); - voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) + Pubkey = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey), + InValue = randomHashes[i] + }).ToDictionary(t => t.Pubkey.ToHex(), t => t); + + var voter = GetElectionContractTester(VoterKeyPairs[0]); + foreach (var candidateKeyPair in ValidationDataCenterKeyPairs) + { + var voteResult = await voter.Vote.SendAsync(new VoteMinerInput { - var currentKeyPair = InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey); + CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), + Amount = 10 + new Random().Next(1, 10), + EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100) + }); + voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - KeyPairProvider.SetKeyPair(currentKeyPair); + foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) + { + var currentKeyPair = InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey); - BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime); + KeyPairProvider.SetKeyPair(currentKeyPair); - var tester = GetAEDPoSContractStub(currentKeyPair); - var headerInformation = - (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] - .ToBytesValue())).ToConsensusHeaderInformation(); + BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime); - // Update consensus information. - var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); - await tester.UpdateValue.SendAsync(toUpdate); - } + var tester = GetAEDPoSContractStub(currentKeyPair); + var headerInformation = + (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] + .ToBytesValue())).ToConsensusHeaderInformation(); - var changeTermTime = BlockchainStartTimestamp.ToDateTime(); - BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); + // Update consensus information. + var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); + await tester.UpdateValue.SendAsync(toUpdate); + } - var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.NextRound, - Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation(); + var changeTermTime = BlockchainStartTimestamp.ToDateTime(); + BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); - await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); - changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); - BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); + var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation + { + Behaviour = AElfConsensusBehaviour.NextRound, + Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); + + await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); + changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); + BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); + + nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation + { + Behaviour = AElfConsensusBehaviour.NextTerm, + Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); + + var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMinerStub = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); + var termCount = 0; + var minerCount = 0; + while (minerCount < maxCount) + { + var currentRound = await newMinerStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var firstPubKey = currentRound.RealTimeMinersInformation.Keys.First(); + newMinerStub = + GetAEDPoSContractStub(ValidationDataCenterKeyPairs.First(o => o.PublicKey.ToHex() == firstPubKey)); + + minerCount = currentRound.RealTimeMinersInformation.Count; + Assert.Equal(AEDPoSContractTestConstants.SupposedMinersCount.Add(termCount.Mul(2)), minerCount); - nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + changeTermTime = BlockchainStartTimestamp.ToDateTime() + .AddMinutes((termCount + 2).Mul(termIntervalMin)).AddSeconds(10); + BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); + var nextRoundInformation = (await newMinerStub.GetConsensusExtraData.CallAsync( new AElfConsensusTriggerInformation { Behaviour = AElfConsensusBehaviour.NextTerm, - Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) + Pubkey = ByteStringHelper.FromHexString(currentRound.RealTimeMinersInformation.ElementAt(0).Value + .Pubkey) }.ToBytesValue())).ToConsensusHeaderInformation(); - var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var newMinerStub = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); - var termCount = 0; - var minerCount = 0; - while (minerCount < maxCount) - { - var currentRound = await newMinerStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var firstPubKey = currentRound.RealTimeMinersInformation.Keys.First(); - newMinerStub = GetAEDPoSContractStub(ValidationDataCenterKeyPairs.First(o =>o.PublicKey.ToHex() == firstPubKey)); - - minerCount = currentRound.RealTimeMinersInformation.Count; - Assert.Equal(AEDPoSContractTestConstants.SupposedMinersCount.Add(termCount.Mul(2)), minerCount); - - changeTermTime = BlockchainStartTimestamp.ToDateTime() - .AddMinutes((termCount + 2).Mul(termIntervalMin)).AddSeconds(10); - BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); - var nextRoundInformation = (await newMinerStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.NextTerm, - Pubkey = ByteStringHelper.FromHexString(currentRound.RealTimeMinersInformation.ElementAt(0).Value.Pubkey) - }.ToBytesValue())).ToConsensusHeaderInformation(); - - await newMinerStub.NextTerm.SendAsync(nextRoundInformation.Round); - termCount++; - } + await newMinerStub.NextTerm.SendAsync(nextRoundInformation.Round); + termCount++; } + } - [Fact] - public async Task AEDPoSContract_SetMaximumMinersCount_NoPermission() - { - var transactionResult = - (await AEDPoSContractStub.SetMaximumMinersCount.SendAsync(new Int32Value {Value = 100})) - .TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("No permission"); - } + [Fact] + public async Task AEDPoSContract_SetMaximumMinersCount_NoPermission() + { + var transactionResult = + (await AEDPoSContractStub.SetMaximumMinersCount.SendAsync(new Int32Value { Value = 100 })) + .TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("No permission"); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index 00498c50dd..cb9dfcf1ff 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -3,12 +3,9 @@ using System.Threading.Tasks; using AElf.Contracts.Economic.TestBase; using AElf.Contracts.Election; -using AElf.Contracts.MultiToken; -using AElf.Cryptography; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.TestBase; using AElf.Types; using Google.Protobuf; @@ -16,130 +13,127 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + [IgnoreOnCIFact] + public async Task Candidates_NotEnough_Test() { - [IgnoreOnCIFact] - public async Task Candidates_NotEnough_Test() - { - await InitializeCandidates(EconomicContractsTestConstants.InitialCoreDataCenterCount); + await InitializeCandidates(EconomicContractsTestConstants.InitialCoreDataCenterCount); - var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var firstRound = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Select(_ => HashHelper.ComputeFrom("hash3")).ToList(); - var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i => - new AElfConsensusTriggerInformation - { - Pubkey = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey), - InValue = randomHashes[i] - }).ToDictionary(t => t.Pubkey.ToHex(), t => t); + var randomHashes = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Select(_ => HashHelper.ComputeFrom("hash3")).ToList(); + var triggers = Enumerable.Range(0, EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(i => + new AElfConsensusTriggerInformation + { + Pubkey = ByteString.CopyFrom(InitialCoreDataCenterKeyPairs[i].PublicKey), + InValue = randomHashes[i] + }).ToDictionary(t => t.Pubkey.ToHex(), t => t); - var voter = GetElectionContractTester(VoterKeyPairs[0]); + var voter = GetElectionContractTester(VoterKeyPairs[0]); - foreach (var candidateKeyPair in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants - .InitialCoreDataCenterCount)) + foreach (var candidateKeyPair in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants + .InitialCoreDataCenterCount)) + await voter.Vote.SendAsync(new VoteMinerInput { - await voter.Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), - Amount = 100 + new Random().Next(1, 200), - EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100) - }); - } - - foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) - { - var currentKeyPair = - InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey); - - KeyPairProvider.SetKeyPair(currentKeyPair); - - BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime); - - var tester = GetAEDPoSContractStub(currentKeyPair); - var headerInformation = - (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] - .ToBytesValue())).ToConsensusHeaderInformation(); - - // Update consensus information. - var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); - await tester.UpdateValue.SendAsync(toUpdate); - } - - var changeTermTime = BlockchainStartTimestamp.ToDateTime() - .AddMinutes(AEDPoSContractTestConstants.PeriodSeconds + 1); - BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); - - var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.NextTerm, - Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation(); - - await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); - - // First candidate cheat others with in value. - var oneCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); - var anotherCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[1]); - var randomHash = HashHelper.ComputeFrom("hash5"); - var informationOfSecondRound = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.UpdateValue, - PreviousInValue = Hash.Empty, - InValue = randomHash, - Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation(); - var updateResult = await oneCandidate.UpdateValue.SendAsync( - informationOfSecondRound.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0] - .PublicKey.ToHex())); - - var thirdRoundStartTime = changeTermTime.AddMinutes(AEDPoSContractTestConstants.PeriodSeconds + 2); - BlockTimeProvider.SetBlockTime(thirdRoundStartTime.ToTimestamp()); - var thirdRound = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.NextRound, - Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation().Round; - - await oneCandidate.NextRound.SendAsync(thirdRound); - - var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.UpdateValue, - PreviousInValue = HashHelper.ComputeFrom(randomHash), // Not same as before. - InValue = HashHelper.ComputeFrom("InValue"), // Don't care this value in current test case. - Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation(); - await oneCandidate.UpdateValue.SendAsync( - cheatInformation.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0].PublicKey - .ToHex())); - } + CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), + Amount = 100 + new Random().Next(1, 200), + EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100) + }); - [Fact] - public async Task Update_TinyBlockInformation_Test() + foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) { - await AEDPoSContract_FirstRound_BootMiner_Test(); + var currentKeyPair = + InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey); - var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + KeyPairProvider.SetKeyPair(currentKeyPair); - BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration + BlockTimeProvider.SetBlockTime(minerInRound.ExpectedMiningTime); + + var tester = GetAEDPoSContractStub(currentKeyPair); + var headerInformation = + (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] + .ToBytesValue())).ToConsensusHeaderInformation(); + + // Update consensus information. + var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); + await tester.UpdateValue.SendAsync(toUpdate); + } + + var changeTermTime = BlockchainStartTimestamp.ToDateTime() + .AddMinutes(AEDPoSContractTestConstants.PeriodSeconds + 1); + BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); + + var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation { - Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) - }); - var input = new TinyBlockInput + Behaviour = AElfConsensusBehaviour.NextTerm, + Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); + + await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); + + // First candidate cheat others with in value. + var oneCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); + var anotherCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[1]); + var randomHash = HashHelper.ComputeFrom("hash5"); + var informationOfSecondRound = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation { - RoundId = roundInfo.RoundId, - ProducedBlocks = 4, - ActualMiningTime = BlockTimeProvider.GetBlockTime() - }; - var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Behaviour = AElfConsensusBehaviour.UpdateValue, + PreviousInValue = Hash.Empty, + InValue = randomHash, + Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); + var updateResult = await oneCandidate.UpdateValue.SendAsync( + informationOfSecondRound.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0] + .PublicKey.ToHex())); + + var thirdRoundStartTime = changeTermTime.AddMinutes(AEDPoSContractTestConstants.PeriodSeconds + 2); + BlockTimeProvider.SetBlockTime(thirdRoundStartTime.ToTimestamp()); + var thirdRound = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation + { + Behaviour = AElfConsensusBehaviour.NextRound, + Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation().Round; + + await oneCandidate.NextRound.SendAsync(thirdRound); + + var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation + { + Behaviour = AElfConsensusBehaviour.UpdateValue, + PreviousInValue = HashHelper.ComputeFrom(randomHash), // Not same as before. + InValue = HashHelper.ComputeFrom("InValue"), // Don't care this value in current test case. + Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); + await oneCandidate.UpdateValue.SendAsync( + cheatInformation.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0].PublicKey + .ToHex())); + } + + [Fact] + public async Task Update_TinyBlockInformation_Test() + { + await AEDPoSContract_FirstRound_BootMiner_Test(); + + var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + + BlockTimeProvider.SetBlockTime(BlockchainStartTimestamp + new Duration + { + Seconds = AEDPoSContractTestConstants.MiningInterval.Div(1000) + }); + var input = new TinyBlockInput + { + RoundId = roundInfo.RoundId, + ProducedBlocks = 4, + ActualMiningTime = BlockTimeProvider.GetBlockTime() + }; + var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/SideChainDividendPoolTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/SideChainDividendPoolTest.cs index dd9d219a8a..c70439beed 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/SideChainDividendPoolTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/SideChainDividendPoolTest.cs @@ -4,38 +4,37 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + [Fact] + public async Task SideChainDividendPool_Release_Test() { - [Fact] - public async Task SideChainDividendPool_Release_Test() + var result = await AEDPoSContractStub.Release.SendAsync(new ReleaseInput { - var result = await AEDPoSContractStub.Release.SendAsync(new ReleaseInput - { - PeriodNumber = 1 - }); - result.TransactionResult.Error.ShouldContain("Side chain dividend pool can only release automatically."); - } + PeriodNumber = 1 + }); + result.TransactionResult.Error.ShouldContain("Side chain dividend pool can only release automatically."); + } - [Fact] - public async Task SideChainDividendPool_SetSymbolList_Test() - { - var result = await AEDPoSContractStub.SetSymbolList.SendAsync(new SymbolList()); - result.TransactionResult.Error.ShouldContain("Side chain dividend pool not support setting symbol list."); - } + [Fact] + public async Task SideChainDividendPool_SetSymbolList_Test() + { + var result = await AEDPoSContractStub.SetSymbolList.SendAsync(new SymbolList()); + result.TransactionResult.Error.ShouldContain("Side chain dividend pool not support setting symbol list."); + } - [Fact] - public async Task SideChainDividendPool_Views_Test() - { - var dividends = await AEDPoSContractStub.GetDividends.CallAsync(new Int64Value {Value = 1}); - dividends.Value.Count.ShouldBe(0); + [Fact] + public async Task SideChainDividendPool_Views_Test() + { + var dividends = await AEDPoSContractStub.GetDividends.CallAsync(new Int64Value { Value = 1 }); + dividends.Value.Count.ShouldBe(0); - var symbolList = await AEDPoSContractStub.GetSymbolList.CallAsync(new Empty()); - symbolList.Value.Count.ShouldBe(0); + var symbolList = await AEDPoSContractStub.GetSymbolList.CallAsync(new Empty()); + symbolList.Value.Count.ShouldBe(0); - var undistributedDividends = await AEDPoSContractStub.GetUndistributedDividends.CallAsync(new Empty()); - undistributedDividends.Value.Count.ShouldBe(0); - } + var undistributedDividends = await AEDPoSContractStub.GetUndistributedDividends.CallAsync(new Empty()); + undistributedDividends.Value.Count.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index 683e168095..b75b324ccf 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -1,98 +1,96 @@ using System.Linq; using System.Threading.Tasks; -using AElf.TestBase; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class AEDPoSTest { - public partial class AEDPoSTest + [Fact] + public async Task Query_RoundInformation_Test() { - [Fact] - public async Task Query_RoundInformation_Test() - { - //first round - var roundNumber = await AEDPoSContractStub.GetCurrentRoundNumber.CallAsync(new Empty()); + //first round + var roundNumber = await AEDPoSContractStub.GetCurrentRoundNumber.CallAsync(new Empty()); - var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - roundInfo.TermNumber.ShouldBe(roundNumber.Value); + var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + roundInfo.TermNumber.ShouldBe(roundNumber.Value); - //second round - var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( - new AElfConsensusTriggerInformation - { - Behaviour = AElfConsensusBehaviour.NextRound, - Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) - }.ToBytesValue())).ToConsensusHeaderInformation(); + //second round + var nextTermInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( + new AElfConsensusTriggerInformation + { + Behaviour = AElfConsensusBehaviour.NextRound, + Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) + }.ToBytesValue())).ToConsensusHeaderInformation(); - var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - roundNumber = await AEDPoSContractStub.GetCurrentRoundNumber.CallAsync(new Empty()); - roundNumber.Value.ShouldBe(2); + roundNumber = await AEDPoSContractStub.GetCurrentRoundNumber.CallAsync(new Empty()); + roundNumber.Value.ShouldBe(2); - roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - roundInfo.RoundNumber.ShouldBe(2); + roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + roundInfo.RoundNumber.ShouldBe(2); - var previousRoundInfo = await AEDPoSContractStub.GetPreviousRoundInformation.CallAsync(new Empty()); - previousRoundInfo.RoundNumber.ShouldBe(1); + var previousRoundInfo = await AEDPoSContractStub.GetPreviousRoundInformation.CallAsync(new Empty()); + previousRoundInfo.RoundNumber.ShouldBe(1); - var roundInformation = await AEDPoSContractStub.GetRoundInformation.CallAsync(new Int64Value - { - Value = 2 - }); - roundInformation.RoundNumber.ShouldBe(2); - roundInformation.TermNumber.ShouldBe(1); - - var currentTermRemainSeconds = - (await AEDPoSContractStub.GetNextElectCountDown.CallAsync(new Empty())).Value; - currentTermRemainSeconds.ShouldBeGreaterThan(0); - currentTermRemainSeconds.ShouldBe(604800); - - //get term number - var termNumber = await AEDPoSContractStub.GetCurrentTermNumber.CallAsync(new Empty()); - termNumber.Value.ShouldBe(1); - } - - [Fact] - public async Task GetCurrentMinerPubkeyList_Test() + var roundInformation = await AEDPoSContractStub.GetRoundInformation.CallAsync(new Int64Value { - var pubkeyList = await AEDPoSContractStub.GetCurrentMinerPubkeyList.CallAsync(new Empty()); - pubkeyList.Pubkeys.Count.ShouldBe(5); + Value = 2 + }); + roundInformation.RoundNumber.ShouldBe(2); + roundInformation.TermNumber.ShouldBe(1); + + var currentTermRemainSeconds = + (await AEDPoSContractStub.GetNextElectCountDown.CallAsync(new Empty())).Value; + currentTermRemainSeconds.ShouldBeGreaterThan(0); + currentTermRemainSeconds.ShouldBe(604800); + + //get term number + var termNumber = await AEDPoSContractStub.GetCurrentTermNumber.CallAsync(new Empty()); + termNumber.Value.ShouldBe(1); + } - var miners = await AEDPoSContractStub.GetMinerList.CallAsync(new GetMinerListInput - { - TermNumber = 1 - }); - var pubKeys = miners.Pubkeys.Select(o => o.ToHex()).ToList(); - pubKeys.Count.ShouldBe(5); - pubKeys.ShouldBe(pubkeyList.Pubkeys); - } - - [Fact] - public async Task GetNextMinerPubkey_Test() - { - var pubkeyList = await AEDPoSContractStub.GetCurrentMinerPubkeyList.CallAsync(new Empty()); - var nextMiner = await AEDPoSContractStub.GetNextMinerPubkey.CallAsync(new Empty()); - pubkeyList.Pubkeys.ShouldContain(nextMiner.Value); - } + [Fact] + public async Task GetCurrentMinerPubkeyList_Test() + { + var pubkeyList = await AEDPoSContractStub.GetCurrentMinerPubkeyList.CallAsync(new Empty()); + pubkeyList.Pubkeys.Count.ShouldBe(5); - [Fact] - public async Task GetCurrentMinerList_Test() + var miners = await AEDPoSContractStub.GetMinerList.CallAsync(new GetMinerListInput { - var minerList = await AEDPoSContractStub.GetMinerList.CallAsync(new GetMinerListInput {TermNumber = 1}); - minerList.Pubkeys.Count.ShouldBe(5); + TermNumber = 1 + }); + var pubKeys = miners.Pubkeys.Select(o => o.ToHex()).ToList(); + pubKeys.Count.ShouldBe(5); + pubKeys.ShouldBe(pubkeyList.Pubkeys); + } + + [Fact] + public async Task GetNextMinerPubkey_Test() + { + var pubkeyList = await AEDPoSContractStub.GetCurrentMinerPubkeyList.CallAsync(new Empty()); + var nextMiner = await AEDPoSContractStub.GetNextMinerPubkey.CallAsync(new Empty()); + pubkeyList.Pubkeys.ShouldContain(nextMiner.Value); + } + + [Fact] + public async Task GetCurrentMinerList_Test() + { + var minerList = await AEDPoSContractStub.GetMinerList.CallAsync(new GetMinerListInput { TermNumber = 1 }); + minerList.Pubkeys.Count.ShouldBe(5); - var currentMinerListWithRoundNumber = - await AEDPoSContractStub.GetCurrentMinerListWithRoundNumber.CallAsync(new Empty()); - currentMinerListWithRoundNumber.MinerList.Pubkeys.Count.ShouldBe(5); - currentMinerListWithRoundNumber.RoundNumber.ShouldBe(1); + var currentMinerListWithRoundNumber = + await AEDPoSContractStub.GetCurrentMinerListWithRoundNumber.CallAsync(new Empty()); + currentMinerListWithRoundNumber.MinerList.Pubkeys.Count.ShouldBe(5); + currentMinerListWithRoundNumber.RoundNumber.ShouldBe(1); - var nextMiner = await AEDPoSContractStub.GetNextMinerPubkey.CallAsync(new Empty()); - minerList.Pubkeys.Select(k => k.ToHex()).ShouldContain(nextMiner.Value); - } + var nextMiner = await AEDPoSContractStub.GetNextMinerPubkey.CallAsync(new Empty()); + minerList.Pubkeys.Select(k => k.ToHex()).ShouldContain(nextMiner.Value); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Extensions/BytesValueExtensions.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Extensions/BytesValueExtensions.cs index 519d733f73..7876782d76 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Extensions/BytesValueExtensions.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Extensions/BytesValueExtensions.cs @@ -1,15 +1,14 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public static class ByteStringExtensions { - public static class ByteStringExtensions + internal static AElfConsensusHeaderInformation ToConsensusHeaderInformation(this BytesValue bytesValue) { - internal static AElfConsensusHeaderInformation ToConsensusHeaderInformation(this BytesValue bytesValue) - { - var headerInformation = new AElfConsensusHeaderInformation(); - headerInformation.MergeFrom(bytesValue.Value); - return headerInformation; - } + var headerInformation = new AElfConsensusHeaderInformation(); + headerInformation.MergeFrom(bytesValue.Value); + return headerInformation; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/ResetBlockTimeProvider.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/ResetBlockTimeProvider.cs index 741f1345f7..6b34af0e81 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/ResetBlockTimeProvider.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/ResetBlockTimeProvider.cs @@ -1,10 +1,9 @@ using AElf.ContractTestKit; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +public class ResetBlockTimeProvider : IResetBlockTimeProvider { - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => false; - public int StepMilliseconds => 0; - } + public bool Enabled => false; + public int StepMilliseconds => 0; } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/MinerList.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/MinerList.cs index 38e379de8c..326aedf750 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/MinerList.cs @@ -4,46 +4,42 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval).ToTimestamp(); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval).ToTimestamp(); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs index 795989f87d..f0e6cee28e 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs @@ -1,151 +1,133 @@ using System; -using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS4; using AElf.Types; -using AElf.Sdk.CSharp; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public long RoundId { - public long RoundId + get { - get - { - if (RealTimeMinersInformation.Values.All(bpInfo => bpInfo.ExpectedMiningTime != null)) - { - return RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); - } - - return RoundIdForValidation; - } - } + if (RealTimeMinersInformation.Values.All(bpInfo => bpInfo.ExpectedMiningTime != null)) + return RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); - /// - /// This method is only available when the miners of this round is more than 1. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } - - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); - var distance = - (int) (firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - - firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) - .TotalMilliseconds; - return distance > 0 ? distance : -distance; + return RoundIdForValidation; } + } - /// - /// Actually the expected mining time of the miner whose order is 1. - /// - /// - public DateTime GetStartTime() - { - return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); - } + /// + /// This method is only available when the miners of this round is more than 1. + /// + /// + public int GetMiningInterval() + { + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; + + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); + var distance = + (int)(firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - + firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) + .TotalMilliseconds; + return distance > 0 ? distance : -distance; + } - /// - /// This method for now is able to handle the situation of a miner keeping offline so many rounds, - /// by using missedRoundsCount. - /// - /// - /// - /// - /// - public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } - - var totalMilliseconds = TotalMilliseconds(miningInterval); - return GetStartTime().AddMilliseconds(totalMilliseconds) - // Arrange an ending time if this node missed so many rounds. - .AddMilliseconds(missedRoundsCount * totalMilliseconds) - .ToTimestamp(); - } + /// + /// Actually the expected mining time of the miner whose order is 1. + /// + /// + public DateTime GetStartTime() + { + return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); + } - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + /// + /// This method for now is able to handle the situation of a miner keeping offline so many rounds, + /// by using missedRoundsCount. + /// + /// + /// + /// + /// + public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } + var totalMilliseconds = TotalMilliseconds(miningInterval); + return GetStartTime().AddMilliseconds(totalMilliseconds) + // Arrange an ending time if this node missed so many rounds. + .AddMilliseconds(missedRoundsCount * totalMilliseconds) + .ToTimestamp(); + } - /// - /// Maybe tune other miners' supposed order of next round, - /// will record this purpose to their FinalOrderOfNextRound field. - /// - /// - /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) - { - if (!RealTimeMinersInformation.ContainsKey(pubkey)) - { - return null; - } - - var minerInRound = RealTimeMinersInformation[pubkey]; - - var tuneOrderInformation = RealTimeMinersInformation.Values - .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) - .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); - - var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => - v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) - .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); - - var minersPreviousInValues = - RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( - info => info.Pubkey, - info => info.PreviousInValue); - - return new UpdateValueInput - { - OutValue = minerInRound.OutValue, - Signature = minerInRound.Signature, - PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, - RoundId = RoundIdForValidation, - ProducedBlocks = minerInRound.ProducedBlocks, - ActualMiningTime = minerInRound.ActualMiningTimes.First(), - SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, - TuneOrderInformation = {tuneOrderInformation}, - EncryptedPieces = {minerInRound.EncryptedPieces}, - DecryptedPieces = {decryptedPreviousInValues}, - MinersPreviousInValues = {minersPreviousInValues} - }; - } + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - public long GetMinedBlocks() - { - return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); - } + return RealTimeMinersInformation.Count * miningInterval + miningInterval; + } + + /// + /// Maybe tune other miners' supposed order of next round, + /// will record this purpose to their FinalOrderOfNextRound field. + /// + /// + /// + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) + { + if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; + + var minerInRound = RealTimeMinersInformation[pubkey]; + + var tuneOrderInformation = RealTimeMinersInformation.Values + .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) + .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); + + var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => + v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) + .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); - private static int GetAbsModulus(long longValue, int intValue) + var minersPreviousInValues = + RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( + info => info.Pubkey, + info => info.PreviousInValue); + + return new UpdateValueInput { - return Math.Abs((int) longValue % intValue); - } + OutValue = minerInRound.OutValue, + Signature = minerInRound.Signature, + PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, + RoundId = RoundIdForValidation, + ProducedBlocks = minerInRound.ProducedBlocks, + ActualMiningTime = minerInRound.ActualMiningTimes.First(), + SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, + TuneOrderInformation = { tuneOrderInformation }, + EncryptedPieces = { minerInRound.EncryptedPieces }, + DecryptedPieces = { decryptedPreviousInValues }, + MinersPreviousInValues = { minersPreviousInValues } + }; + } + + public long GetMinedBlocks() + { + return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); + } + + private static int GetAbsModulus(long longValue, int intValue) + { + return Math.Abs((int)longValue % intValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs index e163cac3bd..34830558d0 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs @@ -1,110 +1,98 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound) { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, out Round nextRound) - { - nextRound = new Round(); + nextRound = new Round(); - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - if (RoundNumber == 1) - { - nextRound.BlockchainAge = 1; - } - else - { - nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - } + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + if (RoundNumber == 1) + nextRound.BlockchainAge = 1; + else + nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + { + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; + } - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + { + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots + 1 - }; - } + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + 1 + }; + } - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; - return true; - } - - private int CalculateNextExtraBlockProducerOrder() - { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) - { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } + return true; + } - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToByteArray().ToInt64(true); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; - } - - public List GetMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); - } - - public List GetNotMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); - } + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; + + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToByteArray().ToInt64(true); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } + + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } + + public List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/AElf.Contracts.CrossChain.Tests.csproj b/test/AElf.Contracts.CrossChain.Tests/AElf.Contracts.CrossChain.Tests.csproj index 9deb0308be..ade4df35b6 100644 --- a/test/AElf.Contracts.CrossChain.Tests/AElf.Contracts.CrossChain.Tests.csproj +++ b/test/AElf.Contracts.CrossChain.Tests/AElf.Contracts.CrossChain.Tests.csproj @@ -7,14 +7,14 @@ false - - - - - - + + + + + + - + Protobuf\Proto\authority_info.proto @@ -84,6 +84,6 @@ - + diff --git a/test/AElf.Contracts.CrossChain.Tests/ContractDeploymentListProvider.cs b/test/AElf.Contracts.CrossChain.Tests/ContractDeploymentListProvider.cs index e0b81bb969..7c9e1c5301 100644 --- a/test/AElf.Contracts.CrossChain.Tests/ContractDeploymentListProvider.cs +++ b/test/AElf.Contracts.CrossChain.Tests/ContractDeploymentListProvider.cs @@ -7,20 +7,19 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +public class ContractDeploymentListProvider : IContractDeploymentListProvider { - public class ContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - AssociationSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - }; - } + AssociationSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestAElfModule.cs b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestAElfModule.cs index 17dc5a7d13..d785248b31 100644 --- a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestAElfModule.cs +++ b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestAElfModule.cs @@ -13,41 +13,40 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(GovernmentSystemAElfModule))] +public class CrossChainContractTestAElfModule : AbpModule { - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(GovernmentSystemAElfModule))] - public class CrossChainContractTestAElfModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = - SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); - }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.RemoveAll(s => s.ImplementationType == typeof(TokenContractInitializationProvider)); - context.Services - .AddTransient(); - context.Services - .AddTransient(); - } - - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + Configure(options => { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + options.MiningInterval = 4000; + options.InitialMinerList = + SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); + }); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.RemoveAll(s => s.ImplementationType == typeof(TokenContractInitializationProvider)); + context.Services + .AddTransient(); + context.Services + .AddTransient(); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs index 9245f94b91..11e08408eb 100644 --- a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs +++ b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.Association; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; @@ -12,6 +10,8 @@ using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.SmartContract; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -21,425 +21,426 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +public class CrossChainContractTestBase : ContractTestBase where T : AbpModule { - public class CrossChainContractTestBase : ContractTestBase where T : AbpModule + public CrossChainContractTestBase() { - #region Contract Address - - #endregion + AsyncHelper.RunSync(InitializeTokenAsync); + } - protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; + protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; - protected ECKeyPair AnotherKeyPair => Accounts.Last().KeyPair; - protected Address AnotherSender => Accounts.Last().Address; + protected ECKeyPair AnotherKeyPair => Accounts.Last().KeyPair; + protected Address AnotherSender => Accounts.Last().Address; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - protected Address DefaultSender => Address.FromPublicKey(DefaultKeyPair.PublicKey); + protected Address DefaultSender => Address.FromPublicKey(DefaultKeyPair.PublicKey); - protected Address AnotherSenderAddress => Address.FromPublicKey(AnotherKeyPair.PublicKey); + protected Address AnotherSenderAddress => Address.FromPublicKey(AnotherKeyPair.PublicKey); - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); - #region Token + #region Token - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub => - GetTester(TokenContractAddress, DefaultKeyPair); - - #endregion + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub => + GetTester(TokenContractAddress, DefaultKeyPair); - #region Paliament + #endregion - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetTester(ParliamentContractAddress, DefaultKeyPair); + internal CrossChainContractImplContainer.CrossChainContractImplStub CrossChainContractStub => + GetCrossChainContractStub(DefaultKeyPair); - internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub => - GetTester(AssociationContractAddress, DefaultKeyPair); - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } - - internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractStub(ECKeyPair keyPair) - { - return GetTester(AssociationContractAddress, - keyPair); - } + protected List ResourceTokenSymbolList => + GetRequiredService>() + .Value.ContextVariables["SymbolListToPayRental"].Split(",").ToList(); - #endregion + internal CrossChainContractImplContainer.CrossChainContractImplStub GetCrossChainContractStub( + ECKeyPair keyPair) + { + return GetTester( + CrossChainContractAddress, + keyPair); + } - internal CrossChainContractImplContainer.CrossChainContractImplStub CrossChainContractStub => - GetCrossChainContractStub(DefaultKeyPair); + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractStub(ECKeyPair keyPair) + { + return GetTester( + TokenContractAddress, + keyPair); + } - internal CrossChainContractImplContainer.CrossChainContractImplStub GetCrossChainContractStub( - ECKeyPair keyPair) + protected async Task InitializeCrossChainContractAsync(long parentChainHeightOfCreation = 0, + int parentChainId = 0, bool withException = false) + { + var tx = CrossChainContractStub.Initialize.GetTransaction(new InitializeInput { - return GetTester( - CrossChainContractAddress, - keyPair); - } + ParentChainId = parentChainId, + CreationHeightOnParentChain = parentChainHeightOfCreation + }); - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractStub(ECKeyPair keyPair) + var blockExecutedSet = await MineAsync(new List { - return GetTester( - TokenContractAddress, - keyPair); - } - - protected List ResourceTokenSymbolList => GetRequiredService>() - .Value.ContextVariables["SymbolListToPayRental"].Split(",").ToList(); - - public CrossChainContractTestBase() - { - AsyncHelper.RunSync(InitializeTokenAsync); - } + tx + }); + (blockExecutedSet.TransactionResultMap[tx.GetHash()].Status == TransactionResultStatus.Failed).ShouldBe( + withException); + } - protected async Task InitializeCrossChainContractAsync(long parentChainHeightOfCreation = 0, - int parentChainId = 0, bool withException = false) - { - var tx = CrossChainContractStub.Initialize.GetTransaction(new InitializeInput - { - ParentChainId = parentChainId, - CreationHeightOnParentChain = parentChainHeightOfCreation - }); - - var blockExecutedSet = await MineAsync(new List - { - tx - }); - (blockExecutedSet.TransactionResultMap[tx.GetHash()].Status == TransactionResultStatus.Failed).ShouldBe( - withException); - } + internal async Task InitAndCreateSideChainAsync(long parentChainHeightOfCreation = 0, + int parentChainId = 0, long lockedTokenAmount = 10, long indexingFee = 1, ECKeyPair keyPair = null, + bool withException = false, bool isPrivilegeReserved = false) + { + await InitializeCrossChainContractAsync(parentChainHeightOfCreation, parentChainId, withException); + await ApproveBalanceAsync(lockedTokenAmount, keyPair); + var proposalId = + await CreateSideChainProposalAsync(indexingFee, lockedTokenAmount, keyPair, null, isPrivilegeReserved); + await ApproveWithMinersAsync(proposalId); + + var crossChainContractStub = keyPair == null ? CrossChainContractStub : GetCrossChainContractStub(keyPair); + var releaseTx = + await crossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var chainId = sideChainCreatedEvent.ChainId; + + return chainId; + } - internal async Task InitAndCreateSideChainAsync(long parentChainHeightOfCreation = 0, - int parentChainId = 0, long lockedTokenAmount = 10, long indexingFee = 1, ECKeyPair keyPair = null, - bool withException = false, bool isPrivilegeReserved = false) - { - await InitializeCrossChainContractAsync(parentChainHeightOfCreation, parentChainId, withException); - await ApproveBalanceAsync(lockedTokenAmount, keyPair); - var proposalId = - await CreateSideChainProposalAsync(indexingFee, lockedTokenAmount, keyPair, null, isPrivilegeReserved); - await ApproveWithMinersAsync(proposalId); - - var crossChainContractStub = keyPair == null ? CrossChainContractStub : GetCrossChainContractStub(keyPair); - var releaseTx = - await crossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var chainId = sideChainCreatedEvent.ChainId; - - return chainId; - } - - internal async Task CreateSideChainAsync(bool initCrossChainContract, long parentChainHeightOfCreation, - int parentChainId, long lockedTokenAmount, long indexingFee, bool isPrivilegeReserved) - { - if (initCrossChainContract) - await InitializeCrossChainContractAsync(parentChainHeightOfCreation, parentChainId); - await ApproveBalanceAsync(lockedTokenAmount); - var proposalId = - await CreateSideChainProposalAsync(indexingFee, lockedTokenAmount, null, null, isPrivilegeReserved); - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - - return releaseTx.TransactionResult; - } - - internal async Task CreateSideChainByDefaultSenderAsync(bool initCrossChainContract, long parentChainHeightOfCreation = 0, - int parentChainId = 0, long lockedTokenAmount = 10, long indexingFee = 1, bool isPrivilegeReserved = false) - { - var releaseTxResult = - await CreateSideChainAsync(initCrossChainContract, parentChainHeightOfCreation, parentChainId, lockedTokenAmount, - indexingFee, isPrivilegeReserved); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(releaseTxResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); - - var sideChainId = sideChainCreatedEvent.ChainId; - return sideChainId; - } + internal async Task CreateSideChainAsync(bool initCrossChainContract, + long parentChainHeightOfCreation, + int parentChainId, long lockedTokenAmount, long indexingFee, bool isPrivilegeReserved) + { + if (initCrossChainContract) + await InitializeCrossChainContractAsync(parentChainHeightOfCreation, parentChainId); + await ApproveBalanceAsync(lockedTokenAmount); + var proposalId = + await CreateSideChainProposalAsync(indexingFee, lockedTokenAmount, null, null, isPrivilegeReserved); + await ApproveWithMinersAsync(proposalId); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + + return releaseTx.TransactionResult; + } - private async Task InitializeParliamentContractAsync() - { - var initializeResult = await ParliamentContractStub.Initialize.SendAsync( - new Parliament.InitializeInput - { - PrivilegedProposer = DefaultSender, - ProposerAuthorityRequired = false - }); - CheckResult(initializeResult.TransactionResult); - } + internal async Task CreateSideChainByDefaultSenderAsync(bool initCrossChainContract, + long parentChainHeightOfCreation = 0, + int parentChainId = 0, long lockedTokenAmount = 10, long indexingFee = 1, bool isPrivilegeReserved = false) + { + var releaseTxResult = + await CreateSideChainAsync(initCrossChainContract, parentChainHeightOfCreation, parentChainId, + lockedTokenAmount, + indexingFee, isPrivilegeReserved); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(releaseTxResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); + + var sideChainId = sideChainCreatedEvent.ChainId; + return sideChainId; + } - private async Task InitializeTokenAsync() - { - const string symbol = "ELF"; - const long totalSupply = 100_000_000; - await MineAsync(new List + private async Task InitializeParliamentContractAsync() + { + var initializeResult = await ParliamentContractStub.Initialize.SendAsync( + new Parliament.InitializeInput { - TokenContractStub.Create.GetTransaction(new CreateInput - { - Symbol = symbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - }), - TokenContractStub.Issue.GetTransaction(new IssueInput - { - Symbol = symbol, - Amount = totalSupply - 20 * 100_000L, - To = DefaultSender, - Memo = "Issue token to default user.", - }) + PrivilegedProposer = DefaultSender, + ProposerAuthorityRequired = false }); - } + CheckResult(initializeResult.TransactionResult); + } - protected async Task ApproveBalanceAsync(long amount, ECKeyPair keyPair = null) + private async Task InitializeTokenAsync() + { + const string symbol = "ELF"; + const long totalSupply = 100_000_000; + await MineAsync(new List { - var tokenContractStub = keyPair == null ? TokenContractStub : GetTokenContractStub(keyPair); - await MineAsync(new List + TokenContractStub.Create.GetTransaction(new CreateInput { - tokenContractStub.Approve.GetTransaction(new ApproveInput - { - Spender = CrossChainContractAddress, - Symbol = "ELF", - Amount = amount - }), - tokenContractStub.GetAllowance.GetTransaction(new GetAllowanceInput - { - Symbol = "ELF", - Owner = DefaultSender, - Spender = CrossChainContractAddress - }) - }); - } + Symbol = symbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender + }), + TokenContractStub.Issue.GetTransaction(new IssueInput + { + Symbol = symbol, + Amount = totalSupply - 20 * 100_000L, + To = DefaultSender, + Memo = "Issue token to default user." + }) + }); + } - internal async Task ApproveAndTransferOrganizationBalanceAsync(Address organizationAddress, - long amount) + protected async Task ApproveBalanceAsync(long amount, ECKeyPair keyPair = null) + { + var tokenContractStub = keyPair == null ? TokenContractStub : GetTokenContractStub(keyPair); + await MineAsync(new List { - var approveInput = new ApproveInput + tokenContractStub.Approve.GetTransaction(new ApproveInput { Spender = CrossChainContractAddress, Symbol = "ELF", Amount = amount - }; - var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = approveInput.ToByteString(), - ToAddress = TokenContractAddress, - OrganizationAddress = organizationAddress - })).Output; - await ApproveWithMinersAsync(proposal); - await ReleaseProposalAsync(proposal); - - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "ELF", - Amount = amount, - To = organizationAddress - }); - - var allowance = (await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + }), + tokenContractStub.GetAllowance.GetTransaction(new GetAllowanceInput { Symbol = "ELF", - Owner = organizationAddress, + Owner = DefaultSender, Spender = CrossChainContractAddress - })); + }) + }); + } - return allowance; - } + internal async Task ApproveAndTransferOrganizationBalanceAsync(Address organizationAddress, + long amount) + { + var approveInput = new ApproveInput + { + Spender = CrossChainContractAddress, + Symbol = "ELF", + Amount = amount + }; + var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = approveInput.ToByteString(), + ToAddress = TokenContractAddress, + OrganizationAddress = organizationAddress + })).Output; + await ApproveWithMinersAsync(proposal); + await ReleaseProposalAsync(proposal); + + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Symbol = "ELF", + Amount = amount, + To = organizationAddress + }); - internal async Task CreateSideChainProposalAsync(long indexingPrice, long lockedTokenAmount, - ECKeyPair keyPair = null, - Dictionary resourceAmount = null, bool isPrivilegeReserved = false) + var allowance = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - var createProposalInput = CreateSideChainCreationRequest(indexingPrice, lockedTokenAmount, - resourceAmount ?? GetValidResourceAmount(), new[] + Symbol = "ELF", + Owner = organizationAddress, + Spender = CrossChainContractAddress + }); + + return allowance; + } + + internal async Task CreateSideChainProposalAsync(long indexingPrice, long lockedTokenAmount, + ECKeyPair keyPair = null, + Dictionary resourceAmount = null, bool isPrivilegeReserved = false) + { + var createProposalInput = CreateSideChainCreationRequest(indexingPrice, lockedTokenAmount, + resourceAmount ?? GetValidResourceAmount(), new[] + { + new SideChainTokenInitialIssue { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, isPrivilegeReserved); - var crossChainContractStub = keyPair == null ? CrossChainContractStub : GetCrossChainContractStub(keyPair); - var requestSideChainCreation = - await crossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - - var proposalId = ProposalCreated.Parser.ParseFrom(requestSideChainCreation.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; - return proposalId; - } + Address = DefaultSender, + Amount = 100 + } + }, isPrivilegeReserved); + var crossChainContractStub = keyPair == null ? CrossChainContractStub : GetCrossChainContractStub(keyPair); + var requestSideChainCreation = + await crossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); + + var proposalId = ProposalCreated.Parser.ParseFrom(requestSideChainCreation.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + return proposalId; + } - internal async Task CreateParliamentProposalAsync(string method, Address organizationAddress, - IMessage input, Address toAddress = null) + internal async Task CreateParliamentProposalAsync(string method, Address organizationAddress, + IMessage input, Address toAddress = null) + { + var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + ToAddress = toAddress ?? CrossChainContractAddress, + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = organizationAddress, + Params = input.ToByteString() + })).Output; + return proposal; + } + + internal async Task CreateAssociationProposalAsync(string method, Address organizationAddress, + Address toAddress, + IMessage input, AssociationContractImplContainer.AssociationContractImplStub authorizationContractStub = null) + { + var proposalId = (await (authorizationContractStub ?? AssociationContractStub).CreateProposal.SendAsync( + new CreateProposalInput { - ToAddress = toAddress ?? CrossChainContractAddress, + ToAddress = toAddress, ContractMethodName = method, ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), OrganizationAddress = organizationAddress, Params = input.ToByteString() })).Output; - return proposal; - } - - internal async Task CreateAssociationProposalAsync(string method, Address organizationAddress, - Address toAddress, - IMessage input, AssociationContractImplContainer.AssociationContractImplStub authorizationContractStub = null) - { - var proposalId = (await (authorizationContractStub ?? AssociationContractStub).CreateProposal.SendAsync( - new CreateProposalInput - { - ToAddress = toAddress, - ContractMethodName = method, - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = organizationAddress, - Params = input.ToByteString() - })).Output; - return proposalId; - } + return proposalId; + } - protected async Task ReleaseProposalAsync(Hash proposalId) - { - var transaction = await ParliamentContractStub.Release.SendAsync(proposalId); - return transaction.TransactionResult; - } + protected async Task ReleaseProposalAsync(Hash proposalId) + { + var transaction = await ParliamentContractStub.Release.SendAsync(proposalId); + return transaction.TransactionResult; + } - protected async Task ReleaseProposalWithExceptionAsync(Hash proposalId) - { - var transaction = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - return transaction.TransactionResult; - } + protected async Task ReleaseProposalWithExceptionAsync(Hash proposalId) + { + var transaction = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + return transaction.TransactionResult; + } - internal SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, - Dictionary resourceAmount, SideChainTokenInitialIssue[] sideChainTokenInitialIssueList, - bool isPrivilegePreserved = false) + internal SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, + Dictionary resourceAmount, SideChainTokenInitialIssue[] sideChainTokenInitialIssueList, + bool isPrivilegePreserved = false) + { + var res = new SideChainCreationRequest { - var res = new SideChainCreationRequest + IndexingPrice = indexingPrice, + LockedTokenAmount = lockedTokenAmount, + SideChainTokenCreationRequest = new SideChainTokenCreationRequest { - IndexingPrice = indexingPrice, - LockedTokenAmount = lockedTokenAmount, - SideChainTokenCreationRequest = new SideChainTokenCreationRequest - { - SideChainTokenDecimals = 2, - SideChainTokenTotalSupply = 1_000_000_000, - SideChainTokenSymbol = "TE", - SideChainTokenName = "TEST" - }, - SideChainTokenInitialIssueList = {sideChainTokenInitialIssueList}, - InitialResourceAmount = {resourceAmount}, - IsPrivilegePreserved = isPrivilegePreserved - }; - return res; - } + SideChainTokenDecimals = 2, + SideChainTokenTotalSupply = 1_000_000_000, + SideChainTokenSymbol = "TE", + SideChainTokenName = "TEST" + }, + SideChainTokenInitialIssueList = { sideChainTokenInitialIssueList }, + InitialResourceAmount = { resourceAmount }, + IsPrivilegePreserved = isPrivilegePreserved + }; + return res; + } - internal Dictionary GetValidResourceAmount() - { - return ResourceTokenSymbolList.ToDictionary(resource => resource, resource => 1); - } + internal Dictionary GetValidResourceAmount() + { + return ResourceTokenSymbolList.ToDictionary(resource => resource, resource => 1); + } - protected async Task ApproveWithMinersAsync(Hash proposalId) + protected async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - CheckResult(approveResult.TransactionResult); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + CheckResult(approveResult.TransactionResult); } + } - protected async Task GetBalance(Address address, string symbol = "ELF") + protected async Task GetBalance(Address address, string symbol = "ELF") + { + return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - return (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = address, - Symbol = "ELF" - })).Balance; - } + Owner = address, + Symbol = "ELF" + })).Balance; + } - internal void AssertChainIndexingProposalStatus(PendingChainIndexingProposalStatus pendingChainIndexingProposalStatus, - Address expectedProposer, Hash expectedProposalId, CrossChainBlockData expectedCrossChainData, bool toBeReleased) - { - pendingChainIndexingProposalStatus.ProposalId.ShouldBe(expectedProposalId); - pendingChainIndexingProposalStatus.Proposer.ShouldBe(expectedProposer); - pendingChainIndexingProposalStatus.ProposedCrossChainBlockData.ShouldBe(expectedCrossChainData); - pendingChainIndexingProposalStatus.ToBeReleased.ShouldBe(toBeReleased); - } - - internal async Task DoIndexAsync(CrossChainBlockData crossChainBlockData, int[] chainIdList) - { - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalIdList = txRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) - .Select(e => ProposalCreated.Parser.ParseFrom(e.NonIndexed).ProposalId); - foreach (var proposalId in proposalIdList) - { - await ApproveWithMinersAsync(proposalId); - } + internal void AssertChainIndexingProposalStatus( + PendingChainIndexingProposalStatus pendingChainIndexingProposalStatus, + Address expectedProposer, Hash expectedProposalId, CrossChainBlockData expectedCrossChainData, + bool toBeReleased) + { + pendingChainIndexingProposalStatus.ProposalId.ShouldBe(expectedProposalId); + pendingChainIndexingProposalStatus.Proposer.ShouldBe(expectedProposer); + pendingChainIndexingProposalStatus.ProposedCrossChainBlockData.ShouldBe(expectedCrossChainData); + pendingChainIndexingProposalStatus.ToBeReleased.ShouldBe(toBeReleased); + } - var txResult =await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {chainIdList} - }); - return txResult.TransactionResult.BlockNumber; - } + internal async Task DoIndexAsync(CrossChainBlockData crossChainBlockData, int[] chainIdList) + { + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalIdList = txRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) + .Select(e => ProposalCreated.Parser.ParseFrom(e.NonIndexed).ProposalId); + foreach (var proposalId in proposalIdList) await ApproveWithMinersAsync(proposalId); - internal async Task DisposeSideChainProposalAsync(Int32Value chainId) - { - var disposalInput = chainId; - var organizationAddress = - (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; - var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + var txResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - ContractMethodName = nameof(CrossChainContractStub.DisposeSideChain), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = disposalInput.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = organizationAddress - })).Output; - return proposal; - } + ChainIdList = { chainIdList } + }); + return txResult.TransactionResult.BlockNumber; + } - internal async Task GetSideChainBalanceAsync(int chainId) - { - return (await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value {Value = chainId})).Value; - } - - internal async Task GetSideChainStatusAsync(int chainId) - { - return (await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value {Value = chainId})).Status; - } - - private void CheckResult(TransactionResult result) + internal async Task DisposeSideChainProposalAsync(Int32Value chainId) + { + var disposalInput = chainId; + var organizationAddress = + (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; + var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - if (!string.IsNullOrEmpty(result.Error)) - { - throw new Exception(result.Error); - } - } + ContractMethodName = nameof(CrossChainContractStub.DisposeSideChain), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = disposalInput.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = organizationAddress + })).Output; + return proposal; + } + + internal async Task GetSideChainBalanceAsync(int chainId) + { + return (await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value { Value = chainId })).Value; + } + + internal async Task GetSideChainStatusAsync(int chainId) + { + return (await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { Value = chainId })).Status; + } + + private void CheckResult(TransactionResult result) + { + if (!string.IsNullOrEmpty(result.Error)) throw new Exception(result.Error); + } - internal ParentChainBlockData CreateParentChainBlockData(long height, int sideChainId, Hash txMerkleTreeRoot) + internal ParentChainBlockData CreateParentChainBlockData(long height, int sideChainId, Hash txMerkleTreeRoot) + { + return new ParentChainBlockData { - return new ParentChainBlockData - { - ChainId = sideChainId, - Height = height, - TransactionStatusMerkleTreeRoot = txMerkleTreeRoot - }; - } + ChainId = sideChainId, + Height = height, + TransactionStatusMerkleTreeRoot = txMerkleTreeRoot + }; + } + + #region Contract Address + + #endregion + + #region Paliament + + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetTester(ParliamentContractAddress, + DefaultKeyPair); + + internal AssociationContractImplContainer.AssociationContractImplStub AssociationContractStub => + GetTester(AssociationContractAddress, + DefaultKeyPair); + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); } + + internal AssociationContractImplContainer.AssociationContractImplStub GetAssociationContractStub(ECKeyPair keyPair) + { + return GetTester(AssociationContractAddress, + keyPair); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/CrossChainIndexingActionTest.cs b/test/AElf.Contracts.CrossChain.Tests/CrossChainIndexingActionTest.cs index f65917b379..977c7bf7b4 100644 --- a/test/AElf.Contracts.CrossChain.Tests/CrossChainIndexingActionTest.cs +++ b/test/AElf.Contracts.CrossChain.Tests/CrossChainIndexingActionTest.cs @@ -1,1706 +1,1711 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.MultiToken; using AElf.CSharp.Core.Extension; using AElf.CSharp.Core.Utils; using AElf.Kernel; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +public class CrossChainIndexingActionTest : CrossChainContractTestBase { - public class CrossChainIndexingActionTest : CrossChainContractTestBase + [Fact] + public async Task LockedToken_Verification() { - #region Propose + var parentChainId = 123; + var lockedToken = 100_000L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - [Fact] - public async Task ProposeCrossChainData_Twice() - { - int parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData} - }; + var lockedToken1 = + await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value { Value = sideChainId }); + lockedToken1.Value.ShouldBe(lockedToken); - { - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - Assert.Equal(TransactionResultStatus.Mined, txRes.TransactionResult.Status); - } + var address = + await CrossChainContractStub.GetSideChainCreator.CallAsync(new Int32Value { Value = sideChainId }); + address.ShouldBe(Address.FromPublicKey(DefaultKeyPair.PublicKey)); + } - { - var txRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - Assert.Equal(TransactionResultStatus.Failed, txRes.TransactionResult.Status); - } - } + #region HelpMethods - [Fact] - public async Task ProposeCrossChainData_NotAuthorized() + private SideChainBlockData CreateSideChainBlockData(Hash blockHash, long height, int sideChainId, + Hash txMerkleTreeRoot) + { + return new SideChainBlockData { - int parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData} - }; + BlockHeaderHash = blockHash, + Height = height, + ChainId = sideChainId, + TransactionStatusMerkleTreeRoot = txMerkleTreeRoot + }; + } - { - var txRes = await GetCrossChainContractStub(Accounts.Last().KeyPair).ProposeCrossChainIndexing - .SendWithExceptionAsync(crossChainBlockData); - Assert.Equal(TransactionResultStatus.Failed, txRes.TransactionResult.Status); - } - } + #endregion - // #region Parent chain + #region Propose - [Fact] - public async Task ProposeCrossChainData_ParentChainBlockData() + [Fact] + public async Task ProposeCrossChainData_Twice() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var crossChainBlockData = new CrossChainBlockData { - int parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - - Hash fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; + SideChainBlockDataList = { sideChainBlockData } + }; + { var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - var proposedCrossChainBlockData = CrossChainIndexingDataProposedEvent.Parser - .ParseFrom(txRes.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(CrossChainIndexingDataProposedEvent))).NonIndexed) - .ProposedCrossChainData; - Assert.NotNull(proposedCrossChainBlockData); - Assert.Equal(crossChainBlockData, proposedCrossChainBlockData); - - { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[parentChainId]; - Assert.Equal(proposalId, pendingProposal.ProposalId); - Assert.Equal(DefaultSender, pendingProposal.Proposer); - Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); - Assert.False(pendingProposal.ToBeReleased); - } + Assert.Equal(TransactionResultStatus.Mined, txRes.TransactionResult.Status); } - [Fact] - public async Task ProposeCrossChainData_WrongParentChainId() { - int parentChainId = 123; - await InitAndCreateSideChainAsync(parentChainId); - int fakeParentChainId = 124; - var parentChainBlockData = CreateParentChainBlockData(1, fakeParentChainId, null); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); + Assert.Equal(TransactionResultStatus.Failed, txRes.TransactionResult.Status); } + } - [Fact] - public async Task ProposeParentChainData_WrongHeight() + [Fact] + public async Task ProposeCrossChainData_NotAuthorized() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var crossChainBlockData = new CrossChainBlockData { - int parentChainId = 123; - await InitAndCreateSideChainAsync(parentChainId); - var parentChainBlockData = CreateParentChainBlockData(0, parentChainId, null); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; - - var txRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Failed); - } + SideChainBlockDataList = { sideChainBlockData } + }; - [Fact] - public async Task ProposeParentChainData_ContinuousData() { - int parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + var txRes = await GetCrossChainContractStub(Accounts.Last().KeyPair).ProposeCrossChainIndexing + .SendWithExceptionAsync(crossChainBlockData); + Assert.Equal(TransactionResultStatus.Failed, txRes.TransactionResult.Status); + } + } - Hash fakeTransactionStatusMerkleRoot1 = HashHelper.ComputeFrom("TransactionStatusMerkleRoot1"); - var parentChainBlockData1 = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot1); + // #region Parent chain - Hash fakeTransactionStatusMerkleRoot2 = HashHelper.ComputeFrom("TransactionStatusMerkleRoot2"); - var parentChainBlockData2 = CreateParentChainBlockData(parentChainHeightOfCreation + 1, parentChainId, - fakeTransactionStatusMerkleRoot2); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData1, parentChainBlockData2} - }; + [Fact] + public async Task ProposeCrossChainData_ParentChainBlockData() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + + var fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; + + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + var proposedCrossChainBlockData = CrossChainIndexingDataProposedEvent.Parser + .ParseFrom(txRes.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(CrossChainIndexingDataProposedEvent))).NonIndexed) + .ProposedCrossChainData; + Assert.NotNull(proposedCrossChainBlockData); + Assert.Equal(crossChainBlockData, proposedCrossChainBlockData); - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - Assert.Equal(TransactionResultStatus.Mined, txRes.TransactionResult.Status); + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[parentChainId]; + Assert.Equal(proposalId, pendingProposal.ProposalId); + Assert.Equal(DefaultSender, pendingProposal.Proposer); + Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); + Assert.False(pendingProposal.ToBeReleased); } + } - [Fact] - public async Task RecordParentChainData_DiscontinuousData() + [Fact] + public async Task ProposeCrossChainData_WrongParentChainId() + { + var parentChainId = 123; + await InitAndCreateSideChainAsync(parentChainId); + var fakeParentChainId = 124; + var parentChainBlockData = CreateParentChainBlockData(1, fakeParentChainId, null); + var crossChainBlockData = new CrossChainBlockData { - int parentChainId = 123; - await InitAndCreateSideChainAsync(parentChainId); - var parentChainBlockData1 = CreateParentChainBlockData(1, parentChainId, null); + ParentChainBlockDataList = { parentChainBlockData } + }; - var parentChainBlockData2 = CreateParentChainBlockData(3, parentChainId, null); + var txRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); + } - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData1, parentChainBlockData2} - }; + [Fact] + public async Task ProposeParentChainData_WrongHeight() + { + var parentChainId = 123; + await InitAndCreateSideChainAsync(parentChainId); + var parentChainBlockData = CreateParentChainBlockData(0, parentChainId, null); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; - var txRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Failed); - } + var txRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Failed); + } - [Fact] - public async Task GetParentChainHeight_WithoutIndexing() + [Fact] + public async Task ProposeParentChainData_ContinuousData() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + + var fakeTransactionStatusMerkleRoot1 = HashHelper.ComputeFrom("TransactionStatusMerkleRoot1"); + var parentChainBlockData1 = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot1); + + var fakeTransactionStatusMerkleRoot2 = HashHelper.ComputeFrom("TransactionStatusMerkleRoot2"); + var parentChainBlockData2 = CreateParentChainBlockData(parentChainHeightOfCreation + 1, parentChainId, + fakeTransactionStatusMerkleRoot2); + var crossChainBlockData = new CrossChainBlockData { - int parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + ParentChainBlockDataList = { parentChainBlockData1, parentChainBlockData2 } + }; - var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - Assert.Equal(parentChainHeightOfCreation - 1, height.Value); - } + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + Assert.Equal(TransactionResultStatus.Mined, txRes.TransactionResult.Status); + } + + [Fact] + public async Task RecordParentChainData_DiscontinuousData() + { + var parentChainId = 123; + await InitAndCreateSideChainAsync(parentChainId); + var parentChainBlockData1 = CreateParentChainBlockData(1, parentChainId, null); + + var parentChainBlockData2 = CreateParentChainBlockData(3, parentChainId, null); - [Fact] - public async Task GetParentChainHeight() + var crossChainBlockData = new CrossChainBlockData { - int parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + ParentChainBlockDataList = { parentChainBlockData1, parentChainBlockData2 } + }; - { - var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - Assert.Equal(parentChainHeightOfCreation - 1, height.Value); - } - Hash fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; + var txRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + Assert.True(txRes.TransactionResult.Status == TransactionResultStatus.Failed); + } - var tx = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - Assert.True(tx.TransactionResult.Status == TransactionResultStatus.Mined); + [Fact] + public async Task GetParentChainHeight_WithoutIndexing() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - { - var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - Assert.Equal(parentChainHeightOfCreation - 1, height.Value); - } + var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + Assert.Equal(parentChainHeightOfCreation - 1, height.Value); + } + + [Fact] + public async Task GetParentChainHeight() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + + { + var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + Assert.Equal(parentChainHeightOfCreation - 1, height.Value); } + var fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; + + var tx = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + Assert.True(tx.TransactionResult.Status == TransactionResultStatus.Mined); - [Fact] - public async Task ProposeForSideChain() { - var parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + var height = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + Assert.Equal(parentChainHeightOfCreation - 1, height.Value); + } + } - var rechargeInput = new RechargeInput() - { - ChainId = sideChainId, - Amount = 100_000L - }; + [Fact] + public async Task ProposeForSideChain() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); - { - //without enough token - var txResult = (await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput)) - .TransactionResult; - Assert.Equal(TransactionResultStatus.Failed, txResult.Status); - Assert.Contains("Insufficient allowance", txResult.Error); - } + var rechargeInput = new RechargeInput + { + ChainId = sideChainId, + Amount = 100_000L + }; - { - //with enough token - await ApproveBalanceAsync(100_000L); - var txResult = (await CrossChainContractStub.Recharge.SendAsync(rechargeInput)).TransactionResult; - Assert.Equal(TransactionResultStatus.Mined, txResult.Status); - } + { + //without enough token + var txResult = (await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput)) + .TransactionResult; + Assert.Equal(TransactionResultStatus.Failed, txResult.Status); + Assert.Contains("Insufficient allowance", txResult.Error); } - - [Fact] - public async Task RechargeForSideChain_Terminated() { - var parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + //with enough token await ApproveBalanceAsync(100_000L); + var txResult = (await CrossChainContractStub.Recharge.SendAsync(rechargeInput)).TransactionResult; + Assert.Equal(TransactionResultStatus.Mined, txResult.Status); + } + } - var proposalId = await DisposeSideChainProposalAsync(new Int32Value {Value = sideChainId}); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); - - var rechargeInput = new RechargeInput() - { - ChainId = sideChainId, - Amount = 100_000L - }; - var chainStatus = - await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value {Value = sideChainId}); - Assert.True(chainStatus.Status == SideChainStatus.Terminated); + [Fact] + public async Task RechargeForSideChain_Terminated() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + await ApproveBalanceAsync(100_000L); - var txResult = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.TransactionResult.Error.Contains("Side chain not found or incorrect side chain status.") - .ShouldBeTrue(); - } + var proposalId = await DisposeSideChainProposalAsync(new Int32Value { Value = sideChainId }); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); - [Fact] - public async Task RechargeForSideChain_ChainNoExist() + var rechargeInput = new RechargeInput { - var parentChainId = 123; - long lockedTokenAmount = 10; - await InitializeCrossChainContractAsync(parentChainId); + ChainId = sideChainId, + Amount = 100_000L + }; + + var chainStatus = + await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { Value = sideChainId }); + Assert.True(chainStatus.Status == SideChainStatus.Terminated); + + var txResult = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.TransactionResult.Error.Contains("Side chain not found or incorrect side chain status.") + .ShouldBeTrue(); + } - await ApproveBalanceAsync(lockedTokenAmount); - var otherChainId = ChainHelper.GetChainId(5); - var rechargeInput = new RechargeInput() - { - ChainId = otherChainId, - Amount = 100_000L - }; - await ApproveBalanceAsync(100_000L); - var txResult = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.TransactionResult.Error.Contains("Side chain not found or incorrect side chain status.") - .ShouldBeTrue(); - } + [Fact] + public async Task RechargeForSideChain_ChainNoExist() + { + var parentChainId = 123; + long lockedTokenAmount = 10; + await InitializeCrossChainContractAsync(parentChainId); - [Fact] - public async Task RechargeForSideChain_IndexingFeeDebt() + await ApproveBalanceAsync(lockedTokenAmount); + var otherChainId = ChainHelper.GetChainId(5); + var rechargeInput = new RechargeInput { - int parentChainId = 123; - long lockedToken = 2; - long indexingPrice = 1; - long parentChainHeightOfCreation = 10; - - // transfer token - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Amount = 1000, - Symbol = "ELF", - To = AnotherSender - }); - - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken, - indexingPrice, AnotherKeyPair); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - - { - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} - }; + ChainId = otherChainId, + Amount = 100_000L + }; + await ApproveBalanceAsync(100_000L); + var txResult = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.TransactionResult.Error.Contains("Side chain not found or incorrect side chain status.") + .ShouldBeTrue(); + } - await DoIndexAsync(crossChainBlockData, new []{sideChainId}); - var chainStatus = await GetSideChainStatusAsync(sideChainId); - chainStatus.ShouldBe(SideChainStatus.Active); - } + [Fact] + public async Task RechargeForSideChain_IndexingFeeDebt() + { + var parentChainId = 123; + long lockedToken = 2; + long indexingPrice = 1; + long parentChainHeightOfCreation = 10; - { - await ApproveBalanceAsync(1); - var rechargeInput = new RechargeInput - { - ChainId = sideChainId, - Amount = 1 - }; - await CrossChainContractStub.Recharge.SendAsync(rechargeInput); - var chainStatus = await GetSideChainStatusAsync(sideChainId); - chainStatus.ShouldBe(SideChainStatus.Active); - var balance = await GetSideChainBalanceAsync(sideChainId); - balance.ShouldBe(1); - } + // transfer token + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Amount = 1000, + Symbol = "ELF", + To = AnotherSender + }); - { - var sideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData4 = - CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData3, sideChainBlockData4} - }; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken, + indexingPrice, AnotherKeyPair); - await DoIndexAsync(crossChainBlockData, new []{sideChainId}); - var chainStatus = await GetSideChainStatusAsync(sideChainId); - chainStatus.ShouldBe(SideChainStatus.IndexingFeeDebt); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - (await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallWithExceptionAsync(new Int32Value - {Value = 0})).Value.ShouldContain("Side chain not found."); - - var debt = await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallAsync(new Int32Value - {Value = sideChainId}); - debt.Value.ShouldBe(1); - } - - { - await ApproveBalanceAsync(2); - var rechargeInput = new RechargeInput - { - ChainId = sideChainId, - Amount = 2 - }; - var balanceBeforeRecharge = await GetSideChainBalanceAsync(sideChainId); - balanceBeforeRecharge.ShouldBe(0); - - var rechargeTx = await CrossChainContractStub.Recharge.SendAsync(rechargeInput); - - var transferredNonIndexedEvents = rechargeTx.TransactionResult.Logs - .Where(l => l.Name.Contains(nameof(Transferred))).Select(e => e.NonIndexed); - var transferredNonIndexed = Transferred.Parser.ParseFrom(transferredNonIndexedEvents.Last()); - transferredNonIndexed.Amount.ShouldBe(1); - - var transferredIndexedEvents = rechargeTx.TransactionResult.Logs - .Where(l => l.Name.Contains(nameof(Transferred))).Select(e => e.Indexed[1]); - var transferredIndexed = Transferred.Parser.ParseFrom(transferredIndexedEvents.Last()); - transferredIndexed.To.ShouldBe(DefaultSender); - - var balanceAfterRecharge = await GetSideChainBalanceAsync(sideChainId); - balanceAfterRecharge.ShouldBe(1); - var chainStatus = await GetSideChainStatusAsync(sideChainId); - chainStatus.ShouldBe(SideChainStatus.Active); - - var debt = await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallAsync(new Int32Value - {Value = sideChainId}); - debt.Value.ShouldBe(0); - } - } - - [Fact] - public async Task ProposeSideChainData() - { - var parentChainId = 123; - var lockedToken = 2; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + { var sideChainBlockData1 = CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); var sideChainBlockData2 = CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - var crossChainIndexingDataProposedEvent = CrossChainIndexingDataProposedEvent.Parser - .ParseFrom(txRes.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(CrossChainIndexingDataProposedEvent))).NonIndexed); - Assert.Equal(crossChainBlockData, crossChainIndexingDataProposedEvent.ProposedCrossChainData); - var pendingProposal = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - var chainIndexingProposalStatus = pendingProposal.ChainIndexingProposalStatus[sideChainId]; - crossChainIndexingDataProposedEvent.ProposalId.ShouldBe(proposalId); - chainIndexingProposalStatus.Proposer.ShouldBe(DefaultSender); - chainIndexingProposalStatus.ProposedCrossChainBlockData.ShouldBe(crossChainBlockData); - chainIndexingProposalStatus.ToBeReleased.ShouldBeFalse(); - } - - [Fact] - public async Task ProposeSideChainData_MultiTimesInOneBlock() - { - var parentChainId = 123; - var lockedToken = 2; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - - var firstCrossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1} - }; - - var secondCrossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData2} - }; - - var tx1 = CrossChainContractStub.ProposeCrossChainIndexing.GetTransaction(firstCrossChainBlockData); - var tx2 = CrossChainContractStub.ProposeCrossChainIndexing.GetTransaction(secondCrossChainBlockData); - var blockExecutedSet = await MineAsync(new List {tx1, tx2}); - blockExecutedSet.TransactionResultMap[tx2.GetHash()].Status.ShouldBe(TransactionResultStatus.Failed); - blockExecutedSet.TransactionResultMap[tx2.GetHash()].Error.ShouldContain("Cannot execute this tx."); - } - - [Fact] - public async Task ProposeSideChainData_EmptyInput() - { - var parentChainId = 123; - var lockedToken = 2; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - - var crossChainBlockData = new CrossChainBlockData(); - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - txRes.TransactionResult.Error.ShouldContain("Empty cross chain data proposed."); + await DoIndexAsync(crossChainBlockData, new[] { sideChainId }); + var chainStatus = await GetSideChainStatusAsync(sideChainId); + chainStatus.ShouldBe(SideChainStatus.Active); } - [Fact] - public async Task ProposeSideChainData_WithChainNotExist() - { - int parentChainId = 123; - long lockedToken = 10; - long parentChainHeightOfCreation = 10; - var sideChainId1 = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - - // create second side chain - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId1, fakeTxMerkleTreeRoot); - int fakeChainId = 124; - - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, fakeChainId, fakeTxMerkleTreeRoot); - var crossChainBlockData = new CrossChainBlockData + { + await ApproveBalanceAsync(1); + var rechargeInput = new RechargeInput { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} + ChainId = sideChainId, + Amount = 1 }; - - var txRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); + await CrossChainContractStub.Recharge.SendAsync(rechargeInput); + var chainStatus = await GetSideChainStatusAsync(sideChainId); + chainStatus.ShouldBe(SideChainStatus.Active); + var balance = await GetSideChainBalanceAsync(sideChainId); + balance.ShouldBe(1); } - [Fact] - public async Task ProposeSideChainData_WithChainIndexingFeeDebt() { - int parentChainId = 123; - long lockedToken = 2; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); var sideChainBlockData3 = CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); - + var sideChainBlockData4 = + CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); var crossChainBlockData = new CrossChainBlockData { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2, sideChainBlockData3} + SideChainBlockDataList = { sideChainBlockData3, sideChainBlockData4 } }; - var txResult = - await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + await DoIndexAsync(crossChainBlockData, new[] { sideChainId }); + var chainStatus = await GetSideChainStatusAsync(sideChainId); + chainStatus.ShouldBe(SideChainStatus.IndexingFeeDebt); + + (await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallWithExceptionAsync(new Int32Value + { Value = 0 })).Value.ShouldContain("Side chain not found."); - var proposalId = ProposalCreated.Parser - .ParseFrom(txResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - await ApproveWithMinersAsync(proposalId); - - // release - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync(new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - var debt = await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallAsync(new Int32Value - {Value = sideChainId}); + { Value = sideChainId }); debt.Value.ShouldBe(1); } - - [Fact] - public async Task ProposeSideChainData_Inconsistent() - { - int parentChainId = 123; - long lockedToken = 5; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData + + { + await ApproveBalanceAsync(2); + var rechargeInput = new RechargeInput { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2, sideChainBlockData3} + ChainId = sideChainId, + Amount = 2 }; + var balanceBeforeRecharge = await GetSideChainBalanceAsync(sideChainId); + balanceBeforeRecharge.ShouldBe(0); - var txResult = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - txResult.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); - } + var rechargeTx = await CrossChainContractStub.Recharge.SendAsync(rechargeInput); - [Fact] - public async Task GetChainInitializationContext_Success() - { - var parentChainId = 123; - var lockedToken = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var transferredNonIndexedEvents = rechargeTx.TransactionResult.Logs + .Where(l => l.Name.Contains(nameof(Transferred))).Select(e => e.NonIndexed); + var transferredNonIndexed = Transferred.Parser.ParseFrom(transferredNonIndexedEvents.Last()); + transferredNonIndexed.Amount.ShouldBe(1); - //not exist chain id - var error = - await CrossChainContractStub.GetChainInitializationData.CallWithExceptionAsync(new Int32Value - {Value = parentChainId}); - error.Value.ShouldContain("Side chain not found."); + var transferredIndexedEvents = rechargeTx.TransactionResult.Logs + .Where(l => l.Name.Contains(nameof(Transferred))).Select(e => e.Indexed[1]); + var transferredIndexed = Transferred.Parser.ParseFrom(transferredIndexedEvents.Last()); + transferredIndexed.To.ShouldBe(DefaultSender); + + var balanceAfterRecharge = await GetSideChainBalanceAsync(sideChainId); + balanceAfterRecharge.ShouldBe(1); + var chainStatus = await GetSideChainStatusAsync(sideChainId); + chainStatus.ShouldBe(SideChainStatus.Active); - //valid chain id - var chainInitializationContext = - await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value - {Value = sideChainId}); - chainInitializationContext.ChainId.ShouldBe(sideChainId); - chainInitializationContext.Creator.ShouldBe(Address.FromPublicKey(DefaultKeyPair.PublicKey)); + var debt = await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallAsync(new Int32Value + { Value = sideChainId }); + debt.Value.ShouldBe(0); } + } - #endregion + [Fact] + public async Task ProposeSideChainData() + { + var parentChainId = 123; + var lockedToken = 2; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + var crossChainIndexingDataProposedEvent = CrossChainIndexingDataProposedEvent.Parser + .ParseFrom(txRes.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(CrossChainIndexingDataProposedEvent))).NonIndexed); + Assert.Equal(crossChainBlockData, crossChainIndexingDataProposedEvent.ProposedCrossChainData); + + var pendingProposal = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + var chainIndexingProposalStatus = pendingProposal.ChainIndexingProposalStatus[sideChainId]; + crossChainIndexingDataProposedEvent.ProposalId.ShouldBe(proposalId); + chainIndexingProposalStatus.Proposer.ShouldBe(DefaultSender); + chainIndexingProposalStatus.ProposedCrossChainBlockData.ShouldBe(crossChainBlockData); + chainIndexingProposalStatus.ToBeReleased.ShouldBeFalse(); + } - #region Release + [Fact] + public async Task ProposeSideChainData_MultiTimesInOneBlock() + { + var parentChainId = 123; + var lockedToken = 2; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + var firstCrossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1 } + }; - [Fact] - public async Task Release_IndexingSideChain_Success() + var secondCrossChainBlockData = new CrossChainBlockData { - var lockedToken = 5; - var sideChainId = - await InitAndCreateSideChainAsync(0, 0, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} - }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - - { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[sideChainId]; - Assert.Equal(proposalId, pendingProposal.ProposalId); - Assert.Equal(DefaultSender, pendingProposal.Proposer); - Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); - Assert.False(pendingProposal.ToBeReleased); - } - - await ApproveWithMinersAsync(proposalId); + SideChainBlockDataList = { sideChainBlockData2 } + }; + + var tx1 = CrossChainContractStub.ProposeCrossChainIndexing.GetTransaction(firstCrossChainBlockData); + var tx2 = CrossChainContractStub.ProposeCrossChainIndexing.GetTransaction(secondCrossChainBlockData); + var blockExecutedSet = await MineAsync(new List { tx1, tx2 }); + blockExecutedSet.TransactionResultMap[tx2.GetHash()].Status.ShouldBe(TransactionResultStatus.Failed); + blockExecutedSet.TransactionResultMap[tx2.GetHash()].Error.ShouldContain("Cannot execute this tx."); + } - { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[sideChainId]; - Assert.Equal(proposalId, pendingProposal.ProposalId); - Assert.Equal(DefaultSender, pendingProposal.Proposer); - Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); - Assert.True(pendingProposal.ToBeReleased); - } + [Fact] + public async Task ProposeSideChainData_EmptyInput() + { + var parentChainId = 123; + var lockedToken = 2; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + + var crossChainBlockData = new CrossChainBlockData(); + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + txRes.TransactionResult.Error.ShouldContain("Empty cross chain data proposed."); + } - { - var error = await CrossChainContractStub.GetSideChainHeight.CallWithExceptionAsync(new Int32Value - { - Value = 0 - }); - error.Value.ShouldContain("Side chain not found."); - } + [Fact] + public async Task ProposeSideChainData_WithChainNotExist() + { + var parentChainId = 123; + long lockedToken = 10; + long parentChainHeightOfCreation = 10; + var sideChainId1 = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - { - var height = await CrossChainContractStub.GetParentChainHeight.CallWithExceptionAsync(new Empty()); + // create second side chain + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); - var error = await CrossChainContractStub.GetParentChainId.CallWithExceptionAsync(new Empty()); - } - - { - var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value - { - Value = sideChainId - }); - indexedHeight.Value.ShouldBe(0); - - var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value - { - Value = sideChainId - }); - balance.Value.ShouldBe(lockedToken); - } + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId1, fakeTxMerkleTreeRoot); + var fakeChainId = 124; - { - var tx = - await GetCrossChainContractStub(AnotherKeyPair).ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - tx.TransactionResult.Error.ShouldContain("No permission."); - } + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, fakeChainId, fakeTxMerkleTreeRoot); + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); + var txRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); + } + + [Fact] + public async Task ProposeSideChainData_WithChainIndexingFeeDebt() + { + var parentChainId = 123; + long lockedToken = 2; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2, sideChainBlockData3 } + }; + + var txResult = + await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + + var proposalId = ProposalCreated.Parser + .ParseFrom(txResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + await ApproveWithMinersAsync(proposalId); + + // release + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value - { - Value = sideChainId - }); - indexedHeight.Value.ShouldBe(2); - - var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value - { - Value = sideChainId - }); - balance.Value.ShouldBe(lockedToken - 2); - } - + ChainIdList = { sideChainId } + }); + + var debt = await CrossChainContractStub.GetSideChainIndexingFeeDebt.CallAsync(new Int32Value + { Value = sideChainId }); + debt.Value.ShouldBe(1); + } + + [Fact] + public async Task ProposeSideChainData_Inconsistent() + { + var parentChainId = 123; + long lockedToken = 5; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2, sideChainBlockData3 } + }; + + var txResult = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + txResult.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); + } + + [Fact] + public async Task GetChainInitializationContext_Success() + { + var parentChainId = 123; + var lockedToken = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + + //not exist chain id + var error = + await CrossChainContractStub.GetChainInitializationData.CallWithExceptionAsync(new Int32Value + { Value = parentChainId }); + error.Value.ShouldContain("Side chain not found."); + + //valid chain id + var chainInitializationContext = + await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value + { Value = sideChainId }); + chainInitializationContext.ChainId.ShouldBe(sideChainId); + chainInitializationContext.Creator.ShouldBe(Address.FromPublicKey(DefaultKeyPair.PublicKey)); + } + + #endregion + + #region Release + + [Fact] + public async Task Release_IndexingSideChain_Success() + { + var lockedToken = 5; + var sideChainId = + await InitAndCreateSideChainAsync(0, 0, lockedToken); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[sideChainId]; + Assert.Equal(proposalId, pendingProposal.ProposalId); + Assert.Equal(DefaultSender, pendingProposal.Proposer); + Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); + Assert.False(pendingProposal.ToBeReleased); + } + + await ApproveWithMinersAsync(proposalId); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[sideChainId]; + Assert.Equal(proposalId, pendingProposal.ProposalId); + Assert.Equal(DefaultSender, pendingProposal.Proposer); + Assert.Equal(crossChainBlockData, pendingProposal.ProposedCrossChainBlockData); + Assert.True(pendingProposal.ToBeReleased); + } + + { + var error = await CrossChainContractStub.GetSideChainHeight.CallWithExceptionAsync(new Int32Value { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - pendingProposalStatus.ChainIndexingProposalStatus.ShouldBeEmpty(); - } + Value = 0 + }); + error.Value.ShouldContain("Side chain not found."); } - - [Fact] - public async Task Release_IndexingMultiSideChains_Success() - { - var parentChainId = 123; - var lockedToken = 5; - long parentChainHeightOfCreation = 10; - var firstChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var secondChainId = - await CreateSideChainByDefaultSenderAsync(false, parentChainHeightOfCreation, parentChainId, lockedToken); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var firstSideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, firstChainId, fakeTxMerkleTreeRoot); - var firstSideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, firstChainId, fakeTxMerkleTreeRoot); - - var secondSideChainBlockData = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, secondChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData + + { + var height = await CrossChainContractStub.GetParentChainHeight.CallWithExceptionAsync(new Empty()); + + var error = await CrossChainContractStub.GetParentChainId.CallWithExceptionAsync(new Empty()); + } + + { + var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { - SideChainBlockDataList = {firstSideChainBlockData1, firstSideChainBlockData2, secondSideChainBlockData} - }; - - var firstProposingTxRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalCreationEvents = - firstProposingTxRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) - .Select(log => ProposalCreated.Parser.ParseFrom(log.NonIndexed)).ToList(); - - proposalCreationEvents.Count.ShouldBe(2); - + Value = sideChainId + }); + indexedHeight.Value.ShouldBe(0); + + var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - - var pendingProposalForSideChainOne = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; - AssertChainIndexingProposalStatus(pendingProposalForSideChainOne, DefaultSender, - proposalCreationEvents[0].ProposalId, new CrossChainBlockData - { - SideChainBlockDataList = {firstSideChainBlockData1, firstSideChainBlockData2} - }, false); - - var pendingProposalForSideChainTwo = pendingProposalStatus.ChainIndexingProposalStatus[secondChainId]; - AssertChainIndexingProposalStatus(pendingProposalForSideChainTwo, DefaultSender, - proposalCreationEvents[1].ProposalId, new CrossChainBlockData - { - SideChainBlockDataList = {secondSideChainBlockData} - }, false); - } - - await ApproveWithMinersAsync(proposalCreationEvents[0].ProposalId); + Value = sideChainId + }); + balance.Value.ShouldBe(lockedToken); + } + { + var tx = + await GetCrossChainContractStub(AnotherKeyPair).ReleaseCrossChainIndexingProposal + .SendWithExceptionAsync( + new ReleaseCrossChainIndexingProposalInput + { + ChainIdList = { sideChainId } + }); + tx.TransactionResult.Error.ShouldContain("No permission."); + } + + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; - AssertChainIndexingProposalStatus(pendingProposal, DefaultSender, - proposalCreationEvents[0].ProposalId, new CrossChainBlockData - { - SideChainBlockDataList = {firstSideChainBlockData1, firstSideChainBlockData2} - }, true); - } + ChainIdList = { sideChainId } + }); + { + var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { - var txResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {firstChainId, secondChainId} - }); - txResult.TransactionResult.Error.ShouldContain("Not approved cross chain indexing proposal."); - } + Value = sideChainId + }); + indexedHeight.Value.ShouldBe(2); - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput + var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value + { + Value = sideChainId + }); + balance.Value.ShouldBe(lockedToken - 2); + } + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + pendingProposalStatus.ChainIndexingProposalStatus.ShouldBeEmpty(); + } + } + + [Fact] + public async Task Release_IndexingMultiSideChains_Success() + { + var parentChainId = 123; + var lockedToken = 5; + long parentChainHeightOfCreation = 10; + var firstChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var secondChainId = + await CreateSideChainByDefaultSenderAsync(false, parentChainHeightOfCreation, parentChainId, lockedToken); + + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var firstSideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, firstChainId, fakeTxMerkleTreeRoot); + var firstSideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, firstChainId, fakeTxMerkleTreeRoot); + + var secondSideChainBlockData = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, secondChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { firstSideChainBlockData1, firstSideChainBlockData2, secondSideChainBlockData } + }; + + var firstProposingTxRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalCreationEvents = + firstProposingTxRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) + .Select(log => ProposalCreated.Parser.ParseFrom(log.NonIndexed)).ToList(); + + proposalCreationEvents.Count.ShouldBe(2); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + + var pendingProposalForSideChainOne = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; + AssertChainIndexingProposalStatus(pendingProposalForSideChainOne, DefaultSender, + proposalCreationEvents[0].ProposalId, new CrossChainBlockData { - ChainIdList = {firstChainId} - }); + SideChainBlockDataList = { firstSideChainBlockData1, firstSideChainBlockData2 } + }, false); - { - var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + var pendingProposalForSideChainTwo = pendingProposalStatus.ChainIndexingProposalStatus[secondChainId]; + AssertChainIndexingProposalStatus(pendingProposalForSideChainTwo, DefaultSender, + proposalCreationEvents[1].ProposalId, new CrossChainBlockData { - Value = firstChainId - }); - indexedHeight.Value.ShouldBe(2); - - var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value + SideChainBlockDataList = { secondSideChainBlockData } + }, false); + } + + await ApproveWithMinersAsync(proposalCreationEvents[0].ProposalId); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + var pendingProposal = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; + AssertChainIndexingProposalStatus(pendingProposal, DefaultSender, + proposalCreationEvents[0].ProposalId, new CrossChainBlockData + { + SideChainBlockDataList = { firstSideChainBlockData1, firstSideChainBlockData2 } + }, true); + } + + { + var txResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( + new ReleaseCrossChainIndexingProposalInput { - Value = firstChainId + ChainIdList = { firstChainId, secondChainId } }); - balance.Value.ShouldBe(lockedToken - 2); - } - - var firstSideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 3, firstChainId, fakeTxMerkleTreeRoot); - var firstSideChainBlockData4 = - CreateSideChainBlockData(fakeSideChainBlockHash, 4, firstChainId, fakeTxMerkleTreeRoot); - - var secondProposingTxRes = - await CrossChainContractStub.ProposeCrossChainIndexing - .SendWithExceptionAsync(new CrossChainBlockData - { - SideChainBlockDataList = {firstSideChainBlockData3, firstSideChainBlockData4, secondSideChainBlockData} - }); - secondProposingTxRes.TransactionResult.Error.ShouldContain("Chain indexing already proposed."); + txResult.TransactionResult.Error.ShouldContain("Not approved cross chain indexing proposal."); + } - var secondCrossChainBlockData = new CrossChainBlockData + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - SideChainBlockDataList = {firstSideChainBlockData3, firstSideChainBlockData4} - }; + ChainIdList = { firstChainId } + }); - var thirdProposingTxRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); - var secondProposalCreationEvents = - thirdProposingTxRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) - .Select(log => ProposalCreated.Parser.ParseFrom(log.NonIndexed)).ToList(); - - secondProposalCreationEvents.Count.ShouldBe(1); - + { + var indexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - - var pendingProposalForSideChainOne = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; - AssertChainIndexingProposalStatus(pendingProposalForSideChainOne, DefaultSender, - secondProposalCreationEvents[0].ProposalId, new CrossChainBlockData - { - SideChainBlockDataList = {firstSideChainBlockData3, firstSideChainBlockData4} - }, false); - - var pendingProposalForSideChainTwo = pendingProposalStatus.ChainIndexingProposalStatus[secondChainId]; - AssertChainIndexingProposalStatus(pendingProposalForSideChainTwo, DefaultSender, - proposalCreationEvents[1].ProposalId, new CrossChainBlockData - { - SideChainBlockDataList = {secondSideChainBlockData} - }, false); - } - - await ApproveWithMinersAsync(proposalCreationEvents[1].ProposalId); - await ApproveWithMinersAsync(secondProposalCreationEvents[0].ProposalId); - - var releaseTx1 = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( - new ReleaseCrossChainIndexingProposalInput + Value = firstChainId + }); + indexedHeight.Value.ShouldBe(2); + + var balance = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value + { + Value = firstChainId + }); + balance.Value.ShouldBe(lockedToken - 2); + } + + var firstSideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 3, firstChainId, fakeTxMerkleTreeRoot); + var firstSideChainBlockData4 = + CreateSideChainBlockData(fakeSideChainBlockHash, 4, firstChainId, fakeTxMerkleTreeRoot); + + var secondProposingTxRes = + await CrossChainContractStub.ProposeCrossChainIndexing + .SendWithExceptionAsync(new CrossChainBlockData { - ChainIdList = {firstChainId} + SideChainBlockDataList = + { firstSideChainBlockData3, firstSideChainBlockData4, secondSideChainBlockData } }); - - var releaseTx2 = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( - new ReleaseCrossChainIndexingProposalInput + secondProposingTxRes.TransactionResult.Error.ShouldContain("Chain indexing already proposed."); + + var secondCrossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { firstSideChainBlockData3, firstSideChainBlockData4 } + }; + + var thirdProposingTxRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); + var secondProposalCreationEvents = + thirdProposingTxRes.TransactionResult.Logs.Where(l => l.Name.Contains(nameof(ProposalCreated))) + .Select(log => ProposalCreated.Parser.ParseFrom(log.NonIndexed)).ToList(); + + secondProposalCreationEvents.Count.ShouldBe(1); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + + var pendingProposalForSideChainOne = pendingProposalStatus.ChainIndexingProposalStatus[firstChainId]; + AssertChainIndexingProposalStatus(pendingProposalForSideChainOne, DefaultSender, + secondProposalCreationEvents[0].ProposalId, new CrossChainBlockData { - ChainIdList = {secondChainId} - }); + SideChainBlockDataList = { firstSideChainBlockData3, firstSideChainBlockData4 } + }, false); - var blockExecutedSet = await MineAsync(new List {releaseTx1, releaseTx2}); - blockExecutedSet.TransactionResultMap[releaseTx2.GetHash()].Error.ShouldContain("Cannot execute this tx."); - - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput + var pendingProposalForSideChainTwo = pendingProposalStatus.ChainIndexingProposalStatus[secondChainId]; + AssertChainIndexingProposalStatus(pendingProposalForSideChainTwo, DefaultSender, + proposalCreationEvents[1].ProposalId, new CrossChainBlockData { - ChainIdList = {secondChainId} - }); - + SideChainBlockDataList = { secondSideChainBlockData } + }, false); + } + + await ApproveWithMinersAsync(proposalCreationEvents[1].ProposalId); + await ApproveWithMinersAsync(secondProposalCreationEvents[0].ProposalId); + + var releaseTx1 = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( + new ReleaseCrossChainIndexingProposalInput { - var pendingProposalStatus = - await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); - pendingProposalStatus.ChainIndexingProposalStatus.ShouldBeEmpty(); - } + ChainIdList = { firstChainId } + }); + var releaseTx2 = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( + new ReleaseCrossChainIndexingProposalInput { - var firstSideChainIndexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + ChainIdList = { secondChainId } + }); + + var blockExecutedSet = await MineAsync(new List { releaseTx1, releaseTx2 }); + blockExecutedSet.TransactionResultMap[releaseTx2.GetHash()].Error.ShouldContain("Cannot execute this tx."); + + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput + { + ChainIdList = { secondChainId } + }); + + { + var pendingProposalStatus = + await CrossChainContractStub.GetIndexingProposalStatus.CallAsync(new Empty()); + pendingProposalStatus.ChainIndexingProposalStatus.ShouldBeEmpty(); + } + + { + var firstSideChainIndexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + { + Value = firstChainId + }); + firstSideChainIndexedHeight.Value.ShouldBe(4); + + var secondSideChainIndexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + { + Value = secondChainId + }); + secondSideChainIndexedHeight.Value.ShouldBe(1); + } + + var tx = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( + new ReleaseCrossChainIndexingProposalInput + { + ChainIdList = { firstChainId, secondChainId } + }); + tx.TransactionResult.Error.ShouldContain("Chain indexing not proposed."); + } + + [Fact] + public async Task Release_IndexingSideChain_ContinuousTwice() + { + var parentChainId = 123; + var lockedToken = 5; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + await ApproveWithMinersAsync(proposalId); + + + var sideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData4 = + CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData5 = + CreateSideChainBlockData(fakeSideChainBlockHash, 5, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData6 = + CreateSideChainBlockData(fakeSideChainBlockHash, 6, sideChainId, fakeTxMerkleTreeRoot); + + var secondCrossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData3, sideChainBlockData4, sideChainBlockData5 } + }; + + { + var secondProposingTxRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( + secondCrossChainBlockData); + secondProposingTxRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); + } + + { + // empty input + var releaseResult = + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( + new ReleaseCrossChainIndexingProposalInput()); + releaseResult.TransactionResult.Error.ShouldContain("Empty input not allowed."); + } + + { + var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - Value = firstChainId + ChainIdList = { sideChainId } }); - firstSideChainIndexedHeight.Value.ShouldBe(4); - - var secondSideChainIndexedHeight = await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + { + var secondProposingTxRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(new CrossChainBlockData { - Value = secondChainId + SideChainBlockDataList = { sideChainBlockData6 } }); - secondSideChainIndexedHeight.Value.ShouldBe(1); - } - - var tx = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( + secondProposingTxRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); + } + + { + var secondProposingTxRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); + var secondProposalId = ProposalCreated.Parser.ParseFrom(secondProposingTxRes.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + Assert.NotNull(secondProposalId); + await ApproveWithMinersAsync(secondProposalId); + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( new ReleaseCrossChainIndexingProposalInput { - ChainIdList = {firstChainId, secondChainId} + ChainIdList = { sideChainId } }); - tx.TransactionResult.Error.ShouldContain("Chain indexing not proposed."); + var indexedHeight = + await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { Value = sideChainId }); + indexedHeight.Value.ShouldBe(5); + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value + { + Value = sideChainId + }); + chainStatus.Status.ShouldBe(SideChainStatus.Active); } - - [Fact] - public async Task Release_IndexingSideChain_ContinuousTwice() - { - var parentChainId = 123; - var lockedToken = 5; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + } - - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} - }; + [Fact] + public async Task Release_IndexingSideChain_Terminated() + { + var parentChainId = 123; + var lockedToken = 2; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; + + { var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var proposalId = ProposalCreated.Parser .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) .NonIndexed) .ProposalId; - Assert.NotNull(proposalId); + proposalId.ShouldNotBeNull(); await ApproveWithMinersAsync(proposalId); + } - - var sideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData4 = - CreateSideChainBlockData(fakeSideChainBlockHash, 4, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData5 = - CreateSideChainBlockData(fakeSideChainBlockHash, 5, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData6 = - CreateSideChainBlockData(fakeSideChainBlockHash, 6, sideChainId, fakeTxMerkleTreeRoot); + var disposeSideChainProposalId = await DisposeSideChainProposalAsync(new Int32Value { Value = sideChainId }); + await ApproveWithMinersAsync(disposeSideChainProposalId); + await ReleaseProposalAsync(disposeSideChainProposalId); - var secondCrossChainBlockData = new CrossChainBlockData + { + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { - SideChainBlockDataList = {sideChainBlockData3, sideChainBlockData4, sideChainBlockData5} - }; + Value = sideChainId + }); + chainStatus.Status.ShouldBe(SideChainStatus.Terminated); + } + var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( + new ReleaseCrossChainIndexingProposalInput { - var secondProposingTxRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( - secondCrossChainBlockData); - secondProposingTxRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); - } + ChainIdList = { sideChainId } + }); + releaseResult.TransactionResult.Error.ShouldContain("Chain indexing not proposed."); - { - // empty input - var releaseResult = - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( - new ReleaseCrossChainIndexingProposalInput()); - releaseResult.TransactionResult.Error.ShouldContain("Empty input not allowed."); - } - - { - var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - { - var secondProposingTxRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData6} - }); - secondProposingTxRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); - } - - { - var secondProposingTxRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); - var secondProposalId = ProposalCreated.Parser.ParseFrom(secondProposingTxRes.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; - Assert.NotNull(secondProposalId); - await ApproveWithMinersAsync(secondProposalId); - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - var indexedHeight = - await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value {Value = sideChainId}); - indexedHeight.Value.ShouldBe(5); - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value + { + var sideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( + new CrossChainBlockData { - Value = sideChainId + SideChainBlockDataList = { sideChainBlockData3 } }); - chainStatus.Status.ShouldBe(SideChainStatus.Active); - } + txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); } - - [Fact] - public async Task Release_IndexingSideChain_Terminated() - { - var parentChainId = 123; - var lockedToken = 2; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} - }; - - { - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(proposalId); - } - - var disposeSideChainProposalId = await DisposeSideChainProposalAsync(new Int32Value {Value = sideChainId}); - await ApproveWithMinersAsync(disposeSideChainProposalId); - await ReleaseProposalAsync(disposeSideChainProposalId); + } - { - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainStatus.Status.ShouldBe(SideChainStatus.Terminated); - } + [Fact] + public async Task Release_IndexingSideChain_IndexingFeeDebt() + { + var parentChainId = 123; + long lockedToken = 2; + long indexingPrice = 1; + long parentChainHeightOfCreation = 10; - var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendWithExceptionAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - releaseResult.TransactionResult.Error.ShouldContain("Chain indexing not proposed."); - - { - var sideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( - new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData3} - }); - txRes.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed"); - } - } + // transfer token + var transferTx = await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Amount = 1000, + Symbol = "ELF", + To = AnotherSender + }); + + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken, + indexingPrice, AnotherKeyPair); + + var balanceBeforeIndexing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + }); + + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData3 = + CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2, sideChainBlockData3 } + }; + + var txRes = + await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + await ApproveWithMinersAsync(proposalId); - [Fact] - public async Task Release_IndexingSideChain_IndexingFeeDebt() { - int parentChainId = 123; - long lockedToken = 2; - long indexingPrice = 1; - long parentChainHeightOfCreation = 10; - - // transfer token - var transferTx = await TokenContractStub.Transfer.SendAsync(new TransferInput + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { - Amount = 1000, - Symbol = "ELF", - To = AnotherSender + Value = sideChainId }); - - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken, - indexingPrice, AnotherKeyPair); + chainStatus.Status.ShouldBe(SideChainStatus.Active); + } - var balanceBeforeIndexing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - Owner = DefaultSender, - Symbol = "ELF" + ChainIdList = { sideChainId } }); - - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData3 = - CreateSideChainBlockData(fakeSideChainBlockHash, 3, sideChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2, sideChainBlockData3} - }; - - var txRes = - await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - await ApproveWithMinersAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainStatus.Status.ShouldBe(SideChainStatus.Active); - } - - var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync(new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} + Value = sideChainId }); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + chainStatus.Status.ShouldBe(SideChainStatus.IndexingFeeDebt); + } - { - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainStatus.Status.ShouldBe(SideChainStatus.IndexingFeeDebt); - } + var sideChainIndexedHeight = + (await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { Value = sideChainId })) + .Value; + sideChainIndexedHeight.ShouldBe(crossChainBlockData.SideChainBlockDataList.Last().Height); - var sideChainIndexedHeight = - (await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value {Value = sideChainId})) - .Value; - sideChainIndexedHeight.ShouldBe(crossChainBlockData.SideChainBlockDataList.Last().Height); - - var balanceAfterIndexing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "ELF" - }); - balanceAfterIndexing.Balance.ShouldBe(balanceBeforeIndexing.Balance + lockedToken); - - // recharge - var arrearsAmount = crossChainBlockData.SideChainBlockDataList.Count - lockedToken; - var rechargeAmount = arrearsAmount + indexingPrice; - // approve allowance - await ApproveBalanceAsync(rechargeAmount, AnotherKeyPair); - - var crossChainContractStub = GetCrossChainContractStub(AnotherKeyPair); - - { - var rechargeTxFailed = await crossChainContractStub.Recharge.SendWithExceptionAsync(new RechargeInput - { - ChainId = sideChainId, - Amount = rechargeAmount - 1 - }); - rechargeTxFailed.TransactionResult.Error.ShouldContain("Indexing fee recharging not enough."); - } - - var rechargeTx = await crossChainContractStub.Recharge.SendAsync(new RechargeInput + var balanceAfterIndexing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + }); + balanceAfterIndexing.Balance.ShouldBe(balanceBeforeIndexing.Balance + lockedToken); + + // recharge + var arrearsAmount = crossChainBlockData.SideChainBlockDataList.Count - lockedToken; + var rechargeAmount = arrearsAmount + indexingPrice; + // approve allowance + await ApproveBalanceAsync(rechargeAmount, AnotherKeyPair); + + var crossChainContractStub = GetCrossChainContractStub(AnotherKeyPair); + + { + var rechargeTxFailed = await crossChainContractStub.Recharge.SendWithExceptionAsync(new RechargeInput { ChainId = sideChainId, - Amount = rechargeAmount + Amount = rechargeAmount - 1 }); - rechargeTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balanceAfterRecharge = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + rechargeTxFailed.TransactionResult.Error.ShouldContain("Indexing fee recharging not enough."); + } + + var rechargeTx = await crossChainContractStub.Recharge.SendAsync(new RechargeInput + { + ChainId = sideChainId, + Amount = rechargeAmount + }); + rechargeTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var balanceAfterRecharge = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + }); + balanceAfterRecharge.Balance.ShouldBe(balanceAfterIndexing.Balance + arrearsAmount); + + { + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { - Owner = DefaultSender, - Symbol = "ELF" + Value = sideChainId }); - balanceAfterRecharge.Balance.ShouldBe(balanceAfterIndexing.Balance + arrearsAmount); - - { - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainStatus.Status.ShouldBe(SideChainStatus.Active); - } + chainStatus.Status.ShouldBe(SideChainStatus.Active); } - - [Fact] - public async Task Release_IndexingParentChain_Success() - { - var parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - Hash fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - await ApproveWithMinersAsync(proposalId); + } - { - var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - indexedHeight.Value.ShouldBe(parentChainHeightOfCreation - 1); - } - - var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {parentChainId} - }); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Release_IndexingParentChain_Success() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + var fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + await ApproveWithMinersAsync(proposalId); - { - var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - indexedHeight.Value.ShouldBe(parentChainHeightOfCreation); - } + { + var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + indexedHeight.Value.ShouldBe(parentChainHeightOfCreation - 1); } - - [Fact] - public async Task Release_IndexingParentChain_ContinuousTwice() - { - var parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - Hash fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - Assert.NotNull(proposalId); - await ApproveWithMinersAsync(proposalId); + var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - indexedHeight.Value.ShouldBe(parentChainHeightOfCreation - 1); - } - - var parentChainBlockData2 = CreateParentChainBlockData(parentChainHeightOfCreation + 1, parentChainId, - fakeTransactionStatusMerkleRoot); - var parentChainBlockData3 = CreateParentChainBlockData(parentChainHeightOfCreation + 2, parentChainId, - fakeTransactionStatusMerkleRoot); - var secondCrossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData2, parentChainBlockData3} - }; + ChainIdList = { parentChainId } + }); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - { - var secondProposingTx = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); - secondProposingTx.TransactionResult.Error.ShouldContain("Chain indexing already proposed."); - } + { + var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + indexedHeight.Value.ShouldBe(parentChainHeightOfCreation); + } + } - { - var secondProposingTx = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( - secondCrossChainBlockData); - secondProposingTx.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); - } + [Fact] + public async Task Release_IndexingParentChain_ContinuousTwice() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); + var fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + Assert.NotNull(proposalId); + await ApproveWithMinersAsync(proposalId); - var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {parentChainId} - }); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + indexedHeight.Value.ShouldBe(parentChainHeightOfCreation - 1); + } - { - var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - indexedHeight.Value.ShouldBe(parentChainHeightOfCreation); - } + var parentChainBlockData2 = CreateParentChainBlockData(parentChainHeightOfCreation + 1, parentChainId, + fakeTransactionStatusMerkleRoot); + var parentChainBlockData3 = CreateParentChainBlockData(parentChainHeightOfCreation + 2, parentChainId, + fakeTransactionStatusMerkleRoot); + var secondCrossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData2, parentChainBlockData3 } + }; + { + var secondProposingTx = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync(crossChainBlockData); + secondProposingTx.TransactionResult.Error.ShouldContain("Chain indexing already proposed."); + } + + { + var secondProposingTx = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( + secondCrossChainBlockData); + secondProposingTx.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); + } + + var releaseResult = await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - var secondProposingTx = - await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( - new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData3} - }); - secondProposingTx.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); - } - - { - var secondProposingTx = - await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); - var secondProposalId = ProposalCreated.Parser.ParseFrom(secondProposingTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; - await ApproveWithMinersAsync(secondProposalId); - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput + ChainIdList = { parentChainId } + }); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + { + var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + indexedHeight.Value.ShouldBe(parentChainHeightOfCreation); + } + + { + var secondProposingTx = + await CrossChainContractStub.ProposeCrossChainIndexing.SendWithExceptionAsync( + new CrossChainBlockData { - ChainIdList = {parentChainId} + ParentChainBlockDataList = { parentChainBlockData3 } }); - var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); - indexedHeight.Value.ShouldBe(parentChainHeightOfCreation + - secondCrossChainBlockData.ParentChainBlockDataList.Count); - } + secondProposingTx.TransactionResult.Error.ShouldContain("Invalid cross chain data to be indexed."); } - - [Fact] - public async Task AcceptCrossChainIndexingProposal_Failed() - { - var parentChainId = 123; - long parentChainHeightOfCreation = 10; - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - - var organizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - - // create a normal proposal - { - var proposalTx = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + + { + var secondProposingTx = + await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(secondCrossChainBlockData); + var secondProposalId = ProposalCreated.Parser.ParseFrom(secondProposingTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + await ApproveWithMinersAsync(secondProposalId); + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { - ContractMethodName = nameof(CrossChainContractStub.AcceptCrossChainIndexingProposal), - OrganizationAddress = organizationAddress, - ExpiredTime = TimestampHelper.GetUtcNow().AddMinutes(10), - ToAddress = CrossChainContractAddress, - Params = new AcceptCrossChainIndexingProposalInput - { - ChainId = parentChainId - }.ToByteString() + ChainIdList = { parentChainId } }); - proposalTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = ProposalCreated.Parser - .ParseFrom(proposalTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - - // approve - await ApproveWithMinersAsync(proposalId); - - // release - var releaseTx = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - releaseTx.TransactionResult.Error.ShouldContain("Incorrect cross chain indexing proposal status."); - } + var indexedHeight = await CrossChainContractStub.GetParentChainHeight.CallAsync(new Empty()); + indexedHeight.Value.ShouldBe(parentChainHeightOfCreation + + secondCrossChainBlockData.ParentChainBlockDataList.Count); + } + } - { - // not authorized - var tx = await CrossChainContractStub.AcceptCrossChainIndexingProposal.SendWithExceptionAsync( - new AcceptCrossChainIndexingProposalInput - { - ChainId = parentChainId - }); + [Fact] + public async Task AcceptCrossChainIndexingProposal_Failed() + { + var parentChainId = 123; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId); - tx.TransactionResult.Error.ShouldContain("Unauthorized behavior."); - } - } - - [Fact] - public async Task GetIndexedCrossChainBlockData_Test() - { - var parentChainId = 123; - var lockedToken = 2; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); - var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); - var sideChainBlockData1 = - CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); - var sideChainBlockData2 = - CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); - - var crossChainBlockData = new CrossChainBlockData + var organizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + + // create a normal proposal + { + var proposalTx = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - SideChainBlockDataList = {sideChainBlockData1, sideChainBlockData2} - }; - var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + ContractMethodName = nameof(CrossChainContractStub.AcceptCrossChainIndexingProposal), + OrganizationAddress = organizationAddress, + ExpiredTime = TimestampHelper.GetUtcNow().AddMinutes(10), + ToAddress = CrossChainContractAddress, + Params = new AcceptCrossChainIndexingProposalInput + { + ChainId = parentChainId + }.ToByteString() + }); + proposalTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var proposalId = ProposalCreated.Parser - .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ParseFrom(proposalTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed) .ProposalId; - await ApproveWithMinersAsync(proposalId); + proposalId.ShouldNotBeNull(); - var releaseResult = - await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput {ChainIdList = {sideChainId}}); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // approve + await ApproveWithMinersAsync(proposalId); - var indexedCrossChainBlockData = - await CrossChainContractStub.GetIndexedSideChainBlockDataByHeight.CallAsync(new Int64Value - {Value = releaseResult.TransactionResult.BlockNumber}); - - indexedCrossChainBlockData.SideChainBlockDataList.ShouldBe(crossChainBlockData.SideChainBlockDataList); + // release + var releaseTx = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + releaseTx.TransactionResult.Error.ShouldContain("Incorrect cross chain indexing proposal status."); } - - #endregion - - #region Verification - [Fact] - public async Task CrossChain_MerklePath_Test() { - int parentChainId = 123; - long lockedToken = 10; - long parentChainHeightOfCreation = 10; + // not authorized + var tx = await CrossChainContractStub.AcceptCrossChainIndexingProposal.SendWithExceptionAsync( + new AcceptCrossChainIndexingProposalInput + { + ChainId = parentChainId + }); + + tx.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + } + } + + [Fact] + public async Task GetIndexedCrossChainBlockData_Test() + { + var parentChainId = 123; + var lockedToken = 2; + long parentChainHeightOfCreation = 10; + var sideChainId = await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var transactionId = HashHelper.ComputeFrom("sideChainBlockHash"); - - var fakeHash1 = HashHelper.ComputeFrom("fake1"); - var fakeHash2 = HashHelper.ComputeFrom("fake2"); + var fakeSideChainBlockHash = HashHelper.ComputeFrom("sideChainBlockHash"); + var fakeTxMerkleTreeRoot = HashHelper.ComputeFrom("txMerkleTreeRoot"); + var sideChainBlockData1 = + CreateSideChainBlockData(fakeSideChainBlockHash, 1, sideChainId, fakeTxMerkleTreeRoot); + var sideChainBlockData2 = + CreateSideChainBlockData(fakeSideChainBlockHash, 2, sideChainId, fakeTxMerkleTreeRoot); + + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockData1, sideChainBlockData2 } + }; + var txRes = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + txRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = ProposalCreated.Parser + .ParseFrom(txRes.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + await ApproveWithMinersAsync(proposalId); + + var releaseResult = + await CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { ChainIdList = { sideChainId } }); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] {transactionId, fakeHash1, fakeHash2}); - var merkleTreeRoot = binaryMerkleTree.Root; - var merklePath = binaryMerkleTree.GenerateMerklePath(0); - Hash fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - fakeTransactionStatusMerkleRoot); + var indexedCrossChainBlockData = + await CrossChainContractStub.GetIndexedSideChainBlockDataByHeight.CallAsync(new Int64Value + { Value = releaseResult.TransactionResult.BlockNumber }); - long sideChainHeight = 1; - parentChainBlockData.IndexedMerklePath.Add(sideChainHeight, merklePath); - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData} - }; + indexedCrossChainBlockData.SideChainBlockDataList.ShouldBe(crossChainBlockData.SideChainBlockDataList); + } - await DoIndexAsync(crossChainBlockData, new []{parentChainId}); + #endregion - { - var crossChainMerkleProofContext = - await CrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallWithExceptionAsync(new Int64Value - {Value = sideChainHeight + 1}); - } - - { - var crossChainMerkleProofContext = - await CrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallAsync(new Int64Value - {Value = sideChainHeight}); - Assert.Equal(merklePath.ToByteString(), - crossChainMerkleProofContext.MerklePathFromParentChain.ToByteString()); - var calculatedRoot = crossChainMerkleProofContext.MerklePathFromParentChain - .ComputeRootWithLeafNode(transactionId); - Assert.Equal(merkleTreeRoot, calculatedRoot); - } - } + #region Verification - [Fact] - public async Task CrossChain_Verification() - { - int parentChainId = 123; - long lockedToken = 10; - long parentChainHeightOfCreation = 10; - var sideChainId = await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); - var txId = HashHelper.ComputeFrom("sideChainBlockHash"); - - var fakeHash1 = HashHelper.ComputeFrom("fake1"); - var fakeHash2 = HashHelper.ComputeFrom("fake2"); - - var rawBytes = ByteArrayHelper.ConcatArrays(txId.ToByteArray(), - EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); - var hash = HashHelper.ComputeFrom(rawBytes); - - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] {hash, fakeHash1, fakeHash2}); - var merkleTreeRoot = binaryMerkleTree.Root; - - var parentChainTxId = HashHelper.ComputeFrom("parentChainTx"); - var parentChainTxStatusRawBytes = ByteArrayHelper.ConcatArrays(parentChainTxId.ToByteArray(), - EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); - var parentChainTxStatusMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] - { - fakeHash1, - HashHelper.ComputeFrom(parentChainTxStatusRawBytes), - fakeHash2 - }); - - var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, - parentChainTxStatusMerkleTree.Root); - var sideChainTxId = HashHelper.ComputeFrom("sideChainTx"); - var sideChainTxStatusRawBytes = ByteArrayHelper.ConcatArrays(sideChainTxId.ToByteArray(), - EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); - var sideChainTxStatusMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] - { - fakeHash1, - fakeHash2, - HashHelper.ComputeFrom(sideChainTxStatusRawBytes), - }); + [Fact] + public async Task CrossChain_MerklePath_Test() + { + var parentChainId = 123; + long lockedToken = 10; + long parentChainHeightOfCreation = 10; + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var transactionId = HashHelper.ComputeFrom("sideChainBlockHash"); + + var fakeHash1 = HashHelper.ComputeFrom("fake1"); + var fakeHash2 = HashHelper.ComputeFrom("fake2"); + + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] { transactionId, fakeHash1, fakeHash2 }); + var merkleTreeRoot = binaryMerkleTree.Root; + var merklePath = binaryMerkleTree.GenerateMerklePath(0); + var fakeTransactionStatusMerkleRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot"); + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + fakeTransactionStatusMerkleRoot); + + long sideChainHeight = 1; + parentChainBlockData.IndexedMerklePath.Add(sideChainHeight, merklePath); + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData } + }; - var sideChainBlockData = CreateSideChainBlockData(HashHelper.ComputeFrom("SideChainBlockHash"), 1, - sideChainId, sideChainTxStatusMerkleTree.Root); - - parentChainBlockData.CrossChainExtraData = new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = merkleTreeRoot, - }; - var crossChainBlockData = new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockData}, - SideChainBlockDataList = {sideChainBlockData} - }; + await DoIndexAsync(crossChainBlockData, new[] { parentChainId }); - var blockHeight = await DoIndexAsync(crossChainBlockData, new[] {parentChainId, sideChainId}); + { + var crossChainMerkleProofContext = + await CrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallWithExceptionAsync( + new Int64Value + { Value = sideChainHeight + 1 }); + } - { - var merklePath = binaryMerkleTree.GenerateMerklePath(0); + { + var crossChainMerkleProofContext = + await CrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallAsync(new Int64Value + { Value = sideChainHeight }); + Assert.Equal(merklePath.ToByteString(), + crossChainMerkleProofContext.MerklePathFromParentChain.ToByteString()); + var calculatedRoot = crossChainMerkleProofContext.MerklePathFromParentChain + .ComputeRootWithLeafNode(transactionId); + Assert.Equal(merkleTreeRoot, calculatedRoot); + } + } - // cousin chain verification - { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = txId, - ParentChainHeight = parentChainHeightOfCreation, - Path = merklePath, - }; + [Fact] + public async Task CrossChain_Verification() + { + var parentChainId = 123; + long lockedToken = 10; + long parentChainHeightOfCreation = 10; + var sideChainId = await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + var txId = HashHelper.ComputeFrom("sideChainBlockHash"); + + var fakeHash1 = HashHelper.ComputeFrom("fake1"); + var fakeHash2 = HashHelper.ComputeFrom("fake2"); + + var rawBytes = ByteArrayHelper.ConcatArrays(txId.ToByteArray(), + EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); + var hash = HashHelper.ComputeFrom(rawBytes); + + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] { hash, fakeHash1, fakeHash2 }); + var merkleTreeRoot = binaryMerkleTree.Root; + + var parentChainTxId = HashHelper.ComputeFrom("parentChainTx"); + var parentChainTxStatusRawBytes = ByteArrayHelper.ConcatArrays(parentChainTxId.ToByteArray(), + EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); + var parentChainTxStatusMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] + { + fakeHash1, + HashHelper.ComputeFrom(parentChainTxStatusRawBytes), + fakeHash2 + }); + + var parentChainBlockData = CreateParentChainBlockData(parentChainHeightOfCreation, parentChainId, + parentChainTxStatusMerkleTree.Root); + var sideChainTxId = HashHelper.ComputeFrom("sideChainTx"); + var sideChainTxStatusRawBytes = ByteArrayHelper.ConcatArrays(sideChainTxId.ToByteArray(), + EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())); + var sideChainTxStatusMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] + { + fakeHash1, + fakeHash2, + HashHelper.ComputeFrom(sideChainTxStatusRawBytes) + }); - var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); - var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; - verified.ShouldBeTrue(); - } + var sideChainBlockData = CreateSideChainBlockData(HashHelper.ComputeFrom("SideChainBlockHash"), 1, + sideChainId, sideChainTxStatusMerkleTree.Root); - { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = txId, - ParentChainHeight = parentChainHeightOfCreation + 1, - Path = merklePath, - }; + parentChainBlockData.CrossChainExtraData = new CrossChainExtraData + { + TransactionStatusMerkleTreeRoot = merkleTreeRoot + }; + var crossChainBlockData = new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockData }, + SideChainBlockDataList = { sideChainBlockData } + }; + + var blockHeight = await DoIndexAsync(crossChainBlockData, new[] { parentChainId, sideChainId }); - var error = await CrossChainContractStub.VerifyTransaction - .CallWithExceptionAsync(verificationInput); - error.Value.ShouldContain( - $"Parent chain block at height {verificationInput.ParentChainHeight} is not recorded."); - } + { + var merklePath = binaryMerkleTree.GenerateMerklePath(0); + // cousin chain verification + { + var verificationInput = new VerifyTransactionInput { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = fakeHash1, - ParentChainHeight = parentChainHeightOfCreation, - Path = merklePath, - }; - - var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); - res.Value.ShouldBeFalse(); - } + TransactionId = txId, + ParentChainHeight = parentChainHeightOfCreation, + Path = merklePath + }; + + var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); + var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; + verified.ShouldBeTrue(); } - - { - // parent chain verification - - var merklePath = parentChainTxStatusMerkleTree.GenerateMerklePath(1); + { + var verificationInput = new VerifyTransactionInput { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = parentChainTxId, - ParentChainHeight = parentChainHeightOfCreation, - Path = merklePath, - VerifiedChainId = parentChainId - }; + TransactionId = txId, + ParentChainHeight = parentChainHeightOfCreation + 1, + Path = merklePath + }; - var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); - var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; - verified.ShouldBeTrue(); - } + var error = await CrossChainContractStub.VerifyTransaction + .CallWithExceptionAsync(verificationInput); + error.Value.ShouldContain( + $"Parent chain block at height {verificationInput.ParentChainHeight} is not recorded."); + } + { + var verificationInput = new VerifyTransactionInput { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = parentChainTxId, - ParentChainHeight = parentChainHeightOfCreation + 1, - Path = merklePath, - VerifiedChainId = parentChainId - }; - - var error = await CrossChainContractStub.VerifyTransaction - .CallWithExceptionAsync(verificationInput); - error.Value.ShouldContain( - $"Parent chain block at height {verificationInput.ParentChainHeight} is not recorded."); - } + TransactionId = fakeHash1, + ParentChainHeight = parentChainHeightOfCreation, + Path = merklePath + }; - { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = fakeHash1, - ParentChainHeight = parentChainHeightOfCreation, - Path = merklePath, - VerifiedChainId = parentChainId - }; - - var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); - res.Value.ShouldBeFalse(); - } + var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); + res.Value.ShouldBeFalse(); } + } + + { + // parent chain verification + + var merklePath = parentChainTxStatusMerkleTree.GenerateMerklePath(1); { - // side chain verification - var merklePath = sideChainTxStatusMerkleTree.GenerateMerklePath(2); - merklePath.MerklePathNodes.Add(new MerklePathNode + var verificationInput = new VerifyTransactionInput { - Hash = sideChainTxStatusMerkleTree.Root, - IsLeftChildNode = true - }); - - { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = sideChainTxId, - ParentChainHeight = blockHeight, - Path = merklePath, - VerifiedChainId = sideChainId - }; + TransactionId = parentChainTxId, + ParentChainHeight = parentChainHeightOfCreation, + Path = merklePath, + VerifiedChainId = parentChainId + }; - var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); - var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; - verified.ShouldBeTrue(); - } + var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); + var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; + verified.ShouldBeTrue(); + } + { + var verificationInput = new VerifyTransactionInput { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = sideChainTxId, - ParentChainHeight = blockHeight + 1, - Path = merklePath, - VerifiedChainId = sideChainId - }; + TransactionId = parentChainTxId, + ParentChainHeight = parentChainHeightOfCreation + 1, + Path = merklePath, + VerifiedChainId = parentChainId + }; - var error = await CrossChainContractStub.VerifyTransaction - .CallWithExceptionAsync(verificationInput); - } + var error = await CrossChainContractStub.VerifyTransaction + .CallWithExceptionAsync(verificationInput); + error.Value.ShouldContain( + $"Parent chain block at height {verificationInput.ParentChainHeight} is not recorded."); + } + { + var verificationInput = new VerifyTransactionInput { - var verificationInput = new VerifyTransactionInput() - { - TransactionId = fakeHash1, - ParentChainHeight = blockHeight, - Path = merklePath, - VerifiedChainId = sideChainId - }; - - var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); - res.Value.ShouldBeFalse(); - } + TransactionId = fakeHash1, + ParentChainHeight = parentChainHeightOfCreation, + Path = merklePath, + VerifiedChainId = parentChainId + }; + + var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); + res.Value.ShouldBeFalse(); } } - #endregion - - [Fact] - public async Task LockedToken_Verification() { - var parentChainId = 123; - var lockedToken = 100_000L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedToken); + // side chain verification + var merklePath = sideChainTxStatusMerkleTree.GenerateMerklePath(2); + merklePath.MerklePathNodes.Add(new MerklePathNode + { + Hash = sideChainTxStatusMerkleTree.Root, + IsLeftChildNode = true + }); - var lockedToken1 = - await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value {Value = sideChainId}); - lockedToken1.Value.ShouldBe(lockedToken); + { + var verificationInput = new VerifyTransactionInput + { + TransactionId = sideChainTxId, + ParentChainHeight = blockHeight, + Path = merklePath, + VerifiedChainId = sideChainId + }; - var address = await CrossChainContractStub.GetSideChainCreator.CallAsync(new Int32Value {Value = sideChainId}); - address.ShouldBe(Address.FromPublicKey(DefaultKeyPair.PublicKey)); - } - - #region HelpMethods + var txRes = await CrossChainContractStub.VerifyTransaction.SendAsync(verificationInput); + var verified = BoolValue.Parser.ParseFrom(txRes.TransactionResult.ReturnValue).Value; + verified.ShouldBeTrue(); + } - private SideChainBlockData CreateSideChainBlockData(Hash blockHash, long height, int sideChainId, - Hash txMerkleTreeRoot) - { - return new SideChainBlockData { - BlockHeaderHash = blockHash, - Height = height, - ChainId = sideChainId, - TransactionStatusMerkleTreeRoot = txMerkleTreeRoot - }; - } + var verificationInput = new VerifyTransactionInput + { + TransactionId = sideChainTxId, + ParentChainHeight = blockHeight + 1, + Path = merklePath, + VerifiedChainId = sideChainId + }; + + var error = await CrossChainContractStub.VerifyTransaction + .CallWithExceptionAsync(verificationInput); + } + + { + var verificationInput = new VerifyTransactionInput + { + TransactionId = fakeHash1, + ParentChainHeight = blockHeight, + Path = merklePath, + VerifiedChainId = sideChainId + }; - #endregion + var res = await CrossChainContractStub.VerifyTransaction.CallAsync(verificationInput); + res.Value.ShouldBeFalse(); + } + } } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/SideChainLifeTimeManagementTest.cs b/test/AElf.Contracts.CrossChain.Tests/SideChainLifeTimeManagementTest.cs index dbf6e4bc6b..3ac1e98ed9 100644 --- a/test/AElf.Contracts.CrossChain.Tests/SideChainLifeTimeManagementTest.cs +++ b/test/AElf.Contracts.CrossChain.Tests/SideChainLifeTimeManagementTest.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.Association; using AElf.Contracts.MultiToken; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -15,1687 +15,1688 @@ using Xunit; using CreateOrganizationInput = AElf.Contracts.Parliament.CreateOrganizationInput; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +public class + ChangeCrossChainIndexingControllerSideChainLifeTimeManagementTest : CrossChainContractTestBase< + CrossChainContractTestAElfModule> { - public class ChangeCrossChainIndexingControllerSideChainLifeTimeManagementTest : CrossChainContractTestBase + [Fact] + public async Task ChangeIndexingController() { - #region Side Chain Action - - [Fact] - public async Task Initialize_Test() - { - await InitializeCrossChainContractAsync(0, 0, false); - // initialize twice - await InitializeCrossChainContractAsync(0, 0, true); - } - - [Fact] - public async Task SetController_Test() - { - { - // no permission - var txResult = await CrossChainContractStub.SetInitialSideChainLifetimeControllerAddress - .SendWithExceptionAsync( - DefaultSender); - txResult.TransactionResult.Error.ShouldContain("No permission."); - } - { - // no permission - var txResult = await CrossChainContractStub.SetInitialIndexingControllerAddress.SendWithExceptionAsync( - DefaultSender); - txResult.TransactionResult.Error.ShouldContain("No permission."); - } - - await InitializeCrossChainContractAsync(); + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - // no permission - var txResult = await CrossChainContractStub.SetInitialSideChainLifetimeControllerAddress - .SendWithExceptionAsync( - DefaultSender); - txResult.TransactionResult.Error.ShouldContain("Already initialized."); - } + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 3333, + MaximalRejectionThreshold = 3333, + MinimalApprovalThreshold = 3333, + MinimalVoteThreshold = 3333 + }, + ParliamentMemberProposingAllowed = true + })).Output; + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo { - // no permission - var txResult = await CrossChainContractStub.SetInitialIndexingControllerAddress.SendWithExceptionAsync( - DefaultSender); - txResult.TransactionResult.Error.ShouldContain("Already initialized."); - } - } + ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendAsync(proposalId)).TransactionResult; + releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var crossChainIndexingController = + await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty()); + crossChainIndexingController.ContractAddress.ShouldBe(ParliamentContractAddress); + crossChainIndexingController.OwnerAddress.ShouldBe(newOrganizationAddress); + } - [Fact] - public async Task Create_SideChain() + [Fact] + public async Task ChangeIndexingController_InvalidOwnerAddress() + { + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - await InitializeCrossChainContractAsync(); - + ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo { - // not PrivilegeReserved - - // Create proposal and approve - var proposalId = await CreateSideChainProposalAsync(0, 0); - - await CrossChainContractStub.ReleaseSideChainCreation.SendWithExceptionAsync( - new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var chainId = sideChainCreatedEvent.ChainId; - var creator = sideChainCreatedEvent.Creator; - creator.ShouldBe(DefaultSender); - - var chainStatus = - await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value {Value = chainId}); - chainStatus.Status .ShouldBe(SideChainStatus.Active); - - releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(TokenCreated))).ShouldBeFalse(); - } + ContractAddress = ParliamentContractAddress, OwnerAddress = DefaultSender + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) + .TransactionResult; + releaseResult.Error.ShouldContain("Invalid authority input."); + } - { - // PrivilegeReserved - - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - var proposalId = - await CreateSideChainProposalAsync(1, lockedTokenAmount, null, GetValidResourceAmount(), true); - - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var tokenCreatedEvent = TokenCreated.Parser - .ParseFrom(releaseTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(TokenCreated))) - .NonIndexed); - tokenCreatedEvent.Symbol.ShouldBe("TE"); - } - } - - [Fact] - public async Task Release_SideChain_Expired() - { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - - // Create proposal and approve - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - - BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); + [Fact] + public async Task ChangeIndexingController_NotAuthorized() + { + await InitializeCrossChainContractAsync(); + var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .ShouldBeFalse(); - } - } - - [Fact] - public async Task RequestSideChainCreation_Twice() - { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 3333, + MaximalRejectionThreshold = 3333, + MinimalApprovalThreshold = 3333, + MinimalVoteThreshold = 3333 + } + })).Output; - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount - 1, lockedTokenAmount, - GetValidResourceAmount(), new[] + var res = + (await CrossChainContractStub.ChangeCrossChainIndexingController.SendWithExceptionAsync( + new AuthorityInfo { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }); - await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); + ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress + })).TransactionResult; - BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86399)); - var secondRequestTx = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - secondRequestTx.TransactionResult.Error.ShouldContain("Request side chain creation failed."); + var status = res.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Unauthorized behavior.", res.Error); + } - BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); - var thirdRequestTx = await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - thirdRequestTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + [Fact] + public async Task ChangeIndexingController_InvalidOrganization() + { + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - [Fact] - public async Task RequestSideChainCreationSecondTimeAfterRelease() { - await InitializeCrossChainContractAsync(); + var newOrganizationCreationInput = new Association.CreateOrganizationInput { - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - // Create proposal and approve - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - } - + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { DefaultSender } + }, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { DefaultSender } + } + }; + var newOrganizationAddress = + (await AssociationContractStub.CreateOrganization.SendAsync(newOrganizationCreationInput)).Output; + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - proposalId.ShouldNotBeNull(); - } + ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo + { + ContractAddress = AssociationContractAddress, OwnerAddress = newOrganizationAddress + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) + .TransactionResult; + releaseResult.Error.ShouldContain("Invalid authority input."); } - [Fact] - public async Task RequestSideChainCreation_Failed() { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - + var newParliamentOrganizationCreationInput = new CreateOrganizationInput { - var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount - 1, lockedTokenAmount, - GetValidResourceAmount(), new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - - requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - requestSideChainCreation.TransactionResult.Error.ShouldContain("Allowance not enough"); - } - - await ApproveBalanceAsync(lockedTokenAmount); + ParliamentMemberProposingAllowed = false, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1, + MaximalRejectionThreshold = 0, + MaximalAbstentionThreshold = 0 + }, + ProposerAuthorityRequired = true + }; + var newOrganizationAddress = + (await ParliamentContractStub.CreateOrganization.SendAsync(newParliamentOrganizationCreationInput)) + .Output; + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - var createProposalInput = CreateSideChainCreationRequest(10, 0, GetValidResourceAmount(), - new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); + ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); - requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - requestSideChainCreation.TransactionResult.Error.ShouldContain("Invalid chain creation request."); - } - - { - var createProposalInput = CreateSideChainCreationRequest(-1, 10, GetValidResourceAmount(), - new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) + .TransactionResult; + releaseResult.Error.ShouldContain("Invalid authority input."); + } + } - requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - requestSideChainCreation.TransactionResult.Error.ShouldContain("Invalid chain creation request."); - } + [Fact] + public async Task ChangeSideChainLifeTimeController() + { + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; + var newOrganizationAddress = (await AssociationContractStub.CreateOrganization.SendAsync( + new Association.CreateOrganizationInput { - foreach (var t in ResourceTokenSymbolList) + ProposalReleaseThreshold = new ProposalReleaseThreshold { - // invalid resource token - var resourceAmount = GetValidResourceAmount(); - resourceAmount.Remove(t); - var createProposalInput = CreateSideChainCreationRequest(1, lockedTokenAmount, - resourceAmount, new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync( - createProposalInput); - - requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - requestSideChainCreation.TransactionResult.Error.ShouldContain( - "Invalid side chain resource token request."); - } - - foreach (var t in ResourceTokenSymbolList) + MaximalAbstentionThreshold = 0, + MaximalRejectionThreshold = 0, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ProposerWhiteList = new ProposerWhiteList { - // invalid resource token - var resourceAmount = GetValidResourceAmount(); - resourceAmount[t] = 0; - var createProposalInput = CreateSideChainCreationRequest(1, lockedTokenAmount, - resourceAmount, new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync( - createProposalInput); - - requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + Proposers = { DefaultSender } + }, + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { DefaultSender } } - } - - { - var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount, lockedTokenAmount, - GetValidResourceAmount(), new SideChainTokenInitialIssue[0], true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - requestSideChainCreation.TransactionResult.Error.ShouldContain( - "Invalid side chain token initial issue list."); - } - - var utcNow = TimestampHelper.GetUtcNow(); + })).Output; - BlockTimeProvider.SetBlockTime(utcNow); - { - var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount, lockedTokenAmount, - GetValidResourceAmount(), new[] - { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } - }, true); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - } - - BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo { - var createProposalInput = CreateSideChainCreationRequest(0, 0, - new Dictionary(), new SideChainTokenInitialIssue[0]); - var requestSideChainCreation = - await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - } - } + ContractAddress = AssociationContractAddress, OwnerAddress = newOrganizationAddress + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendAsync(proposalId)).TransactionResult; + releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var sideChainLifetimeController = + await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty()); + sideChainLifetimeController.ContractAddress.ShouldBe(AssociationContractAddress); + sideChainLifetimeController.OwnerAddress.ShouldBe(newOrganizationAddress); + } + + [Fact] + public async Task ChangeSideChainLifeTimeController_Failed() + { + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; - [Fact] - public async Task CreateSideChainCreation_WithoutRequest() { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; - var proposalCreation = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + // invalid new owner address + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - ContractMethodName = nameof(CrossChainContractStub.CreateSideChain), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - OrganizationAddress = oldOrganizationAddress, - ToAddress = CrossChainContractAddress, - Params = new CreateSideChainInput + ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo { - Proposer = DefaultSender, - SideChainCreationRequest = new SideChainCreationRequest - { - IndexingPrice = 1, - LockedTokenAmount = 10, - SideChainTokenCreationRequest = new SideChainTokenCreationRequest - { - SideChainTokenDecimals = 2, - SideChainTokenTotalSupply = 1_000_000_000, - SideChainTokenSymbol = "TE", - SideChainTokenName = "TEST", - } - } - }.ToByteString() + ContractAddress = ParliamentContractAddress, OwnerAddress = DefaultSender + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress }); - var proposalId = ProposalCreated.Parser.ParseFrom(proposalCreation.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); await ApproveWithMinersAsync(proposalId); - var proposalRelease = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - proposalRelease.TransactionResult.Error.ShouldContain("Side chain creation failed without proposed data."); + var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) + .TransactionResult; + releaseResult.Error.ShouldContain("Invalid authority input."); } - [Fact] - public async Task ReleaseSideChainCreation_WithoutRequest() { - await InitializeCrossChainContractAsync(); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendWithExceptionAsync( - new ReleaseSideChainCreationInput - {ProposalId = Hash.Empty}); - releaseTx.TransactionResult.Error.ShouldContain("Release side chain creation failed."); + // wrong authorization contract address + var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new AuthorityInfo + { + ContractAddress = AssociationContractAddress, OwnerAddress = oldOrganizationAddress + }.ToByteString(), + ToAddress = CrossChainContractAddress, + OrganizationAddress = oldOrganizationAddress + }); + + var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); + await ApproveWithMinersAsync(proposalId); + var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) + .TransactionResult; + releaseResult.Error.ShouldContain("Invalid authority input."); } - [Fact] - public async Task Create_SideChain_NotAuthorized() { - long lockedTokenAmount = 10; - await InitializeCrossChainContractAsync(); - await ApproveBalanceAsync(lockedTokenAmount); - - var sideChainCreationRequest = CreateSideChainCreationRequest(1, lockedTokenAmount, - GetValidResourceAmount(), new[] + // no proposal created + var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - new SideChainTokenInitialIssue + ProposalReleaseThreshold = new ProposalReleaseThreshold { - Address = DefaultSender, - Amount = 100 + MaximalAbstentionThreshold = 3333, + MaximalRejectionThreshold = 3333, + MinimalApprovalThreshold = 3333, + MinimalVoteThreshold = 3333 } - }); - var result = await CrossChainContractStub.CreateSideChain.SendWithExceptionAsync(new CreateSideChainInput - { - SideChainCreationRequest = sideChainCreationRequest, - Proposer = DefaultSender - } - ); - var status = result.TransactionResult.Status; + })).Output; + + var res = + (await CrossChainContractStub.ChangeSideChainLifetimeController.SendWithExceptionAsync( + new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress + })).TransactionResult; + + var status = res.Status; Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Unauthorized behavior.", result.TransactionResult.Error); + Assert.Contains("Unauthorized behavior.", res.Error); } + } - [Fact] - public async Task CreatSideChain_ByOrganization() - { - long lockedTokenAmount = 10; - await InitializeCrossChainContractAsync(); - - var organizationAddress = - (await ParliamentContractStub.CreateOrganization.SendAsync(new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = true - })).Output; - var allowanceResult = - await ApproveAndTransferOrganizationBalanceAsync(organizationAddress, lockedTokenAmount); - Assert.True(allowanceResult.Spender == CrossChainContractAddress); - Assert.True(allowanceResult.Allowance == lockedTokenAmount); + [Fact] + public async Task AdjustCrossChainIndexingFeePriceTest() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var organizationAddress = OrganizationCreated.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(OrganizationCreated))) + .NonIndexed).OrganizationAddress; + organizationAddress.ShouldNotBeNull(); + + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var sideChainId = sideChainCreatedEvent.ChainId; - var createSideChainCreationInput = CreateSideChainCreationRequest(1, lockedTokenAmount, - GetValidResourceAmount(), new[] + { + var newIndexingFeePrice = 1; + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput { - new SideChainTokenInitialIssue - { - Address = DefaultSender, - Amount = 100 - } + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + 1 }); - var createProposal = await CreateParliamentProposalAsync( - nameof(CrossChainContractStub.RequestSideChainCreation), - organizationAddress, createSideChainCreationInput); - await ApproveWithMinersAsync(createProposal); - var release = await ReleaseProposalAsync(createProposal); - Assert.True(release.Status == TransactionResultStatus.Mined); - - var createSideChainProposalId = ProposalCreated.Parser - .ParseFrom(release.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; - await ApproveWithMinersAsync(createSideChainProposalId); - - var releaseInput = new ReleaseSideChainCreationInput {ProposalId = createSideChainProposalId}; - var releaseProposal = await CreateParliamentProposalAsync( - nameof(CrossChainContractStub.ReleaseSideChainCreation), - organizationAddress, releaseInput); - await ApproveWithMinersAsync(releaseProposal); - var releaseRelease = await ReleaseProposalAsync(releaseProposal); - Assert.True(releaseRelease.Status == TransactionResultStatus.Mined); - - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseRelease.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var chainId = sideChainCreatedEvent.ChainId; - var creator = sideChainCreatedEvent.Creator; - Assert.True(creator == organizationAddress); - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value {Value = chainId}); - Assert.True(chainStatus.Status == SideChainStatus.Active); + var parliamentOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + var txResult = + (await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId)) + .TransactionResult; + txResult.Error.ShouldContain("Side chain not found or incorrect side chain status."); } - [Fact] - public async Task CheckLockedBalance() { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var chainId = sideChainCreatedEvent.ChainId; - var balance = - (await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value {Value = chainId})) - .Value; - Assert.Equal(10, balance); - } + var newIndexingFeePrice = -1; + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); - [Fact] - public async Task CheckLockedBalance_NotExist() - { - var chainId = ChainHelper.GetChainId(1); + var parliamentOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); var txResult = - (await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value - {Value = chainId})) + (await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId)) .TransactionResult; - var status = txResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found.", txResult.Error); + txResult.Error.ShouldContain("Invalid side chain fee price."); } - [Fact] - public async Task GetLockedToken() { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + var newIndexingFeePrice = 2; + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); - var lockedToken = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value - { - Value = sideChainId - }); - Assert.True(lockedToken.Value == lockedTokenAmount); + var parliamentOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); + + var indexingFeePriceCheck = + await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value + { Value = sideChainId }); + indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); } + } - [Fact] - public async Task GetLockedToken_NotExist() + [Fact] + public async Task AdjustCrossChainIndexingFeePriceTest_IndexingFeeDebt_Dispose() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var organizationAddress = OrganizationCreated.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(OrganizationCreated))) + .NonIndexed).OrganizationAddress; + organizationAddress.ShouldNotBeNull(); + + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var sideChainId = sideChainCreatedEvent.ChainId; { - var sideChainId = ChainHelper.GetChainId(1); - var res = await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value - { - Value = sideChainId - }); + var newIndexingFeePrice = 10; + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); - Assert.True(res.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found.", res.TransactionResult.Error); + var parliamentOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); + + var indexingFeePriceCheck = + await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value + { Value = sideChainId }); + indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); + + var sideChainStatus = await GetSideChainStatusAsync(sideChainId); + sideChainStatus.ShouldBe(SideChainStatus.Active); } - [Fact] - public async Task GetSideChainBalance_DisposedChain() { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + var newIndexingFeePrice = 11; + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); - var proposalId = await DisposeSideChainProposalAsync(new Int32Value - { - Value = sideChainId - }); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); + var parliamentOrganizationAddress = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); - var res = await CrossChainContractStub.GetSideChainBalance.SendAsync(new Int32Value - { - Value = sideChainId - }); + (await CrossChainContractStub.GetSideChainIndexingFeePrice.CallWithExceptionAsync(new Int32Value + { Value = sideChainId + 1 })).Value.ShouldContain("Side chain not found."); - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Mined); - var actual = Int64Value.Parser.ParseFrom(res.TransactionResult.ReturnValue); - Assert.True(0 == actual.Value); - } + var indexingFeePriceCheck = + await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value + { Value = sideChainId }); + indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); - [Fact] - public async Task GetSideChainCreator() - { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + var sideChainStatus = await GetSideChainStatusAsync(sideChainId); + sideChainStatus.ShouldBe(SideChainStatus.Active); - (await CrossChainContractStub.GetSideChainCreator.CallWithExceptionAsync(new Int32Value - { - Value = 0 - })).Value.ShouldContain("Side chain not found."); - - var address = await CrossChainContractStub.GetSideChainCreator.CallAsync(new Int32Value + var disposalProposalId = await DisposeSideChainProposalAsync(new Int32Value { Value = sideChainId }); - - Assert.True(address == DefaultSender); + await ApproveWithMinersAsync(disposalProposalId); + var transactionResult = await ReleaseProposalAsync(disposalProposalId); + var status = transactionResult.Status; + status.ShouldBe(TransactionResultStatus.Mined); } + } - [Fact] - public async Task GetGetSideChainCreator_NotExist() - { - var sideChainId = ChainHelper.GetChainId(1); - var res = await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value + [Fact] + public async Task AdjustCrossChainIndexingFeePriceTest_AfterControllerChanged() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); + var sideChainCreationReleaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var organizationAddress = OrganizationCreated.Parser + .ParseFrom(sideChainCreationReleaseTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(OrganizationCreated))) + .NonIndexed).OrganizationAddress; + organizationAddress.ShouldNotBeNull(); + + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(sideChainCreationReleaseTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var sideChainId = sideChainCreatedEvent.ChainId; + + // change side chain lifetime controller + var newSideChainFeeControllerAddress = (await AssociationContractStub.CreateOrganization.SendAsync( + new Association.CreateOrganizationInput { - Value = sideChainId - }); - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found.", res.TransactionResult.Error); - } + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 0, + MaximalRejectionThreshold = 0, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { AnotherSenderAddress, DefaultSender } + }, + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { AnotherSenderAddress } + } + })).Output; + + var indexingController = + await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty()); - [Fact] - public async Task GetLockedAddress_DisposedChain() + (await CrossChainContractStub.GetSideChainIndexingFeeController.CallWithExceptionAsync(new Int32Value { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + Value = sideChainId + 1 + })).Value.ShouldContain("Side chain not found."); - var proposalId = await DisposeSideChainProposalAsync(new Int32Value + var oldSideChainFeeController = + await CrossChainContractStub.GetSideChainIndexingFeeController.CallAsync(new Int32Value { Value = sideChainId }); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); + var sideChainIndexingFeeControllerChangeProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.ChangeSideChainIndexingFeeController), + oldSideChainFeeController.OwnerAddress, CrossChainContractAddress, + new ChangeSideChainIndexingFeeControllerInput + { + ChainId = sideChainId, + AuthorityInfo = new AuthorityInfo + { + ContractAddress = AssociationContractAddress, + OwnerAddress = newSideChainFeeControllerAddress + } + }); + // creator approve + await AssociationContractStub.Approve.SendAsync(sideChainIndexingFeeControllerChangeProposalId); + + + var parliamentApprovalProposalId = await CreateParliamentProposalAsync( + nameof(AssociationContractStub.Approve), + indexingController.OwnerAddress, sideChainIndexingFeeControllerChangeProposalId + , AssociationContractAddress); + await ApproveWithMinersAsync(parliamentApprovalProposalId); + await ParliamentContractStub.Release.SendAsync(parliamentApprovalProposalId); + await AssociationContractStub.Release.SendAsync(sideChainIndexingFeeControllerChangeProposalId); - var res = await CrossChainContractStub.GetSideChainCreator.SendAsync(new Int32Value + var newSideChainFeeController = + await CrossChainContractStub.GetSideChainIndexingFeeController.CallAsync(new Int32Value { Value = sideChainId }); + newSideChainFeeController.OwnerAddress.ShouldBe(newSideChainFeeControllerAddress); - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Mined); - var actual = Address.Parser.ParseFrom(res.TransactionResult.ReturnValue); - Assert.Equal(DefaultSender, actual); + var newIndexingFeePrice = 2; + var crossChainIndexingController = + (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + { + // use old controller to create proposal + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + oldSideChainFeeController.OwnerAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); + + var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), + crossChainIndexingController, indexingFeeAdjustProposalId, AssociationContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + var releaseTx = + await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId); + releaseTx.TransactionResult.Error.ShouldContain("No permission."); } - [Fact] - public async Task RechargeForSideChain() { - var parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + // side chain fee adjustment proposal + var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( + nameof(CrossChainContractStub.AdjustIndexingFeePrice), + newSideChainFeeController.OwnerAddress, CrossChainContractAddress, + new AdjustIndexingFeeInput + { + IndexingFee = newIndexingFeePrice, + SideChainId = sideChainId + }); - var rechargeInput = new RechargeInput() - { - ChainId = sideChainId, - Amount = 100_000L - }; + // side chain creator creates proposal + var anotherSenderAssociationContractStub = GetAssociationContractStub(AnotherKeyPair); - //without enough token - var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Insufficient allowance", res.TransactionResult.Error); + // side chain lifetime controller approve + await anotherSenderAssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - //with enough token - await ApproveBalanceAsync(100_000L); - res = await CrossChainContractStub.Recharge.SendAsync(rechargeInput); - status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Mined); + // release + await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); + + var indexingFeePriceCheck = + await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value + { Value = sideChainId }); + indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); } + } - [Fact] - public async Task RechargeForSideChain_Terminated() - { - var parentChainId = 123; - var sideChainId = await InitAndCreateSideChainAsync(parentChainId); - await ApproveBalanceAsync(100_000L); + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + + var methodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); + const string proposalCreationMethodName = + nameof(CrossChainContractStub.ChangeMethodFeeController); + var proposalId = await CreateParliamentProposalAsync(proposalCreationMethodName, + methodFeeController.OwnerAddress, + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = await DisposeSideChainProposalAsync(new Int32Value {Value = sideChainId}); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); + var newMethodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } - var rechargeInput = new RechargeInput() - { - ChainId = sideChainId, - Amount = 100_000L - }; - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var methodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); + var result = await CrossChainContractStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo { - Value = sideChainId + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress }); - Assert.True(chainStatus.Status == SideChainStatus.Terminated); - var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found or incorrect side chain status.", res.TransactionResult.Error); - } + [Fact] + public async Task ChangeCrossChainMethodFee_Test() + { + await InitializeCrossChainContractAsync(); + var organizationAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var methodName = nameof(CrossChainContractStub.Recharge); + var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ToAddress = CrossChainContractAddress, + ContractMethodName = nameof(CrossChainContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + OrganizationAddress = organizationAddress, + Params = new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = "ELF", + BasicFee = 5000_0000L + } + } + }.ToByteString() + }); + var proposalId = proposal.Output; + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); - [Fact] - public async Task RechargeForSideChain_ChainNoExist() + var methodFee = await CrossChainContractStub.GetMethodFee.CallAsync(new StringValue { - var parentChainId = 123; - long lockedTokenAmount = 10; - await InitializeCrossChainContractAsync(parentChainId); + Value = methodName + }); + methodFee.MethodName.ShouldBe(methodName); + methodFee.Fees.First().ShouldBe(new MethodFee + { + Symbol = "ELF", + BasicFee = 5000_0000L + }); + } - await ApproveBalanceAsync(lockedTokenAmount); - var otherChainId = ChainHelper.GetChainId(5); - var rechargeInput = new RechargeInput() - { - ChainId = otherChainId, - Amount = 100_000L - }; - await ApproveBalanceAsync(100_000L); - var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + [Fact] + public async Task GetSideChainIdAndHeight_Test() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + + var sideChainIdAndHeight = await CrossChainContractStub.GetSideChainIdAndHeight.CallAsync(new Empty()); + sideChainIdAndHeight.IdHeightDict.Count.ShouldBe(1); + sideChainIdAndHeight.IdHeightDict.Keys.First().ShouldBe(sideChainId); + } - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found or incorrect side chain status.", res.TransactionResult.Error); - } + [Fact] + public async Task GetAllChainsIdAndHeight_Test() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + + var sideChainIdAndHeight = await CrossChainContractStub.GetAllChainsIdAndHeight.CallAsync(new Empty()); + sideChainIdAndHeight.IdHeightDict.Count.ShouldBe(2); + var chainIds = sideChainIdAndHeight.IdHeightDict.Keys; + chainIds.ShouldContain(parentChainId); + chainIds.ShouldContain(sideChainId); + } + + [Fact] + public async Task GetSideChainIndexingInformationList_Test() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); + + var sideChainIndexingInformationList = + await CrossChainContractStub.GetSideChainIndexingInformationList.CallAsync(new Empty()); + sideChainIndexingInformationList.IndexingInformationList.Count.ShouldBe(1); + var indexInfo = sideChainIndexingInformationList.IndexingInformationList.First(); + indexInfo.ChainId.ShouldBe(sideChainId); + indexInfo.IndexedHeight.ShouldBe(0); + } + + [Fact] + public async Task GetSideChainInitializationDataTest() + { + (await CrossChainContractStub.GetChainInitializationData.CallWithExceptionAsync(new Int32Value + { + Value = 0 + })).Value.ShouldContain("Side chain not found."); - [Fact] - public async Task DisposeSideChain() { long lockedTokenAmount = 10; - await InitializeCrossChainContractAsync(); - await ApproveBalanceAsync(lockedTokenAmount); - var chainId = await InitAndCreateSideChainAsync(withException: true); + await ApproveBalanceAsync(lockedTokenAmount * 2); + // Create proposal and approve + // var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); + var txResult = + await CreateSideChainAsync(true, 0, 0, lockedTokenAmount, 1, true); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(txResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); - { - // no permission - var disposeTx = - await CrossChainContractStub.DisposeSideChain.SendWithExceptionAsync(new Int32Value - {Value = chainId}); - disposeTx.TransactionResult.Error.ShouldContain("Unauthorized behavior."); - } - { - var proposalId = await DisposeSideChainProposalAsync(new Int32Value - { - Value = chainId - }); - await ApproveWithMinersAsync(proposalId); - var balanceBeforeDisposal = await GetBalance(DefaultSender); - var transactionResult = await ReleaseProposalAsync(proposalId); - var status = transactionResult.Status; - status.ShouldBe(TransactionResultStatus.Mined); - - var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value {Value = chainId}); - chainStatus.Status.ShouldBe(SideChainStatus.Terminated); - - var sideChainBalance = - await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value {Value = chainId}); - sideChainBalance.Value.ShouldBe(0); - - var balanceAfterDisposal = await GetBalance(DefaultSender); - balanceAfterDisposal.ShouldBe(balanceBeforeDisposal + lockedTokenAmount); - - // try to adjust indexing fee after disposal - var indexingFeeAdjustingTx = await CrossChainContractStub.AdjustIndexingFeePrice.SendWithExceptionAsync( - new AdjustIndexingFeeInput - { - SideChainId = chainId, - IndexingFee = lockedTokenAmount - 1 - }); - indexingFeeAdjustingTx.TransactionResult.Error.ShouldContain( - "Side chain not found or incorrect side chain status."); - } - - { - var proposalId = await DisposeSideChainProposalAsync(new Int32Value + var sideChainId = sideChainCreatedEvent.ChainId; + var chainInitializationData = + await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value { - Value = chainId + Value = sideChainId }); - await ApproveWithMinersAsync(proposalId); - var transactionResult = await ReleaseProposalWithExceptionAsync(proposalId); - transactionResult.Error.ShouldContain("Incorrect chain status."); - } + chainInitializationData.ShouldNotBeNull(); + chainInitializationData.Creator.ShouldBe(DefaultSender); + chainInitializationData.ChainId.ShouldBe(sideChainId); + chainInitializationData.CreationHeightOnParentChain.ShouldBe(txResult.BlockNumber); + chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeTrue(); + chainInitializationData.ParentChainTokenContractAddress.ShouldBe(TokenContractAddress); + TokenInfo.Parser.ParseFrom(chainInitializationData.NativeTokenInfoData).Symbol.ShouldBe("ELF"); + TokenInfo.Parser.ParseFrom(chainInitializationData.ChainPrimaryTokenInfo.ChainPrimaryTokenData).Symbol + .ShouldBe("TE"); + chainInitializationData.ResourceTokenInfo.ShouldNotBeNull(); } - [Fact] - public async Task DisposeSideChain_NotFound() { - await InitializeCrossChainContractAsync(); - var chainId = ChainHelper.GetChainId(1); - var proposalId = await DisposeSideChainProposalAsync(new Int32Value - { - Value = chainId - }); - await ApproveWithMinersAsync(proposalId); - var transactionResult = await ReleaseProposalWithExceptionAsync(proposalId); - var status = transactionResult.Status; + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount * 2); + // Create proposal and approve + var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); + var txResult = + await CreateSideChainAsync(false, 0, parentChainId, lockedTokenAmount, 1, false); - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found.", transactionResult.Error); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(txResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); + var sideChainId = sideChainCreatedEvent.ChainId; + var chainInitializationData = + await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value + { + Value = sideChainId + }); + chainInitializationData.ShouldNotBeNull(); + chainInitializationData.Creator.ShouldBe(DefaultSender); + chainInitializationData.ChainId.ShouldBe(sideChainId); + chainInitializationData.CreationHeightOnParentChain.ShouldBe(txResult.BlockNumber); + chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeFalse(); + chainInitializationData.ParentChainTokenContractAddress.ShouldBe(TokenContractAddress); + TokenInfo.Parser.ParseFrom(chainInitializationData.NativeTokenInfoData).Symbol.ShouldBe("ELF"); + chainInitializationData.ChainPrimaryTokenInfo.ShouldBeNull(); + chainInitializationData.ResourceTokenInfo.ShouldNotBeNull(); } + } - [Fact] - public async Task DisposeSideChain_Insufficient_Balance() - { - long lockedTokenAmount = 1; - await ApproveBalanceAsync(lockedTokenAmount); - var chainId = await InitAndCreateSideChainAsync(); - var proposalId1 = await DisposeSideChainProposalAsync(new Int32Value + [Fact] + public async Task SecondarySideChainCreationTest() + { + var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); + await InitializeCrossChainContractAsync(0, parentChainId); + + // initialize as side chain + var organizationAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateParliamentProposalAsync(nameof(TokenContractStub.InitializeFromParentChain), + organizationAddress, new InitializeFromParentChainInput { - Value = chainId - }); - await ApproveWithMinersAsync(proposalId1); - var transactionResult1 = await ReleaseProposalAsync(proposalId1); - var status1 = transactionResult1.Status; - Assert.True(status1 == TransactionResultStatus.Mined); + Creator = DefaultSender + }, TokenContractAddress); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); + + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + // Create proposal and approve + var sideChainCreationProposalId = + await CreateSideChainProposalAsync(1, lockedTokenAmount, null, null, true); + await ApproveWithMinersAsync(sideChainCreationProposalId); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = sideChainCreationProposalId }); + var sideChainCreatedEventFired = + releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(SideChainCreatedEvent))); + sideChainCreatedEventFired.ShouldBeTrue(); + + var tokenCreatedEventFired = + releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(TokenCreated))); + tokenCreatedEventFired.ShouldBeFalse(); + + var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(releaseTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); + + var sideChainId = sideChainCreatedEvent.ChainId; + var chainInitializationData = + await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value { Value = sideChainId }); + chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeTrue(); + chainInitializationData.ChainPrimaryTokenInfo.ShouldBeNull(); + } - var proposalId2 = await DisposeSideChainProposalAsync(new Int32Value - { - Value = chainId - }); - await ApproveWithMinersAsync(proposalId2); - var transactionResult2 = await ReleaseProposalWithExceptionAsync(proposalId2); - var status2 = transactionResult2.Status; - Assert.True(status2 == TransactionResultStatus.Failed); - Assert.Contains("Incorrect chain status.", transactionResult2.Error); + #region Side Chain Action + + [Fact] + public async Task Initialize_Test() + { + await InitializeCrossChainContractAsync(); + // initialize twice + await InitializeCrossChainContractAsync(0, 0, true); + } + + [Fact] + public async Task SetController_Test() + { + { + // no permission + var txResult = await CrossChainContractStub.SetInitialSideChainLifetimeControllerAddress + .SendWithExceptionAsync( + DefaultSender); + txResult.TransactionResult.Error.ShouldContain("No permission."); + } + { + // no permission + var txResult = await CrossChainContractStub.SetInitialIndexingControllerAddress.SendWithExceptionAsync( + DefaultSender); + txResult.TransactionResult.Error.ShouldContain("No permission."); } - [Fact] - public async Task GetChainStatus_NotExist() + await InitializeCrossChainContractAsync(); + { - var chainId = ChainHelper.GetChainId(1); - var res = await CrossChainContractStub.GetChainStatus.SendWithExceptionAsync(new Int32Value - {Value = chainId}); - var status = res.TransactionResult.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Side chain not found.", res.TransactionResult.Error); + // no permission + var txResult = await CrossChainContractStub.SetInitialSideChainLifetimeControllerAddress + .SendWithExceptionAsync( + DefaultSender); + txResult.TransactionResult.Error.ShouldContain("Already initialized."); + } + { + // no permission + var txResult = await CrossChainContractStub.SetInitialIndexingControllerAddress.SendWithExceptionAsync( + DefaultSender); + txResult.TransactionResult.Error.ShouldContain("Already initialized."); } + } - #endregion + [Fact] + public async Task Create_SideChain() + { + await InitializeCrossChainContractAsync(); - [Fact] - public async Task ChangeIndexingController() { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; + // not PrivilegeReserved - var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 3333, - MaximalRejectionThreshold = 3333, - MinimalApprovalThreshold = 3333, - MinimalVoteThreshold = 3333 - }, - ParliamentMemberProposingAllowed = true - })).Output; - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + // Create proposal and approve + var proposalId = await CreateSideChainProposalAsync(0, 0); + + await CrossChainContractStub.ReleaseSideChainCreation.SendWithExceptionAsync( + new ReleaseSideChainCreationInput + { ProposalId = proposalId }); - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendAsync(proposalId)).TransactionResult; - releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); - var crossChainIndexingController = - await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty()); - crossChainIndexingController.ContractAddress.ShouldBe(ParliamentContractAddress); - crossChainIndexingController.OwnerAddress.ShouldBe(newOrganizationAddress); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var chainId = sideChainCreatedEvent.ChainId; + var creator = sideChainCreatedEvent.Creator; + creator.ShouldBe(DefaultSender); + + var chainStatus = + await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { Value = chainId }); + chainStatus.Status.ShouldBe(SideChainStatus.Active); + + releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(TokenCreated))).ShouldBeFalse(); } - [Fact] - public async Task ChangeIndexingController_InvalidOwnerAddress() { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, OwnerAddress = DefaultSender - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + // PrivilegeReserved + + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + var proposalId = + await CreateSideChainProposalAsync(1, lockedTokenAmount, null, GetValidResourceAmount(), true); - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) - .TransactionResult; - releaseResult.Error.ShouldContain("Invalid authority input."); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var tokenCreatedEvent = TokenCreated.Parser + .ParseFrom(releaseTx.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(TokenCreated))) + .NonIndexed); + tokenCreatedEvent.Symbol.ShouldBe("TE"); } + } + [Fact] + public async Task Release_SideChain_Expired() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); - [Fact] - public async Task ChangeIndexingController_NotAuthorized() - { - await InitializeCrossChainContractAsync(); - var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 3333, - MaximalRejectionThreshold = 3333, - MinimalApprovalThreshold = 3333, - MinimalVoteThreshold = 3333 - } - })).Output; + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); - var res = - (await CrossChainContractStub.ChangeCrossChainIndexingController.SendWithExceptionAsync( - new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress - })).TransactionResult; + // Create proposal and approve + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); - var status = res.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Unauthorized behavior.", res.Error); + BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); + { + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .ShouldBeFalse(); } + } - [Fact] - public async Task ChangeIndexingController_InvalidOrganization() - { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - + [Fact] + public async Task RequestSideChainCreation_Twice() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount - 1, lockedTokenAmount, + GetValidResourceAmount(), new[] { - var newOrganizationCreationInput = new Association.CreateOrganizationInput + new SideChainTokenInitialIssue { - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {DefaultSender} - }, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {DefaultSender} - } - }; - var newOrganizationAddress = - (await AssociationContractStub.CreateOrganization.SendAsync(newOrganizationCreationInput)).Output; - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo - { - ContractAddress = AssociationContractAddress, OwnerAddress = newOrganizationAddress - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + Address = DefaultSender, + Amount = 100 + } + }); + await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) - .TransactionResult; - releaseResult.Error.ShouldContain("Invalid authority input."); - } + BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86399)); + var secondRequestTx = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); + secondRequestTx.TransactionResult.Error.ShouldContain("Request side chain creation failed."); - { - var newParliamentOrganizationCreationInput = new CreateOrganizationInput - { - ParliamentMemberProposingAllowed = false, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1, - MaximalRejectionThreshold = 0, - MaximalAbstentionThreshold = 0 - }, - ProposerAuthorityRequired = true - }; - var newOrganizationAddress = - (await ParliamentContractStub.CreateOrganization.SendAsync(newParliamentOrganizationCreationInput)) - .Output; - - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeCrossChainIndexingController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); + var thirdRequestTx = await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); + thirdRequestTx.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) - .TransactionResult; - releaseResult.Error.ShouldContain("Invalid authority input."); - } + [Fact] + public async Task RequestSideChainCreationSecondTimeAfterRelease() + { + await InitializeCrossChainContractAsync(); + { + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + // Create proposal and approve + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); } - [Fact] - public async Task ChangeSideChainLifeTimeController() { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + proposalId.ShouldNotBeNull(); + } + } - var newOrganizationAddress = (await AssociationContractStub.CreateOrganization.SendAsync( - new Association.CreateOrganizationInput + [Fact] + public async Task RequestSideChainCreation_Failed() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + + { + var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount - 1, lockedTokenAmount, + GetValidResourceAmount(), new[] { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 0, - MaximalRejectionThreshold = 0, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {DefaultSender} - }, - OrganizationMemberList = new OrganizationMemberList + new SideChainTokenInitialIssue { - OrganizationMembers = {DefaultSender} + Address = DefaultSender, + Amount = 100 } - })).Output; + }); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo - { - ContractAddress = AssociationContractAddress, OwnerAddress = newOrganizationAddress - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + requestSideChainCreation.TransactionResult.Error.ShouldContain("Allowance not enough"); + } - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendAsync(proposalId)).TransactionResult; - releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); + await ApproveBalanceAsync(lockedTokenAmount); + + { + var createProposalInput = CreateSideChainCreationRequest(10, 0, GetValidResourceAmount(), + new[] + { + new SideChainTokenInitialIssue + { + Address = DefaultSender, + Amount = 100 + } + }, true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - var sideChainLifetimeController = - await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty()); - sideChainLifetimeController.ContractAddress.ShouldBe(AssociationContractAddress); - sideChainLifetimeController.OwnerAddress.ShouldBe(newOrganizationAddress); + requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + requestSideChainCreation.TransactionResult.Error.ShouldContain("Invalid chain creation request."); } - [Fact] - public async Task ChangeSideChainLifeTimeController_Failed() { - await InitializeCrossChainContractAsync(); - var oldOrganizationAddress = - (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; - - { - // invalid new owner address - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + var createProposalInput = CreateSideChainCreationRequest(-1, 10, GetValidResourceAmount(), + new[] { - ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo + new SideChainTokenInitialIssue { - ContractAddress = ParliamentContractAddress, OwnerAddress = DefaultSender - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + Address = DefaultSender, + Amount = 100 + } + }, true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) - .TransactionResult; - releaseResult.Error.ShouldContain("Invalid authority input."); - } + requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + requestSideChainCreation.TransactionResult.Error.ShouldContain("Invalid chain creation request."); + } + { + foreach (var t in ResourceTokenSymbolList) { - // wrong authorization contract address - var proposalRes = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(CrossChainContractStub.ChangeSideChainLifetimeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new AuthorityInfo + // invalid resource token + var resourceAmount = GetValidResourceAmount(); + resourceAmount.Remove(t); + var createProposalInput = CreateSideChainCreationRequest(1, lockedTokenAmount, + resourceAmount, new[] { - ContractAddress = AssociationContractAddress, OwnerAddress = oldOrganizationAddress - }.ToByteString(), - ToAddress = CrossChainContractAddress, - OrganizationAddress = oldOrganizationAddress - }); + new SideChainTokenInitialIssue + { + Address = DefaultSender, + Amount = 100 + } + }, true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync( + createProposalInput); - var proposalId = Hash.Parser.ParseFrom(proposalRes.TransactionResult.ReturnValue); - await ApproveWithMinersAsync(proposalId); - var releaseResult = (await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId)) - .TransactionResult; - releaseResult.Error.ShouldContain("Invalid authority input."); + requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + requestSideChainCreation.TransactionResult.Error.ShouldContain( + "Invalid side chain resource token request."); } + foreach (var t in ResourceTokenSymbolList) { - // no proposal created - var newOrganizationAddress = (await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput + // invalid resource token + var resourceAmount = GetValidResourceAmount(); + resourceAmount[t] = 0; + var createProposalInput = CreateSideChainCreationRequest(1, lockedTokenAmount, + resourceAmount, new[] { - ProposalReleaseThreshold = new ProposalReleaseThreshold + new SideChainTokenInitialIssue { - MaximalAbstentionThreshold = 3333, - MaximalRejectionThreshold = 3333, - MinimalApprovalThreshold = 3333, - MinimalVoteThreshold = 3333 + Address = DefaultSender, + Amount = 100 } - })).Output; - - var res = - (await CrossChainContractStub.ChangeSideChainLifetimeController.SendWithExceptionAsync( - new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, OwnerAddress = newOrganizationAddress - })).TransactionResult; + }, true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync( + createProposalInput); - var status = res.Status; - Assert.True(status == TransactionResultStatus.Failed); - Assert.Contains("Unauthorized behavior.", res.Error); + requestSideChainCreation.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); } } - [Fact] - public async Task AdjustCrossChainIndexingFeePriceTest() { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var organizationAddress = OrganizationCreated.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(OrganizationCreated))) - .NonIndexed).OrganizationAddress; - organizationAddress.ShouldNotBeNull(); - - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var sideChainId = sideChainCreatedEvent.ChainId; + var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount, lockedTokenAmount, + GetValidResourceAmount(), new SideChainTokenInitialIssue[0], true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendWithExceptionAsync(createProposalInput); + requestSideChainCreation.TransactionResult.Error.ShouldContain( + "Invalid side chain token initial issue list."); + } - { - var newIndexingFeePrice = 1; - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId + 1 - }); - - var parliamentOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - var txResult = - (await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId)) - .TransactionResult; - txResult.Error.ShouldContain("Side chain not found or incorrect side chain status."); - } - - { - var newIndexingFeePrice = -1; - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); - - var parliamentOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - var txResult = - (await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId)) - .TransactionResult; - txResult.Error.ShouldContain("Invalid side chain fee price."); - } + var utcNow = TimestampHelper.GetUtcNow(); - { - var newIndexingFeePrice = 2; - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput + BlockTimeProvider.SetBlockTime(utcNow); + { + var createProposalInput = CreateSideChainCreationRequest(lockedTokenAmount, lockedTokenAmount, + GetValidResourceAmount(), new[] + { + new SideChainTokenInitialIssue { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); - - var parliamentOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); - - var indexingFeePriceCheck = - await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value() - {Value = sideChainId}); - indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); - } + Address = DefaultSender, + Amount = 100 + } + }, true); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); } - [Fact] - public async Task AdjustCrossChainIndexingFeePriceTest_IndexingFeeDebt_Dispose() + BlockTimeProvider.SetBlockTime(utcNow.AddSeconds(86400)); { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); - - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var organizationAddress = OrganizationCreated.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(OrganizationCreated))) - .NonIndexed).OrganizationAddress; - organizationAddress.ShouldNotBeNull(); - - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var sideChainId = sideChainCreatedEvent.ChainId; - { - var newIndexingFeePrice = 10; - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); - - var parliamentOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); - - var indexingFeePriceCheck = - await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value() - {Value = sideChainId}); - indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); - - var sideChainStatus = await GetSideChainStatusAsync(sideChainId); - sideChainStatus.ShouldBe(SideChainStatus.Active); - } - - { - var newIndexingFeePrice = 11; - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - organizationAddress, CrossChainContractAddress, new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); - - var parliamentOrganizationAddress = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - parliamentOrganizationAddress, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); - - (await CrossChainContractStub.GetSideChainIndexingFeePrice.CallWithExceptionAsync(new Int32Value() - {Value = sideChainId + 1})).Value.ShouldContain("Side chain not found."); - - var indexingFeePriceCheck = - await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value() - {Value = sideChainId}); - indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); - - var sideChainStatus = await GetSideChainStatusAsync(sideChainId); - sideChainStatus.ShouldBe(SideChainStatus.Active); - - var disposalProposalId = await DisposeSideChainProposalAsync(new Int32Value - { - Value = sideChainId - }); - await ApproveWithMinersAsync(disposalProposalId); - var transactionResult = await ReleaseProposalAsync(disposalProposalId); - var status = transactionResult.Status; - status.ShouldBe(TransactionResultStatus.Mined); - } + var createProposalInput = CreateSideChainCreationRequest(0, 0, + new Dictionary(), new SideChainTokenInitialIssue[0]); + var requestSideChainCreation = + await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); } + } - [Fact] - public async Task AdjustCrossChainIndexingFeePriceTest_AfterControllerChanged() + [Fact] + public async Task CreateSideChainCreation_WithoutRequest() + { + await InitializeCrossChainContractAsync(); + var oldOrganizationAddress = + (await CrossChainContractStub.GetSideChainLifetimeController.CallAsync(new Empty())).OwnerAddress; + var proposalCreation = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - await InitializeCrossChainContractAsync(); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); + ContractMethodName = nameof(CrossChainContractStub.CreateSideChain), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + OrganizationAddress = oldOrganizationAddress, + ToAddress = CrossChainContractAddress, + Params = new CreateSideChainInput + { + Proposer = DefaultSender, + SideChainCreationRequest = new SideChainCreationRequest + { + IndexingPrice = 1, + LockedTokenAmount = 10, + SideChainTokenCreationRequest = new SideChainTokenCreationRequest + { + SideChainTokenDecimals = 2, + SideChainTokenTotalSupply = 1_000_000_000, + SideChainTokenSymbol = "TE", + SideChainTokenName = "TEST" + } + } + }.ToByteString() + }); + var proposalId = ProposalCreated.Parser.ParseFrom(proposalCreation.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + await ApproveWithMinersAsync(proposalId); + var proposalRelease = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + proposalRelease.TransactionResult.Error.ShouldContain("Side chain creation failed without proposed data."); + } - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); - await ApproveWithMinersAsync(proposalId); - var sideChainCreationReleaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var organizationAddress = OrganizationCreated.Parser - .ParseFrom(sideChainCreationReleaseTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(OrganizationCreated))) - .NonIndexed).OrganizationAddress; - organizationAddress.ShouldNotBeNull(); + [Fact] + public async Task ReleaseSideChainCreation_WithoutRequest() + { + await InitializeCrossChainContractAsync(); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendWithExceptionAsync( + new ReleaseSideChainCreationInput + { ProposalId = Hash.Empty }); + releaseTx.TransactionResult.Error.ShouldContain("Release side chain creation failed."); + } - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(sideChainCreationReleaseTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var sideChainId = sideChainCreatedEvent.ChainId; + [Fact] + public async Task Create_SideChain_NotAuthorized() + { + long lockedTokenAmount = 10; + await InitializeCrossChainContractAsync(); + await ApproveBalanceAsync(lockedTokenAmount); - // change side chain lifetime controller - var newSideChainFeeControllerAddress = (await AssociationContractStub.CreateOrganization.SendAsync( - new Association.CreateOrganizationInput + var sideChainCreationRequest = CreateSideChainCreationRequest(1, lockedTokenAmount, + GetValidResourceAmount(), new[] + { + new SideChainTokenInitialIssue { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 0, - MaximalRejectionThreshold = 0, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {AnotherSenderAddress, DefaultSender} - }, - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {AnotherSenderAddress} - } - })).Output; + Address = DefaultSender, + Amount = 100 + } + }); + var result = await CrossChainContractStub.CreateSideChain.SendWithExceptionAsync(new CreateSideChainInput + { + SideChainCreationRequest = sideChainCreationRequest, + Proposer = DefaultSender + } + ); + var status = result.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Unauthorized behavior.", result.TransactionResult.Error); + } - var indexingController = - await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty()); + [Fact] + public async Task CreatSideChain_ByOrganization() + { + long lockedTokenAmount = 10; + await InitializeCrossChainContractAsync(); - (await CrossChainContractStub.GetSideChainIndexingFeeController.CallWithExceptionAsync(new Int32Value + var organizationAddress = + (await ParliamentContractStub.CreateOrganization.SendAsync(new CreateOrganizationInput { - Value = sideChainId + 1 - })).Value.ShouldContain("Side chain not found."); - - var oldSideChainFeeController = - await CrossChainContractStub.GetSideChainIndexingFeeController.CallAsync(new Int32Value + ProposalReleaseThreshold = new ProposalReleaseThreshold { - Value = sideChainId - }); - var sideChainIndexingFeeControllerChangeProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.ChangeSideChainIndexingFeeController), - oldSideChainFeeController.OwnerAddress, CrossChainContractAddress, - new ChangeSideChainIndexingFeeControllerInput + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = true + })).Output; + var allowanceResult = + await ApproveAndTransferOrganizationBalanceAsync(organizationAddress, lockedTokenAmount); + Assert.True(allowanceResult.Spender == CrossChainContractAddress); + Assert.True(allowanceResult.Allowance == lockedTokenAmount); + + var createSideChainCreationInput = CreateSideChainCreationRequest(1, lockedTokenAmount, + GetValidResourceAmount(), new[] + { + new SideChainTokenInitialIssue { - ChainId = sideChainId, - AuthorityInfo = new AuthorityInfo - { - ContractAddress = AssociationContractAddress, - OwnerAddress = newSideChainFeeControllerAddress - } - }); - // creator approve - await AssociationContractStub.Approve.SendAsync(sideChainIndexingFeeControllerChangeProposalId); - + Address = DefaultSender, + Amount = 100 + } + }); + var createProposal = await CreateParliamentProposalAsync( + nameof(CrossChainContractStub.RequestSideChainCreation), + organizationAddress, createSideChainCreationInput); + await ApproveWithMinersAsync(createProposal); + var release = await ReleaseProposalAsync(createProposal); + Assert.True(release.Status == TransactionResultStatus.Mined); + + var createSideChainProposalId = ProposalCreated.Parser + .ParseFrom(release.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + await ApproveWithMinersAsync(createSideChainProposalId); + + var releaseInput = new ReleaseSideChainCreationInput { ProposalId = createSideChainProposalId }; + var releaseProposal = await CreateParliamentProposalAsync( + nameof(CrossChainContractStub.ReleaseSideChainCreation), + organizationAddress, releaseInput); + await ApproveWithMinersAsync(releaseProposal); + var releaseRelease = await ReleaseProposalAsync(releaseProposal); + Assert.True(releaseRelease.Status == TransactionResultStatus.Mined); + + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseRelease.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var chainId = sideChainCreatedEvent.ChainId; + var creator = sideChainCreatedEvent.Creator; + Assert.True(creator == organizationAddress); + + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { Value = chainId }); + Assert.True(chainStatus.Status == SideChainStatus.Active); + } - var parliamentApprovalProposalId = await CreateParliamentProposalAsync( - nameof(AssociationContractStub.Approve), - indexingController.OwnerAddress, sideChainIndexingFeeControllerChangeProposalId - , AssociationContractAddress); - await ApproveWithMinersAsync(parliamentApprovalProposalId); - await ParliamentContractStub.Release.SendAsync(parliamentApprovalProposalId); - await AssociationContractStub.Release.SendAsync(sideChainIndexingFeeControllerChangeProposalId); + [Fact] + public async Task CheckLockedBalance() + { + await InitializeCrossChainContractAsync(); + long lockedTokenAmount = 10; + await ApproveBalanceAsync(lockedTokenAmount); + + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount); + await ApproveWithMinersAsync(proposalId); + var releaseTx = + await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseTx.TransactionResult.Logs.First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var chainId = sideChainCreatedEvent.ChainId; + var balance = + (await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value { Value = chainId })) + .Value; + Assert.Equal(10, balance); + } - var newSideChainFeeController = - await CrossChainContractStub.GetSideChainIndexingFeeController.CallAsync(new Int32Value - { - Value = sideChainId - }); - newSideChainFeeController.OwnerAddress.ShouldBe(newSideChainFeeControllerAddress); + [Fact] + public async Task CheckLockedBalance_NotExist() + { + var chainId = ChainHelper.GetChainId(1); + var txResult = + (await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value + { Value = chainId })) + .TransactionResult; + var status = txResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found.", txResult.Error); + } - var newIndexingFeePrice = 2; - var crossChainIndexingController = - (await CrossChainContractStub.GetCrossChainIndexingController.CallAsync(new Empty())).OwnerAddress; - { - // use old controller to create proposal - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - oldSideChainFeeController.OwnerAddress, CrossChainContractAddress, new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); - - var approveProposalId = await CreateParliamentProposalAsync(nameof(AssociationContractStub.Approve), - crossChainIndexingController, indexingFeeAdjustProposalId, AssociationContractAddress); - await ApproveWithMinersAsync(approveProposalId); - await ParliamentContractStub.Release.SendAsync(approveProposalId); - await AssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); - var releaseTx = - await AssociationContractStub.Release.SendWithExceptionAsync(indexingFeeAdjustProposalId); - releaseTx.TransactionResult.Error.ShouldContain("No permission."); - } + [Fact] + public async Task GetLockedToken() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - { - // side chain fee adjustment proposal - var indexingFeeAdjustProposalId = await CreateAssociationProposalAsync( - nameof(CrossChainContractStub.AdjustIndexingFeePrice), - newSideChainFeeController.OwnerAddress, CrossChainContractAddress, - new AdjustIndexingFeeInput - { - IndexingFee = newIndexingFeePrice, - SideChainId = sideChainId - }); + var lockedToken = await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value + { + Value = sideChainId + }); + Assert.True(lockedToken.Value == lockedTokenAmount); + } - // side chain creator creates proposal - var anotherSenderAssociationContractStub = GetAssociationContractStub(AnotherKeyPair); + [Fact] + public async Task GetLockedToken_NotExist() + { + var sideChainId = ChainHelper.GetChainId(1); + var res = await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value + { + Value = sideChainId + }); - // side chain lifetime controller approve - await anotherSenderAssociationContractStub.Approve.SendAsync(indexingFeeAdjustProposalId); + Assert.True(res.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found.", res.TransactionResult.Error); + } - // release - await AssociationContractStub.Release.SendAsync(indexingFeeAdjustProposalId); + [Fact] + public async Task GetSideChainBalance_DisposedChain() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - var indexingFeePriceCheck = - await CrossChainContractStub.GetSideChainIndexingFeePrice.SendAsync(new Int32Value() - {Value = sideChainId}); - indexingFeePriceCheck.Output.Value.ShouldBe(newIndexingFeePrice); - } - } + var proposalId = await DisposeSideChainProposalAsync(new Int32Value + { + Value = sideChainId + }); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); - [Fact] - public async Task ChangeMethodFeeController_Test() + var res = await CrossChainContractStub.GetSideChainBalance.SendAsync(new Int32Value { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); - const string proposalCreationMethodName = - nameof(CrossChainContractStub.ChangeMethodFeeController); - var proposalId = await CreateParliamentProposalAsync(proposalCreationMethodName, - methodFeeController.OwnerAddress, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Value = sideChainId + }); - var newMethodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); - } + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Mined); + var actual = Int64Value.Parser.ParseFrom(res.TransactionResult.ReturnValue); + Assert.True(0 == actual.Value); + } + + [Fact] + public async Task GetSideChainCreator() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() + (await CrossChainContractStub.GetSideChainCreator.CallWithExceptionAsync(new Int32Value { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var methodFeeController = await CrossChainContractStub.GetMethodFeeController.CallAsync(new Empty()); - var result = await CrossChainContractStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); + Value = 0 + })).Value.ShouldContain("Side chain not found."); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + var address = await CrossChainContractStub.GetSideChainCreator.CallAsync(new Int32Value + { + Value = sideChainId + }); + + Assert.True(address == DefaultSender); + } - [Fact] - public async Task ChangeCrossChainMethodFee_Test() + [Fact] + public async Task GetGetSideChainCreator_NotExist() + { + var sideChainId = ChainHelper.GetChainId(1); + var res = await CrossChainContractStub.GetSideChainBalance.SendWithExceptionAsync(new Int32Value { - await InitializeCrossChainContractAsync(); - var organizationAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var methodName = nameof(CrossChainContractStub.Recharge); - var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ToAddress = CrossChainContractAddress, - ContractMethodName = nameof(CrossChainContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - OrganizationAddress = organizationAddress, - Params = new MethodFees - { - MethodName = methodName, - Fees = - { - new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - } - } - }.ToByteString() - }); - var proposalId = proposal.Output; - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); + Value = sideChainId + }); + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found.", res.TransactionResult.Error); + } - var methodFee = await CrossChainContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName - }); - methodFee.MethodName.ShouldBe(methodName); - methodFee.Fees.First().ShouldBe(new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - }); - } + [Fact] + public async Task GetLockedAddress_DisposedChain() + { + var parentChainId = 123; + var lockedTokenAmount = 10L; + long parentChainHeightOfCreation = 10; + var sideChainId = + await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - [Fact] - public async Task GetSideChainIdAndHeight_Test() + var proposalId = await DisposeSideChainProposalAsync(new Int32Value { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - - var sideChainIdAndHeight = await CrossChainContractStub.GetSideChainIdAndHeight.CallAsync(new Empty()); - sideChainIdAndHeight.IdHeightDict.Count.ShouldBe(1); - sideChainIdAndHeight.IdHeightDict.Keys.First().ShouldBe(sideChainId); - } + Value = sideChainId + }); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); - [Fact] - public async Task GetAllChainsIdAndHeight_Test() + var res = await CrossChainContractStub.GetSideChainCreator.SendAsync(new Int32Value { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - - var sideChainIdAndHeight = await CrossChainContractStub.GetAllChainsIdAndHeight.CallAsync(new Empty()); - sideChainIdAndHeight.IdHeightDict.Count.ShouldBe(2); - var chainIds = sideChainIdAndHeight.IdHeightDict.Keys; - chainIds.ShouldContain(parentChainId); - chainIds.ShouldContain(sideChainId); - } + Value = sideChainId + }); + + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Mined); + var actual = Address.Parser.ParseFrom(res.TransactionResult.ReturnValue); + Assert.Equal(DefaultSender, actual); + } + + [Fact] + public async Task RechargeForSideChain() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); - [Fact] - public async Task GetSideChainIndexingInformationList_Test() + var rechargeInput = new RechargeInput { - var parentChainId = 123; - var lockedTokenAmount = 10L; - long parentChainHeightOfCreation = 10; - var sideChainId = - await InitAndCreateSideChainAsync(parentChainHeightOfCreation, parentChainId, lockedTokenAmount); - - var sideChainIndexingInformationList = - await CrossChainContractStub.GetSideChainIndexingInformationList.CallAsync(new Empty()); - sideChainIndexingInformationList.IndexingInformationList.Count.ShouldBe(1); - var indexInfo = sideChainIndexingInformationList.IndexingInformationList.First(); - indexInfo.ChainId.ShouldBe(sideChainId); - indexInfo.IndexedHeight.ShouldBe(0); - } + ChainId = sideChainId, + Amount = 100_000L + }; + + //without enough token + var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Insufficient allowance", res.TransactionResult.Error); + + //with enough token + await ApproveBalanceAsync(100_000L); + res = await CrossChainContractStub.Recharge.SendAsync(rechargeInput); + status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Mined); + } + + [Fact] + public async Task RechargeForSideChain_Terminated() + { + var parentChainId = 123; + var sideChainId = await InitAndCreateSideChainAsync(parentChainId); + await ApproveBalanceAsync(100_000L); - [Fact] - public async Task GetSideChainInitializationDataTest() + var proposalId = await DisposeSideChainProposalAsync(new Int32Value { Value = sideChainId }); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); + + var rechargeInput = new RechargeInput { - (await CrossChainContractStub.GetChainInitializationData.CallWithExceptionAsync(new Int32Value - { - Value = 0 - })).Value.ShouldContain("Side chain not found."); - - { - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount * 2); - // Create proposal and approve - // var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - var txResult = - await CreateSideChainAsync(true, 0, 0, lockedTokenAmount, 1, true); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(txResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); - - var sideChainId = sideChainCreatedEvent.ChainId; - var chainInitializationData = - await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainInitializationData.ShouldNotBeNull(); - chainInitializationData.Creator.ShouldBe(DefaultSender); - chainInitializationData.ChainId.ShouldBe(sideChainId); - chainInitializationData.CreationHeightOnParentChain.ShouldBe(txResult.BlockNumber); - chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeTrue(); - chainInitializationData.ParentChainTokenContractAddress.ShouldBe(TokenContractAddress); - TokenInfo.Parser.ParseFrom(chainInitializationData.NativeTokenInfoData).Symbol.ShouldBe("ELF"); - TokenInfo.Parser.ParseFrom(chainInitializationData.ChainPrimaryTokenInfo.ChainPrimaryTokenData).Symbol - .ShouldBe("TE"); - chainInitializationData.ResourceTokenInfo.ShouldNotBeNull(); - } + ChainId = sideChainId, + Amount = 100_000L + }; + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value + { + Value = sideChainId + }); - { - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount * 2); - // Create proposal and approve - var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - var txResult = - await CreateSideChainAsync(false, 0, parentChainId, lockedTokenAmount, 1, false); - - var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(txResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); - var sideChainId = sideChainCreatedEvent.ChainId; - var chainInitializationData = - await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value - { - Value = sideChainId - }); - chainInitializationData.ShouldNotBeNull(); - chainInitializationData.Creator.ShouldBe(DefaultSender); - chainInitializationData.ChainId.ShouldBe(sideChainId); - chainInitializationData.CreationHeightOnParentChain.ShouldBe(txResult.BlockNumber); - chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeFalse(); - chainInitializationData.ParentChainTokenContractAddress.ShouldBe(TokenContractAddress); - TokenInfo.Parser.ParseFrom(chainInitializationData.NativeTokenInfoData).Symbol.ShouldBe("ELF"); - chainInitializationData.ChainPrimaryTokenInfo.ShouldBeNull(); - chainInitializationData.ResourceTokenInfo.ShouldNotBeNull(); - } - } + Assert.True(chainStatus.Status == SideChainStatus.Terminated); + var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found or incorrect side chain status.", res.TransactionResult.Error); + } - [Fact] - public async Task SecondarySideChainCreationTest() + [Fact] + public async Task RechargeForSideChain_ChainNoExist() + { + var parentChainId = 123; + long lockedTokenAmount = 10; + await InitializeCrossChainContractAsync(parentChainId); + + await ApproveBalanceAsync(lockedTokenAmount); + var otherChainId = ChainHelper.GetChainId(5); + var rechargeInput = new RechargeInput { - var parentChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - await InitializeCrossChainContractAsync(0, parentChainId); + ChainId = otherChainId, + Amount = 100_000L + }; + await ApproveBalanceAsync(100_000L); + var res = await CrossChainContractStub.Recharge.SendWithExceptionAsync(rechargeInput); + + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found or incorrect side chain status.", res.TransactionResult.Error); + } - // initialize as side chain - var organizationAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateParliamentProposalAsync(nameof(TokenContractStub.InitializeFromParentChain), - organizationAddress, new InitializeFromParentChainInput - { - Creator = DefaultSender - }, TokenContractAddress); + [Fact] + public async Task DisposeSideChain() + { + long lockedTokenAmount = 10; + await InitializeCrossChainContractAsync(); + await ApproveBalanceAsync(lockedTokenAmount); + var chainId = await InitAndCreateSideChainAsync(withException: true); + + { + // no permission + var disposeTx = + await CrossChainContractStub.DisposeSideChain.SendWithExceptionAsync(new Int32Value + { Value = chainId }); + disposeTx.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + } + { + var proposalId = await DisposeSideChainProposalAsync(new Int32Value + { + Value = chainId + }); await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); + var balanceBeforeDisposal = await GetBalance(DefaultSender); + var transactionResult = await ReleaseProposalAsync(proposalId); + var status = transactionResult.Status; + status.ShouldBe(TransactionResultStatus.Mined); - long lockedTokenAmount = 10; - await ApproveBalanceAsync(lockedTokenAmount); + var chainStatus = await CrossChainContractStub.GetChainStatus.CallAsync(new Int32Value { Value = chainId }); + chainStatus.Status.ShouldBe(SideChainStatus.Terminated); - // Create proposal and approve - var sideChainCreationProposalId = - await CreateSideChainProposalAsync(1, lockedTokenAmount, null, null, true); - await ApproveWithMinersAsync(sideChainCreationProposalId); - var releaseTx = - await CrossChainContractStub.ReleaseSideChainCreation.SendAsync(new ReleaseSideChainCreationInput - {ProposalId = sideChainCreationProposalId}); - var sideChainCreatedEventFired = - releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(SideChainCreatedEvent))); - sideChainCreatedEventFired.ShouldBeTrue(); + var sideChainBalance = + await CrossChainContractStub.GetSideChainBalance.CallAsync(new Int32Value { Value = chainId }); + sideChainBalance.Value.ShouldBe(0); - var tokenCreatedEventFired = - releaseTx.TransactionResult.Logs.Any(l => l.Name.Contains(nameof(TokenCreated))); - tokenCreatedEventFired.ShouldBeFalse(); + var balanceAfterDisposal = await GetBalance(DefaultSender); + balanceAfterDisposal.ShouldBe(balanceBeforeDisposal + lockedTokenAmount); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser.ParseFrom(releaseTx.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))).NonIndexed); + // try to adjust indexing fee after disposal + var indexingFeeAdjustingTx = await CrossChainContractStub.AdjustIndexingFeePrice.SendWithExceptionAsync( + new AdjustIndexingFeeInput + { + SideChainId = chainId, + IndexingFee = lockedTokenAmount - 1 + }); + indexingFeeAdjustingTx.TransactionResult.Error.ShouldContain( + "Side chain not found or incorrect side chain status."); + } - var sideChainId = sideChainCreatedEvent.ChainId; - var chainInitializationData = - await CrossChainContractStub.GetChainInitializationData.CallAsync(new Int32Value {Value = sideChainId}); - chainInitializationData.ChainCreatorPrivilegePreserved.ShouldBeTrue(); - chainInitializationData.ChainPrimaryTokenInfo.ShouldBeNull(); + { + var proposalId = await DisposeSideChainProposalAsync(new Int32Value + { + Value = chainId + }); + await ApproveWithMinersAsync(proposalId); + var transactionResult = await ReleaseProposalWithExceptionAsync(proposalId); + transactionResult.Error.ShouldContain("Incorrect chain status."); } } + + [Fact] + public async Task DisposeSideChain_NotFound() + { + await InitializeCrossChainContractAsync(); + var chainId = ChainHelper.GetChainId(1); + var proposalId = await DisposeSideChainProposalAsync(new Int32Value + { + Value = chainId + }); + await ApproveWithMinersAsync(proposalId); + var transactionResult = await ReleaseProposalWithExceptionAsync(proposalId); + var status = transactionResult.Status; + + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found.", transactionResult.Error); + } + + [Fact] + public async Task DisposeSideChain_Insufficient_Balance() + { + long lockedTokenAmount = 1; + await ApproveBalanceAsync(lockedTokenAmount); + var chainId = await InitAndCreateSideChainAsync(); + var proposalId1 = await DisposeSideChainProposalAsync(new Int32Value + { + Value = chainId + }); + await ApproveWithMinersAsync(proposalId1); + var transactionResult1 = await ReleaseProposalAsync(proposalId1); + var status1 = transactionResult1.Status; + Assert.True(status1 == TransactionResultStatus.Mined); + + var proposalId2 = await DisposeSideChainProposalAsync(new Int32Value + { + Value = chainId + }); + await ApproveWithMinersAsync(proposalId2); + var transactionResult2 = await ReleaseProposalWithExceptionAsync(proposalId2); + var status2 = transactionResult2.Status; + Assert.True(status2 == TransactionResultStatus.Failed); + Assert.Contains("Incorrect chain status.", transactionResult2.Error); + } + + [Fact] + public async Task GetChainStatus_NotExist() + { + var chainId = ChainHelper.GetChainId(1); + var res = await CrossChainContractStub.GetChainStatus.SendWithExceptionAsync(new Int32Value + { Value = chainId }); + var status = res.TransactionResult.Status; + Assert.True(status == TransactionResultStatus.Failed); + Assert.Contains("Side chain not found.", res.TransactionResult.Error); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.CrossChain.Tests/UnitTestContractInitializationProvider.cs b/test/AElf.Contracts.CrossChain.Tests/UnitTestContractInitializationProvider.cs index a4a888a23e..273b612aee 100644 --- a/test/AElf.Contracts.CrossChain.Tests/UnitTestContractInitializationProvider.cs +++ b/test/AElf.Contracts.CrossChain.Tests/UnitTestContractInitializationProvider.cs @@ -4,27 +4,26 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Contracts.CrossChain.Tests +namespace AElf.Contracts.CrossChain.Tests; + +public class UnitTestTokenContractInitializationProvider : IContractInitializationProvider { - public class UnitTestTokenContractInitializationProvider : IContractInitializationProvider + public Hash SystemSmartContractName { get; } = TokenSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.MultiToken"; + + public List GetInitializeMethodList(byte[] contractCode) { - public Hash SystemSmartContractName { get; } = TokenSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.MultiToken"; - - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + return new List(); } - - public class UnitTestCrossChainContractInitializationProvider : IContractInitializationProvider +} + +public class UnitTestCrossChainContractInitializationProvider : IContractInitializationProvider +{ + public Hash SystemSmartContractName { get; } = CrossChainSmartContractAddressNameProvider.Name; + public string ContractCodeName { get; } = "AElf.Contracts.CrossChain"; + + public List GetInitializeMethodList(byte[] contractCode) { - public Hash SystemSmartContractName { get; } = CrossChainSmartContractAddressNameProvider.Name; - public string ContractCodeName { get; } = "AElf.Contracts.CrossChain"; - - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj index 3384770f0a..f0028a345f 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/AElf.Contracts.Economic.AEDPoSExtension.Tests.csproj @@ -6,19 +6,19 @@ - - - - - - + + + + + + - - - + + + - + Protobuf\Proto\authority_info.proto diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestBase.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestBase.cs index 4083386896..7fa01e09f4 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestBase.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestBase.cs @@ -1,189 +1,174 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Election; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.ContractTestKit; using AElf.Contracts.Treasury; using AElf.ContractTestKit.AEDPoSExtension; using AElf.Cryptography.ECDSA; using AElf.EconomicSystem; using AElf.GovernmentSystem; -using AElf.Kernel; using AElf.Kernel.Consensus; -using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +// ReSharper disable once InconsistentNaming +public partial class EconomicTestBase : AEDPoSExtensionTestBase { - // ReSharper disable once InconsistentNaming - public partial class EconomicTestBase : AEDPoSExtensionTestBase + internal readonly List ParliamentStubs = new(); + + public EconomicTestBase() { - internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal TokenContractContainer.TokenContractStub TokenStub => - GetTester( - ContractAddresses[TokenSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetTester( - ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal ElectionContractContainer.ElectionContractStub ElectionStub => - GetTester( - ContractAddresses[ElectionSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal EconomicContractContainer.EconomicContractStub EconomicStub => - GetTester( - ContractAddresses[EconomicSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal TreasuryContractContainer.TreasuryContractStub TreasuryStub => - GetTester( - ContractAddresses[TreasurySmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal ProfitContractContainer.ProfitContractStub ProfitStub => - GetTester( - ContractAddresses[ProfitSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal readonly List ParliamentStubs = - new List(); - - public EconomicTestBase() + ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List { - ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List - { - TokenSmartContractAddressNameProvider.Name, - VoteSmartContractAddressNameProvider.Name, - ProfitSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ElectionSmartContractAddressNameProvider.Name, - TreasurySmartContractAddressNameProvider.Name, - TokenConverterSmartContractAddressNameProvider.Name, - EconomicSmartContractAddressNameProvider.Name, - TokenHolderSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name - })); + TokenSmartContractAddressNameProvider.Name, + VoteSmartContractAddressNameProvider.Name, + ProfitSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ElectionSmartContractAddressNameProvider.Name, + TreasurySmartContractAddressNameProvider.Name, + TokenConverterSmartContractAddressNameProvider.Name, + EconomicSmartContractAddressNameProvider.Name, + TokenHolderSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name + })); + + AsyncHelper.RunSync(InitialEconomicSystem); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal TokenContractContainer.TokenContractStub TokenStub => + GetTester( + ContractAddresses[TokenSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); - AsyncHelper.RunSync(InitialEconomicSystem); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetTester( + ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); - private async Task InitialEconomicSystem() + internal ElectionContractContainer.ElectionContractStub ElectionStub => + GetTester( + ContractAddresses[ElectionSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal EconomicContractContainer.EconomicContractStub EconomicStub => + GetTester( + ContractAddresses[EconomicSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal TreasuryContractContainer.TreasuryContractStub TreasuryStub => + GetTester( + ContractAddresses[TreasurySmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal ProfitContractContainer.ProfitContractStub ProfitStub => + GetTester( + ContractAddresses[ProfitSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + private async Task InitialEconomicSystem() + { + // Profit distribution schemes related to Treasury must be created before initialization of Economic System. + await BlockMiningService.MineBlockAsync(new List { - // Profit distribution schemes related to Treasury must be created before initialization of Economic System. - await BlockMiningService.MineBlockAsync(new List - { - ParliamentContractStub.Initialize.GetTransaction(new InitializeInput()), - TreasuryStub.InitialTreasuryContract.GetTransaction(new Empty()), - TreasuryStub.InitialMiningRewardProfitItem.GetTransaction(new Empty()) - }); - await BlockMiningService.MineBlockAsync(new List - { - ElectionStub.InitialElectionContract.GetTransaction(new InitialElectionContractInput - { - MinerList = {MissionedECKeyPairs.InitialKeyPairs.Select(p => p.PublicKey.ToHex())}, - MinerIncreaseInterval = AEDPoSExtensionConstants.MinerIncreaseInterval, - TimeEachTerm = AEDPoSExtensionConstants.PeriodSeconds, - MinimumLockTime = EconomicTestConstants.MinimumLockTime, - MaximumLockTime = EconomicTestConstants.MaximumLockTime - }), - EconomicStub.InitialEconomicSystem.GetTransaction(new InitialEconomicSystemInput - { - IsNativeTokenBurnable = true, - MiningRewardTotalAmount = 1_200_000_000_00000000, - NativeTokenDecimals = 8, - NativeTokenSymbol = EconomicTestConstants.TokenSymbol, - NativeTokenTotalSupply = 10_000_000_000_00000000, - NativeTokenName = "Native Token", - TransactionSizeFeeUnitPrice = 1000 - }) - }); - await BlockMiningService.MineBlockAsync(GetIssueTransactions()); - } - - private List GetIssueTransactions() + ParliamentContractStub.Initialize.GetTransaction(new InitializeInput()), + TreasuryStub.InitialTreasuryContract.GetTransaction(new Empty()), + TreasuryStub.InitialMiningRewardProfitItem.GetTransaction(new Empty()) + }); + await BlockMiningService.MineBlockAsync(new List { - var issueTransactions = new List(); - foreach (var coreDataCenterKeyPair in MissionedECKeyPairs.CoreDataCenterKeyPairs - .Concat(MissionedECKeyPairs.ValidationDataCenterKeyPairs).Concat(MissionedECKeyPairs.CitizenKeyPairs)) + ElectionStub.InitialElectionContract.GetTransaction(new InitialElectionContractInput { - issueTransactions.Add(EconomicStub.IssueNativeToken.GetTransaction(new IssueNativeTokenInput - { - To = Address.FromPublicKey(coreDataCenterKeyPair.PublicKey), - Amount = 8_800_000_000_00000000 / Accounts.Count, - })); - } - - return issueTransactions; - } - - internal async Task ParliamentReachAnAgreementAsync(CreateProposalInput createProposalInput) - { - var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); - await BlockMiningService.MineBlockAsync(new List + MinerList = { MissionedECKeyPairs.InitialKeyPairs.Select(p => p.PublicKey.ToHex()) }, + MinerIncreaseInterval = AEDPoSExtensionConstants.MinerIncreaseInterval, + TimeEachTerm = AEDPoSExtensionConstants.PeriodSeconds, + MinimumLockTime = EconomicTestConstants.MinimumLockTime, + MaximumLockTime = EconomicTestConstants.MaximumLockTime + }), + EconomicStub.InitialEconomicSystem.GetTransaction(new InitialEconomicSystemInput { - createProposalTx - }); - var proposalId = new Hash(); - proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); - var approvals = new List(); - foreach (var stub in ParliamentStubs) + IsNativeTokenBurnable = true, + MiningRewardTotalAmount = 1_200_000_000_00000000, + NativeTokenDecimals = 8, + NativeTokenSymbol = EconomicTestConstants.TokenSymbol, + NativeTokenTotalSupply = 10_000_000_000_00000000, + NativeTokenName = "Native Token", + TransactionSizeFeeUnitPrice = 1000 + }) + }); + await BlockMiningService.MineBlockAsync(GetIssueTransactions()); + } + + private List GetIssueTransactions() + { + var issueTransactions = new List(); + foreach (var coreDataCenterKeyPair in MissionedECKeyPairs.CoreDataCenterKeyPairs + .Concat(MissionedECKeyPairs.ValidationDataCenterKeyPairs) + .Concat(MissionedECKeyPairs.CitizenKeyPairs)) + issueTransactions.Add(EconomicStub.IssueNativeToken.GetTransaction(new IssueNativeTokenInput { - approvals.Add(stub.Approve.GetTransaction(proposalId)); - } - - await BlockMiningService.MineBlockAsync(approvals); - - await ParliamentStubs.First().Release.SendAsync(proposalId); - } - - internal async Task EmergencyResponseOrganizationReachAnAgreementAsync(CreateProposalInput createProposalInput) + To = Address.FromPublicKey(coreDataCenterKeyPair.PublicKey), + Amount = 8_800_000_000_00000000 / Accounts.Count + })); + + return issueTransactions; + } + + internal async Task ParliamentReachAnAgreementAsync(CreateProposalInput createProposalInput) + { + var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); + await BlockMiningService.MineBlockAsync(new List { - var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); - await BlockMiningService.MineBlockAsync(new List - { - createProposalTx - }); - var proposalId = new Hash(); - proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); - var approvals = new List(); - foreach (var stub in ParliamentStubs) - { - approvals.Add(stub.Approve.GetTransaction(proposalId)); - } - - await BlockMiningService.MineBlockAsync(approvals); - - await ParliamentStubs.First().Release.SendAsync(proposalId); - } - - internal void UpdateParliamentStubs(IEnumerable keyPairs) + createProposalTx + }); + var proposalId = new Hash(); + proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); + var approvals = new List(); + foreach (var stub in ParliamentStubs) approvals.Add(stub.Approve.GetTransaction(proposalId)); + + await BlockMiningService.MineBlockAsync(approvals); + + await ParliamentStubs.First().Release.SendAsync(proposalId); + } + + internal async Task EmergencyResponseOrganizationReachAnAgreementAsync(CreateProposalInput createProposalInput) + { + var createProposalTx = ParliamentStubs.First().CreateProposal.GetTransaction(createProposalInput); + await BlockMiningService.MineBlockAsync(new List { - ParliamentStubs.Clear(); - foreach (var initialKeyPair in keyPairs) - { - ParliamentStubs.Add(GetTester( - ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair)); - } - } + createProposalTx + }); + var proposalId = new Hash(); + proposalId.MergeFrom(TransactionTraceProvider.GetTransactionTrace(createProposalTx.GetHash()).ReturnValue); + var approvals = new List(); + foreach (var stub in ParliamentStubs) approvals.Add(stub.Approve.GetTransaction(proposalId)); + + await BlockMiningService.MineBlockAsync(approvals); + + await ParliamentStubs.First().Release.SendAsync(proposalId); + } + + internal void UpdateParliamentStubs(IEnumerable keyPairs) + { + ParliamentStubs.Clear(); + foreach (var initialKeyPair in keyPairs) + ParliamentStubs.Add(GetTester( + ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair)); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestConstants.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestConstants.cs index e0678c15d0..f5cc1448e8 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestConstants.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestConstants.cs @@ -1,13 +1,12 @@ -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +public static class EconomicTestConstants { - public static class EconomicTestConstants - { - public const string TokenSymbol = "ELF"; - public const long RewardPerBlock = 1250_0000; + public const string TokenSymbol = "ELF"; + public const long RewardPerBlock = 1250_0000; - public const long MinimumLockTime = 90; - public const long MaximumLockTime = 1080; + public const long MinimumLockTime = 90; + public const long MaximumLockTime = 1080; - public const long TransactionFeeOfClaimProfit = 0; - } + public const long TransactionFeeOfClaimProfit = 0; } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestHelpers.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestHelpers.cs index a1499baf69..71bca3eb2d 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestHelpers.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestHelpers.cs @@ -12,170 +12,164 @@ using AElf.EconomicSystem; using AElf.GovernmentSystem; using AElf.Kernel.Consensus; -using AElf.Kernel.Consensus.AEDPoS; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +/// +/// Some view methods. +/// +public partial class EconomicTestBase { - /// - /// Some view methods. - /// - public partial class EconomicTestBase + public enum SchemeType { - protected async Task GetBalanceAsync(Address owner) - { - return (await TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = owner, - Symbol = EconomicTestConstants.TokenSymbol - })).Balance; - } - - internal async Task GetDistributedInformationAsync(Hash schemeId, long period) - { - return await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - SchemeId = schemeId, - Period = period - }); - } + Treasury, - internal async Task> GetTreasurySchemesAsync() - { - var treasurySchemeId = await TreasuryStub.GetTreasurySchemeId.CallAsync(new Empty()); - var schemes = new Dictionary(); - var treasuryScheme = await ProfitStub.GetScheme.CallAsync(treasurySchemeId); - schemes.Add(SchemeType.Treasury, treasuryScheme); - var minerRewardScheme = await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[0].SchemeId); - schemes.Add(SchemeType.MinerReward, minerRewardScheme); - schemes.Add(SchemeType.BackupSubsidy, - await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[1].SchemeId)); - schemes.Add(SchemeType.CitizenWelfare, - await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[2].SchemeId)); - schemes.Add(SchemeType.MinerBasicReward, - await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[0].SchemeId)); - schemes.Add(SchemeType.WelcomeReward, - await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[1].SchemeId)); - schemes.Add(SchemeType.FlexibleReward, - await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[2].SchemeId)); - return schemes; - } + MinerReward, + BackupSubsidy, + CitizenWelfare, - internal async Task ClaimProfits(IEnumerable keyPairs, Hash schemeId) - { - var stubs = ConvertKeyPairsToProfitStubs(keyPairs); - await BlockMiningService.MineBlockAsync(stubs.Select(s => - s.ClaimProfits.GetTransaction(new ClaimProfitsInput - { - SchemeId = schemeId, - })).ToList()); - } + MinerBasicReward, + WelcomeReward, + FlexibleReward + } - /// - /// Tolerance: 10 - /// - /// - /// - /// - /// - internal async Task CheckBalancesAsync(IEnumerable keyPairs, long shouldIncrease, - Dictionary balancesBefore = null) + protected async Task GetBalanceAsync(Address owner) + { + return (await TokenStub.GetBalance.CallAsync(new GetBalanceInput { - const long tolerance = 20; - balancesBefore ??= new Dictionary(); - foreach (var keyPair in keyPairs) - { - var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); - amount.ShouldBeGreaterThanOrEqualTo(shouldIncrease + balancesBefore[keyPair] - tolerance); - amount.ShouldBeLessThanOrEqualTo(shouldIncrease + balancesBefore[keyPair] + tolerance); - } - } + Owner = owner, + Symbol = EconomicTestConstants.TokenSymbol + })).Balance; + } - public enum SchemeType + internal async Task GetDistributedInformationAsync(Hash schemeId, long period) + { + return await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - Treasury, + SchemeId = schemeId, + Period = period + }); + } - MinerReward, - BackupSubsidy, - CitizenWelfare, + internal async Task> GetTreasurySchemesAsync() + { + var treasurySchemeId = await TreasuryStub.GetTreasurySchemeId.CallAsync(new Empty()); + var schemes = new Dictionary(); + var treasuryScheme = await ProfitStub.GetScheme.CallAsync(treasurySchemeId); + schemes.Add(SchemeType.Treasury, treasuryScheme); + var minerRewardScheme = await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[0].SchemeId); + schemes.Add(SchemeType.MinerReward, minerRewardScheme); + schemes.Add(SchemeType.BackupSubsidy, + await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[1].SchemeId)); + schemes.Add(SchemeType.CitizenWelfare, + await ProfitStub.GetScheme.CallAsync(treasuryScheme.SubSchemes[2].SchemeId)); + schemes.Add(SchemeType.MinerBasicReward, + await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[0].SchemeId)); + schemes.Add(SchemeType.WelcomeReward, + await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[1].SchemeId)); + schemes.Add(SchemeType.FlexibleReward, + await ProfitStub.GetScheme.CallAsync(minerRewardScheme.SubSchemes[2].SchemeId)); + return schemes; + } - MinerBasicReward, - WelcomeReward, - FlexibleReward - } + internal async Task ClaimProfits(IEnumerable keyPairs, Hash schemeId) + { + var stubs = ConvertKeyPairsToProfitStubs(keyPairs); + await BlockMiningService.MineBlockAsync(stubs.Select(s => + s.ClaimProfits.GetTransaction(new ClaimProfitsInput + { + SchemeId = schemeId + })).ToList()); + } - internal List ConvertKeyPairsToConsensusStubs( - IEnumerable keyPairs) - { - return keyPairs.Select(p => - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], p)).ToList(); - } - - internal List ConvertKeyPairsToProfitStubs( - IEnumerable keyPairs) - { - return keyPairs.Select(p => - GetTester( - ContractAddresses[ProfitSmartContractAddressNameProvider.Name], p)).ToList(); - } - - internal List ConvertKeyPairsToElectionStubs( - IEnumerable keyPairs) + /// + /// Tolerance: 10 + /// + /// + /// + /// + /// + internal async Task CheckBalancesAsync(IEnumerable keyPairs, long shouldIncrease, + Dictionary balancesBefore = null) + { + const long tolerance = 20; + balancesBefore ??= new Dictionary(); + foreach (var keyPair in keyPairs) { - return keyPairs.Select(p => - GetTester( - ContractAddresses[ElectionSmartContractAddressNameProvider.Name], p)).ToList(); + var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); + amount.ShouldBeGreaterThanOrEqualTo(shouldIncrease + balancesBefore[keyPair] - tolerance); + amount.ShouldBeLessThanOrEqualTo(shouldIncrease + balancesBefore[keyPair] + tolerance); } + } - internal List GetVoteTransactions(int timesOfMinimumLockDays, - long amount, string candidatePubkey, int votersCount = 0) - { - if (votersCount > AEDPoSExtensionConstants.CitizenKeyPairsCount) - { - throw new ArgumentOutOfRangeException(nameof(votersCount), $"Didn't prepare this amount of citizens. {votersCount} > {AEDPoSExtensionConstants.CitizenKeyPairsCount}"); - } + internal List ConvertKeyPairsToConsensusStubs( + IEnumerable keyPairs) + { + return keyPairs.Select(p => + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], p)).ToList(); + } + + internal List ConvertKeyPairsToProfitStubs( + IEnumerable keyPairs) + { + return keyPairs.Select(p => + GetTester( + ContractAddresses[ProfitSmartContractAddressNameProvider.Name], p)).ToList(); + } - votersCount = votersCount == 0 ? AEDPoSExtensionConstants.CitizenKeyPairsCount : votersCount; + internal List ConvertKeyPairsToElectionStubs( + IEnumerable keyPairs) + { + return keyPairs.Select(p => + GetTester( + ContractAddresses[ElectionSmartContractAddressNameProvider.Name], p)).ToList(); + } - var voteTransaction = new List(); + internal List GetVoteTransactions(int timesOfMinimumLockDays, + long amount, string candidatePubkey, int votersCount = 0) + { + if (votersCount > AEDPoSExtensionConstants.CitizenKeyPairsCount) + throw new ArgumentOutOfRangeException(nameof(votersCount), + $"Didn't prepare this amount of citizens. {votersCount} > {AEDPoSExtensionConstants.CitizenKeyPairsCount}"); - var blockTime = TestDataProvider.GetBlockTime(); + votersCount = votersCount == 0 ? AEDPoSExtensionConstants.CitizenKeyPairsCount : votersCount; - var electionStubs = ConvertKeyPairsToElectionStubs(MissionedECKeyPairs.CitizenKeyPairs.Take(votersCount)); + var voteTransaction = new List(); - foreach (var electionStub in electionStubs) - { - voteTransaction.Add(electionStub.Vote.GetTransaction(new VoteMinerInput - { - CandidatePubkey = candidatePubkey, - Amount = amount, - EndTimestamp = - blockTime.AddSeconds(timesOfMinimumLockDays * EconomicTestConstants.MinimumLockTime) - })); - } - - return voteTransaction; - } + var blockTime = TestDataProvider.GetBlockTime(); - internal async Task MineBlocksToNextTermAsync(long currentTermNumber = 0) - { - currentTermNumber = currentTermNumber == 0 - ? (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value - : currentTermNumber; - var targetTermNumber = currentTermNumber + 1; - var actualTermNumber = 0L; - while (actualTermNumber != targetTermNumber) + var electionStubs = ConvertKeyPairsToElectionStubs(MissionedECKeyPairs.CitizenKeyPairs.Take(votersCount)); + + foreach (var electionStub in electionStubs) + voteTransaction.Add(electionStub.Vote.GetTransaction(new VoteMinerInput { - BlockMiningService.SkipTime(1); - await BlockMiningService.MineBlockAsync(); - actualTermNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; - } + CandidatePubkey = candidatePubkey, + Amount = amount, + EndTimestamp = + blockTime.AddSeconds(timesOfMinimumLockDays * EconomicTestConstants.MinimumLockTime) + })); + + return voteTransaction; + } - return (await ConsensusStub.GetMinedBlocksOfPreviousTerm.CallAsync(new Empty())).Value; + internal async Task MineBlocksToNextTermAsync(long currentTermNumber = 0) + { + currentTermNumber = currentTermNumber == 0 + ? (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value + : currentTermNumber; + var targetTermNumber = currentTermNumber + 1; + var actualTermNumber = 0L; + while (actualTermNumber != targetTermNumber) + { + BlockMiningService.SkipTime(1); + await BlockMiningService.MineBlockAsync(); + actualTermNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; } + + return (await ConsensusStub.GetMinedBlocksOfPreviousTerm.CallAsync(new Empty())).Value; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestModule.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestModule.cs index f5be4818e1..07e33581ce 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestModule.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EconomicTestModule.cs @@ -3,16 +3,15 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +[DependsOn(typeof(ContractTestAEDPoSExtensionModule))] +// ReSharper disable once InconsistentNaming +public class EconomicTestModule : ContractTestAEDPoSExtensionModule { - [DependsOn(typeof(ContractTestAEDPoSExtensionModule))] - // ReSharper disable once InconsistentNaming - public class EconomicTestModule : ContractTestAEDPoSExtensionModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - } + context.Services.AddAssemblyOf(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EvilNodeRelatedTests.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EvilNodeRelatedTests.cs index edadf8b3be..2b5ec6c900 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EvilNodeRelatedTests.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/EvilNodeRelatedTests.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Election; using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; @@ -10,80 +9,76 @@ using AElf.GovernmentSystem; using AElf.Kernel; using AElf.Kernel.Proposal; +using AElf.Standards.ACS3; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +public class EvilNodeRelatedTests : EconomicTestBase { - public class EvilNodeRelatedTests : EconomicTestBase + [Fact(Skip = "Need fix.")] + internal async Task MarkEvilNodeTest() { - [Fact(Skip = "Need fix.")] - internal async Task MarkEvilNodeTest() - { - UpdateParliamentStubs(MissionedECKeyPairs.InitialKeyPairs); - var newCandidates = MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(18).ToList(); - await NodesAnnounceElection(newCandidates); - await BlockMiningService.MineBlockToNextTermAsync(); + UpdateParliamentStubs(MissionedECKeyPairs.InitialKeyPairs); + var newCandidates = MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(18).ToList(); + await NodesAnnounceElection(newCandidates); + await BlockMiningService.MineBlockToNextTermAsync(); - var miners = newCandidates.Take(17).ToList(); - //UpdateParliamentStubs(miners); + var miners = newCandidates.Take(17).ToList(); + //UpdateParliamentStubs(miners); - await BlockMiningService.MineBlockToNextRoundAsync(); + await BlockMiningService.MineBlockToNextRoundAsync(); - var defaultOrganizationAddress = - await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); - await ParliamentReachAnAgreementAsync(new CreateProposalInput - { - ToAddress = ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], - ContractMethodName = "CreateEmergencyResponseOrganization", - Params = new Empty().ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = defaultOrganizationAddress - }); - var eroAddress = - await ParliamentStubs.First().GetEmergencyResponseOrganizationAddress.CallAsync(new Empty()); - var evilNodePubkey = MissionedECKeyPairs.ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); - await EmergencyResponseOrganizationReachAnAgreementAsync(new CreateProposalInput + var defaultOrganizationAddress = + await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + await ParliamentReachAnAgreementAsync(new CreateProposalInput + { + ToAddress = ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], + ContractMethodName = "CreateEmergencyResponseOrganization", + Params = new Empty().ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultOrganizationAddress + }); + var eroAddress = + await ParliamentStubs.First().GetEmergencyResponseOrganizationAddress.CallAsync(new Empty()); + var evilNodePubkey = MissionedECKeyPairs.ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); + await EmergencyResponseOrganizationReachAnAgreementAsync(new CreateProposalInput + { + ToAddress = ContractAddresses[ElectionSmartContractAddressNameProvider.Name], + ContractMethodName = nameof(ElectionStub.RemoveEvilNode), + Params = new StringValue { - ToAddress = ContractAddresses[ElectionSmartContractAddressNameProvider.Name], - ContractMethodName = nameof(ElectionStub.RemoveEvilNode), - Params = new StringValue - { - Value = evilNodePubkey - }.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = eroAddress - }); - await BlockMiningService.MineBlockToNextRoundAsync(); - miners.Remove(MissionedECKeyPairs.ValidationDataCenterKeyPairs.First()); - miners.Add(MissionedECKeyPairs.ValidationDataCenterKeyPairs.Skip(17).Take(1).First()); - UpdateParliamentStubs(miners); + Value = evilNodePubkey + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = eroAddress + }); + await BlockMiningService.MineBlockToNextRoundAsync(); + miners.Remove(MissionedECKeyPairs.ValidationDataCenterKeyPairs.First()); + miners.Add(MissionedECKeyPairs.ValidationDataCenterKeyPairs.Skip(17).Take(1).First()); + UpdateParliamentStubs(miners); - var currentRound = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - currentRound.RealTimeMinersInformation.Keys.ShouldNotContain(evilNodePubkey); - } + var currentRound = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + currentRound.RealTimeMinersInformation.Keys.ShouldNotContain(evilNodePubkey); + } - private async Task NodesAnnounceElection(List nodeAccounts) - { - var candidateElectionStubs = nodeAccounts.Select(keyPair => - GetTester( - ContractAddresses[ElectionSmartContractAddressNameProvider.Name], keyPair)).ToList(); - foreach (var electionStub in candidateElectionStubs) - { - await electionStub.AnnounceElection.SendAsync(SampleAccount.Accounts.First().Address); - } + private async Task NodesAnnounceElection(List nodeAccounts) + { + var candidateElectionStubs = nodeAccounts.Select(keyPair => + GetTester( + ContractAddresses[ElectionSmartContractAddressNameProvider.Name], keyPair)).ToList(); + foreach (var electionStub in candidateElectionStubs) + await electionStub.AnnounceElection.SendAsync(SampleAccount.Accounts.First().Address); - foreach (var keyPair in nodeAccounts) + foreach (var keyPair in nodeAccounts) + await candidateElectionStubs.First().Vote.SendAsync(new VoteMinerInput { - await candidateElectionStubs.First().Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = keyPair.PublicKey.ToHex(), - Amount = 100, - EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(100) - }); - } - } + CandidatePubkey = keyPair.PublicKey.ToHex(), + Amount = 100, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(100) + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryCollectionTests.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryCollectionTests.cs index 3c93aeb4d7..79f8525256 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryCollectionTests.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryCollectionTests.cs @@ -2,27 +2,46 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; -using AElf.TestBase; -using AElf.Contracts.Treasury; using AElf.ContractTestKit.AEDPoSExtension; using AElf.CSharp.Core; +using AElf.TestBase; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Volo.Abp.Threading; using Xunit; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +public partial class EconomicTests : EconomicTestBase { - public partial class EconomicTests : EconomicTestBase + [Fact] + public async Task TreasuryCollection_FirstTerm_Test() { - [Fact] - public async Task TreasuryCollection_FirstTerm_Test() - { - var distributedAmount = await TreasuryDistribution_FirstTerm_Test(); + var distributedAmount = await TreasuryDistribution_FirstTerm_Test(); - // First 7 core data centers can profit from backup subsidy - var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + // First 7 core data centers can profit from backup subsidy + var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); + await CheckBalancesAsync(firstSevenCoreDataCenters, + distributedAmount / 20 / 7, balancesBefore); + } + + [IgnoreOnCIFact] + public async Task TreasuryCollection_SecondTerm_Test() + { + var distributedAmountOfFirstTerm = await TreasuryDistribution_FirstTerm_Test(); + var distributionInformationOfSecondTerm = await TreasuryDistribution_SecondTerm_Test(); + + // First 7 core data centers can profit from backup subsidy of term 1 and term 2. + var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + { var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput { @@ -30,253 +49,235 @@ public async Task TreasuryCollection_FirstTerm_Test() Symbol = EconomicTestConstants.TokenSymbol })).Balance); await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); + var subsidyInFirstTerm = distributedAmountOfFirstTerm / 20 / 7; + var subsidyInformation = distributionInformationOfSecondTerm[SchemeType.BackupSubsidy]; + var subsidyInSecondTerm = subsidyInformation.Amount / subsidyInformation.TotalShares; await CheckBalancesAsync(firstSevenCoreDataCenters, - distributedAmount / 20 / 7 , balancesBefore); + subsidyInFirstTerm + subsidyInSecondTerm - EconomicTestConstants.TransactionFeeOfClaimProfit, + balancesBefore); } - [IgnoreOnCIFact] - public async Task TreasuryCollection_SecondTerm_Test() + // First 7 core data centers can profit from miner basic reward because they acted as miners during second term. { - var distributedAmountOfFirstTerm = await TreasuryDistribution_FirstTerm_Test(); - var distributionInformationOfSecondTerm = await TreasuryDistribution_SecondTerm_Test(); - - // First 7 core data centers can profit from backup subsidy of term 1 and term 2. - var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); + var previousRound = ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 2 }) + .Result; + var totalBlocks = previousRound.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); + foreach (var keyPair in firstSevenCoreDataCenters) { - var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); - var subsidyInFirstTerm = distributedAmountOfFirstTerm / 20 / 7; - var subsidyInformation = distributionInformationOfSecondTerm[SchemeType.BackupSubsidy]; - var subsidyInSecondTerm = subsidyInformation.Amount / subsidyInformation.TotalShares; - await CheckBalancesAsync(firstSevenCoreDataCenters, - subsidyInFirstTerm + subsidyInSecondTerm - EconomicTestConstants.TransactionFeeOfClaimProfit, - balancesBefore); + var shouldIncrease = distributionInformationOfSecondTerm[SchemeType.MinerBasicReward].Amount * + previousRound.RealTimeMinersInformation[keyPair.PublicKey.ToHex()] + .ProducedBlocks / totalBlocks - + EconomicTestConstants.TransactionFeeOfClaimProfit; + var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); + amount.ShouldBe(shouldIncrease + balancesBefore[keyPair]); } + } - // First 7 core data centers can profit from miner basic reward because they acted as miners during second term. - { - var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); - var previousRound = ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value {Value = 2}) - .Result; - var totalBlocks = previousRound.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); - foreach (var keyPair in firstSevenCoreDataCenters) + // First 10 voters can profit from citizen welfare. + var firstTenVoters = MissionedECKeyPairs.CitizenKeyPairs.Take(10).ToList(); + { + var balancesBefore = firstTenVoters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput { - var shouldIncrease = distributionInformationOfSecondTerm[SchemeType.MinerBasicReward].Amount * - previousRound.RealTimeMinersInformation[keyPair.PublicKey.ToHex()] - .ProducedBlocks / totalBlocks - - EconomicTestConstants.TransactionFeeOfClaimProfit; - var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); - amount.ShouldBe(shouldIncrease + balancesBefore[keyPair]); - } - } + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); + var citizenWelfare = distributionInformationOfSecondTerm[SchemeType.CitizenWelfare].Amount / 10; + await CheckBalancesAsync(firstTenVoters, + citizenWelfare - EconomicTestConstants.TransactionFeeOfClaimProfit, + balancesBefore); + } + } - // First 10 voters can profit from citizen welfare. - var firstTenVoters = MissionedECKeyPairs.CitizenKeyPairs.Take(10).ToList(); - { - var balancesBefore = firstTenVoters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); - var citizenWelfare = distributionInformationOfSecondTerm[SchemeType.CitizenWelfare].Amount / 10; - await CheckBalancesAsync(firstTenVoters, - citizenWelfare - EconomicTestConstants.TransactionFeeOfClaimProfit, - balancesBefore); - } + [IgnoreOnCIFact] + public async Task TreasuryCollection_ThirdTerm_Test() + { + var distributedAmountOfFirstTerm = await TreasuryDistribution_FirstTerm_Test(); + var distributionInformationOfSecondTerm = await TreasuryDistribution_SecondTerm_Test(); + var distributionInformationOfThirdTerm = await TreasuryDistribution_ThirdTerm_Test(); + + var subsidyInformationOfSecondTerm = distributionInformationOfSecondTerm[SchemeType.BackupSubsidy]; + var subsidyInformationOfThirdTerm = distributionInformationOfThirdTerm[SchemeType.BackupSubsidy]; + + // First 7 core data centers can profit from backup subsidy of term 1, term 2 and term 3. + var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + { + var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); + var subsidyInFirstTerm = distributedAmountOfFirstTerm / 20 / 7; + var subsidyInSecondTerm = + subsidyInformationOfSecondTerm.Amount / subsidyInformationOfSecondTerm.TotalShares; + var subsidyInThirdTerm = + subsidyInformationOfThirdTerm.Amount / subsidyInformationOfThirdTerm.TotalShares; + await CheckBalancesAsync(firstSevenCoreDataCenters, + subsidyInFirstTerm + subsidyInSecondTerm + subsidyInThirdTerm - + EconomicTestConstants.TransactionFeeOfClaimProfit, + balancesBefore); } - [IgnoreOnCIFact] - public async Task TreasuryCollection_ThirdTerm_Test() + // Last 12 core data centers can profit from backup subsidy of term 2 and term 3. + var lastTwelveCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).Take(12).ToList(); + { - var distributedAmountOfFirstTerm = await TreasuryDistribution_FirstTerm_Test(); - var distributionInformationOfSecondTerm = await TreasuryDistribution_SecondTerm_Test(); - var distributionInformationOfThirdTerm = await TreasuryDistribution_ThirdTerm_Test(); + var balancesBefore = lastTwelveCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(lastTwelveCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); + var subsidyInSecondTerm = + subsidyInformationOfSecondTerm.Amount / subsidyInformationOfSecondTerm.TotalShares; + var subsidyInThirdTerm = + subsidyInformationOfThirdTerm.Amount / subsidyInformationOfThirdTerm.TotalShares; + await CheckBalancesAsync(lastTwelveCoreDataCenters, + subsidyInSecondTerm + subsidyInThirdTerm - + EconomicTestConstants.TransactionFeeOfClaimProfit, + balancesBefore); + } - var subsidyInformationOfSecondTerm = distributionInformationOfSecondTerm[SchemeType.BackupSubsidy]; - var subsidyInformationOfThirdTerm = distributionInformationOfThirdTerm[SchemeType.BackupSubsidy]; + // First 7 core data centers can profit from miner basic reward of term 2 and term 3. + { + var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); - // First 7 core data centers can profit from backup subsidy of term 1, term 2 and term 3. - var firstSevenCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7).ToList(); + // Term 2. + var secondTermInformation = ConsensusStub.GetPreviousTermInformation + .CallAsync(new Int64Value { Value = 2 }) + .Result; + var producedBlocksOfSecondTerm = secondTermInformation.RealTimeMinersInformation.Values + .Select(i => i.ProducedBlocks).ToList(); + var totalProducedBlocksOfSecondTerm = producedBlocksOfSecondTerm.Sum(); + var averageOfSecondTerm = totalProducedBlocksOfSecondTerm.Div(producedBlocksOfSecondTerm.Count); + var sharesDictOfSecondTerm = new Dictionary(); + foreach (var pubkey in secondTermInformation.RealTimeMinersInformation.Keys) { - var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); - var subsidyInFirstTerm = distributedAmountOfFirstTerm / 20 / 7; - var subsidyInSecondTerm = - subsidyInformationOfSecondTerm.Amount / subsidyInformationOfSecondTerm.TotalShares; - var subsidyInThirdTerm = - subsidyInformationOfThirdTerm.Amount / subsidyInformationOfThirdTerm.TotalShares; - await CheckBalancesAsync(firstSevenCoreDataCenters, - subsidyInFirstTerm + subsidyInSecondTerm + subsidyInThirdTerm - - EconomicTestConstants.TransactionFeeOfClaimProfit, - balancesBefore); + var producedBlocks = secondTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; + sharesDictOfSecondTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfSecondTerm)); } - // Last 12 core data centers can profit from backup subsidy of term 2 and term 3. - var lastTwelveCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).Take(12).ToList(); + var totalSharesOfSecondTerm = sharesDictOfSecondTerm.Values.Sum(); + // Term 3. + var thirdTermInformation = ConsensusStub.GetPreviousTermInformation + .CallAsync(new Int64Value { Value = 3 }) + .Result; + var producedBlocksOfThirdTerm = thirdTermInformation.RealTimeMinersInformation.Values + .Select(i => i.ProducedBlocks).ToList(); + var totalProducedBlocksOfThirdTerm = producedBlocksOfThirdTerm.Sum(); + var averageOfThirdTerm = totalProducedBlocksOfThirdTerm.Div(producedBlocksOfThirdTerm.Count); + var sharesDictOfThirdTerm = new Dictionary(); + foreach (var pubkey in thirdTermInformation.RealTimeMinersInformation.Keys) { - var balancesBefore = lastTwelveCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(lastTwelveCoreDataCenters, _schemes[SchemeType.BackupSubsidy].SchemeId); - var subsidyInSecondTerm = - subsidyInformationOfSecondTerm.Amount / subsidyInformationOfSecondTerm.TotalShares; - var subsidyInThirdTerm = - subsidyInformationOfThirdTerm.Amount / subsidyInformationOfThirdTerm.TotalShares; - await CheckBalancesAsync(lastTwelveCoreDataCenters, - subsidyInSecondTerm + subsidyInThirdTerm - - EconomicTestConstants.TransactionFeeOfClaimProfit, - balancesBefore); + var producedBlocks = thirdTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; + sharesDictOfThirdTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfThirdTerm)); } - // First 7 core data centers can profit from miner basic reward of term 2 and term 3. + var totalSharesOfThirdTerm = sharesDictOfThirdTerm.Values.Sum(); + foreach (var keyPair in firstSevenCoreDataCenters) { - var balancesBefore = firstSevenCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(firstSevenCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); - - // Term 2. - var secondTermInformation = ConsensusStub.GetPreviousTermInformation - .CallAsync(new Int64Value { Value = 2 }) - .Result; - var producedBlocksOfSecondTerm = secondTermInformation.RealTimeMinersInformation.Values - .Select(i => i.ProducedBlocks).ToList(); - var totalProducedBlocksOfSecondTerm = producedBlocksOfSecondTerm.Sum(); - var averageOfSecondTerm = totalProducedBlocksOfSecondTerm.Div(producedBlocksOfSecondTerm.Count); - var sharesDictOfSecondTerm = new Dictionary(); - foreach (var pubkey in secondTermInformation.RealTimeMinersInformation.Keys) - { - var producedBlocks = secondTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; - sharesDictOfSecondTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfSecondTerm)); - } - var totalSharesOfSecondTerm = sharesDictOfSecondTerm.Values.Sum(); - - // Term 3. - var thirdTermInformation = ConsensusStub.GetPreviousTermInformation - .CallAsync(new Int64Value { Value = 3 }) - .Result; - var producedBlocksOfThirdTerm = thirdTermInformation.RealTimeMinersInformation.Values - .Select(i => i.ProducedBlocks).ToList(); - var totalProducedBlocksOfThirdTerm = producedBlocksOfThirdTerm.Sum(); - var averageOfThirdTerm = totalProducedBlocksOfThirdTerm.Div(producedBlocksOfThirdTerm.Count); - var sharesDictOfThirdTerm = new Dictionary(); - foreach (var pubkey in thirdTermInformation.RealTimeMinersInformation.Keys) - { - var producedBlocks = thirdTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; - sharesDictOfThirdTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfThirdTerm)); - } - var totalSharesOfThirdTerm = sharesDictOfThirdTerm.Values.Sum(); - foreach (var keyPair in firstSevenCoreDataCenters) - { - var shouldIncreaseForSecondTerm = - distributionInformationOfSecondTerm[SchemeType.MinerBasicReward].Amount * - sharesDictOfSecondTerm[keyPair.PublicKey.ToHex()] / totalSharesOfSecondTerm; - var shouldIncreaseForThirdTerm = - distributionInformationOfThirdTerm[SchemeType.MinerBasicReward].Amount * - sharesDictOfThirdTerm[keyPair.PublicKey.ToHex()] / totalSharesOfThirdTerm; - var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); - amount.ShouldBe(shouldIncreaseForSecondTerm + shouldIncreaseForThirdTerm + balancesBefore[keyPair]); - } + var shouldIncreaseForSecondTerm = + distributionInformationOfSecondTerm[SchemeType.MinerBasicReward].Amount * + sharesDictOfSecondTerm[keyPair.PublicKey.ToHex()] / totalSharesOfSecondTerm; + var shouldIncreaseForThirdTerm = + distributionInformationOfThirdTerm[SchemeType.MinerBasicReward].Amount * + sharesDictOfThirdTerm[keyPair.PublicKey.ToHex()] / totalSharesOfThirdTerm; + var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); + amount.ShouldBe(shouldIncreaseForSecondTerm + shouldIncreaseForThirdTerm + balancesBefore[keyPair]); } + } - // Last 12 core data centers can profit from miner basic reward of term 3. - { - var balancesBefore = lastTwelveCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(lastTwelveCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); - var thirdTermInformation = ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value {Value = 3}) - .Result; - var producedBlocksOfThirdTerm = thirdTermInformation.RealTimeMinersInformation.Values - .Select(i => i.ProducedBlocks).ToList(); - var totalProducedBlocksOfThirdTerm = producedBlocksOfThirdTerm.Sum(); - var averageOfThirdTerm = totalProducedBlocksOfThirdTerm.Div(producedBlocksOfThirdTerm.Count); - var sharesDictOfThirdTerm = new Dictionary(); - foreach (var pubkey in thirdTermInformation.RealTimeMinersInformation.Keys) - { - var producedBlocks = thirdTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; - sharesDictOfThirdTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfThirdTerm)); - } - var totalSharesOfThirdTerm = sharesDictOfThirdTerm.Values.Sum(); - foreach (var keyPair in lastTwelveCoreDataCenters) + // Last 12 core data centers can profit from miner basic reward of term 3. + { + var balancesBefore = lastTwelveCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput { - var shouldIncrease = distributionInformationOfThirdTerm[SchemeType.MinerBasicReward].Amount * - CalculateShares(sharesDictOfThirdTerm[keyPair.PublicKey.ToHex()], - averageOfThirdTerm) / totalSharesOfThirdTerm - - EconomicTestConstants.TransactionFeeOfClaimProfit; - var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); - amount.ShouldBe(shouldIncrease + balancesBefore[keyPair]); - } - } - - // Last 2 core data centers can profit from welcome reward (of only term 3) + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(lastTwelveCoreDataCenters, _schemes[SchemeType.MinerBasicReward].SchemeId); + var thirdTermInformation = ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 3 }) + .Result; + var producedBlocksOfThirdTerm = thirdTermInformation.RealTimeMinersInformation.Values + .Select(i => i.ProducedBlocks).ToList(); + var totalProducedBlocksOfThirdTerm = producedBlocksOfThirdTerm.Sum(); + var averageOfThirdTerm = totalProducedBlocksOfThirdTerm.Div(producedBlocksOfThirdTerm.Count); + var sharesDictOfThirdTerm = new Dictionary(); + foreach (var pubkey in thirdTermInformation.RealTimeMinersInformation.Keys) { - var lastTwoCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(22).Take(2).ToList(); - var balancesBefore = lastTwoCoreDataCenters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - await ClaimProfits(lastTwoCoreDataCenters, _schemes[SchemeType.WelcomeReward].SchemeId); - var welcomeRewardInThirdTerm = - distributionInformationOfThirdTerm[SchemeType.WelcomeReward].Amount / 10; - await CheckBalancesAsync(lastTwoCoreDataCenters, - welcomeRewardInThirdTerm - EconomicTestConstants.TransactionFeeOfClaimProfit, - balancesBefore); + var producedBlocks = thirdTermInformation.RealTimeMinersInformation[pubkey].ProducedBlocks; + sharesDictOfThirdTerm.Add(pubkey, CalculateShares(producedBlocks, averageOfThirdTerm)); } - // First 10 voters can profit from citizen welfare. - var firstTenVoters = MissionedECKeyPairs.CitizenKeyPairs.Take(10).ToList(); + var totalSharesOfThirdTerm = sharesDictOfThirdTerm.Values.Sum(); + foreach (var keyPair in lastTwelveCoreDataCenters) { - var balancesBefore = firstTenVoters.ToDictionary(k => k, k => - AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(k.PublicKey), - Symbol = EconomicTestConstants.TokenSymbol - })).Balance); - // We limited profiting, thus ClaimProfits need to be called 4 times to profit all. - await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); - await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); - await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); - await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); - var citizenWelfareInSecondTerm = - distributionInformationOfSecondTerm[SchemeType.CitizenWelfare].Amount / 10; - var citizenWelfareInThirdTerm = - distributionInformationOfThirdTerm[SchemeType.CitizenWelfare].Amount / 10; - await CheckBalancesAsync(firstTenVoters, - citizenWelfareInSecondTerm + citizenWelfareInThirdTerm - - EconomicTestConstants.TransactionFeeOfClaimProfit * 4, - balancesBefore); + var shouldIncrease = distributionInformationOfThirdTerm[SchemeType.MinerBasicReward].Amount * + CalculateShares(sharesDictOfThirdTerm[keyPair.PublicKey.ToHex()], + averageOfThirdTerm) / totalSharesOfThirdTerm - + EconomicTestConstants.TransactionFeeOfClaimProfit; + var amount = await GetBalanceAsync(Address.FromPublicKey(keyPair.PublicKey)); + amount.ShouldBe(shouldIncrease + balancesBefore[keyPair]); } } + + // Last 2 core data centers can profit from welcome reward (of only term 3) + { + var lastTwoCoreDataCenters = MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(22).Take(2).ToList(); + var balancesBefore = lastTwoCoreDataCenters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + await ClaimProfits(lastTwoCoreDataCenters, _schemes[SchemeType.WelcomeReward].SchemeId); + var welcomeRewardInThirdTerm = + distributionInformationOfThirdTerm[SchemeType.WelcomeReward].Amount / 10; + await CheckBalancesAsync(lastTwoCoreDataCenters, + welcomeRewardInThirdTerm - EconomicTestConstants.TransactionFeeOfClaimProfit, + balancesBefore); + } + + // First 10 voters can profit from citizen welfare. + var firstTenVoters = MissionedECKeyPairs.CitizenKeyPairs.Take(10).ToList(); + { + var balancesBefore = firstTenVoters.ToDictionary(k => k, k => + AsyncHelper.RunSync(() => TokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(k.PublicKey), + Symbol = EconomicTestConstants.TokenSymbol + })).Balance); + // We limited profiting, thus ClaimProfits need to be called 4 times to profit all. + await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); + await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); + await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); + await ClaimProfits(firstTenVoters, _schemes[SchemeType.CitizenWelfare].SchemeId); + var citizenWelfareInSecondTerm = + distributionInformationOfSecondTerm[SchemeType.CitizenWelfare].Amount / 10; + var citizenWelfareInThirdTerm = + distributionInformationOfThirdTerm[SchemeType.CitizenWelfare].Amount / 10; + await CheckBalancesAsync(firstTenVoters, + citizenWelfareInSecondTerm + citizenWelfareInThirdTerm - + EconomicTestConstants.TransactionFeeOfClaimProfit * 4, + balancesBefore); + } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionInformation.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionInformation.cs index 3aba03da40..39deb91ca7 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionInformation.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionInformation.cs @@ -1,26 +1,24 @@ using System.Collections.Generic; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests -{ - public class TreasuryDistributionInformation - { - private readonly Dictionary _information = - new Dictionary(); +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; - public long TotalAmount { get; set; } +public class TreasuryDistributionInformation +{ + private readonly Dictionary _information = new(); - public DistributionInformation this[EconomicTestBase.SchemeType schemeType] - { - get => _information.TryGetValue(schemeType, out var information) - ? information - : new DistributionInformation(); - set => _information[schemeType] = value; - } - } + public long TotalAmount { get; set; } - public class DistributionInformation + public DistributionInformation this[EconomicTestBase.SchemeType schemeType] { - public long Amount { get; set; } - public long TotalShares { get; set; } + get => _information.TryGetValue(schemeType, out var information) + ? information + : new DistributionInformation(); + set => _information[schemeType] = value; } +} + +public class DistributionInformation +{ + public long Amount { get; set; } + public long TotalShares { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionTests.cs b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionTests.cs index 28c79ee6a1..d41dd5ec80 100644 --- a/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionTests.cs +++ b/test/AElf.Contracts.Economic.AEDPoSExtension.Tests/TreasuryDistributionTests.cs @@ -1,10 +1,7 @@ using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using AElf.Contracts.Election; using AElf.Contracts.Profit; -using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; using AElf.CSharp.Core; using AElf.TestBase; @@ -14,297 +11,291 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.Contracts.Economic.AEDPoSExtension.Tests +namespace AElf.Contracts.Economic.AEDPoSExtension.Tests; + +public partial class EconomicTests { - public partial class EconomicTests + private readonly Dictionary _schemes; + private readonly Hash _treasurySchemeId; + + public EconomicTests() { - private readonly Hash _treasurySchemeId; - private readonly Dictionary _schemes; + _schemes = AsyncHelper.RunSync(GetTreasurySchemesAsync); + _treasurySchemeId = AsyncHelper.RunSync(() => TreasuryStub.GetTreasurySchemeId.CallAsync(new Empty())); + } - public EconomicTests() - { - _schemes = AsyncHelper.RunSync(GetTreasurySchemesAsync); - _treasurySchemeId = AsyncHelper.RunSync(() => TreasuryStub.GetTreasurySchemeId.CallAsync(new Empty())); - } + /// + /// Distribute treasury after first term and check each profit scheme. + /// + /// + [IgnoreOnCIFact] + public async Task TreasuryDistribution_FirstTerm_Test() + { + const long period = 1; + long distributedAmount; - /// - /// Distribute treasury after first term and check each profit scheme. - /// - /// - [IgnoreOnCIFact] - public async Task TreasuryDistribution_FirstTerm_Test() - { - const long period = 1; - long distributedAmount; - - //Without candidate announce election - var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(0); - - // First 7 core data centers announce election. - var list = ConvertKeyPairsToElectionStubs( - MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7)); - var announceTransactions = list.Select((stub, i) => - stub.AnnounceElection.GetTransaction( - Address.FromPublicKey(MissionedECKeyPairs.CoreDataCenterKeyPairs.ToList()[i].PublicKey))).ToList(); + //Without candidate announce election + var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(0); + + // First 7 core data centers announce election. + var list = ConvertKeyPairsToElectionStubs( + MissionedECKeyPairs.CoreDataCenterKeyPairs.Take(7)); + var announceTransactions = list.Select((stub, i) => + stub.AnnounceElection.GetTransaction( + Address.FromPublicKey(MissionedECKeyPairs.CoreDataCenterKeyPairs.ToList()[i].PublicKey))).ToList(); - await BlockMiningService.MineBlockAsync(announceTransactions); + await BlockMiningService.MineBlockAsync(announceTransactions); - // Check candidates. - candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(7); + // Check candidates. + candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(7); - // First 10 citizens do some votes. - var votesTransactions = new List(); - candidates.Value.ToList().ForEach(c => - votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 10))); - await BlockMiningService.MineBlockAsync(votesTransactions); + // First 10 citizens do some votes. + var votesTransactions = new List(); + candidates.Value.ToList().ForEach(c => + votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 10))); + await BlockMiningService.MineBlockAsync(votesTransactions); - // Check voted candidates - var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(7); + // Check voted candidates + var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(7); + + var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(1); + + // Check new term. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(2); + + // Now we have 12 miners. + var currentMiners = await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty()); + currentMiners.Pubkeys.Count.ShouldBe(12); + // And none of the initial miners was replaced. + MissionedECKeyPairs.InitialKeyPairs.Select(p => p.PublicKey.ToHex()) + .Except(currentMiners.Pubkeys.Select(p => p.ToHex())).Count().ShouldBe(0); + } - var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(1); + // Check distributed total amount. + { + distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; + var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod + { + SchemeId = _treasurySchemeId, + Period = period + }); + distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); + } - // Check new term. + // Check amount distributed to each scheme. + { + // Miner Basic Reward: 10% + 5% (from Flexible Reward) { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(2); - - // Now we have 12 miners. - var currentMiners = await ConsensusStub.GetCurrentMinerList.CallAsync(new Empty()); - currentMiners.Pubkeys.Count.ShouldBe(12); - // And none of the initial miners was replaced. - MissionedECKeyPairs.InitialKeyPairs.Select(p => p.PublicKey.ToHex()) - .Except(currentMiners.Pubkeys.Select(p => p.ToHex())).Count().ShouldBe(0); + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 10 + distributedAmount / 20); } - // Check distributed total amount. + // Backup Subsidy: 5% { - distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; - var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - SchemeId = _treasurySchemeId, - Period = period - }); - distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); } - // Check amount distributed to each scheme. + // Citizen Welfare: -75% (Burned) { - // Miner Basic Reward: 10% + 5% (from Flexible Reward) - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 10 + distributedAmount / 20); - } - - // Backup Subsidy: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - } - - // Citizen Welfare: -75% (Burned) - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(-distributedAmount * 3 / 4); - } + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(-distributedAmount * 3 / 4); + } - // Flexible Reward: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - } + // Flexible Reward: 5% + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + } - // Welcome Reward: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - } - return distributedAmount; + // Welcome Reward: 5% + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); } + return distributedAmount; } + } - [IgnoreOnCIFact] - public async Task TreasuryDistribution_SecondTerm_Test() - { - var information = new TreasuryDistributionInformation(); - const long period = 2; - long distributedAmount; + [IgnoreOnCIFact] + public async Task TreasuryDistribution_SecondTerm_Test() + { + var information = new TreasuryDistributionInformation(); + const long period = 2; + long distributedAmount; - var termNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; - if (termNumber < 2) - { - await TreasuryDistribution_FirstTerm_Test(); - } + var termNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; + if (termNumber < 2) await TreasuryDistribution_FirstTerm_Test(); - // Remain 10 core data centers announce election. - var list = ConvertKeyPairsToElectionStubs( - MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).Take(10)); - var announceTransactions = list.Select((stub, i) => - stub.AnnounceElection.GetTransaction( - Address.FromPublicKey(MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).ToList()[i] - .PublicKey))) - .ToList(); + // Remain 10 core data centers announce election. + var list = ConvertKeyPairsToElectionStubs( + MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).Take(10)); + var announceTransactions = list.Select((stub, i) => + stub.AnnounceElection.GetTransaction( + Address.FromPublicKey(MissionedECKeyPairs.CoreDataCenterKeyPairs.Skip(7).ToList()[i] + .PublicKey))) + .ToList(); - await BlockMiningService.MineBlockAsync(announceTransactions); + await BlockMiningService.MineBlockAsync(announceTransactions); - // Check candidates. - var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); + // Check candidates. + var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); - // First 10 citizens do some votes. - var votesTransactions = new List(); - candidates.Value.ToList().ForEach(c => - votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 10))); - await BlockMiningService.MineBlockAsync(votesTransactions); + // First 10 citizens do some votes. + var votesTransactions = new List(); + candidates.Value.ToList().ForEach(c => + votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 10))); + await BlockMiningService.MineBlockAsync(votesTransactions); - // Check voted candidates - var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); + // Check voted candidates + var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); - var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(2); + var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(2); - // Check term number. + // Check term number. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(3); + } + + // Check distributed total amount. + { + distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; + var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(3); - } + SchemeId = _treasurySchemeId, + Period = period + }); + distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); + + information.TotalAmount = distributedAmount; + } - // Check distributed total amount. + // Check amount distributed to each scheme. + { + // Miner Basic Reward: 10% { - distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; - var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 10); + var totalShares = distributedInformation.TotalShares; + var previousTermInformation = + ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 2 }).Result; + totalShares.ShouldBe( + previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks)); + + information[SchemeType.MinerBasicReward] = new DistributionInformation { - SchemeId = _treasurySchemeId, - Period = period - }); - distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); - - information.TotalAmount = distributedAmount; + Amount = amount, + TotalShares = totalShares + }; } - // Check amount distributed to each scheme. + // Backup Subsidy: 5% { - // Miner Basic Reward: 10% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 10); - var totalShares = distributedInformation.TotalShares; - var previousTermInformation = - ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value {Value = 2}).Result; - totalShares.ShouldBe( - previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks)); - - information[SchemeType.MinerBasicReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Backup Subsidy: 5% + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); + + information[SchemeType.BackupSubsidy] = new DistributionInformation { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBe(AEDPoSExtensionConstants.CoreDataCenterKeyPairCount); - - information[SchemeType.BackupSubsidy] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Citizen Welfare: 75% + 5% (from Flexible Reward) - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount * 4 / 5); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBePositive(); - - information[SchemeType.CitizenWelfare] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Welcome Reward: 5% + Amount = amount, + TotalShares = totalShares + }; + } + + // Citizen Welfare: 75% + 5% (from Flexible Reward) + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount * 4 / 5); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBePositive(); + + information[SchemeType.CitizenWelfare] = new DistributionInformation { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - // Went to miners. Now there are 10 miners. - totalShares.ShouldBe(10); - - information[SchemeType.WelcomeReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Flexible Reward: 5% + Amount = amount, + TotalShares = totalShares + }; + } + + // Welcome Reward: 5% + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + // Went to miners. Now there are 10 miners. + totalShares.ShouldBe(10); + + information[SchemeType.WelcomeReward] = new DistributionInformation { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBe(1); - - information[SchemeType.FlexibleReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } + Amount = amount, + TotalShares = totalShares + }; } - return information; + // Flexible Reward: 5% + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBe(1); + + information[SchemeType.FlexibleReward] = new DistributionInformation + { + Amount = amount, + TotalShares = totalShares + }; + } } - [Fact] - public async Task TreasuryDistribution_ThirdTerm_Test() - { - var information = new TreasuryDistributionInformation(); - const long period = 3; - long distributedAmount; + return information; + } - var termNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; - if (termNumber < 3) - { - await TreasuryDistribution_SecondTerm_Test(); - } + [Fact] + public async Task TreasuryDistribution_ThirdTerm_Test() + { + var information = new TreasuryDistributionInformation(); + const long period = 3; + long distributedAmount; + + var termNumber = (await ConsensusStub.GetCurrentTermNumber.CallAsync(new Empty())).Value; + if (termNumber < 3) await TreasuryDistribution_SecondTerm_Test(); - // 10 validation data centers announce election. - var list = ConvertKeyPairsToElectionStubs( - MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(10)); - var announceTransactions = list.Select((stub, i) => - stub.AnnounceElection.GetTransaction( - Address.FromPublicKey(MissionedECKeyPairs.ValidationDataCenterKeyPairs.ToList()[i].PublicKey))) - .ToList(); - await BlockMiningService.MineBlockAsync(announceTransactions); + // 10 validation data centers announce election. + var list = ConvertKeyPairsToElectionStubs( + MissionedECKeyPairs.ValidationDataCenterKeyPairs.Take(10)); + var announceTransactions = list.Select((stub, i) => + stub.AnnounceElection.GetTransaction( + Address.FromPublicKey(MissionedECKeyPairs.ValidationDataCenterKeyPairs.ToList()[i].PublicKey))) + .ToList(); + await BlockMiningService.MineBlockAsync(announceTransactions); // await BlockMiningService.MineBlockAsync(new List // { @@ -315,160 +306,155 @@ public async Task TreasuryDistribution_ThirdTer // }) // }); - // Check candidates. - var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(27); + // Check candidates. + var candidates = await ElectionStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(27); - // First 10 citizens do some votes. - var votesTransactions = new List(); - candidates.Value.ToList().ForEach(c => - votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 20))); - await BlockMiningService.MineBlockAsync(votesTransactions); + // First 10 citizens do some votes. + var votesTransactions = new List(); + candidates.Value.ToList().ForEach(c => + votesTransactions.AddRange(GetVoteTransactions(5, 100, c.ToHex(), 20))); + await BlockMiningService.MineBlockAsync(votesTransactions); - // Check voted candidates - var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(27); + // Check voted candidates + var votedCandidates = await ElectionStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(27); - var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(3); + var minedBlocksInFirstRound = await MineBlocksToNextTermAsync(3); + + // Check term number. + { + var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(4); + } - // Check term number. + // Check distributed total amount. + { + distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; + var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - var round = await ConsensusStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(4); - } + SchemeId = _treasurySchemeId, + Period = period + }); + distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); + + information.TotalAmount = distributedAmount; + } - // Check distributed total amount. + // Check amount distributed to each scheme. + { + // Miner Basic Reward: 10% { - distributedAmount = minedBlocksInFirstRound * EconomicTestConstants.RewardPerBlock; - var distributedInformation = await ProfitStub.GetDistributedProfitsInfo.CallAsync(new SchemePeriod + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 10); + var totalShares = distributedInformation.TotalShares; + var previousTermInformation = + ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 3 }).Result; + var producedBlocks = previousTermInformation.RealTimeMinersInformation.Values + .Select(i => i.ProducedBlocks).ToList(); + var average = CalculateAverage(producedBlocks); + var shares = producedBlocks.Select(i => CalculateShares(i, average)).ToList(); + totalShares.ShouldBe(shares.Sum()); + + information[SchemeType.MinerBasicReward] = new DistributionInformation { - SchemeId = _treasurySchemeId, - Period = period - }); - distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol].ShouldBe(distributedAmount); - - information.TotalAmount = distributedAmount; + Amount = amount, + TotalShares = totalShares + }; } - // Check amount distributed to each scheme. + // Backup Subsidy: 5% { - // Miner Basic Reward: 10% + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBe(27); + + information[SchemeType.BackupSubsidy] = new DistributionInformation { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.MinerBasicReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 10); - var totalShares = distributedInformation.TotalShares; - var previousTermInformation = - ConsensusStub.GetPreviousTermInformation.CallAsync(new Int64Value {Value = 3}).Result; - var producedBlocks = previousTermInformation.RealTimeMinersInformation.Values - .Select(i => i.ProducedBlocks).ToList(); - var average = CalculateAverage(producedBlocks); - var shares = producedBlocks.Select(i => CalculateShares(i, average)).ToList(); - totalShares.ShouldBe(shares.Sum()); - - information[SchemeType.MinerBasicReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Backup Subsidy: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.BackupSubsidy].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBe(27); - - information[SchemeType.BackupSubsidy] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Citizen Welfare: 75% + 5% (from Flexible Reward) - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount * 4 / 5); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBePositive(); - - information[SchemeType.CitizenWelfare] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Welcome Reward: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - // Went to 2 new miners -> Welcome - totalShares.ShouldBe(2); - - information[SchemeType.WelcomeReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } - - // Flexible Reward: 5% - { - var distributedInformation = - await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); - var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; - amount.ShouldBe(distributedAmount / 20); - var totalShares = distributedInformation.TotalShares; - totalShares.ShouldBe(1); - - information[SchemeType.FlexibleReward] = new DistributionInformation - { - Amount = amount, - TotalShares = totalShares - }; - } + Amount = amount, + TotalShares = totalShares + }; } - return information; - } - - /// - /// Just to make sure not using double type. - /// - /// - /// - private long CalculateAverage(List list) - { - var sum = list.Sum(); - return sum.Div(list.Count); - } - - private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) - { - if (producedBlocksCount < averageProducedBlocksCount.Div(2)) + // Citizen Welfare: 75% + 5% (from Flexible Reward) { - // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. - return 0; + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.CitizenWelfare].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount * 4 / 5); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBePositive(); + + information[SchemeType.CitizenWelfare] = new DistributionInformation + { + Amount = amount, + TotalShares = totalShares + }; } - if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) + // Welcome Reward: 5% { - // If count < (4/5) * average_count, then ratio will be (count / average_count) - return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.WelcomeReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + // Went to 2 new miners -> Welcome + totalShares.ShouldBe(2); + + information[SchemeType.WelcomeReward] = new DistributionInformation + { + Amount = amount, + TotalShares = totalShares + }; } - return producedBlocksCount; + // Flexible Reward: 5% + { + var distributedInformation = + await GetDistributedInformationAsync(_schemes[SchemeType.FlexibleReward].SchemeId, period); + var amount = distributedInformation.AmountsMap[EconomicTestConstants.TokenSymbol]; + amount.ShouldBe(distributedAmount / 20); + var totalShares = distributedInformation.TotalShares; + totalShares.ShouldBe(1); + + information[SchemeType.FlexibleReward] = new DistributionInformation + { + Amount = amount, + TotalShares = totalShares + }; + } } + + return information; + } + + /// + /// Just to make sure not using double type. + /// + /// + /// + private long CalculateAverage(List list) + { + var sum = list.Sum(); + return sum.Div(list.Count); + } + + private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) + { + if (producedBlocksCount < averageProducedBlocksCount.Div(2)) + // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. + return 0; + + if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) + // If count < (4/5) * average_count, then ratio will be (count / average_count) + return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); + + return producedBlocksCount; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj index cf117409df..05ddeb5025 100644 --- a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj +++ b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj @@ -8,12 +8,12 @@ - - - - - - + + + + + + @@ -62,9 +62,9 @@ Contract PreserveNewest - - - + + + false Contract @@ -90,8 +90,8 @@ Contract PreserveNewest - - + + @@ -172,6 +172,6 @@ - + diff --git a/test/AElf.Contracts.Economic.TestBase/AssemblyInfo.cs b/test/AElf.Contracts.Economic.TestBase/AssemblyInfo.cs index 54a9c393cb..e69de29bb2 100644 --- a/test/AElf.Contracts.Economic.TestBase/AssemblyInfo.cs +++ b/test/AElf.Contracts.Economic.TestBase/AssemblyInfo.cs @@ -1,2 +0,0 @@ -using System.Runtime.CompilerServices; - diff --git a/test/AElf.Contracts.Economic.TestBase/Contracts.cs b/test/AElf.Contracts.Economic.TestBase/Contracts.cs index af82346490..3e32bdd1cd 100644 --- a/test/AElf.Contracts.Economic.TestBase/Contracts.cs +++ b/test/AElf.Contracts.Economic.TestBase/Contracts.cs @@ -1,42 +1,41 @@ -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +public enum Contracts { - public enum Contracts - { - Association, - Configuration, - AEDPoS, - CrossChain, - Economic, - Election, - Genesis, - MultiToken, - Parliament, - Profit, - Referendum, - TransactionFee, - TokenConverter, - Treasury, - Vote, - TokenHolder - } + Association, + Configuration, + AEDPoS, + CrossChain, + Economic, + Election, + Genesis, + MultiToken, + Parliament, + Profit, + Referendum, + TransactionFee, + TokenConverter, + Treasury, + Vote, + TokenHolder +} - public enum TestContracts - { - BasicFunction, - BasicSecurity, - BasicUpdate, - MethodCallThreshold, - ResourceSpender - } +public enum TestContracts +{ + BasicFunction, + BasicSecurity, + BasicUpdate, + MethodCallThreshold, + ResourceSpender +} - public enum ProfitType - { - Treasury, - MinerReward, - BackupSubsidy, - CitizenWelfare, - BasicMinerReward, - WelcomeReward, - FlexibleReward, - } +public enum ProfitType +{ + Treasury, + MinerReward, + BackupSubsidy, + CitizenWelfare, + BasicMinerReward, + WelcomeReward, + FlexibleReward } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 9238942614..43c09934d5 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Configuration; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Election; @@ -18,630 +17,628 @@ 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; using Google.Protobuf.WellKnownTypes; using Shouldly; using Volo.Abp.Threading; -using ApproveInput = AElf.Contracts.MultiToken.ApproveInput; using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +// ReSharper disable InconsistentNaming +public partial class EconomicContractsTestBase { - // ReSharper disable InconsistentNaming - public partial class EconomicContractsTestBase - { - #region Private Preperties + #region Private Preperties - private const int Category = KernelConstants.CodeCoverageRunnerCategory; + private const int Category = KernelConstants.CodeCoverageRunnerCategory; - #endregion + #endregion - #region Contract Address + #region Contract Address - protected Dictionary ProfitItemsIds { get; set; } + protected Dictionary ProfitItemsIds { get; set; } - private Address _zeroAddress; - protected new Address ContractZeroAddress => GetZeroContract(); + private Address _zeroAddress; + protected new Address ContractZeroAddress => GetZeroContract(); - private Address _tokenAddress; - protected Address TokenContractAddress => GetOrDeployContract(Contracts.MultiToken, ref _tokenAddress); + private Address _tokenAddress; + protected Address TokenContractAddress => GetOrDeployContract(Contracts.MultiToken, ref _tokenAddress); - private Address _voteAddress; - protected Address VoteContractAddress => GetOrDeployContract(Contracts.Vote, ref _voteAddress); + private Address _voteAddress; + protected Address VoteContractAddress => GetOrDeployContract(Contracts.Vote, ref _voteAddress); - private Address _profitAddress; - protected Address ProfitContractAddress => GetOrDeployContract(Contracts.Profit, ref _profitAddress); + private Address _profitAddress; + protected Address ProfitContractAddress => GetOrDeployContract(Contracts.Profit, ref _profitAddress); - private Address _electionAddress; - protected Address ElectionContractAddress => GetOrDeployContract(Contracts.Election, ref _electionAddress); + private Address _electionAddress; + protected Address ElectionContractAddress => GetOrDeployContract(Contracts.Election, ref _electionAddress); - private Address _consensusAddress; - protected Address ConsensusContractAddress => GetOrDeployContract(Contracts.AEDPoS, ref _consensusAddress); + private Address _consensusAddress; + protected Address ConsensusContractAddress => GetOrDeployContract(Contracts.AEDPoS, ref _consensusAddress); - private Address _tokenConverterAddress; + private Address _tokenConverterAddress; - protected Address TokenConverterContractAddress => - GetOrDeployContract(Contracts.TokenConverter, ref _tokenConverterAddress); + protected Address TokenConverterContractAddress => + GetOrDeployContract(Contracts.TokenConverter, ref _tokenConverterAddress); - private Address _treasuryAddress; - protected Address TreasuryContractAddress => GetOrDeployContract(Contracts.Treasury, ref _treasuryAddress); + private Address _treasuryAddress; + protected Address TreasuryContractAddress => GetOrDeployContract(Contracts.Treasury, ref _treasuryAddress); - private Address _feeChargingAddress; + private Address _feeChargingAddress; - protected Address TransactionFeeChargingContractAddress => - GetOrDeployContract(Contracts.TransactionFee, ref _feeChargingAddress); - - private Address _associationAddress; - protected Address AssociationContractAddress => GetOrDeployContract(Contracts.Association, ref _associationAddress); - - private Address _methodCallThresholdAddress; + protected Address TransactionFeeChargingContractAddress => + GetOrDeployContract(Contracts.TransactionFee, ref _feeChargingAddress); - protected Address MethodCallThresholdContractAddress => - GetOrDeployContract(TestContracts.MethodCallThreshold, ref _methodCallThresholdAddress); + private Address _associationAddress; + protected Address AssociationContractAddress => GetOrDeployContract(Contracts.Association, ref _associationAddress); - private Address _economicAddress; - protected Address EconomicContractAddress => GetOrDeployContract(Contracts.Economic, ref _economicAddress); + private Address _methodCallThresholdAddress; - private Address _parliamentAddress; + protected Address MethodCallThresholdContractAddress => + GetOrDeployContract(TestContracts.MethodCallThreshold, ref _methodCallThresholdAddress); - protected Address ParliamentContractAddress => - GetOrDeployContract(Contracts.Parliament, ref _parliamentAddress); - - private Address _referendumAddress; + private Address _economicAddress; + protected Address EconomicContractAddress => GetOrDeployContract(Contracts.Economic, ref _economicAddress); - protected Address ReferendumContractAddress => - GetOrDeployContract(Contracts.Referendum, ref _referendumAddress); - - private Address _tokenHolderAddress; + private Address _parliamentAddress; - protected Address TokenHolderContractAddress => - GetOrDeployContract(Contracts.TokenHolder, ref _tokenHolderAddress); + protected Address ParliamentContractAddress => + GetOrDeployContract(Contracts.Parliament, ref _parliamentAddress); - private Address _configurationAddress; - protected Address ConfigurationAddress => - GetOrDeployContract(Contracts.Configuration, ref _configurationAddress); + private Address _referendumAddress; - #endregion + protected Address ReferendumContractAddress => + GetOrDeployContract(Contracts.Referendum, ref _referendumAddress); - #region Contract Stub + private Address _tokenHolderAddress; - internal BasicContractZeroContainer.BasicContractZeroStub BasicContractZeroStub => - GetContractZeroTester(BootMinerKeyPair); + protected Address TokenHolderContractAddress => + GetOrDeployContract(Contracts.TokenHolder, ref _tokenHolderAddress); - internal TokenContractContainer.TokenContractStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); + private Address _configurationAddress; - internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub => - GetTokenConverterContractTester(BootMinerKeyPair); + protected Address ConfigurationAddress => + GetOrDeployContract(Contracts.Configuration, ref _configurationAddress); - internal VoteContractContainer.VoteContractStub VoteContractStub => - GetVoteContractTester(BootMinerKeyPair); + #endregion - internal ProfitContractContainer.ProfitContractStub ProfitContractStub => - GetProfitContractTester(BootMinerKeyPair); + #region Contract Stub - internal ElectionContractContainer.ElectionContractStub ElectionContractStub => - GetElectionContractTester(BootMinerKeyPair); + internal BasicContractZeroContainer.BasicContractZeroStub BasicContractZeroStub => + GetContractZeroTester(BootMinerKeyPair); - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => - GetConsensusContractTester(BootMinerKeyPair); + internal TokenContractContainer.TokenContractStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); - internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub => - GetTreasuryContractTester(BootMinerKeyPair); + internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub => + GetTokenConverterContractTester(BootMinerKeyPair); - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetParliamentContractTester(BootMinerKeyPair); + internal VoteContractContainer.VoteContractStub VoteContractStub => + GetVoteContractTester(BootMinerKeyPair); - internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub - TransactionFeeChargingContractStub => GetTransactionFeeChargingContractTester(BootMinerKeyPair); + internal ProfitContractContainer.ProfitContractStub ProfitContractStub => + GetProfitContractTester(BootMinerKeyPair); - internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub MethodCallThresholdContractStub => - GetMethodCallThresholdContractTester(BootMinerKeyPair); + internal ElectionContractContainer.ElectionContractStub ElectionContractStub => + GetElectionContractTester(BootMinerKeyPair); - internal EconomicContractContainer.EconomicContractStub EconomicContractStub => - GetEconomicContractTester(BootMinerKeyPair); + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => + GetConsensusContractTester(BootMinerKeyPair); - internal ConfigurationContainer.ConfigurationStub ConfigurationStub => - GetConfigurationContractTester(BootMinerKeyPair); - #endregion + internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub => + GetTreasuryContractTester(BootMinerKeyPair); - #region Get Contract Stub Tester + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetParliamentContractTester(BootMinerKeyPair); - internal BasicContractZeroContainer.BasicContractZeroStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub + TransactionFeeChargingContractStub => GetTransactionFeeChargingContractTester(BootMinerKeyPair); - internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub MethodCallThresholdContractStub => + GetMethodCallThresholdContractTester(BootMinerKeyPair); - internal TokenConverterContractContainer.TokenConverterContractStub GetTokenConverterContractTester( - ECKeyPair keyPair) - { - return GetTester(TokenConverterContractAddress, - keyPair); - } + internal EconomicContractContainer.EconomicContractStub EconomicContractStub => + GetEconomicContractTester(BootMinerKeyPair); - internal VoteContractContainer.VoteContractStub GetVoteContractTester(ECKeyPair keyPair) - { - return GetTester(VoteContractAddress, keyPair); - } + internal ConfigurationContainer.ConfigurationStub ConfigurationStub => + GetConfigurationContractTester(BootMinerKeyPair); - internal ProfitContractContainer.ProfitContractStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } + #endregion - internal ElectionContractContainer.ElectionContractStub GetElectionContractTester(ECKeyPair keyPair) - { - return GetTester(ElectionContractAddress, keyPair); - } + #region Get Contract Stub Tester - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal BasicContractZeroContainer.BasicContractZeroStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal TreasuryContractContainer.TreasuryContractStub GetTreasuryContractTester(ECKeyPair keyPair) - { - return GetTester(TreasuryContractAddress, keyPair); - } + internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + internal TokenConverterContractContainer.TokenConverterContractStub GetTokenConverterContractTester( + ECKeyPair keyPair) + { + return GetTester(TokenConverterContractAddress, + keyPair); + } - internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub - GetTransactionFeeChargingContractTester(ECKeyPair keyPair) - { - return GetTester( - TransactionFeeChargingContractAddress, keyPair); - } + internal VoteContractContainer.VoteContractStub GetVoteContractTester(ECKeyPair keyPair) + { + return GetTester(VoteContractAddress, keyPair); + } - internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub - GetMethodCallThresholdContractTester( - ECKeyPair keyPair) - { - return GetTester( - MethodCallThresholdContractAddress, - keyPair); - } + internal ProfitContractContainer.ProfitContractStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } - internal EconomicContractContainer.EconomicContractStub GetEconomicContractTester(ECKeyPair keyPair) - { - return GetTester(EconomicContractAddress, keyPair); - } + internal ElectionContractContainer.ElectionContractStub GetElectionContractTester(ECKeyPair keyPair) + { + return GetTester(ElectionContractAddress, keyPair); + } - internal ConfigurationContainer.ConfigurationStub GetConfigurationContractTester(ECKeyPair keyPair) - { - return GetTester(ConfigurationAddress, keyPair); - } + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } - #endregion + internal TreasuryContractContainer.TreasuryContractStub GetTreasuryContractTester(ECKeyPair keyPair) + { + return GetTester(TreasuryContractAddress, keyPair); + } - #region Get or Deploy Contract + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - private Address GetZeroContract() - { - if (_zeroAddress != null) - return _zeroAddress; + internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub + GetTransactionFeeChargingContractTester(ECKeyPair keyPair) + { + return GetTester( + TransactionFeeChargingContractAddress, keyPair); + } - _zeroAddress = ContractAddressService.GetZeroSmartContractAddress(); + internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub + GetMethodCallThresholdContractTester( + ECKeyPair keyPair) + { + return GetTester( + MethodCallThresholdContractAddress, + keyPair); + } + + internal EconomicContractContainer.EconomicContractStub GetEconomicContractTester(ECKeyPair keyPair) + { + return GetTester(EconomicContractAddress, keyPair); + } + + internal ConfigurationContainer.ConfigurationStub GetConfigurationContractTester(ECKeyPair keyPair) + { + return GetTester(ConfigurationAddress, keyPair); + } + + #endregion + + #region Get or Deploy Contract + + private Address GetZeroContract() + { + if (_zeroAddress != null) return _zeroAddress; - } - private Address GetOrDeployContract(Contracts contract, ref Address address) - { - if (address != null) - return address; + _zeroAddress = ContractAddressService.GetZeroSmartContractAddress(); + return _zeroAddress; + } - address = AsyncHelper.RunSync(() => DeployContract(contract)); + private Address GetOrDeployContract(Contracts contract, ref Address address) + { + if (address != null) return address; - } - private Address GetOrDeployContract(TestContracts contract, ref Address address) - { - if (address != null) - return address; + address = AsyncHelper.RunSync(() => DeployContract(contract)); + return address; + } - address = AsyncHelper.RunSync(() => DeployContract(contract)); + private Address GetOrDeployContract(TestContracts contract, ref Address address) + { + if (address != null) return address; - } - private async Task
DeployContract(Contracts contract) - { - var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; - Hash hash; - switch (contract) - { - case Contracts.Parliament: - hash = HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); - break; - case Contracts.AEDPoS: - hash = HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); - break; - case Contracts.MultiToken: - hash = HashHelper.ComputeFrom("AElf.ContractNames.Token"); - break; - case Contracts.TransactionFee: - hash = HashHelper.ComputeFrom("AElf.ContractNames.TransactionFeeCharging"); - break; - default: - hash = HashHelper.ComputeFrom($"AElf.ContractNames.{contract.ToString()}"); - break; - } - - var address = await DeploySystemSmartContract(Category, code, hash, BootMinerKeyPair); + address = AsyncHelper.RunSync(() => DeployContract(contract)); + return address; + } - return address; - } + private async Task
DeployContract(Contracts contract) + { + var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; + Hash hash; + switch (contract) + { + case Contracts.Parliament: + hash = HashHelper.ComputeFrom("AElf.ContractNames.Parliament"); + break; + case Contracts.AEDPoS: + hash = HashHelper.ComputeFrom("AElf.ContractNames.Consensus"); + break; + case Contracts.MultiToken: + hash = HashHelper.ComputeFrom("AElf.ContractNames.Token"); + break; + case Contracts.TransactionFee: + hash = HashHelper.ComputeFrom("AElf.ContractNames.TransactionFeeCharging"); + break; + default: + hash = HashHelper.ComputeFrom($"AElf.ContractNames.{contract.ToString()}"); + break; + } + + var address = await DeploySystemSmartContract(Category, code, hash, BootMinerKeyPair); + + return address; + } - private async Task
DeployContract(TestContracts contract) - { - var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; - var hash = HashHelper.ComputeFrom($"AElf.ContractNames.{contract.ToString()}"); - var address = await DeploySystemSmartContract(Category, code, hash, BootMinerKeyPair); + private async Task
DeployContract(TestContracts contract) + { + var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; + var hash = HashHelper.ComputeFrom($"AElf.ContractNames.{contract.ToString()}"); + var address = await DeploySystemSmartContract(Category, code, hash, BootMinerKeyPair); - return address; - } + return address; + } - protected void DeployAllContracts() - { - _ = VoteContractAddress; - _ = ProfitContractAddress; - _ = EconomicContractAddress; - _ = ElectionContractAddress; - _ = TreasuryContractAddress; - _ = TransactionFeeChargingContractAddress; - _ = ParliamentContractAddress; - _ = TokenConverterContractAddress; - _ = ConsensusContractAddress; - _ = MethodCallThresholdContractAddress; - _ = ReferendumContractAddress; - _ = TokenContractAddress; - _ = TokenHolderContractAddress; - _ = AssociationContractAddress; - } + protected void DeployAllContracts() + { + _ = VoteContractAddress; + _ = ProfitContractAddress; + _ = EconomicContractAddress; + _ = ElectionContractAddress; + _ = TreasuryContractAddress; + _ = TransactionFeeChargingContractAddress; + _ = ParliamentContractAddress; + _ = TokenConverterContractAddress; + _ = ConsensusContractAddress; + _ = MethodCallThresholdContractAddress; + _ = ReferendumContractAddress; + _ = TokenContractAddress; + _ = TokenHolderContractAddress; + _ = AssociationContractAddress; + } - #endregion + #endregion - #region Contract Initialize + #region Contract Initialize - protected async Task InitializeTreasuryConverter() + protected async Task InitializeTreasuryConverter() + { { - { - var result = - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - CheckResult(result.TransactionResult); - } - { - var result = - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( - new Empty()); - CheckResult(result.TransactionResult); - } - //get profit ids - { - var profitIds = (await ProfitContractStub.GetManagingSchemeIds.CallAsync( - new GetManagingSchemeIdsInput - { - Manager = TreasuryContractAddress - })).SchemeIds; - ProfitItemsIds = new Dictionary - { - {ProfitType.Treasury, profitIds[0]}, - {ProfitType.MinerReward, profitIds[1]}, - {ProfitType.BasicMinerReward, profitIds[2]}, - {ProfitType.FlexibleReward, profitIds[3]}, - {ProfitType.WelcomeReward, profitIds[4]}, - }; - } - { - var profitIds = (await ProfitContractStub.GetManagingSchemeIds.CallAsync( - new GetManagingSchemeIdsInput - { - Manager = ElectionContractAddress - })).SchemeIds; - ProfitItemsIds.Add(ProfitType.BackupSubsidy, profitIds[0]); - ProfitItemsIds.Add(ProfitType.CitizenWelfare, profitIds[1]); - } + var result = + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + CheckResult(result.TransactionResult); } - - protected async Task InitializeElection() { - var minerList = InitialCoreDataCenterKeyPairs.Select(o => o.PublicKey.ToHex()).ToArray(); - var result = await ElectionContractStub.InitialElectionContract.SendAsync(new InitialElectionContractInput - { - MaximumLockTime = 1080 * 86400, - MinimumLockTime = 90 * 86400, - TimeEachTerm = EconomicContractsTestConstants.PeriodSeconds, - MinerList = {minerList}, - MinerIncreaseInterval = EconomicContractsTestConstants.MinerIncreaseInterval - }); + var result = + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( + new Empty()); CheckResult(result.TransactionResult); } - - protected async Task InitializeEconomicContract() + //get profit ids { - //create native token + var profitIds = (await ProfitContractStub.GetManagingSchemeIds.CallAsync( + new GetManagingSchemeIdsInput + { + Manager = TreasuryContractAddress + })).SchemeIds; + ProfitItemsIds = new Dictionary { - var result = await EconomicContractStub.InitialEconomicSystem.SendAsync(new InitialEconomicSystemInput + { ProfitType.Treasury, profitIds[0] }, + { ProfitType.MinerReward, profitIds[1] }, + { ProfitType.BasicMinerReward, profitIds[2] }, + { ProfitType.FlexibleReward, profitIds[3] }, + { ProfitType.WelcomeReward, profitIds[4] } + }; + } + { + var profitIds = (await ProfitContractStub.GetManagingSchemeIds.CallAsync( + new GetManagingSchemeIdsInput { - NativeTokenDecimals = EconomicContractsTestConstants.Decimals, - IsNativeTokenBurnable = EconomicContractsTestConstants.IsBurnable, - NativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol, - NativeTokenTotalSupply = EconomicContractsTestConstants.TotalSupply, - MiningRewardTotalAmount = EconomicContractsTestConstants.TotalSupply / 5, - }); - CheckResult(result.TransactionResult); - } + Manager = ElectionContractAddress + })).SchemeIds; + ProfitItemsIds.Add(ProfitType.BackupSubsidy, profitIds[0]); + ProfitItemsIds.Add(ProfitType.CitizenWelfare, profitIds[1]); } + } - protected async Task InitialMiningRewards() + protected async Task InitializeElection() + { + var minerList = InitialCoreDataCenterKeyPairs.Select(o => o.PublicKey.ToHex()).ToArray(); + var result = await ElectionContractStub.InitialElectionContract.SendAsync(new InitialElectionContractInput + { + MaximumLockTime = 1080 * 86400, + MinimumLockTime = 90 * 86400, + TimeEachTerm = EconomicContractsTestConstants.PeriodSeconds, + MinerList = { minerList }, + MinerIncreaseInterval = EconomicContractsTestConstants.MinerIncreaseInterval + }); + CheckResult(result.TransactionResult); + } + + protected async Task InitializeEconomicContract() + { + //create native token { - //Issue native token to core data center keyPairs + var result = await EconomicContractStub.InitialEconomicSystem.SendAsync(new InitialEconomicSystemInput { - var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.TotalSupply / 5, - To = TreasuryContractAddress, - Memo = "Set mining rewards." - }); - CheckResult(result.TransactionResult); - } + NativeTokenDecimals = EconomicContractsTestConstants.Decimals, + IsNativeTokenBurnable = EconomicContractsTestConstants.IsBurnable, + NativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol, + NativeTokenTotalSupply = EconomicContractsTestConstants.TotalSupply, + MiningRewardTotalAmount = EconomicContractsTestConstants.TotalSupply / 5 + }); + CheckResult(result.TransactionResult); } + } - protected async Task InitializeToken() + protected async Task InitialMiningRewards() + { + //Issue native token to core data center keyPairs { - //issue some to default user and buy resource + var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var issueResult = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = 1000_000_00000000L, - To = BootMinerAddress, - Memo = "Used to transfer other testers" - }); - CheckResult(issueResult.TransactionResult); - - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = BootMinerAddress, - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(1000_000_00000000L); - } + Amount = EconomicContractsTestConstants.TotalSupply / 5, + To = TreasuryContractAddress, + Memo = "Set mining rewards." + }); + CheckResult(result.TransactionResult); + } + } - foreach (var coreDataCenterKeyPair in CoreDataCenterKeyPairs) + protected async Task InitializeToken() + { + //issue some to default user and buy resource + { + var issueResult = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.LockTokenForElection * 10, - To = Address.FromPublicKey(coreDataCenterKeyPair.PublicKey), - Memo = "Used to announce election." - }); - CheckResult(result.TransactionResult); - } + Amount = 1000_000_00000000L, + To = BootMinerAddress, + Memo = "Used to transfer other testers" + }); + CheckResult(issueResult.TransactionResult); - foreach (var validationDataCenterKeyPair in ValidationDataCenterKeyPairs) + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, - To = Address.FromPublicKey(validationDataCenterKeyPair.PublicKey), - Memo = "Used to announce election." - }); - CheckResult(result.TransactionResult); - } + Owner = BootMinerAddress, + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(1000_000_00000000L); + } - foreach (var validationDataCenterCandidateKeyPair in ValidationDataCenterCandidateKeyPairs) + foreach (var coreDataCenterKeyPair in CoreDataCenterKeyPairs) + { + var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, - To = Address.FromPublicKey(validationDataCenterCandidateKeyPair.PublicKey), - Memo = "Used to announce election." - }); - CheckResult(result.TransactionResult); - } + Amount = EconomicContractsTestConstants.LockTokenForElection * 10, + To = Address.FromPublicKey(coreDataCenterKeyPair.PublicKey), + Memo = "Used to announce election." + }); + CheckResult(result.TransactionResult); + } - foreach (var voterKeyPair in VoterKeyPairs) + foreach (var validationDataCenterKeyPair in ValidationDataCenterKeyPairs) + { + var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, - To = Address.FromPublicKey(voterKeyPair.PublicKey), - Memo = "Used to vote data center." - }); - CheckResult(result.TransactionResult); - } + Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, + To = Address.FromPublicKey(validationDataCenterKeyPair.PublicKey), + Memo = "Used to announce election." + }); + CheckResult(result.TransactionResult); } - protected async Task InitializeAElfConsensus() + foreach (var validationDataCenterCandidateKeyPair in ValidationDataCenterCandidateKeyPairs) { + var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var result = await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = EconomicContractsTestConstants.MinerIncreaseInterval - }); - CheckResult(result.TransactionResult); - } + Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, + To = Address.FromPublicKey(validationDataCenterCandidateKeyPair.PublicKey), + Memo = "Used to announce election." + }); + CheckResult(result.TransactionResult); + } + + foreach (var voterKeyPair in VoterKeyPairs) + { + var result = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput { - var result = await AEDPoSContractStub.FirstRound.SendAsync( - new MinerList - { - Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, StartTimestamp)); - CheckResult(result.TransactionResult); - } + Amount = EconomicContractsTestConstants.UserInitializeTokenAmount, + To = Address.FromPublicKey(voterKeyPair.PublicKey), + Memo = "Used to vote data center." + }); + CheckResult(result.TransactionResult); } + } - protected async Task InitializeTransactionFeeChargingContract() + protected async Task InitializeAElfConsensus() + { { - await ExecuteProposalForParliamentTransaction(TokenContractAddress, - nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), TransactionFeeChargingContractAddress); - var result = await TransactionFeeChargingContractStub.InitializeTransactionFeeChargingContract.SendAsync( - new InitializeTransactionFeeChargingContractInput + var result = await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput { - Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol + PeriodSeconds = 604800L, + MinerIncreaseInterval = EconomicContractsTestConstants.MinerIncreaseInterval }); CheckResult(result.TransactionResult); - - { - var approveResult = await TokenContractStub.Approve.SendAsync(new ApproveInput + } + { + var result = await AEDPoSContractStub.FirstRound.SendAsync( + new MinerList { - Symbol = EconomicContractsTestConstants.NativeTokenSymbol, - Spender = TokenConverterContractAddress, - Amount = 1000_000_00000000L - }); - approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, StartTimestamp)); + CheckResult(result.TransactionResult); + } + } - foreach (var coreDataCenterKeyPair in CoreDataCenterKeyPairs) + protected async Task InitializeTransactionFeeChargingContract() + { + await ExecuteProposalForParliamentTransaction(TokenContractAddress, + nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), TransactionFeeChargingContractAddress); + var result = await TransactionFeeChargingContractStub.InitializeTransactionFeeChargingContract.SendAsync( + new InitializeTransactionFeeChargingContractInput { - var tokenStub = GetTokenContractTester(coreDataCenterKeyPair); - var approveResult = await tokenStub.Approve.SendAsync(new ApproveInput - { - Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, - Spender = TreasuryContractAddress, - Amount = 1000_000_00000000L - }); - approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } + Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol + }); + CheckResult(result.TransactionResult); - protected async Task InitializeTokenConverter() { - await SetConnectors(); + var approveResult = await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = EconomicContractsTestConstants.NativeTokenSymbol, + Spender = TokenConverterContractAddress, + Amount = 1000_000_00000000L + }); + approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - protected async Task InitializeParliamentContract() + foreach (var coreDataCenterKeyPair in CoreDataCenterKeyPairs) { - var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + var tokenStub = GetTokenContractTester(coreDataCenterKeyPair); + var approveResult = await tokenStub.Approve.SendAsync(new ApproveInput { - PrivilegedProposer = BootMinerAddress, - ProposerAuthorityRequired = true + Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, + Spender = TreasuryContractAddress, + Amount = 1000_000_00000000L }); - CheckResult(initializeResult.TransactionResult); + approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - protected async Task SetConnectors() + protected async Task InitializeTokenConverter() + { + await SetConnectors(); + } + + protected async Task InitializeParliamentContract() + { + var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput { - { - await SetConnector(new PairConnectorParam - { - ResourceConnectorSymbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, - ResourceWeight = "0.05", - NativeWeight = "0.05", - NativeVirtualBalance = 1_000_000_00000000, - }); - } - } + PrivilegedProposer = BootMinerAddress, + ProposerAuthorityRequired = true + }); + CheckResult(initializeResult.TransactionResult); + } - private async Task ApproveByParliamentMembers(Hash proposalId) + protected async Task SetConnectors() + { { - foreach (var bp in InitialCoreDataCenterKeyPairs) + await SetConnector(new PairConnectorParam { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - CheckResult(approveResult.TransactionResult); - } + ResourceConnectorSymbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, + ResourceWeight = "0.05", + NativeWeight = "0.05", + NativeVirtualBalance = 1_000_000_00000000 + }); } + } - private async Task CreateAndApproveProposalForParliament(Address contract, - string method, IMessage input, Address parliamentOrganization = null) + private async Task ApproveByParliamentMembers(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = parliamentOrganization, - ContractMethodName = method, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contract - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - CheckResult(createResult.TransactionResult); - var proposalHash = createResult.Output; - await ApproveByParliamentMembers(proposalHash); - return proposalHash; + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + CheckResult(approveResult.TransactionResult); } + } + private async Task CreateAndApproveProposalForParliament(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = parliamentOrganization, + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contract + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + CheckResult(createResult.TransactionResult); + var proposalHash = createResult.Output; + await ApproveByParliamentMembers(proposalHash); + return proposalHash; + } - protected async Task ExecuteProposalForParliamentTransaction(Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); - CheckResult(releaseResult.TransactionResult); - } - - protected async Task ExecuteProposalForParliamentTransactionWithException(Address from, Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); - return releaseResult.TransactionResult; - } + protected async Task ExecuteProposalForParliamentTransaction(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); + CheckResult(releaseResult.TransactionResult); + } + + protected async Task ExecuteProposalForParliamentTransactionWithException(Address from, + Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); + return releaseResult.TransactionResult; + } - #endregion + #endregion - #region Other Methods + #region Other Methods - private void CheckResult(TransactionResult result) - { - if (!string.IsNullOrEmpty(result.Error)) - { - throw new Exception(result.Error); - } - } + private void CheckResult(TransactionResult result) + { + if (!string.IsNullOrEmpty(result.Error)) throw new Exception(result.Error); + } - private async Task SetConnector(PairConnectorParam connector) + private async Task SetConnector(PairConnectorParam connector) + { + var connectorManagerAddress = + await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); + var proposal = new CreateProposalInput { - var connectorManagerAddress = await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = connectorManagerAddress.OwnerAddress, - ContractMethodName = nameof(TokenConverterContractStub.AddPairConnector), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = connector.ToByteString(), - ToAddress = TokenConverterContractAddress - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - CheckResult(createResult.TransactionResult); - - var proposalHash = createResult.Output; - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalHash); - CheckResult(approveResult.TransactionResult); - } + OrganizationAddress = connectorManagerAddress.OwnerAddress, + ContractMethodName = nameof(TokenConverterContractStub.AddPairConnector), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = connector.ToByteString(), + ToAddress = TokenConverterContractAddress + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + CheckResult(createResult.TransactionResult); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); - CheckResult(releaseResult.TransactionResult); + var proposalHash = createResult.Output; + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalHash); + CheckResult(approveResult.TransactionResult); } - #endregion + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalHash); + CheckResult(releaseResult.TransactionResult); } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs index 0b455aeb83..60a5a0d350 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs @@ -7,45 +7,44 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +public partial class EconomicContractsTestBase : ContractTestBase { - public partial class EconomicContractsTestBase : ContractTestBase - { - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); - - protected Timestamp StartTimestamp => TimestampHelper.GetUtcNow(); - - protected ECKeyPair BootMinerKeyPair => Accounts[0].KeyPair; - - protected Address BootMinerAddress => Address.FromPublicKey(BootMinerKeyPair.PublicKey); - - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - - protected List CoreDataCenterKeyPairs => - Accounts.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Take(EconomicContractsTestConstants.CoreDataCenterCount).Select(a => a.KeyPair).ToList(); - - protected List ValidationDataCenterKeyPairs => - Accounts - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + - EconomicContractsTestConstants.CoreDataCenterCount) - .Take(EconomicContractsTestConstants.ValidateDataCenterCount).Select(a => a.KeyPair).ToList(); - - protected List ValidationDataCenterCandidateKeyPairs => - Accounts - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + - EconomicContractsTestConstants.CoreDataCenterCount + - EconomicContractsTestConstants.ValidateDataCenterCount) - .Take(EconomicContractsTestConstants.ValidateDataCenterCandidateCount).Select(a => a.KeyPair).ToList(); - - protected List VoterKeyPairs => - Accounts - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + - EconomicContractsTestConstants.CoreDataCenterCount + - EconomicContractsTestConstants.ValidateDataCenterCount + - EconomicContractsTestConstants.ValidateDataCenterCandidateCount) - .Take(EconomicContractsTestConstants.VoterCount).Select(a => a.KeyPair).ToList(); - } + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); + + protected Timestamp StartTimestamp => TimestampHelper.GetUtcNow(); + + protected ECKeyPair BootMinerKeyPair => Accounts[0].KeyPair; + + protected Address BootMinerAddress => Address.FromPublicKey(BootMinerKeyPair.PublicKey); + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + + protected List CoreDataCenterKeyPairs => + Accounts.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Take(EconomicContractsTestConstants.CoreDataCenterCount).Select(a => a.KeyPair).ToList(); + + protected List ValidationDataCenterKeyPairs => + Accounts + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + + EconomicContractsTestConstants.CoreDataCenterCount) + .Take(EconomicContractsTestConstants.ValidateDataCenterCount).Select(a => a.KeyPair).ToList(); + + protected List ValidationDataCenterCandidateKeyPairs => + Accounts + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + + EconomicContractsTestConstants.CoreDataCenterCount + + EconomicContractsTestConstants.ValidateDataCenterCount) + .Take(EconomicContractsTestConstants.ValidateDataCenterCandidateCount).Select(a => a.KeyPair).ToList(); + + protected List VoterKeyPairs => + Accounts + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount + + EconomicContractsTestConstants.CoreDataCenterCount + + EconomicContractsTestConstants.ValidateDataCenterCount + + EconomicContractsTestConstants.ValidateDataCenterCandidateCount) + .Take(EconomicContractsTestConstants.VoterCount).Select(a => a.KeyPair).ToList(); } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestConstants.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestConstants.cs index 3e43f487d6..d1cb065bb7 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestConstants.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestConstants.cs @@ -1,29 +1,28 @@ -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +public class EconomicContractsTestConstants { - public class EconomicContractsTestConstants - { - public const string NativeTokenSymbol = "ELF"; - public const string TransactionFeeChargingContractTokenSymbol = "TFCC"; - public const int Decimals = 8; - public const bool IsBurnable = true; - public const long TotalSupply = 1_000_000_000_00000000; + public const string NativeTokenSymbol = "ELF"; + public const string TransactionFeeChargingContractTokenSymbol = "TFCC"; + public const int Decimals = 8; + public const bool IsBurnable = true; + public const long TotalSupply = 1_000_000_000_00000000; + + public const int InitialCoreDataCenterCount = 5; + public const int CoreDataCenterCount = 7; + public const int ValidateDataCenterCount = 35; + public const int ValidateDataCenterCandidateCount = 13; + public const int VoterCount = 10; + public const int SupposedMinersCount = 17; + + public const int MiningInterval = 4000; + public const long PeriodSeconds = 604800; + public const long MinerIncreaseInterval = 31536000; + + public const string VoteSymbol = "VOTE"; + public const long LockTokenForElection = 100_000_00000000; + public const long UserInitializeTokenAmount = 110_000_00000000; + public const long ElfTokenPerBlock = 1250_0000; - public const int InitialCoreDataCenterCount = 5; - public const int CoreDataCenterCount = 7; - public const int ValidateDataCenterCount = 35; - public const int ValidateDataCenterCandidateCount = 13; - public const int VoterCount = 10; - public const int SupposedMinersCount = 17; - - public const int MiningInterval = 4000; - public const long PeriodSeconds = 604800; - public const long MinerIncreaseInterval = 31536000; - - public const string VoteSymbol = "VOTE"; - public const long LockTokenForElection = 100_000_00000000; - public const long UserInitializeTokenAmount = 110_000_00000000; - public const long ElfTokenPerBlock = 1250_0000; - - public const string TokenConverterFeeRate = "0.005"; - } + public const string TokenConverterFeeRate = "0.005"; } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs index c5fd72af1d..158133ef8a 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs @@ -8,25 +8,24 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +[DependsOn(typeof(ContractTestModule))] +public class EconomicContractsTestModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - public class EconomicContractsTestModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); + Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - // context.Services.AddSingleton(); - // context.Services.AddSingleton(); - // context.Services.AddSingleton(); - // context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.RemoveAll(); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + // context.Services.AddSingleton(); + // context.Services.AddSingleton(); + // context.Services.AddSingleton(); + // context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicTestTransactionExecutor.cs b/test/AElf.Contracts.Economic.TestBase/EconomicTestTransactionExecutor.cs index 81c80f97cb..74b1d2d7c8 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicTestTransactionExecutor.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicTestTransactionExecutor.cs @@ -8,77 +8,75 @@ using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContractExecution.Application; -using AElf.Kernel.TransactionPool.Application; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +//TODO: should inherit from base class, not a new executor +public class EconomicTestTransactionExecutor : ITestTransactionExecutor { - //TODO: should inherit from base class, not a new executor - public class EconomicTestTransactionExecutor : ITestTransactionExecutor + private readonly IServiceProvider _serviceProvider; + + public EconomicTestTransactionExecutor(IServiceProvider serviceProvider) { - private readonly IServiceProvider _serviceProvider; + _serviceProvider = serviceProvider; + } - public EconomicTestTransactionExecutor(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } + public async Task ExecuteAsync(Transaction transaction) + { + var blockTimeProvider = _serviceProvider.GetRequiredService(); + var blockchainService = _serviceProvider.GetRequiredService(); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var miningService = _serviceProvider.GetRequiredService(); + var blockAttachService = _serviceProvider.GetRequiredService(); - public async Task ExecuteAsync(Transaction transaction) - { - var blockTimeProvider = _serviceProvider.GetRequiredService(); - var blockchainService = _serviceProvider.GetRequiredService(); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var miningService = _serviceProvider.GetRequiredService(); - var blockAttachService = _serviceProvider.GetRequiredService(); + var transactions = new List { transaction }; + var blockExecutedSet = await miningService.MineAsync( + new RequestMiningDto + { + PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, transactions, blockTimeProvider.GetBlockTime()); - var transactions = new List {transaction}; - var blockExecutedSet = await miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = int.MaxValue - }, transactions, blockTimeProvider.GetBlockTime()); - - var block = blockExecutedSet.Block; + var block = blockExecutedSet.Block; - await blockchainService.AddTransactionsAsync(transactions); - await blockchainService.AddBlockAsync(block); - await blockAttachService.AttachBlockAsync(block); + await blockchainService.AddTransactionsAsync(transactions); + await blockchainService.AddBlockAsync(block); + await blockAttachService.AttachBlockAsync(block); - return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; - } + return blockExecutedSet.TransactionResultMap[transaction.GetHash()]; + } - public Task ExecuteWithExceptionAsync(Transaction transaction) - { - throw new NotImplementedException(); - } + public Task ExecuteWithExceptionAsync(Transaction transaction) + { + throw new NotImplementedException(); + } - public async Task ReadAsync(Transaction transaction) - { - var blockchainService = _serviceProvider.GetRequiredService(); - var transactionReadOnlyExecutionService = - _serviceProvider.GetRequiredService(); - var blockTimeProvider = _serviceProvider.GetRequiredService(); + public async Task ReadAsync(Transaction transaction) + { + var blockchainService = _serviceProvider.GetRequiredService(); + var transactionReadOnlyExecutionService = + _serviceProvider.GetRequiredService(); + var blockTimeProvider = _serviceProvider.GetRequiredService(); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = preBlock.GetHash(), - BlockHeight = preBlock.Height - }, - transaction, - blockTimeProvider.GetBlockTime()); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext + { + BlockHash = preBlock.GetHash(), + BlockHeight = preBlock.Height + }, + transaction, + blockTimeProvider.GetBlockTime()); - return transactionTrace.ReturnValue; - } + return transactionTrace.ReturnValue; + } - public Task ReadWithExceptionAsync(Transaction transaction) - { - throw new NotImplementedException(); - } + public Task ReadWithExceptionAsync(Transaction transaction) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/MockBlockValidationService.cs b/test/AElf.Contracts.Economic.TestBase/MockBlockValidationService.cs index 2401d42b1e..976265daa4 100644 --- a/test/AElf.Contracts.Economic.TestBase/MockBlockValidationService.cs +++ b/test/AElf.Contracts.Economic.TestBase/MockBlockValidationService.cs @@ -2,23 +2,22 @@ using AElf.Kernel; using AElf.Kernel.Blockchain.Application; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +public class MockBlockValidationService : IBlockValidationService { - public class MockBlockValidationService : IBlockValidationService + public Task ValidateBlockBeforeAttachAsync(IBlock block) { - public Task ValidateBlockBeforeAttachAsync(IBlock block) - { - return Task.FromResult(true); - } + return Task.FromResult(true); + } - public Task ValidateBlockBeforeExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockBeforeExecuteAsync(IBlock block) + { + return Task.FromResult(true); + } - public Task ValidateBlockAfterExecuteAsync(IBlock block) - { - return Task.FromResult(true); - } + public Task ValidateBlockAfterExecuteAsync(IBlock block) + { + return Task.FromResult(true); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index 1a01d3ea5b..79ccd69436 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -1,105 +1,98 @@ -using System; using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Cryptography.ECDSA; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; -namespace AElf.Contracts.Economic.TestBase +namespace AElf.Contracts.Economic.TestBase; + +public partial class EconomicContractsTestBase { - public partial class EconomicContractsTestBase - { - #region Other Contracts Action and View + #region Other Contracts Action and View - protected async Task NextTerm(ECKeyPair keyPair) + protected async Task NextTerm(ECKeyPair keyPair) + { + var miner = GetConsensusContractTester(keyPair); + var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); + var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); + var miners = new MinerList { - var miner = GetConsensusContractTester(keyPair); - var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); - var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); - var miners = new MinerList + Pubkeys = { - Pubkeys = - { - victories.Value - } - }; - var firstRoundOfNextTerm = - miners.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, - BlockTimeProvider.GetBlockTime(), round.RoundNumber, round.TermNumber); - var executionResult = (await miner.NextTerm.SendAsync(firstRoundOfNextTerm)).TransactionResult; - executionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + victories.Value + } + }; + var firstRoundOfNextTerm = + miners.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, + BlockTimeProvider.GetBlockTime(), round.RoundNumber, round.TermNumber); + var executionResult = (await miner.NextTerm.SendAsync(firstRoundOfNextTerm)).TransactionResult; + executionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - protected async Task NextRound(ECKeyPair keyPair) - { - var miner = GetConsensusContractTester(keyPair); - var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); - round.GenerateNextRoundInformation( - StartTimestamp.ToDateTime().AddMilliseconds(round.TotalMilliseconds()).ToTimestamp(), StartTimestamp, - out var nextRound); - await miner.NextRound.SendAsync(nextRound); - } + protected async Task NextRound(ECKeyPair keyPair) + { + var miner = GetConsensusContractTester(keyPair); + var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); + round.GenerateNextRoundInformation( + StartTimestamp.ToDateTime().AddMilliseconds(round.TotalMilliseconds()).ToTimestamp(), StartTimestamp, + out var nextRound); + await miner.NextRound.SendAsync(nextRound); + } - protected async Task NormalBlock(ECKeyPair keyPair) + protected async Task NormalBlock(ECKeyPair keyPair) + { + var miner = GetConsensusContractTester(keyPair); + var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); + var minerInRound = round.RealTimeMinersInformation[keyPair.PublicKey.ToHex()]; + + await miner.UpdateValue.SendAsync(new UpdateValueInput { - var miner = GetConsensusContractTester(keyPair); - var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); - var minerInRound = round.RealTimeMinersInformation[keyPair.PublicKey.ToHex()]; - - await miner.UpdateValue.SendAsync(new UpdateValueInput - { - OutValue = minerInRound.OutValue, - Signature = minerInRound.Signature, - PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, - RoundId = round.RoundId, - ProducedBlocks = minerInRound.ProducedBlocks + 1, - ActualMiningTime = minerInRound.ExpectedMiningTime, - SupposedOrderOfNextRound = 1 - }); - } + OutValue = minerInRound.OutValue, + Signature = minerInRound.Signature, + PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, + RoundId = round.RoundId, + ProducedBlocks = minerInRound.ProducedBlocks + 1, + ActualMiningTime = minerInRound.ExpectedMiningTime, + SupposedOrderOfNextRound = 1 + }); + } - protected async Task ProduceBlocks(ECKeyPair keyPair, int roundsCount, bool changeTerm = false) + protected async Task ProduceBlocks(ECKeyPair keyPair, int roundsCount, bool changeTerm = false) + { + for (var i = 0; i < roundsCount; i++) { - for (var i = 0; i < roundsCount; i++) - { - await NormalBlock(keyPair); - if (i != roundsCount - 1) continue; - if (changeTerm) - { - await NextTerm(keyPair); - } - else - { - await NextRound(keyPair); - } - } + await NormalBlock(keyPair); + if (i != roundsCount - 1) continue; + if (changeTerm) + await NextTerm(keyPair); + else + await NextRound(keyPair); } + } - protected async Task GetNativeTokenBalance(byte[] publicKey) + protected async Task GetNativeTokenBalance(byte[] publicKey) + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = EconomicContractsTestConstants.NativeTokenSymbol, - Owner = Address.FromPublicKey(publicKey) - })).Balance; + Symbol = EconomicContractsTestConstants.NativeTokenSymbol, + Owner = Address.FromPublicKey(publicKey) + })).Balance; - return balance; - } + return balance; + } - protected async Task GetVoteTokenBalance(byte[] publicKey) + protected async Task GetVoteTokenBalance(byte[] publicKey) + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = EconomicContractsTestConstants.VoteSymbol, - Owner = Address.FromPublicKey(publicKey) - })).Balance; + Symbol = EconomicContractsTestConstants.VoteSymbol, + Owner = Address.FromPublicKey(publicKey) + })).Balance; - return balance; - } - - #endregion + return balance; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs index e7495a3d4b..ed9c3082b5 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs @@ -1,50 +1,44 @@ using System.Linq; -using AElf.Contracts.Consensus.AEDPoS; using AElf.CSharp.Core.Extension; using AElf.Types; -using AElf.Sdk.CSharp; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/Types/Round.cs b/test/AElf.Contracts.Economic.TestBase/Types/Round.cs index 5cf66b3c08..8c2f02be3b 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/Round.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/Round.cs @@ -1,60 +1,49 @@ using System; -using System.Collections.Generic; using System.Linq; -using AElf.Types; -using AElf.Sdk.CSharp; -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public long RoundId => + RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + + /// + /// This method is only available when the miners of this round is more than 1. + /// + /// + public int GetMiningInterval() { - public long RoundId => - RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; - /// - /// This method is only available when the miners of this round is more than 1. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); + var distance = + (int)(firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - + firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) + .TotalMilliseconds; + return distance > 0 ? distance : -distance; + } - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); - var distance = - (int) (firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - - firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) - .TotalMilliseconds; - return distance > 0 ? distance : -distance; - } + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + return RealTimeMinersInformation.Count * miningInterval + miningInterval; + } - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } - - private static int GetAbsModulus(long longValue, int intValue) - { - return Math.Abs((int) longValue % intValue); - } + private static int GetAbsModulus(long longValue, int intValue) + { + return Math.Abs((int)longValue % intValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs index a1680b677a..567ca6cf6a 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs @@ -1,103 +1,95 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound) { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, out Round nextRound) - { - nextRound = new Round(); + nextRound = new Round(); - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + { + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; + } - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + { + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots + 1 - }; - } + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + 1 + }; + } - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; - return true; - } - - private int CalculateNextExtraBlockProducerOrder() - { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) - { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } + return true; + } - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToByteArray().ToInt64(true); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; - } - - public List GetMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); - } - - public List GetNotMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); - } + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; + + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToByteArray().ToInt64(true); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } + + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } + + public List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj index 368b2c9f45..06c8ad61db 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj +++ b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj @@ -8,12 +8,12 @@ 0436 - - - - - - + + + + + + @@ -66,10 +66,10 @@ Contract PreserveNewest - - - - + + + + false Contract @@ -90,9 +90,9 @@ Contract PreserveNewest - - - + + + @@ -213,5 +213,5 @@ - + diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/AETCTest.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/AETCTest.cs index 7311b938d3..12e5f8c237 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/AETCTest.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/AETCTest.cs @@ -5,57 +5,56 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + [Fact] + public void ElectionContract_CreateTreasury_Test() { - [Fact] - public void ElectionContract_CreateTreasury_Test() - { - // Check profit schemes related to Treasury. - // Theses items already created during AElf Consensus Contract initialization, - // and cached in ElectionContractTestBase.InitializeContracts in order to test. - ProfitItemsIds.Count.ShouldBe(7); - } - - [Fact] - public async Task ElectionContract_RegisterToTreasury_Test() - { - var treasury = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); - // MinerReward (Shares 3) -> Treasury - treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.MinerReward]); - treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.MinerReward]).Shares - .ShouldBe(ElectionContractConstants.MinerRewardWeight); - // BackupSubsidy (Shares 1) -> Treasury - treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.BackupSubsidy]); - treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.BackupSubsidy]).Shares - .ShouldBe(ElectionContractConstants.BackupSubsidyWeight); - // CitizenWelfare (Shares 1) -> Treasury - treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.CitizenWelfare]); - treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.CitizenWelfare]).Shares - .ShouldBe(ElectionContractConstants.CitizenWelfareWeight); + // Check profit schemes related to Treasury. + // Theses items already created during AElf Consensus Contract initialization, + // and cached in ElectionContractTestBase.InitializeContracts in order to test. + ProfitItemsIds.Count.ShouldBe(7); + } - var reward = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); - // BasicMinerReward (Shares 4) -> Reward - reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.BasicMinerReward]); - reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.BasicMinerReward]).Shares - .ShouldBe(ElectionContractConstants.BasicMinerRewardWeight); - // VotesWeightReward (Shares 1) -> Reward - reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.FlexibleReward]); - reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.FlexibleReward]).Shares - .ShouldBe(ElectionContractConstants.FlexibleRewardWeight); - // ReElectionReward (Shares 1) -> Reward - reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.WelcomeReward]); - reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.WelcomeReward]).Shares - .ShouldBe(ElectionContractConstants.WelcomeRewardWeight); + [Fact] + public async Task ElectionContract_RegisterToTreasury_Test() + { + var treasury = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); + // MinerReward (Shares 3) -> Treasury + treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.MinerReward]); + treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.MinerReward]).Shares + .ShouldBe(ElectionContractConstants.MinerRewardWeight); + // BackupSubsidy (Shares 1) -> Treasury + treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.BackupSubsidy]); + treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.BackupSubsidy]).Shares + .ShouldBe(ElectionContractConstants.BackupSubsidyWeight); + // CitizenWelfare (Shares 1) -> Treasury + treasury.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.CitizenWelfare]); + treasury.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.CitizenWelfare]).Shares + .ShouldBe(ElectionContractConstants.CitizenWelfareWeight); + + var reward = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); + // BasicMinerReward (Shares 4) -> Reward + reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.BasicMinerReward]); + reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.BasicMinerReward]).Shares + .ShouldBe(ElectionContractConstants.BasicMinerRewardWeight); + // VotesWeightReward (Shares 1) -> Reward + reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.FlexibleReward]); + reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.FlexibleReward]).Shares + .ShouldBe(ElectionContractConstants.FlexibleRewardWeight); + // ReElectionReward (Shares 1) -> Reward + reward.SubSchemes.Select(s => s.SchemeId).ShouldContain(ProfitItemsIds[ProfitType.WelcomeReward]); + reward.SubSchemes.First(s => s.SchemeId == ProfitItemsIds[ProfitType.WelcomeReward]).Shares + .ShouldBe(ElectionContractConstants.WelcomeRewardWeight); - // Check the balance of Treasury - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = treasury.VirtualAddress, - Symbol = "VOTE" - }); - balance.Balance.ShouldBe(0); - } + // Check the balance of Treasury + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = treasury.VirtualAddress, + Symbol = "VOTE" + }); + balance.Balance.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/AdvanceResourceTokenTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/AdvanceResourceTokenTests.cs index 31eca19677..aefdd9b864 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/AdvanceResourceTokenTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/AdvanceResourceTokenTests.cs @@ -1,205 +1,202 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -using AElf.ContractTestKit; using AElf.Contracts.TokenConverter; +using AElf.ContractTestKit; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + private const long Amount = 100; + private const string ResourceTokenSymbol = "TRAFFIC"; + + private async Task
TokenContract_AdvanceResourceToken_Test() { - private const long Amount = 100; - private const string ResourceTokenSymbol = "TRAFFIC"; + var contractAddress = SampleAddress.AddressList[0]; + var developerAddress = BootMinerAddress; - private async Task
TokenContract_AdvanceResourceToken_Test() + await TokenConverterContractStub.Buy.SendAsync(new BuyInput { - var contractAddress = SampleAddress.AddressList[0]; - var developerAddress = BootMinerAddress; + Symbol = ResourceTokenSymbol, + Amount = Amount + }); - await TokenConverterContractStub.Buy.SendAsync(new BuyInput - { - Symbol = ResourceTokenSymbol, - Amount = Amount, - }); + var balanceBeforeAdvancing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = developerAddress, + Symbol = ResourceTokenSymbol + }); + + await TokenContractStub.AdvanceResourceToken.SendAsync(new AdvanceResourceTokenInput + { + ContractAddress = contractAddress, + Amount = Amount, + ResourceTokenSymbol = ResourceTokenSymbol + }); - var balanceBeforeAdvancing = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + // Check balance of contract address. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Owner = developerAddress, + Owner = contractAddress, Symbol = ResourceTokenSymbol }); + balance.Balance.ShouldBe(Amount); + } - await TokenContractStub.AdvanceResourceToken.SendAsync(new AdvanceResourceTokenInput + // Check balance of developer. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - ContractAddress = contractAddress, - Amount = Amount, - ResourceTokenSymbol = ResourceTokenSymbol + Owner = developerAddress, + Symbol = ResourceTokenSymbol }); + balance.Balance.ShouldBe(balanceBeforeAdvancing.Balance - Amount); + } - // Check balance of contract address. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = contractAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(Amount); - } + return contractAddress; + } - // Check balance of developer. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = developerAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(balanceBeforeAdvancing.Balance - Amount); - } + [Fact] + public async Task TokenContract_TakeResourceTokenBack_Test() + { + var contractAddress = await TokenContract_AdvanceResourceToken_Test(); + var developerAddress = BootMinerAddress; - return contractAddress; - } + var balanceBeforeTakingBack = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = developerAddress, + Symbol = ResourceTokenSymbol + }); - [Fact] - public async Task TokenContract_TakeResourceTokenBack_Test() + await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput { - var contractAddress = await TokenContract_AdvanceResourceToken_Test(); - var developerAddress = BootMinerAddress; + ContractAddress = contractAddress, + Amount = Amount, + ResourceTokenSymbol = ResourceTokenSymbol + }); - var balanceBeforeTakingBack = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + // Check balance of developer. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = developerAddress, Symbol = ResourceTokenSymbol }); + balance.Balance.ShouldBe(balanceBeforeTakingBack.Balance + Amount); + } - await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput + // Check balance of contract address. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - ContractAddress = contractAddress, - Amount = Amount, - ResourceTokenSymbol = ResourceTokenSymbol + Owner = contractAddress, + Symbol = ResourceTokenSymbol }); + balance.Balance.ShouldBe(0); + } + } - // Check balance of developer. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = developerAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(balanceBeforeTakingBack.Balance + Amount); - } + [Fact] + public async Task TokenContract_TakeResourceTokenBack_NotAll_Test() + { + var contractAddress = await TokenContract_AdvanceResourceToken_Test(); + var developerAddress = BootMinerAddress; + const long takeBackAmount = Amount / 2; - // Check balance of contract address. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = contractAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(0); - } - } + var balanceBeforeTakingBack = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = developerAddress, + Symbol = ResourceTokenSymbol + }); - [Fact] - public async Task TokenContract_TakeResourceTokenBack_NotAll_Test() + await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput { - var contractAddress = await TokenContract_AdvanceResourceToken_Test(); - var developerAddress = BootMinerAddress; - const long takeBackAmount = Amount / 2; + ContractAddress = contractAddress, + Amount = takeBackAmount, + ResourceTokenSymbol = ResourceTokenSymbol + }); - var balanceBeforeTakingBack = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + // Check balance of developer. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = developerAddress, Symbol = ResourceTokenSymbol }); - - await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput - { - ContractAddress = contractAddress, - Amount = takeBackAmount, - ResourceTokenSymbol = ResourceTokenSymbol - }); - - // Check balance of developer. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = developerAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(balanceBeforeTakingBack.Balance + takeBackAmount); - } - - // Check balance of contract address. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = contractAddress, - Symbol = ResourceTokenSymbol - }); - balance.Balance.ShouldBe(Amount - takeBackAmount); - } + balance.Balance.ShouldBe(balanceBeforeTakingBack.Balance + takeBackAmount); } - [Fact] - public async Task TokenContract_TakeResourceTokenBack_Exceed_Test() + // Check balance of contract address. { - var contractAddress = await TokenContract_AdvanceResourceToken_Test(); - const long takeBackAmount = Amount * 2; - - var result = await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - ContractAddress = contractAddress, - Amount = takeBackAmount, - ResourceTokenSymbol = ResourceTokenSymbol + Owner = contractAddress, + Symbol = ResourceTokenSymbol }); - - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Can't take back that more."); + balance.Balance.ShouldBe(Amount - takeBackAmount); } + } + + [Fact] + public async Task TokenContract_TakeResourceTokenBack_Exceed_Test() + { + var contractAddress = await TokenContract_AdvanceResourceToken_Test(); + const long takeBackAmount = Amount * 2; - [Fact] - public async Task SetControllerForManageConnector_Test() + var result = await TokenContractStub.TakeResourceTokenBack.SendAsync(new TakeResourceTokenBackInput { - var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = createOrganizationResult.Output; - var defaultController = - await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + ContractAddress = contractAddress, + Amount = takeBackAmount, + ResourceTokenSymbol = ResourceTokenSymbol + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Can't take back that more."); + } + + [Fact] + public async Task SetControllerForManageConnector_Test() + { + var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - ToAddress = TokenConverterContractAddress, - ContractMethodName = nameof(TokenConverterContractStub.ChangeConnectorController), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = new AuthorityInfo + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ContractAddress = defaultController.ContractAddress, - OwnerAddress = organizationAddress - }.ToByteString(), - OrganizationAddress = defaultOrganization + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - var proposalId = proposal.Output; - await ApproveWithAllMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var newController = await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); - newController.OwnerAddress.ShouldBe(organizationAddress); - - } + var organizationAddress = createOrganizationResult.Output; + var defaultController = + await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ToAddress = TokenConverterContractAddress, + ContractMethodName = nameof(TokenConverterContractStub.ChangeConnectorController), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = new AuthorityInfo + { + ContractAddress = defaultController.ContractAddress, + OwnerAddress = organizationAddress + }.ToByteString(), + OrganizationAddress = defaultOrganization + }); + var proposalId = proposal.Output; + await ApproveWithAllMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var newController = await TokenConverterContractStub.GetControllerForManageConnector.CallAsync(new Empty()); + newController.OwnerAddress.ShouldBe(organizationAddress); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/CalculateCoefficientFeeTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/CalculateCoefficientFeeTests.cs index 7e2dac294a..f0aa4372a0 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/CalculateCoefficientFeeTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/CalculateCoefficientFeeTests.cs @@ -5,21 +5,20 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + [Fact] + public async Task UpdateCoefficient_NotChange_Test() { - [Fact] - public async Task UpdateCoefficient_NotChange_Test() - { - //invalid setting - var tokenContractImplStub = GetTokenContractImplTester(InitialCoreDataCenterKeyPairs.Last()); - var txResult = - await tokenContractImplStub.UpdateCoefficientsForContract.SendAsync(new UpdateCoefficientsInput()); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + //invalid setting + var tokenContractImplStub = GetTokenContractImplTester(InitialCoreDataCenterKeyPairs.Last()); + var txResult = + await tokenContractImplStub.UpdateCoefficientsForContract.SendAsync(new UpdateCoefficientsInput()); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult = await tokenContractImplStub.UpdateCoefficientsForSender.SendAsync(new UpdateCoefficientsInput()); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } + txResult = await tokenContractImplStub.UpdateCoefficientsForSender.SendAsync(new UpdateCoefficientsInput()); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/ConfigurationTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/ConfigurationTests.cs index 88771af783..8df9dc72b9 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/ConfigurationTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/ConfigurationTests.cs @@ -1,125 +1,121 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Configuration; using AElf.Contracts.Parliament; -using AElf.Kernel.Configuration; -using AElf.Kernel.Miner; -using AElf.Types; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +partial class EconomicSystemTest { - partial class EconomicSystemTest + [Fact] + public async Task SetConfiguration_TransactionFee_Test() { - [Fact] - public async Task SetConfiguration_TransactionFee_Test() - { - await ExecuteProposalForParliamentTransaction(ConfigurationAddress, - nameof(ConfigurationContractStub.SetMethodFee), - new MethodFees + await ExecuteProposalForParliamentTransaction(ConfigurationAddress, + nameof(ConfigurationContractStub.SetMethodFee), + new MethodFees + { + MethodName = nameof(ConfigurationContractStub.SetConfiguration), + Fees = { - MethodName = nameof(ConfigurationContractStub.SetConfiguration), - Fees = + new MethodFee { - new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - } + Symbol = "ELF", + BasicFee = 5000_0000L } - }); - var result = await ConfigurationContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ConfigurationContractStub.SetConfiguration) + } }); - var tokenFee = result.Fees.First(); - tokenFee.Symbol.ShouldBe("ELF"); - tokenFee.BasicFee.ShouldBe(5000_0000L); - } - - [Fact] - public async Task SetBlockTransactionLimit_Test() + var result = await ConfigurationContractStub.GetMethodFee.CallAsync(new StringValue { - await ExecuteProposalForParliamentTransaction(ConfigurationAddress, - nameof(ConfigurationContractStub.SetConfiguration), - new SetConfigurationInput - { - Key = "BlockTransactionLimit", - Value = new Int32Value - { - Value = 50 - }.ToByteString() - }); - var result = await ConfigurationContractStub.GetConfiguration.CallAsync(new StringValue + Value = nameof(ConfigurationContractStub.SetConfiguration) + }); + var tokenFee = result.Fees.First(); + tokenFee.Symbol.ShouldBe("ELF"); + tokenFee.BasicFee.ShouldBe(5000_0000L); + } + + [Fact] + public async Task SetBlockTransactionLimit_Test() + { + await ExecuteProposalForParliamentTransaction(ConfigurationAddress, + nameof(ConfigurationContractStub.SetConfiguration), + new SetConfigurationInput { - Value = "BlockTransactionLimit" + Key = "BlockTransactionLimit", + Value = new Int32Value + { + Value = 50 + }.ToByteString() }); - var limit = new Int32Value(); - limit.MergeFrom(BytesValue.Parser.ParseFrom(result.ToByteString()).Value); - limit.Value.ShouldBe(50); - } - - [Fact] - public async Task Configuration_ChangeMethodFeeController_Test() + var result = await ConfigurationContractStub.GetConfiguration.CallAsync(new StringValue { - var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput + Value = "BlockTransactionLimit" + }); + var limit = new Int32Value(); + limit.MergeFrom(BytesValue.Parser.ParseFrom(result.ToByteString()).Value); + limit.Value.ShouldBe(50); + } + + [Fact] + public async Task Configuration_ChangeMethodFeeController_Test() + { + var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); - var organizationAddress = createOrganizationResult.Output; + var organizationAddress = createOrganizationResult.Output; - var methodFeeController = await ConfigurationContractStub.GetMethodFeeController.CallAsync(new Empty()); - await ExecuteProposalForParliamentTransaction(ConfigurationAddress, - nameof(ConfigurationContractStub.ChangeMethodFeeController), - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); + var methodFeeController = await ConfigurationContractStub.GetMethodFeeController.CallAsync(new Empty()); + await ExecuteProposalForParliamentTransaction(ConfigurationAddress, + nameof(ConfigurationContractStub.ChangeMethodFeeController), + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); - var newMethodFeeController = await ConfigurationContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var newMethodFeeController = await ConfigurationContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task ChangeOwnerAddress_Test() - { - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var defaultOwner = await ConfigurationContractStub.GetConfigurationController.CallAsync(new Empty()); - defaultOwner.OwnerAddress.ShouldBe(defaultOrganization); - - var newOrganization = - (await ParliamentContractStub.CreateOrganization.SendAsync(new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = true - })).Output; + [Fact] + public async Task ChangeOwnerAddress_Test() + { + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var defaultOwner = await ConfigurationContractStub.GetConfigurationController.CallAsync(new Empty()); + defaultOwner.OwnerAddress.ShouldBe(defaultOrganization); - await ExecuteProposalForParliamentTransaction(ConfigurationAddress, - nameof(ConfigurationContractStub.ChangeConfigurationController), - new AuthorityInfo + var newOrganization = + (await ParliamentContractStub.CreateOrganization.SendAsync(new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ContractAddress = ParliamentContractAddress, - OwnerAddress = newOrganization - }); + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = true + })).Output; + + await ExecuteProposalForParliamentTransaction(ConfigurationAddress, + nameof(ConfigurationContractStub.ChangeConfigurationController), + new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, + OwnerAddress = newOrganization + }); - var newOwner = await ConfigurationContractStub.GetConfigurationController.CallAsync(new Empty()); - newOwner.OwnerAddress.ShouldBe(newOrganization); - } + var newOwner = await ConfigurationContractStub.GetConfigurationController.CallAsync(new Empty()); + newOwner.OwnerAddress.ShouldBe(newOrganization); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs index 7d862b23b9..db05af1544 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs @@ -1,207 +1,206 @@ using System.Threading.Tasks; -using AElf.Standards.ACS10; using AElf.Contracts.MultiToken; using AElf.Contracts.TestContract.TransactionFeeCharging; -using AElf.ContractTestKit; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.Cryptography.ECDSA; +using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + [Fact] + public async Task Donate_FewELF_Success_Test() { - [Fact] - public async Task Donate_FewELF_Success_Test() + var account = Accounts[1]; + await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 100); + var stub = GetTreasuryContractTester(account.KeyPair); + + var donateResult = await stub.Donate.SendAsync(new DonateInput { - var account = Accounts[1]; - await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 100); - var stub = GetTreasuryContractTester(account.KeyPair); + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Amount = 50 + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var donateResult = await stub.Donate.SendAsync(new DonateInput - { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Amount = 50 - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = account.Address, + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + })).Balance; + userBalance.ShouldBe(50); - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = account.Address, - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - })).Balance; - userBalance.ShouldBe(50); + var treasuryBalance = await GetCurrentTreasuryBalance(); + treasuryBalance.ShouldBeGreaterThanOrEqualTo(50); + } - var treasuryBalance = await GetCurrentTreasuryBalance(); - treasuryBalance.ShouldBeGreaterThanOrEqualTo(50); - } + [Fact] + public async Task Donate_AllELF_Success_Test() + { + var account = Accounts[1]; + await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 100); + var stub = GetTreasuryContractTester(account.KeyPair); - [Fact] - public async Task Donate_AllELF_Success_Test() + var donateResult = await stub.DonateAll.SendAsync(new DonateAllInput { - var account = Accounts[1]; - await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 100); - var stub = GetTreasuryContractTester(account.KeyPair); + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var donateResult = await stub.DonateAll.SendAsync(new DonateAllInput - { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = account.Address, + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + })).Balance; + userBalance.ShouldBe(0); - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = account.Address, - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - })).Balance; - userBalance.ShouldBe(0); + var treasuryBalance = await GetCurrentTreasuryBalance(); + treasuryBalance.ShouldBeGreaterThanOrEqualTo(100); + } - var treasuryBalance = await GetCurrentTreasuryBalance(); - treasuryBalance.ShouldBeGreaterThanOrEqualTo(100); - } + [Fact] + public async Task Donate_ELF_LessThan_Owned_Test() + { + var account = Accounts[1]; - [Fact] - public async Task Donate_ELF_LessThan_Owned_Test() + await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 50); + var stub = GetTreasuryContractTester(account.KeyPair); + var donateResult = await stub.Donate.SendAsync(new DonateInput { - var account = Accounts[1]; - - await TransferToken(account.KeyPair, EconomicSystemTestConstants.NativeTokenSymbol, 50); - var stub = GetTreasuryContractTester(account.KeyPair); - var donateResult = await stub.Donate.SendAsync(new DonateInput - { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Amount = 100 - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Amount = 100 + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = account.Address, - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - })).Balance; - userBalance.ShouldBe(50); - } + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = account.Address, + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + })).Balance; + userBalance.ShouldBe(50); + } - [Fact] - public async Task Donate_FewOtherToken_Success_Test() + [Fact] + public async Task Donate_FewOtherToken_Success_Test() + { + await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); + var keyPair = CoreDataCenterKeyPairs[0]; + await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 100); + var stub = GetTreasuryContractTester(keyPair); + var donateResult = await stub.Donate.SendAsync(new DonateInput { - await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); - var keyPair = CoreDataCenterKeyPairs[0]; - await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 100); - var stub = GetTreasuryContractTester(keyPair); - var donateResult = await stub.Donate.SendAsync(new DonateInput - { - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, - Amount = 50 - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, + Amount = 50 + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(keyPair.PublicKey), - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol - })).Balance; - userBalance.ShouldBe(50); - } + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(keyPair.PublicKey), + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol + })).Balance; + userBalance.ShouldBe(50); + } - private async Task InitialBuildConnector(string symbol) + private async Task InitialBuildConnector(string symbol) + { + var token = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = symbol + }); + var tokenInfo = new ToBeConnectedTokenInfo { - var token = (await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + TokenSymbol = symbol, + AmountToTokenConvert = 0 + }; + var issueRet = (await TransactionFeeChargingContractStub.IssueToTokenConvert.SendAsync( + new IssueAmount { Symbol = symbol, - })); - var tokenInfo = new ToBeConnectedTokenInfo - { - TokenSymbol = symbol, - AmountToTokenConvert = 0 - }; - var issueRet = (await TransactionFeeChargingContractStub.IssueToTokenConvert.SendAsync( - new IssueAmount - { - Symbol = symbol, - Amount = token.TotalSupply - token.Supply - })).TransactionResult; - issueRet.Status.ShouldBe(TransactionResultStatus.Mined); - var buildConnector = (await TokenConverterContractStub.EnableConnector.SendAsync(tokenInfo)).TransactionResult; - buildConnector.Status.ShouldBe(TransactionResultStatus.Mined); - } - [Fact] - public async Task Donate_AllOtherToken_Success_Test() + Amount = token.TotalSupply - token.Supply + })).TransactionResult; + issueRet.Status.ShouldBe(TransactionResultStatus.Mined); + var buildConnector = (await TokenConverterContractStub.EnableConnector.SendAsync(tokenInfo)).TransactionResult; + buildConnector.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task Donate_AllOtherToken_Success_Test() + { + await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); + var keyPair = CoreDataCenterKeyPairs[0]; + + await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 100); + var stub = GetTreasuryContractTester(keyPair); + var donateResult = await stub.DonateAll.SendAsync(new DonateAllInput { - await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); - var keyPair = CoreDataCenterKeyPairs[0]; + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 100); - var stub = GetTreasuryContractTester(keyPair); - var donateResult = await stub.DonateAll.SendAsync(new DonateAllInput - { - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(keyPair.PublicKey), + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol + })).Balance; + userBalance.ShouldBe(0); + } - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(keyPair.PublicKey), - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol - })).Balance; - userBalance.ShouldBe(0); - } + [Fact] + public async Task Donate_OtherToken_LessThan_Owned_Test() + { + await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); + var keyPair = CoreDataCenterKeyPairs[0]; - [Fact] - public async Task Donate_OtherToken_LessThan_Owned_Test() + await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 50); + var stub = GetTreasuryContractTester(keyPair); + var donateResult = await stub.Donate.SendAsync(new DonateInput { - await InitialBuildConnector(EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol); - var keyPair = CoreDataCenterKeyPairs[0]; - - await TransferToken(keyPair, EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, 50); - var stub = GetTreasuryContractTester(keyPair); - var donateResult = await stub.Donate.SendAsync(new DonateInput - { - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, - Amount = 100 - }); - donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol, + Amount = 100 + }); + donateResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(keyPair.PublicKey), - Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol - })).Balance; - userBalance.ShouldBe(50); - } + var userBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(keyPair.PublicKey), + Symbol = EconomicSystemTestConstants.TransactionFeeChargingContractTokenSymbol + })).Balance; + userBalance.ShouldBe(50); + } - private async Task TransferToken(ECKeyPair keyPair, string symbol, long amount) + private async Task TransferToken(ECKeyPair keyPair, string symbol, long amount) + { + var toAddress = Address.FromPublicKey(keyPair.PublicKey); + if (symbol != EconomicSystemTestConstants.NativeTokenSymbol) { - var toAddress = Address.FromPublicKey(keyPair.PublicKey); - if (symbol != EconomicSystemTestConstants.NativeTokenSymbol) + var buyResult = await TokenConverterContractStub.Buy.SendAsync(new BuyInput { - var buyResult = await TokenConverterContractStub.Buy.SendAsync(new BuyInput - { - Symbol = symbol, - Amount = amount - }); - buyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = toAddress, Symbol = symbol, - Amount = amount, - Memo = "transfer for test" + Amount = amount }); - transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + buyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private async Task GetCurrentTreasuryBalance() + var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput { - var balance = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); + To = toAddress, + Symbol = symbol, + Amount = amount, + Memo = "transfer for test" + }); + transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - return balance.Value[EconomicSystemTestConstants.NativeTokenSymbol]; - } + private async Task GetCurrentTreasuryBalance() + { + var balance = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); + + return balance.Value[EconomicSystemTestConstants.NativeTokenSymbol]; } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/LockTokenTest.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/LockTokenTest.cs index 97a346720b..f7d9aa9b1b 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/LockTokenTest.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/LockTokenTest.cs @@ -1,78 +1,76 @@ -using System.Linq; using System.Threading.Tasks; using AElf.Contracts.Economic; using AElf.Contracts.Economic.TestBase; +using AElf.Contracts.Election; using AElf.Contracts.MultiToken; +using AElf.Cryptography.ECDSA; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; -using Xunit; -using AElf.Contracts.Election; -using AElf.ContractTestKit; -using AElf.Cryptography.ECDSA; using Volo.Abp.Threading; +using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public class TokenTestBase : EconomicSystemTestBase { - public class TokenTestBase : EconomicSystemTestBase - { - protected ECKeyPair AnnounceElectionKeyPair => Accounts[81].KeyPair; - internal ElectionContractImplContainer.ElectionContractImplStub tokenTestElectionContractStub { get; set; } - } + protected ECKeyPair AnnounceElectionKeyPair => Accounts[81].KeyPair; + internal ElectionContractImplContainer.ElectionContractImplStub tokenTestElectionContractStub { get; set; } +} - public class TokenTest : TokenTestBase +public class TokenTest : TokenTestBase +{ + public TokenTest() { - public TokenTest() - { - InitializeContracts(); - tokenTestElectionContractStub = - GetTester(ElectionContractAddress, - AnnounceElectionKeyPair); + InitializeContracts(); + tokenTestElectionContractStub = + GetTester(ElectionContractAddress, + AnnounceElectionKeyPair); - var issueResult = AsyncHelper.RunSync(() => EconomicContractStub.IssueNativeToken.SendAsync( + var issueResult = AsyncHelper.RunSync(() => EconomicContractStub.IssueNativeToken.SendAsync( + new IssueNativeTokenInput + { + Amount = 1000_000_00000000L, + To = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), + Memo = "Used to transfer other testers" + })); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var result = AsyncHelper.RunSync(() => EconomicContractStub.IssueNativeToken.SendAsync( new IssueNativeTokenInput { - Amount = 1000_000_00000000L, - To = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), - Memo = "Used to transfer other testers" + Amount = EconomicContractsTestConstants.TotalSupply / 5, + To = TokenContractAddress, + Memo = "Set mining rewards." })); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - { - var result = AsyncHelper.RunSync(() => EconomicContractStub.IssueNativeToken.SendAsync( - new IssueNativeTokenInput - { - Amount = EconomicContractsTestConstants.TotalSupply / 5, - To = TokenContractAddress, - Memo = "Set mining rewards." - })); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - private async Task Token_Lock_Test() + private async Task Token_Lock_Test() + { + await tokenTestElectionContractStub.AnnounceElection.SendAsync( + Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey)); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await tokenTestElectionContractStub.AnnounceElection.SendAsync(Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey)); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(1000_000_00000000 - 100_000_00000000); - } + Owner = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(1000_000_00000000 - 100_000_00000000); + } - [Fact] - public async Task Token_Unlock_Test() - { - await Token_Lock_Test(); + [Fact] + public async Task Token_Unlock_Test() + { + await Token_Lock_Test(); - await tokenTestElectionContractStub.QuitElection.SendAsync(new StringValue - {Value = AnnounceElectionKeyPair.PublicKey.ToHex()}); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), - Symbol = EconomicSystemTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(1000_000_00000000L); - } + await tokenTestElectionContractStub.QuitElection.SendAsync(new StringValue + { Value = AnnounceElectionKeyPair.PublicKey.ToHex() }); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(AnnounceElectionKeyPair.PublicKey), + Symbol = EconomicSystemTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(1000_000_00000000L); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/ThresholdContractTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/ThresholdContractTests.cs index 6ae3d57968..5ba3357f2e 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/ThresholdContractTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/ThresholdContractTests.cs @@ -5,42 +5,41 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public class ThresholdContractTests : EconomicSystemTestBase { - public class ThresholdContractTests : EconomicSystemTestBase + [Fact] + public async Task MethodCallingThreshold_Test() { - [Fact] - public async Task MethodCallingThreshold_Test() - { - var methodResult = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync( - new StringValue - { - Value = "SendForFun" - }); - methodResult.SymbolToAmount.Count.ShouldBe(0); + var methodResult = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync( + new StringValue + { + Value = "SendForFun" + }); + methodResult.SymbolToAmount.Count.ShouldBe(0); - var setResult = await MethodCallThresholdContractStub.SetMethodCallingThreshold.SendAsync( - new SetMethodCallingThresholdInput + var setResult = await MethodCallThresholdContractStub.SetMethodCallingThreshold.SendAsync( + new SetMethodCallingThresholdInput + { + Method = "SendForFun", + SymbolToAmount = { - Method = "SendForFun", - SymbolToAmount = - { - {"ELF", 1_0000_0000} - }, - ThresholdCheckType = ThresholdCheckType.Balance - }); - setResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - methodResult = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync( - new StringValue - { - Value = "SendForFun" - }); - methodResult.SymbolToAmount.Count.ShouldBe(1); - methodResult.ThresholdCheckType.ShouldBe(ThresholdCheckType.Balance); + { "ELF", 1_0000_0000 } + }, + ThresholdCheckType = ThresholdCheckType.Balance + }); + setResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + methodResult = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync( + new StringValue + { + Value = "SendForFun" + }); + methodResult.SymbolToAmount.Count.ShouldBe(1); + methodResult.ThresholdCheckType.ShouldBe(ThresholdCheckType.Balance); - var executionResult = await MethodCallThresholdContractStub.SendForFun.SendAsync(new Empty()); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var executionResult = await MethodCallThresholdContractStub.SendForFun.SendAsync(new Empty()); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeProviderTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeProviderTests.cs index dbd77f6f03..6d8477c910 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeProviderTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeProviderTests.cs @@ -1,184 +1,183 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; -using AElf.Contracts.TokenConverter; using AElf.Contracts.TokenHolder; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + private const string MethodName = "SetMethodFee"; + + private readonly MethodFee TokenAmount = new() + { + BasicFee = 5000_0000, + Symbol = "ELF" + }; + + private Address Tester => Address.FromPublicKey(InitialCoreDataCenterKeyPairs.First().PublicKey); + + [Fact] + public async Task Economic_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(EconomicContractAddress, MethodName, new MethodFees + { + MethodName = nameof(EconomicContractStub.IssueNativeToken), + Fees = { TokenAmount } + }); + var result = await EconomicContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(EconomicContractStub.IssueNativeToken) + }); + result.Fees.First().ShouldBe(TokenAmount); + } + + [Fact] + public async Task Vote_FeeProvider_Test() { - private Address Tester => Address.FromPublicKey(InitialCoreDataCenterKeyPairs.First().PublicKey); - private const string MethodName = "SetMethodFee"; - private MethodFee TokenAmount = new MethodFee + var registerResult = await VoteContractStub.GetMethodFee.CallAsync(new StringValue { - BasicFee = 5000_0000, + Value = nameof(VoteContractStub.Register) + }); + registerResult.Fees.First().ShouldBe(new MethodFee + { + BasicFee = 10_00000000, Symbol = "ELF" - }; + }); + + await ExecuteProposalForParliamentTransaction(VoteContractAddress, MethodName, new MethodFees + { + MethodName = nameof(VoteContractStub.Register), + Fees = { TokenAmount } + }); + var result = await VoteContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(VoteContractStub.Register) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Economic_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(EconomicContractAddress, MethodName, new MethodFees - { - MethodName = nameof(EconomicContractStub.IssueNativeToken), - Fees = {TokenAmount} - }); - var result = await EconomicContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(EconomicContractStub.IssueNativeToken) - }); - result.Fees.First().ShouldBe(TokenAmount); - } - - [Fact] - public async Task Vote_FeeProvider_Test() - { - var registerResult = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(VoteContractStub.Register) - }); - registerResult.Fees.First().ShouldBe(new MethodFee - { - BasicFee = 10_00000000, - Symbol = "ELF" - }); - - await ExecuteProposalForParliamentTransaction(VoteContractAddress, MethodName, new MethodFees - { - MethodName = nameof(VoteContractStub.Register), - Fees = {TokenAmount} - }); - var result = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(VoteContractStub.Register) - }); - result.Fees.First().ShouldBe(TokenAmount); - } - - [Fact] - public async Task Treasury_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, MethodName, new MethodFees - { - MethodName = nameof(TreasuryContractStub.Donate), - Fees = {TokenAmount} - }); - var result = await TreasuryContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(TreasuryContractStub.Donate) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Treasury_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, MethodName, new MethodFees + { + MethodName = nameof(TreasuryContractStub.Donate), + Fees = { TokenAmount } + }); + var result = await TreasuryContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(TreasuryContractStub.Donate) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Election_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(ElectionContractAddress, MethodName, new MethodFees - { - MethodName = nameof(ElectionContractStub.Vote), - Fees = {TokenAmount} - }); - var result = await ElectionContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ElectionContractStub.Vote) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Election_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(ElectionContractAddress, MethodName, new MethodFees + { + MethodName = nameof(ElectionContractStub.Vote), + Fees = { TokenAmount } + }); + var result = await ElectionContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(ElectionContractStub.Vote) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Parliament_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(ParliamentContractAddress, MethodName, new MethodFees - { - MethodName = nameof(ParliamentContractStub.Approve), - Fees = {TokenAmount} - }); - var result = await ParliamentContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ParliamentContractStub.Approve) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Parliament_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(ParliamentContractAddress, MethodName, new MethodFees + { + MethodName = nameof(ParliamentContractStub.Approve), + Fees = { TokenAmount } + }); + var result = await ParliamentContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(ParliamentContractStub.Approve) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Genesis_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(ContractZeroAddress, MethodName, new MethodFees - { - MethodName = nameof(BasicContractZeroStub.DeploySmartContract), - Fees = {TokenAmount} - }); - var result = await BasicContractZeroStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(BasicContractZeroStub.DeploySmartContract) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Genesis_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(ContractZeroAddress, MethodName, new MethodFees + { + MethodName = nameof(BasicContractZeroStub.DeploySmartContract), + Fees = { TokenAmount } + }); + var result = await BasicContractZeroStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(BasicContractZeroStub.DeploySmartContract) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task TokenConverter_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, MethodName, new MethodFees - { - MethodName = nameof(TokenConverterContractStub.Buy), - Fees = {TokenAmount} - }); - var result = await TokenConverterContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(TokenConverterContractStub.Buy) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task TokenConverter_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, MethodName, new MethodFees + { + MethodName = nameof(TokenConverterContractStub.Buy), + Fees = { TokenAmount } + }); + var result = await TokenConverterContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(TokenConverterContractStub.Buy) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Token_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(TokenContractAddress, MethodName, new MethodFees - { - MethodName = nameof(TokenContractImplStub.Transfer), - Fees = { TokenAmount} - }); - var result = await TokenContractImplStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(TokenContractImplStub.Transfer) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Token_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(TokenContractAddress, MethodName, new MethodFees + { + MethodName = nameof(TokenContractImplStub.Transfer), + Fees = { TokenAmount } + }); + var result = await TokenContractImplStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(TokenContractImplStub.Transfer) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task TokenHolder_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(TokenHolderContractAddress, MethodName, new MethodFees - { - MethodName = nameof(TokenHolderContractImplContainer.TokenHolderContractImplStub.Withdraw), - Fees = { TokenAmount} - }); - var result = await TokenHolderStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(TokenHolderContractImplContainer.TokenHolderContractImplStub.Withdraw) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task TokenHolder_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(TokenHolderContractAddress, MethodName, new MethodFees + { + MethodName = nameof(TokenHolderContractImplContainer.TokenHolderContractImplStub.Withdraw), + Fees = { TokenAmount } + }); + var result = await TokenHolderStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(TokenHolderContractImplContainer.TokenHolderContractImplStub.Withdraw) + }); + result.Fees.First().ShouldBe(TokenAmount); + } - [Fact] - public async Task Consensus_FeeProvider_Test() - { - await ExecuteProposalForParliamentTransaction(ConsensusContractAddress, MethodName, new MethodFees - { - MethodName = nameof(AEDPoSContractStub.SetMaximumMinersCount), - Fees = { TokenAmount} - }); - var result = await AedPoSContractImplStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(AEDPoSContractStub.SetMaximumMinersCount) - }); - result.Fees.First().ShouldBe(TokenAmount); - } + [Fact] + public async Task Consensus_FeeProvider_Test() + { + await ExecuteProposalForParliamentTransaction(ConsensusContractAddress, MethodName, new MethodFees + { + MethodName = nameof(AEDPoSContractStub.SetMaximumMinersCount), + Fees = { TokenAmount } + }); + var result = await AedPoSContractImplStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(AEDPoSContractStub.SetMaximumMinersCount) + }); + result.Fees.First().ShouldBe(TokenAmount); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeTests.cs index e31d4dcdff..d2a7396ada 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TransactionFeeTests.cs @@ -1,307 +1,305 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.ContractTestKit; using AElf.Contracts.Vote; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest - { - private const long DefaultFeeAmount = 1_0000_0000; - private const long NewFeeAmount = 0; - private const long CreateSchemeAmount = 10_00000000; + private const long DefaultFeeAmount = 1_0000_0000; + private const long NewFeeAmount = 0; + private const long CreateSchemeAmount = 10_00000000; - private async Task Vote_SetMethodFee_Test() + private async Task Vote_SetMethodFee_Test() + { + //default fee { - //default fee - { - var addOptionFeeAmount = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(VoteContractStub.AddOption) - }); - addOptionFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty - addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); - addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(DefaultFeeAmount); - } - - //set transaction fee + var addOptionFeeAmount = await VoteContractStub.GetMethodFee.CallAsync(new StringValue { - await Vote_SetMethodFee(nameof(VoteContractStub.AddOption), - EconomicSystemTestConstants.NativeTokenSymbol, NewFeeAmount); - - //query result - var addOptionFeeAmount = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(VoteContractStub.AddOption) - }); - addOptionFeeAmount.Fees.Count.ShouldBe(1); - addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); - addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(NewFeeAmount); - } + Value = nameof(VoteContractStub.AddOption) + }); + addOptionFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty + addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); + addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(DefaultFeeAmount); } - [Fact] - public async Task Vote_Execute_AddOption_Test() + //set transaction fee { - await Vote_SetMethodFee_Test(); - - var registerItem = await RegisterVotingItemAsync(100, 3, true, BootMinerAddress, 1); - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Owner = BootMinerAddress - })).Balance; - var address = Accounts[10].Address.ToBase58(); - var transactionResult = (await VoteContractStub.AddOption.SendAsync(new AddOptionInput - { - Option = address, - VotingItemId = registerItem.VotingItemId - })); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var transactionSize = transactionResult.Transaction.Size(); + await Vote_SetMethodFee(nameof(VoteContractStub.AddOption), + EconomicSystemTestConstants.NativeTokenSymbol, NewFeeAmount); - var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //query result + var addOptionFeeAmount = await VoteContractStub.GetMethodFee.CallAsync(new StringValue { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Owner = BootMinerAddress - })).Balance; - beforeBalance.ShouldBe(afterBalance + 0 + transactionSize * 0); + Value = nameof(VoteContractStub.AddOption) + }); + addOptionFeeAmount.Fees.Count.ShouldBe(1); + addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); + addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(NewFeeAmount); } + } - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await EconomicContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = - nameof(EconomicContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); - await ApproveWithAllMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Vote_Execute_AddOption_Test() + { + await Vote_SetMethodFee_Test(); - var newMethodFeeController = await EconomicContractStub.GetMethodFeeController.CallAsync(new Empty()); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); - } + var registerItem = await RegisterVotingItemAsync(100, 3, true, BootMinerAddress, 1); + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Owner = BootMinerAddress + })).Balance; + var address = Accounts[10].Address.ToBase58(); + var transactionResult = await VoteContractStub.AddOption.SendAsync(new AddOptionInput + { + Option = address, + VotingItemId = registerItem.VotingItemId + }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionSize = transactionResult.Transaction.Size(); - private async Task Profit_SetMethodFee_Test() + var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - //default fee - { - //create scheme - var createSchemeFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ProfitContractStub.CreateScheme) - }); - createSchemeFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty - createSchemeFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); - createSchemeFeeAmount.Fees.First().BasicFee.ShouldBe(CreateSchemeAmount); - - //others - var othersFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Owner = BootMinerAddress + })).Balance; + beforeBalance.ShouldBe(afterBalance + 0 + transactionSize * 0); + } + + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - Value = nameof(ProfitContractStub.AddBeneficiaries) + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - othersFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty - othersFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); - othersFeeAmount.Fees.First().BasicFee.ShouldBe(DefaultFeeAmount); - } + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + + var methodFeeController = await EconomicContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - //set transaction fee + const string proposalCreationMethodName = + nameof(EconomicContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { - await Profit_SetMethodFee(nameof(ProfitContractStub.CreateScheme), - EconomicSystemTestConstants.NativeTokenSymbol, NewFeeAmount); + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); + await ApproveWithAllMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //query result - var addOptionFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ProfitContractStub.CreateScheme) - }); - addOptionFeeAmount.Fees.Count.ShouldBe(1); - addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); - addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(NewFeeAmount); - } - } + var newMethodFeeController = await EconomicContractStub.GetMethodFeeController.CallAsync(new Empty()); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } - [Fact] - public async Task Profit_Execute_CreateScheme_Test() + private async Task Profit_SetMethodFee_Test() + { + //default fee { - await Profit_SetMethodFee_Test(); - - var tester = Accounts[11].KeyPair; - var testerAddress = Address.FromPublicKey(tester.PublicKey); - var creator = GetProfitContractTester(tester); - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //create scheme + var createSchemeFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Owner = testerAddress - })).Balance; + Value = nameof(ProfitContractStub.CreateScheme) + }); + createSchemeFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty + createSchemeFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); + createSchemeFeeAmount.Fees.First().BasicFee.ShouldBe(CreateSchemeAmount); - var transactionResult = await creator.CreateScheme.SendAsync(new CreateSchemeInput + //others + var othersFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue { - ProfitReceivingDuePeriodCount = 10 + Value = nameof(ProfitContractStub.AddBeneficiaries) }); + othersFeeAmount.MethodName.ShouldBe(string.Empty); //default value is empty + othersFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); + othersFeeAmount.Fees.First().BasicFee.ShouldBe(DefaultFeeAmount); + } - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var transactionSize = transactionResult.Transaction.Size(); + //set transaction fee + { + await Profit_SetMethodFee(nameof(ProfitContractStub.CreateScheme), + EconomicSystemTestConstants.NativeTokenSymbol, NewFeeAmount); - var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //query result + var addOptionFeeAmount = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue { - Symbol = EconomicSystemTestConstants.NativeTokenSymbol, - Owner = testerAddress - })).Balance; - beforeBalance.ShouldBe(afterBalance + 0 + transactionSize * 0); + Value = nameof(ProfitContractStub.CreateScheme) + }); + addOptionFeeAmount.Fees.Count.ShouldBe(1); + addOptionFeeAmount.Fees.First().Symbol.ShouldBe(EconomicSystemTestConstants.NativeTokenSymbol); + addOptionFeeAmount.Fees.First().BasicFee.ShouldBe(NewFeeAmount); } + } + + [Fact] + public async Task Profit_Execute_CreateScheme_Test() + { + await Profit_SetMethodFee_Test(); + + var tester = Accounts[11].KeyPair; + var testerAddress = Address.FromPublicKey(tester.PublicKey); + var creator = GetProfitContractTester(tester); + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Owner = testerAddress + })).Balance; - private async Task Vote_SetMethodFee(string method, string symbol, long feeAmount) + var transactionResult = await creator.CreateScheme.SendAsync(new CreateSchemeInput { - var gensisOwner = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput + ProfitReceivingDuePeriodCount = 10 + }); + + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionSize = transactionResult.Transaction.Size(); + + var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = EconomicSystemTestConstants.NativeTokenSymbol, + Owner = testerAddress + })).Balance; + beforeBalance.ShouldBe(afterBalance + 0 + transactionSize * 0); + } + + private async Task Vote_SetMethodFee(string method, string symbol, long feeAmount) + { + var gensisOwner = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = gensisOwner, + ContractMethodName = nameof(VoteContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new MethodFees { - OrganizationAddress = gensisOwner, - ContractMethodName = nameof(VoteContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new MethodFees + MethodName = method, + Fees = { - MethodName = method, - Fees = + new MethodFee { - new MethodFee - { - Symbol = symbol, - BasicFee = feeAmount - } + Symbol = symbol, + BasicFee = feeAmount } - }.ToByteString(), - ToAddress = VoteContractAddress - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + }.ToByteString(), + ToAddress = VoteContractAddress + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = createResult.Output; - await ApproveWithAllMinersAsync(proposalId); + var proposalId = createResult.Output; + await ApproveWithAllMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - private async Task Profit_SetMethodFee(string method, string symbol, long feeAmount) + private async Task Profit_SetMethodFee(string method, string symbol, long feeAmount) + { + var gensisOwner = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput { - var gensisOwner = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput + OrganizationAddress = gensisOwner, + ContractMethodName = nameof(ProfitContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new MethodFees { - OrganizationAddress = gensisOwner, - ContractMethodName = nameof(ProfitContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new MethodFees + MethodName = method, + Fees = { - MethodName = method, - Fees = + new MethodFee { - new MethodFee - { - Symbol = symbol, - BasicFee = feeAmount - } + Symbol = symbol, + BasicFee = feeAmount } - }.ToByteString(), - ToAddress = ProfitContractAddress - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = createResult.Output; - await ApproveWithAllMinersAsync(proposalId); - - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + } + }.ToByteString(), + ToAddress = ProfitContractAddress + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = createResult.Output; + await ApproveWithAllMinersAsync(proposalId); + + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - private async Task RegisterVotingItemAsync(int lastingDays, int optionsCount, bool isLockToken, - Address sender, - int totalSnapshotNumber = int.MaxValue) + private async Task RegisterVotingItemAsync(int lastingDays, int optionsCount, bool isLockToken, + Address sender, + int totalSnapshotNumber = int.MaxValue) + { + var startTime = TimestampHelper.GetUtcNow(); + var options = Enumerable.Range(0, optionsCount).Select(_ => Accounts[0].Address.ToBase58()) + .ToList(); + var input = new VotingRegisterInput { - var startTime = TimestampHelper.GetUtcNow(); - var options = Enumerable.Range(0, optionsCount).Select(_ => Accounts[0].Address.ToBase58()) - .ToList(); - var input = new VotingRegisterInput - { - TotalSnapshotNumber = totalSnapshotNumber, - EndTimestamp = startTime.AddDays(lastingDays), - StartTimestamp = startTime, - Options = {options}, - AcceptedCurrency = EconomicSystemTestConstants.NativeTokenSymbol, - IsLockToken = isLockToken - }; - var transactionResult = (await VoteContractStub.Register.SendAsync(input)).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - input.Options.Clear(); - var votingItemId = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sender)); - return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = votingItemId - }); - } + TotalSnapshotNumber = totalSnapshotNumber, + EndTimestamp = startTime.AddDays(lastingDays), + StartTimestamp = startTime, + Options = { options }, + AcceptedCurrency = EconomicSystemTestConstants.NativeTokenSymbol, + IsLockToken = isLockToken + }; + var transactionResult = (await VoteContractStub.Register.SendAsync(input)).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + input.Options.Clear(); + var votingItemId = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sender)); + return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput + { + VotingItemId = votingItemId + }); + } - private async Task ApproveWithAllMinersAsync(Hash proposalId) + private async Task ApproveWithAllMinersAsync(Hash proposalId) + { + foreach (var keyPair in InitialCoreDataCenterKeyPairs) { - foreach (var keyPair in InitialCoreDataCenterKeyPairs) - { - var parliamentContractStub = GetParliamentContractTester(keyPair); - var approveResult = await parliamentContractStub.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var parliamentContractStub = GetParliamentContractTester(keyPair); + var approveResult = await parliamentContractStub.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = EconomicContractAddress - }; - - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; - - return proposalId; - } + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = EconomicContractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + + return proposalId; } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasureViewTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasureViewTests.cs index d65a10a5c6..866c2fe00c 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasureViewTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasureViewTests.cs @@ -3,91 +3,91 @@ using AElf.Contracts.Economic.TestBase; using AElf.Contracts.Election; using AElf.Contracts.Profit; -using AElf.ContractTestKit; +using AElf.Contracts.Treasury; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -using GetWelfareRewardAmountSampleInput = AElf.Contracts.Treasury.GetWelfareRewardAmountSampleInput; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest { - public partial class EconomicSystemTest + [Fact] + public async Task GetWelfareRewardAmountSample_Test() { - [Fact] - public async Task GetWelfareRewardAmountSample_Test() - { - await NextTerm(BootMinerKeyPair); - await AttendElectionAndVotes(); - await ProduceBlocks(BootMinerKeyPair, 20); + await NextTerm(BootMinerKeyPair); + await AttendElectionAndVotes(); + await ProduceBlocks(BootMinerKeyPair, 20); - for (var i = 0; i < 3; i++) - { - var contributeProfitsResult = await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + for (var i = 0; i < 3; i++) + { + var contributeProfitsResult = await ProfitContractStub.ContributeProfits.SendAsync( + new ContributeProfitsInput { Amount = 8000_00000000, Period = i + 2, Symbol = EconomicContractsTestConstants.NativeTokenSymbol, SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare] }); - contributeProfitsResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await NextTerm(BootMinerKeyPair); - } - - const int lockTime1 = 300 * 24 * 60 * 60; - const int lockTime2 = 600 * 24 * 60 * 60; - const int lockTime3 = 900 * 24 * 60 * 60; - var rewardAmount = await TreasuryContractStub.GetWelfareRewardAmountSample.CallAsync( - new GetWelfareRewardAmountSampleInput - { - Value = { lockTime1, lockTime2, lockTime3 } - }); - rewardAmount.Value.Count.ShouldBe(3); - - var rewardMoney = rewardAmount.Value.ToArray(); - rewardMoney[0].ShouldBeGreaterThan(0); - rewardMoney[1].ShouldBeGreaterThan(rewardMoney[0]); - rewardMoney[2].ShouldBeGreaterThan(rewardMoney[1]); + contributeProfitsResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await NextTerm(BootMinerKeyPair); } - [Fact] - public async Task GetCurrentTermMiningReward_Test() - { - await NextTerm(BootMinerKeyPair); - await AttendElectionAndVotes(); - await ProduceBlocks(BootMinerKeyPair, 20); + const int lockTime1 = 300 * 24 * 60 * 60; + const int lockTime2 = 600 * 24 * 60 * 60; + const int lockTime3 = 900 * 24 * 60 * 60; + var rewardAmount = await TreasuryContractStub.GetWelfareRewardAmountSample.CallAsync( + new GetWelfareRewardAmountSampleInput + { + Value = { lockTime1, lockTime2, lockTime3 } + }); + rewardAmount.Value.Count.ShouldBe(3); - var currentTermMiningReward = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); - currentTermMiningReward.Value.ShouldBeGreaterThan(0); - } + var rewardMoney = rewardAmount.Value.ToArray(); + rewardMoney[0].ShouldBeGreaterThan(0); + rewardMoney[1].ShouldBeGreaterThan(rewardMoney[0]); + rewardMoney[2].ShouldBeGreaterThan(rewardMoney[1]); + } + + [Fact] + public async Task GetCurrentTermMiningReward_Test() + { + await NextTerm(BootMinerKeyPair); + await AttendElectionAndVotes(); + await ProduceBlocks(BootMinerKeyPair, 20); - private async Task AttendElectionAndVotes() + var currentTermMiningReward = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); + currentTermMiningReward.Value.ShouldBeGreaterThan(0); + } + + private async Task AttendElectionAndVotes() + { + //announce election + foreach (var user in ValidationDataCenterKeyPairs.Take( + EconomicContractsTestConstants.InitialCoreDataCenterCount)) { - //announce election - foreach (var user in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount)) - { - var electionTester = GetElectionContractTester(user); - var electionResult = await electionTester.AnnounceElection.SendAsync(Address.FromPublicKey(user.PublicKey)); - electionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var electionTester = GetElectionContractTester(user); + var electionResult = await electionTester.AnnounceElection.SendAsync(Address.FromPublicKey(user.PublicKey)); + electionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + var candidates = (await ElectionContractStub.GetCandidates.CallAsync(new Empty())) + .Value.Select(o => o.ToHex()).ToArray(); - var candidates = (await ElectionContractStub.GetCandidates.CallAsync(new Empty())) - .Value.Select(o=>o.ToHex()).ToArray(); - - //vote candidate - for (var i = 0; i< EconomicContractsTestConstants.InitialCoreDataCenterCount; i++) + //vote candidate + for (var i = 0; i < EconomicContractsTestConstants.InitialCoreDataCenterCount; i++) + { + var electionTester = GetElectionContractTester(VoterKeyPairs[i]); + var voteResult = await electionTester.Vote.SendAsync(new VoteMinerInput { - var electionTester = GetElectionContractTester(VoterKeyPairs[i]); - var voteResult = await electionTester.Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = candidates[i], - Amount = 10000, - EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100 + 100 * i) - }); - voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + CandidatePubkey = candidates[i], + Amount = 10000, + EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100 + 100 * i) + }); + voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs index fb724cb1b0..44fa2b131a 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs @@ -1,9 +1,5 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; -using AElf.Standards.ACS5; -using AElf.Standards.ACS10; using AElf.Contracts.Economic.TestBase; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; @@ -11,618 +7,629 @@ using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.CSharp.Core; -using AElf.CSharp.Core.Extension; -using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS10; +using AElf.Standards.ACS3; +using AElf.Standards.ACS5; using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.EconomicSystem.Tests.BVT +namespace AElf.Contracts.EconomicSystem.Tests.BVT; + +public partial class EconomicSystemTest : EconomicSystemTestBase { - public partial class EconomicSystemTest : EconomicSystemTestBase + public EconomicSystemTest() { - public EconomicSystemTest() - { - InitializeContracts(); - } + InitializeContracts(); + } - [Fact] - public async Task EconomistSystem_CheckBasicInformation_Test() - { - var symbolList = await TreasuryContractStub.GetSymbolList.CallAsync(new Empty()); - symbolList.Value.Count.ShouldBe(1); - symbolList.Value[0].ShouldBe(EconomicContractsTestConstants.NativeTokenSymbol); - - // Treasury contract created Treasury profit scheme and set Profit Id to Profit Contract. - var treasuryProfit = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); - treasuryProfit.Manager.ShouldBe(TreasuryContractAddress); - treasuryProfit.SubSchemes.Count.ShouldBe(3); - treasuryProfit.IsReleaseAllBalanceEveryTimeByDefault.ShouldBe(true); - } + [Fact] + public async Task EconomistSystem_CheckBasicInformation_Test() + { + var symbolList = await TreasuryContractStub.GetSymbolList.CallAsync(new Empty()); + symbolList.Value.Count.ShouldBe(1); + symbolList.Value[0].ShouldBe(EconomicContractsTestConstants.NativeTokenSymbol); - [Fact] - public async Task EconomistSystem_SetMethodCallThreshold_Test() - { - const long feeAmount = 100L; - var setMethodResult = await MethodCallThresholdContractStub.SetMethodCallingThreshold.SendAsync( - new SetMethodCallingThresholdInput - { - Method = nameof(MethodCallThresholdContractStub.SendForFun), - SymbolToAmount = {{EconomicSystemTestConstants.NativeTokenSymbol, feeAmount}} - }); - setMethodResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // Treasury contract created Treasury profit scheme and set Profit Id to Profit Contract. + var treasuryProfit = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); + treasuryProfit.Manager.ShouldBe(TreasuryContractAddress); + treasuryProfit.SubSchemes.Count.ShouldBe(3); + treasuryProfit.IsReleaseAllBalanceEveryTimeByDefault.ShouldBe(true); + } - var tokenAmount = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync(new StringValue + [Fact] + public async Task EconomistSystem_SetMethodCallThreshold_Test() + { + const long feeAmount = 100L; + var setMethodResult = await MethodCallThresholdContractStub.SetMethodCallingThreshold.SendAsync( + new SetMethodCallingThresholdInput { - Value = nameof(MethodCallThresholdContractStub.SendForFun) + Method = nameof(MethodCallThresholdContractStub.SendForFun), + SymbolToAmount = { { EconomicSystemTestConstants.NativeTokenSymbol, feeAmount } } }); - tokenAmount.SymbolToAmount[EconomicSystemTestConstants.NativeTokenSymbol].ShouldBe(feeAmount); - } + setMethodResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task Treasury_Dividend_Pool_Weight_Update_To_Miner_Reward_Weight_Test() + var tokenAmount = await MethodCallThresholdContractStub.GetMethodCallingThreshold.CallAsync(new StringValue { - var newWeightSetting = new DividendPoolWeightSetting - { - BackupSubsidyWeight = 1, - CitizenWelfareWeight = 1, - MinerRewardWeight = 8 - }; - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, nameof(TreasuryContractStub.SetDividendPoolWeightSetting), newWeightSetting); - var minerRewardProfit = - await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); - var subSchemes = minerRewardProfit.SubSchemes; - subSchemes.Count.ShouldBe(3); - var minerRewardWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); - var basicMinerRewardScheme = subSchemes.Single(x => - x.SchemeId == minerRewardWeightSetting.BasicMinerRewardProportionInfo.SchemeId); - basicMinerRewardScheme.Shares.ShouldBe(2); - var reElectionRewardScheme = subSchemes.Single(x => - x.SchemeId == minerRewardWeightSetting.WelcomeRewardProportionInfo.SchemeId); - reElectionRewardScheme.Shares.ShouldBe(1); - var votesWeightRewardScheme = subSchemes.Single(x => - x.SchemeId == minerRewardWeightSetting.FlexibleRewardProportionInfo.SchemeId); - votesWeightRewardScheme.Shares.ShouldBe(1); - } + Value = nameof(MethodCallThresholdContractStub.SendForFun) + }); + tokenAmount.SymbolToAmount[EconomicSystemTestConstants.NativeTokenSymbol].ShouldBe(feeAmount); + } - [Fact] - public async Task TreasuryContract_InitialTreasuryContract_Repeat_Test() - { - var repeatInitializeRet = await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - repeatInitializeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - repeatInitializeRet.TransactionResult.Error.ShouldContain("Already initialized"); - } - - [Fact] - public async Task TreasuryContract_InitialMiningRewardProfitItem_Repeat_Test() + [Fact] + public async Task Treasury_Dividend_Pool_Weight_Update_To_Miner_Reward_Weight_Test() + { + var newWeightSetting = new DividendPoolWeightSetting { - var repeatInitializeRet = await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); - repeatInitializeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - repeatInitializeRet.TransactionResult.Error.ShouldContain("Already initialized"); - } - - [Fact] - public async Task TreasuryContract_Release_Without_Authority_Test() + BackupSubsidyWeight = 1, + CitizenWelfareWeight = 1, + MinerRewardWeight = 8 + }; + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + nameof(TreasuryContractStub.SetDividendPoolWeightSetting), newWeightSetting); + var minerRewardProfit = + await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); + var subSchemes = minerRewardProfit.SubSchemes; + subSchemes.Count.ShouldBe(3); + var minerRewardWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); + var basicMinerRewardScheme = subSchemes.Single(x => + x.SchemeId == minerRewardWeightSetting.BasicMinerRewardProportionInfo.SchemeId); + basicMinerRewardScheme.Shares.ShouldBe(2); + var reElectionRewardScheme = subSchemes.Single(x => + x.SchemeId == minerRewardWeightSetting.WelcomeRewardProportionInfo.SchemeId); + reElectionRewardScheme.Shares.ShouldBe(1); + var votesWeightRewardScheme = subSchemes.Single(x => + x.SchemeId == minerRewardWeightSetting.FlexibleRewardProportionInfo.SchemeId); + votesWeightRewardScheme.Shares.ShouldBe(1); + } + + [Fact] + public async Task TreasuryContract_InitialTreasuryContract_Repeat_Test() + { + var repeatInitializeRet = await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + repeatInitializeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + repeatInitializeRet.TransactionResult.Error.ShouldContain("Already initialized"); + } + + [Fact] + public async Task TreasuryContract_InitialMiningRewardProfitItem_Repeat_Test() + { + var repeatInitializeRet = await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); + repeatInitializeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + repeatInitializeRet.TransactionResult.Error.ShouldContain("Already initialized"); + } + + [Fact] + public async Task TreasuryContract_Release_Without_Authority_Test() + { + var releaseRet = await TreasuryContractStub.Release.SendAsync(new ReleaseInput()); + releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseRet.TransactionResult.Error.ShouldContain( + "nly AElf Consensus Contract can release profits from Treasury"); + } + + [Fact] + public async Task TreasuryContract_InitialMiningRewardProfitItem_Success_Test() + { + var treasurySchemeId = await TreasuryContractStub.GetTreasurySchemeId.CallAsync(new Empty()); + treasurySchemeId.ShouldBe(ProfitItemsIds[ProfitType.Treasury]); + var defaultDividendPoolWeightSetting = + await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); + defaultDividendPoolWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(5); + defaultDividendPoolWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(75); + defaultDividendPoolWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(20); + + var defaultMinerRewardWeightSetting = + await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); + defaultMinerRewardWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(50); + defaultMinerRewardWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(25); + defaultMinerRewardWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(25); + + var treasuryScheme = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput { - var releaseRet = await TreasuryContractStub.Release.SendAsync(new ReleaseInput()); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseRet.TransactionResult.Error.ShouldContain("nly AElf Consensus Contract can release profits from Treasury"); - } - - [Fact] - public async Task TreasuryContract_InitialMiningRewardProfitItem_Success_Test() + Manager = TreasuryContractAddress + }); + var electionScheme = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput { - var treasurySchemeId = await TreasuryContractStub.GetTreasurySchemeId.CallAsync(new Empty()); - treasurySchemeId.ShouldBe(ProfitItemsIds[ProfitType.Treasury]); - var defaultDividendPoolWeightSetting = await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); - defaultDividendPoolWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(5); - defaultDividendPoolWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(75); - defaultDividendPoolWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(20); - - var defaultMinerRewardWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); - defaultMinerRewardWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(50); - defaultMinerRewardWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(25); - defaultMinerRewardWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(25); - - var treasuryScheme = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = TreasuryContractAddress - }); - var electionScheme = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = ElectionContractAddress - }); - treasuryScheme.SchemeIds.Count.ShouldBe(5); - electionScheme.SchemeIds.Count.ShouldBe(2); - } + Manager = ElectionContractAddress + }); + treasuryScheme.SchemeIds.Count.ShouldBe(5); + electionScheme.SchemeIds.Count.ShouldBe(2); + } - [Fact] - public async Task TreasuryContract_Donate_With_Invalid_Input_Test() + [Fact] + public async Task TreasuryContract_Donate_With_Invalid_Input_Test() + { + var donateRet = await TreasuryContractStub.Donate.SendAsync(new DonateInput { - var donateRet = await TreasuryContractStub.Donate.SendAsync(new DonateInput - { - Amount = 0 - }); - donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - donateRet.TransactionResult.Error.ShouldContain("Invalid amount of donating"); - } - - [Fact] - public async Task TreasuryContract_Donate_Success_Test() - { - // donate resource token - var resourceTokenSymbol = ResourceTokenSymbol; - var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; - var startResourceTokenDeposit = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( - new StringValue - { - Value = resourceTokenSymbol - }); - var balanceOfResourceTokenSymbol = await GetBalanceAsync(resourceTokenSymbol, BootMinerAddress); - balanceOfResourceTokenSymbol.ShouldBe(0); - var buyAmount = 1_00000000; - var approveAmount = 1_00000000; - await TokenContractStub.Approve.SendAsync(new ApproveInput + Amount = 0 + }); + donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + donateRet.TransactionResult.Error.ShouldContain("Invalid amount of donating"); + } + + [Fact] + public async Task TreasuryContract_Donate_Success_Test() + { + // donate resource token + var resourceTokenSymbol = ResourceTokenSymbol; + var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; + var startResourceTokenDeposit = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( + new StringValue { - Symbol = nativeTokenSymbol, - Amount = approveAmount, - Spender = TokenConverterContractAddress + Value = resourceTokenSymbol }); - var buyRet = await TokenConverterContractStub.Buy.SendAsync(new BuyInput + var balanceOfResourceTokenSymbol = await GetBalanceAsync(resourceTokenSymbol, BootMinerAddress); + balanceOfResourceTokenSymbol.ShouldBe(0); + var buyAmount = 1_00000000; + var approveAmount = 1_00000000; + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = nativeTokenSymbol, + Amount = approveAmount, + Spender = TokenConverterContractAddress + }); + var buyRet = await TokenConverterContractStub.Buy.SendAsync(new BuyInput + { + Symbol = resourceTokenSymbol, + Amount = buyAmount + }); + buyRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var depositBeforeDonate = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( + new StringValue { - Symbol = resourceTokenSymbol, - Amount = buyAmount + Value = ResourceTokenSymbol }); - buyRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var depositBeforeDonate = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( - new StringValue - { - Value = ResourceTokenSymbol - }); - var nativeTokenCost = depositBeforeDonate.Value.Sub(startResourceTokenDeposit.Value); - var treasuryVirtualAddress = await GetTreasurySchemeVirtualAddressAsync(); - var balanceOfTreasuryBeforeDonate = await GetBalanceAsync(nativeTokenSymbol, treasuryVirtualAddress); - //donate - var donateRet = await TreasuryContractStub.Donate.SendAsync(new DonateInput + var nativeTokenCost = depositBeforeDonate.Value.Sub(startResourceTokenDeposit.Value); + var treasuryVirtualAddress = await GetTreasurySchemeVirtualAddressAsync(); + var balanceOfTreasuryBeforeDonate = await GetBalanceAsync(nativeTokenSymbol, treasuryVirtualAddress); + //donate + var donateRet = await TreasuryContractStub.Donate.SendAsync(new DonateInput + { + Symbol = resourceTokenSymbol, + Amount = buyAmount + }); + donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var depositAfterDonate = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( + new StringValue { - Symbol = resourceTokenSymbol, - Amount = buyAmount + Value = ResourceTokenSymbol }); - donateRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var depositAfterDonate = await TokenConverterContractStub.GetDepositConnectorBalance.CallAsync( - new StringValue - { - Value = ResourceTokenSymbol - }); - depositBeforeDonate.Value.Sub(depositAfterDonate.Value).ShouldBe(nativeTokenCost); - var feeRateString = EconomicContractsTestConstants.TokenConverterFeeRate; - var feeRate = decimal.Parse(feeRateString); - var balanceOfTreasuryAfterDonate = await GetBalanceAsync(nativeTokenSymbol, treasuryVirtualAddress); - balanceOfTreasuryAfterDonate.ShouldBe(nativeTokenCost.Add(balanceOfTreasuryBeforeDonate)); - } + depositBeforeDonate.Value.Sub(depositAfterDonate.Value).ShouldBe(nativeTokenCost); + var feeRateString = EconomicContractsTestConstants.TokenConverterFeeRate; + var feeRate = decimal.Parse(feeRateString); + var balanceOfTreasuryAfterDonate = await GetBalanceAsync(nativeTokenSymbol, treasuryVirtualAddress); + balanceOfTreasuryAfterDonate.ShouldBe(nativeTokenCost.Add(balanceOfTreasuryBeforeDonate)); + } - [Fact] - public async Task Treasury_ChangeTreasuryController_Fail_Test() + [Fact] + public async Task Treasury_ChangeTreasuryController_Fail_Test() + { + // without authority { - // without authority - { - var changeRet = await TreasuryContractStub.ChangeTreasuryController.SendAsync(new AuthorityInfo()); - changeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - changeRet.TransactionResult.Error.ShouldContain("no permission"); - } - - // organization does not exist - { - var newController = new AuthorityInfo - { - OwnerAddress = ParliamentContractAddress, - ContractAddress = ParliamentContractAddress - }; - var changeRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, - nameof(TreasuryContractStub.ChangeTreasuryController), newController); - changeRet.Status.ShouldBe(TransactionResultStatus.Failed); - changeRet.Error.ShouldContain("Invalid authority input"); - } + var changeRet = await TreasuryContractStub.ChangeTreasuryController.SendAsync(new AuthorityInfo()); + changeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + changeRet.TransactionResult.Error.ShouldContain("no permission"); } - - [Fact] - public async Task Treasury_ChangeTreasuryController_Success_Test() + + // organization does not exist { - var newParliament = new CreateOrganizationInput - { - ProposerAuthorityRequired = false, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 1, - MaximalRejectionThreshold = 1, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = false - }; - var createNewParliament = - (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; - createNewParliament.Status.ShouldBe(TransactionResultStatus.Mined); - var calculatedNewParliamentAddress = await ParliamentContractStub.CalculateOrganizationAddress.CallAsync(newParliament); var newController = new AuthorityInfo { - ContractAddress = ParliamentContractAddress, - OwnerAddress = calculatedNewParliamentAddress + OwnerAddress = ParliamentContractAddress, + ContractAddress = ParliamentContractAddress }; - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + var changeRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, nameof(TreasuryContractStub.ChangeTreasuryController), newController); - var getController = await TreasuryContractStub.GetTreasuryController.CallAsync(new Empty()); - getController.ContractAddress.ShouldBe(newController.ContractAddress); - getController.OwnerAddress.ShouldBe(newController.OwnerAddress); - } - - [Fact] - public async Task Treasury_SetSymbolList_Without_Authority() - { - var setRet = await TreasuryContractStub.SetSymbolList.SendAsync(new SymbolList()); - setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setRet.TransactionResult.Error.ShouldContain("no permission"); + changeRet.Status.ShouldBe(TransactionResultStatus.Failed); + changeRet.Error.ShouldContain("Invalid authority input"); } + } - [Fact] - public async Task Treasury_SetSymbolList_With_Invalid_Token_Test() + [Fact] + public async Task Treasury_ChangeTreasuryController_Success_Test() + { + var newParliament = new CreateOrganizationInput { - var tokenSymbol = "TEST"; - var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; - var resourceTokenSymbol = ResourceTokenSymbol; - var methodName = nameof(TreasuryContractStub.SetSymbolList); - var tokenCreateInput = new CreateInput - { - Symbol = tokenSymbol, - TokenName = "TEST name", - TotalSupply = 1_0000_0000, - Issuer = BootMinerAddress, - IsBurnable = true - }; - var createTokenRet = await TokenContractStub.Create.SendAsync(tokenCreateInput); - createTokenRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - // without native token + ProposerAuthorityRequired = false, + ProposalReleaseThreshold = new ProposalReleaseThreshold { - var newSymbolList = new SymbolList - { - Value = - { - tokenSymbol - } - }; - var setSymbolRet = - await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, - newSymbolList); - setSymbolRet.Error.ShouldContain("Need to contain native symbol"); - } - - //not valid connector - { - var newSymbolList = new SymbolList - { - Value = - { - nativeTokenSymbol, resourceTokenSymbol - } - }; - var setSymbolRet = - await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, - newSymbolList); - setSymbolRet.Error.ShouldContain($"Token {resourceTokenSymbol} doesn't need to set to symbol list"); - } - } + MaximalAbstentionThreshold = 1, + MaximalRejectionThreshold = 1, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = false + }; + var createNewParliament = + (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; + createNewParliament.Status.ShouldBe(TransactionResultStatus.Mined); + var calculatedNewParliamentAddress = + await ParliamentContractStub.CalculateOrganizationAddress.CallAsync(newParliament); + var newController = new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, + OwnerAddress = calculatedNewParliamentAddress + }; + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + nameof(TreasuryContractStub.ChangeTreasuryController), newController); + var getController = await TreasuryContractStub.GetTreasuryController.CallAsync(new Empty()); + getController.ContractAddress.ShouldBe(newController.ContractAddress); + getController.OwnerAddress.ShouldBe(newController.OwnerAddress); + } - [Fact] - public async Task Treasury_SetSymbolList_Success_Test() + [Fact] + public async Task Treasury_SetSymbolList_Without_Authority() + { + var setRet = await TreasuryContractStub.SetSymbolList.SendAsync(new SymbolList()); + setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setRet.TransactionResult.Error.ShouldContain("no permission"); + } + + [Fact] + public async Task Treasury_SetSymbolList_With_Invalid_Token_Test() + { + var tokenSymbol = "TEST"; + var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; + var resourceTokenSymbol = ResourceTokenSymbol; + var methodName = nameof(TreasuryContractStub.SetSymbolList); + var tokenCreateInput = new CreateInput + { + Symbol = tokenSymbol, + TokenName = "TEST name", + TotalSupply = 1_0000_0000, + Issuer = BootMinerAddress, + IsBurnable = true + }; + var createTokenRet = await TokenContractStub.Create.SendAsync(tokenCreateInput); + createTokenRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // without native token { - var tokenSymbol = "CWJ"; - var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; - var methodName = nameof(TreasuryContractStub.SetSymbolList); - var tokenCreateInput = new CreateInput - { - Symbol = tokenSymbol, - TokenName = "CWJ name", - TotalSupply = 1_0000_0000, - Issuer = BootMinerAddress, - IsBurnable = true - }; - await TokenContractStub.Create.SendAsync(tokenCreateInput); var newSymbolList = new SymbolList { Value = { - nativeTokenSymbol, tokenSymbol + tokenSymbol } }; - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, methodName, + var setSymbolRet = + await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, newSymbolList); - var getSymbolList = await TreasuryContractStub.GetSymbolList.CallAsync(new Empty()); - getSymbolList.Value.Count.ShouldBe(2); - getSymbolList.Value.Contains(tokenSymbol).ShouldBeTrue(); + setSymbolRet.Error.ShouldContain("Need to contain native symbol"); } - [Fact] - public async Task Treasury_SetDividendPoolWeightSetting_Fail_Test() + //not valid connector { - // No permission - { - var setRet = - await TreasuryContractStub.SetDividendPoolWeightSetting.SendAsync(new DividendPoolWeightSetting()); - setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setRet.TransactionResult.Error.ShouldContain("no permission"); - } - - // Invalid input + var newSymbolList = new SymbolList { - var methodName = nameof(TreasuryContractStub.SetDividendPoolWeightSetting); - var newDividendSetting = new DividendPoolWeightSetting + Value = { - BackupSubsidyWeight = 0 - }; - var setRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, - newDividendSetting); - setRet.Status.ShouldBe(TransactionResultStatus.Failed); - setRet.Error.ShouldContain("invalid input"); - } + nativeTokenSymbol, resourceTokenSymbol + } + }; + var setSymbolRet = + await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, + newSymbolList); + setSymbolRet.Error.ShouldContain($"Token {resourceTokenSymbol} doesn't need to set to symbol list"); } + } - [Fact] - public async Task Treasury_SetDividendPoolWeightSetting_Success_Test() + [Fact] + public async Task Treasury_SetSymbolList_Success_Test() + { + var tokenSymbol = "CWJ"; + var nativeTokenSymbol = EconomicContractsTestConstants.NativeTokenSymbol; + var methodName = nameof(TreasuryContractStub.SetSymbolList); + var tokenCreateInput = new CreateInput { - var defaultWeightSetting = await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); - defaultWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(5); - defaultWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(75); - defaultWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(20); - var newWeightSetting = new DividendPoolWeightSetting - { - BackupSubsidyWeight = 1, - CitizenWelfareWeight = 1, - MinerRewardWeight = 8 - }; - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, nameof(TreasuryContractStub.SetDividendPoolWeightSetting), newWeightSetting); - var updatedWeightSetting = await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); - updatedWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(10); - updatedWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(10); - updatedWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(80); - var treasuryProfit = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); - var subSchemes = treasuryProfit.SubSchemes; - subSchemes.Count.ShouldBe(3); - var backSubsidyScheme = subSchemes.Single(x => x.SchemeId == updatedWeightSetting.BackupSubsidyProportionInfo.SchemeId); - backSubsidyScheme.Shares.ShouldBe(1); - var citizenWelfareScheme = subSchemes.Single(x => x.SchemeId == updatedWeightSetting.CitizenWelfareProportionInfo.SchemeId); - citizenWelfareScheme.Shares.ShouldBe(1); - var minerRewardScheme = subSchemes.Single(x => x.SchemeId == updatedWeightSetting.MinerRewardProportionInfo.SchemeId); - minerRewardScheme.Shares.ShouldBe(8); - } - - [Fact] - public async Task Treasury_SetMinerRewardWeightSetting_Fail_Test() + Symbol = tokenSymbol, + TokenName = "CWJ name", + TotalSupply = 1_0000_0000, + Issuer = BootMinerAddress, + IsBurnable = true + }; + await TokenContractStub.Create.SendAsync(tokenCreateInput); + var newSymbolList = new SymbolList { - //without authority + Value = { - var setRet = - await TreasuryContractStub.SetMinerRewardWeightSetting.SendAsync(new MinerRewardWeightSetting()); - setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setRet.TransactionResult.Error.ShouldContain("no permission"); - } - - //invalid Inpout - { - var methodName = nameof(TreasuryContractStub.SetMinerRewardWeightSetting); - var newRewardWeightSetting= new MinerRewardWeightSetting - { - BasicMinerRewardWeight = 0 - }; - var setRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, methodName, - newRewardWeightSetting); - setRet.Status.ShouldBe(TransactionResultStatus.Failed); - setRet.Error.ShouldContain("invalid input"); + nativeTokenSymbol, tokenSymbol } + }; + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, methodName, + newSymbolList); + var getSymbolList = await TreasuryContractStub.GetSymbolList.CallAsync(new Empty()); + getSymbolList.Value.Count.ShouldBe(2); + getSymbolList.Value.Contains(tokenSymbol).ShouldBeTrue(); + } + + [Fact] + public async Task Treasury_SetDividendPoolWeightSetting_Fail_Test() + { + // No permission + { + var setRet = + await TreasuryContractStub.SetDividendPoolWeightSetting.SendAsync(new DividendPoolWeightSetting()); + setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setRet.TransactionResult.Error.ShouldContain("no permission"); } - [Fact] - public async Task Treasury_SetMinerRewardWeightSetting_Success_Test() + // Invalid input { - var defaultWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); - defaultWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(50); - defaultWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(25); - defaultWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(25); - var newWeightSetting = new MinerRewardWeightSetting + var methodName = nameof(TreasuryContractStub.SetDividendPoolWeightSetting); + var newDividendSetting = new DividendPoolWeightSetting { - BasicMinerRewardWeight = 1, - WelcomeRewardWeight = 1, - FlexibleRewardWeight = 8 + BackupSubsidyWeight = 0 }; - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, - nameof(TreasuryContractStub.SetMinerRewardWeightSetting), newWeightSetting); - - var updatedWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); - updatedWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(10); - updatedWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(10); - updatedWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(80); - - var minerRewardProfit = - await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); - var subSchemes = minerRewardProfit.SubSchemes; - subSchemes.Count.ShouldBe(3); - var basicMinerRewardScheme = subSchemes.Single(x => - x.SchemeId == updatedWeightSetting.BasicMinerRewardProportionInfo.SchemeId); - basicMinerRewardScheme.Shares.ShouldBe(1); - var welcomeRewardScheme = subSchemes.Single(x => - x.SchemeId == updatedWeightSetting.WelcomeRewardProportionInfo.SchemeId); - welcomeRewardScheme.Shares.ShouldBe(1); - var flexibleRewardScheme = subSchemes.Single(x => - x.SchemeId == updatedWeightSetting.FlexibleRewardProportionInfo.SchemeId); - flexibleRewardScheme.Shares.ShouldBe(8); + var setRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, + methodName, + newDividendSetting); + setRet.Status.ShouldBe(TransactionResultStatus.Failed); + setRet.Error.ShouldContain("invalid input"); } + } - [Fact] - public async Task Treasury_ChangeMethodFeeController_Test() + [Fact] + public async Task Treasury_SetDividendPoolWeightSetting_Success_Test() + { + var defaultWeightSetting = await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); + defaultWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(5); + defaultWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(75); + defaultWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(20); + var newWeightSetting = new DividendPoolWeightSetting { - var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - - var organizationAddress = createOrganizationResult.Output; - - var methodFeeController = await TreasuryContractStub.GetMethodFeeController.CallAsync(new Empty()); - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, - nameof(TreasuryContractStub.ChangeMethodFeeController), - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = methodFeeController.ContractAddress - }); + BackupSubsidyWeight = 1, + CitizenWelfareWeight = 1, + MinerRewardWeight = 8 + }; + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + nameof(TreasuryContractStub.SetDividendPoolWeightSetting), newWeightSetting); + var updatedWeightSetting = await TreasuryContractStub.GetDividendPoolWeightProportion.CallAsync(new Empty()); + updatedWeightSetting.BackupSubsidyProportionInfo.Proportion.ShouldBe(10); + updatedWeightSetting.CitizenWelfareProportionInfo.Proportion.ShouldBe(10); + updatedWeightSetting.MinerRewardProportionInfo.Proportion.ShouldBe(80); + var treasuryProfit = await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); + var subSchemes = treasuryProfit.SubSchemes; + subSchemes.Count.ShouldBe(3); + var backSubsidyScheme = + subSchemes.Single(x => x.SchemeId == updatedWeightSetting.BackupSubsidyProportionInfo.SchemeId); + backSubsidyScheme.Shares.ShouldBe(1); + var citizenWelfareScheme = + subSchemes.Single(x => x.SchemeId == updatedWeightSetting.CitizenWelfareProportionInfo.SchemeId); + citizenWelfareScheme.Shares.ShouldBe(1); + var minerRewardScheme = + subSchemes.Single(x => x.SchemeId == updatedWeightSetting.MinerRewardProportionInfo.SchemeId); + minerRewardScheme.Shares.ShouldBe(8); + } - var newMethodFeeController = await TreasuryContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } - - - [Fact] - public async Task Treasury_ChangeMethodFeeController_With_Invalid_Authority_Test() + [Fact] + public async Task Treasury_SetMinerRewardWeightSetting_Fail_Test() + { + //without authority { - var newController = new AuthorityInfo - { - OwnerAddress = ElectionContractAddress, - ContractAddress = ParliamentContractAddress - }; - var proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); - var changeRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, - nameof(TreasuryContractStub.ChangeMethodFeeController), newController); - changeRet.Status.ShouldBe(TransactionResultStatus.Failed); - changeRet.Error.ShouldContain("Invalid authority input"); + var setRet = + await TreasuryContractStub.SetMinerRewardWeightSetting.SendAsync(new MinerRewardWeightSetting()); + setRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setRet.TransactionResult.Error.ShouldContain("no permission"); } - [Fact] - public async Task Treasury_ChangeMethodFeeController_WithoutAuth_Test() + //invalid Inpout { - var newController = new AuthorityInfo + var methodName = nameof(TreasuryContractStub.SetMinerRewardWeightSetting); + var newRewardWeightSetting = new MinerRewardWeightSetting { - OwnerAddress = ElectionContractAddress, - ContractAddress = ParliamentContractAddress + BasicMinerRewardWeight = 0 }; - var result = await TreasuryContractStub.ChangeMethodFeeController.SendAsync(newController); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Unauthorized behavior"); + var setRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, + methodName, + newRewardWeightSetting); + setRet.Status.ShouldBe(TransactionResultStatus.Failed); + setRet.Error.ShouldContain("invalid input"); } - - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() + } + + [Fact] + public async Task Treasury_SetMinerRewardWeightSetting_Success_Test() + { + var defaultWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); + defaultWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(50); + defaultWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(25); + defaultWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(25); + var newWeightSetting = new MinerRewardWeightSetting { - // Invalid amount + BasicMinerRewardWeight = 1, + WelcomeRewardWeight = 1, + FlexibleRewardWeight = 8 + }; + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + nameof(TreasuryContractStub.SetMinerRewardWeightSetting), newWeightSetting); + + var updatedWeightSetting = await TreasuryContractStub.GetMinerRewardWeightProportion.CallAsync(new Empty()); + updatedWeightSetting.BasicMinerRewardProportionInfo.Proportion.ShouldBe(10); + updatedWeightSetting.WelcomeRewardProportionInfo.Proportion.ShouldBe(10); + updatedWeightSetting.FlexibleRewardProportionInfo.Proportion.ShouldBe(80); + + var minerRewardProfit = + await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.MinerReward]); + var subSchemes = minerRewardProfit.SubSchemes; + subSchemes.Count.ShouldBe(3); + var basicMinerRewardScheme = subSchemes.Single(x => + x.SchemeId == updatedWeightSetting.BasicMinerRewardProportionInfo.SchemeId); + basicMinerRewardScheme.Shares.ShouldBe(1); + var welcomeRewardScheme = subSchemes.Single(x => + x.SchemeId == updatedWeightSetting.WelcomeRewardProportionInfo.SchemeId); + welcomeRewardScheme.Shares.ShouldBe(1); + var flexibleRewardScheme = subSchemes.Single(x => + x.SchemeId == updatedWeightSetting.FlexibleRewardProportionInfo.SchemeId); + flexibleRewardScheme.Shares.ShouldBe(8); + } + + [Fact] + public async Task Treasury_ChangeMethodFeeController_Test() + { + var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - var setMethodFeeRet = await TreasuryContractStub.SetMethodFee.SendAsync(new MethodFees + ProposalReleaseThreshold = new ProposalReleaseThreshold { - MethodName = "Test", - Fees = - { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = -111 - } - } - }); - setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + + var organizationAddress = createOrganizationResult.Output; - // token does not exist + var methodFeeController = await TreasuryContractStub.GetMethodFeeController.CallAsync(new Empty()); + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, + nameof(TreasuryContractStub.ChangeMethodFeeController), + new AuthorityInfo { - var setMethodFeeRet = await TreasuryContractStub.SetMethodFee.SendAsync(new MethodFees - { - MethodName = "Test", - Fees = - { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = 111 - } - } - }); - setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); - } - } + OwnerAddress = organizationAddress, + ContractAddress = methodFeeController.ContractAddress + }); + + var newMethodFeeController = await TreasuryContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task SetMethodFee_Without_Authority_Test() + + [Fact] + public async Task Treasury_ChangeMethodFeeController_With_Invalid_Authority_Test() + { + var newController = new AuthorityInfo + { + OwnerAddress = ElectionContractAddress, + ContractAddress = ParliamentContractAddress + }; + var proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); + var changeRet = await ExecuteProposalForParliamentTransactionWithException(Tester, TreasuryContractAddress, + nameof(TreasuryContractStub.ChangeMethodFeeController), newController); + changeRet.Status.ShouldBe(TransactionResultStatus.Failed); + changeRet.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task Treasury_ChangeMethodFeeController_WithoutAuth_Test() + { + var newController = new AuthorityInfo + { + OwnerAddress = ElectionContractAddress, + ContractAddress = ParliamentContractAddress + }; + var result = await TreasuryContractStub.ChangeMethodFeeController.SendAsync(newController); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior"); + } + + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + // Invalid amount { - var tokenSymbol = "ELF"; - var methodName = "Test"; - var basicFee = 111; var setMethodFeeRet = await TreasuryContractStub.SetMethodFee.SendAsync(new MethodFees { - MethodName = methodName, + MethodName = "Test", Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = basicFee + Symbol = "NOTEXIST", + BasicFee = -111 } } }); setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); } - [Fact] - public async Task SetMethodFee_Success_Test() + // token does not exist { - var tokenSymbol = "ELF"; - var methodName = "Test"; - var basicFee = 111; - var newMethodFees = new MethodFees + var setMethodFeeRet = await TreasuryContractStub.SetMethodFee.SendAsync(new MethodFees { - MethodName = methodName, + MethodName = "Test", Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = basicFee + Symbol = "NOTEXIST", + BasicFee = 111 } } - }; - const string proposalCreationMethodName = nameof(TreasuryContractStub.SetMethodFee); - await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, proposalCreationMethodName, - newMethodFees); - var getMethodFee = await TreasuryContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); + setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); } + } - private async Task
GetTreasurySchemeVirtualAddressAsync() + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + var tokenSymbol = "ELF"; + var methodName = "Test"; + var basicFee = 111; + var setMethodFeeRet = await TreasuryContractStub.SetMethodFee.SendAsync(new MethodFees { - var treasurySchemeId = await TreasuryContractStub.GetTreasurySchemeId.CallAsync(new Empty()); - var treasuryScheme = await ProfitContractStub.GetScheme.CallAsync(treasurySchemeId); - return treasuryScheme.VirtualAddress; - } - - private async Task GetBalanceAsync(string symbol, Address owner) - { - var balanceResult = await TokenContractStub.GetBalance.CallAsync( - new GetBalanceInput() - { - Owner = owner, - Symbol = symbol - }); - return balanceResult.Balance; - } + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = tokenSymbol, + BasicFee = basicFee + } + } + }); + setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task SetMethodFee_Success_Test() + { + var tokenSymbol = "ELF"; + var methodName = "Test"; + var basicFee = 111; + var newMethodFees = new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = tokenSymbol, + BasicFee = basicFee + } + } + }; + const string proposalCreationMethodName = nameof(TreasuryContractStub.SetMethodFee); + await ExecuteProposalForParliamentTransaction(TreasuryContractAddress, proposalCreationMethodName, + newMethodFees); + var getMethodFee = await TreasuryContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); + } + + private async Task
GetTreasurySchemeVirtualAddressAsync() + { + var treasurySchemeId = await TreasuryContractStub.GetTreasurySchemeId.CallAsync(new Empty()); + var treasuryScheme = await ProfitContractStub.GetScheme.CallAsync(treasurySchemeId); + return treasuryScheme.VirtualAddress; + } + + private async Task GetBalanceAsync(string symbol, Address owner) + { + var balanceResult = await TokenContractStub.GetBalance.CallAsync( + new GetBalanceInput + { + Owner = owner, + Symbol = symbol + }); + return balanceResult.Balance; } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestBase.cs b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestBase.cs index 4975d36019..3947cb09dc 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestBase.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestBase.cs @@ -14,163 +14,163 @@ using AElf.Contracts.Treasury; using AElf.Contracts.Vote; using AElf.Cryptography.ECDSA; -using AElf.Standards.ACS1; using Volo.Abp.Threading; -namespace AElf.Contracts.EconomicSystem.Tests +namespace AElf.Contracts.EconomicSystem.Tests; + +// ReSharper disable InconsistentNaming +public class EconomicSystemTestBase : EconomicContractsTestBase { - // ReSharper disable InconsistentNaming - public class EconomicSystemTestBase : EconomicContractsTestBase - { - protected void InitializeContracts() - { - DeployAllContracts(); - - AsyncHelper.RunSync(InitializeParliamentContract); - AsyncHelper.RunSync(InitializeTreasuryConverter); - AsyncHelper.RunSync(InitializeElection); - AsyncHelper.RunSync(InitializeEconomicContract); - AsyncHelper.RunSync(InitializeToken); - AsyncHelper.RunSync(InitializeAElfConsensus); - AsyncHelper.RunSync(InitializeTokenConverter); - AsyncHelper.RunSync(InitializeTransactionFeeChargingContract); - } - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => - GetBasicContractTester(BootMinerKeyPair); - - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); - - internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub => - GetTokenContractImplTester(BootMinerKeyPair); - - internal TokenHolderContractImplContainer.TokenHolderContractImplStub TokenHolderStub => - GetTokenHolderTester(BootMinerKeyPair); - - internal TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub => - GetTokenConverterContractTester(BootMinerKeyPair); - - internal VoteContractImplContainer.VoteContractImplStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); - - internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub => - GetProfitContractTester(BootMinerKeyPair); - - internal ElectionContractImplContainer.ElectionContractImplStub ElectionContractStub => - GetElectionContractTester(BootMinerKeyPair); - - internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub => - GetAEDPoSContractTester(BootMinerKeyPair); - - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AedPoSContractImplStub => - GetAEDPoSImplContractTester(BootMinerKeyPair); - - internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => - GetTreasuryContractTester(BootMinerKeyPair); - - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetParliamentContractTester(BootMinerKeyPair); - - internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub - TransactionFeeChargingContractStub => GetTransactionFeeChargingContractTester(BootMinerKeyPair); - - internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub MethodCallThresholdContractStub => - GetMethodCallThresholdContractTester(BootMinerKeyPair); - - internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => - GetEconomicContractTester(BootMinerKeyPair); - - internal ConfigurationImplContainer.ConfigurationImplStub ConfigurationContractStub => - GetConfigurationContractTester(BootMinerKeyPair); - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetBasicContractTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } - - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } - - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractImplTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } - - internal TokenHolderContractImplContainer.TokenHolderContractImplStub GetTokenHolderTester(ECKeyPair keyPair) - { - return GetTester(TokenHolderContractAddress, keyPair); - } - - internal TokenConverterContractImplContainer.TokenConverterContractImplStub GetTokenConverterContractTester( - ECKeyPair keyPair) - { - return GetTester(TokenConverterContractAddress, - keyPair); - } - - internal VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) - { - return GetTester(VoteContractAddress, keyPair); - } - - internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } - - internal ElectionContractImplContainer.ElectionContractImplStub GetElectionContractTester(ECKeyPair keyPair) - { - return GetTester(ElectionContractAddress, keyPair); - } - - internal AEDPoSContractContainer.AEDPoSContractStub GetAEDPoSContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } - - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSImplContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } - - internal TreasuryContractImplContainer.TreasuryContractImplStub GetTreasuryContractTester(ECKeyPair keyPair) - { - return GetTester(TreasuryContractAddress, keyPair); - } - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => + GetBasicContractTester(BootMinerKeyPair); + + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub => + GetTokenContractTester(BootMinerKeyPair); + + internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub => + GetTokenContractImplTester(BootMinerKeyPair); + + internal TokenHolderContractImplContainer.TokenHolderContractImplStub TokenHolderStub => + GetTokenHolderTester(BootMinerKeyPair); + + internal TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub => + GetTokenConverterContractTester(BootMinerKeyPair); + + internal VoteContractImplContainer.VoteContractImplStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); + + internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub => + GetProfitContractTester(BootMinerKeyPair); + + internal ElectionContractImplContainer.ElectionContractImplStub ElectionContractStub => + GetElectionContractTester(BootMinerKeyPair); + + internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub => + GetAEDPoSContractTester(BootMinerKeyPair); + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AedPoSContractImplStub => + GetAEDPoSImplContractTester(BootMinerKeyPair); + + internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => + GetTreasuryContractTester(BootMinerKeyPair); + + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetParliamentContractTester(BootMinerKeyPair); + + internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub + TransactionFeeChargingContractStub => GetTransactionFeeChargingContractTester(BootMinerKeyPair); + + internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub MethodCallThresholdContractStub => + GetMethodCallThresholdContractTester(BootMinerKeyPair); + + internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => + GetEconomicContractTester(BootMinerKeyPair); + + internal ConfigurationImplContainer.ConfigurationImplStub ConfigurationContractStub => + GetConfigurationContractTester(BootMinerKeyPair); + + protected void InitializeContracts() + { + DeployAllContracts(); + + AsyncHelper.RunSync(InitializeParliamentContract); + AsyncHelper.RunSync(InitializeTreasuryConverter); + AsyncHelper.RunSync(InitializeElection); + AsyncHelper.RunSync(InitializeEconomicContract); + AsyncHelper.RunSync(InitializeToken); + AsyncHelper.RunSync(InitializeAElfConsensus); + AsyncHelper.RunSync(InitializeTokenConverter); + AsyncHelper.RunSync(InitializeTransactionFeeChargingContract); + } + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetBasicContractTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } + + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } + + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractImplTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } + + internal TokenHolderContractImplContainer.TokenHolderContractImplStub GetTokenHolderTester(ECKeyPair keyPair) + { + return GetTester(TokenHolderContractAddress, + keyPair); + } + + internal TokenConverterContractImplContainer.TokenConverterContractImplStub GetTokenConverterContractTester( + ECKeyPair keyPair) + { + return GetTester( + TokenConverterContractAddress, + keyPair); + } + + internal VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) + { + return GetTester(VoteContractAddress, keyPair); + } + + internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } + + internal ElectionContractImplContainer.ElectionContractImplStub GetElectionContractTester(ECKeyPair keyPair) + { + return GetTester(ElectionContractAddress, keyPair); + } + + internal AEDPoSContractContainer.AEDPoSContractStub GetAEDPoSContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSImplContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + internal TreasuryContractImplContainer.TreasuryContractImplStub GetTreasuryContractTester(ECKeyPair keyPair) + { + return GetTester(TreasuryContractAddress, keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub + GetTransactionFeeChargingContractTester(ECKeyPair keyPair) + { + return GetTester( + TransactionFeeChargingContractAddress, keyPair); + } + + internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub + GetMethodCallThresholdContractTester( ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } - - internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractStub - GetTransactionFeeChargingContractTester(ECKeyPair keyPair) - { - return GetTester( - TransactionFeeChargingContractAddress, keyPair); - } - - internal MethodCallThresholdContractContainer.MethodCallThresholdContractStub - GetMethodCallThresholdContractTester( - ECKeyPair keyPair) - { - return GetTester( - MethodCallThresholdContractAddress, - keyPair); - } - - internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContractTester(ECKeyPair keyPair) - { - return GetTester(EconomicContractAddress, keyPair); - } - - internal ConfigurationImplContainer.ConfigurationImplStub GetConfigurationContractTester(ECKeyPair keyPair) - { - return GetTester(ConfigurationAddress, keyPair); - } + { + return GetTester( + MethodCallThresholdContractAddress, + keyPair); + } + internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContractTester(ECKeyPair keyPair) + { + return GetTester(EconomicContractAddress, keyPair); + } + + internal ConfigurationImplContainer.ConfigurationImplStub GetConfigurationContractTester(ECKeyPair keyPair) + { + return GetTester(ConfigurationAddress, keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestConstants.cs b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestConstants.cs index b0d0fafd1a..263197e153 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestConstants.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestConstants.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.EconomicSystem.Tests +namespace AElf.Contracts.EconomicSystem.Tests; + +public class EconomicSystemTestConstants { - public class EconomicSystemTestConstants - { - public const string NativeTokenSymbol = "ELF"; - public const string TransactionFeeChargingContractTokenSymbol = "TFCC"; - } + public const string NativeTokenSymbol = "ELF"; + public const string TransactionFeeChargingContractTokenSymbol = "TFCC"; } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestModule.cs b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestModule.cs index 6db9313db2..0cd3fd5771 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestModule.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/EconomicSystemTestModule.cs @@ -3,14 +3,13 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.EconomicSystem.Tests +namespace AElf.Contracts.EconomicSystem.Tests; + +[DependsOn(typeof(EconomicContractsTestModule))] +public class EconomicSystemTestModule : EconomicContractsTestModule { - [DependsOn(typeof(EconomicContractsTestModule))] - public class EconomicSystemTestModule : EconomicContractsTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(); - } + context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.EconomicSystem.Tests/ElectionContractConstants.cs b/test/AElf.Contracts.EconomicSystem.Tests/ElectionContractConstants.cs index fce927be53..6be459ac4a 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/ElectionContractConstants.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/ElectionContractConstants.cs @@ -1,14 +1,12 @@ -namespace AElf.Contracts.EconomicSystem.Tests +namespace AElf.Contracts.EconomicSystem.Tests; + +public static class ElectionContractConstants { - public static class ElectionContractConstants - { - public const int CitizenWelfareWeight = 15; - public const int BackupSubsidyWeight = 1; - public const int MinerRewardWeight = 4; - - public const int BasicMinerRewardWeight = 2; - public const int FlexibleRewardWeight = 1; - public const int WelcomeRewardWeight = 1; + public const int CitizenWelfareWeight = 15; + public const int BackupSubsidyWeight = 1; + public const int MinerRewardWeight = 4; - } + public const int BasicMinerRewardWeight = 2; + public const int FlexibleRewardWeight = 1; + public const int WelcomeRewardWeight = 1; } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj index e49e257aa3..cb812643ff 100644 --- a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj +++ b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj @@ -9,17 +9,17 @@ 0436 - - - - - - + + + + + + - - - + + + false Contract @@ -30,9 +30,9 @@ Contract PreserveNewest - - - + + + @@ -42,6 +42,6 @@ Protobuf\Proto\transaction_fee.proto - - + + diff --git a/test/AElf.Contracts.Election.Tests/BVT/ACS1ImplTest.cs b/test/AElf.Contracts.Election.Tests/BVT/ACS1ImplTest.cs index 3397552b8f..83fc4e8b75 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ACS1ImplTest.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ACS1ImplTest.cs @@ -1,220 +1,217 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Authority_Test() { - - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Authority_Test() - { - var newController = new AuthorityInfo - { - OwnerAddress = ElectionContractAddress, - ContractAddress = ParliamentContractAddress - }; - var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); - var proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(ElectionContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, newController); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); - } - - [Fact] - public async Task ChangeMethodFeeController_Test() + var newController = new AuthorityInfo { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(ElectionContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + OwnerAddress = ElectionContractAddress, + ContractAddress = ParliamentContractAddress + }; + var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(ElectionContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, newController); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await ElectionContractStub.ChangeMethodFeeController.SendAsync(new AuthorityInfo + const string proposalCreationMethodName = nameof(ElectionContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(ElectionContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, ContractAddress = ParliamentContractAddress }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } - - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() - { - // Invalid amount - { - var setMethodFeeRet = await ElectionContractStub.SetMethodFee.SendAsync(new MethodFees + var newMethodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - MethodName = "Test", - Fees = + ProposalReleaseThreshold = new ProposalReleaseThreshold { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = -111 - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } }); - setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); - } + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await ElectionContractStub.ChangeMethodFeeController.SendAsync(new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); - // token does not exist + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + // Invalid amount + { + var setMethodFeeRet = await ElectionContractStub.SetMethodFee.SendAsync(new MethodFees { - var setMethodFeeRet = await ElectionContractStub.SetMethodFee.SendAsync(new MethodFees + MethodName = "Test", + Fees = { - MethodName = "Test", - Fees = + new MethodFee { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = 111 - } + Symbol = "NOTEXIST", + BasicFee = -111 } - }); - setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); - } + } + }); + setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); } - [Fact] - public async Task SetMethodFee_Without_Authority_Test() + // token does not exist { - var tokenSymbol = "ELF"; - var methodName = "Test"; - var basicFee = 111; var setMethodFeeRet = await ElectionContractStub.SetMethodFee.SendAsync(new MethodFees { - MethodName = methodName, + MethodName = "Test", Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = basicFee + Symbol = "NOTEXIST", + BasicFee = 111 } } }); setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); } + } - [Fact] - public async Task SetMethodFee_Success_Test() + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + var tokenSymbol = "ELF"; + var methodName = "Test"; + var basicFee = 111; + var setMethodFeeRet = await ElectionContractStub.SetMethodFee.SendAsync(new MethodFees { - var tokenSymbol = "ELF"; - var methodName = "Test"; - var basicFee = 111; - var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); - const string proposalCreationMethodName = nameof(ElectionContractStub.SetMethodFee); - var proposalId = await CreateProposalAsync(ElectionContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new MethodFees + MethodName = methodName, + Fees = + { + new MethodFee { - MethodName = methodName, - Fees = + Symbol = tokenSymbol, + BasicFee = basicFee + } + } + }); + setMethodFeeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task SetMethodFee_Success_Test() + { + var tokenSymbol = "ELF"; + var methodName = "Test"; + var basicFee = 111; + var methodFeeController = await ElectionContractStub.GetMethodFeeController.CallAsync(new Empty()); + const string proposalCreationMethodName = nameof(ElectionContractStub.SetMethodFee); + var proposalId = await CreateProposalAsync(ElectionContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee { - new MethodFee - { - Symbol = tokenSymbol, - BasicFee = basicFee - } + Symbol = tokenSymbol, + BasicFee = basicFee } - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var getMethodFee = await ElectionContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName + } }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); - } + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var getMethodFee = await ElectionContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); + } - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; - } + return proposalId; + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index 14c0823606..1385f4d862 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -2,1254 +2,1267 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.Economic; -using AElf.Standards.ACS3; using AElf.Contracts.Economic.TestBase; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.Contracts.Vote; using AElf.Cryptography.ECDSA; +using AElf.CSharp.Core; +using AElf.CSharp.Core.Extension; +using AElf.Kernel; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -using AElf.Contracts.Parliament; -using AElf.CSharp.Core; -using AElf.CSharp.Core.Extension; -using AElf.Kernel; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests : ElectionContractTestBase { - public partial class ElectionContractTests : ElectionContractTestBase + public const int CandidatesCount = 19; + + [Fact] + public async Task ElectionContract_RegisterElectionVotingEvent_Test() { - public const int CandidatesCount = 19; + // `RegisterElectionVotingEvent` will be called during AElf Consensus Contract initialization, + // so we can check corresponding voting item directly. - [Fact] - public async Task ElectionContract_RegisterElectionVotingEvent_Test() + var electionVotingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - // `RegisterElectionVotingEvent` will be called during AElf Consensus Contract initialization, - // so we can check corresponding voting item directly. + VotingItemId = MinerElectionVotingItemId + }); + + electionVotingItem.VotingItemId.ShouldBe(MinerElectionVotingItemId); + electionVotingItem.Options.Count.ShouldBe(0); + electionVotingItem.Sponsor.ShouldBe(ElectionContractAddress); + electionVotingItem.TotalSnapshotNumber.ShouldBe(long.MaxValue); + electionVotingItem.CurrentSnapshotNumber.ShouldBe(1); + electionVotingItem.IsLockToken.ShouldBe(false); + electionVotingItem.AcceptedCurrency.ShouldBe(ElectionContractTestConstants.NativeTokenSymbol); + } - var electionVotingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = MinerElectionVotingItemId - }); + [Fact] + public async Task ElectionContract_AnnounceElection_State_Test() + { + var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); + var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + await AnnounceElectionAsync(candidatesKeyPair); + var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing - ElectionContractConstants.LockTokenForElection); + var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput + { + VotingItemId = MinerElectionVotingItemId + }); + votingItem.Options.Count.ShouldBe(1); + votingItem.Options.ShouldContain(candidatesKeyPair.PublicKey.ToHex()); + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.ContainsKey(candidatesKeyPair.PublicKey.ToHex()).ShouldBeTrue(); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) + }); + profitDetail.Details.Count.ShouldBe(1); + } - electionVotingItem.VotingItemId.ShouldBe(MinerElectionVotingItemId); - electionVotingItem.Options.Count.ShouldBe(0); - electionVotingItem.Sponsor.ShouldBe(ElectionContractAddress); - electionVotingItem.TotalSnapshotNumber.ShouldBe(long.MaxValue); - electionVotingItem.CurrentSnapshotNumber.ShouldBe(1); - electionVotingItem.IsLockToken.ShouldBe(false); - electionVotingItem.AcceptedCurrency.ShouldBe(ElectionContractTestConstants.NativeTokenSymbol); - } + /// + /// Take first 7 full node key pairs to announce election. + /// + /// Return 7 candidates key pairs. + private async Task> ElectionContract_AnnounceElection_Test() + { + var candidatesKeyPairs = ValidationDataCenterKeyPairs.Take(CandidatesCount).ToList(); + + var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey); + balanceBeforeAnnouncing.ShouldBe(ElectionContractConstants.UserInitializeTokenAmount); + + foreach (var keyPair in candidatesKeyPairs) await AnnounceElectionAsync(keyPair); + + var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey); - [Fact] - public async Task ElectionContract_AnnounceElection_State_Test() + // Check balance after announcing election. + balanceBeforeAnnouncing.ShouldBe(balanceAfterAnnouncing + ElectionContractConstants.LockTokenForElection); + + // Check changes introduced to Main Chain Miner Election voting item. + var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput + { + VotingItemId = MinerElectionVotingItemId + }); + votingItem.Options.Count.ShouldBe(CandidatesCount); + foreach (var candidateKeyPair in candidatesKeyPairs) + votingItem.Options.ShouldContain(candidateKeyPair.PublicKey.ToHex()); + + return candidatesKeyPairs; + } + + [Fact] + public async Task ElectionContract_AnnounceElectionAgain_Test() + { + await ElectionContract_QuiteElection_Test(); + + var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); + + var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + balanceBeforeAnnouncing.ShouldBe(ElectionContractConstants.UserInitializeTokenAmount); + + await AnnounceElectionAsync(candidatesKeyPair); + + var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + + // Check balance after announcing election. + balanceBeforeAnnouncing.ShouldBe(balanceAfterAnnouncing + ElectionContractConstants.LockTokenForElection); + } + + private async Task ElectionContract_QuiteElection_Test() + { + const int quitCount = 2; + + var candidates = await ElectionContract_AnnounceElection_Test(); + + // Check VotingEvent before quiting election. { - var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); - var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); - await AnnounceElectionAsync(candidatesKeyPair); - var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); - balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing - ElectionContractConstants.LockTokenForElection); var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { VotingItemId = MinerElectionVotingItemId }); - votingItem.Options.Count.ShouldBe(1); - votingItem.Options.ShouldContain(candidatesKeyPair.PublicKey.ToHex()); - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.ContainsKey(candidatesKeyPair.PublicKey.ToHex()).ShouldBeTrue(); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) - }); - profitDetail.Details.Count.ShouldBe(1); + votingItem.Options.Count.ShouldBe(candidates.Count); } - /// - /// Take first 7 full node key pairs to announce election. - /// - /// Return 7 candidates key pairs. - private async Task> ElectionContract_AnnounceElection_Test() - { - var candidatesKeyPairs = ValidationDataCenterKeyPairs.Take(CandidatesCount).ToList(); - - var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey); - balanceBeforeAnnouncing.ShouldBe(ElectionContractConstants.UserInitializeTokenAmount); + var quitCandidates = ValidationDataCenterKeyPairs.Take(quitCount).ToList(); - foreach (var keyPair in candidatesKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + var balancesBeforeQuiting = new Dictionary(); + // Record balances before quiting election. + foreach (var quitCandidate in quitCandidates) + balancesBeforeQuiting.Add(quitCandidate, await GetNativeTokenBalance(quitCandidate.PublicKey)); - var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPairs[0].PublicKey); + foreach (var keyPair in quitCandidates) await QuitElectionAsync(keyPair); - // Check balance after announcing election. - balanceBeforeAnnouncing.ShouldBe(balanceAfterAnnouncing + ElectionContractConstants.LockTokenForElection); + // Check balances after quiting election. + foreach (var quitCandidate in quitCandidates) + { + var balance = await GetNativeTokenBalance(quitCandidate.PublicKey); + balance.ShouldBe(balancesBeforeQuiting[quitCandidate] + ElectionContractConstants.LockTokenForElection); + } - // Check changes introduced to Main Chain Miner Election voting item. + // Check VotingEvent after quiting election. + { var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { VotingItemId = MinerElectionVotingItemId }); - votingItem.Options.Count.ShouldBe(CandidatesCount); - foreach (var candidateKeyPair in candidatesKeyPairs) - { - votingItem.Options.ShouldContain(candidateKeyPair.PublicKey.ToHex()); - } - - return candidatesKeyPairs; + votingItem.Options.Count.ShouldBe(candidates.Count - quitCount); } + } - [Fact] - public async Task ElectionContract_AnnounceElectionAgain_Test() + [Fact] + public async Task ElectionContract_QuiteElection_State_Test() + { + var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); + await AnnounceElectionAsync(candidatesKeyPair); + var balanceBeforeQuit = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + await QuitElectionAsync(candidatesKeyPair); + var balanceAfterQuit = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + balanceAfterQuit.ShouldBe(balanceBeforeQuit + ElectionContractConstants.LockTokenForElection); + var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - await ElectionContract_QuiteElection_Test(); - - var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); - - var balanceBeforeAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); - balanceBeforeAnnouncing.ShouldBe(ElectionContractConstants.UserInitializeTokenAmount); - - await AnnounceElectionAsync(candidatesKeyPair); - - var balanceAfterAnnouncing = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); + VotingItemId = MinerElectionVotingItemId + }); + votingItem.Options.Count.ShouldBe(0); + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.Count.ShouldBe(0); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) + }); + profitDetail.Details.Count.ShouldBe(1); + profitDetail.Details[0].EndPeriod.ShouldBe(0); + } - // Check balance after announcing election. - balanceBeforeAnnouncing.ShouldBe(balanceAfterAnnouncing + ElectionContractConstants.LockTokenForElection); - } + /// + /// TokenContract dose have not enough vote token to issue + /// + /// + [Fact] + public async Task ElectionContract_Vote_Without_Enough_VoteToken_Test() + { + var voteSymbol = "VOTE"; + var voteTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = voteSymbol + }); + var amount = voteTokenInfo.TotalSupply.Div(10).Mul(5); + var voterKeyPair = VoterKeyPairs.First(); + var issueRet = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput + { + Amount = amount, + To = Address.FromPublicKey(voterKeyPair.PublicKey) + }); + issueRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + const int lockTime = 100 * 60 * 60 * 24; + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs[0]; + var voteRet = await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), lockTime, amount); + voteRet.Status.ShouldBe(TransactionResultStatus.Mined); + var voteId = + (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { Value = voterKeyPair.PublicKey.ToHex() })).ActiveVotingRecordIds.First(); + BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); + await WithdrawVotes(voterKeyPair, voteId); + var voteBalanceInElectionContract = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = voteSymbol, + Owner = ElectionContractAddress + }); + voteBalanceInElectionContract.Balance.ShouldBe(voteTokenInfo.TotalSupply); + + voteRet = await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), lockTime * 2, amount); + voteRet.Status.ShouldBe(TransactionResultStatus.Mined); + voteBalanceInElectionContract = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = voteSymbol, + Owner = ElectionContractAddress + }); + voteBalanceInElectionContract.Balance.ShouldBe(amount); + } - private async Task ElectionContract_QuiteElection_Test() + [Fact] + public async Task ElectionContract_Vote_With_Token_Test() + { + var amount = 100; + const int lockTime = 100 * 60 * 60 * 24; + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs[0]; + var voteRet = await ElectionContractStub.Vote.SendAsync(new VoteMinerInput { - const int quitCount = 2; + CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), + Amount = amount, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), + Token = HashHelper.ComputeFrom("token A") + }); + voteRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var candidates = await ElectionContract_AnnounceElection_Test(); + /// + /// First 5 candidates will get 500 * 2 votes, next 14 candidates will get 250 * 2 votes. + /// Votes are got from 2 different voters. + /// + /// + public async Task> ElectionContract_Vote_Test() + { + const int votersCount = 2; + const long amount = 500; + const int lockTime = 100 * 60 * 60 * 24; - // Check VotingEvent before quiting election. - { - var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = MinerElectionVotingItemId - }); - votingItem.Options.Count.ShouldBe(candidates.Count); - } + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs[0]; - var quitCandidates = ValidationDataCenterKeyPairs.Take(quitCount).ToList(); + var votersKeyPairs = VoterKeyPairs.Take(votersCount).ToList(); + var voterKeyPair = votersKeyPairs[0]; + var balanceBeforeVoting = await GetNativeTokenBalance(voterKeyPair.PublicKey); + balanceBeforeVoting.ShouldBeGreaterThan(0); - var balancesBeforeQuiting = new Dictionary(); - // Record balances before quiting election. - foreach (var quitCandidate in quitCandidates) - { - balancesBeforeQuiting.Add(quitCandidate, await GetNativeTokenBalance(quitCandidate.PublicKey)); - } + await VoteToCandidates( + votersKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(), + candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, amount); - foreach (var keyPair in quitCandidates) - { - await QuitElectionAsync(keyPair); - } + await VoteToCandidates( + votersKeyPairs.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Take(candidatesKeyPairs.Count - EconomicContractsTestConstants.InitialCoreDataCenterCount) + .ToList(), + candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, amount / 2); - // Check balances after quiting election. - foreach (var quitCandidate in quitCandidates) - { - var balance = await GetNativeTokenBalance(quitCandidate.PublicKey); - balance.ShouldBe(balancesBeforeQuiting[quitCandidate] + ElectionContractConstants.LockTokenForElection); - } + var actualVotedAmount = + amount * EconomicContractsTestConstants.InitialCoreDataCenterCount + amount * + (candidatesKeyPairs.Count - EconomicContractsTestConstants.InitialCoreDataCenterCount); - // Check VotingEvent after quiting election. - { - var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = MinerElectionVotingItemId - }); - votingItem.Options.Count.ShouldBe(candidates.Count - quitCount); - } - } - - [Fact] - public async Task ElectionContract_QuiteElection_State_Test() - { - var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); - await AnnounceElectionAsync(candidatesKeyPair); - var balanceBeforeQuit = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); - await QuitElectionAsync(candidatesKeyPair); - var balanceAfterQuit = await GetNativeTokenBalance(candidatesKeyPair.PublicKey); - balanceAfterQuit.ShouldBe(balanceBeforeQuit + ElectionContractConstants.LockTokenForElection); - var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = MinerElectionVotingItemId - }); - votingItem.Options.Count.ShouldBe(0); - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.Count.ShouldBe(0); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) - }); - profitDetail.Details.Count.ShouldBe(1); - profitDetail.Details[0].EndPeriod.ShouldBe(0); + // Check ELF token balance. + { + var balance = await GetNativeTokenBalance(voterKeyPair.PublicKey); + balance.ShouldBe(balanceBeforeVoting - actualVotedAmount); } - /// - /// TokenContract dose have not enough vote token to issue - /// - /// - [Fact] - public async Task ElectionContract_Vote_Without_Enough_VoteToken_Test() + // Check VOTE token balance. { - var voteSymbol = "VOTE"; - var voteTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = voteSymbol - }); - var amount = voteTokenInfo.TotalSupply.Div(10).Mul(5); - var voterKeyPair = VoterKeyPairs.First(); - var issueRet = await EconomicContractStub.IssueNativeToken.SendAsync(new IssueNativeTokenInput - { - Amount = amount, - To = Address.FromPublicKey(voterKeyPair.PublicKey) - }); - issueRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - const int lockTime = 100 * 60 * 60 * 24; - var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); - var candidateKeyPair = candidatesKeyPairs[0]; - var voteRet = await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), lockTime, amount); - voteRet.Status.ShouldBe(TransactionResultStatus.Mined); - var voteId = - (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue - {Value = voterKeyPair.PublicKey.ToHex()})).ActiveVotingRecordIds.First(); - BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); - await WithdrawVotes(voterKeyPair, voteId); - var voteBalanceInElectionContract = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = voteSymbol, - Owner = ElectionContractAddress - }); - voteBalanceInElectionContract.Balance.ShouldBe(voteTokenInfo.TotalSupply); - - voteRet = await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), lockTime * 2, amount); - voteRet.Status.ShouldBe(TransactionResultStatus.Mined); - voteBalanceInElectionContract = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = voteSymbol, - Owner = ElectionContractAddress - }); - voteBalanceInElectionContract.Balance.ShouldBe(amount); + var balance = await GetVoteTokenBalance(voterKeyPair.PublicKey); + balance.ShouldBe(actualVotedAmount); } - - [Fact] - public async Task ElectionContract_Vote_With_Token_Test() - { - var amount = 100; - const int lockTime = 100 * 60 * 60 * 24; - var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); - var candidateKeyPair = candidatesKeyPairs[0]; - var voteRet = await ElectionContractStub.Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), - Amount = amount, - EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), - Token = HashHelper.ComputeFrom("token A") - }); - voteRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - /// - /// First 5 candidates will get 500 * 2 votes, next 14 candidates will get 250 * 2 votes. - /// Votes are got from 2 different voters. - /// - /// - public async Task> ElectionContract_Vote_Test() - { - const int votersCount = 2; - const long amount = 500; - const int lockTime = 100 * 60 * 60 * 24; - - var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); - var candidateKeyPair = candidatesKeyPairs[0]; - - var votersKeyPairs = VoterKeyPairs.Take(votersCount).ToList(); - var voterKeyPair = votersKeyPairs[0]; - var balanceBeforeVoting = await GetNativeTokenBalance(voterKeyPair.PublicKey); - balanceBeforeVoting.ShouldBeGreaterThan(0); - - await VoteToCandidates( - votersKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(), - candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, amount); - - await VoteToCandidates( - votersKeyPairs.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Take(candidatesKeyPairs.Count - EconomicContractsTestConstants.InitialCoreDataCenterCount) - .ToList(), - candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, amount / 2); - - var actualVotedAmount = - amount * EconomicContractsTestConstants.InitialCoreDataCenterCount + amount * - (candidatesKeyPairs.Count - EconomicContractsTestConstants.InitialCoreDataCenterCount); - - // Check ELF token balance. - { - var balance = await GetNativeTokenBalance(voterKeyPair.PublicKey); - balance.ShouldBe(balanceBeforeVoting - actualVotedAmount); - } - // Check VOTE token balance. + // Check voter's Votes information. + { + var voterVotes = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue { - var balance = await GetVoteTokenBalance(voterKeyPair.PublicKey); - balance.ShouldBe(actualVotedAmount); - } + Value = voterKeyPair.PublicKey.ToHex() + }); + voterVotes.Pubkey.ShouldBe(ByteString.CopyFrom(voterKeyPair.PublicKey)); + voterVotes.ActiveVotingRecordIds.Count.ShouldBe(19); + voterVotes.AllVotedVotesAmount.ShouldBe(actualVotedAmount); + voterVotes.ActiveVotedVotesAmount.ShouldBe(actualVotedAmount); + voterVotes.ActiveVotingRecords.Count.ShouldBe(0); // Not filled. + + var voterVotesWithRecords = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync( + new StringValue + { + Value = voterKeyPair.PublicKey.ToHex() + }); + voterVotesWithRecords.ActiveVotingRecords.Count.ShouldBe(candidatesKeyPairs.Count); - // Check voter's Votes information. - { - var voterVotes = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + var voterVotesWithAllRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync( + new StringValue { Value = voterKeyPair.PublicKey.ToHex() }); - voterVotes.Pubkey.ShouldBe(ByteString.CopyFrom(voterKeyPair.PublicKey)); - voterVotes.ActiveVotingRecordIds.Count.ShouldBe(19); - voterVotes.AllVotedVotesAmount.ShouldBe(actualVotedAmount); - voterVotes.ActiveVotedVotesAmount.ShouldBe(actualVotedAmount); - voterVotes.ActiveVotingRecords.Count.ShouldBe(0); // Not filled. - - var voterVotesWithRecords = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync( - new StringValue - { - Value = voterKeyPair.PublicKey.ToHex() - }); - voterVotesWithRecords.ActiveVotingRecords.Count.ShouldBe(candidatesKeyPairs.Count); + voterVotesWithAllRecords.WithdrawnVotesRecords.Count.ShouldBe(0); + } - var voterVotesWithAllRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync( - new StringValue - { - Value = voterKeyPair.PublicKey.ToHex() - }); - voterVotesWithAllRecords.WithdrawnVotesRecords.Count.ShouldBe(0); - } + // Check candidate's Votes information. + { + //not exist + var input = new StringValue + { + Value = "FakePubkey" + }; + var candidateVotesWithRecords = await ElectionContractStub.GetCandidateVoteWithRecords.CallAsync(input); + candidateVotesWithRecords.ShouldBe(new CandidateVote()); - // Check candidate's Votes information. + var candidateVotes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue { - //not exist - var input = new StringValue - { - Value = "FakePubkey" - }; - var candidateVotesWithRecords = await ElectionContractStub.GetCandidateVoteWithRecords.CallAsync(input); - candidateVotesWithRecords.ShouldBe(new CandidateVote()); - - var candidateVotes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue + Value = candidateKeyPair.PublicKey.ToHex() + }); + candidateVotes.Pubkey.ShouldBe(ByteString.CopyFrom(candidateKeyPair.PublicKey)); + candidateVotes.AllObtainedVotedVotesAmount.ShouldBe(amount * 2); + candidateVotes.ObtainedActiveVotedVotesAmount.ShouldBe(amount * 2); + candidateVotes.ObtainedWithdrawnVotesRecords.Count.ShouldBe(0); // Not filled. + + candidateVotesWithRecords = await ElectionContractStub.GetCandidateVoteWithRecords.CallAsync( + new StringValue { Value = candidateKeyPair.PublicKey.ToHex() }); - candidateVotes.Pubkey.ShouldBe(ByteString.CopyFrom(candidateKeyPair.PublicKey)); - candidateVotes.AllObtainedVotedVotesAmount.ShouldBe(amount * 2); - candidateVotes.ObtainedActiveVotedVotesAmount.ShouldBe(amount * 2); - candidateVotes.ObtainedWithdrawnVotesRecords.Count.ShouldBe(0); // Not filled. + candidateVotesWithRecords.ObtainedActiveVotingRecords.Count.ShouldBe(votersCount); - candidateVotesWithRecords = await ElectionContractStub.GetCandidateVoteWithRecords.CallAsync( - new StringValue - { - Value = candidateKeyPair.PublicKey.ToHex() - }); - candidateVotesWithRecords.ObtainedActiveVotingRecords.Count.ShouldBe(votersCount); - - var voterVotesWithAllRecords = await ElectionContractStub.GetCandidateVoteWithAllRecords.CallAsync( - new StringValue - { - Value = candidateKeyPair.PublicKey.ToHex() - }); - voterVotesWithAllRecords.ObtainedWithdrawnVotesRecords.Count.ShouldBe(0); - } - - // Check voter's profit detail. - { - var welfareHash = ProfitItemsIds[ProfitType.CitizenWelfare]; - var details = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + var voterVotesWithAllRecords = await ElectionContractStub.GetCandidateVoteWithAllRecords.CallAsync( + new StringValue { - SchemeId = welfareHash, - Beneficiary = Address.FromPublicKey(votersKeyPairs.First().PublicKey) + Value = candidateKeyPair.PublicKey.ToHex() }); - details.Details.Count.ShouldBe(candidatesKeyPairs.Count); - } - - return candidatesKeyPairs; + voterVotesWithAllRecords.ObtainedWithdrawnVotesRecords.Count.ShouldBe(0); } - [Fact] - public async Task ElectionContract_ChangeVotingTarget_With_Invalid_Target_Test() - { - const long amount = 500; - const int lockTime = 100 * 60 * 60 * 24; - var validCandidate = ValidationDataCenterKeyPairs.First(); - var validCandidatePublicKeyStr = validCandidate.PublicKey.ToHex(); - var invalidCandidate = ValidationDataCenterKeyPairs.Last(); - var invalidCandidatePublicKeyStr = invalidCandidate.PublicKey.ToHex(); - await AnnounceElectionAsync(validCandidate); - var voterKeyPair = VoterKeyPairs[0]; - var electionStub = GetElectionContractTester(voterKeyPair); - var voteResult = await VoteToCandidate(voterKeyPair, validCandidate.PublicKey.ToHex(), lockTime, amount); - voteResult.Status.ShouldBe(TransactionResultStatus.Mined); - var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue - { - Value = validCandidatePublicKeyStr - }); - candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(amount); - var voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; - - // change to a candidate that does not exist - var changeVoteOptionRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - VoteId = voteId, - CandidatePubkey = invalidCandidatePublicKeyStr, - }); - changeVoteOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - changeVoteOptionRet.TransactionResult.Error.ShouldContain("Candidate not found"); - - // change to a candidate that quits election - await AnnounceElectionAsync(invalidCandidate); - await QuitElectionAsync(invalidCandidate); - changeVoteOptionRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + // Check voter's profit detail. + { + var welfareHash = ProfitItemsIds[ProfitType.CitizenWelfare]; + var details = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - VoteId = voteId, - CandidatePubkey = invalidCandidatePublicKeyStr, + SchemeId = welfareHash, + Beneficiary = Address.FromPublicKey(votersKeyPairs.First().PublicKey) }); - changeVoteOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - changeVoteOptionRet.TransactionResult.Error.ShouldContain("Candidate quited election"); - } - - [Fact] - public async Task ElectionContract_Vote_DataCenter_Amount_Test() - { - const long amount = 500; - const int lockTime = 100 * 60 * 60 * 24; - - var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); - var candidateKeyPair = candidatesKeyPairs.First(); - var voterKeyPair = VoterKeyPairs.First(); - var candidateStringKey = candidateKeyPair.PublicKey.ToHex(); - var firstVoteRet = await VoteToCandidate(voterKeyPair,candidateStringKey, lockTime, amount); - firstVoteRet.Status.ShouldBe(TransactionResultStatus.Mined); - var dataCenter = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenter.DataCenters.ContainsKey(candidateStringKey).ShouldBeTrue(); - dataCenter.DataCenters[candidateStringKey].ShouldBe(amount); - var secondVoteRet = await VoteToCandidate(voterKeyPair,candidateStringKey, lockTime, amount); - secondVoteRet.Status.ShouldBe(TransactionResultStatus.Mined); - dataCenter = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenter.DataCenters[candidateStringKey].ShouldBe(amount * 2); + details.Details.Count.ShouldBe(candidatesKeyPairs.Count); } - - [Fact] - public async Task ElectionContract_ChangeVotingTarget() - { - var candidatesKeyPairs = await ElectionContract_Vote_Test(); - var voterKeyPair = VoterKeyPairs[0]; - - var electionStub = GetElectionContractTester(voterKeyPair); - var electorVote = await electionStub.GetElectorVoteWithRecords.CallAsync(new StringValue - { - Value = voterKeyPair.PublicKey.ToHex() - }); + return candidatesKeyPairs; + } - var voteInformation = electorVote.ActiveVotingRecords[0]; + [Fact] + public async Task ElectionContract_ChangeVotingTarget_With_Invalid_Target_Test() + { + const long amount = 500; + const int lockTime = 100 * 60 * 60 * 24; + var validCandidate = ValidationDataCenterKeyPairs.First(); + var validCandidatePublicKeyStr = validCandidate.PublicKey.ToHex(); + var invalidCandidate = ValidationDataCenterKeyPairs.Last(); + var invalidCandidatePublicKeyStr = invalidCandidate.PublicKey.ToHex(); + await AnnounceElectionAsync(validCandidate); + var voterKeyPair = VoterKeyPairs[0]; + var electionStub = GetElectionContractTester(voterKeyPair); + var voteResult = await VoteToCandidate(voterKeyPair, validCandidate.PublicKey.ToHex(), lockTime, amount); + voteResult.Status.ShouldBe(TransactionResultStatus.Mined); + var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue + { + Value = validCandidatePublicKeyStr + }); + candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(amount); + var voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; + + // change to a candidate that does not exist + var changeVoteOptionRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + { + VoteId = voteId, + CandidatePubkey = invalidCandidatePublicKeyStr + }); + changeVoteOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + changeVoteOptionRet.TransactionResult.Error.ShouldContain("Candidate not found"); + + // change to a candidate that quits election + await AnnounceElectionAsync(invalidCandidate); + await QuitElectionAsync(invalidCandidate); + changeVoteOptionRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + { + VoteId = voteId, + CandidatePubkey = invalidCandidatePublicKeyStr + }); + changeVoteOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + changeVoteOptionRet.TransactionResult.Error.ShouldContain("Candidate quited election"); + } - var oldTarget = voteInformation.Candidate; - var newTarget = candidatesKeyPairs.Last().PublicKey.ToHex(); - Hash voteId; + [Fact] + public async Task ElectionContract_Vote_DataCenter_Amount_Test() + { + const long amount = 500; + const int lockTime = 100 * 60 * 60 * 24; + + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs.First(); + var voterKeyPair = VoterKeyPairs.First(); + var candidateStringKey = candidateKeyPair.PublicKey.ToHex(); + var firstVoteRet = await VoteToCandidate(voterKeyPair, candidateStringKey, lockTime, amount); + firstVoteRet.Status.ShouldBe(TransactionResultStatus.Mined); + var dataCenter = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenter.DataCenters.ContainsKey(candidateStringKey).ShouldBeTrue(); + dataCenter.DataCenters[candidateStringKey].ShouldBe(amount); + var secondVoteRet = await VoteToCandidate(voterKeyPair, candidateStringKey, lockTime, amount); + secondVoteRet.Status.ShouldBe(TransactionResultStatus.Mined); + dataCenter = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenter.DataCenters[candidateStringKey].ShouldBe(amount * 2); + } - // Check old target - { - var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue - { - Value = oldTarget - }); - candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(2); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1000); - voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; - } + [Fact] + public async Task ElectionContract_ChangeVotingTarget() + { + var candidatesKeyPairs = await ElectionContract_Vote_Test(); + var voterKeyPair = VoterKeyPairs[0]; - // Check new target - { - var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue - { - Value = newTarget - }); - candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(2); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1000); - } + var electionStub = GetElectionContractTester(voterKeyPair); - var transactionResult = (await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - CandidatePubkey = newTarget, - VoteId = voteId - })).TransactionResult; + var electorVote = await electionStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = voterKeyPair.PublicKey.ToHex() + }); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var voteInformation = electorVote.ActiveVotingRecords[0]; - // Check old target - { - var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue - { - Value = oldTarget - }); - candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(500); - } + var oldTarget = voteInformation.Candidate; + var newTarget = candidatesKeyPairs.Last().PublicKey.ToHex(); + Hash voteId; - // Check new target + // Check old target + { + var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue { - var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue - { - Value = newTarget - }); - candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(3); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1500); - } + Value = oldTarget + }); + candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(2); + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1000); + voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; } - [Fact] - public async Task ElectionContract_ChangeVoting_To_NewTarget() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var lockTime = 120 * 60 * 60 * 24; - var candidateKeyPairs = ValidationDataCenterKeyPairs.Take(2).ToList(); - var firstCandidate = candidateKeyPairs[0]; - var secondCandidate = candidateKeyPairs[1]; - await AnnounceElectionAsync(firstCandidate); - await AnnounceElectionAsync(secondCandidate); - await VoteToCandidate(voter,firstCandidate.PublicKey.ToHex(), lockTime, voteAmount); - var electionStub = GetElectionContractTester(voter); - var beforeChangeVote = await electionStub.GetCandidateVote.CallAsync(new StringValue + // Check new target + { + var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue { - Value = secondCandidate.PublicKey.ToHex() + Value = newTarget }); - beforeChangeVote.ObtainedActiveVotingRecords.Count.ShouldBe(0); + candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(2); + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1000); + } + + var transactionResult = (await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + { + CandidatePubkey = newTarget, + VoteId = voteId + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check old target + { var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue { - Value = firstCandidate.PublicKey.ToHex() + Value = oldTarget }); candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); - candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(voteAmount); - var voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; - var changeRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - CandidatePubkey = secondCandidate.PublicKey.ToHex(), - VoteId = voteId - }); - changeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var afterChangeVote = await electionStub.GetCandidateVote.CallAsync(new StringValue + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(500); + } + + // Check new target + { + var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue { - Value = secondCandidate.PublicKey.ToHex() + Value = newTarget }); - afterChangeVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); - afterChangeVote.ObtainedActiveVotedVotesAmount.ShouldBe(voteAmount); + candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(3); + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(1500); } + } - [Fact] - public async Task ElectionContract_Withdraw_Test() + [Fact] + public async Task ElectionContract_ChangeVoting_To_NewTarget() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var lockTime = 120 * 60 * 60 * 24; + var candidateKeyPairs = ValidationDataCenterKeyPairs.Take(2).ToList(); + var firstCandidate = candidateKeyPairs[0]; + var secondCandidate = candidateKeyPairs[1]; + await AnnounceElectionAsync(firstCandidate); + await AnnounceElectionAsync(secondCandidate); + await VoteToCandidate(voter, firstCandidate.PublicKey.ToHex(), lockTime, voteAmount); + var electionStub = GetElectionContractTester(voter); + var beforeChangeVote = await electionStub.GetCandidateVote.CallAsync(new StringValue + { + Value = secondCandidate.PublicKey.ToHex() + }); + beforeChangeVote.ObtainedActiveVotingRecords.Count.ShouldBe(0); + var candidateVote = await electionStub.GetCandidateVote.CallAsync(new StringValue + { + Value = firstCandidate.PublicKey.ToHex() + }); + candidateVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); + candidateVote.ObtainedActiveVotedVotesAmount.ShouldBe(voteAmount); + var voteId = candidateVote.ObtainedActiveVotingRecordIds[0]; + var changeRet = await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + { + CandidatePubkey = secondCandidate.PublicKey.ToHex(), + VoteId = voteId + }); + changeRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var afterChangeVote = await electionStub.GetCandidateVote.CallAsync(new StringValue { - const int amount = 1000; - const int lockTime = 120 * 60 * 60 * 24; + Value = secondCandidate.PublicKey.ToHex() + }); + afterChangeVote.ObtainedActiveVotingRecordIds.Count.ShouldBe(1); + afterChangeVote.ObtainedActiveVotedVotesAmount.ShouldBe(voteAmount); + } - var candidateKeyPair = ValidationDataCenterKeyPairs[0]; - await AnnounceElectionAsync(candidateKeyPair); + [Fact] + public async Task ElectionContract_Withdraw_Test() + { + const int amount = 1000; + const int lockTime = 120 * 60 * 60 * 24; - var voterKeyPair = VoterKeyPairs[0]; - var candidateStringKey = candidateKeyPair.PublicKey.ToHex(); - // Vote - var transactionResult = - await VoteToCandidate(voterKeyPair, candidateStringKey, lockTime, amount); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var candidateKeyPair = ValidationDataCenterKeyPairs[0]; + await AnnounceElectionAsync(candidateKeyPair); - var voteId = - (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue - {Value = voterKeyPair.PublicKey.ToHex()})).ActiveVotingRecordIds.First(); + var voterKeyPair = VoterKeyPairs[0]; + var candidateStringKey = candidateKeyPair.PublicKey.ToHex(); + // Vote + var transactionResult = + await VoteToCandidate(voterKeyPair, candidateStringKey, lockTime, amount); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - voteId.ShouldBe(Hash.Parser.ParseFrom(transactionResult.ReturnValue)); - var candidateInfoBeforeWithdraw = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue - { - Value = candidateStringKey - }); - await NextTerm(InitialCoreDataCenterKeyPairs[0]); + var voteId = + (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { Value = voterKeyPair.PublicKey.ToHex() })).ActiveVotingRecordIds.First(); - BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); + voteId.ShouldBe(Hash.Parser.ParseFrom(transactionResult.ReturnValue)); + var candidateInfoBeforeWithdraw = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue + { + Value = candidateStringKey + }); + await NextTerm(InitialCoreDataCenterKeyPairs[0]); - - // Withdraw - { - var executionResult = await WithdrawVotes(voterKeyPair, voteId); - executionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - var candidateInfoAfterWithdraw = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue - { - Value = candidateStringKey - }); - candidateInfoBeforeWithdraw.AllObtainedVotedVotesAmount.ShouldBe(candidateInfoAfterWithdraw.AllObtainedVotedVotesAmount); - candidateInfoBeforeWithdraw.ObtainedActiveVotedVotesAmount.Sub(candidateInfoAfterWithdraw.ObtainedActiveVotedVotesAmount).ShouldBe(amount); - - candidateInfoBeforeWithdraw.ObtainedActiveVotingRecordIds.Contains(voteId).ShouldBeTrue(); - candidateInfoAfterWithdraw.ObtainedActiveVotingRecordIds.Contains(voteId).ShouldBeFalse(); - candidateInfoAfterWithdraw.ObtainedWithdrawnVotingRecordIds.Contains(voteId).ShouldBeTrue(); - - //check candidate records - { - var candidateVote = await ElectionContractStub.GetCandidateVoteWithAllRecords.CallAsync(new StringValue - { - Value = candidateStringKey - }); - candidateVote.ObtainedWithdrawnVotesRecords.Select(o=>o.VoteId).ShouldContain(voteId); - } + BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); - // Profit - var voter = GetProfitContractTester(voterKeyPair); - var claimResult = await voter.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], - }); - claimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Check VOTE token balance. - { - var balance = await GetVoteTokenBalance(voterKeyPair.PublicKey); - balance.ShouldBe(0); - } + // Withdraw + { + var executionResult = await WithdrawVotes(voterKeyPair, voteId); + executionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - [Fact] - public async Task ElectionContract_GetCandidates_Test() + var candidateInfoAfterWithdraw = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue + { + Value = candidateStringKey + }); + candidateInfoBeforeWithdraw.AllObtainedVotedVotesAmount.ShouldBe(candidateInfoAfterWithdraw + .AllObtainedVotedVotesAmount); + candidateInfoBeforeWithdraw.ObtainedActiveVotedVotesAmount + .Sub(candidateInfoAfterWithdraw.ObtainedActiveVotedVotesAmount).ShouldBe(amount); + + candidateInfoBeforeWithdraw.ObtainedActiveVotingRecordIds.Contains(voteId).ShouldBeTrue(); + candidateInfoAfterWithdraw.ObtainedActiveVotingRecordIds.Contains(voteId).ShouldBeFalse(); + candidateInfoAfterWithdraw.ObtainedWithdrawnVotingRecordIds.Contains(voteId).ShouldBeTrue(); + + //check candidate records { - var announcedFullNodesKeyPairs = await ElectionContract_AnnounceElection_Test(); - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - announcedFullNodesKeyPairs.Count.ShouldBe(candidates.Value.Count); - foreach (var keyPair in announcedFullNodesKeyPairs) + var candidateVote = await ElectionContractStub.GetCandidateVoteWithAllRecords.CallAsync(new StringValue { - candidates.Value.ShouldContain(ByteString.CopyFrom(keyPair.PublicKey)); - } + Value = candidateStringKey + }); + candidateVote.ObtainedWithdrawnVotesRecords.Select(o => o.VoteId).ShouldContain(voteId); } - [Fact] - public async Task ElectionContract_GetCandidateInformation_Test() + // Profit + var voter = GetProfitContractTester(voterKeyPair); + var claimResult = await voter.ClaimProfits.SendAsync(new ClaimProfitsInput { - const int roundCount = 5; + SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare] + }); + claimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var minerKeyPair = ValidationDataCenterKeyPairs[0]; + // Check VOTE token balance. + { + var balance = await GetVoteTokenBalance(voterKeyPair.PublicKey); + balance.ShouldBe(0); + } + } - await ElectionContract_GetVictories_ValidCandidatesEnough_Test(); + [Fact] + public async Task ElectionContract_GetCandidates_Test() + { + var announcedFullNodesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + announcedFullNodesKeyPairs.Count.ShouldBe(candidates.Value.Count); + foreach (var keyPair in announcedFullNodesKeyPairs) + candidates.Value.ShouldContain(ByteString.CopyFrom(keyPair.PublicKey)); + } - await ProduceBlocks(BootMinerKeyPair, 1, true); + [Fact] + public async Task ElectionContract_GetCandidateInformation_Test() + { + const int roundCount = 5; - await ProduceBlocks(minerKeyPair, roundCount, true); + var minerKeyPair = ValidationDataCenterKeyPairs[0]; - var information = await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue - { - Value = minerKeyPair.PublicKey.ToHex() - }); + await ElectionContract_GetVictories_ValidCandidatesEnough_Test(); - information.Pubkey.ShouldBe(minerKeyPair.PublicKey.ToHex()); - } + await ProduceBlocks(BootMinerKeyPair, 1, true); + + await ProduceBlocks(minerKeyPair, roundCount, true); - [Fact] - public async Task ConsensusContract_GetPreviousMinerList() + var information = await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue { - await ElectionContract_GetVictories_ValidCandidatesEnough_Test(); - await ProduceBlocks(BootMinerKeyPair, 1, true); - var previousMiners = await AEDPoSContractStub.GetPreviousMinerList.CallAsync(new Empty()); - var previousMinersPubkey = previousMiners.Pubkeys.Select(o => o.ToHex()).OrderBy(o=>o).ToList(); - var initialMinersPubkey = InitialCoreDataCenterKeyPairs.Select(o => o.PublicKey.ToHex()).OrderBy(o=>o).ToList(); - previousMinersPubkey.ShouldBe(initialMinersPubkey); - } + Value = minerKeyPair.PublicKey.ToHex() + }); + + information.Pubkey.ShouldBe(minerKeyPair.PublicKey.ToHex()); + } + + [Fact] + public async Task ConsensusContract_GetPreviousMinerList() + { + await ElectionContract_GetVictories_ValidCandidatesEnough_Test(); + await ProduceBlocks(BootMinerKeyPair, 1, true); + var previousMiners = await AEDPoSContractStub.GetPreviousMinerList.CallAsync(new Empty()); + var previousMinersPubkey = previousMiners.Pubkeys.Select(o => o.ToHex()).OrderBy(o => o).ToList(); + var initialMinersPubkey = + InitialCoreDataCenterKeyPairs.Select(o => o.PublicKey.ToHex()).OrderBy(o => o).ToList(); + previousMinersPubkey.ShouldBe(initialMinersPubkey); + } - [Fact] - public async Task Election_VoteWeightInterestSetting_With_Invalid_Input_Test() + [Fact] + public async Task Election_VoteWeightInterestSetting_With_Invalid_Input_Test() + { + // argument <= 0 { - // argument <= 0 - { - var newSetting = new VoteWeightInterestList - { - VoteWeightInterestInfos = - { - new VoteWeightInterest - { - Capital = 0, - Interest = 4, - Day = 0 - } - } - }; - var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); - settingRet.Status.ShouldBe(TransactionResultStatus.Failed); - settingRet.Error.ShouldContain("invalid input"); - } - - // interest count == 0 - { - var newSetting = new VoteWeightInterestList(); - var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); - settingRet.Status.ShouldBe(TransactionResultStatus.Failed); - settingRet.Error.ShouldContain("invalid input"); - } - - // repeat day + var newSetting = new VoteWeightInterestList { - var newSetting = new VoteWeightInterestList + VoteWeightInterestInfos = { - VoteWeightInterestInfos = + new VoteWeightInterest { - new VoteWeightInterest - { - Capital = 1, - Interest = 2, - Day = 3 - }, - new VoteWeightInterest - { - Capital = 1, - Interest = 2, - Day = 3 - } + Capital = 0, + Interest = 4, + Day = 0 } - }; - var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); - settingRet.Status.ShouldBe(TransactionResultStatus.Failed); - settingRet.Error.ShouldContain("repeat day"); - } - } - - [Fact] - public async Task Election_VoteWeightInterestSetting_Without_Authority_Test() - { - var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( - new Empty()); - defaultSetting.VoteWeightInterestInfos.Count.ShouldBe(3); - defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; - defaultSetting.VoteWeightInterestInfos[0].Day = 50; - - var setWithoutAuthRet = await ElectionContractStub.SetVoteWeightInterest.SendAsync(defaultSetting); - setWithoutAuthRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setWithoutAuthRet.TransactionResult.Error.ShouldContain("No permission."); + } + }; + var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, + ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); + settingRet.Status.ShouldBe(TransactionResultStatus.Failed); + settingRet.Error.ShouldContain("invalid input"); } - [Fact] - public async Task Election_VoteWeightInterestSetting_Test() - { - var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( - new Empty()); - defaultSetting.VoteWeightInterestInfos.Count.ShouldBe(3); - defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; - defaultSetting.VoteWeightInterestInfos[0].Day = 50; - - await ExecuteProposalForParliamentTransaction(ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightInterest), defaultSetting); - - defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( - new Empty()); - defaultSetting.VoteWeightInterestInfos[0].Capital.ShouldBe(13200); - defaultSetting.VoteWeightInterestInfos[0].Day.ShouldBe(50); + // interest count == 0 + { + var newSetting = new VoteWeightInterestList(); + var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, + ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); + settingRet.Status.ShouldBe(TransactionResultStatus.Failed); + settingRet.Error.ShouldContain("invalid input"); } - [Fact] - public async Task Election_ChangeVoteWeightInterestController_Without_Authority_Test() + // repeat day { - var newAuthority = new AuthorityInfo + var newSetting = new VoteWeightInterestList { - OwnerAddress = new Address(), - ContractAddress = ParliamentContractAddress + VoteWeightInterestInfos = + { + new VoteWeightInterest + { + Capital = 1, + Interest = 2, + Day = 3 + }, + new VoteWeightInterest + { + Capital = 1, + Interest = 2, + Day = 3 + } + } }; - var changeControllerRet = - await ElectionContractStub.ChangeVoteWeightInterestController.SendAsync(newAuthority); - changeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - changeControllerRet.TransactionResult.Error.ShouldContain("No Permission"); + var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, + ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightInterest), newSetting); + settingRet.Status.ShouldBe(TransactionResultStatus.Failed); + settingRet.Error.ShouldContain("repeat day"); } - - [Fact] - public async Task Election_ChangeVoteWeightInterestController_With_Invalid_Input_Test() + } + + [Fact] + public async Task Election_VoteWeightInterestSetting_Without_Authority_Test() + { + var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( + new Empty()); + defaultSetting.VoteWeightInterestInfos.Count.ShouldBe(3); + defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; + defaultSetting.VoteWeightInterestInfos[0].Day = 50; + + var setWithoutAuthRet = await ElectionContractStub.SetVoteWeightInterest.SendAsync(defaultSetting); + setWithoutAuthRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setWithoutAuthRet.TransactionResult.Error.ShouldContain("No permission."); + } + + [Fact] + public async Task Election_VoteWeightInterestSetting_Test() + { + var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( + new Empty()); + defaultSetting.VoteWeightInterestInfos.Count.ShouldBe(3); + defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; + defaultSetting.VoteWeightInterestInfos[0].Day = 50; + + await ExecuteProposalForParliamentTransaction(ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightInterest), defaultSetting); + + defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( + new Empty()); + defaultSetting.VoteWeightInterestInfos[0].Capital.ShouldBe(13200); + defaultSetting.VoteWeightInterestInfos[0].Day.ShouldBe(50); + } + + [Fact] + public async Task Election_ChangeVoteWeightInterestController_Without_Authority_Test() + { + var newAuthority = new AuthorityInfo { - var newAuthority = new AuthorityInfo - { - OwnerAddress = TokenHolderContractAddress, - ContractAddress = ParliamentContractAddress - }; - var changeControllerRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, ElectionContractAddress, - nameof(ElectionContractStub.ChangeVoteWeightInterestController), newAuthority); - changeControllerRet.Status.ShouldBe(TransactionResultStatus.Failed); - changeControllerRet.Error.ShouldContain("Invalid authority input."); - } + OwnerAddress = new Address(), + ContractAddress = ParliamentContractAddress + }; + var changeControllerRet = + await ElectionContractStub.ChangeVoteWeightInterestController.SendAsync(newAuthority); + changeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + changeControllerRet.TransactionResult.Error.ShouldContain("No Permission"); + } - [Fact] - public async Task Election_ChangeVoteWeightInterestController_Test() + [Fact] + public async Task Election_ChangeVoteWeightInterestController_With_Invalid_Input_Test() + { + var newAuthority = new AuthorityInfo { - var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( - new Empty()); - defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; - var newParliament = new CreateOrganizationInput - { - ProposerAuthorityRequired = false, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 1, - MaximalRejectionThreshold = 1, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = false - }; - var buildNewParliamentRet = - (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; - buildNewParliamentRet.Status.ShouldBe(TransactionResultStatus.Mined); - var newParliamentAddress = new Address(); - newParliamentAddress.MergeFrom(buildNewParliamentRet.ReturnValue); - var newAuthority = new AuthorityInfo - { - OwnerAddress = newParliamentAddress, - ContractAddress = ParliamentContractAddress - }; - await ExecuteProposalForParliamentTransaction(ElectionContractAddress, - nameof(ElectionContractStub.ChangeVoteWeightInterestController), newAuthority); + OwnerAddress = TokenHolderContractAddress, + ContractAddress = ParliamentContractAddress + }; + var changeControllerRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, + ElectionContractAddress, + nameof(ElectionContractStub.ChangeVoteWeightInterestController), newAuthority); + changeControllerRet.Status.ShouldBe(TransactionResultStatus.Failed); + changeControllerRet.Error.ShouldContain("Invalid authority input."); + } - var getNewAuthority = await ElectionContractStub.GetVoteWeightInterestController.CallAsync(new Empty()); - getNewAuthority.ContractAddress.ShouldBe(newAuthority.ContractAddress); - getNewAuthority.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); - } - - [Fact] - public async Task Election_SetVoteWeightProportion_Without_Authority_Test() + [Fact] + public async Task Election_ChangeVoteWeightInterestController_Test() + { + var defaultSetting = await ElectionContractStub.GetVoteWeightSetting.CallAsync( + new Empty()); + defaultSetting.VoteWeightInterestInfos[0].Capital = 13200; + var newParliament = new CreateOrganizationInput { - var newSetting = new VoteWeightProportion - { - TimeProportion = 3, - AmountProportion = 3 - }; - var settingRet = await ElectionContractStub.SetVoteWeightProportion.SendAsync(newSetting); - settingRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - settingRet.TransactionResult.Error.ShouldContain("No permission"); - } - - [Fact] - public async Task Election_SetVoteWeightProportion_With_Invalid_Input_Test() + ProposerAuthorityRequired = false, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 1, + MaximalRejectionThreshold = 1, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = false + }; + var buildNewParliamentRet = + (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; + buildNewParliamentRet.Status.ShouldBe(TransactionResultStatus.Mined); + var newParliamentAddress = new Address(); + newParliamentAddress.MergeFrom(buildNewParliamentRet.ReturnValue); + var newAuthority = new AuthorityInfo { - var newSetting = new VoteWeightProportion - { - TimeProportion = 0, - AmountProportion = 3 - }; - var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightProportion), newSetting); - settingRet.Status.ShouldBe(TransactionResultStatus.Failed); - settingRet.Error.ShouldContain("invalid input"); - } - - [Fact] - public async Task Election_SetVoteWeightProportion_Test() - { - var defaultSetting = await ElectionContractStub.GetVoteWeightProportion.CallAsync( - new Empty()); - defaultSetting.TimeProportion.ShouldBe(2); - defaultSetting.AmountProportion.ShouldBe(1); - defaultSetting = new VoteWeightProportion - { - TimeProportion = 3, - AmountProportion = 3 - }; - await ExecuteProposalForParliamentTransaction(ElectionContractAddress, - nameof(ElectionContractStub.SetVoteWeightProportion), defaultSetting); - - defaultSetting = await ElectionContractStub.GetVoteWeightProportion.CallAsync( - new Empty()); - defaultSetting.TimeProportion.ShouldBe(3); - defaultSetting.AmountProportion.ShouldBe(3); + OwnerAddress = newParliamentAddress, + ContractAddress = ParliamentContractAddress + }; + await ExecuteProposalForParliamentTransaction(ElectionContractAddress, + nameof(ElectionContractStub.ChangeVoteWeightInterestController), newAuthority); + + var getNewAuthority = await ElectionContractStub.GetVoteWeightInterestController.CallAsync(new Empty()); + getNewAuthority.ContractAddress.ShouldBe(newAuthority.ContractAddress); + getNewAuthority.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); + } + + [Fact] + public async Task Election_SetVoteWeightProportion_Without_Authority_Test() + { + var newSetting = new VoteWeightProportion + { + TimeProportion = 3, + AmountProportion = 3 + }; + var settingRet = await ElectionContractStub.SetVoteWeightProportion.SendAsync(newSetting); + settingRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + settingRet.TransactionResult.Error.ShouldContain("No permission"); + } + + [Fact] + public async Task Election_SetVoteWeightProportion_With_Invalid_Input_Test() + { + var newSetting = new VoteWeightProportion + { + TimeProportion = 0, + AmountProportion = 3 + }; + var settingRet = await ExecuteProposalForParliamentTransactionWithException(BootMinerAddress, + ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightProportion), newSetting); + settingRet.Status.ShouldBe(TransactionResultStatus.Failed); + settingRet.Error.ShouldContain("invalid input"); + } + + [Fact] + public async Task Election_SetVoteWeightProportion_Test() + { + var defaultSetting = await ElectionContractStub.GetVoteWeightProportion.CallAsync( + new Empty()); + defaultSetting.TimeProportion.ShouldBe(2); + defaultSetting.AmountProportion.ShouldBe(1); + defaultSetting = new VoteWeightProportion + { + TimeProportion = 3, + AmountProportion = 3 + }; + await ExecuteProposalForParliamentTransaction(ElectionContractAddress, + nameof(ElectionContractStub.SetVoteWeightProportion), defaultSetting); + + defaultSetting = await ElectionContractStub.GetVoteWeightProportion.CallAsync( + new Empty()); + defaultSetting.TimeProportion.ShouldBe(3); + defaultSetting.AmountProportion.ShouldBe(3); + } + + #region test about adjust data center + + [Fact] + public async Task ElectionContract_Vote_DataCenter_Replace_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - - #region test about adjust data center - [Fact] - public async Task ElectionContract_Vote_DataCenter_Replace_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.Count.ShouldBe(fullCount); - var minimumCandidate = dataCenterList.DataCenters.First(); - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); - var voteToCandidateRet = await VoteToCandidate(voter, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); - voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var newDataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - newDataCenterList.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeFalse(); - newDataCenterList.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeTrue(); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetailOfOldOne = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) - }); - profitDetailOfOldOne.Details.Count.ShouldBe(1); - profitDetailOfOldOne.Details[0].EndPeriod.ShouldBe(0); - var profitDetailOfNewOne = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) - }); - profitDetailOfNewOne.Details.Count.ShouldBe(1); + + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.Count.ShouldBe(fullCount); + var minimumCandidate = dataCenterList.DataCenters.First(); + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); + var voteToCandidateRet = await VoteToCandidate(voter, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); + voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var newDataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + newDataCenterList.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeFalse(); + newDataCenterList.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeTrue(); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetailOfOldOne = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) + }); + profitDetailOfOldOne.Details.Count.ShouldBe(1); + profitDetailOfOldOne.Details[0].EndPeriod.ShouldBe(0); + var profitDetailOfNewOne = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) + }); + profitDetailOfNewOne.Details.Count.ShouldBe(1); + } + + [Fact] + public async Task ElectionContract_Withdraw_DataCenter_Replace_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - - [Fact] - public async Task ElectionContract_Withdraw_DataCenter_Replace_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - var minimumCandidate = dataCenterList.DataCenters.First(); - // vote a new candidate that should be added to the date center, and the minimum one in data center should be removed. - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); - var voter2 = VoterKeyPairs.Skip(1).First(); - var voteToCandidateRet = await VoteToCandidate(voter2, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); - voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); - - // after withdraw, the new candidate should be removed - BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter2.PublicKey), - VotingItemId = electionVoteItemId - }); - voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); - var withdrawVotesRet = await WithdrawVotes(voter2, voteIdOfVoter2.ActiveVotes[0]); - withdrawVotesRet.Status.ShouldBe(TransactionResultStatus.Mined); - var dataCenterListAfterWithDraw = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterListAfterWithDraw.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeTrue(); - dataCenterListAfterWithDraw.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeFalse(); - - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) - }); - profitDetail.Details[0].EndPeriod.ShouldBe(0); - profitDetail.Details[1].EndPeriod.ShouldBe(long.MaxValue); - var profitDetailOfTheWithdraw = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) - }); - profitDetailOfTheWithdraw.Details.Count.ShouldBe(1); + + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + var minimumCandidate = dataCenterList.DataCenters.First(); + // vote a new candidate that should be added to the date center, and the minimum one in data center should be removed. + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); + var voter2 = VoterKeyPairs.Skip(1).First(); + var voteToCandidateRet = await VoteToCandidate(voter2, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); + voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); + + // after withdraw, the new candidate should be removed + BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter2.PublicKey), + VotingItemId = electionVoteItemId + }); + voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); + var withdrawVotesRet = await WithdrawVotes(voter2, voteIdOfVoter2.ActiveVotes[0]); + withdrawVotesRet.Status.ShouldBe(TransactionResultStatus.Mined); + var dataCenterListAfterWithDraw = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterListAfterWithDraw.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeTrue(); + dataCenterListAfterWithDraw.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeFalse(); + + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) + }); + profitDetail.Details[0].EndPeriod.ShouldBe(0); + profitDetail.Details[1].EndPeriod.ShouldBe(long.MaxValue); + var profitDetailOfTheWithdraw = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) + }); + profitDetailOfTheWithdraw.Details.Count.ShouldBe(1); + } + + [Fact] + public async Task ElectionContract_QuitElection_DataCenter_Replace_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - [Fact] - public async Task ElectionContract_QuitElection_DataCenter_Replace_Test() + var maximumVoteAmountCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; + var newCandidate1 = ValidationDataCenterCandidateKeyPairs.First(); + var newCandidate2 = ValidationDataCenterCandidateKeyPairs.Skip(1).First(); + await AnnounceElectionAsync(newCandidate1); + await AnnounceElectionAsync(newCandidate2); + await VoteToCandidate(voter, newCandidate1.PublicKey.ToHex(), lockTime, span.Div(2)); + await VoteToCandidate(voter, newCandidate2.PublicKey.ToHex(), lockTime, span.Div(3)); + await QuitElectionAsync(maximumVoteAmountCandidate); + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.Count.ShouldBe(fullCount); + dataCenterList.DataCenters.ContainsKey(newCandidate1.PublicKey.ToHex()).ShouldBeTrue(); + dataCenterList.DataCenters.ContainsKey(maximumVoteAmountCandidate.PublicKey.ToHex()).ShouldBeFalse(); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetailOfNewCandidate = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - var maximumVoteAmountCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; - var newCandidate1 = ValidationDataCenterCandidateKeyPairs.First(); - var newCandidate2 = ValidationDataCenterCandidateKeyPairs.Skip(1).First(); - await AnnounceElectionAsync(newCandidate1); - await AnnounceElectionAsync(newCandidate2); - await VoteToCandidate(voter,newCandidate1.PublicKey.ToHex(), lockTime, span.Div(2)); - await VoteToCandidate(voter,newCandidate2.PublicKey.ToHex(), lockTime, span.Div(3)); - await QuitElectionAsync(maximumVoteAmountCandidate); - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.Count.ShouldBe(fullCount); - dataCenterList.DataCenters.ContainsKey(newCandidate1.PublicKey.ToHex()).ShouldBeTrue(); - dataCenterList.DataCenters.ContainsKey(maximumVoteAmountCandidate.PublicKey.ToHex()).ShouldBeFalse(); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetailOfNewCandidate = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(newCandidate1.PublicKey) - }); - profitDetailOfNewCandidate.Details.Count.ShouldBe(1); - var profitDetailOfMaximumVoteAmountCandidate = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(newCandidate1.PublicKey) + }); + profitDetailOfNewCandidate.Details.Count.ShouldBe(1); + var profitDetailOfMaximumVoteAmountCandidate = await ProfitContractStub.GetProfitDetails.CallAsync( + new GetProfitDetailsInput { SchemeId = subsidy, Beneficiary = Address.FromPublicKey(maximumVoteAmountCandidate.PublicKey) }); - profitDetailOfMaximumVoteAmountCandidate.Details.Count.ShouldBe(1); - profitDetailOfMaximumVoteAmountCandidate.Details[0].EndPeriod.ShouldBe(0); - - var candidateToQuit1 = ValidationDataCenterKeyPairs[0]; - var candidateToQuit2 = ValidationDataCenterKeyPairs[1]; - await QuitElectionAsync(candidateToQuit1); - await QuitElectionAsync(candidateToQuit2); - dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.Count.ShouldBe(fullCount - 1); - var profitDetailOfMinimumCandidate = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + profitDetailOfMaximumVoteAmountCandidate.Details.Count.ShouldBe(1); + profitDetailOfMaximumVoteAmountCandidate.Details[0].EndPeriod.ShouldBe(0); + + var candidateToQuit1 = ValidationDataCenterKeyPairs[0]; + var candidateToQuit2 = ValidationDataCenterKeyPairs[1]; + await QuitElectionAsync(candidateToQuit1); + await QuitElectionAsync(candidateToQuit2); + dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.Count.ShouldBe(fullCount - 1); + var profitDetailOfMinimumCandidate = await ProfitContractStub.GetProfitDetails.CallAsync( + new GetProfitDetailsInput { SchemeId = subsidy, Beneficiary = Address.FromPublicKey(candidateToQuit1.PublicKey) }); - profitDetailOfMinimumCandidate.Details.Count.ShouldBe(1); - profitDetailOfMinimumCandidate.Details[0].EndPeriod.ShouldBe(0); + profitDetailOfMinimumCandidate.Details.Count.ShouldBe(1); + profitDetailOfMinimumCandidate.Details[0].EndPeriod.ShouldBe(0); + } + + /// + /// changeVoteOption from a candidate A who is in the data center, and it will be replaced by someone out of data + /// center + /// + /// + [Fact] + public async Task ElectionContract_ChangeVoteOption_DataCenter_Replace_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - - /// - /// changeVoteOption from a candidate A who is in the data center, and it will be replaced by someone out of data center - /// - /// - [Fact] - public async Task ElectionContract_ChangeVoteOption_DataCenter_Replace_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - var minimumCandidate = dataCenterList.DataCenters.First(); - // vote a new candidate that should be added to the date center, and the minimum one in data center should be removed. - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); - var voter2 = VoterKeyPairs.Skip(1).First(); - var voteToCandidateRet = await VoteToCandidate(voter2, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); - voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); - - // after change option, the minimum candidate amount add to 2700, it should be in data center - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter2.PublicKey), - VotingItemId = electionVoteItemId - }); - voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); - // await change - var changeOptionRet = await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], minimumCandidate.Key); - changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var dataCenterListAfterChangeOption = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterListAfterChangeOption.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeTrue(); - dataCenterListAfterChangeOption.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeFalse(); - - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetailOfTheIn = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) - }); - profitDetailOfTheIn.Details.Count.ShouldBe(2); - profitDetailOfTheIn.Details[0].EndPeriod.ShouldBe(0); - profitDetailOfTheIn.Details[1].EndPeriod.ShouldBe(long.MaxValue); - var profitDetailOfTheOut = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) - }); - profitDetailOfTheOut.Details.Count.ShouldBe(1); - profitDetailOfTheOut.Details[0].EndPeriod.ShouldBe(0); + + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + var minimumCandidate = dataCenterList.DataCenters.First(); + // vote a new candidate that should be added to the date center, and the minimum one in data center should be removed. + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); + var voter2 = VoterKeyPairs.Skip(1).First(); + var voteToCandidateRet = await VoteToCandidate(voter2, newCandidate.PublicKey.ToHex(), lockTime, voteAmount); + voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); + + // after change option, the minimum candidate amount add to 2700, it should be in data center + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter2.PublicKey), + VotingItemId = electionVoteItemId + }); + voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); + // await change + var changeOptionRet = await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], minimumCandidate.Key); + changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var dataCenterListAfterChangeOption = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterListAfterChangeOption.DataCenters.ContainsKey(minimumCandidate.Key).ShouldBeTrue(); + dataCenterListAfterChangeOption.DataCenters.ContainsKey(newCandidate.PublicKey.ToHex()).ShouldBeFalse(); + + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetailOfTheIn = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(minimumCandidate.Key)) + }); + profitDetailOfTheIn.Details.Count.ShouldBe(2); + profitDetailOfTheIn.Details[0].EndPeriod.ShouldBe(0); + profitDetailOfTheIn.Details[1].EndPeriod.ShouldBe(long.MaxValue); + var profitDetailOfTheOut = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) + }); + profitDetailOfTheOut.Details.Count.ShouldBe(1); + profitDetailOfTheOut.Details[0].EndPeriod.ShouldBe(0); + } + + /// + /// changeVoteOption from a candidate A who is in the data center, and it has enough vote to stay in the date center + /// + /// + [Fact] + public async Task ElectionContract_ChangeVoteOption_DataCenter_Remain_Unchanged_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - /// - /// changeVoteOption from a candidate A who is in the data center, and it has enough vote to stay in the date center - /// - /// - [Fact] - public async Task ElectionContract_ChangeVoteOption_DataCenter_Remain_Unchanged_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - var maximumVoteCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); - var voter2 = VoterKeyPairs.Skip(1).First(); - var voteAmount2 = 100; - var voteToCandidateRet = await VoteToCandidate(voter2, maximumVoteCandidate.PublicKey.ToHex(), lockTime, voteAmount2); - voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter2.PublicKey), - VotingItemId = electionVoteItemId - }); - voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); - var dataCenterListBeforeChangeOption = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - // await change - var changeOptionRet = await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], newCandidate.PublicKey.ToHex()); - changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var dataCenterListAfterChangeOption = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterListBeforeChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); - dataCenterListAfterChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); + var maximumVoteCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); + var voter2 = VoterKeyPairs.Skip(1).First(); + var voteAmount2 = 100; + var voteToCandidateRet = + await VoteToCandidate(voter2, maximumVoteCandidate.PublicKey.ToHex(), lockTime, voteAmount2); + voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter2.PublicKey), + VotingItemId = electionVoteItemId + }); + voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); + var dataCenterListBeforeChangeOption = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + // await change + var changeOptionRet = + await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], newCandidate.PublicKey.ToHex()); + changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var dataCenterListAfterChangeOption = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterListBeforeChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); + dataCenterListAfterChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); + } + + /// + /// changeVoteOption to another candidate A, and A's vote amount is greater than someone in data center + /// + /// + [Fact] + public async Task ElectionContract_ChangeVoteOption_New_Candidate_Replace_DataCenter_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); } - - /// - /// changeVoteOption to another candidate A, and A's vote amount is greater than someone in data center - /// - /// - [Fact] - public async Task ElectionContract_ChangeVoteOption_New_Candidate_Replace_DataCenter_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter,keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - var minimumVoteCandidate= ValidationDataCenterKeyPairs[0]; - var maximumVoteCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); - var voter2 = VoterKeyPairs.Skip(1).First(); - var voteToCandidateRet = await VoteToCandidate(voter2, maximumVoteCandidate.PublicKey.ToHex(), lockTime, voteAmount); - voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter2.PublicKey), - VotingItemId = electionVoteItemId - }); - voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); - var dataCenterListBeforeChangeOption = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - // await change - var changeOptionRet = await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], newCandidate.PublicKey.ToHex()); - changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); - - var dataCenterListAfterChangeOption = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterListBeforeChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); - dataCenterListAfterChangeOption.DataCenters.Keys.ShouldContain(newCandidate.PublicKey.ToHex()); - dataCenterListAfterChangeOption.DataCenters.Keys.ShouldNotContain(minimumVoteCandidate.PublicKey.ToHex()); - - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetailOfTheIn = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + + var minimumVoteCandidate = ValidationDataCenterKeyPairs[0]; + var maximumVoteCandidate = ValidationDataCenterKeyPairs[fullCount - 1]; + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); + var voter2 = VoterKeyPairs.Skip(1).First(); + var voteToCandidateRet = + await VoteToCandidate(voter2, maximumVoteCandidate.PublicKey.ToHex(), lockTime, voteAmount); + voteToCandidateRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter2 = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter2.PublicKey), + VotingItemId = electionVoteItemId + }); + voteIdOfVoter2.ActiveVotes.Count.ShouldBe(1); + var dataCenterListBeforeChangeOption = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + // await change + var changeOptionRet = + await ChangeVoteOption(voter2, voteIdOfVoter2.ActiveVotes[0], newCandidate.PublicKey.ToHex()); + changeOptionRet.Status.ShouldBe(TransactionResultStatus.Mined); + + var dataCenterListAfterChangeOption = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterListBeforeChangeOption.DataCenters.Keys.ShouldNotContain(newCandidate.PublicKey.ToHex()); + dataCenterListAfterChangeOption.DataCenters.Keys.ShouldContain(newCandidate.PublicKey.ToHex()); + dataCenterListAfterChangeOption.DataCenters.Keys.ShouldNotContain(minimumVoteCandidate.PublicKey.ToHex()); + + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetailOfTheIn = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) + }); + profitDetailOfTheIn.Details.Count.ShouldBe(1); + + var profitDetailOfTheOut = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(minimumVoteCandidate.PublicKey) + }); + profitDetailOfTheOut.Details.Count.ShouldBe(1); + profitDetailOfTheOut.Details[0].EndPeriod.ShouldBe(0); + } + + [Fact] + public async Task ElectionContract_UpdateMinerCount_ReduceBp_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var span = 100; + var lockTime = 120 * 60 * 60 * 24; + var fullCount = 5.Mul(5); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) + { + await AnnounceElectionAsync(keyPair); + await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); + voteAmount = voteAmount.Add(span); + } + + var minerCount = 3; + await NextRound(InitialCoreDataCenterKeyPairs[0]); + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.Count.ShouldBe(fullCount); + var diffCount = fullCount.Sub(minerCount.Mul(5)); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(diffCount)) + { + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(newCandidate.PublicKey) + Beneficiary = Address.FromPublicKey(keyPair.PublicKey) }); - profitDetailOfTheIn.Details.Count.ShouldBe(1); - - var profitDetailOfTheOut = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + profitDetail.Details[0].EndPeriod.ShouldNotBe(0); + profitDetail.Details.Count.ShouldBe(1); + } + + await ResetMinerCount(minerCount); + await NextTerm(InitialCoreDataCenterKeyPairs[0]); + var newMinerCount = await ElectionContractStub.GetMinersCount.CallAsync(new Empty()); + newMinerCount.Value.ShouldBe(minerCount); + var dataCenterListAfterReduceBp = + await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + + dataCenterList.DataCenters.Count.Sub(dataCenterListAfterReduceBp.DataCenters.Count).ShouldBe(diffCount); + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(diffCount)) + { + dataCenterListAfterReduceBp.DataCenters.ContainsKey(keyPair.PublicKey.ToHex()).ShouldBeFalse(); + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(minimumVoteCandidate.PublicKey) + Beneficiary = Address.FromPublicKey(keyPair.PublicKey) }); - profitDetailOfTheOut.Details.Count.ShouldBe(1); - profitDetailOfTheOut.Details[0].EndPeriod.ShouldBe(0); - } - - [Fact] - public async Task ElectionContract_UpdateMinerCount_ReduceBp_Test() - { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var span = 100; - var lockTime = 120 * 60 * 60 * 24; - var fullCount = 5.Mul(5); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(fullCount)) - { - await AnnounceElectionAsync(keyPair); - await VoteToCandidate(voter, keyPair.PublicKey.ToHex(), lockTime, voteAmount); - voteAmount = voteAmount.Add(span); - } - var minerCount = 3; - await NextRound(InitialCoreDataCenterKeyPairs[0]); - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.Count.ShouldBe(fullCount); - var diffCount = fullCount.Sub(minerCount.Mul(5)); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(diffCount)) - { - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(keyPair.PublicKey) - }); - profitDetail.Details[0].EndPeriod.ShouldNotBe(0); - profitDetail.Details.Count.ShouldBe(1); - } - await ResetMinerCount(minerCount); - await NextTerm(InitialCoreDataCenterKeyPairs[0]); - var newMinerCount = await ElectionContractStub.GetMinersCount.CallAsync(new Empty()); - newMinerCount.Value.ShouldBe(minerCount); - var dataCenterListAfterReduceBp = - await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - - dataCenterList.DataCenters.Count.Sub(dataCenterListAfterReduceBp.DataCenters.Count).ShouldBe(diffCount); - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(diffCount)) - { - dataCenterListAfterReduceBp.DataCenters.ContainsKey(keyPair.PublicKey.ToHex()).ShouldBeFalse(); - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(keyPair.PublicKey) - }); - profitDetail.Details[0].EndPeriod.ShouldBe(0); - } + profitDetail.Details[0].EndPeriod.ShouldBe(0); } + } - private async Task ResetMinerCount(int count) + private async Task ResetMinerCount(int count) + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalMethodName = nameof(AEDPoSContractStub.SetMaximumMinersCount); + var param = new Int32Value { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalMethodName = nameof(AEDPoSContractStub.SetMaximumMinersCount); - var param = new Int32Value - { - Value = count - }; - var proposalId = await CreateProposalAsync(ConsensusContractAddress, - defaultParliament, proposalMethodName, param); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - } - - #endregion + Value = count + }; + var proposalId = await CreateProposalAsync(ConsensusContractAddress, + defaultParliament, proposalMethodName, param); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs index ab88c9efb1..837407afd5 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs @@ -11,349 +11,337 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests : ElectionContractTestBase { - public partial class ElectionContractTests : ElectionContractTestBase + [Fact] + public async Task GetMinersCount_Test() { - [Fact] - public async Task GetMinersCount_Test() - { - var minersCount = await ElectionContractStub.GetMinersCount.CallAsync(new Empty()); - minersCount.Value.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); - } - - [Fact] - public async Task GetElectionResult_Test() - { - await ElectionContract_Vote_Test(); - await NextTerm(InitialCoreDataCenterKeyPairs[0]); + var minersCount = await ElectionContractStub.GetMinersCount.CallAsync(new Empty()); + minersCount.Value.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); + } - //verify term 1 - var electionResult = await ElectionContractStub.GetElectionResult.CallAsync(new GetElectionResultInput - { - TermNumber = 1 - }); - electionResult.IsActive.ShouldBe(false); - electionResult.Results.Count.ShouldBe(19); - electionResult.Results.Values.ShouldAllBe(o => o == 1000); - } + [Fact] + public async Task GetElectionResult_Test() + { + await ElectionContract_Vote_Test(); + await NextTerm(InitialCoreDataCenterKeyPairs[0]); - [Fact] - public async Task GetElectorVoteWithRecords_NotExist_Test() + //verify term 1 + var electionResult = await ElectionContractStub.GetElectionResult.CallAsync(new GetElectionResultInput { - await ElectionContract_Vote_Test(); + TermNumber = 1 + }); + electionResult.IsActive.ShouldBe(false); + electionResult.Results.Count.ShouldBe(19); + electionResult.Results.Values.ShouldAllBe(o => o == 1000); + } - var voteRecords = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue - { - Value = ValidationDataCenterKeyPairs.Last().PublicKey.ToHex() - }); - voteRecords.ShouldBe(new ElectorVote - { - Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs.Last().PublicKey) - }); - } + [Fact] + public async Task GetElectorVoteWithRecords_NotExist_Test() + { + await ElectionContract_Vote_Test(); - [Fact] - public async Task GetElectorVoteWithAllRecords_Test() + var voteRecords = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue { - var voters = await UserVotesCandidate(2, 500, 100); - var voterKeyPair = voters[0]; - //without withdraw - var allRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue - { - Value = voterKeyPair.PublicKey.ToHex() - }); - allRecords.ActiveVotingRecords.Count.ShouldBeGreaterThanOrEqualTo(1); - allRecords.WithdrawnVotingRecordIds.Count.ShouldBe(0); - - //withdraw - await NextTerm(InitialCoreDataCenterKeyPairs[0]); - BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(100 * 60 * 60 * 24 + 1)); - var voteId = - (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue - {Value = voterKeyPair.PublicKey.ToHex()})).ActiveVotingRecordIds.First(); - var executionResult = await WithdrawVotes(voterKeyPair, voteId); - executionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - allRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue - { - Value = voterKeyPair.PublicKey.ToHex() - }); - allRecords.WithdrawnVotingRecordIds.Count.ShouldBe(1); - } + Value = ValidationDataCenterKeyPairs.Last().PublicKey.ToHex() + }); + voteRecords.ShouldBe(new ElectorVote + { + Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs.Last().PublicKey) + }); + } - [Fact] - public async Task GetVotersCount_Test() + [Fact] + public async Task GetElectorVoteWithAllRecords_Test() + { + var voters = await UserVotesCandidate(2, 500, 100); + var voterKeyPair = voters[0]; + //without withdraw + var allRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = voterKeyPair.PublicKey.ToHex() + }); + allRecords.ActiveVotingRecords.Count.ShouldBeGreaterThanOrEqualTo(1); + allRecords.WithdrawnVotingRecordIds.Count.ShouldBe(0); + + //withdraw + await NextTerm(InitialCoreDataCenterKeyPairs[0]); + BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(100 * 60 * 60 * 24 + 1)); + var voteId = + (await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { Value = voterKeyPair.PublicKey.ToHex() })).ActiveVotingRecordIds.First(); + var executionResult = await WithdrawVotes(voterKeyPair, voteId); + executionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + allRecords = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue { - await UserVotesCandidate(5, 1000, 120); + Value = voterKeyPair.PublicKey.ToHex() + }); + allRecords.WithdrawnVotingRecordIds.Count.ShouldBe(1); + } - var votersCount = await ElectionContractStub.GetVotersCount.CallAsync(new Empty()); - votersCount.Value.ShouldBe(5 * CandidatesCount); - } + [Fact] + public async Task GetVotersCount_Test() + { + await UserVotesCandidate(5, 1000, 120); - [Fact] - public async Task GetVotesAmount_Test() - { - await UserVotesCandidate(2, 200, 120); + var votersCount = await ElectionContractStub.GetVotersCount.CallAsync(new Empty()); + votersCount.Value.ShouldBe(5 * CandidatesCount); + } - var votesAmount = await ElectionContractStub.GetVotesAmount.CallAsync(new Empty()); - votesAmount.Value.ShouldBe(2 * CandidatesCount * 200); - } + [Fact] + public async Task GetVotesAmount_Test() + { + await UserVotesCandidate(2, 200, 120); - [Fact] - public async Task GetTermSnapshot_Test() + var votesAmount = await ElectionContractStub.GetVotesAmount.CallAsync(new Empty()); + votesAmount.Value.ShouldBe(2 * CandidatesCount * 200); + } + + [Fact] + public async Task GetTermSnapshot_Test() + { + //first term { - //first term - { - await ProduceBlocks(InitialCoreDataCenterKeyPairs[0], 5); - await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); - await ProduceBlocks(InitialCoreDataCenterKeyPairs[2], 15); - await NextTerm(BootMinerKeyPair); - - var snapshot = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput - { - TermNumber = 1 - }); - snapshot.MinedBlocks.ShouldBeGreaterThanOrEqualTo(30); - snapshot.ElectionResult.Count.ShouldBe(0); - } - - //second term + await ProduceBlocks(InitialCoreDataCenterKeyPairs[0], 5); + await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); + await ProduceBlocks(InitialCoreDataCenterKeyPairs[2], 15); + await NextTerm(BootMinerKeyPair); + + var snapshot = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput { - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } - - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); - - var moreVotesCandidates = ValidationDataCenterKeyPairs - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - - foreach (var candidate in moreVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], candidate.PublicKey.ToHex(), 100 * 86400, 2); - } - - await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); - await NextTerm(BootMinerKeyPair); - - var snapshot = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput - { - TermNumber = 2 - }); - snapshot.MinedBlocks.ShouldBeGreaterThanOrEqualTo(10); - snapshot.ElectionResult.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); - snapshot.ElectionResult.Values - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToArray() - .ShouldAllBe(item => item == 2); - } + TermNumber = 1 + }); + snapshot.MinedBlocks.ShouldBeGreaterThanOrEqualTo(30); + snapshot.ElectionResult.Count.ShouldBe(0); } - [Fact] - public async Task GetPageableCandidateInformation_Test() + //second term { - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } - - //query before vote - var candidateInformation0 = - await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation - { - Start = 0, - Length = 10 - }); - candidateInformation0.Value.Count.ShouldBe(10); - candidateInformation0.Value.ToList().Select(o=>o.ObtainedVotesAmount).ShouldAllBe(o=>o==0); + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + var moreVotesCandidates = ValidationDataCenterKeyPairs .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var keyPair in moreVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); - } - var fewVotesCandidates = ValidationDataCenterKeyPairs - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount).Take(10).ToList(); - foreach (var keyPair in fewVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 1); - } - - var candidateInformation = - await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation - { - Start = 0, - Length = 5 - }); - candidateInformation.Value.Count.ShouldBe(5); - candidateInformation.Value.ToList().Select(o => o.ObtainedVotesAmount).ShouldAllBe(o => o == 2); - - var candidateInformation1 = - await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation - { - Start = 5, - Length = 10 - }); - candidateInformation1.Value.Count.ShouldBe(10); - candidateInformation1.Value.ToList().Select(o => o.ObtainedVotesAmount).ShouldAllBe(o => o == 1); - } - [Fact] - public async Task GetCurrentMiningReward_Test() - { - await NextTerm(BootMinerKeyPair); + foreach (var candidate in moreVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], candidate.PublicKey.ToHex(), 100 * 86400, 2); - //basic value - { - await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); - var miningReward = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); - miningReward.Value.ShouldBeGreaterThanOrEqualTo(ElectionContractConstants.ElfTokenPerBlock * 10); - } + await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); + await NextTerm(BootMinerKeyPair); - //compare with different term + var snapshot = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput { - await NextTerm(BootMinerKeyPair); - await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); - var miningReward1 = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); - - await NextTerm(BootMinerKeyPair); - await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); - var miningReward2 = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); - - miningReward1.ShouldBe(miningReward2); - } + TermNumber = 2 + }); + snapshot.MinedBlocks.ShouldBeGreaterThanOrEqualTo(10); + snapshot.ElectionResult.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + snapshot.ElectionResult.Values + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToArray() + .ShouldAllBe(item => item == 2); } + } - [Fact] - public async Task Vote_Weight_Calculate() - { - var day = 375; // in 2 year - var weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation - { - Amount = 1000, - LockTime = day * 24 * 3600 - }); - weight.Value.ShouldBe(2254); - day = 180; // in 1 year - weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation - { - Amount = 1000, - LockTime = day * 24 * 3600 - }); - weight.Value.ShouldBe(1697); - day = 1000; // in 3 year - weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation + [Fact] + public async Task GetPageableCandidateInformation_Test() + { + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); + + //query before vote + var candidateInformation0 = + await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation { - Amount = 1000, - LockTime = day * 24 * 3600 + Start = 0, + Length = 10 }); - weight.Value.ShouldBe(7874); - day = 1096; // > 3 year - weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation + candidateInformation0.Value.Count.ShouldBe(10); + candidateInformation0.Value.ToList().Select(o => o.ObtainedVotesAmount).ShouldAllBe(o => o == 0); + + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + var moreVotesCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var keyPair in moreVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); + var fewVotesCandidates = ValidationDataCenterKeyPairs + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount).Take(10).ToList(); + foreach (var keyPair in fewVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 1); + + var candidateInformation = + await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation { - Amount = 1000, - LockTime = day * 24 * 3600 + Start = 0, + Length = 5 }); - weight.Value.ShouldBe(9433); - - day = 1; // 1 day - weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation + candidateInformation.Value.Count.ShouldBe(5); + candidateInformation.Value.ToList().Select(o => o.ObtainedVotesAmount).ShouldAllBe(o => o == 2); + + var candidateInformation1 = + await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation { - Amount = 1000, - LockTime = day * 24 * 3600 + Start = 5, + Length = 10 }); - weight.Value.ShouldBe(1500); - } + candidateInformation1.Value.Count.ShouldBe(10); + candidateInformation1.Value.ToList().Select(o => o.ObtainedVotesAmount).ShouldAllBe(o => o == 1); + } + + [Fact] + public async Task GetCurrentMiningReward_Test() + { + await NextTerm(BootMinerKeyPair); - [Fact] - public async Task Election_GetMinerElectionVotingItemId_Test() + //basic value { - var voteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = voteItemId - }); - voteItem.IsLockToken.ShouldBe(false); + await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); + var miningReward = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); + miningReward.Value.ShouldBeGreaterThanOrEqualTo(ElectionContractConstants.ElfTokenPerBlock * 10); } - [Fact] - public async Task Election_GetVotedCandidates_Test() + //compare with different term { - var ret = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); - ret.ShouldBe(new PubkeyList()); + await NextTerm(BootMinerKeyPair); + await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); + var miningReward1 = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); + + await NextTerm(BootMinerKeyPair); + await ProduceBlocks(InitialCoreDataCenterKeyPairs[1], 10); + var miningReward2 = await AEDPoSContractStub.GetCurrentTermMiningReward.CallAsync(new Empty()); + + miningReward1.ShouldBe(miningReward2); } - - [Fact] - public async Task Election_GetCandidateInformation_Test() + } + + [Fact] + public async Task Vote_Weight_Calculate() + { + var day = 375; // in 2 year + var weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation { - var key = "not exist"; - var ret = await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue - { - Value = key - }); - ret.ShouldBe(new CandidateInformation {Pubkey = key}); - } - - [Fact] - public async Task Election_GetTermSnapshot_Test() + Amount = 1000, + LockTime = day * 24 * 3600 + }); + weight.Value.ShouldBe(2254); + day = 180; // in 1 year + weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation { - var ret = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput - { - TermNumber = 10 - }); - ret.ShouldBe(new TermSnapshot()); - } - - [Fact] - public async Task Election_GetElectorVote_Test() + Amount = 1000, + LockTime = day * 24 * 3600 + }); + weight.Value.ShouldBe(1697); + day = 1000; // in 3 year + weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation { - var key = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); - var ret = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue - { - Value = key - }); - ret.ShouldBe(new ElectorVote {Pubkey = ByteStringHelper.FromHexString(key)}); - } + Amount = 1000, + LockTime = day * 24 * 3600 + }); + weight.Value.ShouldBe(7874); + day = 1096; // > 3 year + weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation + { + Amount = 1000, + LockTime = day * 24 * 3600 + }); + weight.Value.ShouldBe(9433); - [Fact] - public async Task Election_GetPageableCandidateInformation_Test() + day = 1; // 1 day + weight = await ElectionContractStub.GetCalculateVoteWeight.CallAsync(new VoteInformation { - var ret = await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation - { - Start = 100 - }); - ret.ShouldBe(new GetPageableCandidateInformationOutput()); - } - - [Fact] - public async Task Election_GetVoteWeightInterestController_Test() + Amount = 1000, + LockTime = day * 24 * 3600 + }); + weight.Value.ShouldBe(1500); + } + + [Fact] + public async Task Election_GetMinerElectionVotingItemId_Test() + { + var voteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - var ret = await ElectionContractStub.GetVoteWeightInterestController.CallAsync(new Empty()); - var parliamentDefaultAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - ret.OwnerAddress.ShouldBe(parliamentDefaultAddress); - ret.ContractAddress.ShouldBe(ParliamentContractAddress); - } + VotingItemId = voteItemId + }); + voteItem.IsLockToken.ShouldBe(false); + } - private async Task> UserVotesCandidate(int voterCount, long voteAmount, int lockDays) + [Fact] + public async Task Election_GetVotedCandidates_Test() + { + var ret = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); + ret.ShouldBe(new PubkeyList()); + } + + [Fact] + public async Task Election_GetCandidateInformation_Test() + { + var key = "not exist"; + var ret = await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue { - var lockTime = lockDays * 60 * 60 * 24; + Value = key + }); + ret.ShouldBe(new CandidateInformation { Pubkey = key }); + } - var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + [Fact] + public async Task Election_GetTermSnapshot_Test() + { + var ret = await ElectionContractStub.GetTermSnapshot.CallAsync(new GetTermSnapshotInput + { + TermNumber = 10 + }); + ret.ShouldBe(new TermSnapshot()); + } - var votersKeyPairs = VoterKeyPairs.Take(voterCount).ToList(); - var voterKeyPair = votersKeyPairs[0]; - var balanceBeforeVoting = await GetNativeTokenBalance(voterKeyPair.PublicKey); - balanceBeforeVoting.ShouldBeGreaterThan(0); + [Fact] + public async Task Election_GetElectorVote_Test() + { + var key = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); + var ret = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = key + }); + ret.ShouldBe(new ElectorVote { Pubkey = ByteStringHelper.FromHexString(key) }); + } - await VoteToCandidates(votersKeyPairs, - candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, voteAmount); + [Fact] + public async Task Election_GetPageableCandidateInformation_Test() + { + var ret = await ElectionContractStub.GetPageableCandidateInformation.CallAsync(new PageInformation + { + Start = 100 + }); + ret.ShouldBe(new GetPageableCandidateInformationOutput()); + } - return votersKeyPairs; - } + [Fact] + public async Task Election_GetVoteWeightInterestController_Test() + { + var ret = await ElectionContractStub.GetVoteWeightInterestController.CallAsync(new Empty()); + var parliamentDefaultAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + ret.OwnerAddress.ShouldBe(parliamentDefaultAddress); + ret.ContractAddress.ShouldBe(ParliamentContractAddress); + } + + private async Task> UserVotesCandidate(int voterCount, long voteAmount, int lockDays) + { + var lockTime = lockDays * 60 * 60 * 24; + + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + + var votersKeyPairs = VoterKeyPairs.Take(voterCount).ToList(); + var voterKeyPair = votersKeyPairs[0]; + var balanceBeforeVoting = await GetNativeTokenBalance(voterKeyPair.PublicKey); + balanceBeforeVoting.ShouldBeGreaterThan(0); + + await VoteToCandidates(votersKeyPairs, + candidatesKeyPairs.Select(p => p.PublicKey.ToHex()).ToList(), lockTime, voteAmount); + + return votersKeyPairs; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/BVT/ReplaceCandidateTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ReplaceCandidateTests.cs index 3d13f51918..2dae2f88a4 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ReplaceCandidateTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ReplaceCandidateTests.cs @@ -6,154 +6,153 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task ElectionContract_ReplaceCandidatePubkey_Test() { - [Fact] - public async Task ElectionContract_ReplaceCandidatePubkey_Test() - { - var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); - var candidateAdmin = ValidationDataCenterKeyPairs.Last(); - var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); - await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); - - // Check candidate admin - { - var admin = await ElectionContractStub.GetCandidateAdmin.CallAsync(new StringValue - {Value = announceElectionKeyPair.PublicKey.ToHex()}); - admin.ShouldBe(candidateAdminAddress); - } + var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); + var candidateAdmin = ValidationDataCenterKeyPairs.Last(); + var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); + await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); - // Check candidates. - { - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.ShouldContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); - } - - var candidateAdminStub = - GetTester(ElectionContractAddress, - candidateAdmin); - var newKeyPair = ValidationDataCenterKeyPairs.Skip(1).First(); - await candidateAdminStub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput - { - OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), - NewPubkey = newKeyPair.PublicKey.ToHex() - }); + // Check candidate admin + { + var admin = await ElectionContractStub.GetCandidateAdmin.CallAsync(new StringValue + { Value = announceElectionKeyPair.PublicKey.ToHex() }); + admin.ShouldBe(candidateAdminAddress); + } - // Check candidates again. - { - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.ShouldContain(ByteString.CopyFrom(newKeyPair.PublicKey)); - candidates.Value.ShouldNotContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); - } + // Check candidates. + { + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.ShouldContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); + } - // Check candidate information - { - var oldCandidateInformation = - await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue - {Value = announceElectionKeyPair.PublicKey.ToHex()}); - oldCandidateInformation.IsCurrentCandidate.ShouldBeFalse(); - var newPubkeyInformation = - await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue - {Value = newKeyPair.PublicKey.ToHex()}); - newPubkeyInformation.IsCurrentCandidate.ShouldBeTrue(); - } - - // Two pubkeys cannot quit election. - { - var stub = GetTester(ElectionContractAddress, - announceElectionKeyPair); - var result = await stub.QuitElection.SendAsync(new StringValue {Value = newKeyPair.PublicKey.ToHex()}); - result.TransactionResult.Error.ShouldContain("Only admin can quit election."); - } - { - var stub = GetTester(ElectionContractAddress, - newKeyPair); - var result = await stub.QuitElection.SendAsync(new StringValue {Value = newKeyPair.PublicKey.ToHex()}); - result.TransactionResult.Error.ShouldContain("Only admin can quit election."); - } + var candidateAdminStub = + GetTester(ElectionContractAddress, + candidateAdmin); + var newKeyPair = ValidationDataCenterKeyPairs.Skip(1).First(); + await candidateAdminStub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput + { + OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), + NewPubkey = newKeyPair.PublicKey.ToHex() + }); - // Only admin can quit election. - { - await candidateAdminStub.QuitElection.SendAsync(new StringValue - { - Value = newKeyPair.PublicKey.ToHex() - }); - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.ShouldNotContain(ByteString.CopyFrom(newKeyPair.PublicKey)); - } + // Check candidates again. + { + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.ShouldContain(ByteString.CopyFrom(newKeyPair.PublicKey)); + candidates.Value.ShouldNotContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); } - [Fact] - public async Task ElectionContract_ReplaceCandidatePubkey_NotCandidateAdmin_Test() + // Check candidate information { - var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); - var candidateAdmin = ValidationDataCenterKeyPairs.Last(); - var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); - await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); + var oldCandidateInformation = + await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue + { Value = announceElectionKeyPair.PublicKey.ToHex() }); + oldCandidateInformation.IsCurrentCandidate.ShouldBeFalse(); + var newPubkeyInformation = + await ElectionContractStub.GetCandidateInformation.CallAsync(new StringValue + { Value = newKeyPair.PublicKey.ToHex() }); + newPubkeyInformation.IsCurrentCandidate.ShouldBeTrue(); + } - var newKeyPair = ValidationDataCenterKeyPairs.Skip(1).First(); + // Two pubkeys cannot quit election. + { + var stub = GetTester(ElectionContractAddress, + announceElectionKeyPair); + var result = await stub.QuitElection.SendAsync(new StringValue { Value = newKeyPair.PublicKey.ToHex() }); + result.TransactionResult.Error.ShouldContain("Only admin can quit election."); + } + { + var stub = GetTester(ElectionContractAddress, + newKeyPair); + var result = await stub.QuitElection.SendAsync(new StringValue { Value = newKeyPair.PublicKey.ToHex() }); + result.TransactionResult.Error.ShouldContain("Only admin can quit election."); + } + // Only admin can quit election. + { + await candidateAdminStub.QuitElection.SendAsync(new StringValue { - var result = await ElectionContractStub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput - { - OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), - NewPubkey = newKeyPair.PublicKey.ToHex() - }); - result.TransactionResult.Error.ShouldContain("No permission."); - } - - // The one announced election neither can replace pubkey. - { - var stub = GetTester(ElectionContractAddress, - announceElectionKeyPair); - var result = await stub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput - { - OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), - NewPubkey = newKeyPair.PublicKey.ToHex() - }); - result.TransactionResult.Error.ShouldContain("No permission."); - } + Value = newKeyPair.PublicKey.ToHex() + }); + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.ShouldNotContain(ByteString.CopyFrom(newKeyPair.PublicKey)); } + } + + [Fact] + public async Task ElectionContract_ReplaceCandidatePubkey_NotCandidateAdmin_Test() + { + var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); + var candidateAdmin = ValidationDataCenterKeyPairs.Last(); + var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); + await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); + + var newKeyPair = ValidationDataCenterKeyPairs.Skip(1).First(); - [Fact] - public async Task ElectionContract_SetCandidateAdmin_NotCandidateAdmin_Test() { - var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); - var candidateAdmin = ValidationDataCenterKeyPairs.Last(); - var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); - await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); - - var newCandidateAdmin = ValidationDataCenterKeyPairs.Skip(2).First(); - var newCandidateAdminAddress = Address.FromPublicKey(newCandidateAdmin.PublicKey); - - var candidateAdminStub = - GetTester(ElectionContractAddress, - candidateAdmin); - await candidateAdminStub.SetCandidateAdmin.SendAsync(new SetCandidateAdminInput + var result = await ElectionContractStub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput { - Admin = newCandidateAdminAddress, - Pubkey = announceElectionKeyPair.PublicKey.ToHex() + OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), + NewPubkey = newKeyPair.PublicKey.ToHex() }); + result.TransactionResult.Error.ShouldContain("No permission."); + } - // Check new admin. - { - var admin = await ElectionContractStub.GetCandidateAdmin.CallAsync(new StringValue - {Value = announceElectionKeyPair.PublicKey.ToHex()}); - admin.ShouldBe(newCandidateAdminAddress); - } - - // New admin can quit election. - var newCandidateAdminStub = - GetTester(ElectionContractAddress, - newCandidateAdmin); - await newCandidateAdminStub.QuitElection.SendAsync(new StringValue + // The one announced election neither can replace pubkey. + { + var stub = GetTester(ElectionContractAddress, + announceElectionKeyPair); + var result = await stub.ReplaceCandidatePubkey.SendAsync(new ReplaceCandidatePubkeyInput { - Value = announceElectionKeyPair.PublicKey.ToHex() + OldPubkey = announceElectionKeyPair.PublicKey.ToHex(), + NewPubkey = newKeyPair.PublicKey.ToHex() }); - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.ShouldNotContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); + result.TransactionResult.Error.ShouldContain("No permission."); } } + + [Fact] + public async Task ElectionContract_SetCandidateAdmin_NotCandidateAdmin_Test() + { + var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); + var candidateAdmin = ValidationDataCenterKeyPairs.Last(); + var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); + await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); + + var newCandidateAdmin = ValidationDataCenterKeyPairs.Skip(2).First(); + var newCandidateAdminAddress = Address.FromPublicKey(newCandidateAdmin.PublicKey); + + var candidateAdminStub = + GetTester(ElectionContractAddress, + candidateAdmin); + await candidateAdminStub.SetCandidateAdmin.SendAsync(new SetCandidateAdminInput + { + Admin = newCandidateAdminAddress, + Pubkey = announceElectionKeyPair.PublicKey.ToHex() + }); + + // Check new admin. + { + var admin = await ElectionContractStub.GetCandidateAdmin.CallAsync(new StringValue + { Value = announceElectionKeyPair.PublicKey.ToHex() }); + admin.ShouldBe(newCandidateAdminAddress); + } + + // New admin can quit election. + var newCandidateAdminStub = + GetTester(ElectionContractAddress, + newCandidateAdmin); + await newCandidateAdminStub.QuitElection.SendAsync(new StringValue + { + Value = announceElectionKeyPair.PublicKey.ToHex() + }); + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.ShouldNotContain(ByteString.CopyFrom(announceElectionKeyPair.PublicKey)); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/BVT/SponsorTests.cs b/test/AElf.Contracts.Election.Tests/BVT/SponsorTests.cs index d841cc424a..267c8c9ae0 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/SponsorTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/SponsorTests.cs @@ -8,59 +8,58 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task ElectionContract_AnnounceElectionFor_State_Test() { - [Fact] - public async Task ElectionContract_AnnounceElectionFor_State_Test() - { - var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); - var sponsorKeyPair = ValidationDataCenterKeyPairs.Last(); - var balanceBeforeAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); + var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); + var sponsorKeyPair = ValidationDataCenterKeyPairs.Last(); + var balanceBeforeAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); - // Execute AnnounceElectionFor. - var electionStub = GetElectionContractTester(sponsorKeyPair); - var candidateAdmin = Address.FromPublicKey(candidatesKeyPair.PublicKey); - await electionStub.AnnounceElectionFor.SendAsync(new AnnounceElectionForInput - { - Admin = candidateAdmin, - Pubkey = candidatesKeyPair.PublicKey.ToHex() - }); - - var balanceAfterAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); - balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing - ElectionContractConstants.LockTokenForElection); + // Execute AnnounceElectionFor. + var electionStub = GetElectionContractTester(sponsorKeyPair); + var candidateAdmin = Address.FromPublicKey(candidatesKeyPair.PublicKey); + await electionStub.AnnounceElectionFor.SendAsync(new AnnounceElectionForInput + { + Admin = candidateAdmin, + Pubkey = candidatesKeyPair.PublicKey.ToHex() + }); - var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = MinerElectionVotingItemId - }); - votingItem.Options.Count.ShouldBe(1); - votingItem.Options.ShouldContain(candidatesKeyPair.PublicKey.ToHex()); - var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); - dataCenterList.DataCenters.ContainsKey(candidatesKeyPair.PublicKey.ToHex()).ShouldBeTrue(); - var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = subsidy, - Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) - }); - profitDetail.Details.Count.ShouldBe(1); - } + var balanceAfterAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); + balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing - ElectionContractConstants.LockTokenForElection); - [Fact] - public async Task ElectionContract_QuitElection_Sponsor_Test() + var votingItem = await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - await ElectionContract_AnnounceElectionFor_State_Test(); + VotingItemId = MinerElectionVotingItemId + }); + votingItem.Options.Count.ShouldBe(1); + votingItem.Options.ShouldContain(candidatesKeyPair.PublicKey.ToHex()); + var dataCenterList = await ElectionContractStub.GetDataCenterRankingList.CallAsync(new Empty()); + dataCenterList.DataCenters.ContainsKey(candidatesKeyPair.PublicKey.ToHex()).ShouldBeTrue(); + var subsidy = ProfitItemsIds[ProfitType.BackupSubsidy]; + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = subsidy, + Beneficiary = Address.FromPublicKey(candidatesKeyPair.PublicKey) + }); + profitDetail.Details.Count.ShouldBe(1); + } + + [Fact] + public async Task ElectionContract_QuitElection_Sponsor_Test() + { + await ElectionContract_AnnounceElectionFor_State_Test(); - var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); - var sponsorKeyPair = ValidationDataCenterKeyPairs.Last(); - var balanceBeforeAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); + var candidatesKeyPair = ValidationDataCenterKeyPairs.First(); + var sponsorKeyPair = ValidationDataCenterKeyPairs.Last(); + var balanceBeforeAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); - await QuitElectionAsync(candidatesKeyPair); + await QuitElectionAsync(candidatesKeyPair); - var balanceAfterAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); - balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing + ElectionContractConstants.LockTokenForElection); - } + var balanceAfterAnnouncing = await GetNativeTokenBalance(sponsorKeyPair.PublicKey); + balanceAfterAnnouncing.ShouldBe(balanceBeforeAnnouncing + ElectionContractConstants.LockTokenForElection); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractConstants.cs b/test/AElf.Contracts.Election.Tests/ElectionContractConstants.cs index bd4549722d..835a4e7cea 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractConstants.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public static class ElectionContractConstants { - public static class ElectionContractConstants - { - public const long LockTokenForElection = 100_000_00000000; - public const long UserInitializeTokenAmount = 110_000_00000000; - public const long ElfTokenPerBlock = 1; - } + public const long LockTokenForElection = 100_000_00000000; + public const long UserInitializeTokenAmount = 110_000_00000000; + public const long ElfTokenPerBlock = 1; } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs index 1e7fdc7829..4375a2c352 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs @@ -13,125 +13,126 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public class ElectionContractTestBase : EconomicContractsTestBase { - public class ElectionContractTestBase : EconomicContractsTestBase + protected Hash MinerElectionVotingItemId; + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => + GetBasicContractTester(BootMinerKeyPair); + + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub => + GetTokenContractTester(BootMinerKeyPair); + + internal TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub => + GetTokenConverterContractTester(BootMinerKeyPair); + + internal VoteContractImplContainer.VoteContractImplStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); + + internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub => + GetProfitContractTester(BootMinerKeyPair); + + internal ElectionContractImplContainer.ElectionContractImplStub ElectionContractStub => + GetElectionContractTester(BootMinerKeyPair); + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => + GetAEDPoSContractTester(BootMinerKeyPair); + + internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => + GetTreasuryContractTester(BootMinerKeyPair); + + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetParliamentContractTester(BootMinerKeyPair); + + internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => + GetEconomicContractTester(BootMinerKeyPair); + + private new void DeployAllContracts() + { + _ = TokenContractAddress; + _ = VoteContractAddress; + _ = ProfitContractAddress; + _ = EconomicContractAddress; + _ = ElectionContractAddress; + _ = TreasuryContractAddress; + _ = TransactionFeeChargingContractAddress; + _ = ParliamentContractAddress; + _ = TokenConverterContractAddress; + _ = ConsensusContractAddress; + _ = ReferendumContractAddress; + _ = TokenHolderContractAddress; + _ = AssociationContractAddress; + } + + protected void InitializeContracts() + { + DeployAllContracts(); + + AsyncHelper.RunSync(InitializeParliamentContract); + AsyncHelper.RunSync(InitializeTreasuryConverter); + AsyncHelper.RunSync(InitializeElection); + AsyncHelper.RunSync(InitializeEconomicContract); + AsyncHelper.RunSync(InitializeToken); + AsyncHelper.RunSync(InitializeAElfConsensus); + AsyncHelper.RunSync(InitialMiningRewards); + + MinerElectionVotingItemId = AsyncHelper.RunSync(() => + ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty())); + } + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetBasicContractTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } + + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } + + internal TokenConverterContractImplContainer.TokenConverterContractImplStub GetTokenConverterContractTester( + ECKeyPair keyPair) + { + return GetTester( + TokenConverterContractAddress, + keyPair); + } + + internal VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) + { + return GetTester(VoteContractAddress, keyPair); + } + + internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } + + internal ElectionContractImplContainer.ElectionContractImplStub GetElectionContractTester(ECKeyPair keyPair) + { + return GetTester(ElectionContractAddress, keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + internal TreasuryContractImplContainer.TreasuryContractImplStub GetTreasuryContractTester(ECKeyPair keyPair) + { + return GetTester(TreasuryContractAddress, keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContractTester(ECKeyPair keyPair) { - private new void DeployAllContracts() - { - _ = TokenContractAddress; - _ = VoteContractAddress; - _ = ProfitContractAddress; - _ = EconomicContractAddress; - _ = ElectionContractAddress; - _ = TreasuryContractAddress; - _ = TransactionFeeChargingContractAddress; - _ = ParliamentContractAddress; - _ = TokenConverterContractAddress; - _ = ConsensusContractAddress; - _ = ReferendumContractAddress; - _ = TokenHolderContractAddress; - _ = AssociationContractAddress; - } - - protected void InitializeContracts() - { - DeployAllContracts(); - - AsyncHelper.RunSync(InitializeParliamentContract); - AsyncHelper.RunSync(InitializeTreasuryConverter); - AsyncHelper.RunSync(InitializeElection); - AsyncHelper.RunSync(InitializeEconomicContract); - AsyncHelper.RunSync(InitializeToken); - AsyncHelper.RunSync(InitializeAElfConsensus); - AsyncHelper.RunSync(InitialMiningRewards); - - MinerElectionVotingItemId = AsyncHelper.RunSync(() => - ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty())); - } - - protected Hash MinerElectionVotingItemId; - - internal new BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => - GetBasicContractTester(BootMinerKeyPair); - - internal new TokenContractImplContainer.TokenContractImplStub TokenContractStub => GetTokenContractTester(BootMinerKeyPair); - - internal new TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub => - GetTokenConverterContractTester(BootMinerKeyPair); - - internal new VoteContractImplContainer.VoteContractImplStub VoteContractStub => GetVoteContractTester(BootMinerKeyPair); - - internal new ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub => - GetProfitContractTester(BootMinerKeyPair); - - internal new ElectionContractImplContainer.ElectionContractImplStub ElectionContractStub => - GetElectionContractTester(BootMinerKeyPair); - - internal new AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub => - GetAEDPoSContractTester(BootMinerKeyPair); - - internal new TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => - GetTreasuryContractTester(BootMinerKeyPair); - - internal new ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetParliamentContractTester(BootMinerKeyPair); - - internal new EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => - GetEconomicContractTester(BootMinerKeyPair); - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetBasicContractTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } - - internal new TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } - - internal new TokenConverterContractImplContainer.TokenConverterContractImplStub GetTokenConverterContractTester( - ECKeyPair keyPair) - { - return GetTester(TokenConverterContractAddress, - keyPair); - } - - internal new VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) - { - return GetTester(VoteContractAddress, keyPair); - } - - internal new ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } - - internal new ElectionContractImplContainer.ElectionContractImplStub GetElectionContractTester(ECKeyPair keyPair) - { - return GetTester(ElectionContractAddress, keyPair); - } - - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetAEDPoSContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } - - internal new TreasuryContractImplContainer.TreasuryContractImplStub GetTreasuryContractTester(ECKeyPair keyPair) - { - return GetTester(TreasuryContractAddress, keyPair); - } - - internal new ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } - - internal new EconomicContractImplContainer.EconomicContractImplStub GetEconomicContractTester(ECKeyPair keyPair) - { - return GetTester(EconomicContractAddress, keyPair); - } + return GetTester(EconomicContractAddress, keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestConstants.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestConstants.cs index b2aadd8840..4c824fde63 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestConstants.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestConstants.cs @@ -1,13 +1,12 @@ -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public static class ElectionContractTestConstants { - public static class ElectionContractTestConstants - { - public const string NativeTokenSymbol = "ELF"; - public const long NativeTokenTotalSupply = 1_000_000_000_00000000; - public const string VoteTokenSymbol = "VOTE"; - public const long VoteTokenTotalSupply = 200_000_000_00000000; - - public const int Decimals = 8; - public const bool IsBurnable = true; - } + public const string NativeTokenSymbol = "ELF"; + public const long NativeTokenTotalSupply = 1_000_000_000_00000000; + public const string VoteTokenSymbol = "VOTE"; + public const long VoteTokenTotalSupply = 200_000_000_00000000; + + public const int Decimals = 8; + public const bool IsBurnable = true; } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestHelpers.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestHelpers.cs index 166ced6976..a2e65d62ba 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestHelpers.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestHelpers.cs @@ -1,108 +1,100 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; -using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; using Xunit.Abstractions; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests : ElectionContractTestBase { - public partial class ElectionContractTests : ElectionContractTestBase + private readonly ITestOutputHelper _testOutputHelper; + + public ElectionContractTests(ITestOutputHelper testOutputHelper) { - private readonly ITestOutputHelper _testOutputHelper; + _testOutputHelper = testOutputHelper; + InitializeContracts(); + } - public ElectionContractTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - InitializeContracts(); - } + [Fact] + public async Task ElectionContract_NextTerm_Test() + { + await NextTerm(InitialCoreDataCenterKeyPairs[0]); + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(2); + } - [Fact] - public async Task ElectionContract_NextTerm_Test() - { - await NextTerm(InitialCoreDataCenterKeyPairs[0]); - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(2); - } + [Fact] + public async Task ElectionContract_NormalBlock_Test() + { + await NormalBlock(InitialCoreDataCenterKeyPairs[0]); + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.GetMinedBlocks().ShouldBe(1); + round.GetMinedMiners().Count.ShouldBe(1); + } - [Fact] - public async Task ElectionContract_NormalBlock_Test() - { - await NormalBlock(InitialCoreDataCenterKeyPairs[0]); - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.GetMinedBlocks().ShouldBe(1); - round.GetMinedMiners().Count.ShouldBe(1); - } + private async Task AnnounceElectionAsync(ECKeyPair keyPair, Address candidateAdmin = null) + { + var electionStub = GetElectionContractTester(keyPair); + candidateAdmin ??= Address.FromPublicKey(keyPair.PublicKey); + var announceResult = (await electionStub.AnnounceElection.SendAsync(candidateAdmin)) + .TransactionResult; + return announceResult; + } - private async Task AnnounceElectionAsync(ECKeyPair keyPair, Address candidateAdmin = null) - { - var electionStub = GetElectionContractTester(keyPair); - candidateAdmin ??= Address.FromPublicKey(keyPair.PublicKey); - var announceResult = (await electionStub.AnnounceElection.SendAsync(candidateAdmin)) - .TransactionResult; - return announceResult; - } + private async Task QuitElectionAsync(ECKeyPair keyPair) + { + var electionStub = GetElectionContractTester(keyPair); + return (await electionStub.QuitElection.SendAsync(new StringValue { Value = keyPair.PublicKey.ToHex() })) + .TransactionResult; + } - private async Task QuitElectionAsync(ECKeyPair keyPair) + private async Task VoteToCandidate(ECKeyPair voterKeyPair, string candidatePublicKey, + int lockTime, long amount) + { + var electionStub = GetElectionContractTester(voterKeyPair); + var voteResult = (await electionStub.Vote.SendAsync(new VoteMinerInput { - var electionStub = GetElectionContractTester(keyPair); - return (await electionStub.QuitElection.SendAsync(new StringValue {Value = keyPair.PublicKey.ToHex()})) - .TransactionResult; - } + CandidatePubkey = candidatePublicKey, + Amount = amount, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime) + })).TransactionResult; - private async Task VoteToCandidate(ECKeyPair voterKeyPair, string candidatePublicKey, - int lockTime, long amount) - { - var electionStub = GetElectionContractTester(voterKeyPair); - var voteResult = (await electionStub.Vote.SendAsync(new VoteMinerInput - { - CandidatePubkey = candidatePublicKey, - Amount = amount, - EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime) - })).TransactionResult; + return voteResult; + } - return voteResult; - } - - private async Task VoteToCandidate(List votersKeyPairs, string candidatePublicKey, - int lockTime, long amount) - { - foreach (var voterKeyPair in votersKeyPairs) - { - await VoteToCandidate(voterKeyPair, candidatePublicKey, lockTime, amount); - } - } - - private async Task VoteToCandidates(List votersKeyPairs, List candidatesPublicKeys, - int lockTime, long amount) - { - foreach (var candidatePublicKey in candidatesPublicKeys) - { - await VoteToCandidate(votersKeyPairs, candidatePublicKey, lockTime, amount); - } - } + private async Task VoteToCandidate(List votersKeyPairs, string candidatePublicKey, + int lockTime, long amount) + { + foreach (var voterKeyPair in votersKeyPairs) + await VoteToCandidate(voterKeyPair, candidatePublicKey, lockTime, amount); + } - private async Task WithdrawVotes(ECKeyPair keyPair, Hash voteId) - { - var electionStub = GetElectionContractTester(keyPair); - return (await electionStub.Withdraw.SendAsync(voteId)).TransactionResult; - } + private async Task VoteToCandidates(List votersKeyPairs, List candidatesPublicKeys, + int lockTime, long amount) + { + foreach (var candidatePublicKey in candidatesPublicKeys) + await VoteToCandidate(votersKeyPairs, candidatePublicKey, lockTime, amount); + } - private async Task ChangeVoteOption(ECKeyPair keyPair, Hash voteId, string newOption) + private async Task WithdrawVotes(ECKeyPair keyPair, Hash voteId) + { + var electionStub = GetElectionContractTester(keyPair); + return (await electionStub.Withdraw.SendAsync(voteId)).TransactionResult; + } + + private async Task ChangeVoteOption(ECKeyPair keyPair, Hash voteId, string newOption) + { + var electionStub = GetElectionContractTester(keyPair); + return (await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput { - var electionStub = GetElectionContractTester(keyPair); - return (await electionStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - VoteId = voteId, - CandidatePubkey = newOption - })).TransactionResult; - } + VoteId = voteId, + CandidatePubkey = newOption + })).TransactionResult; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestModule.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestModule.cs index d9076dd81a..b741ae1c78 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestModule.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestModule.cs @@ -4,15 +4,14 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +[DependsOn(typeof(EconomicContractsTestModule))] +public class ElectionContractTestModule : EconomicContractsTestModule { - [DependsOn(typeof(EconomicContractsTestModule))] - public class ElectionContractTestModule : EconomicContractsTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.RemoveAll(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Full/MainChainMinerElection.cs b/test/AElf.Contracts.Election.Tests/Full/MainChainMinerElection.cs index 81497d4381..740870d7d7 100644 --- a/test/AElf.Contracts.Election.Tests/Full/MainChainMinerElection.cs +++ b/test/AElf.Contracts.Election.Tests/Full/MainChainMinerElection.cs @@ -6,72 +6,64 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task UserVote_And_GetProfitAmount_Test() { - [Fact] - public async Task UserVote_And_GetProfitAmount_Test() - { - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); - var moreVotesCandidates = ValidationDataCenterKeyPairs - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var kp in moreVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 2); - } - { - var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); - } - var lessVotesCandidates = ValidationDataCenterKeyPairs - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var kp in lessVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 1); - } - - { - var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount * 2); - } + var moreVotesCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var kp in moreVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 2); + { + var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); + } + var lessVotesCandidates = ValidationDataCenterKeyPairs + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var kp in lessVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], kp.PublicKey.ToHex(), 100 * 86400, 1); - { - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(1); - } + { + var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount * 2); + } - await ProduceBlocks(BootMinerKeyPair, 10); - await NextTerm(BootMinerKeyPair); + { + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(1); + } - { - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(2); - } + await ProduceBlocks(BootMinerKeyPair, 10); + await NextTerm(BootMinerKeyPair); - await ProduceBlocks(ValidationDataCenterKeyPairs[0], 10); - await NextTerm(ValidationDataCenterKeyPairs[0]); + { + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(2); + } - { - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(3); - } + await ProduceBlocks(ValidationDataCenterKeyPairs[0], 10); + await NextTerm(ValidationDataCenterKeyPairs[0]); - var profitTester = GetProfitContractTester(VoterKeyPairs[0]); - var profitBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], - Symbol = "ELF" - })).Value; - profitBalance.ShouldBeGreaterThan(24000000); + { + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(3); } + + var profitTester = GetProfitContractTester(VoterKeyPairs[0]); + var profitBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], + Symbol = "ELF" + })).Value; + profitBalance.ShouldBeGreaterThan(24000000); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Full/ReleaseProfitsFromTreasury.cs b/test/AElf.Contracts.Election.Tests/Full/ReleaseProfitsFromTreasury.cs index 0af46611a3..fe0d8fcf92 100644 --- a/test/AElf.Contracts.Election.Tests/Full/ReleaseProfitsFromTreasury.cs +++ b/test/AElf.Contracts.Election.Tests/Full/ReleaseProfitsFromTreasury.cs @@ -6,686 +6,671 @@ using AElf.Contracts.Profit; using AElf.CSharp.Core; using AElf.Kernel; -using AElf.Kernel.SmartContract.Application; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task CheckTreasuryProfitsDistribution_Test() { - [Fact] - public async Task CheckTreasuryProfitsDistribution_Test() + const long txFee = 0; + const long txSizeFeeUnitPrice = 0; + long rewardAmount; + var updatedBackupSubsidy = 0L; + var updatedBasicReward = 0L; + var updatedFlexibleReward = 0L; + var updatedCitizenWelfare = 0L; + + var treasuryScheme = + await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); + + // Prepare candidates and votes. { - const long txFee = 0; - const long txSizeFeeUnitPrice = 0; - long rewardAmount; - var updatedBackupSubsidy = 0L; - var updatedBasicReward = 0L; - var updatedFlexibleReward = 0L; - var updatedCitizenWelfare = 0L; + // SampleKeyPairs[13...47] announce election. + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); + + // Check the count of announce candidates. + var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); + candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + + // SampleKeyPairs[13...17] get 2 votes. + var moreVotesCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var keyPair in moreVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); + + // SampleKeyPairs[18...30] get 1 votes. + var lessVotesCandidates = ValidationDataCenterKeyPairs + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Take(EconomicContractsTestConstants.SupposedMinersCount - + EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var keyPair in lessVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 1); + + var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); + votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.SupposedMinersCount); + } - var treasuryScheme = - await ProfitContractStub.GetScheme.CallAsync(ProfitItemsIds[ProfitType.Treasury]); + // Produce 10 blocks and change term. + { + await ProduceBlocks(BootMinerKeyPair, 10); + await NextTerm(BootMinerKeyPair); + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(2); + } - // Prepare candidates and votes. + // Check released profits of first term. No one can receive released profits of first term. + { + rewardAmount = await GetReleasedAmount(); + const long currentPeriod = 1L; + + // Check balance of Treasury general ledger. { - // SampleKeyPairs[13...47] announce election. - foreach (var keyPair in ValidationDataCenterKeyPairs) + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await AnnounceElectionAsync(keyPair); - } + Owner = treasuryScheme.VirtualAddress, + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(0); + } - // Check the count of announce candidates. - var candidates = await ElectionContractStub.GetCandidates.CallAsync(new Empty()); - candidates.Value.Count.ShouldBe(ValidationDataCenterKeyPairs.Count); + // Backup subsidy. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); + releasedInformation.TotalShares.ShouldBe( + EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // SampleKeyPairs[13...17] get 2 votes. - var moreVotesCandidates = ValidationDataCenterKeyPairs - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var keyPair in moreVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); - } + // Amount of backup subsidy. + { + var amount = await GetProfitAmount(ProfitType.BackupSubsidy); + updatedBackupSubsidy += + rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + amount.ShouldBe(updatedBackupSubsidy); + } - // SampleKeyPairs[18...30] get 1 votes. - var lessVotesCandidates = ValidationDataCenterKeyPairs - .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) - .Take(EconomicContractsTestConstants.SupposedMinersCount - - EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var keyPair in lessVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 1); - } + // Basic reward. + { + var previousTermInformation = + AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 1 }).Result; + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + releasedInformation.TotalShares.ShouldBe( + previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks)); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 10 + rewardAmount / 20); + } - var votedCandidates = await ElectionContractStub.GetVotedCandidates.CallAsync(new Empty()); - votedCandidates.Value.Count.ShouldBe(EconomicContractsTestConstants.SupposedMinersCount); + // Amount of basic reward. + { + var amount = await GetProfitAmount(ProfitType.BasicMinerReward); + amount.ShouldBe(0); } - // Produce 10 blocks and change term. + // Flexible reward. { - await ProduceBlocks(BootMinerKeyPair, 10); - await NextTerm(BootMinerKeyPair); - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(2); + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + // Flexible rewards went to 17 new miners. + releasedInformation.TotalShares.ShouldBe(17); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); } - // Check released profits of first term. No one can receive released profits of first term. + // Amount of flexible reward. { - rewardAmount = await GetReleasedAmount(); - const long currentPeriod = 1L; + var amount = await GetProfitAmount(ProfitType.FlexibleReward); + amount.ShouldBe(rewardAmount / 20 / 17); + updatedFlexibleReward += rewardAmount / 20 / 17; + } - // Check balance of Treasury general ledger. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = treasuryScheme.VirtualAddress, - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(0); - } + // Welcome reward. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + // Welcome rewards went to Citizen Welfare Reward. + releasedInformation.TotalShares.ShouldBe(1); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // Backup subsidy. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); - releasedInformation.TotalShares.ShouldBe( - EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Amount of welcome reward. + { + var amount = await GetProfitAmount(ProfitType.WelcomeReward); + amount.ShouldBe(0); + } - // Amount of backup subsidy. - { - var amount = await GetProfitAmount(ProfitType.BackupSubsidy); - updatedBackupSubsidy += - rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - amount.ShouldBe(updatedBackupSubsidy); - } + // Citizen welfare. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + releasedInformation.TotalShares.ShouldBe(0); + // 75% + 5% + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(-rewardAmount * 3 / 4); + } - // Basic reward. - { - var previousTermInformation = - AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 1 }).Result; - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - releasedInformation.TotalShares.ShouldBe( - previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks)); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 10 + rewardAmount / 20); - } + // Amount of citizen welfare. + { + var amount = await GetProfitAmount(ProfitType.CitizenWelfare); + amount.ShouldBe(0); + } + } - // Amount of basic reward. - { - var amount = await GetProfitAmount(ProfitType.BasicMinerReward); - amount.ShouldBe(0); - } + await GenerateMiningReward(3); - // Flexible reward. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - // Flexible rewards went to 17 new miners. - releasedInformation.TotalShares.ShouldBe(17); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Check released profits of second term. + { + rewardAmount = await GetReleasedAmount(); + const long currentPeriod = 2L; - // Amount of flexible reward. + // Check balance of Treasury general ledger. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var amount = await GetProfitAmount(ProfitType.FlexibleReward); - amount.ShouldBe(rewardAmount / 20 / 17); - updatedFlexibleReward += rewardAmount / 20 / 17; - } + Owner = treasuryScheme.VirtualAddress, + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(0); + } - // Welcome reward. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - // Welcome rewards went to Citizen Welfare Reward. - releasedInformation.TotalShares.ShouldBe(1); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Backup subsidy. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); + releasedInformation.TotalShares.ShouldBe( + EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // Amount of welcome reward. - { - var amount = await GetProfitAmount(ProfitType.WelcomeReward); - amount.ShouldBe(0); - } + // Amount of backup subsidy. + { + var amount = await GetProfitAmount(ProfitType.BackupSubsidy); + updatedBackupSubsidy += + rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + amount.ShouldBe(updatedBackupSubsidy); + } - // Citizen welfare. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - releasedInformation.TotalShares.ShouldBe(0); - // 75% + 5% - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(-rewardAmount * 3 / 4); - } + // Basic reward. + { + var previousTermInformation = + AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 2 }).Result; + var totalProducedBlocks = + previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); + releasedInformation.TotalShares.ShouldBe(totalProducedBlocks); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 10 + rewardAmount / 20); + var amount = await GetProfitAmount(ProfitType.BasicMinerReward); + updatedBasicReward += releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] * + previousTermInformation + .RealTimeMinersInformation[ValidationDataCenterKeyPairs[0].PublicKey.ToHex()] + .ProducedBlocks / totalProducedBlocks; + amount.ShouldBe(updatedBasicReward); + } - // Amount of citizen welfare. - { - var amount = await GetProfitAmount(ProfitType.CitizenWelfare); - amount.ShouldBe(0); - } + // Flexible reward. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); + // Flexible rewards went to Basic Miner Reward. + releasedInformation.TotalShares.ShouldBe(1); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); } - await GenerateMiningReward(3); + // Welcome reward. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + releasedInformation.TotalShares.ShouldBe(1); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // Check released profits of second term. + // Amount of welcome reward. { - rewardAmount = await GetReleasedAmount(); - const long currentPeriod = 2L; + var amount = await GetProfitAmount(ProfitType.WelcomeReward); + amount.ShouldBe(0); + } - // Check balance of Treasury general ledger. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = treasuryScheme.VirtualAddress, - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(0); - } + // Citizen welfare. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount * 4 / 5); - // Backup subsidy. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); - releasedInformation.TotalShares.ShouldBe( - EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Amount of citizen welfare. + var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { Value = VoterKeyPairs[0].PublicKey.ToHex() }); + var electorWeights = electorVote.ActiveVotingRecords.Sum(r => r.Weight); + electorWeights.ShouldBe(releasedInformation.TotalShares); + var amount = await GetProfitAmount(ProfitType.CitizenWelfare); + updatedCitizenWelfare += electorWeights * rewardAmount * 3 / 4 / releasedInformation.TotalShares; + amount.ShouldBeLessThan(updatedCitizenWelfare); + } + } - // Amount of backup subsidy. - { - var amount = await GetProfitAmount(ProfitType.BackupSubsidy); - updatedBackupSubsidy += - rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - amount.ShouldBe(updatedBackupSubsidy); - } + await GenerateMiningReward(4); - // Basic reward. - { - var previousTermInformation = - AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 2 }).Result; - var totalProducedBlocks = - previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); - releasedInformation.TotalShares.ShouldBe(totalProducedBlocks); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 10 + rewardAmount / 20); - var amount = await GetProfitAmount(ProfitType.BasicMinerReward); - updatedBasicReward += releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] * - previousTermInformation - .RealTimeMinersInformation[ValidationDataCenterKeyPairs[0].PublicKey.ToHex()] - .ProducedBlocks / totalProducedBlocks; - amount.ShouldBe(updatedBasicReward); - } + // Check released profits of third term. + { + rewardAmount = await GetReleasedAmount(); + const long currentPeriod = 3L; - // Flexible reward. + // Check balance of Treasury general ledger. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); - // Flexible rewards went to Basic Miner Reward. - releasedInformation.TotalShares.ShouldBe(1); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + Owner = treasuryScheme.VirtualAddress, + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + }); + balance.Balance.ShouldBe(0); + } - // Welcome reward. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - releasedInformation.TotalShares.ShouldBe(1); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Backup subsidy. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); + releasedInformation.TotalShares.ShouldBe( + EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // Amount of welcome reward. - { - var amount = await GetProfitAmount(ProfitType.WelcomeReward); - amount.ShouldBe(0); - } + // Amount of backup subsidy. + { + var amount = await GetProfitAmount(ProfitType.BackupSubsidy); + updatedBackupSubsidy += + rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); + amount.ShouldBe(updatedBackupSubsidy); + } - // Citizen welfare. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount * 4 / 5); - - // Amount of citizen welfare. - var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue - { Value = VoterKeyPairs[0].PublicKey.ToHex() }); - var electorWeights = electorVote.ActiveVotingRecords.Sum(r => r.Weight); - electorWeights.ShouldBe(releasedInformation.TotalShares); - var amount = await GetProfitAmount(ProfitType.CitizenWelfare); - updatedCitizenWelfare += electorWeights * rewardAmount * 3 / 4 / releasedInformation.TotalShares; - amount.ShouldBeLessThan(updatedCitizenWelfare); - } + + // Flexible reward. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); + // Flexible rewards went to Basic Miner Reward. + releasedInformation.TotalShares.ShouldBe(1); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); } - await GenerateMiningReward(4); + // Amount of flexible reward. + { + var amount = await GetProfitAmount(ProfitType.FlexibleReward); + amount.ShouldBe(updatedFlexibleReward); + } - // Check released profits of third term. + // Welcome reward. { - rewardAmount = await GetReleasedAmount(); - const long currentPeriod = 3L; + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); + releasedInformation.IsReleased.ShouldBeTrue(); + releasedInformation.TotalShares.ShouldBe(1); + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 20); + } - // Check balance of Treasury general ledger. - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = treasuryScheme.VirtualAddress, - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - }); - balance.Balance.ShouldBe(0); - } + // Amount of welcome reward. + { + var amount = await GetProfitAmount(ProfitType.WelcomeReward); + amount.ShouldBe(0); + } - // Backup subsidy. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BackupSubsidy, currentPeriod); - releasedInformation.TotalShares.ShouldBe( - EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + // Basic reward. + { + var previousTermInformation = + AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 3 }).Result; + var totalProducedBlocks = + previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); + releasedInformation.TotalShares.ShouldBe(totalProducedBlocks); + // 10% + 5% (from Welcome Reward) + 5% (from Flexible Reward) + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount / 10 + rewardAmount / 20 + rewardAmount / 20); + var amount = await GetProfitAmount(ProfitType.BasicMinerReward); + updatedBasicReward += releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] * + previousTermInformation + .RealTimeMinersInformation[ValidationDataCenterKeyPairs[0].PublicKey.ToHex()] + .ProducedBlocks / totalProducedBlocks; + amount.ShouldBe(updatedBasicReward); + } - // Amount of backup subsidy. - { - var amount = await GetProfitAmount(ProfitType.BackupSubsidy); - updatedBackupSubsidy += - rewardAmount / 20 / (EconomicContractsTestConstants.InitialCoreDataCenterCount * 5); - amount.ShouldBe(updatedBackupSubsidy); - } + // Citizen welfare. + { + var releasedInformation = + await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); + // 75% + 5% (from Flexible Reward) + releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] + .ShouldBe(rewardAmount * 3 / 4); + + // Amount of citizen welfare. + var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { Value = VoterKeyPairs[0].PublicKey.ToHex() }); + var electorWeights = electorVote.ActiveVotingRecords.Sum(r => r.Weight); + electorWeights.ShouldBe(releasedInformation.TotalShares); + var amount = await GetProfitAmount(ProfitType.CitizenWelfare); + updatedCitizenWelfare += electorWeights * rewardAmount * 3 / 4 / releasedInformation.TotalShares; + amount.ShouldBeLessThan(updatedCitizenWelfare); + } + } + //query and profit voter vote profit + { + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(VoterKeyPairs[0].PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; - // Flexible reward. - { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.FlexibleReward, currentPeriod); - // Flexible rewards went to Basic Miner Reward. - releasedInformation.TotalShares.ShouldBe(1); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + var profitTester = GetProfitContractTester(VoterKeyPairs[0]); + var profitAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Value; + profitAmount.ShouldBeGreaterThan(0); + + var profitResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare] + }); + var txSize = profitResult.Transaction.Size(); + profitResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Address.FromPublicKey(VoterKeyPairs[0].PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; + afterBalance.ShouldBe(beforeBalance + profitAmount - txFee - txSize * txSizeFeeUnitPrice); + } + + await GenerateMiningReward(5); - // Amount of flexible reward. + //query and profit miner profit + { + foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants + .InitialCoreDataCenterCount)) + { + var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var amount = await GetProfitAmount(ProfitType.FlexibleReward); - amount.ShouldBe(updatedFlexibleReward); - } + Owner = Address.FromPublicKey(miner.PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; + + var profitTester = GetProfitContractTester(miner); - // Welcome reward. + //basic Shares - 40% + var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.WelcomeReward, currentPeriod); - releasedInformation.IsReleased.ShouldBeTrue(); - releasedInformation.TotalShares.ShouldBe(1); - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 20); - } + SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], + Symbol = "ELF" + })).Value; + basicMinerRewardAmount.ShouldBeGreaterThan(0); - // Amount of welcome reward. + //flexible Shares - 10% + var flexibleRewardWeight = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput { - var amount = await GetProfitAmount(ProfitType.WelcomeReward); - amount.ShouldBe(0); - } + SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], + Symbol = "ELF" + })).Value; + flexibleRewardWeight.ShouldBeGreaterThan(0); - // Basic reward. + //welcome Shares - 10% + var welcomeBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput { - var previousTermInformation = - AEDPoSContractStub.GetPreviousTermInformation.CallAsync(new Int64Value { Value = 3 }).Result; - var totalProducedBlocks = - previousTermInformation.RealTimeMinersInformation.Values.Sum(i => i.ProducedBlocks); - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.BasicMinerReward, currentPeriod); - releasedInformation.TotalShares.ShouldBe(totalProducedBlocks); - // 10% + 5% (from Welcome Reward) + 5% (from Flexible Reward) - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount / 10 + rewardAmount / 20 + rewardAmount / 20); - var amount = await GetProfitAmount(ProfitType.BasicMinerReward); - updatedBasicReward += releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] * - previousTermInformation - .RealTimeMinersInformation[ValidationDataCenterKeyPairs[0].PublicKey.ToHex()] - .ProducedBlocks / totalProducedBlocks; - amount.ShouldBe(updatedBasicReward); - } + SchemeId = ProfitItemsIds[ProfitType.WelcomeReward], + Symbol = "ELF" + })).Value; + welcomeBalance.ShouldBe(0); - // Citizen welfare. + //backup Shares - 20% + var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput { - var releasedInformation = - await GetDistributedProfitsInfo(ProfitType.CitizenWelfare, currentPeriod); - // 75% + 5% (from Flexible Reward) - releasedInformation.AmountsMap[EconomicContractsTestConstants.NativeTokenSymbol] - .ShouldBe(rewardAmount * 3 / 4); - - // Amount of citizen welfare. - var electorVote = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue - { Value = VoterKeyPairs[0].PublicKey.ToHex() }); - var electorWeights = electorVote.ActiveVotingRecords.Sum(r => r.Weight); - electorWeights.ShouldBe(releasedInformation.TotalShares); - var amount = await GetProfitAmount(ProfitType.CitizenWelfare); - updatedCitizenWelfare += electorWeights * rewardAmount * 3 / 4 / releasedInformation.TotalShares; - amount.ShouldBeLessThan(updatedCitizenWelfare); - } - } + SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], + Symbol = "ELF" + })).Value; + backupBalance.ShouldBeGreaterThan(0); - //query and profit voter vote profit - { - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //Profit all + var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput { - Owner = Address.FromPublicKey(VoterKeyPairs[0].PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; + SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward] + }); + var profitSize = profitBasicResult.Transaction.Size(); + profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var profitTester = GetProfitContractTester(VoterKeyPairs[0]); - var profitAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput { - SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Value; - profitAmount.ShouldBeGreaterThan(0); + SchemeId = ProfitItemsIds[ProfitType.FlexibleReward] + }); + var voteSize = voteResult.Transaction.Size(); + voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var profitResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput { - SchemeId = ProfitItemsIds[ProfitType.CitizenWelfare], + SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy] }); - var txSize = profitResult.Transaction.Size(); - profitResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var backSize = backupResult.Transaction.Size(); + backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var afterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var afterToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Owner = Address.FromPublicKey(VoterKeyPairs[0].PublicKey), + Owner = Address.FromPublicKey(miner.PublicKey), Symbol = EconomicContractsTestConstants.NativeTokenSymbol })).Balance; - afterBalance.ShouldBe(beforeBalance + profitAmount - txFee - txSize * txSizeFeeUnitPrice); + var sizeFees = (profitSize + voteSize + backSize) * txSizeFeeUnitPrice; + afterToken.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + + welcomeBalance + backupBalance - txFee * 3 - sizeFees); } + } - await GenerateMiningReward(5); + await GenerateMiningReward(6); - //query and profit miner profit + //query and profit miner profit + { + foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants + .InitialCoreDataCenterCount)) { - foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants - .InitialCoreDataCenterCount)) + var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(miner.PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; - - var profitTester = GetProfitContractTester(miner); + Owner = Address.FromPublicKey(miner.PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; - //basic Shares - 40% - var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], - Symbol = "ELF" - })).Value; - basicMinerRewardAmount.ShouldBeGreaterThan(0); + var profitTester = GetProfitContractTester(miner); - //flexible Shares - 10% - var flexibleRewardWeight = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], - Symbol = "ELF" - })).Value; - flexibleRewardWeight.ShouldBeGreaterThan(0); + //basic Shares - 10% + var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], + Symbol = "ELF" + })).Value; + basicMinerRewardAmount.ShouldBeGreaterThan(0); - //welcome Shares - 10% - var welcomeBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.WelcomeReward], - Symbol = "ELF" - })).Value; - welcomeBalance.ShouldBe(0); + //flexible Shares - 75% + var flexibleRewardWeight = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], + Symbol = "ELF" + })).Value; + flexibleRewardWeight.ShouldBe(0); - //backup Shares - 20% - var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], - Symbol = "ELF" - })).Value; - backupBalance.ShouldBeGreaterThan(0); + //welcome Shares - 5% + var welcomeBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.WelcomeReward], + Symbol = "ELF" + })).Value; + welcomeBalance.ShouldBe(0); - //Profit all - var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], - }); - var profitSize = profitBasicResult.Transaction.Size(); - profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + //backup Shares - 5% + var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput + { + SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], + Symbol = "ELF" + })).Value; + backupBalance.ShouldBeGreaterThan(0); - var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], - }); - var voteSize = voteResult.Transaction.Size(); - voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + //Profit all + var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward] + }); + var profitSize = profitBasicResult.Transaction.Size(); + profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], - }); - var backSize = backupResult.Transaction.Size(); - backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + long sizeFee; - var afterToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = Address.FromPublicKey(miner.PublicKey), Symbol = EconomicContractsTestConstants.NativeTokenSymbol })).Balance; - var sizeFees = (profitSize + voteSize + backSize) * txSizeFeeUnitPrice; - afterToken.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + - welcomeBalance + backupBalance - txFee * 3 - sizeFees); + sizeFee = profitSize * txSizeFeeUnitPrice; + balance.ShouldBe(beforeToken + basicMinerRewardAmount - txFee - sizeFee); + balance.ShouldBe(beforeToken + basicMinerRewardAmount - txFee); } - } - await GenerateMiningReward(6); + var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = ProfitItemsIds[ProfitType.FlexibleReward] + }); + var voteSize = voteResult.Transaction.Size(); + voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //query and profit miner profit - { - foreach (var miner in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants - .InitialCoreDataCenterCount)) { - var beforeToken = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var balance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = Address.FromPublicKey(miner.PublicKey), Symbol = EconomicContractsTestConstants.NativeTokenSymbol })).Balance; - - var profitTester = GetProfitContractTester(miner); - - //basic Shares - 10% - var basicMinerRewardAmount = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], - Symbol = "ELF" - })).Value; - basicMinerRewardAmount.ShouldBeGreaterThan(0); - - //flexible Shares - 75% - var flexibleRewardWeight = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], - Symbol = "ELF" - })).Value; - flexibleRewardWeight.ShouldBe(0); - - //welcome Shares - 5% - var welcomeBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.WelcomeReward], - Symbol = "ELF" - })).Value; - welcomeBalance.ShouldBe(0); - - //backup Shares - 5% - var backupBalance = (await profitTester.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], - Symbol = "ELF" - })).Value; - backupBalance.ShouldBeGreaterThan(0); - - //Profit all - var profitBasicResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.BasicMinerReward], - }); - var profitSize = profitBasicResult.Transaction.Size(); - profitBasicResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - long sizeFee; - - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(miner.PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; - sizeFee = profitSize * txSizeFeeUnitPrice; - balance.ShouldBe(beforeToken + basicMinerRewardAmount - txFee - sizeFee); - balance.ShouldBe(beforeToken + basicMinerRewardAmount - txFee); - } - - var voteResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + sizeFee = (profitSize + voteSize) * txSizeFeeUnitPrice; + balance1.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + - 2 * txFee - sizeFee); + } + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - SchemeId = ProfitItemsIds[ProfitType.FlexibleReward], - }); - var voteSize = voteResult.Transaction.Size(); - voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Owner = Address.FromPublicKey(miner.PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; + sizeFee = (profitSize + voteSize) * txSizeFeeUnitPrice; + balance.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + + welcomeBalance - 2 * txFee - sizeFee); + } - { - var balance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(miner.PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; - sizeFee = (profitSize + voteSize) * txSizeFeeUnitPrice; - balance1.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight - - 2 * txFee - sizeFee); - } - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(miner.PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; - sizeFee = (profitSize + voteSize) * txSizeFeeUnitPrice; - balance.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + - welcomeBalance - 2 * txFee - sizeFee); - } - - var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy], - }); - var backSize = backupResult.Transaction.Size(); - backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var backupResult = await profitTester.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = ProfitItemsIds[ProfitType.BackupSubsidy] + }); + var backSize = backupResult.Transaction.Size(); + backupResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Address.FromPublicKey(miner.PublicKey), - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Balance; - sizeFee = (profitSize + voteSize + backSize) * txSizeFeeUnitPrice; - balance.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + - welcomeBalance + backupBalance - 3 * txFee - sizeFee); - } + Owner = Address.FromPublicKey(miner.PublicKey), + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Balance; + sizeFee = (profitSize + voteSize + backSize) * txSizeFeeUnitPrice; + balance.ShouldBe(beforeToken + basicMinerRewardAmount + flexibleRewardWeight + + welcomeBalance + backupBalance - 3 * txFee - sizeFee); } } } + } - private async Task GenerateMiningReward(long supposedNextTermNumber) - { - for (var i = 0; i < EconomicContractsTestConstants.InitialCoreDataCenterCount; i++) - { - await ProduceBlocks(ValidationDataCenterKeyPairs[i], 10); - } - - await NextTerm(ValidationDataCenterKeyPairs[0]); - - var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - round.TermNumber.ShouldBe(supposedNextTermNumber); - } + private async Task GenerateMiningReward(long supposedNextTermNumber) + { + for (var i = 0; i < EconomicContractsTestConstants.InitialCoreDataCenterCount; i++) + await ProduceBlocks(ValidationDataCenterKeyPairs[i], 10); - private async Task GetDistributedProfitsInfo(ProfitType type, long period) - { - return await ProfitContractStub.GetDistributedProfitsInfo.CallAsync( - new SchemePeriod - { - SchemeId = ProfitItemsIds[type], - Period = period - }); - } + await NextTerm(ValidationDataCenterKeyPairs[0]); - private async Task GetProfitAmount(ProfitType type) - { - ProfitContractImplContainer.ProfitContractImplStub stub; - switch (type) - { - case ProfitType.CitizenWelfare: - stub = GetProfitContractTester(VoterKeyPairs[0]); - break; - default: - stub = GetProfitContractTester(ValidationDataCenterKeyPairs[0]); - break; - } + var round = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + round.TermNumber.ShouldBe(supposedNextTermNumber); + } - return (await stub.GetProfitAmount.CallAsync(new GetProfitAmountInput + private async Task GetDistributedProfitsInfo(ProfitType type, long period) + { + return await ProfitContractStub.GetDistributedProfitsInfo.CallAsync( + new SchemePeriod { SchemeId = ProfitItemsIds[type], - Symbol = EconomicContractsTestConstants.NativeTokenSymbol - })).Value; - } + Period = period + }); + } - private async Task GetReleasedAmount() - { - var previousRound = await AEDPoSContractStub.GetPreviousRoundInformation.CallAsync(new Empty()); - var minedBlocks = previousRound.GetMinedBlocks(); - return EconomicContractsTestConstants.ElfTokenPerBlock * minedBlocks; - } - - /// - /// Just to make sure not using double type. - /// - /// - /// - private long CalculateAverage(List list) + private async Task GetProfitAmount(ProfitType type) + { + ProfitContractImplContainer.ProfitContractImplStub stub; + switch (type) { - var sum = list.Sum(); - return sum.Div(list.Count); + case ProfitType.CitizenWelfare: + stub = GetProfitContractTester(VoterKeyPairs[0]); + break; + default: + stub = GetProfitContractTester(ValidationDataCenterKeyPairs[0]); + break; } - private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) + return (await stub.GetProfitAmount.CallAsync(new GetProfitAmountInput { - if (producedBlocksCount < averageProducedBlocksCount.Div(2)) - { - // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. - return 0; - } + SchemeId = ProfitItemsIds[type], + Symbol = EconomicContractsTestConstants.NativeTokenSymbol + })).Value; + } - if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) - { - // If count < (4/5) * average_count, then ratio will be (count / average_count) - return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); - } + private async Task GetReleasedAmount() + { + var previousRound = await AEDPoSContractStub.GetPreviousRoundInformation.CallAsync(new Empty()); + var minedBlocks = previousRound.GetMinedBlocks(); + return EconomicContractsTestConstants.ElfTokenPerBlock * minedBlocks; + } - return producedBlocksCount; - } + /// + /// Just to make sure not using double type. + /// + /// + /// + private long CalculateAverage(List list) + { + var sum = list.Sum(); + return sum.Div(list.Count); + } + + private long CalculateShares(long producedBlocksCount, long averageProducedBlocksCount) + { + if (producedBlocksCount < averageProducedBlocksCount.Div(2)) + // If count < (1/2) * average_count, then this node won't share Basic Miner Reward. + return 0; + + if (producedBlocksCount < averageProducedBlocksCount.Div(5).Mul(4)) + // If count < (4/5) * average_count, then ratio will be (count / average_count) + return producedBlocksCount.Mul(producedBlocksCount).Div(averageProducedBlocksCount); + + return producedBlocksCount; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/GQL/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/GQL/ElectionTests.cs index 4f9619c2c7..1630d63e80 100644 --- a/test/AElf.Contracts.Election.Tests/GQL/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/GQL/ElectionTests.cs @@ -13,516 +13,480 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public partial class ElectionContractTests { - public partial class ElectionContractTests + [Fact] + public async Task ElectionContract_InitializeTwice_Test() { - [Fact] - public async Task ElectionContract_InitializeTwice_Test() - { - var transactionResult = (await ElectionContractStub.InitialElectionContract.SendAsync( - new InitialElectionContractInput())).TransactionResult; + var transactionResult = (await ElectionContractStub.InitialElectionContract.SendAsync( + new InitialElectionContractInput())).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); - } - - [Fact] - public async Task ElectionContract_RegisterElectionVotingEvent_Register_Twice_Test() + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); + } + + [Fact] + public async Task ElectionContract_RegisterElectionVotingEvent_Register_Twice_Test() + { + var registerAgainRet = + await ElectionContractStub.RegisterElectionVotingEvent.SendAsync(new Empty()); + registerAgainRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + registerAgainRet.TransactionResult.Error.ShouldContain("Already registered."); + } + + [Fact] + public async Task ElectionContract_SetTreasurySchemeIds_SetTwice_Test() + { + var setSchemeIdRet = await ElectionContractStub.SetTreasurySchemeIds.SendAsync(new SetTreasurySchemeIdsInput { - var registerAgainRet = - await ElectionContractStub.RegisterElectionVotingEvent.SendAsync(new Empty()); - registerAgainRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - registerAgainRet.TransactionResult.Error.ShouldContain("Already registered."); - } - - [Fact] - public async Task ElectionContract_SetTreasurySchemeIds_SetTwice_Test() + SubsidyHash = HashHelper.ComputeFrom("Subsidy"), + TreasuryHash = HashHelper.ComputeFrom("Treasury"), + WelfareHash = HashHelper.ComputeFrom("Welfare"), + WelcomeHash = HashHelper.ComputeFrom("Welcome"), + FlexibleHash = HashHelper.ComputeFrom("Flexible") + }); + setSchemeIdRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setSchemeIdRet.TransactionResult.Error.ShouldContain("Treasury profit ids already set."); + } + + #region Vote + + [Fact] + public async Task ElectionContract_Vote_Failed_Test() + { + var candidateKeyPair = ValidationDataCenterKeyPairs[0]; + var voterKeyPair = VoterKeyPairs[0]; + + // candidateKeyPair not announced election yet. { - var setSchemeIdRet = await ElectionContractStub.SetTreasurySchemeIds.SendAsync(new SetTreasurySchemeIdsInput - { - SubsidyHash = HashHelper.ComputeFrom("Subsidy"), - TreasuryHash = HashHelper.ComputeFrom("Treasury"), - WelfareHash = HashHelper.ComputeFrom("Welfare"), - WelcomeHash = HashHelper.ComputeFrom("Welcome"), - FlexibleHash = HashHelper.ComputeFrom("Flexible"), - }); - setSchemeIdRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - setSchemeIdRet.TransactionResult.Error.ShouldContain("Treasury profit ids already set."); + var transactionResult = + await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 120 * 86400, 100); + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Candidate not found"); } - #region AnnounceElection + await AnnounceElectionAsync(candidateKeyPair); - [Fact] - public async Task ElectionContract_AnnounceElection_TokenNotEnough_Test() + // Voter token not enough { - var candidateKeyPair = VoterKeyPairs[0]; - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var voterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Owner = Address.FromPublicKey(candidateKeyPair.PublicKey), - Symbol = ElectionContractTestConstants.NativeTokenSymbol + Owner = Address.FromPublicKey(voterKeyPair.PublicKey), + Symbol = "ELF" })).Balance; - var tokenTester = GetTokenContractTester(candidateKeyPair); - await tokenTester.Transfer.SendAsync(new TransferInput - { - Symbol = ElectionContractTestConstants.NativeTokenSymbol, - Amount = balance / 2, - To = Address.FromPublicKey(VoterKeyPairs[1].PublicKey), - Memo = "transfer token to other" - }); - - var transactionResult = await AnnounceElectionAsync(candidateKeyPair); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Insufficient balance").ShouldBeTrue(); - } + var transactionResult = + await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 120 * 86400, voterBalance + 10); - [Fact] - public async Task ElectionContract_AnnounceElection_Twice_Test() - { - var s = Stopwatch.StartNew(); - s.Start(); - var candidateKeyPair = (await ElectionContract_AnnounceElection_Test())[0]; - var transactionResult = await AnnounceElectionAsync(candidateKeyPair); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("This public key already announced election."); - s.Stop(); - _testOutputHelper.WriteLine(s.ElapsedMilliseconds.ToString()); + transactionResult.Error.ShouldContain("Insufficient balance"); } - - [Fact] - public async Task ElectionContract_AnnounceElection_MinerAnnounce_Test() - { - var miner = InitialCoreDataCenterKeyPairs[0]; - var minerAnnounceRet = await AnnounceElectionAsync(miner); - minerAnnounceRet.Status.ShouldBe(TransactionResultStatus.Failed); - minerAnnounceRet.Error.ShouldContain("Initial miner cannot announce election."); - } - - #endregion - #region QuitElection - - [Fact] - public async Task ElectionContract_QuitElection_NotCandidate_Test() + // Lock time is less than 90 days { - var userKeyPair = Accounts[2].KeyPair; + var transactionResult = + await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 80 * 86400, 1000); - var transactionResult = await QuitElectionAsync(userKeyPair); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Target is not a candidate").ShouldBeTrue(); - } - - [Fact] - public async Task ElectionContract_QuitElection_MinerQuit_Test() - { - await NextRound(BootMinerKeyPair); - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var lockTime = 120 * 60 * 60 * 24; - var candidate = ValidationDataCenterKeyPairs.First(); - await AnnounceElectionAsync(candidate); - await VoteToCandidate(voter,candidate.PublicKey.ToHex(), lockTime, voteAmount); - var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); - victories.Value.Contains(ByteStringHelper.FromHexString(candidate.PublicKey.ToHex())).ShouldBeTrue(); - await NextTerm(InitialCoreDataCenterKeyPairs[0]); - var quitElectionRet = await QuitElectionAsync(candidate); - quitElectionRet.Status.ShouldBe(TransactionResultStatus.Failed); - quitElectionRet.Error.ShouldContain("Current miners cannot quit election"); + transactionResult.Error.ShouldContain("lock time"); } + } - #endregion + #endregion - #region Vote + #region Withdraw - [Fact] - public async Task ElectionContract_Vote_Failed_Test() + [Fact] + public async Task Election_Withdraw_In_LockTime_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var lockTime = 120 * 60 * 60 * 24; + var candidate = ValidationDataCenterKeyPairs.First(); + await AnnounceElectionAsync(candidate); + await VoteToCandidate(voter, candidate.PublicKey.ToHex(), lockTime, voteAmount); + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput { - var candidateKeyPair = ValidationDataCenterKeyPairs[0]; - var voterKeyPair = VoterKeyPairs[0]; + Voter = Address.FromPublicKey(voter.PublicKey), + VotingItemId = electionVoteItemId + }); + var voteId = voteIdOfVoter.ActiveVotes[0]; + var withdrawRet = await WithdrawVotes(voter, voteId); + withdrawRet.Status.ShouldBe(TransactionResultStatus.Failed); + withdrawRet.Error.ShouldContain("days to unlock your token"); + } - // candidateKeyPair not announced election yet. - { - var transactionResult = - await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 120 * 86400, 100); + #endregion - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Candidate not found"); - } + [Fact] + public async Task Election_TakeSnapshot_Without_Authority_Test() + { + var takeSnapshot = await ElectionContractStub.TakeSnapshot.SendAsync(new TakeElectionSnapshotInput + { + TermNumber = 1 + }); + takeSnapshot.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + takeSnapshot.TransactionResult.Error.ShouldContain("No permission"); + } - await AnnounceElectionAsync(candidateKeyPair); + [Fact] + public async Task Election_UpdateCandidateInformation_Without_Authority_Test() + { + var pubkey = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); + var transactionResult = (await ElectionContractStub.UpdateCandidateInformation.SendAsync( + new UpdateCandidateInformationInput + { + IsEvilNode = true, + Pubkey = pubkey, + RecentlyProducedBlocks = 10, + RecentlyMissedTimeSlots = 100 + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Only consensus contract can update candidate information"); + } - // Voter token not enough + [Fact] + public async Task Election_UpdateMultipleCandidateInformation_Without_Authority_Test() + { + var pubkey = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); + var updateInfo = new UpdateMultipleCandidateInformationInput + { + Value = { - var voterBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + new UpdateCandidateInformationInput { - Owner = Address.FromPublicKey(voterKeyPair.PublicKey), - Symbol = "ELF" - })).Balance; - var transactionResult = - await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 120 * 86400, voterBalance + 10); - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Insufficient balance"); - } - - // Lock time is less than 90 days - { - var transactionResult = - await VoteToCandidate(voterKeyPair, candidateKeyPair.PublicKey.ToHex(), 80 * 86400, 1000); - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("lock time"); + IsEvilNode = true, + Pubkey = pubkey, + RecentlyProducedBlocks = 10, + RecentlyMissedTimeSlots = 100 + } } - } + }; - #endregion + var transactionResult = (await ElectionContractStub.UpdateMultipleCandidateInformation.SendAsync(updateInfo) + ).TransactionResult; - #region Withdraw + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Only consensus contract can update candidate information"); + } - [Fact] - public async Task Election_Withdraw_In_LockTime_Test() + [Fact] + public async Task Election_UpdateMinersCount_Without_Authority_Test() + { + var transactionResult = (await ElectionContractStub.UpdateMinersCount.SendAsync(new UpdateMinersCountInput { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var lockTime = 120 * 60 * 60 * 24; - var candidate = ValidationDataCenterKeyPairs.First(); - await AnnounceElectionAsync(candidate); - await VoteToCandidate(voter,candidate.PublicKey.ToHex(), lockTime, voteAmount); - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter.PublicKey), - VotingItemId = electionVoteItemId - }); - var voteId = voteIdOfVoter.ActiveVotes[0]; - var withdrawRet = await WithdrawVotes(voter, voteId); - withdrawRet.Status.ShouldBe(TransactionResultStatus.Failed); - withdrawRet.Error.ShouldContain("days to unlock your token"); - } - #endregion + MinersCount = 10 + })).TransactionResult; - #region ChangeVotingOption + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Only consensus contract can update miners count"); + } - [Fact] - public async Task Election_ChangeVotingOption_Not_Voter_Test() + #region AnnounceElection + + [Fact] + public async Task ElectionContract_AnnounceElection_TokenNotEnough_Test() + { + var candidateKeyPair = VoterKeyPairs[0]; + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var lockTime = 120 * 60 * 60 * 24; - var candidate = ValidationDataCenterKeyPairs.First(); - await AnnounceElectionAsync(candidate); - await VoteToCandidate(voter,candidate.PublicKey.ToHex(), lockTime, voteAmount); - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter.PublicKey), - VotingItemId = electionVoteItemId - }); - var voteId = voteIdOfVoter.ActiveVotes[0]; - var changeOptionRet = await ElectionContractStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - CandidatePubkey = candidate.PublicKey.ToHex(), - VoteId = voteId - }); - changeOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - changeOptionRet.TransactionResult.Error.ShouldContain("No permission to change current vote's option."); - } - - [Fact] - public async Task Election_ChangeVotingOption_With_Expire_Vote_Test() + Owner = Address.FromPublicKey(candidateKeyPair.PublicKey), + Symbol = ElectionContractTestConstants.NativeTokenSymbol + })).Balance; + var tokenTester = GetTokenContractTester(candidateKeyPair); + await tokenTester.Transfer.SendAsync(new TransferInput { - var voter = VoterKeyPairs.First(); - var voteAmount = 100; - var lockTime = 120 * 60 * 60 * 24; - var candidate = ValidationDataCenterKeyPairs.First(); - await AnnounceElectionAsync(candidate); - await VoteToCandidate(voter,candidate.PublicKey.ToHex(), lockTime, voteAmount); - var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); - var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voter.PublicKey), - VotingItemId = electionVoteItemId - }); - var voteId = voteIdOfVoter.ActiveVotes[0]; - BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); - var changeOptionRet = await ChangeVoteOption(voter, voteId, candidate.PublicKey.ToHex()); - changeOptionRet.Status.ShouldBe(TransactionResultStatus.Failed); - changeOptionRet.Error.ShouldContain("This vote already expired"); - } - - [Fact] - public async Task ElectionContract_ChangeVoting_To_Invalid_Target() - { - var invalidCandidateKeyPair = "invalid key"; - var ret = await ElectionContractStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput - { - CandidatePubkey = invalidCandidateKeyPair, - VoteId = new Hash() - }); - var errorMsg = "Candidate not found."; - ret.TransactionResult.Error.ShouldContain(errorMsg); - } + Symbol = ElectionContractTestConstants.NativeTokenSymbol, + Amount = balance / 2, + To = Address.FromPublicKey(VoterKeyPairs[1].PublicKey), + Memo = "transfer token to other" + }); + + var transactionResult = await AnnounceElectionAsync(candidateKeyPair); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Insufficient balance").ShouldBeTrue(); + } - #endregion + [Fact] + public async Task ElectionContract_AnnounceElection_Twice_Test() + { + var s = Stopwatch.StartNew(); + s.Start(); + var candidateKeyPair = (await ElectionContract_AnnounceElection_Test())[0]; + var transactionResult = await AnnounceElectionAsync(candidateKeyPair); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("This public key already announced election."); + s.Stop(); + _testOutputHelper.WriteLine(s.ElapsedMilliseconds.ToString()); + } - #region GetVictories + [Fact] + public async Task ElectionContract_AnnounceElection_MinerAnnounce_Test() + { + var miner = InitialCoreDataCenterKeyPairs[0]; + var minerAnnounceRet = await AnnounceElectionAsync(miner); + minerAnnounceRet.Status.ShouldBe(TransactionResultStatus.Failed); + minerAnnounceRet.Error.ShouldContain("Initial miner cannot announce election."); + } - [Fact] - public async Task ElectionContract_GetVictories_NoCandidate_Test() - { - // To get previous round information. - await NextRound(BootMinerKeyPair); + #endregion - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + #region QuitElection - // Same as initial miners. - victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); - foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) - { - victories.ShouldContain(initialMiner); - } - } + [Fact] + public async Task ElectionContract_QuitElection_NotCandidate_Test() + { + var userKeyPair = Accounts[2].KeyPair; - [Fact] - public async Task ElectionContract_GetVictories_CandidatesNotEnough_Test() - { - // To get previous round information. - await NextRound(BootMinerKeyPair); + var transactionResult = await QuitElectionAsync(userKeyPair); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Target is not a candidate").ShouldBeTrue(); + } - var keyPairs = ValidationDataCenterKeyPairs - .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1).ToList(); - foreach (var keyPair in keyPairs) - { - await AnnounceElectionAsync(keyPair); - } + [Fact] + public async Task ElectionContract_QuitElection_MinerQuit_Test() + { + await NextRound(BootMinerKeyPair); + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var lockTime = 120 * 60 * 60 * 24; + var candidate = ValidationDataCenterKeyPairs.First(); + await AnnounceElectionAsync(candidate); + await VoteToCandidate(voter, candidate.PublicKey.ToHex(), lockTime, voteAmount); + var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); + victories.Value.Contains(ByteStringHelper.FromHexString(candidate.PublicKey.ToHex())).ShouldBeTrue(); + await NextTerm(InitialCoreDataCenterKeyPairs[0]); + var quitElectionRet = await QuitElectionAsync(candidate); + quitElectionRet.Status.ShouldBe(TransactionResultStatus.Failed); + quitElectionRet.Error.ShouldContain("Current miners cannot quit election"); + } - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + #endregion - // Same as initial miners. - victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); - foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) - { - victories.ShouldContain(initialMiner); - } - } + #region ChangeVotingOption - [Fact] - public async Task ElectionContract_GetVictories_NoValidCandidate_Test() + [Fact] + public async Task Election_ChangeVotingOption_Not_Voter_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var lockTime = 120 * 60 * 60 * 24; + var candidate = ValidationDataCenterKeyPairs.First(); + await AnnounceElectionAsync(candidate); + await VoteToCandidate(voter, candidate.PublicKey.ToHex(), lockTime, voteAmount); + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter.PublicKey), + VotingItemId = electionVoteItemId + }); + var voteId = voteIdOfVoter.ActiveVotes[0]; + var changeOptionRet = await ElectionContractStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput { - await NextRound(BootMinerKeyPair); + CandidatePubkey = candidate.PublicKey.ToHex(), + VoteId = voteId + }); + changeOptionRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + changeOptionRet.TransactionResult.Error.ShouldContain("No permission to change current vote's option."); + } - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + [Fact] + public async Task Election_ChangeVotingOption_With_Expire_Vote_Test() + { + var voter = VoterKeyPairs.First(); + var voteAmount = 100; + var lockTime = 120 * 60 * 60 * 24; + var candidate = ValidationDataCenterKeyPairs.First(); + await AnnounceElectionAsync(candidate); + await VoteToCandidate(voter, candidate.PublicKey.ToHex(), lockTime, voteAmount); + var electionVoteItemId = await ElectionContractStub.GetMinerElectionVotingItemId.CallAsync(new Empty()); + var voteIdOfVoter = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = Address.FromPublicKey(voter.PublicKey), + VotingItemId = electionVoteItemId + }); + var voteId = voteIdOfVoter.ActiveVotes[0]; + BlockTimeProvider.SetBlockTime(StartTimestamp.AddSeconds(lockTime + 1)); + var changeOptionRet = await ChangeVoteOption(voter, voteId, candidate.PublicKey.ToHex()); + changeOptionRet.Status.ShouldBe(TransactionResultStatus.Failed); + changeOptionRet.Error.ShouldContain("This vote already expired"); + } - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + [Fact] + public async Task ElectionContract_ChangeVoting_To_Invalid_Target() + { + var invalidCandidateKeyPair = "invalid key"; + var ret = await ElectionContractStub.ChangeVotingOption.SendAsync(new ChangeVotingOptionInput + { + CandidatePubkey = invalidCandidateKeyPair, + VoteId = new Hash() + }); + var errorMsg = "Candidate not found."; + ret.TransactionResult.Error.ShouldContain(errorMsg); + } - // Same as initial miners. - victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); - foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) - { - victories.ShouldContain(initialMiner); - } - } + #endregion - [Fact] - public async Task ElectionContract_ToBecomeValidationDataCenter_Test() - { - foreach (var keyPair in ValidationDataCenterKeyPairs.Take(25)) - { - await AnnounceElectionAsync(keyPair); - } - - //add new candidate and vote into data center - var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); - await AnnounceElectionAsync(newCandidate); + #region GetVictories - var voter = VoterKeyPairs.First(); - await - VoteToCandidate(voter, newCandidate.PublicKey.ToHex(), 100 * 86400, 200); + [Fact] + public async Task ElectionContract_GetVictories_NoCandidate_Test() + { + // To get previous round information. + await NextRound(BootMinerKeyPair); - var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); - victories.Value.Select(o=>o.ToHex()).ShouldContain(newCandidate.PublicKey.ToHex()); - } + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); - [Fact] - public async Task> ElectionContract_GetVictories_ValidCandidatesNotEnough_Test() - { - const int amount = 100; + // Same as initial miners. + victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); + foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) + victories.ShouldContain(initialMiner); + } - await NextRound(BootMinerKeyPair); + [Fact] + public async Task ElectionContract_GetVictories_CandidatesNotEnough_Test() + { + // To get previous round information. + await NextRound(BootMinerKeyPair); - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + var keyPairs = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1).ToList(); + foreach (var keyPair in keyPairs) await AnnounceElectionAsync(keyPair); - var candidates = (await ElectionContractStub.GetCandidates.CallAsync(new Empty())).Value; - foreach (var fullNodesKeyPair in ValidationDataCenterKeyPairs) - { - candidates.ShouldContain(ByteString.CopyFrom(fullNodesKeyPair.PublicKey)); - } + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); - var validCandidates = ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1).ToList(); - foreach (var keyPair in validCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, amount); - } + // Same as initial miners. + victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); + foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) + victories.ShouldContain(initialMiner); + } - foreach (var votedFullNodeKeyPair in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1)) - { - var votes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue - {Value = votedFullNodeKeyPair.PublicKey.ToHex()}); - votes.ObtainedActiveVotedVotesAmount.ShouldBe(amount); - } + [Fact] + public async Task ElectionContract_GetVictories_NoValidCandidate_Test() + { + await NextRound(BootMinerKeyPair); - foreach (var votedFullNodeKeyPair in ValidationDataCenterKeyPairs.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1)) - { - var votes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue - {Value = votedFullNodeKeyPair.PublicKey.ToHex()}); - votes.ObtainedActiveVotedVotesAmount.ShouldBe(0); - } + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); - // Victories should contain all valid candidates. - foreach (var validCandidate in validCandidates) - { - victories.ShouldContain(validCandidate.PublicKey.ToHex()); - } + // Same as initial miners. + victories.Count.ShouldBe(EconomicContractsTestConstants.InitialCoreDataCenterCount); + foreach (var initialMiner in InitialCoreDataCenterKeyPairs.Select(kp => kp.PublicKey.ToHex())) + victories.ShouldContain(initialMiner); + } - return victories; - } + [Fact] + public async Task ElectionContract_ToBecomeValidationDataCenter_Test() + { + foreach (var keyPair in ValidationDataCenterKeyPairs.Take(25)) await AnnounceElectionAsync(keyPair); - [Fact] - public async Task> ElectionContract_GetVictories_NotAllCandidatesGetVotes_Test() - { - await NextRound(BootMinerKeyPair); + //add new candidate and vote into data center + var newCandidate = ValidationDataCenterCandidateKeyPairs.First(); + await AnnounceElectionAsync(newCandidate); - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + var voter = VoterKeyPairs.First(); + await + VoteToCandidate(voter, newCandidate.PublicKey.ToHex(), 100 * 86400, 200); - var validCandidates = ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var keyPair in validCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 100); - } + var victories = await ElectionContractStub.GetVictories.CallAsync(new Empty()); + victories.Value.Select(o => o.ToHex()).ShouldContain(newCandidate.PublicKey.ToHex()); + } - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + [Fact] + public async Task> ElectionContract_GetVictories_ValidCandidatesNotEnough_Test() + { + const int amount = 100; - foreach (var validCandidate in validCandidates) - { - victories.ShouldContain(validCandidate.PublicKey.ToHex()); - } + await NextRound(BootMinerKeyPair); + + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); - return validCandidates; + var candidates = (await ElectionContractStub.GetCandidates.CallAsync(new Empty())).Value; + foreach (var fullNodesKeyPair in ValidationDataCenterKeyPairs) + candidates.ShouldContain(ByteString.CopyFrom(fullNodesKeyPair.PublicKey)); + + var validCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount - 1).ToList(); + foreach (var keyPair in validCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, amount); + + foreach (var votedFullNodeKeyPair in ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants + .InitialCoreDataCenterCount - 1)) + { + var votes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue + { Value = votedFullNodeKeyPair.PublicKey.ToHex() }); + votes.ObtainedActiveVotedVotesAmount.ShouldBe(amount); } - - public async Task> ElectionContract_GetVictories_ValidCandidatesEnough_Test() + + foreach (var votedFullNodeKeyPair in ValidationDataCenterKeyPairs.Skip(EconomicContractsTestConstants + .InitialCoreDataCenterCount - 1)) { - await NextRound(BootMinerKeyPair); + var votes = await ElectionContractStub.GetCandidateVote.CallAsync(new StringValue + { Value = votedFullNodeKeyPair.PublicKey.ToHex() }); + votes.ObtainedActiveVotedVotesAmount.ShouldBe(0); + } - foreach (var keyPair in ValidationDataCenterKeyPairs) - { - await AnnounceElectionAsync(keyPair); - } + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); - var moreVotesCandidates = ValidationDataCenterKeyPairs.Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var keyPair in moreVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); - } + // Victories should contain all valid candidates. + foreach (var validCandidate in validCandidates) victories.ShouldContain(validCandidate.PublicKey.ToHex()); - var lessVotesCandidates = ValidationDataCenterKeyPairs.Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount).Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); - foreach (var candidate in lessVotesCandidates) - { - await VoteToCandidate(VoterKeyPairs[0], candidate.PublicKey.ToHex(), 100 * 86400, 1); - } + return victories; + } - var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value - .Select(p => p.ToHex()).ToList(); + [Fact] + public async Task> ElectionContract_GetVictories_NotAllCandidatesGetVotes_Test() + { + await NextRound(BootMinerKeyPair); - foreach (var validCandidate in moreVotesCandidates) - { - victories.ShouldContain(validCandidate.PublicKey.ToHex()); - } + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); - return victories; - } + var validCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var keyPair in validCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 100); - #endregion + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); - [Fact] - public async Task Election_TakeSnapshot_Without_Authority_Test() - { - var takeSnapshot = await ElectionContractStub.TakeSnapshot.SendAsync(new TakeElectionSnapshotInput - { - TermNumber = 1 - }); - takeSnapshot.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - takeSnapshot.TransactionResult.Error.ShouldContain("No permission"); - } + foreach (var validCandidate in validCandidates) victories.ShouldContain(validCandidate.PublicKey.ToHex()); - [Fact] - public async Task Election_UpdateCandidateInformation_Without_Authority_Test() - { - var pubkey = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); - var transactionResult = (await ElectionContractStub.UpdateCandidateInformation.SendAsync( - new UpdateCandidateInformationInput - { - IsEvilNode = true, - Pubkey = pubkey, - RecentlyProducedBlocks = 10, - RecentlyMissedTimeSlots = 100 - })).TransactionResult; + return validCandidates; + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Only consensus contract can update candidate information"); - } - - [Fact] - public async Task Election_UpdateMultipleCandidateInformation_Without_Authority_Test() - { - var pubkey = ValidationDataCenterKeyPairs.First().PublicKey.ToHex(); - var updateInfo = new UpdateMultipleCandidateInformationInput - { - Value = - { - new UpdateCandidateInformationInput - { - IsEvilNode = true, - Pubkey = pubkey, - RecentlyProducedBlocks = 10, - RecentlyMissedTimeSlots = 100 - } - } - }; - - var transactionResult = (await ElectionContractStub.UpdateMultipleCandidateInformation.SendAsync(updateInfo) - ).TransactionResult; + public async Task> ElectionContract_GetVictories_ValidCandidatesEnough_Test() + { + await NextRound(BootMinerKeyPair); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Only consensus contract can update candidate information"); - } - - [Fact] - public async Task Election_UpdateMinersCount_Without_Authority_Test() - { - var transactionResult = (await ElectionContractStub.UpdateMinersCount.SendAsync(new UpdateMinersCountInput - { - MinersCount = 10 - })).TransactionResult; + foreach (var keyPair in ValidationDataCenterKeyPairs) await AnnounceElectionAsync(keyPair); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Only consensus contract can update miners count"); - } + var moreVotesCandidates = ValidationDataCenterKeyPairs + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var keyPair in moreVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], keyPair.PublicKey.ToHex(), 100 * 86400, 2); + + var lessVotesCandidates = ValidationDataCenterKeyPairs + .Skip(EconomicContractsTestConstants.InitialCoreDataCenterCount) + .Take(EconomicContractsTestConstants.InitialCoreDataCenterCount).ToList(); + foreach (var candidate in lessVotesCandidates) + await VoteToCandidate(VoterKeyPairs[0], candidate.PublicKey.ToHex(), 100 * 86400, 1); + + var victories = (await ElectionContractStub.GetVictories.CallAsync(new Empty())).Value + .Select(p => p.ToHex()).ToList(); + + foreach (var validCandidate in moreVotesCandidates) victories.ShouldContain(validCandidate.PublicKey.ToHex()); + + return victories; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ProfitContractConsts.cs b/test/AElf.Contracts.Election.Tests/ProfitContractConsts.cs index 0fd897e02b..3419aea6d1 100644 --- a/test/AElf.Contracts.Election.Tests/ProfitContractConsts.cs +++ b/test/AElf.Contracts.Election.Tests/ProfitContractConsts.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public class ProfitContractConsts { - public class ProfitContractConsts - { - public const int ProfitLimit = 10; - public const int DefaultExpiredPeriodNumber = 1; - } + public const int ProfitLimit = 10; + public const int DefaultExpiredPeriodNumber = 1; } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Types/MinerList.cs b/test/AElf.Contracts.Election.Tests/Types/MinerList.cs index 43bd4ca1bb..0ef019af8c 100644 --- a/test/AElf.Contracts.Election.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.Election.Tests/Types/MinerList.cs @@ -1,55 +1,50 @@ using System.Linq; using AElf.CSharp.Core.Extension; using AElf.Types; -using AElf.Sdk.CSharp; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; - } + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - public Hash GetMinersHash() + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var orderedMiners = Pubkeys.OrderBy(p => p); - return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; + } + + public Hash GetMinersHash() + { + var orderedMiners = Pubkeys.OrderBy(p => p); + return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Types/Round.cs b/test/AElf.Contracts.Election.Tests/Types/Round.cs index bcd24f1e8b..fe64c9774b 100644 --- a/test/AElf.Contracts.Election.Tests/Types/Round.cs +++ b/test/AElf.Contracts.Election.Tests/Types/Round.cs @@ -1,249 +1,225 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using AElf.Standards.ACS4; -using AElf.CSharp.Core; -using AElf.Kernel; using AElf.Types; -using AElf.Sdk.CSharp; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public long RoundId => + RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + + public Hash GetHash(bool isContainPreviousInValue = true) { - public long RoundId => - RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); + } - public Hash GetHash(bool isContainPreviousInValue = true) - { - return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); - } - - /// - /// This method is only available when the miners of this round is more than 1. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } - - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); - var distance = - (int) (firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - - firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) - .TotalMilliseconds; - return distance > 0 ? distance : -distance; - } + /// + /// This method is only available when the miners of this round is more than 1. + /// + /// + public int GetMiningInterval() + { + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; + + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); + var distance = + (int)(firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - + firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) + .TotalMilliseconds; + return distance > 0 ? distance : -distance; + } + + internal bool IsTimeSlotPassed(string publicKey, DateTime dateTime, + out MinerInRound minerInRound) + { + minerInRound = null; + var miningInterval = GetMiningInterval(); + if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; + minerInRound = RealTimeMinersInformation[publicKey]; + return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; + } - internal bool IsTimeSlotPassed(string publicKey, DateTime dateTime, - out MinerInRound minerInRound) + /// + /// If one node produced block this round or missed his time slot, + /// whatever how long he missed, we can give him a consensus command with new time slot + /// to produce a block (for terminating current round and start new round). + /// The schedule generated by this command will be cancelled + /// if this node executed blocks from other nodes. + /// Notice: + /// This method shouldn't return the expected mining time from round information. + /// To prevent this kind of misuse, this method will return a invalid timestamp + /// when this node hasn't missed his time slot. + /// + /// + public Timestamp ArrangeAbnormalMiningTime(string publicKey, DateTime dateTime, + int miningInterval = 0) + { + if (!RealTimeMinersInformation.ContainsKey(publicKey)) { - minerInRound = null; - var miningInterval = GetMiningInterval(); - if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; - minerInRound = RealTimeMinersInformation[publicKey]; - return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; + return new Timestamp { Seconds = long.MaxValue }; + ; } - /// - /// If one node produced block this round or missed his time slot, - /// whatever how long he missed, we can give him a consensus command with new time slot - /// to produce a block (for terminating current round and start new round). - /// The schedule generated by this command will be cancelled - /// if this node executed blocks from other nodes. - /// - /// Notice: - /// This method shouldn't return the expected mining time from round information. - /// To prevent this kind of misuse, this method will return a invalid timestamp - /// when this node hasn't missed his time slot. - /// - /// - public Timestamp ArrangeAbnormalMiningTime(string publicKey, DateTime dateTime, - int miningInterval = 0) + if (miningInterval == 0) miningInterval = GetMiningInterval(); + + if (!IsTimeSlotPassed(publicKey, dateTime, out var minerInRound) && minerInRound.OutValue == null) { - if (!RealTimeMinersInformation.ContainsKey(publicKey)) - { - return new Timestamp {Seconds = long.MaxValue};; - } - - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } - - if (!IsTimeSlotPassed(publicKey, dateTime, out var minerInRound) && minerInRound.OutValue == null) - { - return new Timestamp {Seconds = long.MaxValue};; - } - - if (GetExtraBlockProducerInformation().Pubkey == publicKey) - { - var distance = (GetExtraBlockMiningTime() - dateTime).TotalMilliseconds; - if (distance > 0) - { - return GetExtraBlockMiningTime().ToTimestamp(); - } - } - - if (RealTimeMinersInformation.ContainsKey(publicKey) && miningInterval > 0) - { - var distanceToRoundStartTime = (dateTime - GetStartTime()).TotalMilliseconds; - var missedRoundsCount = (int) (distanceToRoundStartTime / TotalMilliseconds(miningInterval)); - var expectedEndTime = GetExpectedEndTime(missedRoundsCount, miningInterval); - return expectedEndTime.ToDateTime().AddMilliseconds(minerInRound.Order * miningInterval).ToTimestamp(); - } - - // Never do the mining if this node has no privilege to mime or the mining interval is invalid. - return new Timestamp {Seconds = long.MaxValue};; + return new Timestamp { Seconds = long.MaxValue }; + ; } - - /// - /// Actually the expected mining time of the miner whose order is 1. - /// - /// - public DateTime GetStartTime() + + if (GetExtraBlockProducerInformation().Pubkey == publicKey) { - return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); + var distance = (GetExtraBlockMiningTime() - dateTime).TotalMilliseconds; + if (distance > 0) return GetExtraBlockMiningTime().ToTimestamp(); } - /// - /// This method for now is able to handle the situation of a miner keeping offline so many rounds, - /// by using missedRoundsCount. - /// - /// - /// - /// - /// - public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) + if (RealTimeMinersInformation.ContainsKey(publicKey) && miningInterval > 0) { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } - - var totalMilliseconds = TotalMilliseconds(miningInterval); - return GetStartTime().AddMilliseconds(totalMilliseconds) - // Arrange an ending time if this node missed so many rounds. - .AddMilliseconds(missedRoundsCount * totalMilliseconds) - .ToTimestamp(); + var distanceToRoundStartTime = (dateTime - GetStartTime()).TotalMilliseconds; + var missedRoundsCount = (int)(distanceToRoundStartTime / TotalMilliseconds(miningInterval)); + var expectedEndTime = GetExpectedEndTime(missedRoundsCount, miningInterval); + return expectedEndTime.ToDateTime().AddMilliseconds(minerInRound.Order * miningInterval).ToTimestamp(); } - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + // Never do the mining if this node has no privilege to mime or the mining interval is invalid. + return new Timestamp { Seconds = long.MaxValue }; + ; + } - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } - - public MinerInRound GetExtraBlockProducerInformation() - { - return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; - } - - public DateTime GetExtraBlockMiningTime() - { - return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value - .ExpectedMiningTime.ToDateTime() - .AddMilliseconds(GetMiningInterval()); - } + /// + /// Actually the expected mining time of the miner whose order is 1. + /// + /// + public DateTime GetStartTime() + { + return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); + } - /// - /// Maybe tune other miners' supposed order of next round, - /// will record this purpose to their FinalOrderOfNextRound field. - /// - /// - /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) - { - if (!RealTimeMinersInformation.ContainsKey(pubkey)) - { - return null; - } - - var minerInRound = RealTimeMinersInformation[pubkey]; - - var tuneOrderInformation = RealTimeMinersInformation.Values - .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) - .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); - - var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => - v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) - .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); - - var minersPreviousInValues = - RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( - info => info.Pubkey, - info => info.PreviousInValue); - - return new UpdateValueInput - { - OutValue = minerInRound.OutValue, - Signature = minerInRound.Signature, - PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, - RoundId = RoundId, - ProducedBlocks = minerInRound.ProducedBlocks, - ActualMiningTime = minerInRound.ActualMiningTimes.First(), - SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, - TuneOrderInformation = {tuneOrderInformation}, - EncryptedPieces = {minerInRound.EncryptedPieces}, - DecryptedPieces = {decryptedPreviousInValues}, - MinersPreviousInValues = {minersPreviousInValues} - }; - } + /// + /// This method for now is able to handle the situation of a miner keeping offline so many rounds, + /// by using missedRoundsCount. + /// + /// + /// + /// + /// + public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); + + var totalMilliseconds = TotalMilliseconds(miningInterval); + return GetStartTime().AddMilliseconds(totalMilliseconds) + // Arrange an ending time if this node missed so many rounds. + .AddMilliseconds(missedRoundsCount * totalMilliseconds) + .ToTimestamp(); + } - public long GetMinedBlocks() + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); + + return RealTimeMinersInformation.Count * miningInterval + miningInterval; + } + + public MinerInRound GetExtraBlockProducerInformation() + { + return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; + } + + public DateTime GetExtraBlockMiningTime() + { + return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value + .ExpectedMiningTime.ToDateTime() + .AddMilliseconds(GetMiningInterval()); + } + + /// + /// Maybe tune other miners' supposed order of next round, + /// will record this purpose to their FinalOrderOfNextRound field. + /// + /// + /// + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) + { + if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; + + var minerInRound = RealTimeMinersInformation[pubkey]; + + var tuneOrderInformation = RealTimeMinersInformation.Values + .Where(m => m.FinalOrderOfNextRound != m.SupposedOrderOfNextRound) + .ToDictionary(m => m.Pubkey, m => m.FinalOrderOfNextRound); + + var decryptedPreviousInValues = RealTimeMinersInformation.Values.Where(v => + v.Pubkey != pubkey && v.DecryptedPieces.ContainsKey(pubkey)) + .ToDictionary(info => info.Pubkey, info => info.DecryptedPieces[pubkey]); + + var minersPreviousInValues = + RealTimeMinersInformation.Values.Where(info => info.PreviousInValue != null).ToDictionary( + info => info.Pubkey, + info => info.PreviousInValue); + + return new UpdateValueInput { - return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); - } + OutValue = minerInRound.OutValue, + Signature = minerInRound.Signature, + PreviousInValue = minerInRound.PreviousInValue ?? Hash.Empty, + RoundId = RoundId, + ProducedBlocks = minerInRound.ProducedBlocks, + ActualMiningTime = minerInRound.ActualMiningTimes.First(), + SupposedOrderOfNextRound = minerInRound.SupposedOrderOfNextRound, + TuneOrderInformation = { tuneOrderInformation }, + EncryptedPieces = { minerInRound.EncryptedPieces }, + DecryptedPieces = { decryptedPreviousInValues }, + MinersPreviousInValues = { minersPreviousInValues } + }; + } + + public long GetMinedBlocks() + { + return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); + } - private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + { + var minersInformation = new Dictionary(); + foreach (var minerInRound in RealTimeMinersInformation.Clone()) { - var minersInformation = new Dictionary(); - foreach (var minerInRound in RealTimeMinersInformation.Clone()) - { - var checkableMinerInRound = minerInRound.Value.Clone(); - checkableMinerInRound.EncryptedPieces.Clear(); - checkableMinerInRound.ActualMiningTimes.Clear(); - if (!isContainPreviousInValue) - { - checkableMinerInRound.PreviousInValue = Hash.Empty; - } - - minersInformation.Add(minerInRound.Key, checkableMinerInRound); - } - - var checkableRound = new Round - { - RoundNumber = RoundNumber, - TermNumber = TermNumber, - RealTimeMinersInformation = {minersInformation}, - BlockchainAge = BlockchainAge - }; - return checkableRound.ToByteArray(); + var checkableMinerInRound = minerInRound.Value.Clone(); + checkableMinerInRound.EncryptedPieces.Clear(); + checkableMinerInRound.ActualMiningTimes.Clear(); + if (!isContainPreviousInValue) checkableMinerInRound.PreviousInValue = Hash.Empty; + + minersInformation.Add(minerInRound.Key, checkableMinerInRound); } - - private static int GetAbsModulus(long longValue, int intValue) + + var checkableRound = new Round { - return Math.Abs((int) longValue % intValue); - } + RoundNumber = RoundNumber, + TermNumber = TermNumber, + RealTimeMinersInformation = { minersInformation }, + BlockchainAge = BlockchainAge + }; + return checkableRound.ToByteArray(); + } + + private static int GetAbsModulus(long longValue, int intValue) + { + return Math.Abs((int)longValue % intValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.Election.Tests/Types/Round_Generation.cs index a1680b677a..567ca6cf6a 100644 --- a/test/AElf.Contracts.Election.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Election.Tests/Types/Round_Generation.cs @@ -1,103 +1,95 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound) { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, out Round nextRound) - { - nextRound = new Round(); + nextRound = new Round(); - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + nextRound.BlockchainAge = RoundNumber == 1 ? 1 : (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + { + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; + } - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + { + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots + 1 - }; - } + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + 1 + }; + } - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; - return true; - } - - private int CalculateNextExtraBlockProducerOrder() - { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) - { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } + return true; + } - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToByteArray().ToInt64(true); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; - } - - public List GetMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); - } - - public List GetNotMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); - } + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; + + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToByteArray().ToInt64(true); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } + + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } + + public List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/VoteContractConsts.cs b/test/AElf.Contracts.Election.Tests/VoteContractConsts.cs index 08a2e81ba1..3b57629ac2 100644 --- a/test/AElf.Contracts.Election.Tests/VoteContractConsts.cs +++ b/test/AElf.Contracts.Election.Tests/VoteContractConsts.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Election +namespace AElf.Contracts.Election; + +public class VoteContractConsts { - public class VoteContractConsts - { - public const int MaxActiveDays = 100; + public const int MaxActiveDays = 100; - public const int OptionLengthLimit = 50; - } + public const int OptionLengthLimit = 50; } \ No newline at end of file diff --git a/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj b/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj index c44c752ca7..35e9d43a26 100644 --- a/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj +++ b/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj @@ -10,13 +10,13 @@ - + false Contract PreserveNewest - + false Contract @@ -24,12 +24,12 @@ - - - - - - + + + + + + @@ -43,7 +43,7 @@ Protobuf\Proto\transaction_fee.proto - - - + + + \ No newline at end of file diff --git a/test/AElf.Contracts.Genesis.Tests/GenesisContractAuthTest.cs b/test/AElf.Contracts.Genesis.Tests/GenesisContractAuthTest.cs index 0d4c5792c1..e7bb85515b 100644 --- a/test/AElf.Contracts.Genesis.Tests/GenesisContractAuthTest.cs +++ b/test/AElf.Contracts.Genesis.Tests/GenesisContractAuthTest.cs @@ -2,1342 +2,1349 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Association; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.CodeCheck.Infrastructure; using AElf.Kernel.Token; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; using CreateOrganizationInput = AElf.Contracts.Parliament.CreateOrganizationInput; -using ProposalCreated = AElf.Standards.ACS3.ProposalCreated; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public class GenesisContractAuthTest : BasicContractZeroTestBase { - public class GenesisContractAuthTest : BasicContractZeroTestBase + [Fact] + public async Task SetInitialController_Failed_Test() { - #region Main Chain + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.SetInitialControllerAddress), + ParliamentAddress); + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.ShouldContain("Genesis owner already initialized"); + } - [Fact] - public async Task Initialize_AlreadyExist_Test() - { - { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.Initialize), new InitializeInput - { - ContractDeploymentAuthorityRequired = false - }); - - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.ShouldContain("Contract zero already initialized."); - } + [Fact] + public async Task SetContractProposerRequiredState_Failed_Test() + { + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.SetContractProposerRequiredState), + ParliamentAddress); + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.ShouldContain("Genesis contract already initialized"); + } - { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController), - new AuthorityInfo() - { - OwnerAddress = SampleAddress.AddressList[0], - ContractAddress = BasicContractZeroAddress - }); - - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.ShouldContain("Unauthorized behavior."); - } - } + #region Main Chain - [Fact] - public async Task DeploySystemContract_Test() - { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySystemSmartContract), new SystemContractDeploymentInput() - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) - }); - - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.ShouldContain("System contract deployment failed."); - } - - [Fact] - public async Task DeploySmartContracts_Test() + [Fact] + public async Task Initialize_AlreadyExist_Test() + { { - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - // propose contract code - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - - { - var noPermissionCodeCheckProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeContractCodeCheck), new ContractCodeCheckInput - { - ProposedContractInputHash = proposedContractInputHash - }); - noPermissionCodeCheckProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - noPermissionCodeCheckProposingTxResult.Error.ShouldContain("Unauthorized behavior."); - } - - { - // not proposed - var releaseNotExistApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = HashHelper.ComputeFrom("Random") - }); - releaseNotExistApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseNotExistApprovedContractTxResult.Error.ShouldContain("Invalid contract proposing status."); - } - - { - // wrong sender - var releaseApprovedContractWithWrongSenderTx = await Tester.GenerateTransactionAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), AnotherMinerKeyPair, new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); - var blockReturnSet = await Tester.MineAsync(new List - {releaseApprovedContractWithWrongSenderTx}); - var noPermissionProposingTxResult = - blockReturnSet.TransactionResultMap[releaseApprovedContractWithWrongSenderTx.GetHash()]; - noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - noPermissionProposingTxResult.Error.ShouldContain("Invalid contract proposing status."); - } - - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.Initialize), new InitializeInput { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash + ContractDeploymentAuthorityRequired = false }); - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - codeCheckProposalId.ShouldNotBeNull(); - - { - var releaseAlreadyApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); - releaseAlreadyApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - releaseAlreadyApprovedContractTxResult.Error.ShouldContain("Invalid contract proposing status."); - } - - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - { - var releaseNotProposedContract = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - { - ProposedContractInputHash = HashHelper.ComputeFrom("Random"), - ProposalId = codeCheckProposalId - }); - releaseNotProposedContract.Status.ShouldBe(TransactionResultStatus.Failed); - releaseNotProposedContract.Error.ShouldContain("Invalid contract proposing status."); - } - - { - var contractCodeCheckController = await GetContractCodeCheckController(Tester, BasicContractZeroAddress); - - var deploymentProposalId = await CreateProposalAsync(Tester, ParliamentAddress, - contractCodeCheckController.OwnerAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySmartContract), - contractDeploymentInput); - await ApproveWithMinersAsync(Tester, ParliamentAddress, deploymentProposalId); - var releaseTx = await ReleaseProposalAsync(Tester, ParliamentAddress, deploymentProposalId); - releaseTx.Status.ShouldBe(TransactionResultStatus.Failed); - releaseTx.Error.ShouldContain("Invalid contract proposing status."); - } + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.ShouldContain("Contract zero already initialized."); + } - { - var incorrectContractDeploymentInput = new ContractDeploymentInput + { + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController), + new AuthorityInfo { - Category = KernelConstants.CodeCoverageRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - var contractCodeCheckController = await GetContractCodeCheckController(Tester, BasicContractZeroAddress); - - var deploymentProposalId = await CreateProposalAsync(Tester, ParliamentAddress, - contractCodeCheckController.OwnerAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySmartContract), - incorrectContractDeploymentInput); - await ApproveWithMinersAsync(Tester, ParliamentAddress, deploymentProposalId); - var releaseTx = await ReleaseProposalAsync(Tester, ParliamentAddress, deploymentProposalId); - releaseTx.Status.ShouldBe(TransactionResultStatus.Failed); - releaseTx.Error.ShouldContain("Contract proposing data not found."); - } - + OwnerAddress = SampleAddress.AddressList[0], + ContractAddress = BasicContractZeroAddress + }); - { - var releaseCodeCheckWithWrongSenderTx = await Tester.GenerateTransactionAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseCodeCheckedContract), AnotherMinerKeyPair, new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); - var blockReturnSet = await Tester.MineAsync(new List - {releaseCodeCheckWithWrongSenderTx}); - var noPermissionProposingTxResult = - blockReturnSet.TransactionResultMap[releaseCodeCheckWithWrongSenderTx.GetHash()]; - noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - noPermissionProposingTxResult.Error.ShouldContain("Invalid contract proposing status."); - } - - // release code check proposal and deployment completes - var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var creator = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].Indexed[0]).Author; - creator.ShouldBe(BasicContractZeroAddress); - var deployAddress = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Address; - deployAddress.ShouldNotBeNull(); - - var contractVersion = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Version; - contractVersion.ShouldBe(1); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), deployAddress)); - contractInfo.Version.ShouldBe(1); - contractInfo.Author.ShouldBe(BasicContractZeroAddress); - - { - var releaseContractAlreadyFinished = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - { - ProposedContractInputHash = proposedContractInputHash, - ProposalId = codeCheckProposalId - }); - releaseContractAlreadyFinished.Status.ShouldBe(TransactionResultStatus.Failed); - releaseContractAlreadyFinished.Error.ShouldContain("Invalid contract proposing status."); - } + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.ShouldContain("Unauthorized behavior."); } + } - [Fact] - public async Task Propose_MultiTimes() - { - var contractDeploymentInput = new ContractDeploymentInput + [Fact] + public async Task DeploySystemContract_Test() + { + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySystemSmartContract), + new SystemContractDeploymentInput { Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) + }); - var utcNow = TimestampHelper.GetUtcNow(); - // propose contract code - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - - var secondProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - secondProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.ShouldContain("System contract deployment failed."); + } - var thirdProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow.AddSeconds(86399)); - thirdProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + [Fact] + public async Task DeploySmartContracts_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + // propose contract code + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var forthProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow.AddSeconds(86400)); - forthProposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var noPermissionCodeCheckProposingTxResult = await Tester.ExecuteContractWithMiningAsync( + BasicContractZeroAddress, + nameof(BasicContractZero.ProposeContractCodeCheck), new ContractCodeCheckInput + { + ProposedContractInputHash = proposedContractInputHash + }); + noPermissionCodeCheckProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + noPermissionCodeCheckProposingTxResult.Error.ShouldContain("Unauthorized behavior."); } - - [Fact] - public async Task Deploy_MultiTimes() { - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - { - var address = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); - address.ShouldNotBeNull(); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), address)); - contractInfo.Version.ShouldBe(1); - } - - { - // Deployment of the same contract code will fail and return null address - var address = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); - address.ShouldBeNull(); - } - - { - var newContractDeploymentInput = new ContractDeploymentInput + // not proposed + var releaseNotExistApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync( + BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Configuration")).Value) - }; - - var otherTester = Tester.CreateNewContractTester(AnotherUserKeyPair); - var proposingTxResult = await otherTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), newContractDeploymentInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - proposingTxResult.Error.ShouldContain("Unauthorized to propose."); - } + ProposalId = proposalId, + ProposedContractInputHash = HashHelper.ComputeFrom("Random") + }); + releaseNotExistApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseNotExistApprovedContractTxResult.Error.ShouldContain("Invalid contract proposing status."); } - [Fact] - public async Task UpdateSmartContract_SameCode_Test() { - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); - contractInfo.Version.ShouldBe(1); - var contractUpdateInput = new ContractUpdateInput - { - Address = newAddress, - Code = contractDeploymentInput.Code - }; - - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + // wrong sender + var releaseApprovedContractWithWrongSenderTx = await Tester.GenerateTransactionAsync( + BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), AnotherMinerKeyPair, new ReleaseContractInput { ProposalId = proposalId, ProposedContractInputHash = proposedContractInputHash }); - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - codeCheckProposalId.ShouldNotBeNull(); - - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - updateResult.Status.ShouldBe(TransactionResultStatus.Failed); - updateResult.Error.ShouldContain("Code is not changed."); + var blockReturnSet = await Tester.MineAsync(new List + { releaseApprovedContractWithWrongSenderTx }); + var noPermissionProposingTxResult = + blockReturnSet.TransactionResultMap[releaseApprovedContractWithWrongSenderTx.GetHash()]; + noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + noPermissionProposingTxResult.Error.ShouldContain("Invalid contract proposing status."); } - - [Fact] - public async Task UpdateSmartContract_NewCodeExists_Test() - { - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - - var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); - contractInfo.Version.ShouldBe(1); - - var contractDeploymentInput2 = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Genesis")).Value) - }; - await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput2); - var contractUpdateInput = new ContractUpdateInput + + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Address = newAddress, - Code = contractDeploymentInput2.Code - }; + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + codeCheckProposalId.ShouldNotBeNull(); - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + { + var releaseAlreadyApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync( + BasicContractZeroAddress, nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { ProposalId = proposalId, ProposedContractInputHash = proposedContractInputHash }); - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - codeCheckProposalId.ShouldNotBeNull(); - - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + releaseAlreadyApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + releaseAlreadyApprovedContractTxResult.Error.ShouldContain("Invalid contract proposing status."); + } + + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + + { + var releaseNotProposedContract = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - updateResult.Status.ShouldBe(TransactionResultStatus.Failed); - updateResult.Error.ShouldContain("Same code has been deployed before."); + { + ProposedContractInputHash = HashHelper.ComputeFrom("Random"), + ProposalId = codeCheckProposalId + }); + releaseNotProposedContract.Status.ShouldBe(TransactionResultStatus.Failed); + releaseNotProposedContract.Error.ShouldContain("Invalid contract proposing status."); + } + + { + var contractCodeCheckController = await GetContractCodeCheckController(Tester, BasicContractZeroAddress); + + var deploymentProposalId = await CreateProposalAsync(Tester, ParliamentAddress, + contractCodeCheckController.OwnerAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySmartContract), + contractDeploymentInput); + await ApproveWithMinersAsync(Tester, ParliamentAddress, deploymentProposalId); + var releaseTx = await ReleaseProposalAsync(Tester, ParliamentAddress, deploymentProposalId); + releaseTx.Status.ShouldBe(TransactionResultStatus.Failed); + releaseTx.Error.ShouldContain("Invalid contract proposing status."); } - [Fact] - public async Task UpdateSmartContract_Test() { - var contractDeploymentInput = new ContractDeploymentInput + var incorrectContractDeploymentInput = new ContractDeploymentInput { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Category = KernelConstants.CodeCoverageRunnerCategory, // test the default runner Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) }; - var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); - contractInfo.Version.ShouldBe(1); - var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; - var contractUpdateInput = new ContractUpdateInput - { - Address = newAddress, - Code = ByteString.CopyFrom(code) - }; + var contractCodeCheckController = await GetContractCodeCheckController(Tester, BasicContractZeroAddress); - { - var addressNotExistProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), new ContractUpdateInput - { - Address = AnotherMinerAddress, - Code = ByteString.CopyFrom(code) - }); - addressNotExistProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - addressNotExistProposingTxResult.Error.ShouldContain("Contract not found."); - } - - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var secondTxProposingResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - secondTxProposingResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + var deploymentProposalId = await CreateProposalAsync(Tester, ParliamentAddress, + contractCodeCheckController.OwnerAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.DeploySmartContract), + incorrectContractDeploymentInput); + await ApproveWithMinersAsync(Tester, ParliamentAddress, deploymentProposalId); + var releaseTx = await ReleaseProposalAsync(Tester, ParliamentAddress, deploymentProposalId); + releaseTx.Status.ShouldBe(TransactionResultStatus.Failed); + releaseTx.Error.ShouldContain("Contract proposing data not found."); + } + + + { + var releaseCodeCheckWithWrongSenderTx = await Tester.GenerateTransactionAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseCodeCheckedContract), AnotherMinerKeyPair, new ReleaseContractInput { ProposalId = proposalId, ProposedContractInputHash = proposedContractInputHash }); - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - codeCheckProposalId.ShouldNotBeNull(); + var blockReturnSet = await Tester.MineAsync(new List + { releaseCodeCheckWithWrongSenderTx }); + var noPermissionProposingTxResult = + blockReturnSet.TransactionResultMap[releaseCodeCheckWithWrongSenderTx.GetHash()]; + noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + noPermissionProposingTxResult.Error.ShouldContain("Invalid contract proposing status."); + } - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + // release code check proposal and deployment completes + var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var creator = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].Indexed[0]).Author; + creator.ShouldBe(BasicContractZeroAddress); + var deployAddress = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Address; + deployAddress.ShouldNotBeNull(); + + var contractVersion = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Version; + contractVersion.ShouldBe(1); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), deployAddress)); + contractInfo.Version.ShouldBe(1); + contractInfo.Author.ShouldBe(BasicContractZeroAddress); - var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + { + var releaseContractAlreadyFinished = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - updateResult.Status.ShouldBe(TransactionResultStatus.Mined); - var contractAddress = CodeUpdated.Parser - .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).Indexed[0]).Address; - contractAddress.ShouldBe(newAddress); - var codeHash = HashHelper.ComputeFrom(code); - var newHash = CodeUpdated.Parser - .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).NonIndexed).NewCodeHash; - newHash.ShouldBe(codeHash); - var version = CodeUpdated.Parser - .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).NonIndexed).Version; - version.ShouldBe(contractInfo.Version + 1); - var updateContractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); - updateContractInfo.Version.ShouldBe(contractInfo.Version + 1); - - var thirdTxProposingResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput, - TimestampHelper.GetUtcNow().AddSeconds(86400)); - thirdTxProposingResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + ProposedContractInputHash = proposedContractInputHash, + ProposalId = codeCheckProposalId + }); + releaseContractAlreadyFinished.Status.ShouldBe(TransactionResultStatus.Failed); + releaseContractAlreadyFinished.Error.ShouldContain("Invalid contract proposing status."); } + } - [Fact(Skip = "Skip due to need very long task delay.")] - public async Task DeploySmartContractWithCodeCheck_Test() + [Fact] + public async Task Propose_MultiTimes() + { + var contractDeploymentInput = new ContractDeploymentInput { - var contractPatcher = GetRequiredService(); - var contractCode = contractPatcher.Patch(ReadCode(Path.Combine(BaseDir, "AElf.Contracts.MultiToken.dll")), true); - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(contractCode) - }; - // propose contract code - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + var utcNow = TimestampHelper.GetUtcNow(); + // propose contract code + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + + var secondProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + secondProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var thirdProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow.AddSeconds(86399)); + thirdProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var forthProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput, utcNow.AddSeconds(86400)); + forthProposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - // release contract code and trigger code check proposal - await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); + [Fact] + public async Task Deploy_MultiTimes() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + { + var address = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + address.ShouldNotBeNull(); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync( + BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), address)); + contractInfo.Version.ShouldBe(1); + } - // Mine a block, should include approval transaction - var block = await Tester.MineEmptyBlockAsync(); - var txs = await Tester.GetTransactionsAsync(block.TransactionIds); - var parliamentTxs = txs.Where(tx => tx.To == ParliamentAddress).ToList(); - parliamentTxs[0].MethodName - .ShouldBe(nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ApproveMultiProposals)); + { + // Deployment of the same contract code will fail and return null address + var address = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + address.ShouldBeNull(); } - [Fact(Skip = "Skip due to need task delay.")] - public async Task UpdateSmartContractWithCodeCheck_Test() { - var contractCode = ReadCode(Path.Combine(BaseDir, "AElf.Contracts.TokenConverter.dll.patched")); - var contractDeploymentInput = new ContractDeploymentInput + var newContractDeploymentInput = new ContractDeploymentInput { Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(contractCode) + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Configuration")).Value) }; - var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + var otherTester = Tester.CreateNewContractTester(AnotherUserKeyPair); + var proposingTxResult = await otherTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), newContractDeploymentInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + proposingTxResult.Error.ShouldContain("Unauthorized to propose."); + } + } - var code = ReadCode(Path.Combine(BaseDir, "AElf.Contracts.Referendum.dll")); - var contractUpdateInput = new ContractUpdateInput + [Fact] + public async Task UpdateSmartContract_SameCode_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); + contractInfo.Version.ShouldBe(1); + var contractUpdateInput = new ContractUpdateInput + { + Address = newAddress, + Code = contractDeploymentInput.Code + }; + + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Address = newAddress, - Code = ByteString.CopyFrom(code) - }; + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + codeCheckProposalId.ShouldNotBeNull(); + + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + updateResult.Status.ShouldBe(TransactionResultStatus.Failed); + updateResult.Error.ShouldContain("Code is not changed."); + } - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposalId.ShouldNotBeNull(); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + [Fact] + public async Task UpdateSmartContract_NewCodeExists_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + + var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); + contractInfo.Version.ShouldBe(1); + + var contractDeploymentInput2 = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Genesis")).Value) + }; + await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput2); + var contractUpdateInput = new ContractUpdateInput + { + Address = newAddress, + Code = contractDeploymentInput2.Code + }; + + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + { + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + codeCheckProposalId.ShouldNotBeNull(); + + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + updateResult.Status.ShouldBe(TransactionResultStatus.Failed); + updateResult.Error.ShouldContain("Same code has been deployed before."); + } + + [Fact] + public async Task UpdateSmartContract_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); + contractInfo.Version.ShouldBe(1); + var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; + var contractUpdateInput = new ContractUpdateInput + { + Address = newAddress, + Code = ByteString.CopyFrom(code) + }; + + { + var addressNotExistProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), new ContractUpdateInput { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash + Address = AnotherMinerAddress, + Code = ByteString.CopyFrom(code) }); - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - codeCheckProposalId.ShouldNotBeNull(); - - // Wait for contract code check event handler to finish its job - // Mine a block, should include approval transaction - var block = await Tester.MineEmptyBlockAsync(); - var txs = await Tester.GetTransactionsAsync(block.TransactionIds); - var parliamentTxs = txs.Where(tx => tx.To == ParliamentAddress).ToList(); - parliamentTxs[0].MethodName - .ShouldBe(nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ApproveMultiProposals)); + addressNotExistProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + addressNotExistProposingTxResult.Error.ShouldContain("Contract not found."); } - [Fact] - public async Task Update_ZeroContract_Test() + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var secondTxProposingResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + secondTxProposingResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + { + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + codeCheckProposalId.ShouldNotBeNull(); + + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + + var updateResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + updateResult.Status.ShouldBe(TransactionResultStatus.Mined); + var contractAddress = CodeUpdated.Parser + .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).Indexed[0]).Address; + contractAddress.ShouldBe(newAddress); + var codeHash = HashHelper.ComputeFrom(code); + var newHash = CodeUpdated.Parser + .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).NonIndexed).NewCodeHash; + newHash.ShouldBe(codeHash); + var version = CodeUpdated.Parser + .ParseFrom(updateResult.Logs.First(l => l.Name.Contains(nameof(CodeUpdated))).NonIndexed).Version; + version.ShouldBe(contractInfo.Version + 1); + var updateContractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync( + BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), newAddress)); + updateContractInfo.Version.ShouldBe(contractInfo.Version + 1); + + var thirdTxProposingResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput, + TimestampHelper.GetUtcNow().AddSeconds(86400)); + thirdTxProposingResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact(Skip = "Skip due to need very long task delay.")] + public async Task DeploySmartContractWithCodeCheck_Test() + { + var contractPatcher = GetRequiredService(); + var contractCode = + contractPatcher.Patch(ReadCode(Path.Combine(BaseDir, "AElf.Contracts.MultiToken.dll")), true); + var contractDeploymentInput = new ContractDeploymentInput { - var code = Codes.Single(kv => kv.Key.Contains("GenesisUpdate")).Value; + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(contractCode) + }; + // propose contract code + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + // release contract code and trigger code check proposal + await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + { + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + - var contractUpdateInput = new ContractUpdateInput + // Mine a block, should include approval transaction + var block = await Tester.MineEmptyBlockAsync(); + var txs = await Tester.GetTransactionsAsync(block.TransactionIds); + var parliamentTxs = txs.Where(tx => tx.To == ParliamentAddress).ToList(); + parliamentTxs[0].MethodName + .ShouldBe(nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ApproveMultiProposals)); + } + + [Fact(Skip = "Skip due to need task delay.")] + public async Task UpdateSmartContractWithCodeCheck_Test() + { + var contractCode = ReadCode(Path.Combine(BaseDir, "AElf.Contracts.TokenConverter.dll.patched")); + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(contractCode) + }; + + var newAddress = await DeployAsync(Tester, ParliamentAddress, contractDeploymentInput); + + var code = ReadCode(Path.Combine(BaseDir, "AElf.Contracts.Referendum.dll")); + var contractUpdateInput = new ContractUpdateInput + { + Address = newAddress, + Code = ByteString.CopyFrom(code) + }; + + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposalId.ShouldNotBeNull(); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Address = BasicContractZeroAddress, - Code = ByteString.CopyFrom(code) - }; + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + codeCheckProposalId.ShouldNotBeNull(); + + // Wait for contract code check event handler to finish its job + // Mine a block, should include approval transaction + var block = await Tester.MineEmptyBlockAsync(); + var txs = await Tester.GetTransactionsAsync(block.TransactionIds); + var parliamentTxs = txs.Where(tx => tx.To == ParliamentAddress).ToList(); + parliamentTxs[0].MethodName + .ShouldBe(nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ApproveMultiProposals)); + } - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); + [Fact] + public async Task Update_ZeroContract_Test() + { + var code = Codes.Single(kv => kv.Key.Contains("GenesisUpdate")).Value; - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var contractUpdateInput = new ContractUpdateInput + { + Address = BasicContractZeroAddress, + Code = ByteString.CopyFrom(code) + }; - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), contractUpdateInput); - proposalId.ShouldNotBeNull(); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + proposalId.ShouldNotBeNull(); - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + { + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); - codeCheckProposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - - result.Status.ShouldBe(TransactionResultStatus.Mined); - - var address = CodeUpdated.Parser.ParseFrom(result.Logs[1].Indexed[0]).Address; - address.ShouldBe(BasicContractZeroAddress); - var codeHash = CodeUpdated.Parser.ParseFrom(result.Logs[1].NonIndexed).NewCodeHash; - codeHash.ShouldBe(HashHelper.ComputeFrom(code)); - var contractVersion = CodeUpdated.Parser.ParseFrom(result.Logs[1].NonIndexed).Version; - contractVersion.ShouldBe(2); - var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), BasicContractZeroAddress)); - contractInfo.Version.ShouldBe(2); - } + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - [Fact] - public async Task ChangeContractZeroOwner_Test_Invalid_Address() - { - var address = Tester.GetCallOwnerAddress(); - var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); - var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, - contractDeploymentController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo + codeCheckProposalId.ShouldNotBeNull(); + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + + result.Status.ShouldBe(TransactionResultStatus.Mined); + + var address = CodeUpdated.Parser.ParseFrom(result.Logs[1].Indexed[0]).Address; + address.ShouldBe(BasicContractZeroAddress); + var codeHash = CodeUpdated.Parser.ParseFrom(result.Logs[1].NonIndexed).NewCodeHash; + codeHash.ShouldBe(HashHelper.ComputeFrom(code)); + var contractVersion = CodeUpdated.Parser.ParseFrom(result.Logs[1].NonIndexed).Version; + contractVersion.ShouldBe(2); + var contractInfo = ContractInfo.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractInfo), + BasicContractZeroAddress)); + contractInfo.Version.ShouldBe(2); + } + + [Fact] + public async Task ChangeContractZeroOwner_Test_Invalid_Address() + { + var address = Tester.GetCallOwnerAddress(); + var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); + var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, + contractDeploymentController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo + { + ContractAddress = contractDeploymentController.ContractAddress, + OwnerAddress = address + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Failed); + } + + [Fact] + public async Task ChangeContractZeroOwner_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ContractAddress = contractDeploymentController.ContractAddress, - OwnerAddress = address - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Failed); - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - [Fact] - public async Task ChangeContractZeroOwner_Test() + var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); + var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, + contractDeploymentController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentAddress + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Mined); + + // test deployment with only one miner + var contractDeploymentInput = new ContractDeploymentInput { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); + // propose contract code + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); - var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, - contractDeploymentController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentAddress - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Mined); + var contractProposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + + var tester = Tester.CreateNewContractTester(Tester.InitialMinerList.First()); + await ApproveWithTesterAsync(tester, ParliamentAddress, contractProposalId); - // test deployment with only one miner - var contractDeploymentInput = new ContractDeploymentInput() + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + ProposalId = contractProposalId, + ProposedContractInputHash = proposedContractInputHash + }); - // propose contract code - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - var contractProposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; + // release code check proposal and deployment completes + var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); - var tester = Tester.CreateNewContractTester(Tester.InitialMinerList.First()); - await ApproveWithTesterAsync(tester, ParliamentAddress, contractProposalId); + var creator = ContractDeployed.Parser + .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).Indexed[0]) + .Author; - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = contractProposalId, - ProposedContractInputHash = proposedContractInputHash - }); + creator.ShouldBe(BasicContractZeroAddress); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + var deployAddress = ContractDeployed.Parser + .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed) + .Address; - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + deployAddress.ShouldNotBeNull(); - // release code check proposal and deployment completes - var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); + var author = Address.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); - var creator = ContractDeployed.Parser - .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).Indexed[0]) - .Author; + author.ShouldBe(BasicContractZeroAddress); + } - creator.ShouldBe(BasicContractZeroAddress); + [Fact] + public async Task ChangeContractZeroOwnerByAssociation_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(AssociationContractAddress, + nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateOrganization), + new Association.CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { AnotherMinerAddress } + }, + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { AnotherMinerAddress } + } + }); - var deployAddress = ContractDeployed.Parser - .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed) - .Address; + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - deployAddress.ShouldNotBeNull(); + var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); + var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, + contractDeploymentController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = AssociationContractAddress + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - var author = Address.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); + var contractDeploymentControllerAfterChanged = + await GetContractDeploymentController(Tester, BasicContractZeroAddress); - author.ShouldBe(BasicContractZeroAddress); - } + contractDeploymentControllerAfterChanged.ContractAddress.ShouldBe(AssociationContractAddress); + contractDeploymentControllerAfterChanged.OwnerAddress.ShouldBe(organizationAddress); - [Fact] - public async Task ChangeContractZeroOwnerByAssociation_Test() + // test deployment with only one miner + var contractDeploymentInput = new ContractDeploymentInput { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(AssociationContractAddress, - nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateOrganization), - new Association.CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {AnotherMinerAddress} - }, - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {AnotherMinerAddress} - } - }); + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); + var anotherMinerTester = Tester.CreateNewContractTester(AnotherMinerKeyPair); - var contractDeploymentController = await GetContractDeploymentController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController); - var proposalId = await CreateProposalAsync(Tester, contractDeploymentController.ContractAddress, - contractDeploymentController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = AssociationContractAddress - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Mined); + // propose contract code + var proposingTxResult = await anotherMinerTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + + var contractProposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; - var contractDeploymentControllerAfterChanged = - await GetContractDeploymentController(Tester, BasicContractZeroAddress); + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; - contractDeploymentControllerAfterChanged.ContractAddress.ShouldBe(AssociationContractAddress); - contractDeploymentControllerAfterChanged.OwnerAddress.ShouldBe(organizationAddress); + await ApproveWithTesterAsync(anotherMinerTester, AssociationContractAddress, contractProposalId); - // test deployment with only one miner - var contractDeploymentInput = new ContractDeploymentInput() + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await anotherMinerTester.ExecuteContractWithMiningAsync( + BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + ProposalId = contractProposalId, + ProposedContractInputHash = proposedContractInputHash + }); - var anotherMinerTester = Tester.CreateNewContractTester(AnotherMinerKeyPair); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - // propose contract code - var proposingTxResult = await anotherMinerTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - var contractProposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; + // release code check proposal and deployment completes + var deploymentResult = await anotherMinerTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; + var creator = ContractDeployed.Parser + .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).Indexed[0]) + .Author; - await ApproveWithTesterAsync(anotherMinerTester, AssociationContractAddress, contractProposalId); + creator.ShouldBe(AnotherMinerAddress); - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await anotherMinerTester.ExecuteContractWithMiningAsync( - BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = contractProposalId, - ProposedContractInputHash = proposedContractInputHash - }); + var deployAddress = ContractDeployed.Parser + .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed) + .Address; + var author = Address.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + author.ShouldBe(AnotherMinerAddress); + } - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + [Fact] + public async Task DeploySmartContracts_WithoutAuth_Test() + { + var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.DeploySmartContract), new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) + }); - // release code check proposal and deployment completes - var deploymentResult = await anotherMinerTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); + txResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - var creator = ContractDeployed.Parser - .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).Indexed[0]) - .Author; + [Fact] + public async Task DeploySmartContracts_WithWrongProposer_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + var otherTester = Tester.CreateNewContractTester(AnotherUserKeyPair); + var result = await otherTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.ProposeNewContract), contractDeploymentInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain("Unauthorized to propose."); + } - creator.ShouldBe(AnotherMinerAddress); + [Fact] + public async Task DeploySmartContracts_RepeatedProposals_Test() + { + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; - var deployAddress = ContractDeployed.Parser - .ParseFrom(deploymentResult.Logs.First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed) - .Address; - var author = Address.Parser.ParseFrom(await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); + // propose contract code + var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - author.ShouldBe(AnotherMinerAddress); + { + // propose contract code + var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); } - [Fact] - public async Task DeploySmartContracts_WithoutAuth_Test() { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.DeploySmartContract), (new ContractDeploymentInput() - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) - })); - - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + // propose contract code + var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); } - [Fact] - public async Task DeploySmartContracts_WithWrongProposer_Test() - { - var contractDeploymentInput = new ContractDeploymentInput + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); - var otherTester = Tester.CreateNewContractTester(AnotherUserKeyPair); - var result = await otherTester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.ProposeNewContract), contractDeploymentInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain("Unauthorized to propose."); - } + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - [Fact] - public async Task DeploySmartContracts_RepeatedProposals_Test() + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); { - var contractDeploymentInput = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + // propose contract code + var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); + } + + // release code check proposal and deployment completes + var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); + { // propose contract code - var proposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + } + [Fact] + public async Task UpdateSmartContract_WithoutAuth_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.UpdateSmartContract), + new ContractUpdateInput { - // propose contract code - var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); - } - - { - // propose contract code - var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); - } + Address = ParliamentAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value) + }); - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; + [Fact] + public async Task ChangeContractZeroOwner_WithoutAuth_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController), + new AuthorityInfo + { + OwnerAddress = Tester.GetCallOwnerAddress(), + ContractAddress = BasicContractZeroAddress + }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); + [Fact] + public async Task ValidateSystemContractAddress_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.ValidateSystemContractAddress), new ValidateSystemContractAddressInput + { + Address = TokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + result.Status.ShouldBe(TransactionResultStatus.Mined); + } - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + [Fact] + public async Task ValidateSystemContractAddress_WrongAddress_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.ValidateSystemContractAddress), new ValidateSystemContractAddressInput { - // propose contract code - var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - repeatedProposingTxResult.Error.Contains("Already proposed.").ShouldBeTrue(); - } - - // release code check proposal and deployment completes - var deploymentResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); + Address = ParliamentAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); - deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); - { - // propose contract code - var repeatedProposingTxResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - repeatedProposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Address not expected.").ShouldBeTrue(); + } - [Fact] - public async Task UpdateSmartContract_WithoutAuth_Test() - { - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.UpdateSmartContract), - new ContractUpdateInput - { - Address = ParliamentAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value) - }); - - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + #endregion - [Fact] - public async Task ChangeContractZeroOwner_WithoutAuth_Test() - { - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeContractDeploymentController), - new AuthorityInfo() - { - OwnerAddress = Tester.GetCallOwnerAddress(), - ContractAddress = BasicContractZeroAddress - }); + #region Side chain - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + [Fact] + public async Task DeploySmartContracts_CreatorDeploy_Test() + { + StartSideChain(); - [Fact] - public async Task ValidateSystemContractAddress_Test() + var contractDeploymentInput = new ContractDeploymentInput { - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.ValidateSystemContractAddress), new ValidateSystemContractAddressInput - { - Address = TokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; - result.Status.ShouldBe(TransactionResultStatus.Mined); - } + // propose contract code + var proposingTxResult = await SideChainTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - [Fact] - public async Task ValidateSystemContractAddress_WrongAddress_Test() - { - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.ValidateSystemContractAddress), new ValidateSystemContractAddressInput - { - Address = ParliamentAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); + proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Address not expected.").ShouldBeTrue(); - } + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; - #endregion + proposalId.ShouldNotBeNull(); - #region Side chain + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; - [Fact] - public async Task DeploySmartContracts_CreatorDeploy_Test() - { - StartSideChain(); + await ApproveWithMinersAsync(SideChainTester, SideParliamentAddress, proposalId); - var contractDeploymentInput = new ContractDeploymentInput + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await SideChainTester.ExecuteContractWithMiningAsync( + SideBasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); - // propose contract code - var proposingTxResult = await SideChainTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); - proposingTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; + codeCheckProposalId.ShouldNotBeNull(); + await ApproveWithMinersAsync(SideChainTester, SideParliamentAddress, codeCheckProposalId); - proposalId.ShouldNotBeNull(); + // release code check proposal and deployment completes + var deploymentResult = await SideChainTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; + deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); + var creator = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].Indexed[0]).Author; + creator.ShouldBe(SideChainTester.GetCallOwnerAddress()); + var deployAddress = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Address; + deployAddress.ShouldNotBeNull(); - await ApproveWithMinersAsync(SideChainTester, SideParliamentAddress, proposalId); + var author = Address.Parser.ParseFrom(await SideChainTester.CallContractMethodAsync( + SideBasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await SideChainTester.ExecuteContractWithMiningAsync( - SideBasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput + author.ShouldBe(SideChainTester.GetCallOwnerAddress()); + + { + var noPermissionProposingTx = await SideChainTester.GenerateTransactionAsync(SideBasicContractZeroAddress, + nameof(BasicContractZero.ProposeUpdateContract), AnotherMinerKeyPair, new ContractUpdateInput { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash + Address = deployAddress, + Code = ByteString.Empty }); + var blockReturnSet = await SideChainTester.MineAsync(new List { noPermissionProposingTx }); + var noPermissionProposingTxResult = + blockReturnSet.TransactionResultMap[noPermissionProposingTx.GetHash()]; + noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); + noPermissionProposingTxResult.Error.ShouldContain("No permission."); + } + } - releaseApprovedContractTxResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task DeploySmartContracts_MinerDeploy_Test() + { + StartSideChain(); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + var contractDeploymentInput = new ContractDeploymentInput + { + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) + }; + + var result = await SideChainMinerTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, + nameof(ACS0Container.ACS0Stub.ProposeNewContract), contractDeploymentInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain("Unauthorized to propose."); + } - codeCheckProposalId.ShouldNotBeNull(); - await ApproveWithMinersAsync(SideChainTester, SideParliamentAddress, codeCheckProposalId); + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); - // release code check proposal and deployment completes - var deploymentResult = await SideChainTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - deploymentResult.Status.ShouldBe(TransactionResultStatus.Mined); - var creator = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].Indexed[0]).Author; - creator.ShouldBe(SideChainTester.GetCallOwnerAddress()); - var deployAddress = ContractDeployed.Parser.ParseFrom(deploymentResult.Logs[1].NonIndexed).Address; - deployAddress.ShouldNotBeNull(); + var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentAddress + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - var author = Address.Parser.ParseFrom(await SideChainTester.CallContractMethodAsync( - SideBasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractAuthor), deployAddress)); + var newMethodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); + Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); + } - author.ShouldBe(SideChainTester.GetCallOwnerAddress()); - + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController), + new AuthorityInfo { - var noPermissionProposingTx = await SideChainTester.GenerateTransactionAsync(SideBasicContractZeroAddress, - nameof(BasicContractZero.ProposeUpdateContract), AnotherMinerKeyPair, new ContractUpdateInput - { - Address = deployAddress, - Code = ByteString.Empty - }); - var blockReturnSet = await SideChainTester.MineAsync(new List {noPermissionProposingTx}); - var noPermissionProposingTxResult = - blockReturnSet.TransactionResultMap[noPermissionProposingTx.GetHash()]; - noPermissionProposingTxResult.Status.ShouldBe(TransactionResultStatus.Failed); - noPermissionProposingTxResult.Error.ShouldContain("No permission."); - } - } + OwnerAddress = Tester.GetCallOwnerAddress(), + ContractAddress = ParliamentAddress + }); - [Fact] - public async Task DeploySmartContracts_MinerDeploy_Test() - { - StartSideChain(); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - var contractDeploymentInput = new ContractDeploymentInput + // Invalid organization address + var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value) - }; - - var result = await SideChainMinerTester.ExecuteContractWithMiningAsync(SideBasicContractZeroAddress, - nameof(ACS0Container.ACS0Stub.ProposeNewContract), contractDeploymentInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain("Unauthorized to propose."); - } + OwnerAddress = SampleAddress.AddressList[4], + ContractAddress = ParliamentAddress + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Failed); + txResult2.Error.Contains("Invalid authority input.").ShouldBeTrue(); + } - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), - new CreateOrganizationInput + [Fact] + public async Task ChangeMethodFeeControllerByAssociation_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(AssociationContractAddress, + nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateOrganization), + new Association.CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { AnotherMinerAddress } + }, + OrganizationMemberList = new OrganizationMemberList + { + OrganizationMembers = { AnotherMinerAddress } + } + }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentAddress - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Mined); + var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = AssociationContractAddress + }); + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); + txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - var newMethodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); - Assert.True(newMethodFeeController.OwnerAddress == organizationAddress); - } + var methodFeeControllerAfterChange = + await GetMethodFeeController(Tester, BasicContractZeroAddress); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var result = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController), - new AuthorityInfo() + methodFeeControllerAfterChange.ContractAddress.ShouldBe(AssociationContractAddress); + methodFeeControllerAfterChange.OwnerAddress.ShouldBe(organizationAddress); + } + + [Fact] + public async Task ChangeCodeCheckController_Test() + { + var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - OwnerAddress = Tester.GetCallOwnerAddress(), - ContractAddress = ParliamentAddress - }); + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); + + var byteResult = await Tester.CallContractMethodAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetCodeCheckController), + new Empty()); + var codeCheckController = AuthorityInfo.Parser.ParseFrom(byteResult); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + const string proposalCreationMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeCodeCheckController); - // Invalid organization address - var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, + { + // organization address not exists + var proposalId = await CreateProposalAsync(Tester, codeCheckController.ContractAddress, + codeCheckController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { - OwnerAddress = SampleAddress.AddressList[4], + OwnerAddress = TokenContractAddress, ContractAddress = ParliamentAddress }); await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); txResult2.Status.ShouldBe(TransactionResultStatus.Failed); - txResult2.Error.Contains("Invalid authority input.").ShouldBeTrue(); + txResult2.Error.ShouldContain("Invalid authority input."); } - [Fact] - public async Task ChangeMethodFeeControllerByAssociation_Test() { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(AssociationContractAddress, - nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateOrganization), - new Association.CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {AnotherMinerAddress} - }, - OrganizationMemberList = new OrganizationMemberList - { - OrganizationMembers = {AnotherMinerAddress} - } - }); - - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - - var methodFeeController = await GetMethodFeeController(Tester, BasicContractZeroAddress); - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(Tester, methodFeeController.ContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, + var proposalId = await CreateProposalAsync(Tester, codeCheckController.ContractAddress, + codeCheckController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, - ContractAddress = AssociationContractAddress + ContractAddress = ParliamentAddress }); await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - var methodFeeControllerAfterChange = - await GetMethodFeeController(Tester, BasicContractZeroAddress); - - methodFeeControllerAfterChange.ContractAddress.ShouldBe(AssociationContractAddress); - methodFeeControllerAfterChange.OwnerAddress.ShouldBe(organizationAddress); - } - - [Fact] - public async Task ChangeCodeCheckController_Test() - { - var createOrganizationResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.ReturnValue); - - var byteResult = await Tester.CallContractMethodAsync(BasicContractZeroAddress, + byteResult = await Tester.CallContractMethodAsync(BasicContractZeroAddress, nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetCodeCheckController), new Empty()); - var codeCheckController = AuthorityInfo.Parser.ParseFrom(byteResult); - - const string proposalCreationMethodName = - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeCodeCheckController); - - { - // organization address not exists - var proposalId = await CreateProposalAsync(Tester, codeCheckController.ContractAddress, - codeCheckController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = TokenContractAddress, - ContractAddress = ParliamentAddress - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Failed); - txResult2.Error.ShouldContain("Invalid authority input."); - } - - { - var proposalId = await CreateProposalAsync(Tester, codeCheckController.ContractAddress, - codeCheckController.OwnerAddress, proposalCreationMethodName, - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentAddress - }); - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - var txResult2 = await ReleaseProposalAsync(Tester, ParliamentAddress, proposalId); - txResult2.Status.ShouldBe(TransactionResultStatus.Mined); - - byteResult = await Tester.CallContractMethodAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetCodeCheckController), - new Empty()); - var newCodeCheckController = AuthorityInfo.Parser.ParseFrom(byteResult); - Assert.True(newCodeCheckController.OwnerAddress == organizationAddress); - } - } - - #endregion - - [Fact] - public async Task SetInitialController_Failed_Test() - { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.SetInitialControllerAddress), - ParliamentAddress); - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.ShouldContain("Genesis owner already initialized"); - } - - [Fact] - public async Task SetContractProposerRequiredState_Failed_Test() - { - var txResult = await Tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.SetContractProposerRequiredState), - ParliamentAddress); - txResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.Error.ShouldContain("Genesis contract already initialized"); + var newCodeCheckController = AuthorityInfo.Parser.ParseFrom(byteResult); + Assert.True(newCodeCheckController.OwnerAddress == organizationAddress); } } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Genesis.Tests/GenesisContractTest.cs b/test/AElf.Contracts.Genesis.Tests/GenesisContractTest.cs index 816cb95f33..05fc803a4b 100644 --- a/test/AElf.Contracts.Genesis.Tests/GenesisContractTest.cs +++ b/test/AElf.Contracts.Genesis.Tests/GenesisContractTest.cs @@ -1,197 +1,196 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Kernel; using AElf.Kernel.Token; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public class BasicContractZeroTest : AuthorityNotRequiredBasicContractZeroTestBase { - public class BasicContractZeroTest : AuthorityNotRequiredBasicContractZeroTestBase + private async Task
Deploy_SmartContracts_Test() { - private async Task
Deploy_SmartContracts_Test() + var contractDeploymentInput = new ContractDeploymentInput { - var contractDeploymentInput = new ContractDeploymentInput() - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) - }; - var result = await DefaultTester.DeploySmartContract.SendAsync(contractDeploymentInput); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.Output.ShouldNotBeNull(); + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) + }; + var result = await DefaultTester.DeploySmartContract.SendAsync(contractDeploymentInput); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + result.Output.ShouldNotBeNull(); - { - var tx = await DefaultTester.DeploySmartContract.SendWithExceptionAsync(contractDeploymentInput); - tx.TransactionResult.Error.ShouldContain("contract code has already been deployed before"); - } - return result.Output; + { + var tx = await DefaultTester.DeploySmartContract.SendWithExceptionAsync(contractDeploymentInput); + tx.TransactionResult.Error.ShouldContain("contract code has already been deployed before"); } + return result.Output; + } - [Fact] - public async Task DeploySystemContract_Test_Unauthorized() + [Fact] + public async Task DeploySystemContract_Test_Unauthorized() + { + var txResult = await DefaultTester.DeploySystemSmartContract.SendAsync(new SystemContractDeploymentInput { - var txResult = await DefaultTester.DeploySystemSmartContract.SendAsync( new SystemContractDeploymentInput() - { - Category = KernelConstants.DefaultRunnerCategory, // test the default runner - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value), - Name = TokenSmartContractAddressNameProvider.Name - }); + Category = KernelConstants.DefaultRunnerCategory, // test the default runner + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value), + Name = TokenSmartContractAddressNameProvider.Name + }); - var contractDeployed = ContractDeployed.Parser.ParseFrom(txResult.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed); - var address = contractDeployed.Address; - var author = await DefaultTester.GetContractAuthor.CallAsync(address); - author.ShouldBe(DefaultSender); + var contractDeployed = ContractDeployed.Parser.ParseFrom(txResult.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ContractDeployed))).NonIndexed); + var address = contractDeployed.Address; + var author = await DefaultTester.GetContractAuthor.CallAsync(address); + author.ShouldBe(DefaultSender); - var address2 = - await DefaultTester.GetContractAddressByName.CallAsync(TokenSmartContractAddressNameProvider.Name); - address2.ShouldBe(address); + var address2 = + await DefaultTester.GetContractAddressByName.CallAsync(TokenSmartContractAddressNameProvider.Name); + address2.ShouldBe(address); - { - (await DefaultTester.GetContractAddressByName.CallAsync(HashHelper.ComputeFrom("Random"))).ShouldBe( - new Address()); - } - } - - [Fact] - public async Task Query_SmartContracts_Info_Test() { - var contractAddress = await Deploy_SmartContracts_Test(); - - var resultSerialNumber = await DefaultTester.CurrentContractSerialNumber.CallAsync(new Empty()); - resultSerialNumber.Value.ShouldNotBe(0); + (await DefaultTester.GetContractAddressByName.CallAsync(HashHelper.ComputeFrom("Random"))).ShouldBe( + new Address()); + } + } - { - var resultInfo = await DefaultTester.GetContractInfo.CallAsync(DefaultSender); - resultInfo.ShouldBe(new ContractInfo()); + [Fact] + public async Task Query_SmartContracts_Info_Test() + { + var contractAddress = await Deploy_SmartContracts_Test(); - var resultHash = await DefaultTester.GetContractHash.CallAsync(DefaultSender); - resultHash.ShouldBe(new Hash()); - } - - { - var resultInfo = await DefaultTester.GetContractInfo.CallAsync(contractAddress); - resultInfo.ShouldNotBeNull(); - resultInfo.Author.ShouldBe(DefaultSender); - } + var resultSerialNumber = await DefaultTester.CurrentContractSerialNumber.CallAsync(new Empty()); + resultSerialNumber.Value.ShouldNotBe(0); - { - var resultHash = await DefaultTester.GetContractHash.CallAsync(contractAddress); - var contractCode = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - var contractHash = HashHelper.ComputeFrom(contractCode); - resultHash.ShouldBe(contractHash); - } + { + var resultInfo = await DefaultTester.GetContractInfo.CallAsync(DefaultSender); + resultInfo.ShouldBe(new ContractInfo()); - { - var author = await DefaultTester.GetContractAuthor.CallAsync(contractAddress); - author.ShouldBe(DefaultSender); - } + var resultHash = await DefaultTester.GetContractHash.CallAsync(DefaultSender); + resultHash.ShouldBe(new Hash()); } - [Fact] - public async Task Query_ContractRegistration_Test() { - //not exist - { - var address = SampleAddress.AddressList[0]; - var registrationInfo = - await DefaultTester.GetSmartContractRegistrationByAddress.CallAsync(address); - registrationInfo.ShouldBe(new SmartContractRegistration()); - } - - { - var registrationInfo = - await DefaultTester.GetSmartContractRegistrationByCodeHash.CallAsync( - HashHelper.ComputeFrom("Random")); - registrationInfo.ShouldBe(new SmartContractRegistration()); - } - - //exist contract - { - //query by address - var registrationInfo = - await DefaultTester.GetSmartContractRegistrationByAddress.CallAsync(ContractZeroAddress); - registrationInfo.Category.ShouldBe(KernelConstants.CodeCoverageRunnerCategory); - registrationInfo.CodeHash.ShouldNotBeNull(); - registrationInfo.Code.Length.ShouldBeGreaterThan(0); - - //query by hash - var registrationInfo1 = - await DefaultTester.GetSmartContractRegistrationByCodeHash.CallAsync(registrationInfo.CodeHash); - registrationInfo1.ShouldBe(registrationInfo); - } + var resultInfo = await DefaultTester.GetContractInfo.CallAsync(contractAddress); + resultInfo.ShouldNotBeNull(); + resultInfo.Author.ShouldBe(DefaultSender); } - - [Fact] - public async Task Update_SmartContract_Test() + { - var contractAddress = await Deploy_SmartContracts_Test(); - - var failedUpdate = await AnotherTester.UpdateSmartContract.SendWithExceptionAsync( - new ContractUpdateInput() - { - Address = contractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value), - }); - failedUpdate.TransactionResult.Error.ShouldContain("No permission."); - - var resultUpdate = await DefaultTester.UpdateSmartContract.SendAsync( - new ContractUpdateInput() - { - Address = contractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value), - }); - resultUpdate.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var updateAddress = resultUpdate.Output; - updateAddress.ShouldBe(contractAddress); - - var resultHash = await DefaultTester.GetContractHash.CallAsync(updateAddress); - var contractCode = Codes.Single(kv => kv.Key.Contains("Consensus")).Value; + var resultHash = await DefaultTester.GetContractHash.CallAsync(contractAddress); + var contractCode = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; var contractHash = HashHelper.ComputeFrom(contractCode); resultHash.ShouldBe(contractHash); } - [Fact] - public async Task Update_SmartContract_WrongAuthor_Test() { - var contractAddress = await Deploy_SmartContracts_Test(); - - var resultUpdate = await AnotherTester.UpdateSmartContract.SendWithExceptionAsync( - new ContractUpdateInput() - { - Address = contractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value), - }); - resultUpdate.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - resultUpdate.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + var author = await DefaultTester.GetContractAuthor.CallAsync(contractAddress); + author.ShouldBe(DefaultSender); + } + } + + [Fact] + public async Task Query_ContractRegistration_Test() + { + //not exist + { + var address = SampleAddress.AddressList[0]; + var registrationInfo = + await DefaultTester.GetSmartContractRegistrationByAddress.CallAsync(address); + registrationInfo.ShouldBe(new SmartContractRegistration()); } - [Fact] - public async Task Update_SmartContract_With_Same_Code_Test() { - var contractAddress = await Deploy_SmartContracts_Test(); - - var result = await DefaultTester.UpdateSmartContract.SendWithExceptionAsync( - new ContractUpdateInput - { - Address = contractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Code is not changed.").ShouldBeTrue(); + var registrationInfo = + await DefaultTester.GetSmartContractRegistrationByCodeHash.CallAsync( + HashHelper.ComputeFrom("Random")); + registrationInfo.ShouldBe(new SmartContractRegistration()); } - [Fact] - public async Task SetInitialController_Failed_Test() + //exist contract { - var tx = await ZeroTester.SetInitialControllerAddress.SendWithExceptionAsync(ContractZeroAddress); - tx.TransactionResult.Error.ShouldContain("Unauthorized to initialize genesis contract."); + //query by address + var registrationInfo = + await DefaultTester.GetSmartContractRegistrationByAddress.CallAsync(ContractZeroAddress); + registrationInfo.Category.ShouldBe(KernelConstants.CodeCoverageRunnerCategory); + registrationInfo.CodeHash.ShouldNotBeNull(); + registrationInfo.Code.Length.ShouldBeGreaterThan(0); + + //query by hash + var registrationInfo1 = + await DefaultTester.GetSmartContractRegistrationByCodeHash.CallAsync(registrationInfo.CodeHash); + registrationInfo1.ShouldBe(registrationInfo); } } + + [Fact] + public async Task Update_SmartContract_Test() + { + var contractAddress = await Deploy_SmartContracts_Test(); + + var failedUpdate = await AnotherTester.UpdateSmartContract.SendWithExceptionAsync( + new ContractUpdateInput + { + Address = contractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value) + }); + failedUpdate.TransactionResult.Error.ShouldContain("No permission."); + + var resultUpdate = await DefaultTester.UpdateSmartContract.SendAsync( + new ContractUpdateInput + { + Address = contractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value) + }); + resultUpdate.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var updateAddress = resultUpdate.Output; + updateAddress.ShouldBe(contractAddress); + + var resultHash = await DefaultTester.GetContractHash.CallAsync(updateAddress); + var contractCode = Codes.Single(kv => kv.Key.Contains("Consensus")).Value; + var contractHash = HashHelper.ComputeFrom(contractCode); + resultHash.ShouldBe(contractHash); + } + + [Fact] + public async Task Update_SmartContract_WrongAuthor_Test() + { + var contractAddress = await Deploy_SmartContracts_Test(); + + var resultUpdate = await AnotherTester.UpdateSmartContract.SendWithExceptionAsync( + new ContractUpdateInput + { + Address = contractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("Consensus")).Value) + }); + resultUpdate.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + resultUpdate.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + } + + [Fact] + public async Task Update_SmartContract_With_Same_Code_Test() + { + var contractAddress = await Deploy_SmartContracts_Test(); + + var result = await DefaultTester.UpdateSmartContract.SendWithExceptionAsync( + new ContractUpdateInput + { + Address = contractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.Contains("MultiToken")).Value) + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Code is not changed.").ShouldBeTrue(); + } + + [Fact] + public async Task SetInitialController_Failed_Test() + { + var tx = await ZeroTester.SetInitialControllerAddress.SendWithExceptionAsync(ContractZeroAddress); + tx.TransactionResult.Error.ShouldContain("Unauthorized to initialize genesis contract."); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Genesis.Tests/GenesisContractTestAElfModule.cs b/test/AElf.Contracts.Genesis.Tests/GenesisContractTestAElfModule.cs index 3c1f95166a..ae31341a1b 100644 --- a/test/AElf.Contracts.Genesis.Tests/GenesisContractTestAElfModule.cs +++ b/test/AElf.Contracts.Genesis.Tests/GenesisContractTestAElfModule.cs @@ -7,28 +7,27 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +[DependsOn( + typeof(ContractTestAElfModule) +)] +public class BasicContractZeroTestAElfModule : ContractTestAElfModule { - [DependsOn( - typeof(ContractTestAElfModule) - )] - public class BasicContractZeroTestAElfModule : ContractTestAElfModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var codeCheck = context.ServiceProvider.GetRequiredService>(); - codeCheck.CurrentValue.CodeCheckEnabled = true; - } + var codeCheck = context.ServiceProvider.GetRequiredService>(); + codeCheck.CurrentValue.CodeCheckEnabled = true; } +} - [DependsOn( - typeof(ContractTestModule) - )] - public class AuthorityNotRequiredBasicContractZeroTestModule : ContractTestModule +[DependsOn( + typeof(ContractTestModule) +)] +public class AuthorityNotRequiredBasicContractZeroTestModule : ContractTestModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Genesis.Tests/GenesisContractTestBase.cs b/test/AElf.Contracts.Genesis.Tests/GenesisContractTestBase.cs index a0caf3cc34..67def221fb 100644 --- a/test/AElf.Contracts.Genesis.Tests/GenesisContractTestBase.cs +++ b/test/AElf.Contracts.Genesis.Tests/GenesisContractTestBase.cs @@ -2,288 +2,285 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.Contracts.TestBase; using AElf.Cryptography.ECDSA; using AElf.GovernmentSystem; -using AElf.Kernel; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.Contracts.Genesis +namespace AElf.Contracts.Genesis; + +public class + AuthorityNotRequiredBasicContractZeroTestBase : ContractTestKit.ContractTestBase< + AuthorityNotRequiredBasicContractZeroTestModule> { - public class - AuthorityNotRequiredBasicContractZeroTestBase : ContractTestKit.ContractTestBase< - AuthorityNotRequiredBasicContractZeroTestModule> - { - protected new ISmartContractAddressService ContractAddressService => - Application.ServiceProvider.GetRequiredService(); + protected new ISmartContractAddressService ContractAddressService => + Application.ServiceProvider.GetRequiredService(); - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - internal ACS0Container.ACS0Stub DefaultTester => - GetTester(ContractZeroAddress, DefaultSenderKeyPair); + internal ACS0Container.ACS0Stub DefaultTester => + GetTester(ContractZeroAddress, DefaultSenderKeyPair); - internal BasicContractZeroImplContainer.BasicContractZeroImplStub ZeroTester => - GetTester(ContractZeroAddress, DefaultSenderKeyPair); + internal BasicContractZeroImplContainer.BasicContractZeroImplStub ZeroTester => + GetTester(ContractZeroAddress, DefaultSenderKeyPair); - protected ECKeyPair DefaultSenderKeyPair => Accounts.First().KeyPair; - protected Address DefaultSender => Accounts.First().Address; - protected ECKeyPair AnotherUserKeyPair => Accounts.Last().KeyPair; - protected Address AnotherUser => Accounts.Last().Address; + protected ECKeyPair DefaultSenderKeyPair => Accounts.First().KeyPair; + protected Address DefaultSender => Accounts.First().Address; + protected ECKeyPair AnotherUserKeyPair => Accounts.Last().KeyPair; + protected Address AnotherUser => Accounts.Last().Address; - internal ACS0Container.ACS0Stub AnotherTester => - GetTester(ContractZeroAddress, AnotherUserKeyPair); - } + internal ACS0Container.ACS0Stub AnotherTester => + GetTester(ContractZeroAddress, AnotherUserKeyPair); +} - public class BasicContractZeroTestBase : ContractTestBase - { - protected Address ParliamentAddress; - protected Address BasicContractZeroAddress; - protected Address TokenContractAddress; - protected Address AssociationContractAddress; +public class BasicContractZeroTestBase : TestBase.ContractTestBase +{ + protected readonly string BaseDir = AppDomain.CurrentDomain.BaseDirectory; - protected Address SideBasicContractZeroAddress; - protected Address SideTokenContractAddress; - protected Address SideParliamentAddress; + protected readonly ECKeyPair TesterKeyPair; + protected Address AssociationContractAddress; + protected long BalanceOfStarter; + protected Address BasicContractZeroAddress; + protected Address ParliamentAddress; - protected long TotalSupply; - protected long BalanceOfStarter; + protected Address SideBasicContractZeroAddress; + protected ContractTester SideChainMinerTester; - protected ContractTester SideChainTester; - protected ContractTester SideChainMinerTester; + protected ContractTester SideChainTester; + protected Address SideParliamentAddress; + protected Address SideTokenContractAddress; + protected Address TokenContractAddress; - protected readonly ECKeyPair TesterKeyPair; + protected long TotalSupply; - protected readonly string BaseDir = AppDomain.CurrentDomain.BaseDirectory; + public BasicContractZeroTestBase() + { + TesterKeyPair = Tester.KeyPair; + AsyncHelper.RunSync(() => + Tester.InitialChainAsyncWithAuthAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), + out TotalSupply, + out _, + out BalanceOfStarter))); + + BasicContractZeroAddress = Tester.GetZeroContractAddress(); + ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); + TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + AssociationContractAddress = Tester.GetContractAddress(AssociationSmartContractAddressNameProvider.Name); + } - protected ECKeyPair AnotherUserKeyPair => SampleECKeyPairs.KeyPairs.Last(); - protected ECKeyPair CreatorKeyPair => SampleECKeyPairs.KeyPairs[10]; + protected ECKeyPair AnotherUserKeyPair => SampleECKeyPairs.KeyPairs.Last(); + protected ECKeyPair CreatorKeyPair => SampleECKeyPairs.KeyPairs[10]; - protected ECKeyPair AnotherMinerKeyPair => SampleECKeyPairs.KeyPairs[2]; + protected ECKeyPair AnotherMinerKeyPair => SampleECKeyPairs.KeyPairs[2]; - protected Address AnotherMinerAddress => Address.FromPublicKey(AnotherMinerKeyPair.PublicKey); + protected Address AnotherMinerAddress => Address.FromPublicKey(AnotherMinerKeyPair.PublicKey); - public BasicContractZeroTestBase() - { - TesterKeyPair = Tester.KeyPair; - AsyncHelper.RunSync(() => - Tester.InitialChainAsyncWithAuthAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), - out TotalSupply, - out _, - out BalanceOfStarter))); - - BasicContractZeroAddress = Tester.GetZeroContractAddress(); - ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); - TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); - AssociationContractAddress = Tester.GetContractAddress(AssociationSmartContractAddressNameProvider.Name); - } - - protected void StartSideChain() - { - var chainId = ChainHelper.ConvertBase58ToChainId("Side"); - var mainChainId = Tester.GetChainAsync().Result.Id; - SideChainTester = - new ContractTester(chainId, CreatorKeyPair); - AsyncHelper.RunSync(() => - SideChainTester.InitialCustomizedChainAsync(chainId, - configureSmartContract: SideChainTester.GetSideChainSystemContract( - SideChainTester.GetCallOwnerAddress(), mainChainId, "STA", out TotalSupply, - SideChainTester.GetCallOwnerAddress()))); - SideBasicContractZeroAddress = SideChainTester.GetZeroContractAddress(); - SideTokenContractAddress = SideChainTester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); - SideParliamentAddress = - SideChainTester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); - - SideChainMinerTester = SideChainTester.CreateNewContractTester(SideChainTester.InitialMinerList.First()); - } - - protected async Task ApproveWithMinersAsync( - ContractTester tester, Address parliamentContract, Hash proposalId) - { - var tester0 = tester.CreateNewContractTester(Tester.InitialMinerList[0]); - await tester0.ExecuteContractWithMiningAsync(parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); + protected void StartSideChain() + { + var chainId = ChainHelper.ConvertBase58ToChainId("Side"); + var mainChainId = Tester.GetChainAsync().Result.Id; + SideChainTester = + new ContractTester(chainId, CreatorKeyPair); + AsyncHelper.RunSync(() => + SideChainTester.InitialCustomizedChainAsync(chainId, + configureSmartContract: SideChainTester.GetSideChainSystemContract( + SideChainTester.GetCallOwnerAddress(), mainChainId, "STA", out TotalSupply, + SideChainTester.GetCallOwnerAddress()))); + SideBasicContractZeroAddress = SideChainTester.GetZeroContractAddress(); + SideTokenContractAddress = SideChainTester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + SideParliamentAddress = + SideChainTester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); + + SideChainMinerTester = SideChainTester.CreateNewContractTester(SideChainTester.InitialMinerList.First()); + } - var tester1 = tester.CreateNewContractTester(Tester.InitialMinerList[1]); - await tester1.ExecuteContractWithMiningAsync(parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); + protected async Task ApproveWithMinersAsync( + ContractTester tester, Address parliamentContract, Hash proposalId) + { + var tester0 = tester.CreateNewContractTester(Tester.InitialMinerList[0]); + await tester0.ExecuteContractWithMiningAsync(parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); - var tester2 = tester.CreateNewContractTester(Tester.InitialMinerList[2]); - await tester2.ExecuteContractWithMiningAsync(parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); - } + var tester1 = tester.CreateNewContractTester(Tester.InitialMinerList[1]); + await tester1.ExecuteContractWithMiningAsync(parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); - protected async Task CreateProposalAsync(ContractTester tester, - Address contractAddress, Address organizationAddress, string methodName, IMessage input) - { - var basicContract = tester.GetZeroContractAddress(); - // var organizationAddress = await GetGenesisAddressAsync(tester, parliamentContractAddress); - var proposal = await tester.ExecuteContractWithMiningAsync(contractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = methodName, - ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), - Params = input.ToByteString(), - ToAddress = basicContract, - OrganizationAddress = organizationAddress - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - return proposalId; - } - - protected async Task ReleaseProposalAsync( - ContractTester tester, Address parliamentContract, Hash proposalId) - { - var transactionResult = await tester.ExecuteContractWithMiningAsync(parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); - return transactionResult; - } - - internal async Task ProposeContractAsync( - ContractTester tester, string methodName, - IMessage input) - { - var contractDeploymentController = await GetContractDeploymentController(tester, BasicContractZeroAddress); - var proposalId = await CreateProposalAsync(tester, contractDeploymentController.ContractAddress, - contractDeploymentController.OwnerAddress, methodName, input); - await ApproveWithMinersAsync(tester, contractDeploymentController.ContractAddress, proposalId); - var releaseResult = - await ReleaseProposalAsync(tester, contractDeploymentController.ContractAddress, proposalId); - var proposedContractInputHash = CodeCheckRequired.Parser - .ParseFrom(releaseResult.Logs.First(l => l.Name.Contains(nameof(CodeCheckRequired))).NonIndexed) - .ProposedContractInputHash; - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - - return new ReleaseContractInput + var tester2 = tester.CreateNewContractTester(Tester.InitialMinerList[2]); + await tester2.ExecuteContractWithMiningAsync(parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId); + } + + protected async Task CreateProposalAsync(ContractTester tester, + Address contractAddress, Address organizationAddress, string methodName, IMessage input) + { + var basicContract = tester.GetZeroContractAddress(); + // var organizationAddress = await GetGenesisAddressAsync(tester, parliamentContractAddress); + var proposal = await tester.ExecuteContractWithMiningAsync(contractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), + new CreateProposalInput { - ProposedContractInputHash = proposedContractInputHash, - ProposalId = codeCheckProposalId - }; - } + ContractMethodName = methodName, + ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), + Params = input.ToByteString(), + ToAddress = basicContract, + OrganizationAddress = organizationAddress + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + return proposalId; + } - internal async Task ApproveWithTesterAsync( - ContractTester tester, Address contractAddress, Hash proposalId) - { - return await tester.ExecuteContractWithMiningAsync(contractAddress, - nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), proposalId); - } + protected async Task ReleaseProposalAsync( + ContractTester tester, Address parliamentContract, Hash proposalId) + { + var transactionResult = await tester.ExecuteContractWithMiningAsync(parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); + return transactionResult; + } - internal async Task
DeployAsync(ContractTester tester, - Address parliamentContract, ContractDeploymentInput contractDeploymentInput) - { - var proposingTxResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); - - var proposalCreatedEvent = - proposingTxResult.Logs.FirstOrDefault(l => l.Name.Contains(nameof(ProposalCreated))); - if (proposalCreatedEvent == null) - return null; - - var proposalId = ProposalCreated.Parser - .ParseFrom(proposalCreatedEvent.NonIndexed) - .ProposalId; - var proposedContractInputHash = ContractProposed.Parser - .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) - .ProposedContractInputHash; - await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); - - // release contract code and trigger code check proposal - var releaseApprovedContractTxResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput - { - ProposalId = proposalId, - ProposedContractInputHash = proposedContractInputHash - }); - var codeCheckProposalId = ProposalCreated.Parser - .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - - await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); - - // release code check proposal and deployment completes - var deploymentResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), - new ReleaseContractInput - {ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId}); - var deploymentEvent = deploymentResult.Logs.FirstOrDefault(l => l.Name.Contains(nameof(ContractDeployed))); - - var address = deploymentEvent != null - ? ContractDeployed.Parser.ParseFrom(deploymentEvent.NonIndexed).Address - : null; - return address; - } - - protected async Task
CreateOrganizationAsync(ContractTester tester, - Address parliamentContract) + internal async Task ProposeContractAsync( + ContractTester tester, string methodName, + IMessage input) + { + var contractDeploymentController = await GetContractDeploymentController(tester, BasicContractZeroAddress); + var proposalId = await CreateProposalAsync(tester, contractDeploymentController.ContractAddress, + contractDeploymentController.OwnerAddress, methodName, input); + await ApproveWithMinersAsync(tester, contractDeploymentController.ContractAddress, proposalId); + var releaseResult = + await ReleaseProposalAsync(tester, contractDeploymentController.ContractAddress, proposalId); + var proposedContractInputHash = CodeCheckRequired.Parser + .ParseFrom(releaseResult.Logs.First(l => l.Name.Contains(nameof(CodeCheckRequired))).NonIndexed) + .ProposedContractInputHash; + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + + return new ReleaseContractInput { - var createOrganizationInput = new CreateOrganizationInput + ProposedContractInputHash = proposedContractInputHash, + ProposalId = codeCheckProposalId + }; + } + + internal async Task ApproveWithTesterAsync( + ContractTester tester, Address contractAddress, Hash proposalId) + { + return await tester.ExecuteContractWithMiningAsync(contractAddress, + nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), proposalId); + } + + internal async Task
DeployAsync(ContractTester tester, + Address parliamentContract, ContractDeploymentInput contractDeploymentInput) + { + var proposingTxResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ProposeNewContract), contractDeploymentInput); + + var proposalCreatedEvent = + proposingTxResult.Logs.FirstOrDefault(l => l.Name.Contains(nameof(ProposalCreated))); + if (proposalCreatedEvent == null) + return null; + + var proposalId = ProposalCreated.Parser + .ParseFrom(proposalCreatedEvent.NonIndexed) + .ProposalId; + var proposedContractInputHash = ContractProposed.Parser + .ParseFrom(proposingTxResult.Logs.First(l => l.Name.Contains(nameof(ContractProposed))).NonIndexed) + .ProposedContractInputHash; + await ApproveWithMinersAsync(Tester, ParliamentAddress, proposalId); + + // release contract code and trigger code check proposal + var releaseApprovedContractTxResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZero.ReleaseApprovedContract), new ReleaseContractInput { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 20000 / tester.InitialMinerList.Count, - MinimalVoteThreshold = 20000 / tester.InitialMinerList.Count - } - }; - var transactionResult = - await tester.ExecuteContractWithMiningAsync(parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), - createOrganizationInput); - return Address.Parser.ParseFrom(transactionResult.ReturnValue); - } - - protected async Task
GetGenesisAddressAsync(ContractTester tester, - Address parliamentContract) - { - var organizationAddress = Address.Parser.ParseFrom(await tester.CallContractMethodAsync( - parliamentContract, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), - new Empty())); - return organizationAddress; - } - - protected byte[] ReadCode(string path) - { - return File.Exists(path) - ? File.ReadAllBytes(path) - : throw new FileNotFoundException("Contract DLL cannot be found. " + path); - } + ProposalId = proposalId, + ProposedContractInputHash = proposedContractInputHash + }); + var codeCheckProposalId = ProposalCreated.Parser + .ParseFrom(releaseApprovedContractTxResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + + await ApproveWithMinersAsync(Tester, ParliamentAddress, codeCheckProposalId); + + // release code check proposal and deployment completes + var deploymentResult = await tester.ExecuteContractWithMiningAsync(BasicContractZeroAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ReleaseCodeCheckedContract), + new ReleaseContractInput + { ProposedContractInputHash = proposedContractInputHash, ProposalId = codeCheckProposalId }); + var deploymentEvent = deploymentResult.Logs.FirstOrDefault(l => l.Name.Contains(nameof(ContractDeployed))); + + var address = deploymentEvent != null + ? ContractDeployed.Parser.ParseFrom(deploymentEvent.NonIndexed).Address + : null; + return address; + } - internal async Task GetContractDeploymentController( - ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule - { - var contractDeploymentControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractDeploymentController), new Empty()); - return AuthorityInfo.Parser.ParseFrom(contractDeploymentControllerByteString); - } - - internal async Task GetContractCodeCheckController( - ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule + protected async Task
CreateOrganizationAsync(ContractTester tester, + Address parliamentContract) + { + var createOrganizationInput = new CreateOrganizationInput { - var contractCodeCheckControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetCodeCheckController), new Empty()); - return AuthorityInfo.Parser.ParseFrom(contractCodeCheckControllerByteString); - } + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 20000 / tester.InitialMinerList.Count, + MinimalVoteThreshold = 20000 / tester.InitialMinerList.Count + } + }; + var transactionResult = + await tester.ExecuteContractWithMiningAsync(parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), + createOrganizationInput); + return Address.Parser.ParseFrom(transactionResult.ReturnValue); + } - internal async Task GetMethodFeeController( - ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule - { - var methodFeeControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetMethodFeeController), new Empty()); - return AuthorityInfo.Parser.ParseFrom(methodFeeControllerByteString); - } + protected async Task
GetGenesisAddressAsync(ContractTester tester, + Address parliamentContract) + { + var organizationAddress = Address.Parser.ParseFrom(await tester.CallContractMethodAsync( + parliamentContract, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), + new Empty())); + return organizationAddress; + } + + protected byte[] ReadCode(string path) + { + return File.Exists(path) + ? File.ReadAllBytes(path) + : throw new FileNotFoundException("Contract DLL cannot be found. " + path); + } + + internal async Task GetContractDeploymentController( + ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule + { + var contractDeploymentControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetContractDeploymentController), + new Empty()); + return AuthorityInfo.Parser.ParseFrom(contractDeploymentControllerByteString); + } + + internal async Task GetContractCodeCheckController( + ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule + { + var contractCodeCheckControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetCodeCheckController), new Empty()); + return AuthorityInfo.Parser.ParseFrom(contractCodeCheckControllerByteString); + } + + internal async Task GetMethodFeeController( + ContractTester tester, Address genesisContractAddress) where T : ContractTestAElfModule + { + var methodFeeControllerByteString = await tester.CallContractMethodAsync(genesisContractAddress, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.GetMethodFeeController), new Empty()); + return AuthorityInfo.Parser.ParseFrom(methodFeeControllerByteString); } } \ No newline at end of file diff --git a/test/AElf.Contracts.GenesisUpdate/AElf.Contracts.GenesisUpdate.csproj b/test/AElf.Contracts.GenesisUpdate/AElf.Contracts.GenesisUpdate.csproj index 6b66f0ef84..04f683af8b 100644 --- a/test/AElf.Contracts.GenesisUpdate/AElf.Contracts.GenesisUpdate.csproj +++ b/test/AElf.Contracts.GenesisUpdate/AElf.Contracts.GenesisUpdate.csproj @@ -5,15 +5,15 @@ - true + true - true + true - + diff --git a/test/AElf.Contracts.GenesisUpdate/BasicContractZero.cs b/test/AElf.Contracts.GenesisUpdate/BasicContractZero.cs index f4a3b5f0ce..b4f30459aa 100644 --- a/test/AElf.Contracts.GenesisUpdate/BasicContractZero.cs +++ b/test/AElf.Contracts.GenesisUpdate/BasicContractZero.cs @@ -1,267 +1,253 @@ using System; using AElf.Sdk.CSharp; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using AElf.Standards.ACS0; -namespace AElf.Contracts.GenesisUpdate +namespace AElf.Contracts.GenesisUpdate; + +public class BasicContractZero : BasicContractZeroContainer.BasicContractZeroBase { - public class BasicContractZero : BasicContractZeroContainer.BasicContractZeroBase + public void RequireAuthority() { - #region Views + var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; + if (!State.Initialized.Value) + // only authority of contract zero is valid before initialization + AssertSenderAddressWith(Context.Self); + else if (isGenesisOwnerAuthorityRequired) + // genesis owner authority check is required + AssertSenderAddressWith(State.GenesisOwner.Value); + } - public override Int64Value CurrentContractSerialNumber(Empty input) - { - return new Int64Value() {Value = State.ContractSerialNumber.Value}; - } + private void AssertSenderAddressWith(Address address) + { + Assert(Context.Sender.Equals(address), "Unauthorized behavior."); + } - public override ContractInfo GetContractInfo(Address input) - { - var info = State.ContractInfos[input]; - if (info == null) - { - return new ContractInfo(); - } + private void InitializeGenesisOwner(Address genesisOwner) + { + Assert(State.GenesisOwner.Value == null, "Genesis owner already initialized"); + var address = GetContractAddressByName(SmartContractConstants.ParliamentContractSystemHashName); + Assert(Context.Sender.Equals(address), "Unauthorized to initialize genesis contract."); + Assert(genesisOwner != null, "Genesis Owner should not be null."); + State.GenesisOwner.Value = genesisOwner; + } - return info; - } + #region Views - public override Address GetContractAuthor(Address input) - { - var info = State.ContractInfos[input]; - return info?.Author; - } + public override Int64Value CurrentContractSerialNumber(Empty input) + { + return new Int64Value { Value = State.ContractSerialNumber.Value }; + } - public override Hash GetContractHash(Address input) - { - var info = State.ContractInfos[input]; - return info?.CodeHash; - } + public override ContractInfo GetContractInfo(Address input) + { + var info = State.ContractInfos[input]; + if (info == null) return new ContractInfo(); - public override Address GetContractAddressByName(Hash input) - { - return State.NameAddressMapping[input]; - } + return info; + } - public override SmartContractRegistration GetSmartContractRegistrationByAddress(Address input) - { - var info = State.ContractInfos[input]; - if (info == null) - { - return null; - } + public override Address GetContractAuthor(Address input) + { + var info = State.ContractInfos[input]; + return info?.Author; + } - return State.SmartContractRegistrations[info.CodeHash]; - } + public override Hash GetContractHash(Address input) + { + var info = State.ContractInfos[input]; + return info?.CodeHash; + } - public override Empty ValidateSystemContractAddress(ValidateSystemContractAddressInput input) - { - var actualAddress = GetContractAddressByName(input.SystemContractHashName); - Assert(actualAddress == input.Address, "Address not expected."); - return new Empty(); - } + public override Address GetContractAddressByName(Hash input) + { + return State.NameAddressMapping[input]; + } + + public override SmartContractRegistration GetSmartContractRegistrationByAddress(Address input) + { + var info = State.ContractInfos[input]; + if (info == null) return null; + + return State.SmartContractRegistrations[info.CodeHash]; + } - public override BoolValue GetContractDeploymentAuthorityRequired(Empty input) + public override Empty ValidateSystemContractAddress(ValidateSystemContractAddressInput input) + { + var actualAddress = GetContractAddressByName(input.SystemContractHashName); + Assert(actualAddress == input.Address, "Address not expected."); + return new Empty(); + } + + public override BoolValue GetContractDeploymentAuthorityRequired(Empty input) + { + return new BoolValue { - return new BoolValue - { - Value = State.ContractDeploymentAuthorityRequired.Value - }; - } + Value = State.ContractDeploymentAuthorityRequired.Value + }; + } + + #endregion Views + + #region Actions + + public override Address DeploySystemSmartContract(SystemContractDeploymentInput input) + { + RequireAuthority(); + var name = input.Name; + var category = input.Category; + var code = input.Code.ToByteArray(); + var transactionMethodCallList = input.TransactionMethodCallList; + var address = PrivateDeploySystemSmartContract(name, category, code); + + if (transactionMethodCallList != null) + foreach (var methodCall in transactionMethodCallList.Value) + Context.SendInline(address, methodCall.MethodName, methodCall.Params); + + return address; + } - #endregion Views + private Address PrivateDeploySystemSmartContract(Hash name, int category, byte[] code) + { + if (name != null) + Assert(State.NameAddressMapping[name] == null, "contract name already been registered"); - #region Actions + var serialNumber = State.ContractSerialNumber.Value; + // Increment + State.ContractSerialNumber.Value = serialNumber + 1; + var contractAddress = AddressHelper.BuildContractAddress(Context.ChainId, serialNumber); - public override Address DeploySystemSmartContract(SystemContractDeploymentInput input) + var codeHash = HashHelper.ComputeFrom(code); + + var info = new ContractInfo { - RequireAuthority(); - var name = input.Name; - var category = input.Category; - var code = input.Code.ToByteArray(); - var transactionMethodCallList = input.TransactionMethodCallList; - var address = PrivateDeploySystemSmartContract(name, category, code); - - if (transactionMethodCallList != null) - { - foreach (var methodCall in transactionMethodCallList.Value) - { - Context.SendInline(address, methodCall.MethodName, methodCall.Params); - } - } - - return address; - } + SerialNumber = serialNumber, + Author = Context.Origin, + Category = category, + CodeHash = codeHash + }; + State.ContractInfos[contractAddress] = info; - private Address PrivateDeploySystemSmartContract(Hash name, int category, byte[] code) + var reg = new SmartContractRegistration { - if (name != null) - Assert(State.NameAddressMapping[name] == null, "contract name already been registered"); + Category = category, + Code = ByteString.CopyFrom(code), + CodeHash = codeHash + }; - var serialNumber = State.ContractSerialNumber.Value; - // Increment - State.ContractSerialNumber.Value = serialNumber + 1; - var contractAddress = AddressHelper.BuildContractAddress(Context.ChainId, serialNumber); + State.SmartContractRegistrations[reg.CodeHash] = reg; - var codeHash = HashHelper.ComputeFrom(code); + Context.DeployContract(contractAddress, reg, name); - var info = new ContractInfo - { - SerialNumber = serialNumber, - Author = Context.Origin, - Category = category, - CodeHash = codeHash - }; - State.ContractInfos[contractAddress] = info; + Context.Fire(new ContractDeployed + { + CodeHash = codeHash, + Address = contractAddress, + Author = Context.Origin + }); - var reg = new SmartContractRegistration - { - Category = category, - Code = ByteString.CopyFrom(code), - CodeHash = codeHash - }; + Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + codeHash.ToHex()); + Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58()); - State.SmartContractRegistrations[reg.CodeHash] = reg; - Context.DeployContract(contractAddress, reg, name); + if (name != null) + State.NameAddressMapping[name] = contractAddress; - Context.Fire(new ContractDeployed() - { - CodeHash = codeHash, - Address = contractAddress, - Author = Context.Origin - }); - Context.LogDebug(() => "BasicContractZero - Deployment ContractHash: " + codeHash.ToHex()); - Context.LogDebug(() => "BasicContractZero - Deployment success: " + contractAddress.ToBase58()); + return contractAddress; + } + public override Address DeploySmartContract(ContractDeploymentInput input) + { + RequireAuthority(); - if (name != null) - State.NameAddressMapping[name] = contractAddress; + var address = PrivateDeploySystemSmartContract(null, input.Category, input.Code.ToByteArray()); + return address; + } + public override Address UpdateSmartContract(ContractUpdateInput input) + { + RequireAuthority(); - return contractAddress; - } + var contractAddress = input.Address; + var code = input.Code.ToByteArray(); + var info = State.ContractInfos[contractAddress]; + Assert(info != null, "Contract does not exist."); + Assert(info.Author == Context.Self || info.Author == Context.Origin, + "Only author can propose contract update."); - public override Address DeploySmartContract(ContractDeploymentInput input) - { - RequireAuthority(); + var oldCodeHash = info.CodeHash; + var newCodeHash = HashHelper.ComputeFrom(code); + Assert(!oldCodeHash.Equals(newCodeHash), "Code is not changed."); - var address = PrivateDeploySystemSmartContract(null, input.Category, input.Code.ToByteArray()); - return address; - } + info.CodeHash = newCodeHash; + State.ContractInfos[contractAddress] = info; - public override Address UpdateSmartContract(ContractUpdateInput input) + var reg = new SmartContractRegistration { - RequireAuthority(); - - var contractAddress = input.Address; - var code = input.Code.ToByteArray(); - var info = State.ContractInfos[contractAddress]; - Assert(info != null, "Contract does not exist."); - Assert(info.Author == Context.Self || info.Author == Context.Origin, - "Only author can propose contract update."); - - var oldCodeHash = info.CodeHash; - var newCodeHash = HashHelper.ComputeFrom(code); - Assert(!oldCodeHash.Equals(newCodeHash), "Code is not changed."); - - info.CodeHash = newCodeHash; - State.ContractInfos[contractAddress] = info; - - var reg = new SmartContractRegistration - { - Category = info.Category, - Code = ByteString.CopyFrom(code), - CodeHash = newCodeHash - }; - - State.SmartContractRegistrations[reg.CodeHash] = reg; - - Context.UpdateContract(contractAddress, reg, null); - - Context.Fire(new CodeUpdated() - { - Address = contractAddress, - OldCodeHash = oldCodeHash, - NewCodeHash = newCodeHash - }); - - Context.LogDebug(() => "BasicContractZero - update success: " + contractAddress.ToBase58()); - return contractAddress; - } + Category = info.Category, + Code = ByteString.CopyFrom(code), + CodeHash = newCodeHash + }; - public override Empty Initialize(InitializeInput input) - { - Assert(!State.Initialized.Value, "Contract zero already initialized."); - Assert(Context.Sender == Context.Self, "Unable to initialize."); - State.ContractDeploymentAuthorityRequired.Value = input.ContractDeploymentAuthorityRequired; - State.Initialized.Value = true; - return new Empty(); - } + State.SmartContractRegistrations[reg.CodeHash] = reg; + + Context.UpdateContract(contractAddress, reg, null); - public override Empty ChangeGenesisOwnerAddress(Address newOwnerAddress) + Context.Fire(new CodeUpdated { - if (State.GenesisOwner.Value == null) - InitializeGenesisOwner(newOwnerAddress); - else - { - AssertSenderAddressWith(State.GenesisOwner.Value); - State.GenesisOwner.Value = newOwnerAddress; - } - - return new Empty(); - } + Address = contractAddress, + OldCodeHash = oldCodeHash, + NewCodeHash = newCodeHash + }); - #endregion Actions + Context.LogDebug(() => "BasicContractZero - update success: " + contractAddress.ToBase58()); + return contractAddress; + } - public void RequireAuthority() - { - var isGenesisOwnerAuthorityRequired = State.ContractDeploymentAuthorityRequired.Value; - if (!State.Initialized.Value) - { - // only authority of contract zero is valid before initialization - AssertSenderAddressWith(Context.Self); - } - else if (isGenesisOwnerAuthorityRequired) - { - // genesis owner authority check is required - AssertSenderAddressWith(State.GenesisOwner.Value); - } - } + public override Empty Initialize(InitializeInput input) + { + Assert(!State.Initialized.Value, "Contract zero already initialized."); + Assert(Context.Sender == Context.Self, "Unable to initialize."); + State.ContractDeploymentAuthorityRequired.Value = input.ContractDeploymentAuthorityRequired; + State.Initialized.Value = true; + return new Empty(); + } - private void AssertSenderAddressWith(Address address) + public override Empty ChangeGenesisOwnerAddress(Address newOwnerAddress) + { + if (State.GenesisOwner.Value == null) { - Assert(Context.Sender.Equals(address), "Unauthorized behavior."); + InitializeGenesisOwner(newOwnerAddress); } - - private void InitializeGenesisOwner(Address genesisOwner) + else { - Assert(State.GenesisOwner.Value == null, "Genesis owner already initialized"); - var address = GetContractAddressByName(SmartContractConstants.ParliamentContractSystemHashName); - Assert(Context.Sender.Equals(address), "Unauthorized to initialize genesis contract."); - Assert(genesisOwner != null, "Genesis Owner should not be null."); - State.GenesisOwner.Value = genesisOwner; + AssertSenderAddressWith(State.GenesisOwner.Value); + State.GenesisOwner.Value = newOwnerAddress; } + + return new Empty(); } - public static class AddressHelper + #endregion Actions +} + +public static class AddressHelper +{ + /// + /// + /// + /// + private static Address BuildContractAddress(Hash chainId, long serialNumber) { - /// - /// - /// - /// - /// - private static Address BuildContractAddress(Hash chainId, long serialNumber) - { - var hash = HashHelper.ConcatAndCompute(chainId, HashHelper.ComputeFrom(serialNumber)); - return Address.FromBytes(hash.ToByteArray()); - } + var hash = HashHelper.ConcatAndCompute(chainId, HashHelper.ComputeFrom(serialNumber)); + return Address.FromBytes(hash.ToByteArray()); + } - public static Address BuildContractAddress(int chainId, long serialNumber) - { - return BuildContractAddress(HashHelper.ComputeFrom(chainId), serialNumber); - } + public static Address BuildContractAddress(int chainId, long serialNumber) + { + return BuildContractAddress(HashHelper.ComputeFrom(chainId), serialNumber); } } \ No newline at end of file diff --git a/test/AElf.Contracts.GenesisUpdate/BasicContractZeroState.cs b/test/AElf.Contracts.GenesisUpdate/BasicContractZeroState.cs index a4344c0bfe..83bf14eda2 100644 --- a/test/AElf.Contracts.GenesisUpdate/BasicContractZeroState.cs +++ b/test/AElf.Contracts.GenesisUpdate/BasicContractZeroState.cs @@ -1,27 +1,26 @@ -using AElf.Standards.ACS0; -using AElf.Sdk.CSharp.State; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS0; using AElf.Types; -namespace AElf.Contracts.GenesisUpdate +namespace AElf.Contracts.GenesisUpdate; + +public class BasicContractZeroState : ContractState { - public class BasicContractZeroState : ContractState - { - public Int64State ContractSerialNumber { get; set; } - public MappedState ContractInfos { get; set; } - - public Int32State ChainId { get; set; } - - public MappedState SmartContractRegistrations { get; set; } - - public MappedState NameAddressMapping { get; set; } - - /// - /// Genesis owner controls contract deployment if is true. - /// - public SingletonState
GenesisOwner { get; set; } - - public SingletonState ContractDeploymentAuthorityRequired { get; set; } - - public SingletonState Initialized { get; set; } - } + public Int64State ContractSerialNumber { get; set; } + public MappedState ContractInfos { get; set; } + + public Int32State ChainId { get; set; } + + public MappedState SmartContractRegistrations { get; set; } + + public MappedState NameAddressMapping { get; set; } + + /// + /// Genesis owner controls contract deployment if is true. + /// + public SingletonState
GenesisOwner { get; set; } + + public SingletonState ContractDeploymentAuthorityRequired { get; set; } + + public SingletonState Initialized { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj index 1dcca26251..70ee2cfbdb 100644 --- a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj +++ b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj @@ -6,7 +6,7 @@ false - + false Contract @@ -59,12 +59,12 @@ - - - - - - + + + + + + @@ -125,6 +125,6 @@ Protobuf\Proto\base\acs11.proto - - + + diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs index 428c3d7a80..d2352db489 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs @@ -1,304 +1,303 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests { - public partial class MultiTokenContractTests + [Fact] + public async Task ChangeMethodFeeController_Test() { - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync( - new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); + var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync( + new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - const string proposalCreationMethodName = nameof(TokenContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(TokenContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + const string proposalCreationMethodName = nameof(TokenContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(TokenContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var newMethodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var newMethodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await TokenContractStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await TokenContractStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; + return proposalId; + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } + } + + [Fact] + public async Task SendInvalidTransactionsTest() + { + const string assertionMessage = "This method can only be executed in plugin tx."; + + var txResult = + (await TokenContractStub.ChargeTransactionFees.SendWithExceptionAsync(new ChargeTransactionFeesInput())) + .TransactionResult; + txResult.Error.ShouldContain(assertionMessage); + + txResult = + (await TokenContractStub.ChargeResourceToken.SendWithExceptionAsync(new ChargeResourceTokenInput())) + .TransactionResult; + txResult.Error.ShouldContain(assertionMessage); - private async Task ApproveWithMinersAsync(Hash proposalId) + txResult = + (await TokenContractStub.CheckResourceToken.SendWithExceptionAsync(new Empty())) + .TransactionResult; + txResult.Error.ShouldContain(assertionMessage); + } + + [Fact] + public async Task SetMethodFee_Success_Test() + { + await CreateNativeTokenAsync(); + var methodName = "Transfer"; + var tokenSymbol = NativeTokenInfo.Symbol; + var basicFee = 100; + var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalMethodName = nameof(TokenContractStub.SetMethodFee); + var methodFees = new MethodFees { - foreach (var bp in InitialCoreDataCenterKeyPairs) + MethodName = methodName, + Fees = { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } } - } + }; + var proposalId = await CreateProposalAsync(TokenContractAddress, + methodFeeController.OwnerAddress, proposalMethodName, methodFees); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task SendInvalidTransactionsTest() + var afterUpdateMethodFees = await TokenContractStub.GetMethodFee.CallAsync(new StringValue { - const string assertionMessage = "This method can only be executed in plugin tx."; - - var txResult = - (await TokenContractStub.ChargeTransactionFees.SendWithExceptionAsync(new ChargeTransactionFeesInput())) - .TransactionResult; - txResult.Error.ShouldContain(assertionMessage); - - txResult = - (await TokenContractStub.ChargeResourceToken.SendWithExceptionAsync(new ChargeResourceTokenInput())) - .TransactionResult; - txResult.Error.ShouldContain(assertionMessage); + Value = methodName + }); + var tokenFee = afterUpdateMethodFees.Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); + tokenFee.BasicFee.ShouldBe(basicFee); + } - txResult = - (await TokenContractStub.CheckResourceToken.SendWithExceptionAsync(new Empty())) - .TransactionResult; - txResult.Error.ShouldContain(assertionMessage); - } - - [Fact] - public async Task SetMethodFee_Success_Test() + [Fact] + public async Task SetMethodFee_Fail_Test() + { + await CreateNativeTokenAsync(); + var tokenSymbol = NativeTokenInfo.Symbol; + var methodName = "Transfer"; + // unauthorized { - await CreateNativeTokenAsync(); - var methodName = "Transfer"; - var tokenSymbol = NativeTokenInfo.Symbol; var basicFee = 100; - var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - string proposalMethodName = nameof(TokenContractStub.SetMethodFee); var methodFees = new MethodFees { MethodName = methodName, Fees = { - new MethodFee{Symbol = tokenSymbol, BasicFee = basicFee} + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } } }; - var proposalId = await CreateProposalAsync(TokenContractAddress, - methodFeeController.OwnerAddress, proposalMethodName, methodFees); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var afterUpdateMethodFees = await TokenContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName - }); - var tokenFee = afterUpdateMethodFees.Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); - tokenFee.BasicFee.ShouldBe(basicFee); + var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + ret.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); } - - [Fact] - public async Task SetMethodFee_Fail_Test() + + // invalid fee { - await CreateNativeTokenAsync(); - var tokenSymbol = NativeTokenInfo.Symbol; - var methodName = "Transfer"; - // unauthorized + var basicFee = 0; + var methodFees = new MethodFees { - var basicFee = 100; - var methodFees = new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = tokenSymbol, BasicFee = basicFee} - } - }; - var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - ret.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); - } + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } + } + }; + var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + ret.TransactionResult.Error.ShouldContain("Invalid amount"); + } - // invalid fee + //invalid token symbol + { + var basicFee = 100; + var methodFees = new MethodFees { - var basicFee = 0; - var methodFees = new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = tokenSymbol, BasicFee = basicFee} - } - }; - var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - ret.TransactionResult.Error.ShouldContain("Invalid amount"); - } - - //invalid token symbol + new MethodFee { Symbol = "NOTEXIST", BasicFee = basicFee } + } + }; + var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + ret.TransactionResult.Error.ShouldContain("Token is not found"); + } + + // token is not profitable + { + var tokenNotProfitable = "DLS"; + await TokenContractStub.Create.SendAsync(new CreateInput { - var basicFee = 100; - var methodFees = new MethodFees - { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = "NOTEXIST", BasicFee = basicFee} - } - }; - var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - ret.TransactionResult.Error.ShouldContain("Token is not found"); - } - - // token is not profitable + Symbol = tokenNotProfitable, + TokenName = "name", + Issuer = DefaultAddress, + TotalSupply = 1000_000 + }); + var methodFees = new MethodFees { - var tokenNotProfitable = "DLS"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenNotProfitable, - TokenName = "name", - Issuer = DefaultAddress, - TotalSupply = 1000_000, - }); - var methodFees = new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = tokenNotProfitable, BasicFee = 100} - } - }; - var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - ret.TransactionResult.Error.ShouldContain($"Token {tokenNotProfitable} cannot set as method fee."); - } + new MethodFee { Symbol = tokenNotProfitable, BasicFee = 100 } + } + }; + var ret = await TokenContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + ret.TransactionResult.Error.ShouldContain($"Token {tokenNotProfitable} cannot set as method fee."); } + } - [Theory] - [InlineData("ClaimTransactionFees", "DonateResourceToken", "ChargeTransactionFees", "CheckThreshold", - "CheckResourceToken", "ChargeResourceToken", "CrossChainReceiveToken")] - public async Task GetMethodFee_No_Fee_Test(params string[] defaultSetMethodNames) + [Theory] + [InlineData("ClaimTransactionFees", "DonateResourceToken", "ChargeTransactionFees", "CheckThreshold", + "CheckResourceToken", "ChargeResourceToken", "CrossChainReceiveToken")] + public async Task GetMethodFee_No_Fee_Test(params string[] defaultSetMethodNames) + { + var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalMethodName = nameof(TokenContractStub.SetMethodFee); + await CreateNativeTokenAsync(); + var tokenSymbol = NativeTokenInfo.Symbol; + var basicFee = 100; + foreach (var methodName in defaultSetMethodNames) { - var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - string proposalMethodName = nameof(TokenContractStub.SetMethodFee); - await CreateNativeTokenAsync(); - var tokenSymbol = NativeTokenInfo.Symbol; - var basicFee = 100; - foreach (var methodName in defaultSetMethodNames) + var methodFees = new MethodFees { - var methodFees = new MethodFees - { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = tokenSymbol, BasicFee = basicFee} - } - }; - var proposalId = await CreateProposalAsync(TokenContractAddress, - methodFeeController.OwnerAddress, proposalMethodName, methodFees); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var updatedMethodFee = await TokenContractStub.GetMethodFee.CallAsync(new StringValue + MethodName = methodName, + Fees = { - Value = methodName - }); - updatedMethodFee.Fees.Count.ShouldBe(0); - } + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } + } + }; + var proposalId = await CreateProposalAsync(TokenContractAddress, + methodFeeController.OwnerAddress, proposalMethodName, methodFees); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var updatedMethodFee = await TokenContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + }); + updatedMethodFee.Fees.Count.ShouldBe(0); } - - [Theory] - [InlineData("Create")] - public async Task GetMethodFee_Fix_Fee_Test(params string[] defaultSetMethodNames) + } + + [Theory] + [InlineData("Create")] + public async Task GetMethodFee_Fix_Fee_Test(params string[] defaultSetMethodNames) + { + var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalMethodName = nameof(TokenContractStub.SetMethodFee); + await CreateNativeTokenAsync(); + var tokenSymbol = NativeTokenInfo.Symbol; + var basicFee = 100; + foreach (var methodName in defaultSetMethodNames) { - var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - string proposalMethodName = nameof(TokenContractStub.SetMethodFee); - await CreateNativeTokenAsync(); - var tokenSymbol = NativeTokenInfo.Symbol; - var basicFee = 100; - foreach (var methodName in defaultSetMethodNames) + var beforeFee = (await TokenContractStub.GetMethodFee.CallAsync(new StringValue { - var beforeFee = (await TokenContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName - })).Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); - var methodFees = new MethodFees - { - MethodName = methodName, - Fees = - { - new MethodFee{Symbol = tokenSymbol, BasicFee = basicFee} - } - }; - var proposalId = await CreateProposalAsync(TokenContractAddress, - methodFeeController.OwnerAddress, proposalMethodName, methodFees); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var updatedFee = (await TokenContractStub.GetMethodFee.CallAsync(new StringValue + Value = methodName + })).Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); + var methodFees = new MethodFees + { + MethodName = methodName, + Fees = { - Value = methodName - })).Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); - updatedFee.BasicFee.ShouldBe(beforeFee.BasicFee); - } + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } + } + }; + var proposalId = await CreateProposalAsync(TokenContractAddress, + methodFeeController.OwnerAddress, proposalMethodName, methodFees); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var updatedFee = (await TokenContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + })).Fees.SingleOrDefault(x => x.Symbol == tokenSymbol); + updatedFee.BasicFee.ShouldBe(beforeFee.BasicFee); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index 6eb76a7950..45da7dc586 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -1,77 +1,74 @@ using System.Threading.Tasks; -using AElf.Standards.ACS2; -using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests { - public partial class MultiTokenContractTests + [Fact] + public async Task ACS2_GetResourceInfo_Transfer_Test() + { + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.Transfer), + new TransferInput + { + Amount = 100, + Symbol = "ELF", + To = Accounts[1].Address, + Memo = "Test get resource" + }); + + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeFalse(); + result.WritePaths.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task ACS2_GetResourceInfo_TransferFrom_Test() + { + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.TransferFrom), + new TransferFromInput + { + Amount = 100, + Symbol = "ELF", + From = Accounts[1].Address, + To = Accounts[2].Address, + Memo = "Test get resource" + }); + + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeFalse(); + result.WritePaths.Count.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task ACS2_GetResourceInfo_DonateResourceToken_Test() { - [Fact] - public async Task ACS2_GetResourceInfo_Transfer_Test() - { - var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.Transfer), - new TransferInput - { - Amount = 100, - Symbol = "ELF", - To = Accounts[1].Address, - Memo = "Test get resource" - }); - - var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); - result.NonParallelizable.ShouldBeFalse(); - result.WritePaths.Count.ShouldBeGreaterThan(0); - } - - [Fact] - public async Task ACS2_GetResourceInfo_TransferFrom_Test() - { - var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.TransferFrom), - new TransferFromInput - { - Amount = 100, - Symbol = "ELF", - From = Accounts[1].Address, - To = Accounts[2].Address, - Memo = "Test get resource" - }); - - var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); - result.NonParallelizable.ShouldBeFalse(); - result.WritePaths.Count.ShouldBeGreaterThan(0); - } - - [Fact] - public async Task ACS2_GetResourceInfo_DonateResourceToken_Test() - { - var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.DonateResourceToken), - new Empty()); - - var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); - result.NonParallelizable.ShouldBeTrue(); - } - - [Fact] - public async Task ACS2_GetResourceInfo_ClaimTransactionFees_Test() - { - var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.ClaimTransactionFees), - new Empty()); - - var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); - result.NonParallelizable.ShouldBeTrue(); - } - - [Fact] - public async Task ACS2_GetResourceInfo_UnsupportedMethod_Test() - { - var transaction = GenerateTokenTransaction(Accounts[0].Address, "TestMethod", - new Empty()); - - var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); - result.NonParallelizable.ShouldBeTrue(); - } + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.DonateResourceToken), + new Empty()); + + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeTrue(); + } + + [Fact] + public async Task ACS2_GetResourceInfo_ClaimTransactionFees_Test() + { + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.ClaimTransactionFees), + new Empty()); + + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeTrue(); + } + + [Fact] + public async Task ACS2_GetResourceInfo_UnsupportedMethod_Test() + { + var transaction = GenerateTokenTransaction(Accounts[0].Address, "TestMethod", + new Empty()); + + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 390b361612..4224b5f107 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -1,1194 +1,1188 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS10; using AElf.Contracts.Consensus.DPoS; using AElf.Contracts.TestContract.BasicFunction; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests { - public partial class MultiTokenContractTests + [Fact(DisplayName = "[MultiToken] Transfer token test")] + public async Task MultiTokenContract_Transfer_Test() { - [Fact(DisplayName = "[MultiToken] Transfer token test")] - public async Task MultiTokenContract_Transfer_Test() + await CreateAndIssueMultiTokensAsync(); + + await TokenContractStub.Transfer.SendAsync(new TransferInput { - await CreateAndIssueMultiTokensAsync(); + Amount = 1000L, + Memo = "transfer test", + Symbol = AliceCoinTokenInfo.Symbol, + To = User1Address + }); - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Amount = 1000L, - Memo = "transfer test", - Symbol = AliceCoinTokenInfo.Symbol, - To = User1Address - }); + var defaultBalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Owner = DefaultAddress + }); + var user1BalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Owner = User1Address + }); - var defaultBalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = AliceCoinTokenInfo.Symbol, - Owner = DefaultAddress - }); - var user1BalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = AliceCoinTokenInfo.Symbol, - Owner = User1Address - }); + defaultBalanceOutput.Balance.ShouldBe(AliceCoinTotalAmount - 1000L); + user1BalanceOutput.Balance.ShouldBe(2000L); + } - defaultBalanceOutput.Balance.ShouldBe(AliceCoinTotalAmount - 1000L); - user1BalanceOutput.Balance.ShouldBe(2000L); - } + [Fact(DisplayName = "[MultiToken] Transfer token out of total amount")] + public async Task MultiTokenContract_Transfer_OutOfAmount_Test() + { + await CreateAndIssueMultiTokensAsync(); - [Fact(DisplayName = "[MultiToken] Transfer token out of total amount")] - public async Task MultiTokenContract_Transfer_OutOfAmount_Test() + var result = (await TokenContractStub.Transfer.SendWithExceptionAsync(new TransferInput + { + Amount = AliceCoinTotalAmount + 1, + Memo = "transfer test", + Symbol = AliceCoinTokenInfo.Symbol, + To = DefaultAddress + })).TransactionResult; + result.Error.ShouldContain("Can't do transfer to sender itself"); + + result = (await TokenContractStub.Transfer.SendWithExceptionAsync(new TransferInput { - await CreateAndIssueMultiTokensAsync(); + Amount = AliceCoinTotalAmount + 1, + Memo = "transfer test", + Symbol = AliceCoinTokenInfo.Symbol, + To = User2Address + })).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain("Insufficient balance"); + } - var result = (await TokenContractStub.Transfer.SendWithExceptionAsync(new TransferInput - { - Amount = AliceCoinTotalAmount + 1, - Memo = "transfer test", - Symbol = AliceCoinTokenInfo.Symbol, - To = DefaultAddress - })).TransactionResult; - result.Error.ShouldContain("Can't do transfer to sender itself"); + private async Task MultiTokenContract_Approve_Test() + { + await CreateAndIssueMultiTokensAsync(); - result = (await TokenContractStub.Transfer.SendWithExceptionAsync(new TransferInput - { - Amount = AliceCoinTotalAmount + 1, - Memo = "transfer test", - Symbol = AliceCoinTokenInfo.Symbol, - To = User2Address - })).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain("Insufficient balance"); - } + var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 2000L, + Spender = User1Address + })).TransactionResult; + approveResult.Status.ShouldBe(TransactionResultStatus.Mined); - private async Task MultiTokenContract_Approve_Test() + var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreateAndIssueMultiTokensAsync(); + Owner = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); + balanceOutput.Balance.ShouldBe(1000L); - var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 2000L, - Spender = User1Address - })).TransactionResult; - approveResult.Status.ShouldBe(TransactionResultStatus.Mined); + var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); + allowanceOutput.Allowance.ShouldBe(2000L); - var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - }); - balanceOutput.Balance.ShouldBe(1000L); + var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 2000L, + Spender = BasicFunctionContractAddress + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - }); - allowanceOutput.Allowance.ShouldBe(2000L); + [Fact(DisplayName = "[MultiToken] Approve token test")] + public async Task MultiTokenContract_Approve_NativeSymbol_Test() + { + await CreateAndIssueMultiTokensAsync(); - var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 2000L, - Spender = BasicFunctionContractAddress - })).TransactionResult; - approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = "ELF", + Amount = 2000L, + Spender = User1Address + })).TransactionResult; + approveResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact(DisplayName = "[MultiToken] Approve token test")] - public async Task MultiTokenContract_Approve_NativeSymbol_Test() + var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreateAndIssueMultiTokensAsync(); + Owner = User1Address, + Symbol = "ELF" + }); + balanceOutput.Balance.ShouldBe(0); - var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = "ELF", - Amount = 2000L, - Spender = User1Address - })).TransactionResult; - approveResult.Status.ShouldBe(TransactionResultStatus.Mined); + var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = User1Address, + Symbol = "ELF" + }); + allowanceOutput.Allowance.ShouldBe(2000L); - var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = "ELF" - }); - balanceOutput.Balance.ShouldBe(0); + var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = "ELF", + Amount = 2000L, + Spender = BasicFunctionContractAddress + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = User1Address, - Symbol = "ELF" - }); - allowanceOutput.Allowance.ShouldBe(2000L); + [Fact(DisplayName = "[MultiToken] Approve token to Contract")] + public async Task MultiTokenContract_Approve_ContractAddress_Test() + { + await CreateTokenAndIssue(); + var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = SymbolForTest, + Amount = 2000L, + Spender = BasicFunctionContractAddress + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); - var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = "ELF", - Amount = 2000L, - Spender = BasicFunctionContractAddress - })).TransactionResult; - approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var basicBalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = BasicFunctionContractAddress, + Symbol = SymbolForTest + }); + basicBalanceOutput.Balance.ShouldBe(0L); - [Fact(DisplayName = "[MultiToken] Approve token to Contract")] - public async Task MultiTokenContract_Approve_ContractAddress_Test() + var basicAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - await CreateTokenAndIssue(); - var approveBasisResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = SymbolForTest, - Amount = 2000L, - Spender = BasicFunctionContractAddress - })).TransactionResult; - approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); + Owner = DefaultAddress, + Spender = BasicFunctionContractAddress, + Symbol = SymbolForTest + }); + basicAllowanceOutput.Allowance.ShouldBe(2000L); + } - var basicBalanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = BasicFunctionContractAddress, - Symbol = SymbolForTest - }); - basicBalanceOutput.Balance.ShouldBe(0L); + [Fact(DisplayName = "[MultiToken] Approve token out of owner's balance")] + public async Task MultiTokenContract_Approve_OutOfAmount_Test() + { + await CreateAndIssueMultiTokensAsync(); - var basicAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = BasicFunctionContractAddress, - Symbol = SymbolForTest - }); - basicAllowanceOutput.Allowance.ShouldBe(2000L); - } + var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Amount = AliceCoinTotalAmount + 1, + Spender = User1Address + })).TransactionResult; - [Fact(DisplayName = "[MultiToken] Approve token out of owner's balance")] - public async Task MultiTokenContract_Approve_OutOfAmount_Test() + approveResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact(DisplayName = "[MultiToken] UnApprove token test")] + public async Task MultiTokenContract_UnApprove_Test() + { + await MultiTokenContract_Approve_Test(); + var unApproveBalance = (await TokenContractStub.UnApprove.SendAsync(new UnApproveInput { - await CreateAndIssueMultiTokensAsync(); + Amount = 1000L, + Symbol = AliceCoinTokenInfo.Symbol, + Spender = User1Address + })).TransactionResult; - var approveResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount + 1, - Spender = User1Address - })).TransactionResult; + unApproveBalance.Status.ShouldBe(TransactionResultStatus.Mined); + var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); + allowanceOutput.Allowance.ShouldBe(2000L - 1000L); + } - approveResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + [Fact] + public async Task MultiTokenContract_UnApprove_OutOfAmount_Test() + { + await CreateAndIssueMultiTokensAsync(); - [Fact(DisplayName = "[MultiToken] UnApprove token test")] - public async Task MultiTokenContract_UnApprove_Test() + var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - await MultiTokenContract_Approve_Test(); - var unApproveBalance = (await TokenContractStub.UnApprove.SendAsync(new UnApproveInput - { - Amount = 1000L, - Symbol = AliceCoinTokenInfo.Symbol, - Spender = User1Address - })).TransactionResult; + Owner = DefaultAddress, + Spender = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); - unApproveBalance.Status.ShouldBe(TransactionResultStatus.Mined); - var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + allowanceOutput.Allowance.ShouldBe(0L); + var result = (await TokenContractStub.UnApprove.SendAsync(new UnApproveInput + { + Amount = 1000L, + Spender = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + })).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact(DisplayName = "[MultiToken] Token transferFrom test")] + public async Task MultiTokenContract_TransferFrom_Test() + { + await MultiTokenContract_Approve_Test(); + var user1Stub = + GetTester(TokenContractAddress, User1KeyPair); + var result2 = await user1Stub.TransferFrom.SendAsync(new TransferFromInput + { + Amount = 1000L, + From = DefaultAddress, + Memo = "test", + Symbol = AliceCoinTokenInfo.Symbol, + To = User1Address + }); + result2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var allowanceOutput2 = + await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { Owner = DefaultAddress, Spender = User1Address, Symbol = AliceCoinTokenInfo.Symbol }); - allowanceOutput.Allowance.ShouldBe(2000L - 1000L); - } + allowanceOutput2.Allowance.ShouldBe(2000L - 1000L); - [Fact] - public async Task MultiTokenContract_UnApprove_OutOfAmount_Test() + var allowanceOutput3 = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreateAndIssueMultiTokensAsync(); + Owner = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); + allowanceOutput3.Balance.ShouldBe(2000L); + } - var allowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - }); + [Fact(DisplayName = "[MultiToken] Token transferFrom with error account")] + public async Task MultiTokenContract_TransferFrom_WithErrorAccount_Test() + { + await MultiTokenContract_Approve_Test(); + var wrongResult = (await TokenContractStub.TransferFrom.SendWithExceptionAsync(new TransferFromInput + { + Amount = 1000L, + From = DefaultAddress, + Memo = "transfer from test", + Symbol = AliceCoinTokenInfo.Symbol, + To = User1Address + })).TransactionResult; + wrongResult.Status.ShouldBe(TransactionResultStatus.Failed); + wrongResult.Error.Contains("Insufficient allowance.").ShouldBeTrue(); + + var allowanceOutput2 = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + }); + allowanceOutput2.Allowance.ShouldBe(2000L); - allowanceOutput.Allowance.ShouldBe(0L); - var result = (await TokenContractStub.UnApprove.SendAsync(new UnApproveInput() - { - Amount = 1000L, - Spender = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - })).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Mined); - } + var balanceOutput3 = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = User1Address, + Symbol = DefaultSymbol + }); + balanceOutput3.Balance.ShouldBe(0L); + } - [Fact(DisplayName = "[MultiToken] Token transferFrom test")] - public async Task MultiTokenContract_TransferFrom_Test() + [Fact(DisplayName = "[MultiToken] Token transferFrom with different memo length.")] + public async Task MultiTokenContract_TransferFrom_MemoLength_Test() + { + await MultiTokenContract_Approve_Test(); + var user1Stub = + GetTester(TokenContractAddress, User1KeyPair); { - await MultiTokenContract_Approve_Test(); - var user1Stub = - GetTester(TokenContractAddress, User1KeyPair); - var result2 = await user1Stub.TransferFrom.SendAsync(new TransferFromInput + var result = await user1Stub.TransferFrom.SendAsync(new TransferFromInput { Amount = 1000L, From = DefaultAddress, - Memo = "test", + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..", Symbol = AliceCoinTokenInfo.Symbol, To = User1Address }); - result2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var allowanceOutput2 = - await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = User1Address, - Symbol = AliceCoinTokenInfo.Symbol, - }); - allowanceOutput2.Allowance.ShouldBe(2000L - 1000L); - - var allowanceOutput3 = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - }); - allowanceOutput3.Balance.ShouldBe(2000L); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - [Fact(DisplayName = "[MultiToken] Token transferFrom with error account")] - public async Task MultiTokenContract_TransferFrom_WithErrorAccount_Test() { - await MultiTokenContract_Approve_Test(); - var wrongResult = (await TokenContractStub.TransferFrom.SendWithExceptionAsync(new TransferFromInput + var result = await user1Stub.TransferFrom.SendWithExceptionAsync(new TransferFromInput { Amount = 1000L, From = DefaultAddress, - Memo = "transfer from test", + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest...", Symbol = AliceCoinTokenInfo.Symbol, To = User1Address - })).TransactionResult; - wrongResult.Status.ShouldBe(TransactionResultStatus.Failed); - wrongResult.Error.Contains("Insufficient allowance.").ShouldBeTrue(); - - var allowanceOutput2 = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Spender = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - }); - allowanceOutput2.Allowance.ShouldBe(2000L); - - var balanceOutput3 = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = DefaultSymbol }); - balanceOutput3.Balance.ShouldBe(0L); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Invalid memo size.").ShouldBeTrue(); } + } - [Fact(DisplayName = "[MultiToken] Token transferFrom with different memo length.")] - public async Task MultiTokenContract_TransferFrom_MemoLength_Test() + [Fact(DisplayName = "[MultiToken] Address is in symbol whitelist.")] + public async Task MultiTokenContract_TransferFrom_WhiteList_Test() + { + await CreateTokenAndIssue(); + var transferAmount = Amount.Div(3); + var beforeTransferBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await MultiTokenContract_Approve_Test(); - var user1Stub = - GetTester(TokenContractAddress, User1KeyPair); - { - var result = await user1Stub.TransferFrom.SendAsync(new TransferFromInput - { - Amount = 1000L, - From = DefaultAddress, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..", - Symbol = AliceCoinTokenInfo.Symbol, - To = User1Address - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - { - var result = await user1Stub.TransferFrom.SendWithExceptionAsync(new TransferFromInput - { - Amount = 1000L, - From = DefaultAddress, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest...", - Symbol = AliceCoinTokenInfo.Symbol, - To = User1Address - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Invalid memo size.").ShouldBeTrue(); + Owner = TreasuryContractAddress, + Symbol = SymbolForTest + }); + beforeTransferBalance.Balance.ShouldBe(0); + var allowance = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Spender = TreasuryContractAddress, + Symbol = SymbolForTest, + Owner = DefaultAddress + }); + allowance.Allowance.ShouldBe(0); + var isInSymbolWhitelist = await TokenContractStub.IsInWhiteList.CallAsync(new IsInWhiteListInput + { + Address = TreasuryContractAddress, + Symbol = SymbolForTest + }); + isInSymbolWhitelist.Value.ShouldBeTrue(); + var beforeTransferFromBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAddress, + Symbol = SymbolForTest + }); + await TreasuryContractStub.Donate.SendAsync(new DonateInput + { + Amount = transferAmount, + Symbol = SymbolForTest + }); + var afterTransferFromBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAddress, + Symbol = SymbolForTest + }); + afterTransferFromBalance.Balance.ShouldBe(beforeTransferFromBalance.Balance.Sub(transferAmount)); + } + + private async Task CreateTokenAndIssue(List
whitelist = null, Address issueTo = null) + { + if (whitelist == null) + whitelist = new List
+ { + BasicFunctionContractAddress, + OtherBasicFunctionContractAddress, + TreasuryContractAddress + }; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = SymbolForTest, + Decimals = 2, + IsBurnable = true, + Issuer = DefaultAddress, + TokenName = "elf test token", + TotalSupply = DPoSContractConsts.LockTokenForElection * 1000000, + LockWhiteList = + { + whitelist } - } + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = SymbolForTest, + Amount = DPoSContractConsts.LockTokenForElection * 200000, + To = issueTo == null ? DefaultAddress : issueTo, + Memo = "Issue" + }); + } + + [Fact(DisplayName = "[MultiToken] Token lock and unlock test")] + public async Task MultiTokenContract_LockAndUnLock_Test() + { + await CreateTokenAndIssue(); - [Fact(DisplayName = "[MultiToken] Address is in symbol whitelist.")] - public async Task MultiTokenContract_TransferFrom_WhiteList_Test() + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreateTokenAndIssue(); - var transferAmount = Amount.Div(3); - var beforeTransferBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TreasuryContractAddress, - Symbol = SymbolForTest - }); - beforeTransferBalance.Balance.ShouldBe(0); - var allowance = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Spender = TreasuryContractAddress, - Symbol = SymbolForTest, - Owner = DefaultAddress - }); - allowance.Allowance.ShouldBe(0); - var isInSymbolWhitelist = await TokenContractStub.IsInWhiteList.CallAsync(new IsInWhiteListInput - { - Address = TreasuryContractAddress, - Symbol = SymbolForTest - }); - isInSymbolWhitelist.Value.ShouldBeTrue(); - var beforeTransferFromBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAddress, - Symbol = SymbolForTest - }); - await TreasuryContractStub.Donate.SendAsync(new DonateInput - { - Amount = transferAmount, - Symbol = SymbolForTest - }); - var afterTransferFromBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + Owner = DefaultAddress, + Symbol = SymbolForTest + })).Balance; + + var lockId = HashHelper.ComputeFrom("lockId"); + + // Lock. + var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Amount = Amount, + Symbol = SymbolForTest, + LockId = lockId, + Usage = "Testing." + })).TransactionResult; + lockTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transferred = new Transferred(); + transferred.MergeFrom(lockTokenResult.Logs.First(l => l.Name == nameof(Transferred))); + // Check balance of user after locking. + { + var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DefaultAddress, Symbol = SymbolForTest }); - afterTransferFromBalance.Balance.ShouldBe(beforeTransferFromBalance.Balance.Sub(transferAmount)); + result.Balance.ShouldBe(beforeBalance - Amount); } - private async Task CreateTokenAndIssue(List
whitelist = null, Address issueTo = null) + // Check locked amount { - if (whitelist == null) - whitelist = new List
- { - BasicFunctionContractAddress, - OtherBasicFunctionContractAddress, - TreasuryContractAddress - }; - await TokenContractStub.Create.SendAsync(new CreateInput + var amount = await BasicFunctionContractStub.GetLockedAmount.CallAsync(new GetLockedTokenAmountInput { Symbol = SymbolForTest, - Decimals = 2, - IsBurnable = true, - Issuer = DefaultAddress, - TokenName = "elf test token", - TotalSupply = DPoSContractConsts.LockTokenForElection * 1000000, - LockWhiteList = - { - whitelist - } - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = SymbolForTest, - Amount = DPoSContractConsts.LockTokenForElection * 200000, - To = issueTo == null ? DefaultAddress : issueTo, - Memo = "Issue" + Address = DefaultAddress, + LockId = lockId }); + amount.Amount.ShouldBe(Amount); } - [Fact(DisplayName = "[MultiToken] Token lock and unlock test")] - public async Task MultiTokenContract_LockAndUnLock_Test() + // Unlock. + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput { - await CreateTokenAndIssue(); - - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() + Address = DefaultAddress, + Amount = Amount, + Symbol = SymbolForTest, + LockId = lockId, + Usage = "Testing." + })).TransactionResult; + unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check balance of user after unlocking. + { + var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DefaultAddress, Symbol = SymbolForTest - })).Balance; - - var lockId = HashHelper.ComputeFrom("lockId"); + }); + result.Balance.ShouldBe(beforeBalance); + } - // Lock. - var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + //Check amount of lock address after unlocking + { + var amount = await BasicFunctionContractStub.GetLockedAmount.CallAsync(new GetLockedTokenAmountInput { - Address = DefaultAddress, - Amount = Amount, Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - lockTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); - var transferred = new Transferred(); - transferred.MergeFrom(lockTokenResult.Logs.First(l => l.Name == nameof(Transferred))); - // Check balance of user after locking. - { - var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultAddress, - Symbol = SymbolForTest - }); - result.Balance.ShouldBe(beforeBalance - Amount); - } - - // Check locked amount - { - var amount = await BasicFunctionContractStub.GetLockedAmount.CallAsync(new GetLockedTokenAmountInput - { - Symbol = SymbolForTest, - Address = DefaultAddress, - LockId = lockId, - }); - amount.Amount.ShouldBe(Amount); - } - - // Unlock. - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput - { Address = DefaultAddress, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); - - // Check balance of user after unlocking. - { - var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultAddress, - Symbol = SymbolForTest - }); - result.Balance.ShouldBe(beforeBalance); - } - - //Check amount of lock address after unlocking - { - var amount = await BasicFunctionContractStub.GetLockedAmount.CallAsync(new GetLockedTokenAmountInput - { - Symbol = SymbolForTest, - Address = DefaultAddress, - LockId = lockId, - }); - amount.Amount.ShouldBe(0); - } + LockId = lockId + }); + amount.Amount.ShouldBe(0); } + } - [Fact(DisplayName = "[MultiToken] Token lock through address not in whitelist")] - public async Task MultiTokenContract_Lock_AddressNotInWhiteList_Test() + [Fact(DisplayName = "[MultiToken] Token lock through address not in whitelist")] + public async Task MultiTokenContract_Lock_AddressNotInWhiteList_Test() + { + await CreateTokenAndIssue(); + + // Try to lock. + var lockId = HashHelper.ComputeFrom("lockId"); + var defaultSenderStub = + GetTester(TokenContractAddress, DefaultKeyPair); + // Lock. + var lockResult = (await defaultSenderStub.Lock.SendWithExceptionAsync(new LockInput { - await CreateTokenAndIssue(); - - // Try to lock. - var lockId = HashHelper.ComputeFrom("lockId"); - var defaultSenderStub = - GetTester(TokenContractAddress, DefaultKeyPair); - // Lock. - var lockResult = (await defaultSenderStub.Lock.SendWithExceptionAsync(new LockInput - { - Address = DefaultAddress, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; + Address = DefaultAddress, + Amount = Amount, + Symbol = SymbolForTest, + LockId = lockId, + Usage = "Testing." + })).TransactionResult; + + lockResult.Status.ShouldBe(TransactionResultStatus.Failed); + lockResult.Error.ShouldContain("No Permission."); + } - lockResult.Status.ShouldBe(TransactionResultStatus.Failed); - lockResult.Error.ShouldContain("No Permission."); - } + [Fact(DisplayName = "[MultiToken] When the allowance is sufficient, Token lock will deduct it")] + public async Task Lock_With_Enough_Allowance_Test() + { + await CreateTokenAndIssue(); + var lockId = HashHelper.ComputeFrom("lockId"); + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Amount = Amount, + Symbol = SymbolForTest, + Spender = BasicFunctionContractAddress + }); - [Fact(DisplayName = "[MultiToken] When the allowance is sufficient, Token lock will deduct it")] - public async Task Lock_With_Enough_Allowance_Test() + var allowanceBeforeLock = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - await CreateTokenAndIssue(); - var lockId = HashHelper.ComputeFrom("lockId"); - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Amount = Amount, - Symbol = SymbolForTest, - Spender = BasicFunctionContractAddress - }); + Owner = DefaultAddress, + Symbol = SymbolForTest, + Spender = BasicFunctionContractAddress + }); + allowanceBeforeLock.Allowance.ShouldBe(Amount); + // Lock. + var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Amount = Amount, + Symbol = SymbolForTest, + LockId = lockId, + Usage = "Testing." + })).TransactionResult; + lockTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); + var allowanceAfterLock = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Symbol = SymbolForTest, + Spender = BasicFunctionContractAddress + }); + allowanceAfterLock.Allowance.ShouldBe(0); + } - var allowanceBeforeLock = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Symbol = SymbolForTest, - Spender = BasicFunctionContractAddress - }); - allowanceBeforeLock.Allowance.ShouldBe(Amount); - // Lock. - var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() - { - Address = DefaultAddress, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - lockTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); - var allowanceAfterLock = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = DefaultAddress, - Symbol = SymbolForTest, - Spender = BasicFunctionContractAddress - }); - allowanceAfterLock.Allowance.ShouldBe(0); - } + [Fact(DisplayName = "[MultiToken] Token lock origin sender != input.Address")] + public async Task MultiTokenContract_Lock_Invalid_Sender_Test() + { + await CreateTokenAndIssue(); + + var lockId = HashHelper.ComputeFrom("lockId"); - [Fact(DisplayName = "[MultiToken] Token lock origin sender != input.Address")] - public async Task MultiTokenContract_Lock_Invalid_Sender_Test() + // Lock. + var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendWithExceptionAsync(new LockTokenInput { - await CreateTokenAndIssue(); + Address = User2Address, + Amount = Amount, + Symbol = SymbolForTest, + LockId = lockId, + Usage = "Testing." + })).TransactionResult; + + lockTokenResult.Status.ShouldBe(TransactionResultStatus.Failed); + lockTokenResult.Error.ShouldContain("Lock behaviour should be initialed by origin address"); + } - var lockId = HashHelper.ComputeFrom("lockId"); + [Fact(DisplayName = "[MultiToken] Token lock with insufficient balance")] + public async Task MultiTokenContract_Lock_WithInsufficientBalance_Test() + { + await CreateTokenAndIssue(); - // Lock. - var lockTokenResult = (await BasicFunctionContractStub.LockToken.SendWithExceptionAsync(new LockTokenInput - { - Address = User2Address, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAddress, + Symbol = SymbolForTest + })).Balance; - lockTokenResult.Status.ShouldBe(TransactionResultStatus.Failed); - lockTokenResult.Error.ShouldContain("Lock behaviour should be initialed by origin address"); - } + var lockId = HashHelper.ComputeFrom("lockId"); + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendWithExceptionAsync(new LockTokenInput + { + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = beforeBalance + 1, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + + lockResult.Status.ShouldBe(TransactionResultStatus.Failed); + lockResult.Error.ShouldContain("Insufficient balance"); + } - [Fact(DisplayName = "[MultiToken] Token lock with insufficient balance")] - public async Task MultiTokenContract_Lock_WithInsufficientBalance_Test() - { - await CreateTokenAndIssue(); + /// + /// It's okay to unlock one locked token to get total amount via several times. + /// + /// + [Fact(DisplayName = "[MultiToken] Token unlock until no balance left")] + public async Task MultiTokenContract_Unlock_repeatedly_Test() + { + await CreateTokenAndIssue(); - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultAddress, - Symbol = SymbolForTest - })).Balance; + var lockId = HashHelper.ComputeFrom("lockId"); - var lockId = HashHelper.ComputeFrom("lockId"); - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendWithExceptionAsync(new LockTokenInput() + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = Amount, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + lockResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Unlock half of the amount at first. + { + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput { Address = DefaultAddress, + Amount = Amount / 2, Symbol = SymbolForTest, - Amount = beforeBalance + 1, LockId = lockId, - Usage = "Testing" + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Failed); - lockResult.Error.ShouldContain("Insufficient balance"); + unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); } - /// - /// It's okay to unlock one locked token to get total amount via several times. - /// - /// - [Fact(DisplayName = "[MultiToken] Token unlock until no balance left")] - public async Task MultiTokenContract_Unlock_repeatedly_Test() + // Unlock another half of the amount. { - await CreateTokenAndIssue(); - - var lockId = HashHelper.ComputeFrom("lockId"); - - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput { Address = DefaultAddress, + Amount = Amount / 2, Symbol = SymbolForTest, - Amount = Amount, LockId = lockId, - Usage = "Testing" + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Mined); - - // Unlock half of the amount at first. - { - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput() - { - Address = DefaultAddress, - Amount = Amount / 2, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - // Unlock another half of the amount. - { - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendAsync(new UnlockTokenInput() + // Cannot keep on unlocking. + { + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( + new UnlockTokenInput { Address = DefaultAddress, - Amount = Amount / 2, + Amount = 1, Symbol = SymbolForTest, LockId = lockId, Usage = "Testing." })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - // Cannot keep on unlocking. - { - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( - new UnlockTokenInput() - { - Address = DefaultAddress, - Amount = 1, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - - unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); - unlockResult.Error.ShouldContain("Insufficient balance"); - } + unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); + unlockResult.Error.ShouldContain("Insufficient balance"); } + } - [Fact(DisplayName = "[MultiToken] Token unlock excess the total amount of lock")] - public async Task MultiTokenContract_Unlock_ExcessAmount_Test() - { - await CreateTokenAndIssue(); + [Fact(DisplayName = "[MultiToken] Token unlock excess the total amount of lock")] + public async Task MultiTokenContract_Unlock_ExcessAmount_Test() + { + await CreateTokenAndIssue(); + + var lockId = HashHelper.ComputeFrom("lockId"); - var lockId = HashHelper.ComputeFrom("lockId"); + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = Amount, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + lockResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( + new UnlockTokenInput { Address = DefaultAddress, + Amount = Amount + 1, Symbol = SymbolForTest, - Amount = Amount, LockId = lockId, - Usage = "Testing" + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Mined); + unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); + unlockResult.Error.ShouldContain("Insufficient balance"); + } - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( - new UnlockTokenInput() - { - Address = DefaultAddress, - Amount = Amount + 1, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); - unlockResult.Error.ShouldContain("Insufficient balance"); - } + [Fact(DisplayName = "[MultiToken] A locked his tokens, B want to unlock with A's lock id'.")] + public async Task MultiTokenContract_Unlock_NotLocker_Test() + { + await CreateTokenAndIssue(); - [Fact(DisplayName = "[MultiToken] A locked his tokens, B want to unlock with A's lock id'.")] - public async Task MultiTokenContract_Unlock_NotLocker_Test() + var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreateTokenAndIssue(); + Owner = DefaultAddress, + Symbol = SymbolForTest + })).Balance; + + var lockId = HashHelper.ComputeFrom("lockId"); - var beforeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = Amount, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + lockResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check balance after locking. + { + var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DefaultAddress, Symbol = SymbolForTest - })).Balance; - - var lockId = HashHelper.ComputeFrom("lockId"); + }); + result.Balance.ShouldBe(beforeBalance - Amount); + } - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() + var unlockResult = (await OtherBasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( + new UnlockTokenInput { Address = DefaultAddress, - Symbol = SymbolForTest, Amount = Amount, + Symbol = SymbolForTest, LockId = lockId, - Usage = "Testing" + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Mined); + unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); + unlockResult.Error.ShouldContain("Insufficient balance"); + } - // Check balance after locking. - { - var result = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultAddress, - Symbol = SymbolForTest - }); - result.Balance.ShouldBe(beforeBalance - Amount); - } + [Fact(DisplayName = + "[MultiToken] Unlock the token through strange lockId which is different from locking lockId")] + public async Task MultiTokenContract_Unlock_StrangeLockId_Test() + { + await CreateTokenAndIssue(); - var unlockResult = (await OtherBasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( - new UnlockTokenInput() - { - Address = DefaultAddress, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); - unlockResult.Error.ShouldContain("Insufficient balance"); - } + var lockId = HashHelper.ComputeFrom("lockId"); - [Fact(DisplayName = - "[MultiToken] Unlock the token through strange lockId which is different from locking lockId")] - public async Task MultiTokenContract_Unlock_StrangeLockId_Test() + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput { - await CreateTokenAndIssue(); - - var lockId = HashHelper.ComputeFrom("lockId"); + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = Amount, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + lockResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( + new UnlockTokenInput { Address = DefaultAddress, - Symbol = SymbolForTest, Amount = Amount, - LockId = lockId, - Usage = "Testing" + Symbol = SymbolForTest, + LockId = HashHelper.ComputeFrom("lockId1"), + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Mined); + unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); + unlockResult.Error.ShouldContain("Insufficient balance"); + } - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( - new UnlockTokenInput() - { - Address = DefaultAddress, - Amount = Amount, - Symbol = SymbolForTest, - LockId = HashHelper.ComputeFrom("lockId1"), - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); - unlockResult.Error.ShouldContain("Insufficient balance"); - } + [Fact(DisplayName = "[MultiToken] Unlock the token to another address that isn't the address locked")] + public async Task MultiTokenContract_Unlock_ToOtherAddress_Test() + { + await CreateTokenAndIssue(); - [Fact(DisplayName = "[MultiToken] Unlock the token to another address that isn't the address locked")] - public async Task MultiTokenContract_Unlock_ToOtherAddress_Test() - { - await CreateTokenAndIssue(); + var lockId = HashHelper.ComputeFrom("lockId"); - var lockId = HashHelper.ComputeFrom("lockId"); + // Lock. + var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput + { + Address = DefaultAddress, + Symbol = SymbolForTest, + Amount = Amount, + LockId = lockId, + Usage = "Testing" + })).TransactionResult; + lockResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Lock. - var lockResult = (await BasicFunctionContractStub.LockToken.SendAsync(new LockTokenInput() + var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( + new UnlockTokenInput { - Address = DefaultAddress, - Symbol = SymbolForTest, + Address = User2Address, Amount = Amount, + Symbol = SymbolForTest, LockId = lockId, - Usage = "Testing" + Usage = "Testing." })).TransactionResult; - lockResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var unlockResult = (await BasicFunctionContractStub.UnlockToken.SendWithExceptionAsync( - new UnlockTokenInput - { - Address = User2Address, - Amount = Amount, - Symbol = SymbolForTest, - LockId = lockId, - Usage = "Testing." - })).TransactionResult; - unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); - unlockResult.Error.ShouldContain("Unlock behaviour should be initialed by origin address."); - } + unlockResult.Status.ShouldBe(TransactionResultStatus.Failed); + unlockResult.Error.ShouldContain("Unlock behaviour should be initialed by origin address."); + } - [Fact(DisplayName = "[MultiToken] Token Burn Test")] - public async Task MultiTokenContract_Burn_Test() + [Fact(DisplayName = "[MultiToken] Token Burn Test")] + public async Task MultiTokenContract_Burn_Test() + { + await CreateAndIssueMultiTokensAsync(); + await TokenContractStub.Burn.SendAsync(new BurnInput { - await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Burn.SendAsync(new BurnInput - { - Amount = 3000L, - Symbol = AliceCoinTokenInfo.Symbol - }); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAddress, - Symbol = AliceCoinTokenInfo.Symbol - }); - balance.Balance.ShouldBe(AliceCoinTotalAmount - 3000L); - } + Amount = 3000L, + Symbol = AliceCoinTokenInfo.Symbol + }); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAddress, + Symbol = AliceCoinTokenInfo.Symbol + }); + balance.Balance.ShouldBe(AliceCoinTotalAmount - 3000L); + } - [Fact(DisplayName = "[MultiToken] Token Burn invalid token")] - public async Task MultiTokenContract_Burn_Invalid_Token_Test() + [Fact(DisplayName = "[MultiToken] Token Burn invalid token")] + public async Task MultiTokenContract_Burn_Invalid_Token_Test() + { + await CreateAndIssueMultiTokensAsync(); + var unburnedTokenSymbol = "UNBURNED"; + await TokenContractStub.Create.SendAsync(new CreateInput { - await CreateAndIssueMultiTokensAsync(); - var unburnedTokenSymbol = "UNBURNED"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = unburnedTokenSymbol, - TokenName = "Name", - TotalSupply = 100_000_000_000L, - Decimals = 10, - IsBurnable = false, - Issuer = DefaultAddress - }); - var burnRet = await TokenContractStub.Burn.SendWithExceptionAsync(new BurnInput - { - Amount = 3000L, - Symbol = unburnedTokenSymbol - }); - burnRet.TransactionResult.Error.ShouldContain("The token is not burnable"); - } + Symbol = unburnedTokenSymbol, + TokenName = "Name", + TotalSupply = 100_000_000_000L, + Decimals = 10, + IsBurnable = false, + Issuer = DefaultAddress + }); + var burnRet = await TokenContractStub.Burn.SendWithExceptionAsync(new BurnInput + { + Amount = 3000L, + Symbol = unburnedTokenSymbol + }); + burnRet.TransactionResult.Error.ShouldContain("The token is not burnable"); + } - [Fact(DisplayName = "[MultiToken] Token Burn the amount greater than it's amount")] - public async Task MultiTokenContract_Burn_BeyondBalance_Test() + [Fact(DisplayName = "[MultiToken] Token Burn the amount greater than it's amount")] + public async Task MultiTokenContract_Burn_BeyondBalance_Test() + { + await CreateAndIssueMultiTokensAsync(); + var user1Stub = + GetTester(TokenContractAddress, User1KeyPair); + var result = (await user1Stub.Burn.SendWithExceptionAsync(new BurnInput { - await CreateAndIssueMultiTokensAsync(); - var user1Stub = - GetTester(TokenContractAddress, User1KeyPair); - var result = (await user1Stub.Burn.SendWithExceptionAsync(new BurnInput + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 3000L + })).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain("Insufficient balance"); + } + + [Fact(DisplayName = "[MultiToken] Token TransferToContract test")] + public async Task MultiTokenContract_TransferToContract_Test() + { + await MultiTokenContract_Approve_Test(); + + var result = (await BasicFunctionContractStub.TransferTokenToContract.SendAsync( + new TransferTokenToContractInput { + Amount = 1000L, Symbol = AliceCoinTokenInfo.Symbol, - Amount = 3000L + Memo = "TransferToContract test" })).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain("Insufficient balance"); - } + result.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact(DisplayName = "[MultiToken] Token TransferToContract test")] - public async Task MultiTokenContract_TransferToContract_Test() + var originAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - await MultiTokenContract_Approve_Test(); + Symbol = AliceCoinTokenInfo.Symbol, + Spender = BasicFunctionContractAddress, + Owner = DefaultAddress + }); + originAllowanceOutput.Allowance.ShouldBe(1000L); - var result = (await BasicFunctionContractStub.TransferTokenToContract.SendAsync( - new TransferTokenToContractInput - { - Amount = 1000L, - Symbol = AliceCoinTokenInfo.Symbol, - Memo = "TransferToContract test" - })).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Mined); + var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = BasicFunctionContractAddress, + Symbol = AliceCoinTokenInfo.Symbol + }); + balanceOutput.Balance.ShouldBe(1000L); - var originAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + //allowance not enough + var result1 = (await BasicFunctionContractStub.TransferTokenToContract.SendAsync( + new TransferTokenToContractInput { + Amount = 2000L, Symbol = AliceCoinTokenInfo.Symbol, - Spender = BasicFunctionContractAddress, - Owner = DefaultAddress - }); - originAllowanceOutput.Allowance.ShouldBe(1000L); - - var balanceOutput = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = BasicFunctionContractAddress, - Symbol = AliceCoinTokenInfo.Symbol - }); - balanceOutput.Balance.ShouldBe(1000L); + Memo = "TransferToContract test" + })).TransactionResult; + result1.Status.ShouldBe(TransactionResultStatus.Mined); + } - //allowance not enough - var result1 = (await BasicFunctionContractStub.TransferTokenToContract.SendAsync( - new TransferTokenToContractInput - { - Amount = 2000L, - Symbol = AliceCoinTokenInfo.Symbol, - Memo = "TransferToContract test" - })).TransactionResult; - result1.Status.ShouldBe(TransactionResultStatus.Mined); - } + [Fact(DisplayName = "[MultiToken] invalid token symbol or amount")] + public async Task TransferToContract_With_Invalid_Input_Test() + { + await CreateTokenAndIssue(); + var ret = await TokenContractStub.TransferToContract.SendWithExceptionAsync(new TransferToContractInput + { + Amount = -1, + Symbol = SymbolForTest + }); + ret.TransactionResult.Error.ShouldContain("Invalid amount"); - [Fact(DisplayName = "[MultiToken] invalid token symbol or amount")] - public async Task TransferToContract_With_Invalid_Input_Test() + ret = await TokenContractStub.TransferToContract.SendWithExceptionAsync(new TransferToContractInput { - await CreateTokenAndIssue(); - var ret = await TokenContractStub.TransferToContract.SendWithExceptionAsync(new TransferToContractInput + Amount = 100, + Symbol = "NOTEXIST" + }); + ret.TransactionResult.Error.ShouldContain("Token is not found"); + } + + [Fact(DisplayName = "[MultiToken] sender is in whitelist, without approve, Token TransferToContract test")] + public async Task TransferToContract_Out_Whitelist_Without_Approve_Test() + { + await CreateTokenAndIssue(new List
()); + var transferAmount = Amount.Div(2); + var transferResult = await BasicFunctionContractStub.TransferTokenToContract.SendWithExceptionAsync( + new TransferTokenToContractInput { - Amount = -1, - Symbol = SymbolForTest, + Amount = transferAmount, + Symbol = SymbolForTest }); - ret.TransactionResult.Error.ShouldContain("Invalid amount"); - - ret = await TokenContractStub.TransferToContract.SendWithExceptionAsync(new TransferToContractInput + transferResult.TransactionResult.Error.ShouldContain("Insufficient allowance"); + } + + [Fact(DisplayName = "[MultiToken] sender is in whitelist, without approve, Token TransferToContract test")] + public async Task TransferToContract_In_Whitelist_Without_Approve_Test() + { + await CreateTokenAndIssue(); + var transferAmount = Amount.Div(2); + var beforeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = SymbolForTest, + Owner = BasicFunctionContractAddress + }); + await BasicFunctionContractStub.TransferTokenToContract.SendAsync( + new TransferTokenToContractInput { - Amount = 100, - Symbol = "NOTEXIST" + Amount = transferAmount, + Symbol = SymbolForTest }); - ret.TransactionResult.Error.ShouldContain("Token is not found"); - } + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = SymbolForTest, + Owner = BasicFunctionContractAddress + }); + afterBalance.Balance.ShouldBe(beforeBalance.Balance.Add(transferAmount)); + } - [Fact(DisplayName = "[MultiToken] sender is in whitelist, without approve, Token TransferToContract test")] - public async Task TransferToContract_Out_Whitelist_Without_Approve_Test() + [Fact(DisplayName = "[MultiToken] ChangeTokenIssuer test")] + public async Task ChangeTokenIssuer_Test() + { + const string tokenSymbol = "PO"; + await CreateAndIssueMultiTokensAsync(); + await TokenContractStub.Create.SendAsync(new CreateInput { - await CreateTokenAndIssue(new List
()); - var transferAmount = Amount.Div(2); - var transferResult = await BasicFunctionContractStub.TransferTokenToContract.SendWithExceptionAsync( - new TransferTokenToContractInput - { - Amount = transferAmount, - Symbol = SymbolForTest - }); - transferResult.TransactionResult.Error.ShouldContain("Insufficient allowance"); - } + Symbol = tokenSymbol, + TokenName = "Name", + TotalSupply = 100_000_000_000L, + Decimals = 10, + IsBurnable = true, + Issuer = Accounts[1].Address + }); + var tokenIssuerStub = + GetTester(TokenContractAddress, Accounts[1].KeyPair); - [Fact(DisplayName = "[MultiToken] sender is in whitelist, without approve, Token TransferToContract test")] - public async Task TransferToContract_In_Whitelist_Without_Approve_Test() { - await CreateTokenAndIssue(); - var transferAmount = Amount.Div(2); - var beforeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = SymbolForTest, - Owner = BasicFunctionContractAddress - }); - await BasicFunctionContractStub.TransferTokenToContract.SendAsync( - new TransferTokenToContractInput + var issueNotExistTokenRet = await tokenIssuerStub.ChangeTokenIssuer.SendWithExceptionAsync( + new ChangeTokenIssuerInput { - Amount = transferAmount, - Symbol = SymbolForTest + Symbol = "NOTEXIST", + NewTokenIssuer = Accounts[2].Address }); - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = SymbolForTest, - Owner = BasicFunctionContractAddress - }); - afterBalance.Balance.ShouldBe(beforeBalance.Balance.Add(transferAmount)); + issueNotExistTokenRet.TransactionResult.Error.ShouldContain("invalid token symbol"); } - - [Fact(DisplayName = "[MultiToken] ChangeTokenIssuer test")] - public async Task ChangeTokenIssuer_Test() { - const string tokenSymbol = "PO"; - await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + await tokenIssuerStub.ChangeTokenIssuer.SendAsync(new ChangeTokenIssuerInput { Symbol = tokenSymbol, - TokenName = "Name", - TotalSupply = 100_000_000_000L, - Decimals = 10, - IsBurnable = true, - Issuer = Accounts[1].Address + NewTokenIssuer = Accounts[2].Address }); - var tokenIssuerStub = - GetTester(TokenContractAddress, Accounts[1].KeyPair); - + var tokenInfo = await tokenIssuerStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var issueNotExistTokenRet = await tokenIssuerStub.ChangeTokenIssuer.SendWithExceptionAsync( - new ChangeTokenIssuerInput - { - Symbol = "NOTEXIST", - NewTokenIssuer = Accounts[2].Address - }); - issueNotExistTokenRet.TransactionResult.Error.ShouldContain("invalid token symbol"); - } - { - await tokenIssuerStub.ChangeTokenIssuer.SendAsync(new ChangeTokenIssuerInput - { - Symbol = tokenSymbol, - NewTokenIssuer = Accounts[2].Address - }); - var tokenInfo = await tokenIssuerStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = tokenSymbol - }); - tokenInfo.Issuer.ShouldBe(Accounts[2].Address); - } + Symbol = tokenSymbol + }); + tokenInfo.Issuer.ShouldBe(Accounts[2].Address); } + } - [Fact(DisplayName = "[MultiToken] sender is not the token issuer")] - public async Task ChangeTokenIssuer_Without_Authorization_Test() + [Fact(DisplayName = "[MultiToken] sender is not the token issuer")] + public async Task ChangeTokenIssuer_Without_Authorization_Test() + { + const string tokenSymbol = "PO"; + await CreateAndIssueMultiTokensAsync(); + await TokenContractStub.Create.SendAsync(new CreateInput { - const string tokenSymbol = "PO"; - await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + Symbol = tokenSymbol, + TokenName = "Name", + TotalSupply = 100_000_000_000L, + Decimals = 10, + IsBurnable = true, + Issuer = Accounts[1].Address + }); + var changeIssuerRet = await TokenContractStub.ChangeTokenIssuer.SendWithExceptionAsync( + new ChangeTokenIssuerInput { Symbol = tokenSymbol, - TokenName = "Name", - TotalSupply = 100_000_000_000L, - Decimals = 10, - IsBurnable = true, - Issuer = Accounts[1].Address + NewTokenIssuer = Accounts[2].Address }); - var changeIssuerRet = await TokenContractStub.ChangeTokenIssuer.SendWithExceptionAsync( - new ChangeTokenIssuerInput - { - Symbol = tokenSymbol, - NewTokenIssuer = Accounts[2].Address - }); - changeIssuerRet.TransactionResult.Error.ShouldContain("permission denied"); - } + changeIssuerRet.TransactionResult.Error.ShouldContain("permission denied"); + } - [Fact(DisplayName = "[MultiToken] Token initialize from parent chain test")] - public async Task InitializeFromParent_Test() - { - var netSymbol = "NET"; - var initializedFromParentRet = - await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( - new InitializeFromParentChainInput()); - initializedFromParentRet.TransactionResult.Error.ShouldContain("creator should not be null"); - initializedFromParentRet = - await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( - new InitializeFromParentChainInput - { - Creator = DefaultAddress - }); - initializedFromParentRet.TransactionResult.Error.ShouldContain("No permission"); - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultParliament, nameof(TokenContractStub.InitializeFromParentChain), + [Fact(DisplayName = "[MultiToken] Token initialize from parent chain test")] + public async Task InitializeFromParent_Test() + { + var netSymbol = "NET"; + var initializedFromParentRet = + await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( + new InitializeFromParentChainInput()); + initializedFromParentRet.TransactionResult.Error.ShouldContain("creator should not be null"); + initializedFromParentRet = + await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( new InitializeFromParentChainInput { - Creator = DefaultAddress, - ResourceAmount = {{netSymbol, 100}}, - RegisteredOtherTokenContractAddresses = {{1, ParliamentContractAddress}} - }); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - var resourceAmountDic = await TokenContractStub.GetResourceUsage.CallAsync(new Empty()); - resourceAmountDic.Value[netSymbol].ShouldBe(100); - var chainWhitelist = await TokenContractStub.GetCrossChainTransferTokenContractAddress.CallAsync( - new GetCrossChainTransferTokenContractAddressInput - { - ChainId = 1 + Creator = DefaultAddress }); - chainWhitelist.ShouldBe(ParliamentContractAddress); - initializedFromParentRet = - await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( - new InitializeFromParentChainInput - { - Creator = DefaultAddress - }); - initializedFromParentRet.TransactionResult.Error.ShouldContain("MultiToken has been initialized"); - } - - [Fact(DisplayName = "[MultiToken] Side chain send create token")] - public async Task Side_Chain_Creat_Token_Test() - { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultParliament, nameof(TokenContractStub.InitializeFromParentChain), + initializedFromParentRet.TransactionResult.Error.ShouldContain("No permission"); + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliament, nameof(TokenContractStub.InitializeFromParentChain), + new InitializeFromParentChainInput + { + Creator = DefaultAddress, + ResourceAmount = { { netSymbol, 100 } }, + RegisteredOtherTokenContractAddresses = { { 1, ParliamentContractAddress } } + }); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var resourceAmountDic = await TokenContractStub.GetResourceUsage.CallAsync(new Empty()); + resourceAmountDic.Value[netSymbol].ShouldBe(100); + var chainWhitelist = await TokenContractStub.GetCrossChainTransferTokenContractAddress.CallAsync( + new GetCrossChainTransferTokenContractAddressInput + { + ChainId = 1 + }); + chainWhitelist.ShouldBe(ParliamentContractAddress); + initializedFromParentRet = + await TokenContractStub.InitializeFromParentChain.SendWithExceptionAsync( new InitializeFromParentChainInput { Creator = DefaultAddress }); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + initializedFromParentRet.TransactionResult.Error.ShouldContain("MultiToken has been initialized"); + } + + [Fact(DisplayName = "[MultiToken] Side chain send create token")] + public async Task Side_Chain_Creat_Token_Test() + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliament, nameof(TokenContractStub.InitializeFromParentChain), + new InitializeFromParentChainInput { - Symbol = "ALI", - TokenName = "Ali", - Decimals = 4, - TotalSupply = 100_000, - Issuer = DefaultAddress, + Creator = DefaultAddress }); - createTokenRet.TransactionResult.Error.ShouldContain( - "Failed to create token if side chain creator already set."); - } + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + { + Symbol = "ALI", + TokenName = "Ali", + Decimals = 4, + TotalSupply = 100_000, + Issuer = DefaultAddress + }); + createTokenRet.TransactionResult.Error.ShouldContain( + "Failed to create token if side chain creator already set."); + } - [Theory] - [InlineData(10000, 1000, 0, 999, false, false)] - [InlineData(10000, 1000, 0, 1001, false, true)] - [InlineData(10000, 1000, 600, 599, true, false)] - [InlineData(10000, 1000, 600, 601, true, true)] - public async Task CheckThreshold_With_One_Token_Test(long totalSupply, long issueAmount, long ApproveAmount, - long checkAmount, bool isCheckAllowance, bool isThrowException) - { - await CreateNativeTokenAsync(); - var tokenA = "AITA"; - await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, totalSupply, issueAmount); - if (ApproveAmount > 0) + [Theory] + [InlineData(10000, 1000, 0, 999, false, false)] + [InlineData(10000, 1000, 0, 1001, false, true)] + [InlineData(10000, 1000, 600, 599, true, false)] + [InlineData(10000, 1000, 600, 601, true, true)] + public async Task CheckThreshold_With_One_Token_Test(long totalSupply, long issueAmount, long ApproveAmount, + long checkAmount, bool isCheckAllowance, bool isThrowException) + { + await CreateNativeTokenAsync(); + var tokenA = "AITA"; + await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, totalSupply, issueAmount); + if (ApproveAmount > 0) + await TokenContractStub.Approve.SendAsync(new ApproveInput { - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Amount = ApproveAmount, - Spender = DefaultAddress, - Symbol = tokenA - }); - } + Amount = ApproveAmount, + Spender = DefaultAddress, + Symbol = tokenA + }); - if (isThrowException) - { - var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendWithExceptionAsync( - new CheckThresholdInput - { - IsCheckAllowance = isCheckAllowance, - Sender = DefaultAddress, - SymbolToThreshold = {{tokenA, checkAmount}} - }); - checkSufficientBalance.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold"); - } - else - { - var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendAsync(new CheckThresholdInput + if (isThrowException) + { + var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendWithExceptionAsync( + new CheckThresholdInput { IsCheckAllowance = isCheckAllowance, Sender = DefaultAddress, - SymbolToThreshold = {{tokenA, checkAmount}} + SymbolToThreshold = { { tokenA, checkAmount } } }); - checkSufficientBalance.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + checkSufficientBalance.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold"); } - - [Theory] - [InlineData(999, 0, 1000, 0, false, false)] - [InlineData(1001, 0, 999, 0, false, false)] - [InlineData(1001, 0, 1001, 0, false, true)] - [InlineData(1001, 600, 1001, 600, true, true)] - [InlineData(601, 600, 601, 600, true, true)] - [InlineData(601, 600, 599, 600, true, false)] - public async Task CheckThreshold_With_Multiple_Token_Test(long tokenACheckAmount, long tokenAApporveAmount, - long tokenBCheckAmount, long tokenBApporveAmount, bool isCheckAllowance, bool isThrowException) - { - await CreateNativeTokenAsync(); - var tokenA = "AITA"; - await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, 10000, 1000); - var tokenB = "AITB"; - await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenB, 10000, 1000); - if (tokenAApporveAmount > 0) + else + { + var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendAsync(new CheckThresholdInput { - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Amount = tokenAApporveAmount, - Spender = DefaultAddress, - Symbol = tokenA - }); - } + IsCheckAllowance = isCheckAllowance, + Sender = DefaultAddress, + SymbolToThreshold = { { tokenA, checkAmount } } + }); + checkSufficientBalance.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + } - if (tokenBApporveAmount > 0) + [Theory] + [InlineData(999, 0, 1000, 0, false, false)] + [InlineData(1001, 0, 999, 0, false, false)] + [InlineData(1001, 0, 1001, 0, false, true)] + [InlineData(1001, 600, 1001, 600, true, true)] + [InlineData(601, 600, 601, 600, true, true)] + [InlineData(601, 600, 599, 600, true, false)] + public async Task CheckThreshold_With_Multiple_Token_Test(long tokenACheckAmount, long tokenAApporveAmount, + long tokenBCheckAmount, long tokenBApporveAmount, bool isCheckAllowance, bool isThrowException) + { + await CreateNativeTokenAsync(); + var tokenA = "AITA"; + await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, 10000, 1000); + var tokenB = "AITB"; + await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenB, 10000, 1000); + if (tokenAApporveAmount > 0) + await TokenContractStub.Approve.SendAsync(new ApproveInput { - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Amount = tokenBApporveAmount, - Spender = DefaultAddress, - Symbol = tokenB - }); - } + Amount = tokenAApporveAmount, + Spender = DefaultAddress, + Symbol = tokenA + }); - if (isThrowException) - { - var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendWithExceptionAsync( - new CheckThresholdInput - { - IsCheckAllowance = isCheckAllowance, - Sender = DefaultAddress, - SymbolToThreshold = {{tokenA, tokenACheckAmount}, {tokenB, tokenBCheckAmount}} - }); - checkSufficientBalance.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold"); - } - else + if (tokenBApporveAmount > 0) + await TokenContractStub.Approve.SendAsync(new ApproveInput { - var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendAsync(new CheckThresholdInput + Amount = tokenBApporveAmount, + Spender = DefaultAddress, + Symbol = tokenB + }); + + if (isThrowException) + { + var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendWithExceptionAsync( + new CheckThresholdInput { IsCheckAllowance = isCheckAllowance, Sender = DefaultAddress, - SymbolToThreshold = {{tokenA, tokenACheckAmount}, {tokenB, tokenBCheckAmount}} + SymbolToThreshold = { { tokenA, tokenACheckAmount }, { tokenB, tokenBCheckAmount } } }); - checkSufficientBalance.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + checkSufficientBalance.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold"); } - - private async Task CreateAndIssueCustomizeTokenAsync(Address creator, string symbol, long totalSupply, long issueAmount, - Address to = null, params string[] otherParameters) + else { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - Issuer = creator, - TokenName = symbol + "name", - TotalSupply = totalSupply, - Decimals = 4 - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + var checkSufficientBalance = await TokenContractStub.CheckThreshold.SendAsync(new CheckThresholdInput { - Symbol = symbol, - Amount = issueAmount, - To = to == null ? creator : to + IsCheckAllowance = isCheckAllowance, + Sender = DefaultAddress, + SymbolToThreshold = { { tokenA, tokenACheckAmount }, { tokenB, tokenBCheckAmount } } }); + checkSufficientBalance.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } + + private async Task CreateAndIssueCustomizeTokenAsync(Address creator, string symbol, long totalSupply, + long issueAmount, + Address to = null, params string[] otherParameters) + { + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = symbol, + Issuer = creator, + TokenName = symbol + "name", + TotalSupply = totalSupply, + Decimals = 4 + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = symbol, + Amount = issueAmount, + To = to == null ? creator : to + }); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs index df905e93f1..d35af8163a 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs @@ -1,81 +1,78 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Types; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests { - public partial class MultiTokenContractTests + private async Task InitialEconomicAsync() { - private async Task InitialEconomicAsync() { + const long totalSupply = 100_000_00000000; + await TokenContractStub.Create.SendAsync(new CreateInput { - const long totalSupply = 100_000_00000000; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = DefaultSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultAddress, - LockWhiteList = { TreasuryContractAddress } - }); - await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = DefaultSymbol, - Amount = totalSupply, - To = DefaultAddress, - Memo = "Set for token converter." - }); - } - { - var result = - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - } + Symbol = DefaultSymbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultAddress, + LockWhiteList = { TreasuryContractAddress } + }); + await TokenContractStub.Issue.SendAsync(new IssueInput { - var result = - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( - new Empty()); - } + Symbol = DefaultSymbol, + Amount = totalSupply, + To = DefaultAddress, + Memo = "Set for token converter." + }); + } + { + var result = + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + } + { + var result = + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( + new Empty()); + } + { + var result = (await TokenContractStub.Create.SendAsync(new CreateInput { - var result = (await TokenContractStub.Create.SendAsync(new CreateInput + Symbol = AliceCoinTokenInfo.Symbol, + TokenName = "Native Token", + TotalSupply = AliceCoinTotalAmount, + Decimals = 2, + IsBurnable = true, + Issuer = DefaultAddress, + LockWhiteList = { - Symbol = AliceCoinTokenInfo.Symbol, - TokenName = "Native Token", - TotalSupply = AliceCoinTotalAmount, - Decimals = 2, - IsBurnable = true, - Issuer = DefaultAddress, - LockWhiteList = - { - ParliamentContractAddress, - TreasuryContractAddress - } - })).TransactionResult; - } + ParliamentContractAddress, + TreasuryContractAddress + } + })).TransactionResult; + } + { + AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput { - AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 100_000_000L, - To = DefaultAddress, - Memo = "Set for token converter." - })); - } + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 100_000_000L, + To = DefaultAddress, + Memo = "Set for token converter." + })); + } + { + AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput { - AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount - 100_000_000L, - To = TokenContractAddress, - Memo = "Set for token converter." - })); - } + Symbol = AliceCoinTokenInfo.Symbol, + Amount = AliceCoinTotalAmount - 100_000_000L, + To = TokenContractAddress, + Memo = "Set for token converter." + })); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index b5d98bbf95..91e611aca3 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -6,54 +6,30 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests { - public partial class MultiTokenContractTests + [Fact(DisplayName = "[MultiToken] advance token not exist in resource token")] + public async Task AdvancedResourceToken_Test() { - [Fact(DisplayName = "[MultiToken] advance token not exist in resource token")] - public async Task AdvancedResourceToken_Test() + await CreateNativeTokenAsync(); + long advanceAmount = 1000; { - await CreateNativeTokenAsync(); - long advanceAmount = 1000; - { - var tokenNotResrouce = "NORESOURCE"; - await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenNotResrouce, 10000, 10000); - var advanceRet = await TokenContractStub.AdvanceResourceToken.SendWithExceptionAsync( - new AdvanceResourceTokenInput - { - ContractAddress = BasicFunctionContractAddress, - Amount = advanceAmount, - ResourceTokenSymbol = tokenNotResrouce - }); - advanceRet.TransactionResult.Error.ShouldContain("invalid resource token symbol"); - } - - { - var trafficToken = "TRAFFIC"; - await CreateAndIssueCustomizeTokenAsync(DefaultAddress, trafficToken, 10000, 10000); - var advanceRet = await TokenContractStub.AdvanceResourceToken.SendAsync( - new AdvanceResourceTokenInput - { - ContractAddress = BasicFunctionContractAddress, - Amount = advanceAmount, - ResourceTokenSymbol = trafficToken - }); - advanceRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var tokenNotResrouce = "NORESOURCE"; + await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenNotResrouce, 10000, 10000); + var advanceRet = await TokenContractStub.AdvanceResourceToken.SendWithExceptionAsync( + new AdvanceResourceTokenInput { - Symbol = trafficToken, - Owner = BasicFunctionContractAddress + ContractAddress = BasicFunctionContractAddress, + Amount = advanceAmount, + ResourceTokenSymbol = tokenNotResrouce }); - balance.Balance.ShouldBe(advanceAmount); - } + advanceRet.TransactionResult.Error.ShouldContain("invalid resource token symbol"); } - [Fact(DisplayName = "[MultiToken] take more token than that of the contract address's balance")] - public async Task TakeResourceTokenBack_Test() { - await CreateNativeTokenAsync(); var trafficToken = "TRAFFIC"; - var advanceAmount = 1000; await CreateAndIssueCustomizeTokenAsync(DefaultAddress, trafficToken, 10000, 10000); var advanceRet = await TokenContractStub.AdvanceResourceToken.SendAsync( new AdvanceResourceTokenInput @@ -63,171 +39,197 @@ public async Task TakeResourceTokenBack_Test() ResourceTokenSymbol = trafficToken }); advanceRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var takeMoreToken = await TokenContractStub.TakeResourceTokenBack.SendWithExceptionAsync( - new TakeResourceTokenBackInput - { - Amount = 99999, - ContractAddress = BasicFunctionContractAddress, - ResourceTokenSymbol = trafficToken - }); - takeMoreToken.TransactionResult.Error.ShouldContain("Can't take back that more"); - await TokenContractStub.TakeResourceTokenBack.SendAsync( - new TakeResourceTokenBackInput - { - Amount = advanceAmount, - ContractAddress = BasicFunctionContractAddress, - ResourceTokenSymbol = trafficToken - }); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = trafficToken, Owner = BasicFunctionContractAddress }); - balance.Balance.ShouldBe(0); + balance.Balance.ShouldBe(advanceAmount); } - - [Fact(DisplayName = "[MultiToken] illegal controller try to update the coefficientForContract")] - public async Task UpdateCoefficientForContract_Without_Authorization_Test() - { - await CreatePrimaryTokenAsync(); - var updateInfo = new UpdateCoefficientsInput + } + + [Fact(DisplayName = "[MultiToken] take more token than that of the contract address's balance")] + public async Task TakeResourceTokenBack_Test() + { + await CreateNativeTokenAsync(); + var trafficToken = "TRAFFIC"; + var advanceAmount = 1000; + await CreateAndIssueCustomizeTokenAsync(DefaultAddress, trafficToken, 10000, 10000); + var advanceRet = await TokenContractStub.AdvanceResourceToken.SendAsync( + new AdvanceResourceTokenInput { - Coefficients = new CalculateFeeCoefficients - { - FeeTokenType = (int) FeeTypeEnum.Read - } - }; - var updateRet = - await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); - updateRet.TransactionResult.Error.ShouldContain( - "controller does not initialize, call InitializeAuthorizedController first"); - var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - updateRet = await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); - updateRet.TransactionResult.Error.ShouldContain("no permission"); - } - - [Fact(DisplayName = "[MultiToken] Invalid fee type for Update controller")] - public async Task UpdateCoefficientForContract_With_Invalid_FeeType_Test() - { - await CreatePrimaryTokenAsync(); - var updateInfo = new UpdateCoefficientsInput + ContractAddress = BasicFunctionContractAddress, + Amount = advanceAmount, + ResourceTokenSymbol = trafficToken + }); + advanceRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var takeMoreToken = await TokenContractStub.TakeResourceTokenBack.SendWithExceptionAsync( + new TakeResourceTokenBackInput { - Coefficients = new CalculateFeeCoefficients - { - FeeTokenType = (int) FeeTypeEnum.Tx - } - }; - var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var updateRet = await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); - updateRet.TransactionResult.Error.ShouldContain("Invalid fee type"); - } - - [Fact(DisplayName = "[MultiToken] illegal controller try to update the coefficientForSender")] - public async Task UpdateCoefficientForSender_Without_Authorization_Test() - { - await CreatePrimaryTokenAsync(); - var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var updateRet = - await TokenContractStub.UpdateCoefficientsForSender.SendWithExceptionAsync( - new UpdateCoefficientsInput()); - updateRet.TransactionResult.Error.ShouldContain("no permission"); - } + Amount = 99999, + ContractAddress = BasicFunctionContractAddress, + ResourceTokenSymbol = trafficToken + }); + takeMoreToken.TransactionResult.Error.ShouldContain("Can't take back that more"); + await TokenContractStub.TakeResourceTokenBack.SendAsync( + new TakeResourceTokenBackInput + { + Amount = advanceAmount, + ContractAddress = BasicFunctionContractAddress, + ResourceTokenSymbol = trafficToken + }); - [Fact(DisplayName = "[MultiToken] illegal controller try to set the available token list")] - public async Task SetSymbolsToPayTxSizeFee_Without_Authorization_Test() - { - var setSymbolRet = - await TokenContractStub.SetSymbolsToPayTxSizeFee.SendWithExceptionAsync(new SymbolListToPayTxSizeFee()); - setSymbolRet.TransactionResult.Error.ShouldContain("no permission"); - } - - [Fact(DisplayName = "[MultiToken] Reference Token Fee Controller")] - public async Task InitializeAuthorizedController_Test() + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await CreatePrimaryTokenAsync(); - var tryToGetControllerInfoRet = - await TokenContractStub.GetDeveloperFeeController.SendWithExceptionAsync(new Empty()); - tryToGetControllerInfoRet.TransactionResult.Error.ShouldContain( - "controller does not initialize, call InitializeAuthorizedController first"); - - var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var afterInitializedDeveloperFeeController = - await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); - afterInitializedDeveloperFeeController.DeveloperController.ShouldNotBeNull(); - afterInitializedDeveloperFeeController.ParliamentController.ShouldNotBeNull(); - afterInitializedDeveloperFeeController.RootController.ShouldNotBeNull(); - } - - [Fact] - public async Task DonateResourceToken_Without_Authorized_Test() - { - var tokenStub = GetTester(TokenContractAddress, Accounts.Last().KeyPair); - var donate = - await tokenStub.DonateResourceToken.SendWithExceptionAsync(new TotalResourceTokensMaps()); - donate.TransactionResult.Error.ShouldContain("No permission"); - } + Symbol = trafficToken, + Owner = BasicFunctionContractAddress + }); + balance.Balance.ShouldBe(0); + } - [Fact] - public async Task SetReceiver_Test() + [Fact(DisplayName = "[MultiToken] illegal controller try to update the coefficientForContract")] + public async Task UpdateCoefficientForContract_Without_Authorization_Test() + { + await CreatePrimaryTokenAsync(); + var updateInfo = new UpdateCoefficientsInput { - // without authorized + Coefficients = new CalculateFeeCoefficients { - var setReceiverRet = await TokenContractStub.SetFeeReceiver.SendWithExceptionAsync(new Address()); - setReceiverRet.TransactionResult.Error.ShouldContain("No permission"); + FeeTokenType = (int)FeeTypeEnum.Read } - - var methodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain); - var initialInput = new InitializeFromParentChainInput + }; + var updateRet = + await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); + updateRet.TransactionResult.Error.ShouldContain( + "controller does not initialize, call InitializeAuthorizedController first"); + var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + updateRet = await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); + updateRet.TransactionResult.Error.ShouldContain("no permission"); + } + + [Fact(DisplayName = "[MultiToken] Invalid fee type for Update controller")] + public async Task UpdateCoefficientForContract_With_Invalid_FeeType_Test() + { + await CreatePrimaryTokenAsync(); + var updateInfo = new UpdateCoefficientsInput + { + Coefficients = new CalculateFeeCoefficients { - Creator = DefaultAddress, - RegisteredOtherTokenContractAddresses = { {1, TokenContractAddress}} - }; - await SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, methodName, initialInput); - await TokenContractStub.SetFeeReceiver.SendAsync(DefaultAddress); - var feeReceiver = await TokenContractStub.GetFeeReceiver.CallAsync(new Empty()); - feeReceiver.Value.ShouldBe(DefaultAddress.Value); - } + FeeTokenType = (int)FeeTypeEnum.Tx + } + }; + var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var updateRet = await TokenContractStub.UpdateCoefficientsForContract.SendWithExceptionAsync(updateInfo); + updateRet.TransactionResult.Error.ShouldContain("Invalid fee type"); + } + + [Fact(DisplayName = "[MultiToken] illegal controller try to update the coefficientForSender")] + public async Task UpdateCoefficientForSender_Without_Authorization_Test() + { + await CreatePrimaryTokenAsync(); + var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var updateRet = + await TokenContractStub.UpdateCoefficientsForSender.SendWithExceptionAsync( + new UpdateCoefficientsInput()); + updateRet.TransactionResult.Error.ShouldContain("no permission"); + } + + [Fact(DisplayName = "[MultiToken] illegal controller try to set the available token list")] + public async Task SetSymbolsToPayTxSizeFee_Without_Authorization_Test() + { + var setSymbolRet = + await TokenContractStub.SetSymbolsToPayTxSizeFee.SendWithExceptionAsync(new SymbolListToPayTxSizeFee()); + setSymbolRet.TransactionResult.Error.ShouldContain("no permission"); + } + + [Fact(DisplayName = "[MultiToken] Reference Token Fee Controller")] + public async Task InitializeAuthorizedController_Test() + { + await CreatePrimaryTokenAsync(); + var tryToGetControllerInfoRet = + await TokenContractStub.GetDeveloperFeeController.SendWithExceptionAsync(new Empty()); + tryToGetControllerInfoRet.TransactionResult.Error.ShouldContain( + "controller does not initialize, call InitializeAuthorizedController first"); + + var initializeControllerRet = await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var afterInitializedDeveloperFeeController = + await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); + afterInitializedDeveloperFeeController.DeveloperController.ShouldNotBeNull(); + afterInitializedDeveloperFeeController.ParliamentController.ShouldNotBeNull(); + afterInitializedDeveloperFeeController.RootController.ShouldNotBeNull(); + } + + [Fact] + public async Task DonateResourceToken_Without_Authorized_Test() + { + var tokenStub = + GetTester(TokenContractAddress, Accounts.Last().KeyPair); + var donate = + await tokenStub.DonateResourceToken.SendWithExceptionAsync(new TotalResourceTokensMaps()); + donate.TransactionResult.Error.ShouldContain("No permission"); + } - [Fact] - public async Task GetFeeCoefficientController_Without_Initialize_Test() + [Fact] + public async Task SetReceiver_Test() + { + // without authorized { - var userFeeRet = await TokenContractStub.GetUserFeeController - .SendWithExceptionAsync(new Empty()); - userFeeRet.TransactionResult.Error.ShouldContain("controller does not initialize, call InitializeAuthorizedController first"); - var developerFeeRet = await TokenContractStub.GetDeveloperFeeController - .SendWithExceptionAsync(new Empty()); - developerFeeRet.TransactionResult.Error.ShouldContain("controller does not initialize, call InitializeAuthorizedController first"); + var setReceiverRet = await TokenContractStub.SetFeeReceiver.SendWithExceptionAsync(new Address()); + setReceiverRet.TransactionResult.Error.ShouldContain("No permission"); } - private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractAddress, string methodName, - IMessage message) + var methodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain); + var initialInput = new InitializeFromParentChainInput { - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultParliamentAddress, methodName, message); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Creator = DefaultAddress, + RegisteredOtherTokenContractAddresses = { { 1, TokenContractAddress } } + }; + await SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, methodName, initialInput); + await TokenContractStub.SetFeeReceiver.SendAsync(DefaultAddress); + var feeReceiver = await TokenContractStub.GetFeeReceiver.CallAsync(new Empty()); + feeReceiver.Value.ShouldBe(DefaultAddress.Value); + } - private Transaction GenerateTokenTransaction(Address from, string method, IMessage input) + [Fact] + public async Task GetFeeCoefficientController_Without_Initialize_Test() + { + var userFeeRet = await TokenContractStub.GetUserFeeController + .SendWithExceptionAsync(new Empty()); + userFeeRet.TransactionResult.Error.ShouldContain( + "controller does not initialize, call InitializeAuthorizedController first"); + var developerFeeRet = await TokenContractStub.GetDeveloperFeeController + .SendWithExceptionAsync(new Empty()); + developerFeeRet.TransactionResult.Error.ShouldContain( + "controller does not initialize, call InitializeAuthorizedController first"); + } + + private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractAddress, string methodName, + IMessage message) + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliamentAddress, methodName, message); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private Transaction GenerateTokenTransaction(Address from, string method, IMessage input) + { + return new Transaction { - return new Transaction - { - From = from, - To = TokenContractAddress, - MethodName = method, - Params = ByteString.CopyFrom(input.ToByteArray()) - }; - } + From = from, + To = TokenContractAddress, + MethodName = method, + Params = ByteString.CopyFrom(input.ToByteArray()) + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index 5a7403128c..6135c8a443 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -1,8 +1,4 @@ using System.Threading.Tasks; -using AElf.Standards.ACS2; -using AElf.Contracts.Parliament; -using AElf.Contracts.Profit; -using AElf.Contracts.Referendum; using AElf.Contracts.TokenConverter; using AElf.Kernel; using AElf.Kernel.SmartContract; @@ -13,561 +9,562 @@ using Xunit; // ReSharper disable CheckNamespace -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public partial class MultiTokenContractTests : MultiTokenContractTestBase { - public partial class MultiTokenContractTests : MultiTokenContractTestBase + private const long TotalSupply = 1000_000_000_00000000; + private readonly int _chainId; + + private readonly Connector BaseConnector = new() { - private const long TotalSupply = 1000_000_000_00000000; - private readonly int _chainId; - - public MultiTokenContractTests() - { - _chainId = GetRequiredService>().Value.ChainId; - } + Symbol = "ELF", + VirtualBalance = 0, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false + }; - private TokenInfo NativeTokenInfo => new TokenInfo - { - Symbol = GetRequiredService>().Value - .ContextVariables[ContextVariableDictionary.NativeSymbolName], - TokenName = "Native token", - TotalSupply = TotalSupply, - Decimals = 8, - IsBurnable = true, - Issuer = Accounts[0].Address, - Supply = 0, - IssueChainId = _chainId - }; - - private TokenInfo PrimaryTokenInfo => new TokenInfo - { - Symbol = "PRIMARY", - TokenName = "Primary token", - TotalSupply = TotalSupply, - Decimals = 8, - IsBurnable = true, - Issuer = Accounts[0].Address, - Supply = 0, - IssueChainId = _chainId - }; + private readonly Connector RamConnector = new() + { + Symbol = "ALICE", + VirtualBalance = 0, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false, + RelatedSymbol = "ELF" + }; - /// - /// Burnable & Transferable - /// - private TokenInfo AliceCoinTokenInfo => new TokenInfo - { - Symbol = "ALICE", - TokenName = "For testing multi-token contract", - TotalSupply = TotalSupply, - Decimals = 8, - IsBurnable = true, - Issuer = Accounts[0].Address, - Supply = 0, - IssueChainId = _chainId, - ExternalInfo = new ExternalInfo() - }; + public MultiTokenContractTests() + { + _chainId = GetRequiredService>().Value.ChainId; + } - /// - /// Not Burnable & Transferable - /// - private TokenInfo BobCoinTokenInfo => new TokenInfo - { - Symbol = "BOB", - TokenName = "For testing multi-token contract", - TotalSupply = 1_000_000_000_0000, - Decimals = 4, - IsBurnable = false, - Issuer = Accounts[0].Address, - Supply = 0 - }; + private TokenInfo NativeTokenInfo => new() + { + Symbol = GetRequiredService>().Value + .ContextVariables[ContextVariableDictionary.NativeSymbolName], + TokenName = "Native token", + TotalSupply = TotalSupply, + Decimals = 8, + IsBurnable = true, + Issuer = Accounts[0].Address, + Supply = 0, + IssueChainId = _chainId + }; + + private TokenInfo PrimaryTokenInfo => new() + { + Symbol = "PRIMARY", + TokenName = "Primary token", + TotalSupply = TotalSupply, + Decimals = 8, + IsBurnable = true, + Issuer = Accounts[0].Address, + Supply = 0, + IssueChainId = _chainId + }; + + /// + /// Burnable & Transferable + /// + private TokenInfo AliceCoinTokenInfo => new() + { + Symbol = "ALICE", + TokenName = "For testing multi-token contract", + TotalSupply = TotalSupply, + Decimals = 8, + IsBurnable = true, + Issuer = Accounts[0].Address, + Supply = 0, + IssueChainId = _chainId, + ExternalInfo = new ExternalInfo() + }; - /// - /// Not Burnable & Not Transferable - /// - private TokenInfo EanCoinTokenInfo => new TokenInfo + /// + /// Not Burnable & Transferable + /// + private TokenInfo BobCoinTokenInfo => new() + { + Symbol = "BOB", + TokenName = "For testing multi-token contract", + TotalSupply = 1_000_000_000_0000, + Decimals = 4, + IsBurnable = false, + Issuer = Accounts[0].Address, + Supply = 0 + }; + + /// + /// Not Burnable & Not Transferable + /// + private TokenInfo EanCoinTokenInfo => new() + { + Symbol = "EAN", + TokenName = "For testing multi-token contract", + TotalSupply = 1_000_000_000, + Decimals = 0, + IsBurnable = true, + Issuer = Accounts[0].Address, + Supply = 0 + }; + + private async Task CreateNativeTokenAsync() + { + await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = "EAN", - TokenName = "For testing multi-token contract", - TotalSupply = 1_000_000_000, - Decimals = 0, - IsBurnable = true, - Issuer = Accounts[0].Address, - Supply = 0 - }; + Symbol = NativeTokenInfo.Symbol, + TokenName = NativeTokenInfo.TokenName, + TotalSupply = NativeTokenInfo.TotalSupply, + Decimals = NativeTokenInfo.Decimals, + Issuer = NativeTokenInfo.Issuer, + IsBurnable = NativeTokenInfo.IsBurnable, + LockWhiteList = + { + BasicFunctionContractAddress, + OtherBasicFunctionContractAddress, + TokenConverterContractAddress, + TreasuryContractAddress + } + }); + } - private Connector RamConnector = new Connector + private async Task CreatePrimaryTokenAsync() + { + await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = "ALICE", - VirtualBalance = 0, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false, - RelatedSymbol = "ELF" - }; + Symbol = NativeTokenInfo.Symbol, + TokenName = NativeTokenInfo.TokenName, + TotalSupply = NativeTokenInfo.TotalSupply, + Decimals = NativeTokenInfo.Decimals, + Issuer = NativeTokenInfo.Issuer, + IsBurnable = NativeTokenInfo.IsBurnable + }); - private Connector BaseConnector = new Connector + await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = "ELF", - VirtualBalance = 0, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false - }; + Decimals = PrimaryTokenInfo.Decimals, + IsBurnable = PrimaryTokenInfo.IsBurnable, + Issuer = PrimaryTokenInfo.Issuer, + TotalSupply = PrimaryTokenInfo.TotalSupply, + Symbol = PrimaryTokenInfo.Symbol, + TokenName = PrimaryTokenInfo.TokenName, + IssueChainId = PrimaryTokenInfo.IssueChainId + }); + + await TokenContractStub.SetPrimaryTokenSymbol.SendAsync( + new SetPrimaryTokenSymbolInput + { + Symbol = PrimaryTokenInfo.Symbol + }); + } - private async Task CreateNativeTokenAsync() + private async Task CreateNormalTokenAsync() + { + // Check token information before creating. { - await TokenContractStub.Create.SendAsync(new CreateInput + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - Symbol = NativeTokenInfo.Symbol, - TokenName = NativeTokenInfo.TokenName, - TotalSupply = NativeTokenInfo.TotalSupply, - Decimals = NativeTokenInfo.Decimals, - Issuer = NativeTokenInfo.Issuer, - IsBurnable = NativeTokenInfo.IsBurnable, - LockWhiteList = - { - BasicFunctionContractAddress, - OtherBasicFunctionContractAddress, - TokenConverterContractAddress, - TreasuryContractAddress - }, - ExternalInfo = {} + Symbol = AliceCoinTokenInfo.Symbol }); + tokenInfo.ShouldBe(new TokenInfo()); } - - private async Task CreatePrimaryTokenAsync() + + await TokenContractStub.Create.SendAsync(new CreateInput { - await TokenContractStub.Create.SendAsync(new CreateInput + Symbol = AliceCoinTokenInfo.Symbol, + TokenName = AliceCoinTokenInfo.TokenName, + TotalSupply = AliceCoinTokenInfo.TotalSupply, + Decimals = AliceCoinTokenInfo.Decimals, + Issuer = AliceCoinTokenInfo.Issuer, + IsBurnable = AliceCoinTokenInfo.IsBurnable, + LockWhiteList = { - Symbol = NativeTokenInfo.Symbol, - TokenName = NativeTokenInfo.TokenName, - TotalSupply = NativeTokenInfo.TotalSupply, - Decimals = NativeTokenInfo.Decimals, - Issuer = NativeTokenInfo.Issuer, - IsBurnable = NativeTokenInfo.IsBurnable, - }); + BasicFunctionContractAddress, + OtherBasicFunctionContractAddress, + TokenConverterContractAddress, + TreasuryContractAddress + } + }); - await TokenContractStub.Create.SendAsync(new CreateInput + // Check token information after creating. + { + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - Decimals = PrimaryTokenInfo.Decimals, - IsBurnable = PrimaryTokenInfo.IsBurnable, - Issuer = PrimaryTokenInfo.Issuer, - TotalSupply = PrimaryTokenInfo.TotalSupply, - Symbol = PrimaryTokenInfo.Symbol, - TokenName = PrimaryTokenInfo.TokenName, - IssueChainId = PrimaryTokenInfo.IssueChainId + Symbol = AliceCoinTokenInfo.Symbol }); + tokenInfo.ShouldBe(AliceCoinTokenInfo); + } + } + + private async Task TokenConverterConverterAsync() + { + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); + + await TokenConverterContractStub.Initialize.SendAsync(new InitializeInput + { + Connectors = { RamConnector, BaseConnector }, + BaseTokenSymbol = "ELF", + FeeRate = "0.2" + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = 1000L, + Memo = "ddd", + To = TokenConverterContractAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = 1000L, + Memo = "ddd", + To = TokenConverterContractAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 1000L, + Memo = "ddd", + To = TokenConverterContractAddress + }); + } + + [Fact(DisplayName = "[MultiToken] Create different tokens.")] + public async Task MultiTokenContract_Create_NotSame_Test() + { + await CreateAndIssueMultiTokensAsync(); + + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = BobCoinTokenInfo.Symbol, + TokenName = BobCoinTokenInfo.TokenName, + TotalSupply = BobCoinTokenInfo.TotalSupply, + Decimals = BobCoinTokenInfo.Decimals, + Issuer = BobCoinTokenInfo.Issuer, + IsBurnable = BobCoinTokenInfo.IsBurnable + }); - await TokenContractStub.SetPrimaryTokenSymbol.SendAsync( - new SetPrimaryTokenSymbolInput - { - Symbol = PrimaryTokenInfo.Symbol - }); + // Check token information after creating. + { + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = BobCoinTokenInfo.Symbol + }); + tokenInfo.ShouldNotBe(AliceCoinTokenInfo); } + } - private async Task CreateNormalTokenAsync() + [Fact(DisplayName = "[MultiToken] Create Token use custom address")] + public async Task MultiTokenContract_Create_UseCustomAddress_Test() + { + var transactionResult = (await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput { - // Check token information before creating. + Symbol = NativeTokenInfo.Symbol, + Decimals = 2, + IsBurnable = true, + Issuer = DefaultAddress, + TokenName = NativeTokenInfo.TokenName, + TotalSupply = AliceCoinTotalAmount, + LockWhiteList = { - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = AliceCoinTokenInfo.Symbol - }); - tokenInfo.ShouldBe(new TokenInfo()); + User1Address } + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Addresses in lock white list should be system contract addresses"); + } - await TokenContractStub.Create.SendAsync(new CreateInput + private async Task CreateAndIssueMultiTokensAsync() + { + await CreateNativeTokenAsync(); + await CreateNormalTokenAsync(); + //issue AliceToken amount of 1000_00L to DefaultAddress + { + var result = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = AliceCoinTokenInfo.Symbol, - TokenName = AliceCoinTokenInfo.TokenName, - TotalSupply = AliceCoinTokenInfo.TotalSupply, - Decimals = AliceCoinTokenInfo.Decimals, - Issuer = AliceCoinTokenInfo.Issuer, - IsBurnable = AliceCoinTokenInfo.IsBurnable, - LockWhiteList = - { - BasicFunctionContractAddress, - OtherBasicFunctionContractAddress, - TokenConverterContractAddress, - TreasuryContractAddress - } + Amount = AliceCoinTotalAmount, + To = DefaultAddress, + Memo = "first issue token." }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Check token information after creating. + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = AliceCoinTokenInfo.Symbol - }); - tokenInfo.ShouldBe(AliceCoinTokenInfo); - } + Owner = DefaultAddress, + Symbol = AliceCoinTokenInfo.Symbol + })).Balance; + balance.ShouldBe(AliceCoinTotalAmount); } - private async Task TokenConverterConverterAsync() + //issue ELF amount of 1000_00L to DefaultAddress { - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); - - await TokenConverterContractStub.Initialize.SendAsync(new TokenConverter.InitializeInput - { - Connectors = {RamConnector, BaseConnector}, - BaseTokenSymbol = "ELF", - FeeRate = "0.2", - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + var result = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "ELF", - Amount = 1000L, - Memo = "ddd", - To = TokenConverterContractAddress - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = 1000L, - Memo = "ddd", - To = TokenConverterContractAddress + Amount = AliceCoinTotalAmount, + To = DefaultAddress, + Memo = "first issue token." }); - await TokenContractStub.Issue.SendAsync(new IssueInput + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 1000L, - Memo = "ddd", - To = TokenConverterContractAddress - }); + Owner = DefaultAddress, + Symbol = "ELF" + })).Balance; + balance.ShouldBe(AliceCoinTotalAmount); } - [Fact(DisplayName = "[MultiToken] Create different tokens.")] - public async Task MultiTokenContract_Create_NotSame_Test() + //issue AliceToken amount of 1000L to User1Address { - await CreateAndIssueMultiTokensAsync(); - - await TokenContractStub.Create.SendAsync(new CreateInput + var result = await TokenContractStub.Issue.SendAsync(new IssueInput { - Symbol = BobCoinTokenInfo.Symbol, - TokenName = BobCoinTokenInfo.TokenName, - TotalSupply = BobCoinTokenInfo.TotalSupply, - Decimals = BobCoinTokenInfo.Decimals, - Issuer = BobCoinTokenInfo.Issuer, - IsBurnable = BobCoinTokenInfo.IsBurnable, + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 1000, + To = User1Address, + Memo = "first issue token." }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - // Check token information after creating. + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = BobCoinTokenInfo.Symbol - }); - tokenInfo.ShouldNotBe(AliceCoinTokenInfo); - } + Owner = User1Address, + Symbol = AliceCoinTokenInfo.Symbol + })).Balance; + balance.ShouldBe(1000); } - - [Fact(DisplayName = "[MultiToken] Create Token use custom address")] - public async Task MultiTokenContract_Create_UseCustomAddress_Test() + //Issue AliceToken amount of 1000L to User2Address { - var transactionResult = (await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await TokenContractStub.Issue.SendAsync(new IssueInput { - Symbol = NativeTokenInfo.Symbol, - Decimals = 2, - IsBurnable = true, - Issuer = DefaultAddress, - TokenName = NativeTokenInfo.TokenName, - TotalSupply = AliceCoinTotalAmount, - LockWhiteList = - { - User1Address - } - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Addresses in lock white list should be system contract addresses"); - } + Symbol = AliceCoinTokenInfo.Symbol, + Amount = 1000, + To = User2Address, + Memo = "second issue token." + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - private async Task CreateAndIssueMultiTokensAsync() - { - await CreateNativeTokenAsync(); - await CreateNormalTokenAsync(); - //issue AliceToken amount of 1000_00L to DefaultAddress + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - Memo = "first issue token." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAddress, - Symbol = AliceCoinTokenInfo.Symbol - })).Balance; - balance.ShouldBe(AliceCoinTotalAmount); - } + Owner = User2Address, + Symbol = AliceCoinTokenInfo.Symbol + })).Balance; + balance.ShouldBe(1000); + } + } - //issue ELF amount of 1000_00L to DefaultAddress - { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - Memo = "first issue token." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAddress, - Symbol = "ELF" - })).Balance; - balance.ShouldBe(AliceCoinTotalAmount); - } + [Fact(DisplayName = "[MultiToken] Issue out of total amount")] + public async Task MultiTokenContract_Issue_OutOfAmount_Test() + { + await CreateAndIssueMultiTokensAsync(); + //issue AliceToken amount of 1000L to User1Address + var result = (await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput + { + Symbol = AliceCoinTokenInfo.Symbol, + Amount = AliceCoinTokenInfo.TotalSupply + 1, + To = User1Address, + Memo = "first issue token." + })).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Total supply exceeded").ShouldBeTrue(); + } - //issue AliceToken amount of 1000L to User1Address - { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 1000, - To = User1Address, - Memo = "first issue token." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = AliceCoinTokenInfo.Symbol - })).Balance; - balance.ShouldBe(1000); - } - //Issue AliceToken amount of 1000L to User2Address + [Fact] + public async Task IssueToken_With_Invalid_Input() + { + await CreateNativeTokenAsync(); + await CreateNormalTokenAsync(); + // to is null + { + var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = 1000, - To = User2Address, - Memo = "second issue token." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User2Address, - Symbol = AliceCoinTokenInfo.Symbol - })).Balance; - balance.ShouldBe(1000); - } + Symbol = AliceCoinTokenInfo.Symbol, + Amount = AliceCoinTotalAmount + }); + result.TransactionResult.Error.ShouldContain("To address not filled."); } - - [Fact(DisplayName = "[MultiToken] Issue out of total amount")] - public async Task MultiTokenContract_Issue_OutOfAmount_Test() + // invalid memo { - await CreateAndIssueMultiTokensAsync(); - //issue AliceToken amount of 1000L to User1Address - var result = (await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput() + var result = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTokenInfo.TotalSupply + 1, - To = User1Address, - Memo = "first issue token." - })).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains($"Total supply exceeded").ShouldBeTrue(); + Amount = AliceCoinTotalAmount, + To = DefaultAddress, + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest.." + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - [Fact] - public async Task IssueToken_With_Invalid_Input() { - await CreateNativeTokenAsync(); - await CreateNormalTokenAsync(); - // to is null - { - var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount, - }); - result.TransactionResult.Error.ShouldContain("To address not filled."); - } - // invalid memo - { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest.." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput() - { - Symbol = AliceCoinTokenInfo.Symbol, - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..." - }); - result.TransactionResult.Error.ShouldContain("Invalid memo size."); - } - // issue token that is not existed - { - var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput() - { - Symbol = "NOTEXISTED", - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - }); - result.TransactionResult.Error.ShouldContain("Token is not found"); - } - //invalid chain id + Symbol = AliceCoinTokenInfo.Symbol, + Amount = AliceCoinTotalAmount, + To = DefaultAddress, + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..." + }); + result.TransactionResult.Error.ShouldContain("Invalid memo size."); + } + // issue token that is not existed + { + var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - var chainTokenSymbol = "CHAIN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = chainTokenSymbol, - TokenName = "chain token", - Issuer = DefaultAddress, - IssueChainId = 10, - TotalSupply = 1000_000, - Decimals = 8 - }); - var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput() - { - Symbol = chainTokenSymbol, - Amount = 100, - To = DefaultAddress, - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Unable to issue token with wrong chainId"); - } + Symbol = "NOTEXISTED", + Amount = AliceCoinTotalAmount, + To = DefaultAddress + }); + result.TransactionResult.Error.ShouldContain("Token is not found"); } - - [Fact] - public async Task IssueToken_Test() + //invalid chain id { - await CreateNativeTokenAsync(); - var newTokenSymbol = "AIN"; + var chainTokenSymbol = "CHAIN"; await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = newTokenSymbol, - TokenName = "ain token", + Symbol = chainTokenSymbol, + TokenName = "chain token", Issuer = DefaultAddress, + IssueChainId = 10, TotalSupply = 1000_000, Decimals = 8 }); - // invalid input - { - var issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Amount = 10000, - To = DefaultAddress, - }); - issueRet.TransactionResult.Error.ShouldContain("invalid symbol"); - issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Symbol = "NOTEXIST", - Amount = 10000, - To = DefaultAddress, - }); - issueRet.TransactionResult.Error.ShouldContain("Token is not found"); - } - //invalid amount + var result = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - var issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Symbol = newTokenSymbol, - Amount = -1, - To = DefaultAddress, - }); - issueRet.TransactionResult.Error.ShouldContain("Invalid amount"); - issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Symbol = newTokenSymbol, - Amount = 0, - To = DefaultAddress, - }); - issueRet.TransactionResult.Error.ShouldContain("Invalid amount"); - issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Symbol = newTokenSymbol, - Amount = 1_000_000_000, - To = DefaultAddress, - }); - issueRet.TransactionResult.Error.ShouldContain("Total supply exceeded"); - } + Symbol = chainTokenSymbol, + Amount = 100, + To = DefaultAddress + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Unable to issue token with wrong chainId"); } - - [Fact] - public async Task TokenCreate_Test() + } + + [Fact] + public async Task IssueToken_Test() + { + await CreateNativeTokenAsync(); + var newTokenSymbol = "AIN"; + await TokenContractStub.Create.SendAsync(new CreateInput { - var createTokenInfo = new CreateInput + Symbol = newTokenSymbol, + TokenName = "ain token", + Issuer = DefaultAddress, + TotalSupply = 1000_000, + Decimals = 8 + }); + // invalid input + { + var issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - Symbol = AliceCoinTokenInfo.Symbol, - TokenName = AliceCoinTokenInfo.TokenName, - TotalSupply = AliceCoinTokenInfo.TotalSupply, - Decimals = AliceCoinTokenInfo.Decimals, - Issuer = AliceCoinTokenInfo.Issuer, - IsBurnable = AliceCoinTokenInfo.IsBurnable, - LockWhiteList = - { - BasicFunctionContractAddress, - OtherBasicFunctionContractAddress, - TokenConverterContractAddress, - TreasuryContractAddress - } - }; - var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfo); - createTokenRet.TransactionResult.Error.ShouldContain("Invalid native token input"); - var createTokenInfoWithInvalidTokenName = new CreateInput(); - createTokenInfoWithInvalidTokenName.MergeFrom(createTokenInfo); - createTokenInfoWithInvalidTokenName.Symbol = "ITISAVERYLONGSYMBOLNAME"; - createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidTokenName); - createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - var createTokenInfoWithInvalidDecimal = new CreateInput(); - createTokenInfoWithInvalidDecimal.MergeFrom(createTokenInfo); - createTokenInfoWithInvalidDecimal.Decimals = 100; - createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidDecimal); - createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await CreateNativeTokenAsync(); - await TokenContractStub.Create.SendAsync(createTokenInfo); - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + Amount = 10000, + To = DefaultAddress + }); + issueRet.TransactionResult.Error.ShouldContain("invalid symbol"); + issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - Symbol = AliceCoinTokenInfo.Symbol + Symbol = "NOTEXIST", + Amount = 10000, + To = DefaultAddress }); - tokenInfo.Issuer.ShouldBe(createTokenInfo.Issuer); + issueRet.TransactionResult.Error.ShouldContain("Token is not found"); } - - [Fact] - public async Task SetPrimaryToken_Test() + //invalid amount { - var setPrimaryTokenRet = await TokenContractStub.SetPrimaryTokenSymbol.SendWithExceptionAsync(new SetPrimaryTokenSymbolInput + var issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - Symbol = "NOTEXISTED" + Symbol = newTokenSymbol, + Amount = -1, + To = DefaultAddress }); - setPrimaryTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await CreateNativeTokenAsync(); - await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput + issueRet.TransactionResult.Error.ShouldContain("Invalid amount"); + issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - Symbol = NativeTokenInfo.Symbol + Symbol = newTokenSymbol, + Amount = 0, + To = DefaultAddress }); - var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); - primaryToken.Value.ShouldBe(NativeTokenInfo.Symbol); - setPrimaryTokenRet = await TokenContractStub.SetPrimaryTokenSymbol.SendWithExceptionAsync(new SetPrimaryTokenSymbolInput + issueRet.TransactionResult.Error.ShouldContain("Invalid amount"); + issueRet = await TokenContractStub.Issue.SendWithExceptionAsync(new IssueInput { - Symbol = NativeTokenInfo.Symbol + Symbol = newTokenSymbol, + Amount = 1_000_000_000, + To = DefaultAddress }); - setPrimaryTokenRet.TransactionResult.Error.ShouldContain("Failed to set primary token symbol"); + issueRet.TransactionResult.Error.ShouldContain("Total supply exceeded"); } - [Fact] - public async Task GetNativeToken_Test() + } + + [Fact] + public async Task TokenCreate_Test() + { + var createTokenInfo = new CreateInput { - await CreateNativeTokenAsync(); - var tokenInfo = await TokenContractStub.GetNativeTokenInfo.CallAsync(new Empty()); - tokenInfo.Symbol.ShouldBe(NativeTokenInfo.Symbol); - } + Symbol = AliceCoinTokenInfo.Symbol, + TokenName = AliceCoinTokenInfo.TokenName, + TotalSupply = AliceCoinTokenInfo.TotalSupply, + Decimals = AliceCoinTokenInfo.Decimals, + Issuer = AliceCoinTokenInfo.Issuer, + IsBurnable = AliceCoinTokenInfo.IsBurnable, + LockWhiteList = + { + BasicFunctionContractAddress, + OtherBasicFunctionContractAddress, + TokenConverterContractAddress, + TreasuryContractAddress + } + }; + var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfo); + createTokenRet.TransactionResult.Error.ShouldContain("Invalid native token input"); + var createTokenInfoWithInvalidTokenName = new CreateInput(); + createTokenInfoWithInvalidTokenName.MergeFrom(createTokenInfo); + createTokenInfoWithInvalidTokenName.Symbol = "ITISAVERYLONGSYMBOLNAME"; + createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidTokenName); + createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); + var createTokenInfoWithInvalidDecimal = new CreateInput(); + createTokenInfoWithInvalidDecimal.MergeFrom(createTokenInfo); + createTokenInfoWithInvalidDecimal.Decimals = 100; + createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidDecimal); + createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); + await CreateNativeTokenAsync(); + await TokenContractStub.Create.SendAsync(createTokenInfo); + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = AliceCoinTokenInfo.Symbol + }); + tokenInfo.Issuer.ShouldBe(createTokenInfo.Issuer); + } + + [Fact] + public async Task SetPrimaryToken_Test() + { + var setPrimaryTokenRet = await TokenContractStub.SetPrimaryTokenSymbol.SendWithExceptionAsync( + new SetPrimaryTokenSymbolInput + { + Symbol = "NOTEXISTED" + }); + setPrimaryTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); + await CreateNativeTokenAsync(); + await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput + { + Symbol = NativeTokenInfo.Symbol + }); + var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); + primaryToken.Value.ShouldBe(NativeTokenInfo.Symbol); + setPrimaryTokenRet = await TokenContractStub.SetPrimaryTokenSymbol.SendWithExceptionAsync( + new SetPrimaryTokenSymbolInput + { + Symbol = NativeTokenInfo.Symbol + }); + setPrimaryTokenRet.TransactionResult.Error.ShouldContain("Failed to set primary token symbol"); + } + + [Fact] + public async Task GetNativeToken_Test() + { + await CreateNativeTokenAsync(); + var tokenInfo = await TokenContractStub.GetNativeTokenInfo.CallAsync(new Empty()); + tokenInfo.Symbol.ShouldBe(NativeTokenInfo.Symbol); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BasicFunctionContractInitializationProvider.cs b/test/AElf.Contracts.MultiToken.Tests/BasicFunctionContractInitializationProvider.cs index 18421a4ccb..b885db940f 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BasicFunctionContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BasicFunctionContractInitializationProvider.cs @@ -3,16 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class BasicFunctionContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class BasicFunctionContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"); - public string ContractCodeName { get; } = "AElf.Contracts.TestContract.BasicFunction"; + public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"); + public string ContractCodeName { get; } = "AElf.Contracts.TestContract.BasicFunction"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/ContractDeploymentListProvider.cs b/test/AElf.Contracts.MultiToken.Tests/ContractDeploymentListProvider.cs index bce60e38ea..ba24894592 100644 --- a/test/AElf.Contracts.MultiToken.Tests/ContractDeploymentListProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/ContractDeploymentListProvider.cs @@ -1,37 +1,33 @@ using System.Collections.Generic; -using AElf.CrossChain; using AElf.EconomicSystem; using AElf.GovernmentSystem; -using AElf.Kernel; -using AElf.Kernel.Configuration; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class ContractDeploymentListProvider : IContractDeploymentListProvider { - public class ContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - TokenSmartContractAddressNameProvider.Name, - ProfitSmartContractAddressNameProvider.Name, - TreasurySmartContractAddressNameProvider.Name, - TokenConverterSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"), - HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"), - ParliamentSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - HashHelper.ComputeFrom("AElf.ContractNames.NFT"), - HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"), - HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter"), - }; - } + TokenSmartContractAddressNameProvider.Name, + ProfitSmartContractAddressNameProvider.Name, + TreasurySmartContractAddressNameProvider.Name, + TokenConverterSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"), + HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"), + ParliamentSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + HashHelper.ComputeFrom("AElf.ContractNames.NFT"), + HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"), + HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter") + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/DPoSContractConsts.cs b/test/AElf.Contracts.MultiToken.Tests/DPoSContractConsts.cs index a968c82793..08351afa69 100644 --- a/test/AElf.Contracts.MultiToken.Tests/DPoSContractConsts.cs +++ b/test/AElf.Contracts.MultiToken.Tests/DPoSContractConsts.cs @@ -1,12 +1,11 @@ -namespace AElf.Contracts.Consensus.DPoS +namespace AElf.Contracts.Consensus.DPoS; + +// ReSharper disable InconsistentNaming +public static class DPoSContractConsts { - // ReSharper disable InconsistentNaming - public static class DPoSContractConsts - { - #region Consensus Settings + #region Consensus Settings - public const long LockTokenForElection = 100_000; + public const long LockTokenForElection = 100_000; - #endregion - } + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestAElfModule.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestAElfModule.cs index 64896c25a5..782c1873ea 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestAElfModule.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestAElfModule.cs @@ -15,44 +15,43 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(GovernmentSystemAElfModule), + typeof(EconomicSystemAElfModule))] +public class MultiTokenContractTestAElfModule : AbpModule { - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(GovernmentSystemAElfModule), - typeof(EconomicSystemAElfModule))] - public class MultiTokenContractTestAElfModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = - SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); - }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - var instance = new TestTokenBalanceTransactionGenerator(); - context.Services.AddSingleton(instance); - context.Services.AddSingleton(instance); - context.Services.RemoveAll(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(UnitTestTokenContractInitializationProvider)); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(SideChainUnitTestTokenContractInitializationProvider)); - } - - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + Configure(options => { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + options.MiningInterval = 4000; + options.InitialMinerList = + SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); + }); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + var instance = new TestTokenBalanceTransactionGenerator(); + context.Services.AddSingleton(instance); + context.Services.AddSingleton(instance); + context.Services.RemoveAll(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(UnitTestTokenContractInitializationProvider)); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(SideChainUnitTestTokenContractInitializationProvider)); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index c4e775be8b..6e650acfd8 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -1,83 +1,83 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS2; using AElf.Contracts.Parliament; using AElf.Contracts.TestContract.BasicFunction; -using AElf.Cryptography.ECDSA; -using AElf.Types; -using AElf.Contracts.Treasury; using AElf.Contracts.TokenConverter; +using AElf.Contracts.Treasury; using AElf.ContractTestBase.ContractTestKit; +using AElf.Cryptography.ECDSA; +using AElf.Standards.ACS2; +using AElf.Types; + +namespace AElf.Contracts.MultiToken; -namespace AElf.Contracts.MultiToken +public class MultiTokenContractTestBase : ContractTestBase { - public class MultiTokenContractTestBase : ContractTestBase - { - protected long AliceCoinTotalAmount => 1_000_000_000_0000000L; - protected long BobCoinTotalAmount => 1_000_000_000_0000L; - protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; - protected Address DefaultAddress => Accounts[0].Address; - protected ECKeyPair User1KeyPair => Accounts[10].KeyPair; - protected Address User1Address => Accounts[10].Address; - protected Address User2Address => Accounts[11].Address; - protected const string DefaultSymbol = "ELF"; + protected const string DefaultSymbol = "ELF"; - protected const string SymbolForTest = "ELF"; + protected const string SymbolForTest = "ELF"; - protected const long Amount = 100; + protected const long Amount = 100; + internal ACS2BaseContainer.ACS2BaseStub Acs2BaseStub; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; - internal ACS2BaseContainer.ACS2BaseStub Acs2BaseStub; + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; + internal TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub; - internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub; - internal TokenConverterContractImplContainer.TokenConverterContractImplStub TokenConverterContractStub; + internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub; - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; + public MultiTokenContractTestBase() + { + TokenContractStub = + GetTester(TokenContractAddress, DefaultKeyPair); + Acs2BaseStub = GetTester(TokenContractAddress, DefaultKeyPair); - protected Hash BasicFunctionContractName => HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"); - protected Address BasicFunctionContractAddress { get; set; } - internal BasicFunctionContractContainer.BasicFunctionContractStub BasicFunctionContractStub { get; set; } + TreasuryContractStub = GetTester( + TreasuryContractAddress, + DefaultKeyPair); - protected Hash OtherBasicFunctionContractName => - HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); + TokenConverterContractStub = GetTester( + TokenConverterContractAddress, + DefaultKeyPair); - protected Address OtherBasicFunctionContractAddress { get; set; } - internal BasicFunctionContractContainer.BasicFunctionContractStub OtherBasicFunctionContractStub { get; set; } + BasicFunctionContractAddress = SystemContractAddresses[BasicFunctionContractName]; + BasicFunctionContractStub = GetTester( + BasicFunctionContractAddress, DefaultKeyPair); - public MultiTokenContractTestBase() - { - TokenContractStub = - GetTester(TokenContractAddress, DefaultKeyPair); - Acs2BaseStub = GetTester(TokenContractAddress, DefaultKeyPair); + OtherBasicFunctionContractAddress = SystemContractAddresses[OtherBasicFunctionContractName]; + OtherBasicFunctionContractStub = GetTester( + OtherBasicFunctionContractAddress, DefaultKeyPair); - TreasuryContractStub = GetTester( - TreasuryContractAddress, - DefaultKeyPair); + ParliamentContractStub = GetTester( + ParliamentContractAddress, DefaultKeyPair); + } + + protected long AliceCoinTotalAmount => 1_000_000_000_0000000L; + protected long BobCoinTotalAmount => 1_000_000_000_0000L; + protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; + protected Address DefaultAddress => Accounts[0].Address; + protected ECKeyPair User1KeyPair => Accounts[10].KeyPair; + protected Address User1Address => Accounts[10].Address; + protected Address User2Address => Accounts[11].Address; - TokenConverterContractStub = GetTester( - TokenConverterContractAddress, - DefaultKeyPair); + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - BasicFunctionContractAddress = SystemContractAddresses[BasicFunctionContractName]; - BasicFunctionContractStub = GetTester( - BasicFunctionContractAddress, DefaultKeyPair); + protected Hash BasicFunctionContractName => HashHelper.ComputeFrom("AElf.TestContractNames.BasicFunction"); + protected Address BasicFunctionContractAddress { get; set; } + internal BasicFunctionContractContainer.BasicFunctionContractStub BasicFunctionContractStub { get; set; } - OtherBasicFunctionContractAddress = SystemContractAddresses[OtherBasicFunctionContractName]; - OtherBasicFunctionContractStub = GetTester( - OtherBasicFunctionContractAddress, DefaultKeyPair); + protected Hash OtherBasicFunctionContractName => + HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); - ParliamentContractStub = GetTester( - ParliamentContractAddress, DefaultKeyPair); - } + protected Address OtherBasicFunctionContractAddress { get; set; } + internal BasicFunctionContractContainer.BasicFunctionContractStub OtherBasicFunctionContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs index 5ddde8221b..12a2888fba 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs @@ -1,6 +1,4 @@ using System.Threading.Tasks; -using AElf.Standards.ACS2; -using AElf.Kernel; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -9,72 +7,71 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class MultiTokenContractWithCustomSystemTransactionTest : MultiTokenContractTestBase { - public class MultiTokenContractWithCustomSystemTransactionTest : MultiTokenContractTestBase + private static readonly long _totalSupply = 1_000_000_00000000L; + + public MultiTokenContractWithCustomSystemTransactionTest() { - private static long _totalSupply = 1_000_000_00000000L; + AsyncHelper.RunSync(async () => await InitializeAsync()); + } - public MultiTokenContractWithCustomSystemTransactionTest() + private async Task InitializeAsync() + { + await TokenContractStub.Create.SendAsync(new CreateInput { - AsyncHelper.RunSync(async () => await InitializeAsync()); - } - - private async Task InitializeAsync() + Symbol = DefaultSymbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = _totalSupply, + Issuer = DefaultAddress + }); + await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = DefaultSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = _totalSupply, - Issuer = DefaultAddress - }); - await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput - { - Symbol = DefaultSymbol, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = DefaultSymbol, - Amount = _totalSupply, - To = DefaultAddress, - Memo = "Set for token converter." - }); - var tokenSymbol = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); - tokenSymbol.Value.ShouldBe(DefaultSymbol); - } - - [Fact] - public async Task TokenContract_WithSystemTransaction_Test() + Symbol = DefaultSymbol + }); + await TokenContractStub.Issue.SendAsync(new IssueInput { - var transferAmountInSystemTxn = 1000L; - // Set the address so that a transfer - var generator = Application.ServiceProvider.GetRequiredService(); - generator.GenerateTransactionFunc = (_, preBlockHeight, preBlockHash) => - new Transaction - { - From = DefaultAddress, - To = TokenContractAddress, - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), - Params = new TransferInput - { - Amount = transferAmountInSystemTxn, - Memo = "transfer test", - Symbol = DefaultSymbol, - To = Accounts[1].Address - }.ToByteString(), - RefBlockNumber = preBlockHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash) - }; - var result = await TokenContractStub.GetBalance.SendAsync(new GetBalanceInput + Symbol = DefaultSymbol, + Amount = _totalSupply, + To = DefaultAddress, + Memo = "Set for token converter." + }); + var tokenSymbol = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); + tokenSymbol.Value.ShouldBe(DefaultSymbol); + } + + [Fact] + public async Task TokenContract_WithSystemTransaction_Test() + { + var transferAmountInSystemTxn = 1000L; + // Set the address so that a transfer + var generator = Application.ServiceProvider.GetRequiredService(); + generator.GenerateTransactionFunc = (_, preBlockHeight, preBlockHash) => + new Transaction { - Symbol = DefaultSymbol, - Owner = DefaultAddress - }); + From = DefaultAddress, + To = TokenContractAddress, + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), + Params = new TransferInput + { + Amount = transferAmountInSystemTxn, + Memo = "transfer test", + Symbol = DefaultSymbol, + To = Accounts[1].Address + }.ToByteString(), + RefBlockNumber = preBlockHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash) + }; + var result = await TokenContractStub.GetBalance.SendAsync(new GetBalanceInput + { + Symbol = DefaultSymbol, + Owner = DefaultAddress + }); - result.Output.Balance.ShouldBe(_totalSupply - transferAmountInSystemTxn); - } + result.Output.Balance.ShouldBe(_totalSupply - transferAmountInSystemTxn); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/OtherBasicFunctionContractInitializationProvider.cs b/test/AElf.Contracts.MultiToken.Tests/OtherBasicFunctionContractInitializationProvider.cs index 1381bfb24f..6e929815d9 100644 --- a/test/AElf.Contracts.MultiToken.Tests/OtherBasicFunctionContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/OtherBasicFunctionContractInitializationProvider.cs @@ -3,16 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class OtherBasicFunctionContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class OtherBasicFunctionContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); - public string ContractCodeName { get; } = "AElf.Contracts.TestContract.BasicFunctionWithParallel"; + public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); + public string ContractCodeName { get; } = "AElf.Contracts.TestContract.BasicFunctionWithParallel"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/ParliamentContractInitializationDataProvider.cs b/test/AElf.Contracts.MultiToken.Tests/ParliamentContractInitializationDataProvider.cs index 807e97b737..e189402b60 100644 --- a/test/AElf.Contracts.MultiToken.Tests/ParliamentContractInitializationDataProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/ParliamentContractInitializationDataProvider.cs @@ -1,17 +1,16 @@ using AElf.ContractTestBase.ContractTestKit; using AElf.GovernmentSystem; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider { - public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider + public ParliamentContractInitializationData GetContractInitializationData() { - public ParliamentContractInitializationData GetContractInitializationData() + return new ParliamentContractInitializationData { - return new ParliamentContractInitializationData - { - PrivilegedProposer = ContractTestConstants.DefaultAccount.Address, - ProposerAuthorityRequired = true - }; - } + PrivilegedProposer = ContractTestConstants.DefaultAccount.Address, + ProposerAuthorityRequired = true + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/SideChainUnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiToken.Tests/SideChainUnitTestTokenContractInitializationProvider.cs index b848132438..afe56f4805 100644 --- a/test/AElf.Contracts.MultiToken.Tests/SideChainUnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/SideChainUnitTestTokenContractInitializationProvider.cs @@ -5,138 +5,131 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class SideChainUnitTestTokenContractInitializationProvider : TokenContractInitializationProvider { - public class SideChainUnitTestTokenContractInitializationProvider : TokenContractInitializationProvider + private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + + public SideChainUnitTestTokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) : base( + tokenContractInitializationDataProvider) { - private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; + } - public SideChainUnitTestTokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) : base( - tokenContractInitializationDataProvider) - { - _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; - } + public override List GetInitializeMethodList(byte[] contractCode) + { + var methodList = new List(); + var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); + var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); + var resourceTokenList = + TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); - public override List GetInitializeMethodList(byte[] contractCode) + // native token + methodList.Add(new ContractInitializationMethodCall { - var methodList = new List(); - var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); - var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); - var resourceTokenList = - TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + }); - // native token + // resource token + foreach (var resourceTokenInfo in resourceTokenList.Value) methodList.Add(new ContractInitializationMethodCall { MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() }); - // resource token - foreach (var resourceTokenInfo in resourceTokenList.Value) - { - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() - }); - } + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), + Params = new Empty().ToByteString() + }); + + if (initializationData.PrimaryTokenInfoData != null) + { + // primary token + var chainPrimaryTokenInfo = + TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), - Params = new Empty().ToByteString() + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = GenerateTokenCreateInput(chainPrimaryTokenInfo).ToByteString() }); - if (initializationData.PrimaryTokenInfoData != null) - { - // primary token - var chainPrimaryTokenInfo = - TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); - - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(chainPrimaryTokenInfo).ToByteString() - }); - - foreach (var issueStuff in initializationData.TokenInitialIssueList) - { - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), - Params = new IssueInput - { - Symbol = chainPrimaryTokenInfo.Symbol, - Amount = issueStuff.Amount, - Memo = "Initial issue", - To = issueStuff.Address - }.ToByteString() - }); - } - + foreach (var issueStuff in initializationData.TokenInitialIssueList) methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), + Params = new IssueInput { - Symbol = chainPrimaryTokenInfo.Symbol + Symbol = chainPrimaryTokenInfo.Symbol, + Amount = issueStuff.Amount, + Memo = "Initial issue", + To = issueStuff.Address }.ToByteString() }); - } - else + + methodList.Add(new ContractInitializationMethodCall { - // set primary token with native token - methodList.Add(new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = nativeTokenInfo.Symbol - }.ToByteString() - }); - } - - if (initializationData.RegisteredOtherTokenContractAddresses.Values.All(v => v != null)) + Symbol = chainPrimaryTokenInfo.Symbol + }.ToByteString() + }); + } + else + { + // set primary token with native token + methodList.Add(new ContractInitializationMethodCall { - methodList.Add(new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), - Params = new InitializeFromParentChainInput - { - ResourceAmount = {initializationData.ResourceAmount}, - RegisteredOtherTokenContractAddresses = - { - initializationData.RegisteredOtherTokenContractAddresses - }, - Creator = initializationData.Creator - }.ToByteString() - }); - } + Symbol = nativeTokenInfo.Symbol + }.ToByteString() + }); + } + if (initializationData.RegisteredOtherTokenContractAddresses.Values.All(v => v != null)) methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeAuthorizedController), - Params = ByteString.Empty + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), + Params = new InitializeFromParentChainInput + { + ResourceAmount = { initializationData.ResourceAmount }, + RegisteredOtherTokenContractAddresses = + { + initializationData.RegisteredOtherTokenContractAddresses + }, + Creator = initializationData.Creator + }.ToByteString() }); + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeAuthorizedController), + Params = ByteString.Empty + }); + - return methodList; - } + return methodList; + } - private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo) + private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo) + { + return new CreateInput { - return new CreateInput - { - Decimals = tokenInfo.Decimals, - IssueChainId = tokenInfo.IssueChainId, - Issuer = tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - Symbol = tokenInfo.Symbol, - TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply - }; - } + Decimals = tokenInfo.Decimals, + IssueChainId = tokenInfo.IssueChainId, + Issuer = tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + Symbol = tokenInfo.Symbol, + TokenName = tokenInfo.TokenName, + TotalSupply = tokenInfo.TotalSupply + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/TestTokenBalanceTransactionGenerator.cs b/test/AElf.Contracts.MultiToken.Tests/TestTokenBalanceTransactionGenerator.cs index f773ed773a..f46828ae7b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/TestTokenBalanceTransactionGenerator.cs +++ b/test/AElf.Contracts.MultiToken.Tests/TestTokenBalanceTransactionGenerator.cs @@ -5,22 +5,18 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class TestTokenBalanceTransactionGenerator : ISystemTransactionGenerator, ISingletonDependency { - public class TestTokenBalanceTransactionGenerator : ISystemTransactionGenerator, ISingletonDependency - { - public Func GenerateTransactionFunc { get; set; } + public Func GenerateTransactionFunc { get; set; } - public Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, Hash preBlockHash) - { - var res = new List(); - if (GenerateTransactionFunc == null) - { - return Task.FromResult(res); - } + public Task> GenerateTransactionsAsync(Address from, long preBlockHeight, Hash preBlockHash) + { + var res = new List(); + if (GenerateTransactionFunc == null) return Task.FromResult(res); - res.Add(GenerateTransactionFunc(from, preBlockHeight, preBlockHash)); - return Task.FromResult(res); - } + res.Add(GenerateTransactionFunc(from, preBlockHeight, preBlockHash)); + return Task.FromResult(res); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/Types/MinerList.cs b/test/AElf.Contracts.MultiToken.Tests/Types/MinerList.cs index 4db3af4d4e..ed9c3082b5 100644 --- a/test/AElf.Contracts.MultiToken.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.MultiToken.Tests/Types/MinerList.cs @@ -1,49 +1,44 @@ using System.Linq; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/Types/Round.cs b/test/AElf.Contracts.MultiToken.Tests/Types/Round.cs index 62ad84ab0d..fba2d38bae 100644 --- a/test/AElf.Contracts.MultiToken.Tests/Types/Round.cs +++ b/test/AElf.Contracts.MultiToken.Tests/Types/Round.cs @@ -1,152 +1,138 @@ using System; using System.Collections.Generic; using System.Linq; -using AElf.CSharp.Core; using AElf.Types; -using AElf.Sdk.CSharp; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public long RoundId => + RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + + public bool IsEmpty => RoundId == 0; + + public Hash GetHash(bool isContainPreviousInValue = true) { - public long RoundId => - RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); + } - public bool IsEmpty => RoundId == 0; + /// + /// This method is only available when the miners of this round is more than 1. + /// + /// + public int GetMiningInterval() + { + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; - public Hash GetHash(bool isContainPreviousInValue = true) - { - return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); - } - - /// - /// This method is only available when the miners of this round is more than 1. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } - - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); - var distance = - (int) (firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - - firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) - .TotalMilliseconds; - return distance > 0 ? distance : -distance; - } + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); + var distance = + (int)(firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - + firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) + .TotalMilliseconds; + return distance > 0 ? distance : -distance; + } - public bool IsTimeSlotPassed(string publicKey, DateTime dateTime, - out MinerInRound minerInRound) - { - minerInRound = null; - var miningInterval = GetMiningInterval(); - if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; - minerInRound = RealTimeMinersInformation[publicKey]; - return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; - } + public bool IsTimeSlotPassed(string publicKey, DateTime dateTime, + out MinerInRound minerInRound) + { + minerInRound = null; + var miningInterval = GetMiningInterval(); + if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; + minerInRound = RealTimeMinersInformation[publicKey]; + return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; + } - /// - /// Actually the expected mining time of the miner whose order is 1. - /// - /// - public DateTime GetStartTime() - { - return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); - } + /// + /// Actually the expected mining time of the miner whose order is 1. + /// + /// + public DateTime GetStartTime() + { + return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); + } - /// - /// This method for now is able to handle the situation of a miner keeping offline so many rounds, - /// by using missedRoundsCount. - /// - /// - /// - /// - /// - public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } - - var totalMilliseconds = TotalMilliseconds(miningInterval); - return GetStartTime().AddMilliseconds(totalMilliseconds) - // Arrange an ending time if this node missed so many rounds. - .AddMilliseconds(missedRoundsCount * totalMilliseconds) - .ToTimestamp(); - } + /// + /// This method for now is able to handle the situation of a miner keeping offline so many rounds, + /// by using missedRoundsCount. + /// + /// + /// + /// + /// + public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + var totalMilliseconds = TotalMilliseconds(miningInterval); + return GetStartTime().AddMilliseconds(totalMilliseconds) + // Arrange an ending time if this node missed so many rounds. + .AddMilliseconds(missedRoundsCount * totalMilliseconds) + .ToTimestamp(); + } - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } - - public MinerInRound GetExtraBlockProducerInformation() - { - return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; - } - - public DateTime GetExtraBlockMiningTime() - { - return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value - .ExpectedMiningTime.ToDateTime() - .AddMilliseconds(GetMiningInterval()); - } + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - public long GetMinedBlocks() - { - return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); - } + return RealTimeMinersInformation.Count * miningInterval + miningInterval; + } + + public MinerInRound GetExtraBlockProducerInformation() + { + return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; + } + + public DateTime GetExtraBlockMiningTime() + { + return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value + .ExpectedMiningTime.ToDateTime() + .AddMilliseconds(GetMiningInterval()); + } + + public long GetMinedBlocks() + { + return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); + } - private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + { + var minersInformation = new Dictionary(); + foreach (var minerInRound in RealTimeMinersInformation.Clone()) { - var minersInformation = new Dictionary(); - foreach (var minerInRound in RealTimeMinersInformation.Clone()) - { - var checkableMinerInRound = minerInRound.Value.Clone(); - checkableMinerInRound.EncryptedPieces.Clear(); - checkableMinerInRound.ActualMiningTimes.Clear(); - if (!isContainPreviousInValue) - { - checkableMinerInRound.PreviousInValue = Hash.Empty; - } - - minersInformation.Add(minerInRound.Key, checkableMinerInRound); - } - - var checkableRound = new Round - { - RoundNumber = RoundNumber, - TermNumber = TermNumber, - RealTimeMinersInformation = {minersInformation}, - BlockchainAge = BlockchainAge - }; - return checkableRound.ToByteArray(); + var checkableMinerInRound = minerInRound.Value.Clone(); + checkableMinerInRound.EncryptedPieces.Clear(); + checkableMinerInRound.ActualMiningTimes.Clear(); + if (!isContainPreviousInValue) checkableMinerInRound.PreviousInValue = Hash.Empty; + + minersInformation.Add(minerInRound.Key, checkableMinerInRound); } - - private static int GetAbsModulus(long longValue, int intValue) + + var checkableRound = new Round { - return Math.Abs((int) longValue % intValue); - } + RoundNumber = RoundNumber, + TermNumber = TermNumber, + RealTimeMinersInformation = { minersInformation }, + BlockchainAge = BlockchainAge + }; + return checkableRound.ToByteArray(); + } + + private static int GetAbsModulus(long longValue, int intValue) + { + return Math.Abs((int)longValue % intValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.MultiToken.Tests/Types/Round_Generation.cs index 68349ebfa3..34830558d0 100644 --- a/test/AElf.Contracts.MultiToken.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.MultiToken.Tests/Types/Round_Generation.cs @@ -1,111 +1,98 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound) { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound) - { - nextRound = new Round(); + nextRound = new Round(); - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - if (RoundNumber == 1) - { - nextRound.BlockchainAge = 1; - } - else - { - nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - } + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + if (RoundNumber == 1) + nextRound.BlockchainAge = 1; + else + nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + { + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; + } - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + { + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots + 1 - }; - } + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + 1 + }; + } - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; - return true; - } + return true; + } - private int CalculateNextExtraBlockProducerOrder() - { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) - { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToByteArray().ToInt64(true); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; - } + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToByteArray().ToInt64(true); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } - public List GetMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); - } + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } - public List GetNotMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); - } + public List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/UnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiToken.Tests/UnitTestTokenContractInitializationProvider.cs index 10d34c235a..b9df291357 100644 --- a/test/AElf.Contracts.MultiToken.Tests/UnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiToken.Tests/UnitTestTokenContractInitializationProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using AElf.Kernel; using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; @@ -10,67 +9,66 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Options; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider { - public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider - { - private readonly EconomicOptions _economicOptions; - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; + private readonly EconomicOptions _economicOptions; - public UnitTestTokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, - IOptionsSnapshot economicOptions,IOptionsSnapshot consensusOptions) : base( - tokenContractInitializationDataProvider) - { - _economicOptions = economicOptions.Value; - _consensusOptions = consensusOptions.Value; - } + public UnitTestTokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, + IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) : base( + tokenContractInitializationDataProvider) + { + _economicOptions = economicOptions.Value; + _consensusOptions = consensusOptions.Value; + } - public override List GetInitializeMethodList(byte[] contractCode) + public override List GetInitializeMethodList(byte[] contractCode) + { + var address = Address.FromPublicKey( + ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); + var list = new List { - var address = Address.FromPublicKey( - ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); - var list = new List + new() { - new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = new CreateInput - { - Decimals = _economicOptions.Decimals, - Issuer = address, - IsBurnable = _economicOptions.IsBurnable, - Symbol = _economicOptions.Symbol, - TokenName = _economicOptions.TokenName, - TotalSupply = _economicOptions.TotalSupply, - }.ToByteString(), - }, - new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = new CreateInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), - Params = new IssueInput - { - Symbol = _economicOptions.Symbol, - Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), - To = address, - Memo = "Issue native token" - }.ToByteString() - }, - new ContractInitializationMethodCall + Decimals = _economicOptions.Decimals, + Issuer = address, + IsBurnable = _economicOptions.IsBurnable, + Symbol = _economicOptions.Symbol, + TokenName = _economicOptions.TokenName, + TotalSupply = _economicOptions.TotalSupply + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), + Params = new IssueInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = _economicOptions.Symbol - }.ToByteString() - }, - new ContractInitializationMethodCall + Symbol = _economicOptions.Symbol, + Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), + To = address, + Memo = "Issue native token" + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), - Params = new Empty().ToByteString() - } - }; - return list; - } + Symbol = _economicOptions.Symbol + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), + Params = new Empty().ToByteString() + } + }; + return list; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj index a29e7c9407..e38fe34417 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/AElf.Contracts.MultiTokenCrossChainTransfer.Tests.csproj @@ -1,143 +1,143 @@ - - net6.0 - AElf.Contracts.MultiTokenCrossSideChain - false - - - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - false - Contract - PreserveNewest - - - - - - - - - - - + + net6.0 + AElf.Contracts.MultiTokenCrossSideChain + false + + + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + - - - Protobuf\Proto\authority_info.proto - - - Protobuf\Proto\acs2.proto - - - Protobuf\Proto\acs3.proto - - - Protobuf\Proto\acs5.proto - - - Protobuf\Proto\transaction_fee.proto - - - Protobuf\Proto\token_contract.proto - - - Protobuf\Proto\token_contract_impl.proto - - - Protobuf\Proto\acs3.proto - - - Protobuf\Proto\cross_chain_contract.proto - - - Protobuf\Proto\cross_chain_contract_impl.proto - - - Protobuf\Proto\parliament_contract.proto - - - Protobuf\Proto\parliament_contract_impl.proto - - - Protobuf\Proto\referendum_contract.proto - - - Protobuf\Proto\referendum_contract_impl.proto - - - Protobuf\Proto\aedpos_contract.proto - - - Protobuf\Proto\association_contract.proto - - - Protobuf\Proto\association_contract_impl.proto - - - Protobuf\Proto\aedpos_contract_impl.proto - - - Protobuf\Proto\acs4.proto - - - Protobuf\Proto\acs6.proto - - - Protobuf\Proto\acs10.proto - - - Protobuf\Proto\acs11.proto - - - Protobuf\Proto\acs0.proto - - - Protobuf\Proto\basic_contract_zero.proto - - - Protobuf\Proto\basic_contract_zero_impl.proto - - + + + + + + + + + + + + + Protobuf\Proto\authority_info.proto + + + Protobuf\Proto\acs2.proto + + + Protobuf\Proto\acs3.proto + + + Protobuf\Proto\acs5.proto + + + Protobuf\Proto\transaction_fee.proto + + + Protobuf\Proto\token_contract.proto + + + Protobuf\Proto\token_contract_impl.proto + + + Protobuf\Proto\acs3.proto + + + Protobuf\Proto\cross_chain_contract.proto + + + Protobuf\Proto\cross_chain_contract_impl.proto + + + Protobuf\Proto\parliament_contract.proto + + + Protobuf\Proto\parliament_contract_impl.proto + + + Protobuf\Proto\referendum_contract.proto + + + Protobuf\Proto\referendum_contract_impl.proto + + + Protobuf\Proto\aedpos_contract.proto + + + Protobuf\Proto\association_contract.proto + + + Protobuf\Proto\association_contract_impl.proto + + + Protobuf\Proto\aedpos_contract_impl.proto + + + Protobuf\Proto\acs4.proto + + + Protobuf\Proto\acs6.proto + + + Protobuf\Proto\acs10.proto + + + Protobuf\Proto\acs11.proto + + + Protobuf\Proto\acs0.proto + + + Protobuf\Proto\basic_contract_zero.proto + + + Protobuf\Proto\basic_contract_zero_impl.proto + + diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ContractDeploymentListProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ContractDeploymentListProvider.cs index 9b9efb60d2..2ae6c19595 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ContractDeploymentListProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ContractDeploymentListProvider.cs @@ -7,37 +7,36 @@ using AElf.Kernel.Token; using AElf.Types; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class MultiChainContractDeploymentListProvider : IContractDeploymentListProvider { - public class MultiChainContractDeploymentListProvider : IContractDeploymentListProvider + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - ConsensusSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name - }; - } + ConsensusSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name + }; } - - public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider +} + +public class SideChainContractDeploymentListProvider : IContractDeploymentListProvider +{ + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - ConsensusSmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ReferendumSmartContractAddressNameProvider.Name, - AssociationSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - CrossChainSmartContractAddressNameProvider.Name - }; - } + ConsensusSmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ReferendumSmartContractAddressNameProvider.Name, + AssociationSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + CrossChainSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs index 97d137be91..eb6471b574 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs @@ -1,547 +1,599 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS7; using AElf.Contracts.Parliament; using AElf.ContractTestBase.ContractTestKit; using AElf.CrossChain; using AElf.CSharp.Core.Utils; using AElf.Kernel.Token; +using AElf.Standards.ACS0; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -using ProposalCreated = AElf.Standards.ACS3.ProposalCreated; -using ProposalReleased = AElf.Standards.ACS3.ProposalReleased; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class MultiTokenContractCrossChainTest : MultiTokenContractCrossChainTestBase { - public class MultiTokenContractCrossChainTest : MultiTokenContractCrossChainTestBase + private const string SymbolForTesting = "ELFTEST"; + private const string NativeToken = "ELF"; + private static readonly long _totalSupply = 1000L; + private readonly Hash _fakeBlockHeader = HashHelper.ComputeFrom("fakeBlockHeader"); + private readonly int _parentChainHeightOfCreation = 5; + private readonly string sideChainSymbol = "STA"; + + #region register test + + [Fact] + public async Task MainChain_RegisterCrossChainTokenContractAddress_Test() { - private const string SymbolForTesting = "ELFTEST"; - private const string NativeToken = "ELF"; - private static long _totalSupply = 1000L; - private readonly int _parentChainHeightOfCreation = 5; - private readonly Hash _fakeBlockHeader = HashHelper.ComputeFrom("fakeBlockHeader"); - private string sideChainSymbol = "STA"; + var sideChainId = await GenerateSideChainAsync(); + //Side chain validate transaction + var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = SideTokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var sideBlock = await SideChainTestKit.MineAsync(new List { validateTransaction }); + var validateTransactionResult = sideBlock.TransactionResultMap[validateTransaction.GetHash()]; + validateTransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, validateTransactionResult.Error); + + //Main chain side chain index each other + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await MainAndSideIndexAsync(sideChainId, sideBlock.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(sideBlock.Height); + + // Main chain register + var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, + merklePath, + boundParentChainHeightAndMerklePath, sideChainId); + result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); + } - #region register test + [Fact] + public async Task SideChain_RegisterCrossChainTokenContractAddress_Test() + { + await GenerateSideChainAsync(); + //Main chain validate transaction + var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = TokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var blockExecutedSet = await MineAsync(new List { validateTransaction }); + var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + // Index main chain + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); + //Side chain register + var result = + await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, + _parentChainHeightOfCreation); + Assert.True(result.Status == TransactionResultStatus.Mined, result.Error); + } - [Fact] - public async Task MainChain_RegisterCrossChainTokenContractAddress_Test() - { - var sideChainId = await GenerateSideChainAsync(); - //Side chain validate transaction - var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = SideTokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var sideBlock = await SideChainTestKit.MineAsync(new List {validateTransaction}); - var validateTransactionResult = sideBlock.TransactionResultMap[validateTransaction.GetHash()]; - validateTransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, validateTransactionResult.Error); - - //Main chain side chain index each other - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await MainAndSideIndexAsync(sideChainId, sideBlock.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(sideBlock.Height); - - // Main chain register - var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, - merklePath, - boundParentChainHeightAndMerklePath, sideChainId); - result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); - } + [Fact] + public async Task RegisterCrossChainTokenContractAddress_WithoutPermission_Test() + { + var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = TokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var executionResult = await TokenContractStub.RegisterCrossChainTokenContractAddress.SendWithExceptionAsync( + new RegisterCrossChainTokenContractAddressInput + { + FromChainId = MainChainId, + ParentChainHeight = _parentChainHeightOfCreation, + TokenContractAddress = TokenContractAddress, + TransactionBytes = validateTransaction.ToByteString() + }); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("No permission."); + } - [Fact] - public async Task SideChain_RegisterCrossChainTokenContractAddress_Test() - { - await GenerateSideChainAsync(); - //Main chain validate transaction - var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = TokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var blockExecutedSet = await MineAsync(new List {validateTransaction}); - var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - // Index main chain - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); - //Side chain register - var result = - await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, - _parentChainHeightOfCreation); - Assert.True(result.Status == TransactionResultStatus.Mined, result.Error); - } + [Fact] + public async Task RegisterCrossChainTokenContractAddress_ValidateWrongAddress_Test() + { + var sideChainId = await GenerateSideChainAsync(); + var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = SideCrossChainContractAddress, + SystemContractHashName = CrossChainSmartContractAddressNameProvider.Name + }); + var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List { validateTransaction }); + var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + + //Main chain side chain index each other + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); + + // Main chain register + var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, + merklePath, + boundParentChainHeightAndMerklePath, sideChainId); + + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain("Address validation failed."); + } - [Fact] - public async Task RegisterCrossChainTokenContractAddress_WithoutPermission_Test() - { - var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = TokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var executionResult = await TokenContractStub.RegisterCrossChainTokenContractAddress.SendWithExceptionAsync( - new RegisterCrossChainTokenContractAddressInput - { - FromChainId = MainChainId, - ParentChainHeight = _parentChainHeightOfCreation, - TokenContractAddress = TokenContractAddress, - TransactionBytes = validateTransaction.ToByteString() - }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("No permission."); - } + [Fact] + public async Task RegisterCrossChainTokenContractAddress_InvalidTransaction_Test() + { + var sideChainId = await GenerateSideChainAsync(); + var wrongChainId = ChainHelper.GetChainId(1); + var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = SideTokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List { validateTransaction }); + var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); + + var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, + merklePath, + boundParentChainHeightAndMerklePath, wrongChainId); + Assert.True(result.Status == TransactionResultStatus.Failed); + result.Error.ShouldContain("Invalid transaction."); + } - [Fact] - public async Task RegisterCrossChainTokenContractAddress_ValidateWrongAddress_Test() - { - var sideChainId = await GenerateSideChainAsync(); - var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = SideCrossChainContractAddress, - SystemContractHashName = CrossChainSmartContractAddressNameProvider.Name - }); - var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List {validateTransaction}); - var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - - //Main chain side chain index each other - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); - - // Main chain register - var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, - merklePath, - boundParentChainHeightAndMerklePath, sideChainId); - - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain("Address validation failed."); - } + [Fact] + public async Task RegisterCrossChainTokenContractAddress_VerificationFailed_Test() + { + await GenerateSideChainAsync(); + //Main chain validate transaction + var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput + { + Address = TokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var blockExecutedSet = await MineAsync(new List { validateTransaction }); + var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + // Index main chain + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); + // Wrong merklePath + merklePath.MerklePathNodes.AddRange(merklePath.MerklePathNodes); + //Side chain register + var result = + await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, + _parentChainHeightOfCreation); + Assert.True(result.Status == TransactionResultStatus.Failed); + Assert.Contains("Cross chain verification failed.", result.Error); + } + + #endregion - [Fact] - public async Task RegisterCrossChainTokenContractAddress_InvalidTransaction_Test() + #region cross chain create token test + + [Fact] + public async Task MainChain_CrossChainCreateToken_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + + // Side chain create token + var createTransaction = + CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, + SymbolForTesting); + var executedSet = await SideChainTestKit.MineAsync(new List { createTransaction }); + var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + + var createdTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var sideChainId = await GenerateSideChainAsync(); - var wrongChainId = ChainHelper.GetChainId(1); - var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = SideTokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List {validateTransaction}); - var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); - - var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, - merklePath, - boundParentChainHeightAndMerklePath, wrongChainId); - Assert.True(result.Status == TransactionResultStatus.Failed); - result.Error.ShouldContain("Invalid transaction."); - } + Symbol = SymbolForTesting + }); + var tokenValidationTransaction = + CreateTokenInfoValidationTransaction(createdTokenInfo, SideChainTokenContractStub); + + executedSet = await SideChainTestKit.MineAsync(new List { tokenValidationTransaction }); + var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + await MainAndSideIndexAsync(sideChainId, executedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(executedSet.Height); + + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = sideChainId, + ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = merklePath + }; + crossChainCreateTokenInput.MerklePath.MerklePathNodes.AddRange(boundParentChainHeightAndMerklePath + .MerklePathFromParentChain.MerklePathNodes); + // Main chain cross chain create + await TokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); + } - [Fact] - public async Task RegisterCrossChainTokenContractAddress_VerificationFailed_Test() + [Fact] + public async Task SideChain_CrossChainCreateToken_Test() + { + await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + + // Main chain create token + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting); + var blockExecutedSet = await MineAsync(new List { createTransaction }); + var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + + var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - await GenerateSideChainAsync(); - //Main chain validate transaction - var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = TokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var blockExecutedSet = await MineAsync(new List {validateTransaction}); - var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - // Index main chain - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); - // Wrong merklePath - merklePath.MerklePathNodes.AddRange(merklePath.MerklePathNodes); - //Side chain register - var result = - await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, - _parentChainHeightOfCreation); - Assert.True(result.Status == TransactionResultStatus.Failed); - Assert.Contains("Cross chain verification failed.", result.Error); - } + Symbol = SymbolForTesting + }); + var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, + TokenContractStub); + + blockExecutedSet = await MineAsync(new List { tokenValidationTransaction }); + var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(blockExecutedSet.Height, blockRoot, blockRoot); + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = MainChainId, + ParentChainHeight = blockExecutedSet.Height, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = merklePath + }; + // Side chain cross chain create + var executionResult = + await SideChainTokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, + executionResult.TransactionResult.Error); - #endregion + var newTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = SymbolForTesting + }); + newTokenInfo.TotalSupply.ShouldBe(_totalSupply); + } - #region cross chain create token test + [Fact] + public async Task SideChain_CrossChainSideChainCreateToken_Test() + { + var sideChainId1 = await GenerateSideChainAsync(); + await GenerateSideChain2Async(); + await RegisterSideChainContractAddressOnSideChainAsync(sideChainId1); - [Fact] - public async Task MainChain_CrossChainCreateToken_Test() + // side chain 1 valid token + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var createdTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var sideChainId = await GenerateSideChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - // Side chain create token - var createTransaction = - CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, - SymbolForTesting); - var executedSet = await SideChainTestKit.MineAsync(new List {createTransaction}); - var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - - var createdTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = SymbolForTesting - }); - var tokenValidationTransaction = - CreateTokenInfoValidationTransaction(createdTokenInfo, SideChainTokenContractStub); - - executedSet = await SideChainTestKit.MineAsync(new List {tokenValidationTransaction}); - var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - await MainAndSideIndexAsync(sideChainId, executedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(executedSet.Height); + Symbol = sideChainSymbol + }); + var tokenValidationTransaction = + CreateTokenInfoValidationTransaction(createdTokenInfo, SideChainTokenContractStub); + + var blockExecutedSet = await SideChainTestKit.MineAsync(new List { tokenValidationTransaction }); + var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); + await SideIndexSideChainAsync(sideChainId1, blockExecutedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(blockExecutedSet.Height); + + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = sideChainId1, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = merklePath + }; + crossChainCreateTokenInput.MerklePath.MerklePathNodes.AddRange(boundParentChainHeightAndMerklePath + .MerklePathFromParentChain.MerklePathNodes); + crossChainCreateTokenInput.ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight; + + // Side chain 2 cross chain create + var executionResult = + await SideChain2TokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, + executionResult.TransactionResult.Error); + + var newTokenInfo = await SideChain2TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = sideChainSymbol + }); + Assert.True(newTokenInfo.TotalSupply == createdTokenInfo.TotalSupply); + Assert.True(newTokenInfo.Issuer == createdTokenInfo.Issuer); + Assert.True(newTokenInfo.IssueChainId == createdTokenInfo.IssueChainId); + Assert.True(newTokenInfo.Symbol == createdTokenInfo.Symbol); + } - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = sideChainId, - ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = merklePath - }; - crossChainCreateTokenInput.MerklePath.MerklePathNodes.AddRange(boundParentChainHeightAndMerklePath - .MerklePathFromParentChain.MerklePathNodes); - // Main chain cross chain create - await TokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); - } - [Fact] - public async Task SideChain_CrossChainCreateToken_Test() + [Fact] + public async Task SideChain_CrossChainCreateToken_WithAlreadyCreated_Test() + { + await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting); + var blockExecutedSet = await MineAsync(new List { createTransaction }); + var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + + var sideCreateTransaction = CreateTransactionForTokenCreation(SideChainTokenContractStub, + SideChainTestKit.DefaultAccount.Address, SymbolForTesting); + blockExecutedSet = await SideChainTestKit.MineAsync(new List { sideCreateTransaction }); + var sideCreateResult = blockExecutedSet.TransactionResultMap[sideCreateTransaction.GetHash()]; + Assert.True(sideCreateResult.Status == TransactionResultStatus.Mined, sideCreateResult.Error); + + var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - - // Main chain create token - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); - var blockExecutedSet = await MineAsync(new List {createTransaction}); - var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - - var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = SymbolForTesting - }); - var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, - TokenContractStub); + Symbol = SymbolForTesting + }); + var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, TokenContractStub); + var executedSet = await MineAsync(new List { tokenValidationTransaction }); + var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(executedSet.Height, blockRoot, blockRoot); + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = MainChainId, + ParentChainHeight = executedSet.Height, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = merklePath + }; + + var executionResult = + await SideChainTokenContractStub.CrossChainCreateToken.SendWithExceptionAsync( + crossChainCreateTokenInput); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Token already exists.", executionResult.TransactionResult.Error); + } - blockExecutedSet = await MineAsync(new List {tokenValidationTransaction}); - var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(blockExecutedSet.Height, blockRoot, blockRoot); - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = MainChainId, - ParentChainHeight = blockExecutedSet.Height, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = merklePath - }; - // Side chain cross chain create - var executionResult = - await SideChainTokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, - executionResult.TransactionResult.Error); - - var newTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = SymbolForTesting - }); - newTokenInfo.TotalSupply.ShouldBe(_totalSupply); - } + [Fact] + public async Task CrossChainCreateToken_With_Invalid_Verification_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - [Fact] - public async Task SideChain_CrossChainSideChainCreateToken_Test() + var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = SymbolForTesting + }); + var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, TokenContractStub); + var crossChainCreateTokenInput = new CrossChainCreateTokenInput { - var sideChainId1 = await GenerateSideChainAsync(); - await GenerateSideChain2Async(); - await RegisterSideChainContractAddressOnSideChainAsync(sideChainId1); + FromChainId = sideChainId, + ParentChainHeight = 0, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = new MerklePath() + }; + // Main chain cross chain create + var result = + (await TokenContractStub.CrossChainCreateToken.SendWithExceptionAsync(crossChainCreateTokenInput)) + .TransactionResult; + Assert.True(result.Status == TransactionResultStatus.Failed); + Assert.Contains("Invalid transaction", result.Error); + } - // side chain 1 valid token - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var createdTokenInfo = await SideChainTokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = sideChainSymbol - }); - var tokenValidationTransaction = - CreateTokenInfoValidationTransaction(createdTokenInfo, SideChainTokenContractStub); + #endregion - var blockExecutedSet = await SideChainTestKit.MineAsync(new List {tokenValidationTransaction}); - var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); - await SideIndexSideChainAsync(sideChainId1, blockExecutedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(blockExecutedSet.Height); + #region cross chain transfer - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = sideChainId1, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = merklePath - }; - crossChainCreateTokenInput.MerklePath.MerklePathNodes.AddRange(boundParentChainHeightAndMerklePath - .MerklePathFromParentChain.MerklePathNodes); - crossChainCreateTokenInput.ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight; - - // Side chain 2 cross chain create - var executionResult = - await SideChain2TokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, - executionResult.TransactionResult.Error); - - var newTokenInfo = await SideChain2TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = sideChainSymbol - }); - Assert.True(newTokenInfo.TotalSupply == createdTokenInfo.TotalSupply); - Assert.True(newTokenInfo.Issuer == createdTokenInfo.Issuer); - Assert.True(newTokenInfo.IssueChainId == createdTokenInfo.IssueChainId); - Assert.True(newTokenInfo.Symbol == createdTokenInfo.Symbol); - } + [Fact] + public async Task MainChain_CrossChainTransfer_NativeToken_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAccount.Address, + Symbol = NativeToken + }); - [Fact] - public async Task SideChain_CrossChainCreateToken_WithAlreadyCreated_Test() + //Main chain cross transfer to side chain + var executionResult = await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput + { + Symbol = NativeToken, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId + }); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Mined, + executionResult.TransactionResult.Error); + + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); - var blockExecutedSet = await MineAsync(new List {createTransaction}); - var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - - var sideCreateTransaction = CreateTransactionForTokenCreation(SideChainTokenContractStub, - SideChainTestKit.DefaultAccount.Address, SymbolForTesting); - blockExecutedSet = await SideChainTestKit.MineAsync(new List {sideCreateTransaction}); - var sideCreateResult = blockExecutedSet.TransactionResultMap[sideCreateTransaction.GetHash()]; - Assert.True(sideCreateResult.Status == TransactionResultStatus.Mined, sideCreateResult.Error); - - var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + Owner = DefaultAccount.Address, + Symbol = NativeToken + }); + balance.Balance.ShouldBe(balanceBefore.Balance - 1000); + + //verify side chain token address throw main chain token contract + var tokenAddress = await TokenContractStub.GetCrossChainTransferTokenContractAddress.CallAsync( + new GetCrossChainTransferTokenContractAddressInput { - Symbol = SymbolForTesting + ChainId = sideChainId }); - var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, TokenContractStub); - var executedSet = await MineAsync(new List {tokenValidationTransaction}); - var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(executedSet.Height, blockRoot, blockRoot); - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = MainChainId, - ParentChainHeight = executedSet.Height, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = merklePath - }; - - var executionResult = - await SideChainTokenContractStub.CrossChainCreateToken.SendWithExceptionAsync( - crossChainCreateTokenInput); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Token already exists.", executionResult.TransactionResult.Error); - } - - [Fact] - public async Task CrossChainCreateToken_With_Invalid_Verification_Test() + tokenAddress.ShouldBe(SideTokenContractAddress); + } + + [Fact] + public async Task MainChain_CrossChainTransfer_Without_Burnable_Token_Test() + { + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting, false); + var blockExecutedSet = await MineAsync(new List { createTransaction }); + var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - int sideChainId = await GenerateSideChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + Symbol = SymbolForTesting + }); + var issueId = tokenInfo.IssueChainId; + var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( + new CrossChainTransferInput { - Symbol = SymbolForTesting + Symbol = SymbolForTesting, + ToChainId = issueId, + Amount = 1000, + To = DefaultAccount.Address, + IssueChainId = issueId }); - var tokenValidationTransaction = CreateTokenInfoValidationTransaction(createdTokenInfo, TokenContractStub); - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = sideChainId, - ParentChainHeight = 0, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = new MerklePath() - }; - // Main chain cross chain create - var result = - (await TokenContractStub.CrossChainCreateToken.SendWithExceptionAsync(crossChainCreateTokenInput)).TransactionResult; - Assert.True(result.Status == TransactionResultStatus.Failed); - Assert.Contains("Invalid transaction", result.Error); - } - - #endregion + blockExecutedSet = await MineAsync(new List { crossChainTransferTransaction }); + var txResult2 = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; + txResult2.Error.ShouldContain("The token is not burnable"); + } - #region cross chain transfer - [Fact] - public async Task MainChain_CrossChainTransfer_NativeToken_Test() + [Fact] + public async Task MainChain_CrossChainTransfer_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + + // Main chain create token + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting); + var executedSet = await MineAsync(new List { createTransaction }); + var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + + var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + Symbol = SymbolForTesting + }); + var tokenValidationTransaction = TokenContractStub.ValidateTokenInfoExists.GetTransaction( + new ValidateTokenInfoExistsInput { - Owner = DefaultAccount.Address, - Symbol = NativeToken + TokenName = createdTokenInfo.TokenName, + Symbol = createdTokenInfo.Symbol, + Decimals = createdTokenInfo.Decimals, + Issuer = createdTokenInfo.Issuer, + IsBurnable = createdTokenInfo.IsBurnable, + TotalSupply = createdTokenInfo.TotalSupply, + IssueChainId = createdTokenInfo.IssueChainId }); + executedSet = await MineAsync(new List { tokenValidationTransaction }); + var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(executedSet.Height, blockRoot, blockRoot); + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = MainChainId, + ParentChainHeight = executedSet.Height, + TransactionBytes = tokenValidationTransaction.ToByteString(), + MerklePath = merklePath + }; + // Side chain cross chain create + await SideChainTokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); + + //Main chain cross transfer to side chain + await IssueTransactionAsync(SymbolForTesting, 1000); + var executionResult = await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput + { + Symbol = SymbolForTesting, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId + }); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, + executionResult.TransactionResult.Error); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultAccount.Address, + Symbol = SymbolForTesting + }); + balance.Balance.ShouldBe(0); - //Main chain cross transfer to side chain - var executionResult = await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput + // can't issue Token on chain which is not issue chain + executionResult = await SideChainTokenContractStub.Issue.SendWithExceptionAsync(new IssueInput + { + Symbol = SymbolForTesting, + Amount = _totalSupply, + To = SideChainTestKit.DefaultAccount.Address + }); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Unable to issue token with wrong chainId", executionResult.TransactionResult.Error); + } + + [Fact] + public async Task MainChain_CrossChainTransfer_IncorrectChainId_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + + var executionResult = await TokenContractStub.CrossChainTransfer.SendWithExceptionAsync( + new CrossChainTransferInput { Symbol = NativeToken, ToChainId = sideChainId, Amount = 1000, To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Mined, - executionResult.TransactionResult.Error); - - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAccount.Address, - Symbol = NativeToken + IssueChainId = sideChainId }); - balance.Balance.ShouldBe(balanceBefore.Balance - 1000); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Incorrect issue chain id.", executionResult.TransactionResult.Error); + } - //verify side chain token address throw main chain token contract - var tokenAddress = await TokenContractStub.GetCrossChainTransferTokenContractAddress.CallAsync( - new GetCrossChainTransferTokenContractAddressInput - { - ChainId = sideChainId - }); - tokenAddress.ShouldBe(SideTokenContractAddress); - } + [Fact] + public async Task MainChain_CrossChainTransfer_InvalidChainId_Test() + { + var wrongSideChainId = ChainHelper.GetChainId(1); + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - [Fact] - public async Task MainChain_CrossChainTransfer_Without_Burnable_Token_Test() - { - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting, false); - var blockExecutedSet = await MineAsync(new List {createTransaction}); - var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + await TokenContractStub.CrossChainTransfer.SendAsync( + new CrossChainTransferInput { - Symbol = SymbolForTesting + Symbol = NativeToken, + ToChainId = wrongSideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId }); - var issueId = tokenInfo.IssueChainId; - var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( - new CrossChainTransferInput - { - Symbol = SymbolForTesting, - ToChainId = issueId, - Amount = 1000, - To = DefaultAccount.Address, - IssueChainId = issueId - }); - blockExecutedSet = await MineAsync(new List {crossChainTransferTransaction}); - var txResult2 = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; - txResult2.Error.ShouldContain("The token is not burnable"); - } + } + [Fact] + public async Task MainChain_CrossChainTransfer_MemoLength_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - [Fact] - public async Task MainChain_CrossChainTransfer_Test() { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - // Main chain create token - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); - var executedSet = await MineAsync(new List {createTransaction}); - var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - - var createdTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = SymbolForTesting - }); - var tokenValidationTransaction = TokenContractStub.ValidateTokenInfoExists.GetTransaction( - new ValidateTokenInfoExistsInput - { - TokenName = createdTokenInfo.TokenName, - Symbol = createdTokenInfo.Symbol, - Decimals = createdTokenInfo.Decimals, - Issuer = createdTokenInfo.Issuer, - IsBurnable = createdTokenInfo.IsBurnable, - TotalSupply = createdTokenInfo.TotalSupply, - IssueChainId = createdTokenInfo.IssueChainId - }); - executedSet = await MineAsync(new List {tokenValidationTransaction}); - var merklePath = GetTransactionMerklePathAndRoot(tokenValidationTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(executedSet.Height, blockRoot, blockRoot); - var crossChainCreateTokenInput = new CrossChainCreateTokenInput + await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput { - FromChainId = MainChainId, - ParentChainHeight = executedSet.Height, - TransactionBytes = tokenValidationTransaction.ToByteString(), - MerklePath = merklePath - }; - // Side chain cross chain create - await SideChainTokenContractStub.CrossChainCreateToken.SendAsync(crossChainCreateTokenInput); - - //Main chain cross transfer to side chain - await IssueTransactionAsync(SymbolForTesting, 1000); - var executionResult = await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput - { - Symbol = SymbolForTesting, + Symbol = NativeToken, ToChainId = sideChainId, Amount = 1000, To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined, - executionResult.TransactionResult.Error); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAccount.Address, - Symbol = SymbolForTesting + IssueChainId = MainChainId, + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest.." }); - balance.Balance.ShouldBe(0); - - // can't issue Token on chain which is not issue chain - executionResult = await SideChainTokenContractStub.Issue.SendWithExceptionAsync(new IssueInput - { - Symbol = SymbolForTesting, - Amount = _totalSupply, - To = SideChainTestKit.DefaultAccount.Address - }); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Unable to issue token with wrong chainId", executionResult.TransactionResult.Error); } - [Fact] - public async Task MainChain_CrossChainTransfer_IncorrectChainId_Test() { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - var executionResult = await TokenContractStub.CrossChainTransfer.SendWithExceptionAsync( new CrossChainTransferInput { @@ -549,788 +601,723 @@ public async Task MainChain_CrossChainTransfer_IncorrectChainId_Test() ToChainId = sideChainId, Amount = 1000, To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = sideChainId + IssueChainId = MainChainId, + Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..." }); Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Incorrect issue chain id.", executionResult.TransactionResult.Error); + Assert.Contains("Invalid memo size.", executionResult.TransactionResult.Error); } + } - [Fact] - public async Task MainChain_CrossChainTransfer_InvalidChainId_Test() - { - var wrongSideChainId = ChainHelper.GetChainId(1); - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + #endregion - await TokenContractStub.CrossChainTransfer.SendAsync( - new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = wrongSideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - } + #region cross chain receive - [Fact] - public async Task MainChain_CrossChainTransfer_MemoLength_Test() - { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - { - await TokenContractStub.CrossChainTransfer.SendAsync(new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest.." - }); - } + [Fact] + public async Task SideChain_CrossChainReceived_NativeToken_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + //Main chain cross transfer to side chain + var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( + new CrossChainTransferInput { - var executionResult = await TokenContractStub.CrossChainTransfer.SendWithExceptionAsync( - new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId, - Memo = "MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest MemoTest..." - }); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Invalid memo size.", executionResult.TransactionResult.Error); - } - } - - #endregion - - #region cross chain receive - - [Fact] - public async Task SideChain_CrossChainReceived_NativeToken_Test() + Symbol = NativeToken, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId + }); + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var blockExecutedSet = await MineAsync(new List { crossChainTransferTransaction }); + var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; + txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); + + var height = blockExecutedSet.Height > _parentChainHeightOfCreation + ? blockExecutedSet.Height + : _parentChainHeightOfCreation; + var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput + { + FromChainId = MainChainId, + ParentChainHeight = height, + TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), + MerklePath = transferMerKlePath + }; + await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); + + var output = await SideChainTokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + Owner = SideChainTestKit.DefaultAccount.Address, + Symbol = NativeToken + }); + Assert.Equal(1000, output.Balance); + } - //Main chain cross transfer to side chain - var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( - new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var blockExecutedSet = await MineAsync(new List {crossChainTransferTransaction}); - var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; - txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); - - var height = blockExecutedSet.Height > _parentChainHeightOfCreation - ? blockExecutedSet.Height - : _parentChainHeightOfCreation; - var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput - { - FromChainId = MainChainId, - ParentChainHeight = height, - TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), - MerklePath = transferMerKlePath - }; - await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); + [Fact] + public async Task SideChain_CrossChainReceived_Twice_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - var output = await SideChainTokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //Main chain cross transfer to side chain + var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( + new CrossChainTransferInput { - Owner = SideChainTestKit.DefaultAccount.Address, - Symbol = NativeToken + Symbol = NativeToken, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId }); - Assert.Equal(1000, output.Balance); - } - - [Fact] - public async Task SideChain_CrossChainReceived_Twice_Test() + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var blockExecutedSet = await MineAsync(new List { crossChainTransferTransaction }); + var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; + txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); + + var height = blockExecutedSet.Height > _parentChainHeightOfCreation + ? blockExecutedSet.Height + : _parentChainHeightOfCreation; + var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - //Main chain cross transfer to side chain - var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( - new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var blockExecutedSet = await MineAsync(new List {crossChainTransferTransaction}); - var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; - txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); - - var height = blockExecutedSet.Height > _parentChainHeightOfCreation - ? blockExecutedSet.Height - : _parentChainHeightOfCreation; - var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput - { - FromChainId = MainChainId, - ParentChainHeight = height, - TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), - MerklePath = transferMerKlePath - }; - await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); - - var executionResult = - await SideChainTokenContractStub.CrossChainReceiveToken.SendWithExceptionAsync( - crossChainReceiveTokenInput); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Token already claimed.", executionResult.TransactionResult.Error); - } + FromChainId = MainChainId, + ParentChainHeight = height, + TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), + MerklePath = transferMerKlePath + }; + await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); + + var executionResult = + await SideChainTokenContractStub.CrossChainReceiveToken.SendWithExceptionAsync( + crossChainReceiveTokenInput); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Token already claimed.", executionResult.TransactionResult.Error); + } - [Fact] - public async Task SideChain_CrossChainReceived_InvalidToken_Test() - { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - var transferAmount = 1000; - - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); - var executedSet = await MineAsync(new List {createTransaction}); - var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; - createResult.Status.ShouldBe(TransactionResultStatus.Mined, createResult.Error); - await IssueTransactionAsync(SymbolForTesting, transferAmount); - - //Main chain cross transfer to side chain - var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( - new CrossChainTransferInput - { - Symbol = SymbolForTesting, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var blockExecutedSet = await MineAsync(new List {crossChainTransferTransaction}); - var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; - txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); - - var height = blockExecutedSet.Height > _parentChainHeightOfCreation - ? blockExecutedSet.Height - : _parentChainHeightOfCreation; - var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput + [Fact] + public async Task SideChain_CrossChainReceived_InvalidToken_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); + var transferAmount = 1000; + + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting); + var executedSet = await MineAsync(new List { createTransaction }); + var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; + createResult.Status.ShouldBe(TransactionResultStatus.Mined, createResult.Error); + await IssueTransactionAsync(SymbolForTesting, transferAmount); + + //Main chain cross transfer to side chain + var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( + new CrossChainTransferInput { - FromChainId = MainChainId, - ParentChainHeight = height, - TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), - MerklePath = transferMerKlePath - }; - var executionResult = - await SideChainTokenContractStub.CrossChainReceiveToken.SendWithExceptionAsync( - crossChainReceiveTokenInput); - - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Token is not found.", executionResult.TransactionResult.Error); - } - - [Fact] - public async Task SideChain_CrossChainReceived_WrongReceiver_Test() + Symbol = SymbolForTesting, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId + }); + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + var blockExecutedSet = await MineAsync(new List { crossChainTransferTransaction }); + var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; + txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); + + var height = blockExecutedSet.Height > _parentChainHeightOfCreation + ? blockExecutedSet.Height + : _parentChainHeightOfCreation; + var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput { - var sideChainId = await GenerateSideChainAsync(); - await RegisterSideChainContractAddressOnMainChainAsync(); - await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - - var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( - new CrossChainTransferInput - { - Symbol = NativeToken, - ToChainId = sideChainId, - Amount = 1000, - To = SideChainTestKit.DefaultAccount.Address, - IssueChainId = MainChainId - }); + FromChainId = MainChainId, + ParentChainHeight = height, + TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), + MerklePath = transferMerKlePath + }; + var executionResult = + await SideChainTokenContractStub.CrossChainReceiveToken.SendWithExceptionAsync( + crossChainReceiveTokenInput); + + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Token is not found.", executionResult.TransactionResult.Error); + } - var blockExecutedSet = await MineAsync(new List {crossChainTransferTransaction}); - var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; - txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); + [Fact] + public async Task SideChain_CrossChainReceived_WrongReceiver_Test() + { + var sideChainId = await GenerateSideChainAsync(); + await RegisterSideChainContractAddressOnMainChainAsync(); + await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); - var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(blockExecutedSet.Height, blockRoot, blockRoot); - var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput + var crossChainTransferTransaction = TokenContractStub.CrossChainTransfer.GetTransaction( + new CrossChainTransferInput { - FromChainId = MainChainId, - ParentChainHeight = blockExecutedSet.Height, - TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), - MerklePath = transferMerKlePath - }; - - var tokenContractImplStub = SideChainTestKit.GetTester( - SideTokenContractAddress, - SampleAccount.Accounts[2].KeyPair); - var executionResult = - await tokenContractImplStub.CrossChainReceiveToken.SendWithExceptionAsync(crossChainReceiveTokenInput); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Unable to claim cross chain token.", executionResult.TransactionResult.Error); - } + Symbol = NativeToken, + ToChainId = sideChainId, + Amount = 1000, + To = SideChainTestKit.DefaultAccount.Address, + IssueChainId = MainChainId + }); + + var blockExecutedSet = await MineAsync(new List { crossChainTransferTransaction }); + var txResult = blockExecutedSet.TransactionResultMap[crossChainTransferTransaction.GetHash()]; + txResult.Status.ShouldBe(TransactionResultStatus.Mined, txResult.Error); - [Fact] - public async Task CrossChainCreateToken_WithoutRegister_Test() + var transferMerKlePath = GetTransactionMerklePathAndRoot(crossChainTransferTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(blockExecutedSet.Height, blockRoot, blockRoot); + var crossChainReceiveTokenInput = new CrossChainReceiveTokenInput { - await GenerateSideChainAsync(false); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); - var blockExecutedSet = await MineAsync(new List {createTransaction}); - var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; - Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - - var merklePath = GetTransactionMerklePathAndRoot(createTransaction, out var blockRoot); - await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); - var crossChainCreateTokenInput = new CrossChainCreateTokenInput - { - FromChainId = MainChainId, - ParentChainHeight = _parentChainHeightOfCreation, - TransactionBytes = createTransaction.ToByteString(), - MerklePath = merklePath - }; + FromChainId = MainChainId, + ParentChainHeight = blockExecutedSet.Height, + TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), + MerklePath = transferMerKlePath + }; + + var tokenContractImplStub = SideChainTestKit.GetTester( + SideTokenContractAddress, + SampleAccount.Accounts[2].KeyPair); + var executionResult = + await tokenContractImplStub.CrossChainReceiveToken.SendWithExceptionAsync(crossChainReceiveTokenInput); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Unable to claim cross chain token.", executionResult.TransactionResult.Error); + } - var executionResult = - await SideChainTokenContractStub.CrossChainCreateToken.SendWithExceptionAsync( - crossChainCreateTokenInput); - Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); - Assert.Contains("Token contract address of chain AELF not registered.", - executionResult.TransactionResult.Error); - } + [Fact] + public async Task CrossChainCreateToken_WithoutRegister_Test() + { + await GenerateSideChainAsync(false); + var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting); + var blockExecutedSet = await MineAsync(new List { createTransaction }); + var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; + Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); + + var merklePath = GetTransactionMerklePathAndRoot(createTransaction, out var blockRoot); + await IndexMainChainTransactionAsync(_parentChainHeightOfCreation, blockRoot, blockRoot); + var crossChainCreateTokenInput = new CrossChainCreateTokenInput + { + FromChainId = MainChainId, + ParentChainHeight = _parentChainHeightOfCreation, + TransactionBytes = createTransaction.ToByteString(), + MerklePath = merklePath + }; + + var executionResult = + await SideChainTokenContractStub.CrossChainCreateToken.SendWithExceptionAsync( + crossChainCreateTokenInput); + Assert.True(executionResult.TransactionResult.Status == TransactionResultStatus.Failed); + Assert.Contains("Token contract address of chain AELF not registered.", + executionResult.TransactionResult.Error); + } - #endregion + #endregion - #region private method + #region private method - private async Task GenerateSideChainAsync(bool registerParentChainTokenContractAddress = true) - { - var sideChainId = - await InitAndCreateSideChainAsync(sideChainSymbol, _parentChainHeightOfCreation, MainChainId, 100); - StartSideChain(sideChainId, _parentChainHeightOfCreation, sideChainSymbol, - registerParentChainTokenContractAddress); - return sideChainId; - } + private async Task GenerateSideChainAsync(bool registerParentChainTokenContractAddress = true) + { + var sideChainId = + await InitAndCreateSideChainAsync(sideChainSymbol, _parentChainHeightOfCreation, MainChainId, 100); + StartSideChain(sideChainId, _parentChainHeightOfCreation, sideChainSymbol, + registerParentChainTokenContractAddress); + return sideChainId; + } - private async Task GenerateSideChain2Async() - { - var sideChainId = await InitAndCreateSideChainAsync("STB", _parentChainHeightOfCreation, MainChainId, 100); - StartSideChain2(sideChainId, _parentChainHeightOfCreation, "STB"); - } + private async Task GenerateSideChain2Async() + { + var sideChainId = await InitAndCreateSideChainAsync("STB", _parentChainHeightOfCreation, MainChainId, 100); + StartSideChain2(sideChainId, _parentChainHeightOfCreation, "STB"); + } - private Transaction ValidateTransaction(Address tokenContractAddress, Hash name, bool isMainChain) - { - if (isMainChain) - { - return BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = tokenContractAddress, - SystemContractHashName = name - }); - } - - return SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + private Transaction ValidateTransaction(Address tokenContractAddress, Hash name, bool isMainChain) + { + if (isMainChain) + return BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( new ValidateSystemContractAddressInput { Address = tokenContractAddress, SystemContractHashName = name }); - } - - private Transaction CreateTransactionForTokenCreation( - TokenContractImplContainer.TokenContractImplStub tokenContractImplStub, - Address issuer, string symbol, bool isBurnable = true) - { - var tokenInfo = GetTokenInfo(symbol, issuer, isBurnable); - return tokenContractImplStub.Create.GetTransaction(new CreateInput + return SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput { - Symbol = tokenInfo.Symbol, - Decimals = tokenInfo.Decimals, - Issuer = tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply + Address = tokenContractAddress, + SystemContractHashName = name }); - } + } - private Transaction CreateTokenInfoValidationTransaction(TokenInfo createdTokenInfo, - TokenContractImplContainer.TokenContractImplStub tokenContractImplStub) - { - return tokenContractImplStub.ValidateTokenInfoExists.GetTransaction(new ValidateTokenInfoExistsInput - { - TokenName = createdTokenInfo.TokenName, - Symbol = createdTokenInfo.Symbol, - Decimals = createdTokenInfo.Decimals, - Issuer = createdTokenInfo.Issuer, - IsBurnable = createdTokenInfo.IsBurnable, - TotalSupply = createdTokenInfo.TotalSupply, - IssueChainId = createdTokenInfo.IssueChainId - }); - } - private TokenInfo GetTokenInfo(string symbol, Address issuer, bool isBurnable = true) + private Transaction CreateTransactionForTokenCreation( + TokenContractImplContainer.TokenContractImplStub tokenContractImplStub, + Address issuer, string symbol, bool isBurnable = true) + { + var tokenInfo = GetTokenInfo(symbol, issuer, isBurnable); + return tokenContractImplStub.Create.GetTransaction(new CreateInput { - return new TokenInfo - { - Symbol = symbol, - Decimals = 2, - Issuer = issuer, - IsBurnable = isBurnable, - TokenName = "Symbol for testing", - TotalSupply = 1000 - }; - } + Symbol = tokenInfo.Symbol, + Decimals = tokenInfo.Decimals, + Issuer = tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + TokenName = tokenInfo.TokenName, + TotalSupply = tokenInfo.TotalSupply + }); + } - private async Task IssueTransactionAsync(string symbol, long amount) + private Transaction CreateTokenInfoValidationTransaction(TokenInfo createdTokenInfo, + TokenContractImplContainer.TokenContractImplStub tokenContractImplStub) + { + return tokenContractImplStub.ValidateTokenInfoExists.GetTransaction(new ValidateTokenInfoExistsInput { - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - To = DefaultAccount.Address, - Amount = amount - }); - var output = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAccount.Address, - Symbol = symbol - }); - - output.Balance.ShouldBe(amount); - } + TokenName = createdTokenInfo.TokenName, + Symbol = createdTokenInfo.Symbol, + Decimals = createdTokenInfo.Decimals, + Issuer = createdTokenInfo.Issuer, + IsBurnable = createdTokenInfo.IsBurnable, + TotalSupply = createdTokenInfo.TotalSupply, + IssueChainId = createdTokenInfo.IssueChainId + }); + } - private async Task RegisterMainChainTokenContractAddressOnSideChainAsync(int sideChainId) + private TokenInfo GetTokenInfo(string symbol, Address issuer, bool isBurnable = true) + { + return new TokenInfo { - var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = SideTokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List {validateTransaction}); - var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); - - //await BootMinerChangeRoundAsync(true); - var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, - merklePath, - boundParentChainHeightAndMerklePath, sideChainId); - result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); - } + Symbol = symbol, + Decimals = 2, + Issuer = issuer, + IsBurnable = isBurnable, + TokenName = "Symbol for testing", + TotalSupply = 1000 + }; + } - private async Task RegisterSideChainContractAddressOnMainChainAsync() + private async Task IssueTransactionAsync(string symbol, long amount) + { + await TokenContractStub.Issue.SendAsync(new IssueInput { - var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = TokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var blockExecutedSet = await MineAsync(new List {validateTransaction}); - var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; - Assert.True(validateResult.Status == TransactionResultStatus.Mined, validateResult.Error); - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); - var height = blockExecutedSet.Height > _parentChainHeightOfCreation - ? blockExecutedSet.Height - : _parentChainHeightOfCreation; - await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); - var result = await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, height); - result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); - } - - private async Task RegisterSideChainContractAddressOnSideChainAsync(int sideChainId) + Symbol = symbol, + To = DefaultAccount.Address, + Amount = amount + }); + var output = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var validateTransaction1 = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( - new ValidateSystemContractAddressInput - { - Address = SideTokenContractAddress, - SystemContractHashName = TokenSmartContractAddressNameProvider.Name - }); - var executedSet = await SideChainTestKit.MineAsync(new List {validateTransaction1}); - var validateResult = executedSet.TransactionResultMap[validateTransaction1.GetHash()]; - validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); - - var merklePath = GetTransactionMerklePathAndRoot(validateTransaction1, out var blockRoot); - await SideIndexSideChainAsync(sideChainId, executedSet.Height, blockRoot); - var boundParentChainHeightAndMerklePath = - await GetBoundParentChainHeightAndMerklePathByHeight(executedSet.Height); - - var result = await RegisterSideChainTokenContractOnSieChain2Async(Side2TokenContractAddress, - validateTransaction1, merklePath, - boundParentChainHeightAndMerklePath, sideChainId); - result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); - } + Owner = DefaultAccount.Address, + Symbol = symbol + }); - private async Task RegisterMainChainTokenContractOnSideChainAsync(Transaction transaction, - MerklePath merklePath, - long height) - { - var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput - { - FromChainId = MainChainId, - ParentChainHeight = height, - TokenContractAddress = TokenContractAddress, - TransactionBytes = transaction.ToByteString(), - MerklePath = merklePath - }; - var proposalId = await CreateProposalAsync(SideChainParliamentContractStub, - nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), - registerCrossChainTokenContractAddressInput.ToByteString(), SideTokenContractAddress); - await ApproveWithMinersAsync(proposalId, false); - return await SideChainTestKit.ExecuteTransactionWithMiningAsync( - SideChainParliamentContractStub.Release.GetTransaction(proposalId)); - ; - } + output.Balance.ShouldBe(amount); + } - private async Task RegisterSideChainTokenContractAsync(Address tokenContract, - IMessage transaction, - MerklePath merklePath, - CrossChainMerkleProofContext boundParentChainHeightAndMerklePath, int sideChainId) - { - var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput + private async Task RegisterMainChainTokenContractAddressOnSideChainAsync(int sideChainId) + { + var validateTransaction = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput { - FromChainId = sideChainId, - ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, - TokenContractAddress = SideTokenContractAddress, - TransactionBytes = transaction.ToByteString(), - MerklePath = merklePath - }; - registerCrossChainTokenContractAddressInput.MerklePath.MerklePathNodes.AddRange( - boundParentChainHeightAndMerklePath.MerklePathFromParentChain.MerklePathNodes); - var proposalId = await CreateProposalAsync(ParliamentContractStub, - nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), - registerCrossChainTokenContractAddressInput.ToByteString(), tokenContract); - await ApproveWithMinersAsync(proposalId); - return await ReleaseProposalAsync(proposalId); - } + Address = SideTokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var sideBlockExecutedSet = await SideChainTestKit.MineAsync(new List { validateTransaction }); + var validateResult = sideBlockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + await MainAndSideIndexAsync(sideChainId, sideBlockExecutedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(sideBlockExecutedSet.Height); + + //await BootMinerChangeRoundAsync(true); + var result = await RegisterSideChainTokenContractAsync(TokenContractAddress, validateTransaction, + merklePath, + boundParentChainHeightAndMerklePath, sideChainId); + result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); + } - private async Task RegisterSideChainTokenContractOnSieChain2Async(Address tokenContract, - IMessage transaction, - MerklePath merklePath, - CrossChainMerkleProofContext boundParentChainHeightAndMerklePath, int sideChainId) - { - var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput + private async Task RegisterSideChainContractAddressOnMainChainAsync() + { + var validateTransaction = BasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput { - FromChainId = sideChainId, - ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, - TokenContractAddress = SideTokenContractAddress, - TransactionBytes = transaction.ToByteString(), - MerklePath = merklePath - }; - registerCrossChainTokenContractAddressInput.MerklePath.MerklePathNodes.AddRange( - boundParentChainHeightAndMerklePath.MerklePathFromParentChain.MerklePathNodes); - var proposalId = await CreateProposalAsync(SideChain2ParliamentContractStub, - nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), - registerCrossChainTokenContractAddressInput.ToByteString(), tokenContract); - await ApproveWithMinersAsync(proposalId); - var transactionList = new List(); - foreach (var account in SampleAccount.Accounts.Take(5)) + Address = TokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var blockExecutedSet = await MineAsync(new List { validateTransaction }); + var validateResult = blockExecutedSet.TransactionResultMap[validateTransaction.GetHash()]; + Assert.True(validateResult.Status == TransactionResultStatus.Mined, validateResult.Error); + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction, out var blockRoot); + var height = blockExecutedSet.Height > _parentChainHeightOfCreation + ? blockExecutedSet.Height + : _parentChainHeightOfCreation; + await IndexMainChainTransactionAsync(height, blockRoot, blockRoot); + var result = await RegisterMainChainTokenContractOnSideChainAsync(validateTransaction, merklePath, height); + result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); + } + + private async Task RegisterSideChainContractAddressOnSideChainAsync(int sideChainId) + { + var validateTransaction1 = SideChainBasicContractZeroStub.ValidateSystemContractAddress.GetTransaction( + new ValidateSystemContractAddressInput { - var parliamentContractStub = - SideChain2TestKit.GetTester( - Side2ParliamentAddress, account.KeyPair); - transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); - } - - await SideChain2TestKit.MineAsync(transactionList); - var releaseTransaction = SideChain2ParliamentContractStub.Release.GetTransaction(proposalId); - return await SideChain2TestKit.ExecuteTransactionWithMiningAsync(releaseTransaction); - } + Address = SideTokenContractAddress, + SystemContractHashName = TokenSmartContractAddressNameProvider.Name + }); + var executedSet = await SideChainTestKit.MineAsync(new List { validateTransaction1 }); + var validateResult = executedSet.TransactionResultMap[validateTransaction1.GetHash()]; + validateResult.Status.ShouldBe(TransactionResultStatus.Mined, validateResult.Error); + + var merklePath = GetTransactionMerklePathAndRoot(validateTransaction1, out var blockRoot); + await SideIndexSideChainAsync(sideChainId, executedSet.Height, blockRoot); + var boundParentChainHeightAndMerklePath = + await GetBoundParentChainHeightAndMerklePathByHeight(executedSet.Height); + + var result = await RegisterSideChainTokenContractOnSieChain2Async(Side2TokenContractAddress, + validateTransaction1, merklePath, + boundParentChainHeightAndMerklePath, sideChainId); + result.Status.ShouldBe(TransactionResultStatus.Mined, result.Error); + } - private MerklePath GetTransactionMerklePathAndRoot(Transaction transaction, out Hash root) + private async Task RegisterMainChainTokenContractOnSideChainAsync(Transaction transaction, + MerklePath merklePath, + long height) + { + var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput { - var fakeHash1 = HashHelper.ComputeFrom("fake1"); - var fakeHash2 = HashHelper.ComputeFrom("fake2"); - - var rawBytes = transaction.GetHash().ToByteArray() - .Concat(EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())).ToArray(); - var hash = HashHelper.ComputeFrom(rawBytes); - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes((new[] {hash, fakeHash1, fakeHash2})); - - var merklePath = binaryMerkleTree.GenerateMerklePath(0); - root = binaryMerkleTree.Root; - return merklePath; - } + FromChainId = MainChainId, + ParentChainHeight = height, + TokenContractAddress = TokenContractAddress, + TransactionBytes = transaction.ToByteString(), + MerklePath = merklePath + }; + var proposalId = await CreateProposalAsync(SideChainParliamentContractStub, + nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), + registerCrossChainTokenContractAddressInput.ToByteString(), SideTokenContractAddress); + await ApproveWithMinersAsync(proposalId, false); + return await SideChainTestKit.ExecuteTransactionWithMiningAsync( + SideChainParliamentContractStub.Release.GetTransaction(proposalId)); + ; + } - private async Task IndexMainChainTransactionAsync(long height, Hash txRoot, Hash blockRoot) + private async Task RegisterSideChainTokenContractAsync(Address tokenContract, + IMessage transaction, + MerklePath merklePath, + CrossChainMerkleProofContext boundParentChainHeightAndMerklePath, int sideChainId) + { + var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput { - var indexParentHeight = await GetParentChainHeight(SideChainCrossChainContractStub); - var crossChainBlockData = new CrossChainBlockData(); - var index = indexParentHeight >= _parentChainHeightOfCreation - ? indexParentHeight + 1 - : _parentChainHeightOfCreation; - for (var i = index; i < height; i++) - { - crossChainBlockData.ParentChainBlockDataList.Add(CreateParentChainBlockData(i, MainChainId, - txRoot)); - } - - var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, txRoot); - crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); + FromChainId = sideChainId, + ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, + TokenContractAddress = SideTokenContractAddress, + TransactionBytes = transaction.ToByteString(), + MerklePath = merklePath + }; + registerCrossChainTokenContractAddressInput.MerklePath.MerklePathNodes.AddRange( + boundParentChainHeightAndMerklePath.MerklePathFromParentChain.MerklePathNodes); + var proposalId = await CreateProposalAsync(ParliamentContractStub, + nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), + registerCrossChainTokenContractAddressInput.ToByteString(), tokenContract); + await ApproveWithMinersAsync(proposalId); + return await ReleaseProposalAsync(proposalId); + } - parentChainBlockData.CrossChainExtraData = new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = blockRoot - }; - - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var proposingResult = - await SideChainCrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed) - .ProposalId; - await ApproveWithMinersAsync(proposalId, false); - var releaseResult = - await SideChainCrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput {ChainIdList = {MainChainId}}); - var releasedProposalId = ProposalReleased.Parser - .ParseFrom(releaseResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalReleased))) - .NonIndexed).ProposalId; - releasedProposalId.ShouldBe(proposalId); - - var parentChainHeight = await GetParentChainHeight(SideChainCrossChainContractStub); - parentChainHeight.ShouldBe(height); + private async Task RegisterSideChainTokenContractOnSieChain2Async(Address tokenContract, + IMessage transaction, + MerklePath merklePath, + CrossChainMerkleProofContext boundParentChainHeightAndMerklePath, int sideChainId) + { + var registerCrossChainTokenContractAddressInput = new RegisterCrossChainTokenContractAddressInput + { + FromChainId = sideChainId, + ParentChainHeight = boundParentChainHeightAndMerklePath.BoundParentChainHeight, + TokenContractAddress = SideTokenContractAddress, + TransactionBytes = transaction.ToByteString(), + MerklePath = merklePath + }; + registerCrossChainTokenContractAddressInput.MerklePath.MerklePathNodes.AddRange( + boundParentChainHeightAndMerklePath.MerklePathFromParentChain.MerklePathNodes); + var proposalId = await CreateProposalAsync(SideChain2ParliamentContractStub, + nameof(TokenContractImplContainer.TokenContractImplStub.RegisterCrossChainTokenContractAddress), + registerCrossChainTokenContractAddressInput.ToByteString(), tokenContract); + await ApproveWithMinersAsync(proposalId); + var transactionList = new List(); + foreach (var account in SampleAccount.Accounts.Take(5)) + { + var parliamentContractStub = + SideChain2TestKit.GetTester( + Side2ParliamentAddress, account.KeyPair); + transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); } - private async Task IndexMainChainTransactionOnSideChain2Async(long height, Hash txRoot, Hash blockRoot) - { - var indexParentHeight = await GetParentChainHeight(SideChain2CrossChainContractStub); - var crossChainBlockData = new CrossChainBlockData(); - var index = indexParentHeight >= _parentChainHeightOfCreation - ? indexParentHeight + 1 - : _parentChainHeightOfCreation; - for (var i = index; i < height; i++) - { - crossChainBlockData.ParentChainBlockDataList.Add(CreateParentChainBlockData(i, MainChainId, - txRoot)); - } + await SideChain2TestKit.MineAsync(transactionList); + var releaseTransaction = SideChain2ParliamentContractStub.Release.GetTransaction(proposalId); + return await SideChain2TestKit.ExecuteTransactionWithMiningAsync(releaseTransaction); + } - var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, txRoot); - crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); + private MerklePath GetTransactionMerklePathAndRoot(Transaction transaction, out Hash root) + { + var fakeHash1 = HashHelper.ComputeFrom("fake1"); + var fakeHash2 = HashHelper.ComputeFrom("fake2"); - parentChainBlockData.CrossChainExtraData = new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = blockRoot - }; - - await BootMinerChangeRoundAsync(SideChain2AEDPoSContractStub, false); - var proposingResult = - await SideChain2CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed) - .ProposalId; - - var transactionList = new List(); - foreach (var account in SampleAccount.Accounts.Take(4)) - { - var parliamentContractStub = - SideChain2TestKit.GetTester( - Side2ParliamentAddress, account.KeyPair); - transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); - } - - await SideChain2TestKit.MineAsync(transactionList); - - var releaseResult = - await SideChain2CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput {ChainIdList = {MainChainId}}); - var releasedProposalId = ProposalReleased.Parser - .ParseFrom(releaseResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalReleased))) - .NonIndexed).ProposalId; - releasedProposalId.ShouldBe(proposalId); - - var parentChainHeight = await GetParentChainHeight(SideChain2CrossChainContractStub); - parentChainHeight.ShouldBe(height); - } + var rawBytes = transaction.GetHash().ToByteArray() + .Concat(EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())).ToArray(); + var hash = HashHelper.ComputeFrom(rawBytes); + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] { hash, fakeHash1, fakeHash2 }); + + var merklePath = binaryMerkleTree.GenerateMerklePath(0); + root = binaryMerkleTree.Root; + return merklePath; + } - private async Task DoIndexAsync(CrossChainBlockData crossChainBlockData, long sideTransactionHeight, - int sideChainId) + private async Task IndexMainChainTransactionAsync(long height, Hash txRoot, Hash blockRoot) + { + var indexParentHeight = await GetParentChainHeight(SideChainCrossChainContractStub); + var crossChainBlockData = new CrossChainBlockData(); + var index = indexParentHeight >= _parentChainHeightOfCreation + ? indexParentHeight + 1 + : _parentChainHeightOfCreation; + for (var i = index; i < height; i++) + crossChainBlockData.ParentChainBlockDataList.Add(CreateParentChainBlockData(i, MainChainId, + txRoot)); + + var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, txRoot); + crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); + + parentChainBlockData.CrossChainExtraData = new CrossChainExtraData { - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - // proposing tx - var proposingResult = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + TransactionStatusMerkleTreeRoot = blockRoot + }; + + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var proposingResult = + await SideChainCrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed) + .ProposalId; + await ApproveWithMinersAsync(proposalId, false); + var releaseResult = + await SideChainCrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { ChainIdList = { MainChainId } }); + var releasedProposalId = ProposalReleased.Parser + .ParseFrom(releaseResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalReleased))) + .NonIndexed).ProposalId; + releasedProposalId.ShouldBe(proposalId); + + var parentChainHeight = await GetParentChainHeight(SideChainCrossChainContractStub); + parentChainHeight.ShouldBe(height); + } - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; + private async Task IndexMainChainTransactionOnSideChain2Async(long height, Hash txRoot, Hash blockRoot) + { + var indexParentHeight = await GetParentChainHeight(SideChain2CrossChainContractStub); + var crossChainBlockData = new CrossChainBlockData(); + var index = indexParentHeight >= _parentChainHeightOfCreation + ? indexParentHeight + 1 + : _parentChainHeightOfCreation; + for (var i = index; i < height; i++) + crossChainBlockData.ParentChainBlockDataList.Add(CreateParentChainBlockData(i, MainChainId, + txRoot)); + + var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, txRoot); + crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); + + parentChainBlockData.CrossChainExtraData = new CrossChainExtraData + { + TransactionStatusMerkleTreeRoot = blockRoot + }; + + await BootMinerChangeRoundAsync(SideChain2AEDPoSContractStub, false); + var proposingResult = + await SideChain2CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed) + .ProposalId; + + var transactionList = new List(); + foreach (var account in SampleAccount.Accounts.Take(4)) + { + var parliamentContractStub = + SideChain2TestKit.GetTester( + Side2ParliamentAddress, account.KeyPair); + transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); + } - await ApproveWithMinersAsync(proposalId); - var releaseTx = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - var blockExecutedSet = await MineAsync(new List {releaseTx}); + await SideChain2TestKit.MineAsync(transactionList); - await IndexMainChainBlockAsync(releaseTx, blockExecutedSet.Height, sideTransactionHeight, - crossChainBlockData.SideChainBlockDataList.Select(b => b.TransactionStatusMerkleTreeRoot).ToList()); - } + var releaseResult = + await SideChain2CrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { ChainIdList = { MainChainId } }); + var releasedProposalId = ProposalReleased.Parser + .ParseFrom(releaseResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalReleased))) + .NonIndexed).ProposalId; + releasedProposalId.ShouldBe(proposalId); - private async Task MainAndSideIndexAsync(int sideChainId, long sideTransactionHeight, Hash root) - { - //Main chain index side chain transaction - var crossChainBlockData = new CrossChainBlockData(); - var mainChainIndexSideChain = await GetSideChainHeight(sideChainId); - var height = mainChainIndexSideChain > 1 ? mainChainIndexSideChain + 1 : 1; - for (var i = height; i < sideTransactionHeight; i++) - { - crossChainBlockData.SideChainBlockDataList.Add(CreateSideChainBlockData(_fakeBlockHeader, i, - sideChainId, - root)); - } + var parentChainHeight = await GetParentChainHeight(SideChain2CrossChainContractStub); + parentChainHeight.ShouldBe(height); + } - var sideChainBlockData = CreateSideChainBlockData(_fakeBlockHeader, sideTransactionHeight, sideChainId, - root); - crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); + private async Task DoIndexAsync(CrossChainBlockData crossChainBlockData, long sideTransactionHeight, + int sideChainId) + { + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + // proposing tx + var proposingResult = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - await DoIndexAsync(crossChainBlockData, sideTransactionHeight, sideChainId); - } + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; - private async Task SideIndexSideChainAsync(int sideChainId, long sideTransactionHeight, Hash root) - { - //Main chain index side chain transaction - var crossChainBlockData = new CrossChainBlockData(); - var mainChainIndexSideChain = await GetSideChainHeight(sideChainId); - var height = mainChainIndexSideChain > 1 ? mainChainIndexSideChain + 1 : 1; - for (var i = height; i < sideTransactionHeight; i++) + await ApproveWithMinersAsync(proposalId); + var releaseTx = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( + new ReleaseCrossChainIndexingProposalInput { - crossChainBlockData.SideChainBlockDataList.Add(CreateSideChainBlockData(_fakeBlockHeader, i, - sideChainId, - root)); - } - - var sideChainBlockData = CreateSideChainBlockData(_fakeBlockHeader, sideTransactionHeight, sideChainId, - root); - crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); - - await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - // proposing tx - var executionResult = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalId = ProposalCreated.Parser - .ParseFrom(executionResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - - await ApproveWithMinersAsync(proposalId, true); - var releaseTx = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( - new ReleaseCrossChainIndexingProposalInput - { - ChainIdList = {sideChainId} - }); - var executedSet = await MineAsync(new List {releaseTx}); + ChainIdList = { sideChainId } + }); + var blockExecutedSet = await MineAsync(new List { releaseTx }); - var blockRoot = await IndexMainChainBlockAsync(releaseTx, executedSet.Height, sideTransactionHeight, - crossChainBlockData.SideChainBlockDataList.Select(b => b.TransactionStatusMerkleTreeRoot).ToList()); + await IndexMainChainBlockAsync(releaseTx, blockExecutedSet.Height, sideTransactionHeight, + crossChainBlockData.SideChainBlockDataList.Select(b => b.TransactionStatusMerkleTreeRoot).ToList()); + } - GetTransactionMerklePathAndRoot(releaseTx, out var txRoot); - await IndexMainChainTransactionOnSideChain2Async(executedSet.Height, txRoot, blockRoot); - } + private async Task MainAndSideIndexAsync(int sideChainId, long sideTransactionHeight, Hash root) + { + //Main chain index side chain transaction + var crossChainBlockData = new CrossChainBlockData(); + var mainChainIndexSideChain = await GetSideChainHeight(sideChainId); + var height = mainChainIndexSideChain > 1 ? mainChainIndexSideChain + 1 : 1; + for (var i = height; i < sideTransactionHeight; i++) + crossChainBlockData.SideChainBlockDataList.Add(CreateSideChainBlockData(_fakeBlockHeader, i, + sideChainId, + root)); + + var sideChainBlockData = CreateSideChainBlockData(_fakeBlockHeader, sideTransactionHeight, sideChainId, + root); + crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); + + await DoIndexAsync(crossChainBlockData, sideTransactionHeight, sideChainId); + } - private async Task IndexMainChainBlockAsync(Transaction transaction, long height, long sideHeight, - List indexedSideChainBlockRoots) - { - var fakeHash1 = HashHelper.ComputeFrom("fake1"); - var fakeHash2 = HashHelper.ComputeFrom("fake2"); - - var rawBytes = transaction.GetHash().ToByteArray() - .Concat(EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())).ToArray(); - var hash = HashHelper.ComputeFrom(rawBytes); - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] {hash, fakeHash1, fakeHash2}); - var merkleTreeRootHash = binaryMerkleTree.Root; - - var indexParentHeight = await GetParentChainHeight(SideChainCrossChainContractStub); - var nextHeightToBeIndexed = indexParentHeight >= _parentChainHeightOfCreation - ? indexParentHeight + 1 - : _parentChainHeightOfCreation; - var crossChainBlockData = new CrossChainBlockData(); - for (long i = nextHeightToBeIndexed; i < height; i++) + private async Task SideIndexSideChainAsync(int sideChainId, long sideTransactionHeight, Hash root) + { + //Main chain index side chain transaction + var crossChainBlockData = new CrossChainBlockData(); + var mainChainIndexSideChain = await GetSideChainHeight(sideChainId); + var height = mainChainIndexSideChain > 1 ? mainChainIndexSideChain + 1 : 1; + for (var i = height; i < sideTransactionHeight; i++) + crossChainBlockData.SideChainBlockDataList.Add(CreateSideChainBlockData(_fakeBlockHeader, i, + sideChainId, + root)); + + var sideChainBlockData = CreateSideChainBlockData(_fakeBlockHeader, sideTransactionHeight, sideChainId, + root); + crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); + + await BootMinerChangeRoundAsync(AEDPoSContractStub, true); + // proposing tx + var executionResult = await CrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalId = ProposalCreated.Parser + .ParseFrom(executionResult.TransactionResult.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + + await ApproveWithMinersAsync(proposalId); + var releaseTx = CrossChainContractStub.ReleaseCrossChainIndexingProposal.GetTransaction( + new ReleaseCrossChainIndexingProposalInput { - crossChainBlockData.ParentChainBlockDataList.Add( - CreateParentChainBlockData(i, MainChainId, HashHelper.ConcatAndCompute(fakeHash1, fakeHash2))); - } + ChainIdList = { sideChainId } + }); + var executedSet = await MineAsync(new List { releaseTx }); - var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, - merkleTreeRootHash); - var generatedMerkleTree = BinaryMerkleTree.FromLeafNodes(indexedSideChainBlockRoots); + var blockRoot = await IndexMainChainBlockAsync(releaseTx, executedSet.Height, sideTransactionHeight, + crossChainBlockData.SideChainBlockDataList.Select(b => b.TransactionStatusMerkleTreeRoot).ToList()); - parentChainBlockData.CrossChainExtraData = new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = generatedMerkleTree.Root - }; - parentChainBlockData.IndexedMerklePath.Add(sideHeight, - generatedMerkleTree.GenerateMerklePath(indexedSideChainBlockRoots.Count - 1)); - crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); - - await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); - var proposingExecutionResult = - await SideChainCrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); - var proposalId = ProposalCreated.Parser - .ParseFrom(proposingExecutionResult.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - await ApproveWithMinersAsync(proposalId, false); - var releaseExecutionResult = - await SideChainCrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( - new ReleaseCrossChainIndexingProposalInput {ChainIdList = {MainChainId}}); - var releasedProposalId = ProposalReleased.Parser - .ParseFrom(releaseExecutionResult.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed).ProposalId; - releasedProposalId.ShouldBe(proposalId); - - return generatedMerkleTree.Root; - } + GetTransactionMerklePathAndRoot(releaseTx, out var txRoot); + await IndexMainChainTransactionOnSideChain2Async(executedSet.Height, txRoot, blockRoot); + } - private ParentChainBlockData CreateParentChainBlockData(long height, int mainChainId, Hash txMerkleTreeRoot) + private async Task IndexMainChainBlockAsync(Transaction transaction, long height, long sideHeight, + List indexedSideChainBlockRoots) + { + var fakeHash1 = HashHelper.ComputeFrom("fake1"); + var fakeHash2 = HashHelper.ComputeFrom("fake2"); + + var rawBytes = transaction.GetHash().ToByteArray() + .Concat(EncodingHelper.EncodeUtf8(TransactionResultStatus.Mined.ToString())).ToArray(); + var hash = HashHelper.ComputeFrom(rawBytes); + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(new[] { hash, fakeHash1, fakeHash2 }); + var merkleTreeRootHash = binaryMerkleTree.Root; + + var indexParentHeight = await GetParentChainHeight(SideChainCrossChainContractStub); + var nextHeightToBeIndexed = indexParentHeight >= _parentChainHeightOfCreation + ? indexParentHeight + 1 + : _parentChainHeightOfCreation; + var crossChainBlockData = new CrossChainBlockData(); + for (var i = nextHeightToBeIndexed; i < height; i++) + crossChainBlockData.ParentChainBlockDataList.Add( + CreateParentChainBlockData(i, MainChainId, HashHelper.ConcatAndCompute(fakeHash1, fakeHash2))); + + var parentChainBlockData = CreateParentChainBlockData(height, MainChainId, + merkleTreeRootHash); + var generatedMerkleTree = BinaryMerkleTree.FromLeafNodes(indexedSideChainBlockRoots); + + parentChainBlockData.CrossChainExtraData = new CrossChainExtraData { - return new ParentChainBlockData - { - ChainId = mainChainId, - Height = height, - TransactionStatusMerkleTreeRoot = txMerkleTreeRoot - }; - } + TransactionStatusMerkleTreeRoot = generatedMerkleTree.Root + }; + parentChainBlockData.IndexedMerklePath.Add(sideHeight, + generatedMerkleTree.GenerateMerklePath(indexedSideChainBlockRoots.Count - 1)); + crossChainBlockData.ParentChainBlockDataList.Add(parentChainBlockData); + + await BootMinerChangeRoundAsync(SideChainAEDPoSContractStub, false); + var proposingExecutionResult = + await SideChainCrossChainContractStub.ProposeCrossChainIndexing.SendAsync(crossChainBlockData); + var proposalId = ProposalCreated.Parser + .ParseFrom(proposingExecutionResult.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + await ApproveWithMinersAsync(proposalId, false); + var releaseExecutionResult = + await SideChainCrossChainContractStub.ReleaseCrossChainIndexingProposal.SendAsync( + new ReleaseCrossChainIndexingProposalInput { ChainIdList = { MainChainId } }); + var releasedProposalId = ProposalReleased.Parser + .ParseFrom(releaseExecutionResult.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed).ProposalId; + releasedProposalId.ShouldBe(proposalId); + + return generatedMerkleTree.Root; + } - private SideChainBlockData CreateSideChainBlockData(Hash blockHash, long height, int sideChainId, - Hash txMerkleTreeRoot) + private ParentChainBlockData CreateParentChainBlockData(long height, int mainChainId, Hash txMerkleTreeRoot) + { + return new ParentChainBlockData { - return new SideChainBlockData - { - BlockHeaderHash = blockHash, - Height = height, - ChainId = sideChainId, - TransactionStatusMerkleTreeRoot = txMerkleTreeRoot - }; - } + ChainId = mainChainId, + Height = height, + TransactionStatusMerkleTreeRoot = txMerkleTreeRoot + }; + } - #endregion + private SideChainBlockData CreateSideChainBlockData(Hash blockHash, long height, int sideChainId, + Hash txMerkleTreeRoot) + { + return new SideChainBlockData + { + BlockHeaderHash = blockHash, + Height = height, + ChainId = sideChainId, + TransactionStatusMerkleTreeRoot = txMerkleTreeRoot + }; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestAElfModule.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestAElfModule.cs index 86017cccc3..d4f25b1a63 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestAElfModule.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestAElfModule.cs @@ -18,107 +18,106 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(CrossChainCoreModule), + typeof(GovernmentSystemAElfModule), + typeof(EconomicSystemAElfModule))] +public class MultiTokenContractCrossChainTestAElfModule : AbpModule { - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(CrossChainCoreModule), - typeof(GovernmentSystemAElfModule), - typeof(EconomicSystemAElfModule))] - public class MultiTokenContractCrossChainTestAElfModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = - SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); - }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - var instance = new TestTokenBalanceTransactionGenerator(); - context.Services.AddSingleton(instance); - context.Services.AddSingleton(instance); - context.Services.AddSingleton(); - context.Services.RemoveAll(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(TokenContractInitializationProvider)); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(SideChainUnitTestTokenContractInitializationProvider)); - context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusTransactionGenerator)); + options.MiningInterval = 4000; + options.InitialMinerList = + SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); + }); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + var instance = new TestTokenBalanceTransactionGenerator(); + context.Services.AddSingleton(instance); + context.Services.AddSingleton(instance); + context.Services.AddSingleton(); + context.Services.RemoveAll(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(TokenContractInitializationProvider)); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(SideChainUnitTestTokenContractInitializationProvider)); + context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusTransactionGenerator)); - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC,"; - options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; - }); - } - - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + Configure(options => { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC,"; + options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; + }); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } +} - [DependsOn(typeof(ContractTestModule),typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(CrossChainCoreModule), - typeof(GovernmentSystemAElfModule))] - public class MultiTokenContractSideChainTestAElfModule : AbpModule +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(CrossChainCoreModule), + typeof(GovernmentSystemAElfModule))] +public class MultiTokenContractSideChainTestAElfModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + //Configure(options => options.ChainId = SideChainInitializationDataProvider.ChainId); + Configure(options => { - //Configure(options => options.ChainId = SideChainInitializationDataProvider.ChainId); - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = - SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); - }); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - var instance = new TestTokenBalanceTransactionGenerator(); - context.Services.AddSingleton(instance); - context.Services.AddSingleton(instance); - context.Services.RemoveAll(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.AddTransient(); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(UnitTestTokenContractInitializationProvider)); - context.Services.RemoveAll(s => - s.ImplementationType == typeof(TokenContractInitializationProvider)); - context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusTransactionGenerator)); + options.MiningInterval = 4000; + options.InitialMinerList = + SampleAccount.Accounts.Take(5).Select(a => a.KeyPair.PublicKey.ToHex()).ToList(); + }); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + var instance = new TestTokenBalanceTransactionGenerator(); + context.Services.AddSingleton(instance); + context.Services.AddSingleton(instance); + context.Services.RemoveAll(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.AddTransient(); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(UnitTestTokenContractInitializationProvider)); + context.Services.RemoveAll(s => + s.ImplementationType == typeof(TokenContractInitializationProvider)); + context.Services.RemoveAll(s => s.ImplementationType == typeof(ConsensusTransactionGenerator)); - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC,"; - options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; - }); - } - - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + Configure(options => { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,READ,STORAGE,TRAFFIC,"; + options.ContextVariables["SymbolListToPayRental"] = "CPU,RAM,DISK,NET"; + }); + } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index 711ab75195..ca4e882201 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -1,372 +1,375 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS3; -using AElf.Standards.ACS7; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.CrossChain; using AElf.Contracts.Genesis; using AElf.Contracts.Parliament; using AElf.Contracts.Referendum; -using AElf.CrossChain; -using AElf.Kernel; -using AElf.Kernel.Token; -using AElf.Types; using AElf.ContractTestBase.ContractTestKit; +using AElf.CrossChain; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract; +using AElf.Kernel.Token; +using AElf.Standards.ACS3; +using AElf.Standards.ACS7; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using InitializeInput = AElf.Contracts.CrossChain.InitializeInput; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class MultiTokenContractCrossChainTestBase : ContractTestBase { - public class MultiTokenContractCrossChainTestBase : ContractTestBase - { - internal CrossChainContractImplContainer.CrossChainContractImplStub CrossChainContractStub; + protected readonly List ResourceTokenSymbolList; - internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub; + internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub; + protected long BalanceOfStarter; - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub; + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub; + internal CrossChainContractImplContainer.CrossChainContractImplStub CrossChainContractStub; - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; - - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; + protected int MainChainId; - internal ReferendumContractImplContainer.ReferendumContractImplStub ReferendumContractStub; + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; - protected Address SideBasicContractZeroAddress; - internal BasicContractZeroImplContainer.BasicContractZeroImplStub SideChainBasicContractZeroStub; + internal ReferendumContractImplContainer.ReferendumContractImplStub ReferendumContractStub; - protected Address SideCrossChainContractAddress; - internal CrossChainContractImplContainer.CrossChainContractImplStub SideChainCrossChainContractStub; + protected Address Side2BasicContractZeroAddress; + protected Address Side2ConsensusAddress; + protected Address Side2CrossChainContractAddress; + protected Address Side2ParliamentAddress; + protected Address Side2TokenContractAddress; - protected Address SideTokenContractAddress; - internal TokenContractImplContainer.TokenContractImplStub SideChainTokenContractStub; + protected Address SideBasicContractZeroAddress; + internal AEDPoSContractContainer.AEDPoSContractStub SideChain2AEDPoSContractStub; + internal CrossChainContractImplContainer.CrossChainContractImplStub SideChain2CrossChainContractStub; + internal ParliamentContractImplContainer.ParliamentContractImplStub SideChain2ParliamentContractStub; + protected ContractTestKit SideChain2TestKit; + internal TokenContractImplContainer.TokenContractImplStub SideChain2TokenContractStub; + internal AEDPoSContractContainer.AEDPoSContractStub SideChainAEDPoSContractStub; + internal BasicContractZeroImplContainer.BasicContractZeroImplStub SideChainBasicContractZeroStub; + internal CrossChainContractImplContainer.CrossChainContractImplStub SideChainCrossChainContractStub; + internal ParliamentContractImplContainer.ParliamentContractImplStub SideChainParliamentContractStub; - protected Address SideParliamentAddress; - internal ParliamentContractImplContainer.ParliamentContractImplStub SideChainParliamentContractStub; + protected ContractTestKit SideChainTestKit; + internal TokenContractImplContainer.TokenContractImplStub SideChainTokenContractStub; - protected Address SideConsensusAddress; - internal AEDPoSContractContainer.AEDPoSContractStub SideChainAEDPoSContractStub; + protected Address SideConsensusAddress; - protected Address Side2BasicContractZeroAddress; - protected Address Side2CrossChainContractAddress; - internal CrossChainContractImplContainer.CrossChainContractImplStub SideChain2CrossChainContractStub; - protected Address Side2TokenContractAddress; - internal TokenContractImplContainer.TokenContractImplStub SideChain2TokenContractStub; - protected Address Side2ParliamentAddress; - internal ParliamentContractImplContainer.ParliamentContractImplStub SideChain2ParliamentContractStub; - protected Address Side2ConsensusAddress; - internal AEDPoSContractContainer.AEDPoSContractStub SideChain2AEDPoSContractStub; + protected Address SideCrossChainContractAddress; - protected long TotalSupply; - protected long BalanceOfStarter; - protected Timestamp BlockchainStartTimestamp => TimestampHelper.GetUtcNow(); + protected Address SideParliamentAddress; - protected ContractTestKit SideChainTestKit; - protected ContractTestKit SideChain2TestKit; + protected Address SideTokenContractAddress; - protected readonly List ResourceTokenSymbolList; + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; - protected int MainChainId; + protected long TotalSupply; - public MultiTokenContractCrossChainTestBase() - { - MainChainId = Application.ServiceProvider.GetRequiredService>().Value - .ChainId; - BasicContractZeroStub = - GetTester(BasicContractZeroAddress, - DefaultAccount.KeyPair); + public MultiTokenContractCrossChainTestBase() + { + MainChainId = Application.ServiceProvider.GetRequiredService>().Value + .ChainId; + BasicContractZeroStub = + GetTester(BasicContractZeroAddress, + DefaultAccount.KeyPair); - CrossChainContractStub = - GetTester(CrossChainContractAddress, - DefaultAccount.KeyPair); + CrossChainContractStub = + GetTester(CrossChainContractAddress, + DefaultAccount.KeyPair); - TokenContractStub = - GetTester(TokenContractAddress, - DefaultAccount.KeyPair); + TokenContractStub = + GetTester(TokenContractAddress, + DefaultAccount.KeyPair); - ParliamentContractStub = - GetTester(ParliamentContractAddress, - DefaultAccount.KeyPair); + ParliamentContractStub = + GetTester(ParliamentContractAddress, + DefaultAccount.KeyPair); - AEDPoSContractStub = GetTester(ConsensusContractAddress); + AEDPoSContractStub = GetTester(ConsensusContractAddress); - ReferendumContractStub = - GetTester(ReferendumContractAddress, - DefaultAccount.KeyPair); + ReferendumContractStub = + GetTester(ReferendumContractAddress, + DefaultAccount.KeyPair); - ResourceTokenSymbolList = Application.ServiceProvider - .GetRequiredService>() - .Value.ContextVariables["SymbolListToPayRental"].Split(",").ToList(); - } + ResourceTokenSymbolList = Application.ServiceProvider + .GetRequiredService>() + .Value.ContextVariables["SymbolListToPayRental"].Split(",").ToList(); + } - protected void StartSideChain(int chainId, long height, string symbol, - bool registerParentChainTokenContractAddress) - { - SideChainTestKit = CreateContractTestKit( - new ChainInitializationDto - { - ChainId = chainId, - Symbol = symbol, - ParentChainTokenContractAddress = TokenContractAddress, - ParentChainId = MainChainId, - CreationHeightOnParentChain = height, - RegisterParentChainTokenContractAddress = registerParentChainTokenContractAddress - }); - SideBasicContractZeroAddress = SideChainTestKit.ContractZeroAddress; - SideChainBasicContractZeroStub = - SideChainTestKit.GetTester( - SideBasicContractZeroAddress); - - SideCrossChainContractAddress = - SideChainTestKit.SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; - SideChainCrossChainContractStub = - SideChainTestKit.GetTester( - SideCrossChainContractAddress); - - SideTokenContractAddress = - SideChainTestKit.SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; - SideChainTokenContractStub = - SideChainTestKit.GetTester(SideTokenContractAddress); - SideParliamentAddress = - SideChainTestKit.SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; - SideChainParliamentContractStub = - SideChainTestKit.GetTester(SideParliamentAddress); - - SideConsensusAddress = - SideChainTestKit.SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; - SideChainAEDPoSContractStub = - SideChainTestKit.GetTester(SideConsensusAddress); - } + protected Timestamp BlockchainStartTimestamp => TimestampHelper.GetUtcNow(); + protected void StartSideChain(int chainId, long height, string symbol, + bool registerParentChainTokenContractAddress) + { + SideChainTestKit = CreateContractTestKit( + new ChainInitializationDto + { + ChainId = chainId, + Symbol = symbol, + ParentChainTokenContractAddress = TokenContractAddress, + ParentChainId = MainChainId, + CreationHeightOnParentChain = height, + RegisterParentChainTokenContractAddress = registerParentChainTokenContractAddress + }); + SideBasicContractZeroAddress = SideChainTestKit.ContractZeroAddress; + SideChainBasicContractZeroStub = + SideChainTestKit.GetTester( + SideBasicContractZeroAddress); + + SideCrossChainContractAddress = + SideChainTestKit.SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; + SideChainCrossChainContractStub = + SideChainTestKit.GetTester( + SideCrossChainContractAddress); + + SideTokenContractAddress = + SideChainTestKit.SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; + SideChainTokenContractStub = + SideChainTestKit.GetTester(SideTokenContractAddress); + SideParliamentAddress = + SideChainTestKit.SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; + SideChainParliamentContractStub = + SideChainTestKit.GetTester( + SideParliamentAddress); + + SideConsensusAddress = + SideChainTestKit.SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; + SideChainAEDPoSContractStub = + SideChainTestKit.GetTester(SideConsensusAddress); + } - protected void StartSideChain2(int chainId, long height, string symbol) - { - SideChain2TestKit = CreateContractTestKit( - new ChainInitializationDto - { - ChainId = chainId, - Symbol = symbol, - ParentChainTokenContractAddress = TokenContractAddress, - ParentChainId = MainChainId, - CreationHeightOnParentChain = height - }); - Side2BasicContractZeroAddress = SideChain2TestKit.ContractZeroAddress; - Side2CrossChainContractAddress = - SideChain2TestKit.SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; - SideChain2CrossChainContractStub = - SideChain2TestKit.GetTester( - Side2CrossChainContractAddress); - Side2TokenContractAddress = - SideChain2TestKit.SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; - SideChain2TokenContractStub = SideChain2TestKit - .GetTester(Side2TokenContractAddress); - Side2ParliamentAddress = - SideChain2TestKit.SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; - SideChain2ParliamentContractStub = - SideChain2TestKit.GetTester(Side2ParliamentAddress); - Side2ConsensusAddress = - SideChain2TestKit.SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; - SideChain2AEDPoSContractStub = - SideChain2TestKit.GetTester(Side2ConsensusAddress); - } - protected async Task InitAndCreateSideChainAsync(string symbol, long parentChainHeightOfCreation = 0, - int parentChainId = 0, long lockedTokenAmount = 10) - { - await ApproveBalanceAsync(lockedTokenAmount); - var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount, symbol); - await ApproveWithMinersAsync(proposalId); - - var releaseResult = await CrossChainContractStub.ReleaseSideChainCreation.SendAsync( - new ReleaseSideChainCreationInput - {ProposalId = proposalId}); - var sideChainCreatedEvent = SideChainCreatedEvent.Parser - .ParseFrom(releaseResult.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) - .NonIndexed); - var chainId = sideChainCreatedEvent.ChainId; - - return chainId; - } + protected void StartSideChain2(int chainId, long height, string symbol) + { + SideChain2TestKit = CreateContractTestKit( + new ChainInitializationDto + { + ChainId = chainId, + Symbol = symbol, + ParentChainTokenContractAddress = TokenContractAddress, + ParentChainId = MainChainId, + CreationHeightOnParentChain = height + }); + Side2BasicContractZeroAddress = SideChain2TestKit.ContractZeroAddress; + Side2CrossChainContractAddress = + SideChain2TestKit.SystemContractAddresses[CrossChainSmartContractAddressNameProvider.Name]; + SideChain2CrossChainContractStub = + SideChain2TestKit.GetTester( + Side2CrossChainContractAddress); + Side2TokenContractAddress = + SideChain2TestKit.SystemContractAddresses[TokenSmartContractAddressNameProvider.Name]; + SideChain2TokenContractStub = SideChain2TestKit + .GetTester(Side2TokenContractAddress); + Side2ParliamentAddress = + SideChain2TestKit.SystemContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; + SideChain2ParliamentContractStub = + SideChain2TestKit.GetTester( + Side2ParliamentAddress); + Side2ConsensusAddress = + SideChain2TestKit.SystemContractAddresses[ConsensusSmartContractAddressNameProvider.Name]; + SideChain2AEDPoSContractStub = + SideChain2TestKit.GetTester(Side2ConsensusAddress); + } - internal async Task GetBoundParentChainHeightAndMerklePathByHeight(long height) - { - return await SideChainCrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallAsync( - new Int64Value - { - Value = height - }); - } + protected async Task InitAndCreateSideChainAsync(string symbol, long parentChainHeightOfCreation = 0, + int parentChainId = 0, long lockedTokenAmount = 10) + { + await ApproveBalanceAsync(lockedTokenAmount); + var proposalId = await CreateSideChainProposalAsync(1, lockedTokenAmount, symbol); + await ApproveWithMinersAsync(proposalId); + + var releaseResult = await CrossChainContractStub.ReleaseSideChainCreation.SendAsync( + new ReleaseSideChainCreationInput + { ProposalId = proposalId }); + var sideChainCreatedEvent = SideChainCreatedEvent.Parser + .ParseFrom(releaseResult.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(SideChainCreatedEvent))) + .NonIndexed); + var chainId = sideChainCreatedEvent.ChainId; + + return chainId; + } - internal async Task GetSideChainHeight(int chainId) - { - return (await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value + internal async Task GetBoundParentChainHeightAndMerklePathByHeight(long height) + { + return await SideChainCrossChainContractStub.GetBoundParentChainHeightAndMerklePathByHeight.CallAsync( + new Int64Value { - Value = chainId - })).Value; - ; - } + Value = height + }); + } - internal async Task GetParentChainHeight( - CrossChainContractImplContainer.CrossChainContractImplStub crossChainContractStub) + internal async Task GetSideChainHeight(int chainId) + { + return (await CrossChainContractStub.GetSideChainHeight.CallAsync(new Int32Value { - return (await crossChainContractStub.GetParentChainHeight.CallAsync(new Empty())).Value; - } + Value = chainId + })).Value; + ; + } + + internal async Task GetParentChainHeight( + CrossChainContractImplContainer.CrossChainContractImplStub crossChainContractStub) + { + return (await crossChainContractStub.GetParentChainHeight.CallAsync(new Empty())).Value; + } - private SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, - string symbol, params SideChainTokenInitialIssue[] sideChainTokenInitialIssueList) + private SideChainCreationRequest CreateSideChainCreationRequest(long indexingPrice, long lockedTokenAmount, + string symbol, params SideChainTokenInitialIssue[] sideChainTokenInitialIssueList) + { + var res = new SideChainCreationRequest { - var res = new SideChainCreationRequest + IndexingPrice = indexingPrice, + LockedTokenAmount = lockedTokenAmount, + SideChainTokenCreationRequest = new SideChainTokenCreationRequest { - IndexingPrice = indexingPrice, - LockedTokenAmount = lockedTokenAmount, - SideChainTokenCreationRequest = new SideChainTokenCreationRequest{ - SideChainTokenDecimals = 2, - SideChainTokenTotalSupply = 1_000_000_000, - SideChainTokenSymbol = symbol, - SideChainTokenName = "TEST" - }, - SideChainTokenInitialIssueList = {sideChainTokenInitialIssueList}, - InitialResourceAmount = {ResourceTokenSymbolList.ToDictionary(resource => resource, resource => 1)} - }; - return res; - } + SideChainTokenDecimals = 2, + SideChainTokenTotalSupply = 1_000_000_000, + SideChainTokenSymbol = symbol, + SideChainTokenName = "TEST" + }, + SideChainTokenInitialIssueList = { sideChainTokenInitialIssueList }, + InitialResourceAmount = { ResourceTokenSymbolList.ToDictionary(resource => resource, resource => 1) } + }; + return res; + } - private async Task CreateSideChainProposalAsync(long indexingPrice, long lockedTokenAmount, string symbol) - { - var createProposalInput = CreateSideChainCreationRequest(indexingPrice, lockedTokenAmount, symbol, - new SideChainTokenInitialIssue - { - Address = DefaultAccount.Address, - Amount = 100 - }); - var requestSideChainCreationResult = - await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - - var proposalId = ProposalCreated.Parser.ParseFrom(requestSideChainCreationResult.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; - return proposalId; - } + private async Task CreateSideChainProposalAsync(long indexingPrice, long lockedTokenAmount, string symbol) + { + var createProposalInput = CreateSideChainCreationRequest(indexingPrice, lockedTokenAmount, symbol, + new SideChainTokenInitialIssue + { + Address = DefaultAccount.Address, + Amount = 100 + }); + var requestSideChainCreationResult = + await CrossChainContractStub.RequestSideChainCreation.SendAsync(createProposalInput); - protected async Task ApproveWithMinersAsync(Hash proposalId, bool isMainChain = true) - { - var transactionList = new List(); + var proposalId = ProposalCreated.Parser.ParseFrom(requestSideChainCreationResult.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed).ProposalId; + return proposalId; + } - if (isMainChain) + protected async Task ApproveWithMinersAsync(Hash proposalId, bool isMainChain = true) + { + var transactionList = new List(); + + if (isMainChain) + { + foreach (var account in SampleAccount.Accounts.Take(5)) { - foreach (var account in SampleAccount.Accounts.Take(5)) - { - var parliamentContractStub = - GetTester(ParliamentContractAddress, - account.KeyPair); - transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); - } - - await MineAsync(transactionList); + var parliamentContractStub = + GetTester(ParliamentContractAddress, + account.KeyPair); + transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); } - else + + await MineAsync(transactionList); + } + else + { + foreach (var account in SampleAccount.Accounts.Take(5)) { - foreach (var account in SampleAccount.Accounts.Take(5)) - { - var parliamentContractStub = - SideChainTestKit.GetTester( - SideParliamentAddress, account.KeyPair); - transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); - } - - await SideChainTestKit.MineAsync(transactionList); + var parliamentContractStub = + SideChainTestKit.GetTester( + SideParliamentAddress, account.KeyPair); + transactionList.Add(parliamentContractStub.Approve.GetTransaction(proposalId)); } + + await SideChainTestKit.MineAsync(transactionList); } + } - protected async Task ReleaseProposalAsync(Hash proposalId) + protected async Task ReleaseProposalAsync(Hash proposalId) + { + var transaction = ParliamentContractStub.Release.GetTransaction(proposalId); + return await ExecuteTransactionWithMiningAsync(transaction); + ; + } + + internal async Task CreateProposalAsync( + ParliamentContractImplContainer.ParliamentContractImplStub parliamentContractStub, string method, + ByteString input, Address contractAddress) + { + var organizationAddress = await parliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalResult = await parliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - var transaction = ParliamentContractStub.Release.GetTransaction(proposalId); - return await ExecuteTransactionWithMiningAsync(transaction); - ; - } + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = input, + ToAddress = contractAddress, + OrganizationAddress = organizationAddress + }); + var proposalId = proposalResult.Output; + return proposalId; + } - internal async Task CreateProposalAsync( - ParliamentContractImplContainer.ParliamentContractImplStub parliamentContractStub, string method, - ByteString input, Address contractAddress) + internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSContractStub aedPoSContractStub, + bool isMainChain, long nextRoundNumber = 2) + { + if (isMainChain) { - var organizationAddress = await parliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalResult = await parliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = method, - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = input, - ToAddress = contractAddress, - OrganizationAddress = organizationAddress - }); - var proposalId = proposalResult.Output; - return proposalId; + var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var expectedStartTime = TimestampHelper.GetUtcNow(); + currentRound.GenerateNextRoundInformation(expectedStartTime, BlockchainStartTimestamp, + out var nextRound); + nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] + .ExpectedMiningTime = expectedStartTime; + await aedPoSContractStub.NextRound.SendAsync(nextRound); } - internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSContractStub aedPoSContractStub, - bool isMainChain, long nextRoundNumber = 2) + if (!isMainChain) { - if (isMainChain) + var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); + var expectedStartTime = BlockchainStartTimestamp.ToDateTime() + .AddMilliseconds( + ((long)currentRound.TotalMilliseconds(4000)).Mul( + nextRoundNumber.Sub(1))); + currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, + out var nextRound); + + if (currentRound.RoundNumber >= 3) { - var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var expectedStartTime = TimestampHelper.GetUtcNow(); - currentRound.GenerateNextRoundInformation(expectedStartTime, BlockchainStartTimestamp, - out var nextRound); nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] - .ExpectedMiningTime = expectedStartTime; + .ExpectedMiningTime -= new Duration { Seconds = 2400 }; await aedPoSContractStub.NextRound.SendAsync(nextRound); } - - if (!isMainChain) + else { - var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - var expectedStartTime = BlockchainStartTimestamp.ToDateTime() - .AddMilliseconds( - ((long) currentRound.TotalMilliseconds(4000)).Mul( - nextRoundNumber.Sub(1))); - currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, - out var nextRound); - - if (currentRound.RoundNumber >= 3) - { - nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] - .ExpectedMiningTime -= new Duration {Seconds = 2400}; - await aedPoSContractStub.NextRound.SendAsync(nextRound); - } - else - { - nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] - .ExpectedMiningTime -= new Duration {Seconds = (currentRound.RoundNumber) * 20}; - - await aedPoSContractStub.NextRound.SendAsync(nextRound); - } + nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] + .ExpectedMiningTime -= new Duration { Seconds = currentRound.RoundNumber * 20 }; + + await aedPoSContractStub.NextRound.SendAsync(nextRound); } } + } - private async Task ApproveBalanceAsync(long amount) + private async Task ApproveBalanceAsync(long amount) + { + await TokenContractStub.Approve.SendAsync(new ApproveInput { - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Spender = CrossChainContractAddress, - Symbol = "ELF", - Amount = amount - }); - } + Spender = CrossChainContractAddress, + Symbol = "ELF", + Amount = amount + }); + } - private async Task InitializeCrossChainContractAsync(long parentChainHeightOfCreation = 0, - int parentChainId = 0) + private async Task InitializeCrossChainContractAsync(long parentChainHeightOfCreation = 0, + int parentChainId = 0) + { + await CrossChainContractStub.Initialize.SendAsync(new InitializeInput { - await CrossChainContractStub.Initialize.SendAsync(new CrossChain.InitializeInput - { - ParentChainId = parentChainId == 0 ? ChainHelper.ConvertBase58ToChainId("AELF") : parentChainId, - CreationHeightOnParentChain = parentChainHeightOfCreation - }); - } + ParentChainId = parentChainId == 0 ? ChainHelper.ConvertBase58ToChainId("AELF") : parentChainId, + CreationHeightOnParentChain = parentChainHeightOfCreation + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs index 836b673c74..4db7135097 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs @@ -1,15 +1,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Association; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; -using AElf.Contracts.Referendum; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -18,995 +16,994 @@ using Xunit; using CreateOrganizationInput = AElf.Contracts.Parliament.CreateOrganizationInput; -namespace AElf.Contracts.MultiTokenCrossSideChain +namespace AElf.Contracts.MultiTokenCrossSideChain; + +public class MultiTokenContractReferenceFeeTest : MultiTokenContractCrossChainTestBase { - public class MultiTokenContractReferenceFeeTest : MultiTokenContractCrossChainTestBase + public MultiTokenContractReferenceFeeTest() { - public MultiTokenContractReferenceFeeTest() - { - AsyncHelper.RunSync(InitializeTokenContractAsync); - } + AsyncHelper.RunSync(InitializeTokenContractAsync); + } - private async Task InitializeTokenContractAsync() - { - await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); - } - - [Fact] - public async Task GetDefaultUserFeeController_Test() - { - var defaultParliament = await GetDefaultParliamentAddressAsync(); - var userFeeController = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); - userFeeController.RootController.ContractAddress.ShouldNotBeNull(); - userFeeController.ParliamentController.OwnerAddress.ShouldBe(defaultParliament); - userFeeController.ParliamentController.ContractAddress.ShouldBe(ParliamentContractAddress); - } - - [Fact] - public async Task GetDefaultDeveloperFeeController_Test() - { - var defaultParliament = await GetDefaultParliamentAddressAsync(); - var developerFeeController = await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); - developerFeeController.RootController.ContractAddress.ShouldNotBeNull(); - developerFeeController.ParliamentController.OwnerAddress.ShouldBe(defaultParliament); - developerFeeController.ParliamentController.ContractAddress.ShouldBe(ParliamentContractAddress); - } - - [Fact] - public async Task GetSymbolsToPayTXSizeFeeController_Test() - { - var defaultParliament = await GetDefaultParliamentAddressAsync(); - var controller = await TokenContractStub.GetSymbolsToPayTXSizeFeeController.CallAsync(new Empty()); - controller.OwnerAddress.ShouldBe(defaultParliament); - controller.ContractAddress.ShouldBe(ParliamentContractAddress); - } + private async Task InitializeTokenContractAsync() + { + await TokenContractStub.InitializeAuthorizedController.SendAsync(new Empty()); + } - [Fact] - public async Task ChangeSymbolsToPayTXSizeFeeController_Fail_Test() - { - // no authority - var newAuthority = await CreateNewParliamentAddressAsync(); - var updateWithOutAuthorityRet = - await TokenContractStub.ChangeSymbolsToPayTXSizeFeeController.SendWithExceptionAsync(newAuthority); - updateWithOutAuthorityRet.TransactionResult.Error.ShouldContain("no permission"); + [Fact] + public async Task GetDefaultUserFeeController_Test() + { + var defaultParliament = await GetDefaultParliamentAddressAsync(); + var userFeeController = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); + userFeeController.RootController.ContractAddress.ShouldNotBeNull(); + userFeeController.ParliamentController.OwnerAddress.ShouldBe(defaultParliament); + userFeeController.ParliamentController.ContractAddress.ShouldBe(ParliamentContractAddress); + } - //invalid new organization - var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); - var invalidAuthority = new AuthorityInfo - { - OwnerAddress = newAuthority.OwnerAddress, - ContractAddress = AssociationContractAddress - }; - var createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = invalidAuthority.ToByteString(), - OrganizationAddress = defaultParliamentAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub - .ChangeSymbolsToPayTXSizeFeeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - ret.Error.ShouldContain("new controller does not exist"); - } + [Fact] + public async Task GetDefaultDeveloperFeeController_Test() + { + var defaultParliament = await GetDefaultParliamentAddressAsync(); + var developerFeeController = await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); + developerFeeController.RootController.ContractAddress.ShouldNotBeNull(); + developerFeeController.ParliamentController.OwnerAddress.ShouldBe(defaultParliament); + developerFeeController.ParliamentController.ContractAddress.ShouldBe(ParliamentContractAddress); + } - [Fact] - public async Task ChangeSymbolsToPayTXSizeFeeController_Success_Test() - { - var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); - var newSymbolList = new SymbolListToPayTxSizeFee(); - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = primaryToken.Value, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }); - - // create a new organization to be replace the controller of SetSymbolsToPayTxSizeFee - var newAuthority = await CreateNewParliamentAddressAsync(); - - // get the default parliament that is the controller of SetSymbolsToPayTxSizeFee - var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); - - // create a proposal to replace the controller - var createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newAuthority.ToByteString(), - OrganizationAddress = defaultParliamentAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub - .ChangeSymbolsToPayTXSizeFeeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - - // the new controller try to send SetSymbolsToPayTxSizeFee - var updateInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newSymbolList.ToByteString(), - OrganizationAddress = newAuthority.OwnerAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(updateInput); - var symbolSet = await TokenContractStub.GetSymbolsToPayTxSizeFee.CallAsync(new Empty()); - symbolSet.SymbolsToPayTxSizeFee.Count.ShouldBe(1); - } - - private async Task CreateNewParliamentAddressAsync() - { - var newParliament = new CreateOrganizationInput - { - ProposerAuthorityRequired = false, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 1, - MaximalRejectionThreshold = 1, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = false - }; - var parliamentCreateRet = await ParliamentContractStub.CreateOrganization.SendAsync(newParliament); - var newParliamentAddress = parliamentCreateRet.Output; - return new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, - OwnerAddress = newParliamentAddress - }; - } + [Fact] + public async Task GetSymbolsToPayTXSizeFeeController_Test() + { + var defaultParliament = await GetDefaultParliamentAddressAsync(); + var controller = await TokenContractStub.GetSymbolsToPayTXSizeFeeController.CallAsync(new Empty()); + controller.OwnerAddress.ShouldBe(defaultParliament); + controller.ContractAddress.ShouldBe(ParliamentContractAddress); + } - //fee type : read = 0, storage = 1, write =2, traffic = 3 - [Theory] - [InlineData(false, 3, new []{1}, new [] {1000000, 4, 3, 2})] - [InlineData(false, 0, new []{2}, new []{999999, 1, 4, 2, 5, 250, 40})] - [InlineData(false, 0, new []{3}, new []{int.MaxValue, 2, 8, 2, 6, 300, 50})] - [InlineData(false, 2, new []{2,3}, new []{100, 1, 4, 10000},new []{1000000, 1, 4, 2, 2, 250, 50})] - [InlineData(true, 0, new []{2}, new []{int.MaxValue, 4, 3, 2})] - [InlineData(true, 0, new []{3}, new []{int.MaxValue, 2, 8, 2, 6, 300})] - [InlineData(true, 0, new []{3,2}, new []{1000, 4, 3, 2}, new []{int.MaxValue, 4, 3, 2})] - [InlineData(true, 0, new []{2,3}, new []{100, 4, 3, 2})] - [InlineData(true, 3, new []{1}, new [] {1000000, -1, 3, 2})] - [InlineData(true, 3, new []{1}, new [] {1000000, 4, -1, 2})] - [InlineData(true, 3, new []{1}, new [] {1000000, 4, 3, 0})] - public async Task Update_Coefficient_For_Contract_Test(bool isFail, int feeType, int[] pieceNumber, - params int[][] newPieceFunctions) - { - var originalCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); - var newPieceCoefficientList = newPieceFunctions.Select(x => new CalculateFeePieceCoefficients - { - Value = {x} - }).ToList(); - var updateInput = new UpdateCoefficientsInput - { - PieceNumbers = {pieceNumber}, - Coefficients = new CalculateFeeCoefficients - { - FeeTokenType = feeType, - } - }; - updateInput.Coefficients.PieceCoefficientsList.AddRange(newPieceCoefficientList); - var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(updateInput, - nameof(TokenContractImplContainer.TokenContractImplStub.UpdateCoefficientsForContract)); - await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); - var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); - await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); - await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); - var updatedCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); - if (!isFail) - { - foreach (var newPieceFunction in newPieceFunctions) - { - var hasModified = - GetCalculateFeePieceCoefficients(updatedCoefficients.PieceCoefficientsList, newPieceFunction[0]); - var newCoefficient = newPieceFunction.Skip(1).ToArray(); - hasModified.Value.Skip(1).ShouldBe(newCoefficient); - } - } - else - { - var pieceCount = originalCoefficients.PieceCoefficientsList.Count; - updatedCoefficients.PieceCoefficientsList.Count.ShouldBe(pieceCount); - for (var i = 0; i < pieceCount; i++) - { - originalCoefficients.PieceCoefficientsList[i] - .ShouldBe(updatedCoefficients.PieceCoefficientsList[i]); - } - } - } + [Fact] + public async Task ChangeSymbolsToPayTXSizeFeeController_Fail_Test() + { + // no authority + var newAuthority = await CreateNewParliamentAddressAsync(); + var updateWithOutAuthorityRet = + await TokenContractStub.ChangeSymbolsToPayTXSizeFeeController.SendWithExceptionAsync(newAuthority); + updateWithOutAuthorityRet.TransactionResult.Error.ShouldContain("no permission"); + + //invalid new organization + var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); + var invalidAuthority = new AuthorityInfo + { + OwnerAddress = newAuthority.OwnerAddress, + ContractAddress = AssociationContractAddress + }; + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = invalidAuthority.ToByteString(), + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .ChangeSymbolsToPayTXSizeFeeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + ret.Error.ShouldContain("new controller does not exist"); + } + + [Fact] + public async Task ChangeSymbolsToPayTXSizeFeeController_Success_Test() + { + var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); + var newSymbolList = new SymbolListToPayTxSizeFee(); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = primaryToken.Value, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }); + + // create a new organization to be replace the controller of SetSymbolsToPayTxSizeFee + var newAuthority = await CreateNewParliamentAddressAsync(); + + // get the default parliament that is the controller of SetSymbolsToPayTxSizeFee + var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); + + // create a proposal to replace the controller + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newAuthority.ToByteString(), + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .ChangeSymbolsToPayTXSizeFeeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + + // the new controller try to send SetSymbolsToPayTxSizeFee + var updateInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newSymbolList.ToByteString(), + OrganizationAddress = newAuthority.OwnerAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(updateInput); + var symbolSet = await TokenContractStub.GetSymbolsToPayTxSizeFee.CallAsync(new Empty()); + symbolSet.SymbolsToPayTxSizeFee.Count.ShouldBe(1); + } - [Fact] - public async Task GetCalculateFeeCoefficientsForContract_With_Invalid_FeeType_Test() + private async Task CreateNewParliamentAddressAsync() + { + var newParliament = new CreateOrganizationInput + { + ProposerAuthorityRequired = false, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 1, + MaximalRejectionThreshold = 1, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = false + }; + var parliamentCreateRet = await ParliamentContractStub.CreateOrganization.SendAsync(newParliament); + var newParliamentAddress = parliamentCreateRet.Output; + return new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, + OwnerAddress = newParliamentAddress + }; + } + + //fee type : read = 0, storage = 1, write =2, traffic = 3 + [Theory] + [InlineData(false, 3, new[] { 1 }, new[] { 1000000, 4, 3, 2 })] + [InlineData(false, 0, new[] { 2 }, new[] { 999999, 1, 4, 2, 5, 250, 40 })] + [InlineData(false, 0, new[] { 3 }, new[] { int.MaxValue, 2, 8, 2, 6, 300, 50 })] + [InlineData(false, 2, new[] { 2, 3 }, new[] { 100, 1, 4, 10000 }, new[] { 1000000, 1, 4, 2, 2, 250, 50 })] + [InlineData(true, 0, new[] { 2 }, new[] { int.MaxValue, 4, 3, 2 })] + [InlineData(true, 0, new[] { 3 }, new[] { int.MaxValue, 2, 8, 2, 6, 300 })] + [InlineData(true, 0, new[] { 3, 2 }, new[] { 1000, 4, 3, 2 }, new[] { int.MaxValue, 4, 3, 2 })] + [InlineData(true, 0, new[] { 2, 3 }, new[] { 100, 4, 3, 2 })] + [InlineData(true, 3, new[] { 1 }, new[] { 1000000, -1, 3, 2 })] + [InlineData(true, 3, new[] { 1 }, new[] { 1000000, 4, -1, 2 })] + [InlineData(true, 3, new[] { 1 }, new[] { 1000000, 4, 3, 0 })] + public async Task Update_Coefficient_For_Contract_Test(bool isFail, int feeType, int[] pieceNumber, + params int[][] newPieceFunctions) + { + var originalCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); + var newPieceCoefficientList = newPieceFunctions.Select(x => new CalculateFeePieceCoefficients { - var invalidFeeType = -1; - var ret = await TokenContractStub.GetCalculateFeeCoefficientsForContract.CallAsync(new Int32Value - { - Value = invalidFeeType - }); - ret.ShouldBe(new CalculateFeeCoefficients()); - } - - [Fact] - public async Task ChangeDeveloperController_Success_Test() - { - var newAuthority = await CreateNewParliamentAddressAsync(); - var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(newAuthority, - nameof(TokenContractImplContainer.TokenContractImplStub.ChangeDeveloperController)); - await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); - var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); - await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); - await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); - var developerController = - await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); - developerController.RootController.ContractAddress.ShouldBe(newAuthority.ContractAddress); - developerController.RootController.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); - } - - [Fact] - public async Task ChangeDeveloperController_Fail_Test() - { - var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeDeveloperController); - var newAuthority = await CreateNewParliamentAddressAsync(); - var updateRet = await TokenContractStub.ChangeDeveloperController.SendWithExceptionAsync(newAuthority); - updateRet.TransactionResult.Error.ShouldContain("no permission"); - - var invalidAuthority = new AuthorityInfo - { - OwnerAddress = newAuthority.OwnerAddress, - ContractAddress = AssociationContractAddress - }; - - var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(invalidAuthority, updateMethodName); - await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); - var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); - await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); - var invalidRet = await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); - invalidRet.Error.ShouldContain("Invalid authority input"); - } - - - //fee type : read = 0, storage = 1, write =2, traffic = 3 - [Theory] - [InlineData(false, new []{1}, new [] {100, 4, 3, 2})] - [InlineData(false, new []{2,3}, new []{5000001, 1, 4, 10000},new []{5000002, 1, 4, 2, 2, 250, 50})] - [InlineData(true, new []{2}, new []{int.MaxValue, 4, 3, 2})] - [InlineData(true, new []{1}, new [] {100, 4, 3})] - [InlineData(true, new []{2,3}, new []{5000001, 1, 4, 10000},new []{5000001, 1, 4, 2, 2, 250, 50})] - [InlineData(true, new []{3,2}, new []{5000001, 1, 4, 10000},new []{5000002, 1, 4, 2, 2, 250, 50})] - [InlineData(true, new []{2,3}, new []{5000002, 4, 3, 2})] - public async Task Update_Coefficient_For_Sender_Test(bool isFail, int[] pieceNumber, - params int[][] newPieceFunctions) - { - var feeType = (int) FeeTypeEnum.Tx; - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - await IssuePrimaryTokenToMainChainTesterAsync(); - var originalCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); - var newPieceCoefficientList = newPieceFunctions.Select(x => new CalculateFeePieceCoefficients - { - Value = {x} - }).ToList(); - var updateInput = new UpdateCoefficientsInput - { - PieceNumbers = {pieceNumber}, - Coefficients = new CalculateFeeCoefficients - { - FeeTokenType = feeType, - } - }; - updateInput.Coefficients.PieceCoefficientsList.AddRange(newPieceCoefficientList); - - var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(updateInput, - nameof(TokenContractImplContainer.TokenContractImplStub.UpdateCoefficientsForSender)); - await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); - await VoteToReferendumAsync(proposalId, primaryTokenSymbol); - await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); - - var updatedCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); - if (!isFail) + Value = { x } + }).ToList(); + var updateInput = new UpdateCoefficientsInput + { + PieceNumbers = { pieceNumber }, + Coefficients = new CalculateFeeCoefficients { - foreach (var newPieceFunction in newPieceFunctions) - { - var hasModified = - GetCalculateFeePieceCoefficients(updatedCoefficients.PieceCoefficientsList, newPieceFunction[0]); - var newCoefficient = newPieceFunction.Skip(1).ToArray(); - hasModified.Value.Skip(1).ShouldBe(newCoefficient); - } + FeeTokenType = feeType } - else - { - var pieceCount = originalCoefficients.PieceCoefficientsList.Count; - updatedCoefficients.PieceCoefficientsList.Count.ShouldBe(pieceCount); - for (var i = 0; i < pieceCount; i++) - { - originalCoefficients.PieceCoefficientsList[i] - .ShouldBe(updatedCoefficients.PieceCoefficientsList[i]); - } + }; + updateInput.Coefficients.PieceCoefficientsList.AddRange(newPieceCoefficientList); + var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(updateInput, + nameof(TokenContractImplContainer.TokenContractImplStub.UpdateCoefficientsForContract)); + await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); + var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); + await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); + await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); + var updatedCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); + if (!isFail) + { + foreach (var newPieceFunction in newPieceFunctions) + { + var hasModified = + GetCalculateFeePieceCoefficients(updatedCoefficients.PieceCoefficientsList, newPieceFunction[0]); + var newCoefficient = newPieceFunction.Skip(1).ToArray(); + hasModified.Value.Skip(1).ShouldBe(newCoefficient); } } - - [Fact] - public async Task ChangeUserFeeController_Success_Test() - { - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - await IssuePrimaryTokenToMainChainTesterAsync(); - var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeUserFeeController); - var newAuthority = await CreateNewParliamentAddressAsync(); - - var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(newAuthority,updateMethodName); - await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); - await VoteToReferendumAsync(proposalId, primaryTokenSymbol); - await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); - var userFeeController = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); - userFeeController.RootController.ContractAddress.ShouldBe(newAuthority.ContractAddress); - userFeeController.RootController.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); - } - - [Fact] - public async Task ChangeUserFeeController_Fail_Test() - { - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - await IssuePrimaryTokenToMainChainTesterAsync(); - var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeUserFeeController); - var newAuthority = await CreateNewParliamentAddressAsync(); - var updateRet = - await TokenContractStub.ChangeUserFeeController.SendWithExceptionAsync(newAuthority); - updateRet.TransactionResult.Error.ShouldContain("no permission"); - - var invalidAuthority = new AuthorityInfo - { - OwnerAddress = newAuthority.OwnerAddress, - ContractAddress = AssociationContractAddress - }; - var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(invalidAuthority,updateMethodName); - await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); - await VoteToReferendumAsync(proposalId, primaryTokenSymbol); - var invalidRet = await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); - invalidRet.Error.ShouldContain("Invalid authority input"); - } - - private async Task GetCalculateFeeCoefficientsByFeeTypeAsync(int feeType) + else { - if (feeType == (int) FeeTypeEnum.Tx) - { - var userCoefficient = - await TokenContractStub.GetCalculateFeeCoefficientsForSender.CallAsync(new Empty()); - return userCoefficient; - } - var developerCoefficient = await TokenContractStub.GetCalculateFeeCoefficientsForContract.CallAsync( - new Int32Value - { - Value = feeType - }); - return developerCoefficient; + var pieceCount = originalCoefficients.PieceCoefficientsList.Count; + updatedCoefficients.PieceCoefficientsList.Count.ShouldBe(pieceCount); + for (var i = 0; i < pieceCount; i++) + originalCoefficients.PieceCoefficientsList[i] + .ShouldBe(updatedCoefficients.PieceCoefficientsList[i]); } + } - private CalculateFeePieceCoefficients GetCalculateFeePieceCoefficients( - IEnumerable calculateFeePieceCoefficients, int pieceUpperBound) + [Fact] + public async Task GetCalculateFeeCoefficientsForContract_With_Invalid_FeeType_Test() + { + var invalidFeeType = -1; + var ret = await TokenContractStub.GetCalculateFeeCoefficientsForContract.CallAsync(new Int32Value { - return calculateFeePieceCoefficients.SingleOrDefault(c => c.Value[0] == pieceUpperBound); - } + Value = invalidFeeType + }); + ret.ShouldBe(new CalculateFeeCoefficients()); + } - [Fact] - public async Task MethodFeeController_Test_Fail() + [Fact] + public async Task ChangeDeveloperController_Success_Test() + { + var newAuthority = await CreateNewParliamentAddressAsync(); + var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(newAuthority, + nameof(TokenContractImplContainer.TokenContractImplStub.ChangeDeveloperController)); + await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); + var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); + await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); + await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); + var developerController = + await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); + developerController.RootController.ContractAddress.ShouldBe(newAuthority.ContractAddress); + developerController.RootController.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); + } + + [Fact] + public async Task ChangeDeveloperController_Fail_Test() + { + var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeDeveloperController); + var newAuthority = await CreateNewParliamentAddressAsync(); + var updateRet = await TokenContractStub.ChangeDeveloperController.SendWithExceptionAsync(newAuthority); + updateRet.TransactionResult.Error.ShouldContain("no permission"); + + var invalidAuthority = new AuthorityInfo + { + OwnerAddress = newAuthority.OwnerAddress, + ContractAddress = AssociationContractAddress + }; + + var proposalId = await CreateToRootForDeveloperFeeByTwoLayerAsync(invalidAuthority, updateMethodName); + await ApproveToRootForDeveloperFeeByTwoLayerAsync(proposalId); + var middleApproveProposalId = await ApproveToRootForDeveloperFeeByMiddleLayerAsync(proposalId); + await ApproveThenReleaseMiddleProposalForDeveloperAsync(middleApproveProposalId); + var invalidRet = await ReleaseToRootForDeveloperFeeByTwoLayerAsync(proposalId); + invalidRet.Error.ShouldContain("Invalid authority input"); + } + + + //fee type : read = 0, storage = 1, write =2, traffic = 3 + [Theory] + [InlineData(false, new[] { 1 }, new[] { 100, 4, 3, 2 })] + [InlineData(false, new[] { 2, 3 }, new[] { 5000001, 1, 4, 10000 }, new[] { 5000002, 1, 4, 2, 2, 250, 50 })] + [InlineData(true, new[] { 2 }, new[] { int.MaxValue, 4, 3, 2 })] + [InlineData(true, new[] { 1 }, new[] { 100, 4, 3 })] + [InlineData(true, new[] { 2, 3 }, new[] { 5000001, 1, 4, 10000 }, new[] { 5000001, 1, 4, 2, 2, 250, 50 })] + [InlineData(true, new[] { 3, 2 }, new[] { 5000001, 1, 4, 10000 }, new[] { 5000002, 1, 4, 2, 2, 250, 50 })] + [InlineData(true, new[] { 2, 3 }, new[] { 5000002, 4, 3, 2 })] + public async Task Update_Coefficient_For_Sender_Test(bool isFail, int[] pieceNumber, + params int[][] newPieceFunctions) + { + var feeType = (int)FeeTypeEnum.Tx; + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + await IssuePrimaryTokenToMainChainTesterAsync(); + var originalCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); + var newPieceCoefficientList = newPieceFunctions.Select(x => new CalculateFeePieceCoefficients { - var updateMethodName = nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); - // no authority - var newAuthority = await CreateNewParliamentAddressAsync(); - //invalid new organization - var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); - var invalidAuthority = new AuthorityInfo - { - OwnerAddress = newAuthority.OwnerAddress, - ContractAddress = AssociationContractAddress - }; - var createProposalInput = new CreateProposalInput + Value = { x } + }).ToList(); + var updateInput = new UpdateCoefficientsInput + { + PieceNumbers = { pieceNumber }, + Coefficients = new CalculateFeeCoefficients { - ToAddress = TokenContractAddress, - Params = invalidAuthority.ToByteString(), - OrganizationAddress = defaultParliamentAddress, - ContractMethodName = updateMethodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - ret.Error.ShouldContain("Invalid authority input"); - } - + FeeTokenType = feeType + } + }; + updateInput.Coefficients.PieceCoefficientsList.AddRange(newPieceCoefficientList); - [Fact] - public async Task MethodFeeController_Test_Success() + var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(updateInput, + nameof(TokenContractImplContainer.TokenContractImplStub.UpdateCoefficientsForSender)); + await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); + await VoteToReferendumAsync(proposalId, primaryTokenSymbol); + await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); + + var updatedCoefficients = await GetCalculateFeeCoefficientsByFeeTypeAsync(feeType); + if (!isFail) { - var defaultController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = createOrganizationResult.Output; - - //change controller - var newController = new AuthorityInfo + foreach (var newPieceFunction in newPieceFunctions) { - ContractAddress = defaultController.ContractAddress, - OwnerAddress = organizationAddress - }; - var createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newController.ToByteString(), - OrganizationAddress = defaultController.OwnerAddress, - ContractMethodName = nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - var queryController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); - queryController.ShouldBe(newController); + var hasModified = + GetCalculateFeePieceCoefficients(updatedCoefficients.PieceCoefficientsList, newPieceFunction[0]); + var newCoefficient = newPieceFunction.Skip(1).ToArray(); + hasModified.Value.Skip(1).ShouldBe(newCoefficient); + } } - - [Fact] - public async Task ChangeCrossChainTokenContractRegistrationController_Success_Test() - { - var defaultController = - await TokenContractStub.GetCrossChainTokenContractRegistrationController.CallAsync(new Empty()); - var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); - defaultController.OwnerAddress.ShouldBe(defaultParliamentAddress); - - var newAuthority = await CreateNewParliamentAddressAsync(); - var proposalId = await CreateProposalAsync(ParliamentContractStub, - nameof(TokenContractImplContainer.TokenContractImplStub - .ChangeCrossChainTokenContractRegistrationController), newAuthority.ToByteString(), - TokenContractAddress); - - await ApproveWithMinersAsync(proposalId); - var txResult = await ReleaseProposalAsync(proposalId); - txResult.Status.ShouldBe(TransactionResultStatus.Mined); - var newController = - await TokenContractStub.GetCrossChainTokenContractRegistrationController.CallAsync(new Empty()); - Assert.True(newController.OwnerAddress == newAuthority.OwnerAddress); + else + { + var pieceCount = originalCoefficients.PieceCoefficientsList.Count; + updatedCoefficients.PieceCoefficientsList.Count.ShouldBe(pieceCount); + for (var i = 0; i < pieceCount; i++) + originalCoefficients.PieceCoefficientsList[i] + .ShouldBe(updatedCoefficients.PieceCoefficientsList[i]); } + } + + [Fact] + public async Task ChangeUserFeeController_Success_Test() + { + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + await IssuePrimaryTokenToMainChainTesterAsync(); + var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeUserFeeController); + var newAuthority = await CreateNewParliamentAddressAsync(); + + var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(newAuthority, updateMethodName); + await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); + await VoteToReferendumAsync(proposalId, primaryTokenSymbol); + await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); + var userFeeController = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); + userFeeController.RootController.ContractAddress.ShouldBe(newAuthority.ContractAddress); + userFeeController.RootController.OwnerAddress.ShouldBe(newAuthority.OwnerAddress); + } - [Fact] - public async Task ChangeCrossChainTokenContractRegistrationController_Fail_Test() + [Fact] + public async Task ChangeUserFeeController_Fail_Test() + { + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + await IssuePrimaryTokenToMainChainTesterAsync(); + var updateMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.ChangeUserFeeController); + var newAuthority = await CreateNewParliamentAddressAsync(); + var updateRet = + await TokenContractStub.ChangeUserFeeController.SendWithExceptionAsync(newAuthority); + updateRet.TransactionResult.Error.ShouldContain("no permission"); + + var invalidAuthority = new AuthorityInfo + { + OwnerAddress = newAuthority.OwnerAddress, + ContractAddress = AssociationContractAddress + }; + var proposalId = await CreateToRootForUserFeeByTwoLayerAsync(invalidAuthority, updateMethodName); + await ApproveToRootForUserFeeByTwoLayerAsync(proposalId); + await VoteToReferendumAsync(proposalId, primaryTokenSymbol); + var invalidRet = await ReleaseToRootForUserFeeByTwoLayerAsync(proposalId); + invalidRet.Error.ShouldContain("Invalid authority input"); + } + + private async Task GetCalculateFeeCoefficientsByFeeTypeAsync(int feeType) + { + if (feeType == (int)FeeTypeEnum.Tx) { - var newAuthority = await CreateNewParliamentAddressAsync(); - var result = - await TokenContractStub.ChangeCrossChainTokenContractRegistrationController.SendWithExceptionAsync( - newAuthority); - result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); - - var invalidAuthority = new AuthorityInfo - { - OwnerAddress = newAuthority.OwnerAddress, - ContractAddress = AssociationContractAddress - }; - var proposalId = await CreateProposalAsync(ParliamentContractStub, - nameof(TokenContractImplContainer.TokenContractImplStub - .ChangeCrossChainTokenContractRegistrationController), invalidAuthority.ToByteString(), - TokenContractAddress); - - await ApproveWithMinersAsync(proposalId); - var txResult = await ReleaseProposalAsync(proposalId); - txResult.Error.ShouldContain("Invalid authority input"); + var userCoefficient = + await TokenContractStub.GetCalculateFeeCoefficientsForSender.CallAsync(new Empty()); + return userCoefficient; } - [Fact] - public async Task SetSymbolsToPayTxSizeFee_With_Invalid_Weight_Test() - { - var theDefaultController = await GetDefaultParliamentAddressAsync(); - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 100_000, - IsBurnable = true - }); - var newSymbolList = new SymbolListToPayTxSizeFee(); - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + var developerCoefficient = await TokenContractStub.GetCalculateFeeCoefficientsForContract.CallAsync( + new Int32Value { - TokenSymbol = primaryTokenSymbol, - AddedTokenWeight = 2, - BaseTokenWeight = 1 + Value = feeType }); - var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(false); + return developerCoefficient; + } - newSymbolList.SymbolsToPayTxSizeFee[0].AddedTokenWeight = 1; - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 0, - BaseTokenWeight = 1 - }); - result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(false); - } + private CalculateFeePieceCoefficients GetCalculateFeePieceCoefficients( + IEnumerable calculateFeePieceCoefficients, int pieceUpperBound) + { + return calculateFeePieceCoefficients.SingleOrDefault(c => c.Value[0] == pieceUpperBound); + } - [Fact] - public async Task SetSymbolsToPayTxSizeFee_With_Repeat_Token_Test() - { - var theDefaultController = await GetDefaultParliamentAddressAsync(); - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 100_000 - }); - var newSymbolList = new SymbolListToPayTxSizeFee + [Fact] + public async Task MethodFeeController_Test_Fail() + { + var updateMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController); + // no authority + var newAuthority = await CreateNewParliamentAddressAsync(); + //invalid new organization + var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); + var invalidAuthority = new AuthorityInfo + { + OwnerAddress = newAuthority.OwnerAddress, + ContractAddress = AssociationContractAddress + }; + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = invalidAuthority.ToByteString(), + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = updateMethodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + ret.Error.ShouldContain("Invalid authority input"); + } + + + [Fact] + public async Task MethodFeeController_Test_Success() + { + var defaultController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var createOrganizationResult = await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - SymbolsToPayTxSizeFee = + ProposalReleaseThreshold = new ProposalReleaseThreshold { - new SymbolToPayTxSizeFee - { - TokenSymbol = primaryTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } - }; - - var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(false); - } - - [Fact] - public async Task SetSymbolsToPayTxSizeFee_Without_PrimaryToken_Test() - { - var theDefaultController = await GetDefaultParliamentAddressAsync(); - var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 100_000 }); - var newSymbolList = new SymbolListToPayTxSizeFee(); - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 2, - BaseTokenWeight = 1 - }); - var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(false); - } - - [Fact] - public async Task SetSymbolsToPayTxSizeFee_Without_Profitable_Token_Test() - { - var theDefaultController = await GetDefaultParliamentAddressAsync(); - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - const string feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 100_000, - }); - var newSymbolList = new SymbolListToPayTxSizeFee + var organizationAddress = createOrganizationResult.Output; + + //change controller + var newController = new AuthorityInfo + { + ContractAddress = defaultController.ContractAddress, + OwnerAddress = organizationAddress + }; + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newController.ToByteString(), + OrganizationAddress = defaultController.OwnerAddress, + ContractMethodName = + nameof(BasicContractZeroImplContainer.BasicContractZeroImplStub.ChangeMethodFeeController), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + var queryController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + queryController.ShouldBe(newController); + } + + [Fact] + public async Task ChangeCrossChainTokenContractRegistrationController_Success_Test() + { + var defaultController = + await TokenContractStub.GetCrossChainTokenContractRegistrationController.CallAsync(new Empty()); + var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); + defaultController.OwnerAddress.ShouldBe(defaultParliamentAddress); + + var newAuthority = await CreateNewParliamentAddressAsync(); + var proposalId = await CreateProposalAsync(ParliamentContractStub, + nameof(TokenContractImplContainer.TokenContractImplStub + .ChangeCrossChainTokenContractRegistrationController), newAuthority.ToByteString(), + TokenContractAddress); + + await ApproveWithMinersAsync(proposalId); + var txResult = await ReleaseProposalAsync(proposalId); + txResult.Status.ShouldBe(TransactionResultStatus.Mined); + var newController = + await TokenContractStub.GetCrossChainTokenContractRegistrationController.CallAsync(new Empty()); + Assert.True(newController.OwnerAddress == newAuthority.OwnerAddress); + } + + [Fact] + public async Task ChangeCrossChainTokenContractRegistrationController_Fail_Test() + { + var newAuthority = await CreateNewParliamentAddressAsync(); + var result = + await TokenContractStub.ChangeCrossChainTokenContractRegistrationController.SendWithExceptionAsync( + newAuthority); + result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + + var invalidAuthority = new AuthorityInfo + { + OwnerAddress = newAuthority.OwnerAddress, + ContractAddress = AssociationContractAddress + }; + var proposalId = await CreateProposalAsync(ParliamentContractStub, + nameof(TokenContractImplContainer.TokenContractImplStub + .ChangeCrossChainTokenContractRegistrationController), invalidAuthority.ToByteString(), + TokenContractAddress); + + await ApproveWithMinersAsync(proposalId); + var txResult = await ReleaseProposalAsync(proposalId); + txResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task SetSymbolsToPayTxSizeFee_With_Invalid_Weight_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + var feeToken = "FEETOKEN"; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 100_000, + IsBurnable = true + }); + var newSymbolList = new SymbolListToPayTxSizeFee(); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = primaryTokenSymbol, + AddedTokenWeight = 2, + BaseTokenWeight = 1 + }); + var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(false); + + newSymbolList.SymbolsToPayTxSizeFee[0].AddedTokenWeight = 1; + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 0, + BaseTokenWeight = 1 + }); + result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(false); + } + + [Fact] + public async Task SetSymbolsToPayTxSizeFee_With_Repeat_Token_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + var feeToken = "FEETOKEN"; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 100_000 + }); + var newSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = { - SymbolsToPayTxSizeFee = + new SymbolToPayTxSizeFee + { + TokenSymbol = primaryTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee { - new SymbolToPayTxSizeFee - { - TokenSymbol = primaryTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } + TokenSymbol = feeToken, + AddedTokenWeight = 1, + BaseTokenWeight = 1 } - }; - var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(false); - } - - [Fact(Skip = "Now we remove related logic temporaryly.")] - public async Task SetSymbolsToPayTxSizeFee_With_Overflow_Input_Test() + } + }; + + var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(false); + } + + [Fact] + public async Task SetSymbolsToPayTxSizeFee_Without_PrimaryToken_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var feeToken = "FEETOKEN"; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 100_000 + }); + var newSymbolList = new SymbolListToPayTxSizeFee(); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 2, + BaseTokenWeight = 1 + }); + var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(false); + } + + [Fact] + public async Task SetSymbolsToPayTxSizeFee_Without_Profitable_Token_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + const string feeToken = "FEETOKEN"; + await TokenContractStub.Create.SendAsync(new CreateInput { - var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); - var primaryTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = primaryToken.Value - }); - var newSymbolList = new SymbolListToPayTxSizeFee(); - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = primaryToken.Value, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }); - var feeToken = "FEETOKEN"; - var newTokenTotalSupply = 1000_000_00000; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = newTokenTotalSupply, - IsBurnable = true - }); - var invalidBaseTokenWeight = (int)long.MaxValue.Div(newTokenTotalSupply).Add(1); - newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 1, - BaseTokenWeight = invalidBaseTokenWeight - }); - - var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); - var createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newSymbolList.ToByteString(), - OrganizationAddress = defaultParliamentAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub - .SetSymbolsToPayTxSizeFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var result = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain($"the weight of token {primaryToken.Value} is set too large"); - - invalidBaseTokenWeight = (int) long.MaxValue.Div(primaryTokenInfo.TotalSupply).Add(1); - newSymbolList.SymbolsToPayTxSizeFee[1].BaseTokenWeight = 1; - newSymbolList.SymbolsToPayTxSizeFee[1].AddedTokenWeight = invalidBaseTokenWeight; - createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newSymbolList.ToByteString(), - OrganizationAddress = defaultParliamentAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub - .SetSymbolsToPayTxSizeFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - result = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.ShouldContain($"the weight of token {feeToken} is set too large"); - } - - [Fact] - public async Task SetSymbolsToPayTxSizeFee_Success_Test() - { - var theDefaultController = await GetDefaultParliamentAddressAsync(); - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - const string feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = feeToken, - TokenName = "name", - Issuer = TokenContractAddress, - TotalSupply = 100_000, - IsBurnable = true - }); - var newSymbolList = new SymbolListToPayTxSizeFee + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 100_000 + }); + var newSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = { - SymbolsToPayTxSizeFee = + new SymbolToPayTxSizeFee { - new SymbolToPayTxSizeFee - { - TokenSymbol = primaryTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = feeToken, - AddedTokenWeight = 1, - BaseTokenWeight = 2 - } + TokenSymbol = primaryTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 1, + BaseTokenWeight = 1 } - }; - var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); - result.ShouldBe(true); - } + } + }; + var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(false); + } - [Fact] - public async Task ClaimTransactionFee_Without_Authorized_Test() - { - var input = new TotalTransactionFeesMap(); - var tokenContractStub = - GetTester(TokenContractAddress, Accounts.Last().KeyPair); - var claimRet = await tokenContractStub.ClaimTransactionFees.SendWithExceptionAsync(input); - claimRet.TransactionResult.Error.ShouldContain("No permission"); - } + [Fact(Skip = "Now we remove related logic temporaryly.")] + public async Task SetSymbolsToPayTxSizeFee_With_Overflow_Input_Test() + { + var primaryToken = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); + var primaryTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = primaryToken.Value + }); + var newSymbolList = new SymbolListToPayTxSizeFee(); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = primaryToken.Value, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }); + var feeToken = "FEETOKEN"; + var newTokenTotalSupply = 1000_000_00000; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = newTokenTotalSupply, + IsBurnable = true + }); + var invalidBaseTokenWeight = (int)long.MaxValue.Div(newTokenTotalSupply).Add(1); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 1, + BaseTokenWeight = invalidBaseTokenWeight + }); + + var defaultParliamentAddress = await GetDefaultParliamentAddressAsync(); + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newSymbolList.ToByteString(), + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .SetSymbolsToPayTxSizeFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var result = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain($"the weight of token {primaryToken.Value} is set too large"); + + invalidBaseTokenWeight = (int)long.MaxValue.Div(primaryTokenInfo.TotalSupply).Add(1); + newSymbolList.SymbolsToPayTxSizeFee[1].BaseTokenWeight = 1; + newSymbolList.SymbolsToPayTxSizeFee[1].AddedTokenWeight = invalidBaseTokenWeight; + createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newSymbolList.ToByteString(), + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .SetSymbolsToPayTxSizeFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + result = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.ShouldContain($"the weight of token {feeToken} is set too large"); + } - private async Task MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(CreateProposalInput proposalInput) - { - var parliamentCreateProposal = await ParliamentContractStub.CreateProposal.SendAsync(proposalInput); - var parliamentProposalId = parliamentCreateProposal.Output; - await ApproveWithMinersAsync(parliamentProposalId); - var releaseRet = await ReleaseProposalAsync(parliamentProposalId); - //releaseRet.Status.ShouldBe(TransactionResultStatus.Mined); - return releaseRet; - } + [Fact] + public async Task SetSymbolsToPayTxSizeFee_Success_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + const string feeToken = "FEETOKEN"; + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = feeToken, + TokenName = "name", + Issuer = TokenContractAddress, + TotalSupply = 100_000, + IsBurnable = true + }); + var newSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = primaryTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = feeToken, + AddedTokenWeight = 1, + BaseTokenWeight = 2 + } + } + }; + var result = await VerifyTheSymbolList(theDefaultController, newSymbolList); + result.ShouldBe(true); + } - private async Task CreateToRootForDeveloperFeeByTwoLayerAsync(IMessage input, string methodName) - { - var organizations = await GetControllerForDeveloperFeeAsync(); - var createNestProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.RootController.OwnerAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var createProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = createNestProposalInput.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - - var releaseRet = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - var id = ProposalCreated.Parser - .ParseFrom(releaseRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - return id; - } + [Fact] + public async Task ClaimTransactionFee_Without_Authorized_Test() + { + var input = new TotalTransactionFeesMap(); + var tokenContractStub = + GetTester(TokenContractAddress, Accounts.Last().KeyPair); + var claimRet = await tokenContractStub.ClaimTransactionFees.SendWithExceptionAsync(input); + claimRet.TransactionResult.Error.ShouldContain("No permission"); + } - private async Task ApproveToRootForDeveloperFeeByTwoLayerAsync(Hash input) - { - var organizations = await GetControllerForDeveloperFeeAsync(); - var approveProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveProposalInput); - } + private async Task MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync( + CreateProposalInput proposalInput) + { + var parliamentCreateProposal = await ParliamentContractStub.CreateProposal.SendAsync(proposalInput); + var parliamentProposalId = parliamentCreateProposal.Output; + await ApproveWithMinersAsync(parliamentProposalId); + var releaseRet = await ReleaseProposalAsync(parliamentProposalId); + //releaseRet.Status.ShouldBe(TransactionResultStatus.Mined); + return releaseRet; + } - private async Task ReleaseToRootForDeveloperFeeByTwoLayerAsync(Hash input) - { - var organizations = await GetControllerForDeveloperFeeAsync(); - var releaseProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Release), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - return await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(releaseProposalInput); - } + private async Task CreateToRootForDeveloperFeeByTwoLayerAsync(IMessage input, string methodName) + { + var organizations = await GetControllerForDeveloperFeeAsync(); + var createNestProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.RootController.OwnerAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var createProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = createNestProposalInput.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + + var releaseRet = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + var id = ProposalCreated.Parser + .ParseFrom(releaseRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + return id; + } - private async Task ApproveToRootForDeveloperFeeByMiddleLayerAsync(Hash input) - { - var organizations = await GetControllerForDeveloperFeeAsync(); - var approveMidProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.DeveloperController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var approveLeafProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = approveMidProposalInput.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var newCreateProposalRet = - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveLeafProposalInput); - var middleProposalId = ProposalCreated.Parser - .ParseFrom(newCreateProposalRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - return middleProposalId; - } + private async Task ApproveToRootForDeveloperFeeByTwoLayerAsync(Hash input) + { + var organizations = await GetControllerForDeveloperFeeAsync(); + var approveProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveProposalInput); + } - private async Task ApproveThenReleaseMiddleProposalForDeveloperAsync(Hash input) - { - var organizations = await GetControllerForDeveloperFeeAsync(); - var approveLeafProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveLeafProposalInput); - - approveLeafProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Release), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; + private async Task ReleaseToRootForDeveloperFeeByTwoLayerAsync(Hash input) + { + var organizations = await GetControllerForDeveloperFeeAsync(); + var releaseProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Release), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + return await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(releaseProposalInput); + } + + private async Task ApproveToRootForDeveloperFeeByMiddleLayerAsync(Hash input) + { + var organizations = await GetControllerForDeveloperFeeAsync(); + var approveMidProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.DeveloperController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var approveLeafProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = approveMidProposalInput.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var newCreateProposalRet = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveLeafProposalInput); - } + var middleProposalId = ProposalCreated.Parser + .ParseFrom(newCreateProposalRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + return middleProposalId; + } - private async Task CreateToRootForUserFeeByTwoLayerAsync(IMessage input, string methodName) - { - var organizations = await GetControllerForUserFeeAsync(); - var createNestProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.RootController.OwnerAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - - var createProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = createNestProposalInput.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var releaseRet = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - - var id = ProposalCreated.Parser - .ParseFrom(releaseRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - return id; - } + private async Task ApproveThenReleaseMiddleProposalForDeveloperAsync(Hash input) + { + var organizations = await GetControllerForDeveloperFeeAsync(); + var approveLeafProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveLeafProposalInput); + + approveLeafProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Release), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveLeafProposalInput); + } - private async Task ApproveToRootForUserFeeByTwoLayerAsync(Hash input) - { - var organizations = await GetControllerForUserFeeAsync(); - var approveProposalInput = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveProposalInput); - } + private async Task CreateToRootForUserFeeByTwoLayerAsync(IMessage input, string methodName) + { + var organizations = await GetControllerForUserFeeAsync(); + var createNestProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.RootController.OwnerAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + + var createProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = createNestProposalInput.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.CreateProposal), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var releaseRet = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + + var id = ProposalCreated.Parser + .ParseFrom(releaseRet.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + return id; + } - private async Task VoteToReferendumAsync(Hash input, string primaryTokenSymbol) - { - var organizations = await GetControllerForUserFeeAsync(); + private async Task ApproveToRootForUserFeeByTwoLayerAsync(Hash input) + { + var organizations = await GetControllerForUserFeeAsync(); + var approveProposalInput = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AssociationContractImplContainer.AssociationContractImplStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(approveProposalInput); + } - var referendumProposal = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ReferendumController.OwnerAddress, - ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - - var parliamentProposal = new CreateProposalInput - { - ToAddress = ReferendumContractAddress, - Params = referendumProposal.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); - var referendumProposalId = ProposalCreated.Parser - .ParseFrom(ret.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) - .NonIndexed).ProposalId; - var proposalVirtualAddress = - await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(referendumProposalId); - var approveResult = await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Spender = proposalVirtualAddress, - Symbol = primaryTokenSymbol, - Amount = 100000 - }); - await ReferendumContractStub.Approve.SendAsync(referendumProposalId); + private async Task VoteToReferendumAsync(Hash input, string primaryTokenSymbol) + { + var organizations = await GetControllerForUserFeeAsync(); + + var referendumProposal = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ReferendumController.OwnerAddress, + ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Approve), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + + var parliamentProposal = new CreateProposalInput + { + ToAddress = ReferendumContractAddress, + Params = referendumProposal.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.CreateProposal), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var ret = await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); + var referendumProposalId = ProposalCreated.Parser + .ParseFrom(ret.Logs.First(l => l.Name.Contains(nameof(ProposalCreated))) + .NonIndexed).ProposalId; + var proposalVirtualAddress = + await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(referendumProposalId); + var approveResult = await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = proposalVirtualAddress, + Symbol = primaryTokenSymbol, + Amount = 100000 + }); + await ReferendumContractStub.Approve.SendAsync(referendumProposalId); + + parliamentProposal = new CreateProposalInput + { + ToAddress = ReferendumContractAddress, + Params = referendumProposalId.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); + } - parliamentProposal = new CreateProposalInput - { - ToAddress = ReferendumContractAddress, - Params = referendumProposalId.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); - } + private async Task ReleaseToRootForUserFeeByTwoLayerAsync(Hash input) + { + var organizations = await GetControllerForUserFeeAsync(); + var parliamentProposal = new CreateProposalInput + { + ToAddress = AssociationContractAddress, + Params = input.ToByteString(), + OrganizationAddress = organizations.ParliamentController.OwnerAddress, + ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + return await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); + } - private async Task ReleaseToRootForUserFeeByTwoLayerAsync(Hash input) - { - var organizations = await GetControllerForUserFeeAsync(); - var parliamentProposal = new CreateProposalInput - { - ToAddress = AssociationContractAddress, - Params = input.ToByteString(), - OrganizationAddress = organizations.ParliamentController.OwnerAddress, - ContractMethodName = nameof(AuthorizationContractContainer.AuthorizationContractStub.Release), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - return await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(parliamentProposal); - } + private async Task GetControllerForUserFeeAsync() + { + var organizationInfo = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); + return organizationInfo; + } - private async Task GetControllerForUserFeeAsync() - { - var organizationInfo = await TokenContractStub.GetUserFeeController.CallAsync(new Empty()); - return organizationInfo; - } + private async Task GetControllerForDeveloperFeeAsync() + { + var organizationInfo = await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); + return organizationInfo; + } - private async Task GetControllerForDeveloperFeeAsync() - { - var organizationInfo = await TokenContractStub.GetDeveloperFeeController.CallAsync(new Empty()); - return organizationInfo; - } - - private async Task
GetDefaultParliamentAddressAsync() - { - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - return defaultParliamentAddress; - } + private async Task
GetDefaultParliamentAddressAsync() + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + return defaultParliamentAddress; + } - private async Task IssuePrimaryTokenToMainChainTesterAsync() - { - var callOwner = DefaultAccount.Address; - var primaryTokenSymbol = await GetThePrimaryTokenAsync(); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Amount = 100000, - To = callOwner, - Symbol = primaryTokenSymbol - }); - } + private async Task IssuePrimaryTokenToMainChainTesterAsync() + { + var callOwner = DefaultAccount.Address; + var primaryTokenSymbol = await GetThePrimaryTokenAsync(); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = 100000, + To = callOwner, + Symbol = primaryTokenSymbol + }); + } - private async Task GetThePrimaryTokenAsync() - { - var primaryTokenSymbol = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); - return primaryTokenSymbol.Value; - } + private async Task GetThePrimaryTokenAsync() + { + var primaryTokenSymbol = await TokenContractStub.GetPrimaryTokenSymbol.CallAsync(new Empty()); + return primaryTokenSymbol.Value; + } - private async Task VerifyTheSymbolList(Address defaultController, SymbolListToPayTxSizeFee newSymbolList) - { - var createProposalInput = new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = newSymbolList.ToByteString(), - OrganizationAddress = defaultController, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub - .SetSymbolsToPayTxSizeFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); - var symbolListToPayTxSizeFee = await TokenContractStub.GetSymbolsToPayTxSizeFee.CallAsync(new Empty()); - return symbolListToPayTxSizeFee.SymbolsToPayTxSizeFee.Count != 0; - } + private async Task VerifyTheSymbolList(Address defaultController, SymbolListToPayTxSizeFee newSymbolList) + { + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newSymbolList.ToByteString(), + OrganizationAddress = defaultController, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .SetSymbolsToPayTxSizeFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + await MainChainTesterCreatApproveAndReleaseProposalForParliamentAsync(createProposalInput); + var symbolListToPayTxSizeFee = await TokenContractStub.GetSymbolsToPayTxSizeFee.CallAsync(new Empty()); + return symbolListToPayTxSizeFee.SymbolsToPayTxSizeFee.Count != 0; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ParliamentContractInitializationDataProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ParliamentContractInitializationDataProvider.cs index 71a65ee5f9..e189402b60 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ParliamentContractInitializationDataProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ParliamentContractInitializationDataProvider.cs @@ -1,17 +1,16 @@ using AElf.ContractTestBase.ContractTestKit; using AElf.GovernmentSystem; - - namespace AElf.Contracts.MultiToken - { - public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider - { - public ParliamentContractInitializationData GetContractInitializationData() - { - return new ParliamentContractInitializationData - { - PrivilegedProposer = ContractTestConstants.DefaultAccount.Address, - ProposerAuthorityRequired = true - }; - } - } - } \ No newline at end of file + +namespace AElf.Contracts.MultiToken; + +public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider +{ + public ParliamentContractInitializationData GetContractInitializationData() + { + return new ParliamentContractInitializationData + { + PrivilegedProposer = ContractTestConstants.DefaultAccount.Address, + ProposerAuthorityRequired = true + }; + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ResetBlockTimeProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ResetBlockTimeProvider.cs index 73b7f1678d..714e6e2c8d 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ResetBlockTimeProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/ResetBlockTimeProvider.cs @@ -1,10 +1,9 @@ using AElf.ContractTestBase.ContractTestKit; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class ResetBlockTimeProvider : IResetBlockTimeProvider { - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => false; - public int StepMilliseconds => 0; - } + public bool Enabled => false; + public int StepMilliseconds => 0; } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainInitializationDataProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainInitializationDataProvider.cs index 84a07be5a8..a1635e2408 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainInitializationDataProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainInitializationDataProvider.cs @@ -1,80 +1,77 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.Consensus.AEDPoS; using AElf.ContractTestBase.ContractTestKit; using AElf.CrossChain.Application; using AElf.Kernel; +using AElf.Standards.ACS7; using Google.Protobuf; using Microsoft.Extensions.Options; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider { - public class SideChainInitializationDataProvider : ISideChainInitializationDataProvider - { - public int ParentChainId => _chainInitializationOptions.ParentChainId; + private readonly ChainInitializationOptions _chainInitializationOptions; - private readonly ChainInitializationOptions _chainInitializationOptions; + public SideChainInitializationDataProvider(IOptionsSnapshot chainInitializationOptions) + { + _chainInitializationOptions = chainInitializationOptions.Value; + } - public SideChainInitializationDataProvider(IOptionsSnapshot chainInitializationOptions) - { - _chainInitializationOptions = chainInitializationOptions.Value; - } + public int ParentChainId => _chainInitializationOptions.ParentChainId; - public Task GetChainInitializationDataAsync() + public Task GetChainInitializationDataAsync() + { + var address = SampleAccount.Accounts.First().Address; + // Default Initialization Data + return Task.FromResult(new ChainInitializationData { - var address = SampleAccount.Accounts.First().Address; - // Default Initialization Data - return Task.FromResult(new ChainInitializationData + Creator = address, + ChainId = _chainInitializationOptions.ChainId, + ChainCreatorPrivilegePreserved = true, + ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo { - Creator = address, - ChainId = _chainInitializationOptions.ChainId, - ChainCreatorPrivilegePreserved = true, - ChainInitializationConsensusInfo = new ChainInitializationConsensusInfo + InitialConsensusData = new MinerListWithRoundNumber { - InitialConsensusData = new MinerListWithRoundNumber + MinerList = new MinerList { - MinerList = new MinerList() + Pubkeys = { - Pubkeys = - { - SampleAccount.Accounts.Take(3) - .Select(a => ByteString.CopyFrom(a.KeyPair.PublicKey)) - } + SampleAccount.Accounts.Take(3) + .Select(a => ByteString.CopyFrom(a.KeyPair.PublicKey)) } - }.ToByteString() - }, - CreationHeightOnParentChain = _chainInitializationOptions.CreationHeightOnParentChain, - CreationTimestamp = TimestampHelper.GetUtcNow(), - NativeTokenInfoData = new TokenInfo + } + }.ToByteString() + }, + CreationHeightOnParentChain = _chainInitializationOptions.CreationHeightOnParentChain, + CreationTimestamp = TimestampHelper.GetUtcNow(), + NativeTokenInfoData = new TokenInfo + { + Symbol = "ELF", + TokenName = "ELF", + Decimals = 8, + TotalSupply = 100_000_000_000_000_000, + Issuer = address, + IssueChainId = ParentChainId + }.ToByteString(), + ParentChainTokenContractAddress = _chainInitializationOptions.RegisterParentChainTokenContractAddress + ? _chainInitializationOptions.ParentChainTokenContractAddress + : null, + ResourceTokenInfo = new ResourceTokenInfo(), + ChainPrimaryTokenInfo = new ChainPrimaryTokenInfo + { + ChainPrimaryTokenData = new TokenInfo { - Symbol = "ELF", - TokenName = "ELF", - Decimals = 8, - TotalSupply = 100_000_000_000_000_000, + Decimals = 2, + IsBurnable = true, Issuer = address, - IssueChainId = ParentChainId, - }.ToByteString(), - ParentChainTokenContractAddress = _chainInitializationOptions.RegisterParentChainTokenContractAddress - ? _chainInitializationOptions.ParentChainTokenContractAddress - : null, - ResourceTokenInfo = new ResourceTokenInfo(), - ChainPrimaryTokenInfo = new ChainPrimaryTokenInfo - { - ChainPrimaryTokenData = new TokenInfo - { - Decimals = 2, - IsBurnable = true, - Issuer = address, - TotalSupply = 1_000_000_000, - Symbol = _chainInitializationOptions.Symbol, - TokenName = "TEST", - IssueChainId = _chainInitializationOptions.ChainId - }.ToByteString() - } - }); - } - - + TotalSupply = 1_000_000_000, + Symbol = _chainInitializationOptions.Symbol, + TokenName = "TEST", + IssueChainId = _chainInitializationOptions.ChainId + }.ToByteString() + } + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs index 92448a0717..e6f9791681 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs @@ -1,143 +1,136 @@ using System.Collections.Generic; -using System.Linq; -using AElf.Contracts.MultiToken; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class SideChainUnitTestTokenContractInitializationProvider : TokenContractInitializationProvider { - public class SideChainUnitTestTokenContractInitializationProvider : TokenContractInitializationProvider + private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + + public SideChainUnitTestTokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) : base( + tokenContractInitializationDataProvider) { - private readonly ITokenContractInitializationDataProvider _tokenContractInitializationDataProvider; + _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; + } - public SideChainUnitTestTokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider) : base( - tokenContractInitializationDataProvider) - { - _tokenContractInitializationDataProvider = tokenContractInitializationDataProvider; - } + public override List GetInitializeMethodList(byte[] contractCode) + { + var methodList = new List(); + var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); + var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); + var resourceTokenList = + TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); - public override List GetInitializeMethodList(byte[] contractCode) + // native token + methodList.Add(new ContractInitializationMethodCall { - var methodList = new List(); - var initializationData = _tokenContractInitializationDataProvider.GetContractInitializationData(); - var nativeTokenInfo = TokenInfo.Parser.ParseFrom(initializationData.NativeTokenInfoData); - var resourceTokenList = - TokenInfoList.Parser.ParseFrom(initializationData.ResourceTokenListData); + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + }); - // native token + // resource token + foreach (var resourceTokenInfo in resourceTokenList.Value) methodList.Add(new ContractInitializationMethodCall { MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(nativeTokenInfo).ToByteString() + Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() }); - // resource token - foreach (var resourceTokenInfo in resourceTokenList.Value) - { - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(resourceTokenInfo).ToByteString() - }); - } + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), + Params = new Empty().ToByteString() + }); + + if (initializationData.PrimaryTokenInfoData != null) + { + // primary token + var chainPrimaryTokenInfo = + TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), - Params = new Empty().ToByteString() + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = GenerateTokenCreateInput(chainPrimaryTokenInfo).ToByteString() }); - if (initializationData.PrimaryTokenInfoData != null) - { - // primary token - var chainPrimaryTokenInfo = - TokenInfo.Parser.ParseFrom(initializationData.PrimaryTokenInfoData); - + foreach (var issueStuff in initializationData.TokenInitialIssueList) methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = GenerateTokenCreateInput(chainPrimaryTokenInfo).ToByteString() - }); - - foreach (var issueStuff in initializationData.TokenInitialIssueList) - { - methodList.Add(new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), + Params = new IssueInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), - Params = new IssueInput - { - Symbol = chainPrimaryTokenInfo.Symbol, - Amount = issueStuff.Amount, - Memo = "Initial issue", - To = issueStuff.Address - }.ToByteString() - }); - } - - methodList.Add(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = chainPrimaryTokenInfo.Symbol + Symbol = chainPrimaryTokenInfo.Symbol, + Amount = issueStuff.Amount, + Memo = "Initial issue", + To = issueStuff.Address }.ToByteString() }); - } - else + + methodList.Add(new ContractInitializationMethodCall { - // set primary token with native token - methodList.Add(new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = nativeTokenInfo.Symbol - }.ToByteString() - }); - } - - // if (initializationData.RegisteredOtherTokenContractAddresses.Values.All(v=>v != null)) - // { - // methodList.Add(new ContractInitializationMethodCall - // { - // MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), - // Params = new InitializeFromParentChainInput - // { - // ResourceAmount = {initializationData.ResourceAmount}, - // RegisteredOtherTokenContractAddresses = - // { - // initializationData.RegisteredOtherTokenContractAddresses - // }, - // Creator = initializationData.Creator - // }.ToByteString() - // }); - // } - + Symbol = chainPrimaryTokenInfo.Symbol + }.ToByteString() + }); + } + else + { + // set primary token with native token methodList.Add(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeAuthorizedController), - Params = ByteString.Empty + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput + { + Symbol = nativeTokenInfo.Symbol + }.ToByteString() }); + } + // if (initializationData.RegisteredOtherTokenContractAddresses.Values.All(v=>v != null)) + // { + // methodList.Add(new ContractInitializationMethodCall + // { + // MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), + // Params = new InitializeFromParentChainInput + // { + // ResourceAmount = {initializationData.ResourceAmount}, + // RegisteredOtherTokenContractAddresses = + // { + // initializationData.RegisteredOtherTokenContractAddresses + // }, + // Creator = initializationData.Creator + // }.ToByteString() + // }); + // } + + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitializeAuthorizedController), + Params = ByteString.Empty + }); - return methodList; - } - private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo) + return methodList; + } + + private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo) + { + return new CreateInput { - return new CreateInput - { - Decimals = tokenInfo.Decimals, - IssueChainId = tokenInfo.IssueChainId, - Issuer = tokenInfo.Issuer, - IsBurnable = tokenInfo.IsBurnable, - Symbol = tokenInfo.Symbol, - TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply - }; - } + Decimals = tokenInfo.Decimals, + IssueChainId = tokenInfo.IssueChainId, + Issuer = tokenInfo.Issuer, + IsBurnable = tokenInfo.IsBurnable, + Symbol = tokenInfo.Symbol, + TokenName = tokenInfo.TokenName, + TotalSupply = tokenInfo.TotalSupply + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/TestTokenBalanceTransactionGenerator.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/TestTokenBalanceTransactionGenerator.cs index f773ed773a..f46828ae7b 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/TestTokenBalanceTransactionGenerator.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/TestTokenBalanceTransactionGenerator.cs @@ -5,22 +5,18 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class TestTokenBalanceTransactionGenerator : ISystemTransactionGenerator, ISingletonDependency { - public class TestTokenBalanceTransactionGenerator : ISystemTransactionGenerator, ISingletonDependency - { - public Func GenerateTransactionFunc { get; set; } + public Func GenerateTransactionFunc { get; set; } - public Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, Hash preBlockHash) - { - var res = new List(); - if (GenerateTransactionFunc == null) - { - return Task.FromResult(res); - } + public Task> GenerateTransactionsAsync(Address from, long preBlockHeight, Hash preBlockHash) + { + var res = new List(); + if (GenerateTransactionFunc == null) return Task.FromResult(res); - res.Add(GenerateTransactionFunc(from, preBlockHeight, preBlockHash)); - return Task.FromResult(res); - } + res.Add(GenerateTransactionFunc(from, preBlockHeight, preBlockHash)); + return Task.FromResult(res); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/MinerList.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/MinerList.cs index 2b5371bd69..ed9c3082b5 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/MinerList.cs @@ -4,45 +4,41 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round.cs index d6f2cd915c..40674e1974 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round.cs @@ -5,146 +5,134 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public long RoundId => + RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + + public bool IsEmpty => RoundId == 0; + + public Hash GetHash(bool isContainPreviousInValue = true) { - public long RoundId => - RealTimeMinersInformation.Values.Select(bpInfo => bpInfo.ExpectedMiningTime.Seconds).Sum(); + return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); + } - public bool IsEmpty => RoundId == 0; + /// + /// This method is only available when the miners of this round is more than 1. + /// + /// + public int GetMiningInterval() + { + if (RealTimeMinersInformation.Count == 1) + // Just appoint the mining interval for single miner. + return 4000; - public Hash GetHash(bool isContainPreviousInValue = true) - { - return HashHelper.ComputeFrom(GetCheckableRound(isContainPreviousInValue)); - } - - /// - /// This method is only available when the miners of this round is more than 1. - /// - /// - public int GetMiningInterval() - { - if (RealTimeMinersInformation.Count == 1) - { - // Just appoint the mining interval for single miner. - return 4000; - } - - var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) - .ToList(); - var distance = - (int) (firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - - firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) - .TotalMilliseconds; - return distance > 0 ? distance : -distance; - } + var firstTwoMiners = RealTimeMinersInformation.Values.Where(m => m.Order == 1 || m.Order == 2) + .ToList(); + var distance = + (int)(firstTwoMiners[1].ExpectedMiningTime.ToDateTime() - + firstTwoMiners[0].ExpectedMiningTime.ToDateTime()) + .TotalMilliseconds; + return distance > 0 ? distance : -distance; + } - public bool IsTimeSlotPassed(string publicKey, DateTime dateTime, - out MinerInRound minerInRound) - { - minerInRound = null; - var miningInterval = GetMiningInterval(); - if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; - minerInRound = RealTimeMinersInformation[publicKey]; - return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; - } + public bool IsTimeSlotPassed(string publicKey, DateTime dateTime, + out MinerInRound minerInRound) + { + minerInRound = null; + var miningInterval = GetMiningInterval(); + if (!RealTimeMinersInformation.ContainsKey(publicKey)) return false; + minerInRound = RealTimeMinersInformation[publicKey]; + return minerInRound.ExpectedMiningTime.ToDateTime().AddMilliseconds(miningInterval) <= dateTime; + } - /// - /// Actually the expected mining time of the miner whose order is 1. - /// - /// - public DateTime GetStartTime() - { - return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); - } + /// + /// Actually the expected mining time of the miner whose order is 1. + /// + /// + public DateTime GetStartTime() + { + return RealTimeMinersInformation.Values.First(m => m.Order == 1).ExpectedMiningTime.ToDateTime(); + } - /// - /// This method for now is able to handle the situation of a miner keeping offline so many rounds, - /// by using missedRoundsCount. - /// - /// - /// - /// - /// - public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } - - var totalMilliseconds = TotalMilliseconds(miningInterval); - return GetStartTime().AddMilliseconds(totalMilliseconds) - // Arrange an ending time if this node missed so many rounds. - .AddMilliseconds(missedRoundsCount * totalMilliseconds) - .ToTimestamp(); - } + /// + /// This method for now is able to handle the situation of a miner keeping offline so many rounds, + /// by using missedRoundsCount. + /// + /// + /// + /// + /// + public Timestamp GetExpectedEndTime(int missedRoundsCount = 0, int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - /// - /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer - /// produce a block to terminate current round and confirm the mining order of next round. - /// So totally, the time of one round is: - /// MiningInterval * MinersCount + MiningInterval. - /// - /// - /// - public int TotalMilliseconds(int miningInterval = 0) - { - if (miningInterval == 0) - { - miningInterval = GetMiningInterval(); - } + var totalMilliseconds = TotalMilliseconds(miningInterval); + return GetStartTime().AddMilliseconds(totalMilliseconds) + // Arrange an ending time if this node missed so many rounds. + .AddMilliseconds(missedRoundsCount * totalMilliseconds) + .ToTimestamp(); + } - return RealTimeMinersInformation.Count * miningInterval + miningInterval; - } - - public MinerInRound GetExtraBlockProducerInformation() - { - return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; - } - - public DateTime GetExtraBlockMiningTime() - { - return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value - .ExpectedMiningTime.ToDateTime() - .AddMilliseconds(GetMiningInterval()); - } + /// + /// In current AElf Consensus design, each miner produce his block in one time slot, then the extra block producer + /// produce a block to terminate current round and confirm the mining order of next round. + /// So totally, the time of one round is: + /// MiningInterval * MinersCount + MiningInterval. + /// + /// + /// + public int TotalMilliseconds(int miningInterval = 0) + { + if (miningInterval == 0) miningInterval = GetMiningInterval(); - public long GetMinedBlocks() - { - return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); - } + return RealTimeMinersInformation.Count * miningInterval + miningInterval; + } + + public MinerInRound GetExtraBlockProducerInformation() + { + return RealTimeMinersInformation.First(bp => bp.Value.IsExtraBlockProducer).Value; + } + + public DateTime GetExtraBlockMiningTime() + { + return RealTimeMinersInformation.OrderBy(m => m.Value.ExpectedMiningTime.ToDateTime()).Last().Value + .ExpectedMiningTime.ToDateTime() + .AddMilliseconds(GetMiningInterval()); + } + + public long GetMinedBlocks() + { + return RealTimeMinersInformation.Values.Sum(minerInRound => minerInRound.ProducedBlocks); + } - private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + private byte[] GetCheckableRound(bool isContainPreviousInValue = true) + { + var minersInformation = new Dictionary(); + foreach (var minerInRound in RealTimeMinersInformation.Clone()) { - var minersInformation = new Dictionary(); - foreach (var minerInRound in RealTimeMinersInformation.Clone()) - { - var checkableMinerInRound = minerInRound.Value.Clone(); - checkableMinerInRound.EncryptedPieces.Clear(); - checkableMinerInRound.ActualMiningTimes.Clear(); - if (!isContainPreviousInValue) - { - checkableMinerInRound.PreviousInValue = Hash.Empty; - } - - minersInformation.Add(minerInRound.Key, checkableMinerInRound); - } - - var checkableRound = new Round - { - RoundNumber = RoundNumber, - TermNumber = TermNumber, - RealTimeMinersInformation = {minersInformation}, - BlockchainAge = BlockchainAge - }; - return checkableRound.ToByteArray(); + var checkableMinerInRound = minerInRound.Value.Clone(); + checkableMinerInRound.EncryptedPieces.Clear(); + checkableMinerInRound.ActualMiningTimes.Clear(); + if (!isContainPreviousInValue) checkableMinerInRound.PreviousInValue = Hash.Empty; + + minersInformation.Add(minerInRound.Key, checkableMinerInRound); } - - private static int GetAbsModulus(long longValue, int intValue) + + var checkableRound = new Round { - return Math.Abs((int) longValue % intValue); - } + RoundNumber = RoundNumber, + TermNumber = TermNumber, + RealTimeMinersInformation = { minersInformation }, + BlockchainAge = BlockchainAge + }; + return checkableRound.ToByteArray(); + } + + private static int GetAbsModulus(long longValue, int intValue) + { + return Math.Abs((int)longValue % intValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs index b416a4047d..34830558d0 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs @@ -3,107 +3,96 @@ using AElf.CSharp.Core; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class Round { - internal partial class Round + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + out Round nextRound) { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound) - { - nextRound = new Round(); + nextRound = new Round(); - var minersMinedCurrentRound = GetMinedMiners(); - var minersNotMinedCurrentRound = GetNotMinedMiners(); - var minersCount = RealTimeMinersInformation.Count; + var minersMinedCurrentRound = GetMinedMiners(); + var minersNotMinedCurrentRound = GetNotMinedMiners(); + var minersCount = RealTimeMinersInformation.Count; - var miningInterval = GetMiningInterval(); - nextRound.RoundNumber = RoundNumber + 1; - nextRound.TermNumber = TermNumber; - if (RoundNumber == 1) - { - nextRound.BlockchainAge = 1; - } - else - { - nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - } + var miningInterval = GetMiningInterval(); + nextRound.RoundNumber = RoundNumber + 1; + nextRound.TermNumber = TermNumber; + if (RoundNumber == 1) + nextRound.BlockchainAge = 1; + else + nextRound.BlockchainAge = (currentBlockTimestamp - blockchainStartTimestamp).Seconds; - // Set next round miners' information of miners who successfully mined during this round. - foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + // Set next round miners' information of miners who successfully mined during this round. + foreach (var minerInRound in minersMinedCurrentRound.OrderBy(m => m.FinalOrderOfNextRound)) + { + var order = minerInRound.FinalOrderOfNextRound; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = minerInRound.FinalOrderOfNextRound; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minerInRound.Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots - }; - } + Pubkey = minerInRound.Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + }; + } - // Set miners' information of miners missed their time slot in current round. - var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); - var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); - for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + // Set miners' information of miners missed their time slot in current round. + var occupiedOrders = minersMinedCurrentRound.Select(m => m.FinalOrderOfNextRound).ToList(); + var ableOrders = Enumerable.Range(1, minersCount).Where(i => !occupiedOrders.Contains(i)).ToList(); + for (var i = 0; i < minersNotMinedCurrentRound.Count; i++) + { + var order = ableOrders[i]; + var minerInRound = minersNotMinedCurrentRound[i]; + nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound { - var order = ableOrders[i]; - var minerInRound = minersNotMinedCurrentRound[i]; - nextRound.RealTimeMinersInformation[minerInRound.Pubkey] = new MinerInRound - { - Pubkey = minersNotMinedCurrentRound[i].Pubkey, - Order = order, - ExpectedMiningTime = currentBlockTimestamp + - new Duration {Seconds = miningInterval.Div(1000).Mul(order)}, - ProducedBlocks = minerInRound.ProducedBlocks, - MissedTimeSlots = minerInRound.MissedTimeSlots + 1 - }; - } + Pubkey = minersNotMinedCurrentRound[i].Pubkey, + Order = order, + ExpectedMiningTime = currentBlockTimestamp + + new Duration { Seconds = miningInterval.Div(1000).Mul(order) }, + ProducedBlocks = minerInRound.ProducedBlocks, + MissedTimeSlots = minerInRound.MissedTimeSlots + 1 + }; + } - // Calculate extra block producer order and set the producer. - var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); - var expectedExtraBlockProducer = - nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); - if (expectedExtraBlockProducer == null) - { - nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; - } - else - { - expectedExtraBlockProducer.IsExtraBlockProducer = true; - } + // Calculate extra block producer order and set the producer. + var extraBlockProducerOrder = CalculateNextExtraBlockProducerOrder(); + var expectedExtraBlockProducer = + nextRound.RealTimeMinersInformation.Values.FirstOrDefault(m => m.Order == extraBlockProducerOrder); + if (expectedExtraBlockProducer == null) + nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; + else + expectedExtraBlockProducer.IsExtraBlockProducer = true; - return true; - } + return true; + } - private int CalculateNextExtraBlockProducerOrder() - { - var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) - .FirstOrDefault(m => m.Signature != null); - if (firstPlaceInfo == null) - { - // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. - return 1; - } + private int CalculateNextExtraBlockProducerOrder() + { + var firstPlaceInfo = RealTimeMinersInformation.Values.OrderBy(m => m.Order) + .FirstOrDefault(m => m.Signature != null); + if (firstPlaceInfo == null) + // If no miner produce block during this round, just appoint the first miner to be the extra block producer of next round. + return 1; - var signature = firstPlaceInfo.Signature; - var sigNum = signature.ToByteArray().ToInt64(true); - var blockProducerCount = RealTimeMinersInformation.Count; - var order = GetAbsModulus(sigNum, blockProducerCount) + 1; - return order; - } + var signature = firstPlaceInfo.Signature; + var sigNum = signature.ToByteArray().ToInt64(true); + var blockProducerCount = RealTimeMinersInformation.Count; + var order = GetAbsModulus(sigNum, blockProducerCount) + 1; + return order; + } - public List GetMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); - } + public List GetMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound != 0).ToList(); + } - public List GetNotMinedMiners() - { - // For now only this implementation can support test cases. - return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); - } + public List GetNotMinedMiners() + { + // For now only this implementation can support test cases. + return RealTimeMinersInformation.Values.Where(m => m.SupposedOrderOfNextRound == 0).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs index 8bf5553083..b9df291357 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using AElf.Contracts.MultiToken; using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; @@ -10,67 +9,66 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Options; -namespace AElf.Contracts.MultiToken +namespace AElf.Contracts.MultiToken; + +public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider { - public class UnitTestTokenContractInitializationProvider : TokenContractInitializationProvider - { - private readonly EconomicOptions _economicOptions; - private readonly ConsensusOptions _consensusOptions; + private readonly ConsensusOptions _consensusOptions; + private readonly EconomicOptions _economicOptions; - public UnitTestTokenContractInitializationProvider( - ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, - IOptionsSnapshot economicOptions,IOptionsSnapshot consensusOptions) : base( - tokenContractInitializationDataProvider) - { - _economicOptions = economicOptions.Value; - _consensusOptions = consensusOptions.Value; - } + public UnitTestTokenContractInitializationProvider( + ITokenContractInitializationDataProvider tokenContractInitializationDataProvider, + IOptionsSnapshot economicOptions, IOptionsSnapshot consensusOptions) : base( + tokenContractInitializationDataProvider) + { + _economicOptions = economicOptions.Value; + _consensusOptions = consensusOptions.Value; + } - public override List GetInitializeMethodList(byte[] contractCode) + public override List GetInitializeMethodList(byte[] contractCode) + { + var address = Address.FromPublicKey( + ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); + var list = new List { - var address = Address.FromPublicKey( - ByteArrayHelper.HexStringToByteArray(_consensusOptions.InitialMinerList[0])); - var list = new List + new() { - new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), - Params = new CreateInput - { - Decimals = _economicOptions.Decimals, - Issuer = address, - IsBurnable = _economicOptions.IsBurnable, - Symbol = _economicOptions.Symbol, - TokenName = _economicOptions.TokenName, - TotalSupply = _economicOptions.TotalSupply, - }.ToByteString(), - }, - new ContractInitializationMethodCall + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Create), + Params = new CreateInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), - Params = new IssueInput - { - Symbol = _economicOptions.Symbol, - Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), - To = address, - Memo = "Issue native token" - }.ToByteString() - }, - new ContractInitializationMethodCall + Decimals = _economicOptions.Decimals, + Issuer = address, + IsBurnable = _economicOptions.IsBurnable, + Symbol = _economicOptions.Symbol, + TokenName = _economicOptions.TokenName, + TotalSupply = _economicOptions.TotalSupply + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Issue), + Params = new IssueInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), - Params = new SetPrimaryTokenSymbolInput - { - Symbol = _economicOptions.Symbol - }.ToByteString() - }, - new ContractInitializationMethodCall + Symbol = _economicOptions.Symbol, + Amount = Convert.ToInt64(_economicOptions.TotalSupply * (1 - _economicOptions.DividendPoolRatio)), + To = address, + Memo = "Issue native token" + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.SetPrimaryTokenSymbol), + Params = new SetPrimaryTokenSymbolInput { - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), - Params = new Empty().ToByteString() - } - }; - return list; - } + Symbol = _economicOptions.Symbol + }.ToByteString() + }, + new() + { + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.InitialCoefficients), + Params = new Empty().ToByteString() + } + }; + return list; } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/AElf.Contracts.NFT.Tests.csproj b/test/AElf.Contracts.NFT.Tests/AElf.Contracts.NFT.Tests.csproj index 6d8ff43d47..157421fac0 100644 --- a/test/AElf.Contracts.NFT.Tests/AElf.Contracts.NFT.Tests.csproj +++ b/test/AElf.Contracts.NFT.Tests/AElf.Contracts.NFT.Tests.csproj @@ -6,7 +6,7 @@ false - + false Contract @@ -62,7 +62,7 @@ Contract PreserveNewest - + false Contract @@ -75,12 +75,12 @@ - - - - - - + + + + + + @@ -156,6 +156,6 @@ Protobuf\Proto\base\acs11.proto - - + + diff --git a/test/AElf.Contracts.NFT.Tests/NFTContractInitializationProvider.cs b/test/AElf.Contracts.NFT.Tests/NFTContractInitializationProvider.cs index 245ad1740d..68b4831a04 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTContractInitializationProvider.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTContractInitializationProvider.cs @@ -3,16 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public class NFTContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class NFTContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFT"); - public string ContractCodeName { get; } = "AElf.Contracts.NFT"; + public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFT"); + public string ContractCodeName { get; } = "AElf.Contracts.NFT"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTContractTestAElfModule.cs b/test/AElf.Contracts.NFT.Tests/NFTContractTestAElfModule.cs index e3328b9ba7..af15e3de27 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTContractTestAElfModule.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTContractTestAElfModule.cs @@ -10,19 +10,18 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +[DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), + typeof(TokenKernelAElfModule), + typeof(GovernmentSystemAElfModule), + typeof(EconomicSystemAElfModule), + typeof(MultiTokenContractTestAElfModule))] +public class NFTContractTestAElfModule : AbpModule { - [DependsOn(typeof(ContractTestModule), typeof(AEDPoSAElfModule), - typeof(TokenKernelAElfModule), - typeof(GovernmentSystemAElfModule), - typeof(EconomicSystemAElfModule), - typeof(MultiTokenContractTestAElfModule))] - public class NFTContractTestAElfModule : AbpModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - var contractCodeProvider = context.ServiceProvider.GetService(); - contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); - } + var contractCodeProvider = context.ServiceProvider.GetService(); + contractCodeProvider.Codes = ContractsDeployer.GetContractCodes(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTContractTestBase.cs b/test/AElf.Contracts.NFT.Tests/NFTContractTestBase.cs index 28063490a5..8277d2be9a 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTContractTestBase.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTContractTestBase.cs @@ -4,175 +4,170 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.NFTMarket; using AElf.Contracts.NFTMinter; -using AElf.Standards.ACS2; using AElf.Contracts.Parliament; -using AElf.Contracts.TestContract.BasicFunction; -using AElf.Cryptography.ECDSA; -using AElf.Types; -using AElf.Contracts.Treasury; -using AElf.Contracts.TokenConverter; using AElf.ContractTestBase.ContractTestKit; +using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Standards.ACS3; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public class NFTContractTestBase : ContractTestBase { - public class NFTContractTestBase : ContractTestBase + protected const long Amount = 100; + internal TokenContractImplContainer.TokenContractImplStub NFTBuyer2TokenContractStub; + internal TokenContractImplContainer.TokenContractImplStub NFTBuyerTokenContractStub; + + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; + + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; + internal TokenContractImplContainer.TokenContractImplStub UserTokenContractStub; + + public NFTContractTestBase() { - protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; - protected Address DefaultAddress => Accounts[0].Address; - protected ECKeyPair MinterKeyPair => Accounts[1].KeyPair; - protected Address MinterAddress => Accounts[1].Address; - - protected ECKeyPair User1KeyPair => Accounts[10].KeyPair; - protected ECKeyPair User2KeyPair => Accounts[11].KeyPair; - protected ECKeyPair User3KeyPair => Accounts[14].KeyPair; - protected Address User1Address => Accounts[10].Address; - protected Address User2Address => Accounts[11].Address; - protected Address User3Address => Accounts[14].Address; - protected ECKeyPair MarketServiceFeeReceiverKeyPair => Accounts[12].KeyPair; - protected Address MarketServiceFeeReceiverAddress => Accounts[12].Address; - - protected const long Amount = 100; - - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub; - internal TokenContractImplContainer.TokenContractImplStub UserTokenContractStub; - internal TokenContractImplContainer.TokenContractImplStub NFTBuyerTokenContractStub; - internal TokenContractImplContainer.TokenContractImplStub NFTBuyer2TokenContractStub; - - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; - - protected Hash NFTContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFT"); - protected Hash NFTMarketContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"); - protected Hash NFTMinterContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter"); - protected Address NFTContractAddress { get; set; } - protected Address NFTMarketContractAddress { get; set; } - protected Address NFTMinterContractAddress { get; set; } - internal NFTContractContainer.NFTContractStub NFTContractStub { get; set; } - internal NFTContractContainer.NFTContractStub MinterNFTContractStub { get; set; } - - internal NFTMinterContractContainer.NFTMinterContractStub CreatorNFTMinterContractStub { get; set; } - internal NFTMinterContractContainer.NFTMinterContractStub UserNFTMinterContractStub { get; set; } - - internal NFTMarketContractContainer.NFTMarketContractStub SellerNFTMarketContractStub { get; set; } - internal NFTMarketContractContainer.NFTMarketContractStub BuyerNFTMarketContractStub { get; set; } - internal NFTMarketContractContainer.NFTMarketContractStub Buyer2NFTMarketContractStub { get; set; } - internal NFTMarketContractContainer.NFTMarketContractStub CreatorNFTMarketContractStub { get; set; } - internal NFTMarketContractContainer.NFTMarketContractStub AdminNFTMarketContractStub { get; set; } - - public NFTContractTestBase() - { - TokenContractStub = - GetTester(TokenContractAddress, DefaultKeyPair); - UserTokenContractStub = - GetTester(TokenContractAddress, User1KeyPair); - NFTBuyerTokenContractStub = - GetTester(TokenContractAddress, User2KeyPair); - NFTBuyer2TokenContractStub = - GetTester(TokenContractAddress, User3KeyPair); - - NFTContractAddress = SystemContractAddresses[NFTContractName]; - NFTMarketContractAddress = SystemContractAddresses[NFTMarketContractName]; - NFTMinterContractAddress = SystemContractAddresses[NFTMinterContractName]; - - NFTContractStub = GetTester(NFTContractAddress, DefaultKeyPair); - MinterNFTContractStub = GetTester(NFTContractAddress, MinterKeyPair); - - CreatorNFTMinterContractStub = - GetTester(NFTMinterContractAddress, DefaultKeyPair); - UserNFTMinterContractStub = - GetTester(NFTMinterContractAddress, User1KeyPair); - - SellerNFTMarketContractStub = - GetTester(NFTMarketContractAddress, DefaultKeyPair); - BuyerNFTMarketContractStub = - GetTester(NFTMarketContractAddress, User2KeyPair); - Buyer2NFTMarketContractStub = - GetTester(NFTMarketContractAddress, User3KeyPair); - CreatorNFTMarketContractStub = - GetTester(NFTMarketContractAddress, DefaultKeyPair); - AdminNFTMarketContractStub = - GetTester(NFTMarketContractAddress, DefaultKeyPair); - - ParliamentContractStub = GetTester( - ParliamentContractAddress, DefaultKeyPair); - - AsyncHelper.RunSync(CreateNativeTokenAsync); - AsyncHelper.RunSync(SetNFTContractAddress); - } + TokenContractStub = + GetTester(TokenContractAddress, DefaultKeyPair); + UserTokenContractStub = + GetTester(TokenContractAddress, User1KeyPair); + NFTBuyerTokenContractStub = + GetTester(TokenContractAddress, User2KeyPair); + NFTBuyer2TokenContractStub = + GetTester(TokenContractAddress, User3KeyPair); + + NFTContractAddress = SystemContractAddresses[NFTContractName]; + NFTMarketContractAddress = SystemContractAddresses[NFTMarketContractName]; + NFTMinterContractAddress = SystemContractAddresses[NFTMinterContractName]; + + NFTContractStub = GetTester(NFTContractAddress, DefaultKeyPair); + MinterNFTContractStub = GetTester(NFTContractAddress, MinterKeyPair); + + CreatorNFTMinterContractStub = + GetTester(NFTMinterContractAddress, DefaultKeyPair); + UserNFTMinterContractStub = + GetTester(NFTMinterContractAddress, User1KeyPair); + + SellerNFTMarketContractStub = + GetTester(NFTMarketContractAddress, DefaultKeyPair); + BuyerNFTMarketContractStub = + GetTester(NFTMarketContractAddress, User2KeyPair); + Buyer2NFTMarketContractStub = + GetTester(NFTMarketContractAddress, User3KeyPair); + CreatorNFTMarketContractStub = + GetTester(NFTMarketContractAddress, DefaultKeyPair); + AdminNFTMarketContractStub = + GetTester(NFTMarketContractAddress, DefaultKeyPair); + + ParliamentContractStub = GetTester( + ParliamentContractAddress, DefaultKeyPair); + + AsyncHelper.RunSync(CreateNativeTokenAsync); + AsyncHelper.RunSync(SetNFTContractAddress); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + protected ECKeyPair DefaultKeyPair => Accounts[0].KeyPair; + protected Address DefaultAddress => Accounts[0].Address; + protected ECKeyPair MinterKeyPair => Accounts[1].KeyPair; + protected Address MinterAddress => Accounts[1].Address; + + protected ECKeyPair User1KeyPair => Accounts[10].KeyPair; + protected ECKeyPair User2KeyPair => Accounts[11].KeyPair; + protected ECKeyPair User3KeyPair => Accounts[14].KeyPair; + protected Address User1Address => Accounts[10].Address; + protected Address User2Address => Accounts[11].Address; + protected Address User3Address => Accounts[14].Address; + protected ECKeyPair MarketServiceFeeReceiverKeyPair => Accounts[12].KeyPair; + protected Address MarketServiceFeeReceiverAddress => Accounts[12].Address; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + + protected Hash NFTContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFT"); + protected Hash NFTMarketContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"); + protected Hash NFTMinterContractName => HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter"); + protected Address NFTContractAddress { get; set; } + protected Address NFTMarketContractAddress { get; set; } + protected Address NFTMinterContractAddress { get; set; } + internal NFTContractContainer.NFTContractStub NFTContractStub { get; set; } + internal NFTContractContainer.NFTContractStub MinterNFTContractStub { get; set; } + + internal NFTMinterContractContainer.NFTMinterContractStub CreatorNFTMinterContractStub { get; set; } + internal NFTMinterContractContainer.NFTMinterContractStub UserNFTMinterContractStub { get; set; } + + internal NFTMarketContractContainer.NFTMarketContractStub SellerNFTMarketContractStub { get; set; } + internal NFTMarketContractContainer.NFTMarketContractStub BuyerNFTMarketContractStub { get; set; } + internal NFTMarketContractContainer.NFTMarketContractStub Buyer2NFTMarketContractStub { get; set; } + internal NFTMarketContractContainer.NFTMarketContractStub CreatorNFTMarketContractStub { get; set; } + internal NFTMarketContractContainer.NFTMarketContractStub AdminNFTMarketContractStub { get; set; } + + private TokenInfo NativeTokenInfo => new() + { + Symbol = "ELF", + TokenName = "Native token", + TotalSupply = 10_00000000_00000000, + Decimals = 8, + IsBurnable = true, + Issuer = DefaultAddress + }; + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - private async Task CreateNativeTokenAsync() + private async Task CreateNativeTokenAsync() + { + await TokenContractStub.Create.SendAsync(new MultiToken.CreateInput { - await TokenContractStub.Create.SendAsync(new MultiToken.CreateInput() - { - Symbol = NativeTokenInfo.Symbol, - TokenName = NativeTokenInfo.TokenName, - TotalSupply = NativeTokenInfo.TotalSupply, - Decimals = NativeTokenInfo.Decimals, - Issuer = NativeTokenInfo.Issuer, - IsBurnable = NativeTokenInfo.IsBurnable - }); - } + Symbol = NativeTokenInfo.Symbol, + TokenName = NativeTokenInfo.TokenName, + TotalSupply = NativeTokenInfo.TotalSupply, + Decimals = NativeTokenInfo.Decimals, + Issuer = NativeTokenInfo.Issuer, + IsBurnable = NativeTokenInfo.IsBurnable + }); + } + + private async Task SetNFTContractAddress() + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliament, nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), + NFTContractAddress); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + } - private TokenInfo NativeTokenInfo => new TokenInfo + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - Symbol = "ELF", - TokenName = "Native token", - TotalSupply = 10_00000000_00000000, - Decimals = 8, - IsBurnable = true, - Issuer = DefaultAddress + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress }; - private async Task SetNFTContractAddress() - { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultParliament, nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), - NFTContractAddress); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - } + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) - { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; - - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; - - return proposalId; - } + return proposalId; + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - await tester.Approve.SendAsync(proposalId); - } + var tester = GetParliamentContractTester(bp); + await tester.Approve.SendAsync(proposalId); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTContractTests.cs b/test/AElf.Contracts.NFT.Tests/NFTContractTests.cs index ea366786b7..09d22dd875 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTContractTests.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTContractTests.cs @@ -5,271 +5,270 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests : NFTContractTestBase { - public partial class NFTContractTests : NFTContractTestBase - { - private const string BaseUri = "ipfs://aelf/"; + private const string BaseUri = "ipfs://aelf/"; - [Fact] - public async Task CreateTest() + [Fact] + public async Task CreateTest() + { + await TokenContractStub.Issue.SendAsync(new IssueInput { - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = 1_00000000_00000000, - To = DefaultAddress, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = 1_00000000_00000000, - To = MinterAddress, - }); + Symbol = "ELF", + Amount = 1_00000000_00000000, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = 1_00000000_00000000, + To = MinterAddress + }); - var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + { + BaseUri = BaseUri, + Creator = DefaultAddress, + IsBurnable = true, + Metadata = new Metadata { - BaseUri = BaseUri, - Creator = DefaultAddress, - IsBurnable = true, - Metadata = new Metadata + Value = { - Value = - { - {"Description", "Stands for the human race."} - } - }, - NftType = NFTType.VirtualWorlds.ToString(), - ProtocolName = "HUMAN", - TotalSupply = 1_000_000_000 // One billion - }); - var symbol = executionResult.Output.Value; - - symbol.Length.ShouldBe(11); - - var protocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue - { - Value = symbol - }); - protocolInfo.Symbol.ShouldBe(symbol); - protocolInfo.Metadata.Value.ShouldContainKey("Description"); - protocolInfo.Creator.ShouldBe(DefaultAddress); - protocolInfo.NftType.ShouldBe(NFTType.VirtualWorlds.ToString()); - protocolInfo.TotalSupply.ShouldBe(1_000_000_000); - - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = symbol - }); + { "Description", "Stands for the human race." } + } + }, + NftType = NFTType.VirtualWorlds.ToString(), + ProtocolName = "HUMAN", + TotalSupply = 1_000_000_000 // One billion + }); + var symbol = executionResult.Output.Value; - tokenInfo.Decimals.ShouldBe(0); - tokenInfo.Symbol.ShouldBe(symbol); - tokenInfo.Issuer.ShouldBe(DefaultAddress); - tokenInfo.ExternalInfo.Value["Description"].ShouldBe("Stands for the human race."); - tokenInfo.ExternalInfo.Value["aelf_nft_type"].ShouldBe("VirtualWorlds"); - tokenInfo.ExternalInfo.Value["aelf_nft_base_uri"].ShouldBe(BaseUri); + symbol.Length.ShouldBe(11); - return symbol; - } + var protocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue + { + Value = symbol + }); + protocolInfo.Symbol.ShouldBe(symbol); + protocolInfo.Metadata.Value.ShouldContainKey("Description"); + protocolInfo.Creator.ShouldBe(DefaultAddress); + protocolInfo.NftType.ShouldBe(NFTType.VirtualWorlds.ToString()); + protocolInfo.TotalSupply.ShouldBe(1_000_000_000); - [Fact] - public async Task<(string, Hash)> MintTest() + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var symbol = await CreateTest(); - await AddMinterAsync(symbol); + Symbol = symbol + }); - var tokenHash = (await MinterNFTContractStub.Mint.SendAsync(new MintInput - { - Symbol = symbol, - Alias = "could be anything", - Metadata = new Metadata - { - Value = - { - {"Special Property", "A Value"} - } - }, - Owner = DefaultAddress, - Uri = $"{BaseUri}foo" - })).Output; + tokenInfo.Decimals.ShouldBe(0); + tokenInfo.Symbol.ShouldBe(symbol); + tokenInfo.Issuer.ShouldBe(DefaultAddress); + tokenInfo.ExternalInfo.Value["Description"].ShouldBe("Stands for the human race."); + tokenInfo.ExternalInfo.Value["aelf_nft_type"].ShouldBe("VirtualWorlds"); + tokenInfo.ExternalInfo.Value["aelf_nft_base_uri"].ShouldBe(BaseUri); - { - var nftInfo = await NFTContractStub.GetNFTInfoByTokenHash.CallAsync(tokenHash); - nftInfo.Creator.ShouldBe(DefaultAddress); - nftInfo.Minters.ShouldContain(MinterAddress); - } + return symbol; + } - { - var nftInfo = await NFTContractStub.GetNFTInfo.CallAsync(new GetNFTInfoInput - { - Symbol = symbol, - TokenId = 1 - }); - nftInfo.Creator.ShouldBe(DefaultAddress); - nftInfo.Minters.ShouldContain(MinterAddress); - } + [Fact] + public async Task<(string, Hash)> MintTest() + { + var symbol = await CreateTest(); + await AddMinterAsync(symbol); + var tokenHash = (await MinterNFTContractStub.Mint.SendAsync(new MintInput + { + Symbol = symbol, + Alias = "could be anything", + Metadata = new Metadata { - var protocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue + Value = { - Value = symbol - }); - protocolInfo.Metadata.Value.ShouldNotContainKey("Special Property"); - } + { "Special Property", "A Value" } + } + }, + Owner = DefaultAddress, + Uri = $"{BaseUri}foo" + })).Output; - return (symbol, tokenHash); + { + var nftInfo = await NFTContractStub.GetNFTInfoByTokenHash.CallAsync(tokenHash); + nftInfo.Creator.ShouldBe(DefaultAddress); + nftInfo.Minters.ShouldContain(MinterAddress); } - [Fact(Skip = "Dup in TransferTest")] - public async Task MintMultiTokenTest() { - var symbol = await CreateTest(); - await AddMinterAsync(symbol); - - await MinterNFTContractStub.Mint.SendAsync(new MintInput + var nftInfo = await NFTContractStub.GetNFTInfo.CallAsync(new GetNFTInfoInput { Symbol = symbol, - Alias = "could be anything", - Metadata = new Metadata - { - Value = - { - {"Max Health Points", "0"}, - {"Max Mana Points", "0"}, - {"Skill Points", "0"}, - {"Level", "0"}, - {"Experience", "0"} - } - }, - Quantity = 100, - Uri = $"{BaseUri}foo" + TokenId = 1 }); - - return symbol; + nftInfo.Creator.ShouldBe(DefaultAddress); + nftInfo.Minters.ShouldContain(MinterAddress); } - [Fact] - public async Task TransferTest() { - var symbol = await MintMultiTokenTest(); - await MinterNFTContractStub.Transfer.SendAsync(new TransferInput + var protocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue { - To = User1Address, - Symbol = symbol, - TokenId = 1, - Amount = 10 + Value = symbol }); + protocolInfo.Metadata.Value.ShouldNotContainKey("Special Property"); + } - { - var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = symbol, - TokenId = 1 - })).Balance; - balance.ShouldBe(10); - } + return (symbol, tokenHash); + } + + [Fact(Skip = "Dup in TransferTest")] + public async Task MintMultiTokenTest() + { + var symbol = await CreateTest(); + await AddMinterAsync(symbol); + await MinterNFTContractStub.Mint.SendAsync(new MintInput + { + Symbol = symbol, + Alias = "could be anything", + Metadata = new Metadata { - var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput + Value = { - Owner = MinterAddress, - Symbol = symbol, - TokenId = 1 - })).Balance; - balance.ShouldBe(90); - } + { "Max Health Points", "0" }, + { "Max Mana Points", "0" }, + { "Skill Points", "0" }, + { "Level", "0" }, + { "Experience", "0" } + } + }, + Quantity = 100, + Uri = $"{BaseUri}foo" + }); - return symbol; - } + return symbol; + } - [Fact] - public async Task ApproveTest() + [Fact] + public async Task TransferTest() + { + var symbol = await MintMultiTokenTest(); + await MinterNFTContractStub.Transfer.SendAsync(new TransferInput { - var symbol = await TransferTest(); + To = User1Address, + Symbol = symbol, + TokenId = 1, + Amount = 10 + }); - await MinterNFTContractStub.Approve.SendAsync(new ApproveInput + { + var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - Spender = DefaultAddress, + Owner = User1Address, Symbol = symbol, - TokenId = 1, - Amount = 10 - }); + TokenId = 1 + })).Balance; + balance.ShouldBe(10); + } + { + var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - var allowance = (await NFTContractStub.GetAllowance.CallAsync(new GetAllowanceInput - { - Owner = MinterAddress, - Spender = DefaultAddress, - Symbol = symbol, - TokenId = 1 - })).Allowance; - allowance.ShouldBe(10); - } + Owner = MinterAddress, + Symbol = symbol, + TokenId = 1 + })).Balance; + balance.ShouldBe(90); + } - await NFTContractStub.TransferFrom.SendAsync(new TransferFromInput + return symbol; + } + + [Fact] + public async Task ApproveTest() + { + var symbol = await TransferTest(); + + await MinterNFTContractStub.Approve.SendAsync(new ApproveInput + { + Spender = DefaultAddress, + Symbol = symbol, + TokenId = 1, + Amount = 10 + }); + + { + var allowance = (await NFTContractStub.GetAllowance.CallAsync(new GetAllowanceInput { - To = User1Address, + Owner = MinterAddress, + Spender = DefaultAddress, Symbol = symbol, - TokenId = 1, - Amount = 9, - From = MinterAddress - }); + TokenId = 1 + })).Allowance; + allowance.ShouldBe(10); + } + + await NFTContractStub.TransferFrom.SendAsync(new TransferFromInput + { + To = User1Address, + Symbol = symbol, + TokenId = 1, + Amount = 9, + From = MinterAddress + }); + { + var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await MinterNFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = User1Address, - Symbol = symbol, - TokenId = 1 - })).Balance; - balance.ShouldBe(19); - } + Owner = User1Address, + Symbol = symbol, + TokenId = 1 + })).Balance; + balance.ShouldBe(19); } + } + + [Fact] + public async Task AssembleTest() + { + var (symbol, tokenHash) = await MintTest(); - [Fact] - public async Task AssembleTest() + await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput { - var (symbol, tokenHash) = await MintTest(); + Spender = NFTContractAddress, + Symbol = "ELF", + Amount = long.MaxValue + }); - await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + await NFTContractStub.Assemble.SendAsync(new AssembleInput + { + Symbol = symbol, + AssembledNfts = new AssembledNfts { - Spender = NFTContractAddress, - Symbol = "ELF", - Amount = long.MaxValue - }); - - await NFTContractStub.Assemble.SendAsync(new AssembleInput + Value = { [tokenHash.ToHex()] = 1 } + }, + AssembledFts = new AssembledFts { - Symbol = symbol, - AssembledNfts = new AssembledNfts - { - Value = {[tokenHash.ToHex()] = 1} - }, - AssembledFts = new AssembledFts - { - Value = {["ELF"] = 100} - }, - Metadata = new Metadata + Value = { ["ELF"] = 100 } + }, + Metadata = new Metadata + { + Value = { - Value = - { - ["Advanced Property"] = "whatever" - } + ["Advanced Property"] = "whatever" } - }); - } + } + }); + } - private async Task AddMinterAsync(string symbol) + private async Task AddMinterAsync(string symbol) + { + await NFTContractStub.AddMinters.SendAsync(new AddMintersInput { - await NFTContractStub.AddMinters.SendAsync(new AddMintersInput + Symbol = symbol, + MinterList = new MinterList { - Symbol = symbol, - MinterList = new MinterList - { - Value = {MinterAddress} - } - }); - } + Value = { MinterAddress } + } + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMarketContractInitializationProvider.cs b/test/AElf.Contracts.NFT.Tests/NFTMarketContractInitializationProvider.cs index 7d0601701f..514ce533ca 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMarketContractInitializationProvider.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMarketContractInitializationProvider.cs @@ -3,15 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public class NFTMarketContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class NFTMarketContractInitializationProvider: IContractInitializationProvider, ITransientDependency + public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"); + public string ContractCodeName { get; } = "AElf.Contracts.NFTMarket"; + + public List GetInitializeMethodList(byte[] contractCode) { - public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFTMarket"); - public string ContractCodeName { get; }= "AElf.Contracts.NFTMarket"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests.cs b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests.cs index 7c8f5b82aa..1596d8fb41 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests.cs @@ -7,506 +7,505 @@ using Xunit; using StringList = AElf.Contracts.NFTMarket.StringList; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + private const long InitialELFAmount = 1_00000000_00000000; + + [Fact] + public async Task CreateArtistsTest() { - private const long InitialELFAmount = 1_00000000_00000000; + var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + { + ProtocolName = "aelf Art", + NftType = NFTType.Art.ToString(), + TotalSupply = 1000, + IsBurnable = false, + IsTokenIdReuse = false + }); + var symbol = executionResult.Output.Value; + + var nftProtocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue { Value = symbol }); + nftProtocolInfo.TotalSupply.ShouldBe(1000); + + return symbol; + } - [Fact] - public async Task CreateArtistsTest() + [Fact] + public async Task ListWithFixedPriceTest() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput { - var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput - { - ProtocolName = "aelf Art", - NftType = NFTType.Art.ToString(), - TotalSupply = 1000, - IsBurnable = false, - IsTokenIdReuse = false - }); - var symbol = executionResult.Output.Value; + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - var nftProtocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue {Value = symbol}); - nftProtocolInfo.TotalSupply.ShouldBe(1000); + var symbol = await MintBadgeTest(); - return symbol; - } - - [Fact] - public async Task ListWithFixedPriceTest() + await TokenContractStub.Issue.SendAsync(new IssueInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); - var symbol = await MintBadgeTest(); + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 233, + Amount = 100, + Spender = NFTMarketContractAddress + }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + Symbol = symbol, + TokenId = 233, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, - }); - - await NFTContractStub.Approve.SendAsync(new ApproveInput + Amount = 100_00000000 + }, + Duration = new ListDuration { - Symbol = symbol, - TokenId = 233, - Amount = 100, - Spender = NFTMarketContractAddress - }); + DurationHours = 24 + }, + Quantity = 1 + }); - await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + var listedNftInfo = (await SellerNFTMarketContractStub.GetListedNFTInfoList.CallAsync( + new GetListedNFTInfoListInput { Symbol = symbol, TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Duration = new ListDuration - { - DurationHours = 24 - }, - Quantity = 1 - }); + Owner = DefaultAddress + })).Value.First(); + listedNftInfo.Price.Symbol.ShouldBe("ELF"); + listedNftInfo.Price.Amount.ShouldBe(100_00000000); + listedNftInfo.Quantity.ShouldBe(1); + listedNftInfo.ListType.ShouldBe(ListType.FixedPrice); + listedNftInfo.Duration.StartTime.ShouldNotBeNull(); + listedNftInfo.Duration.DurationHours.ShouldBe(24); - var listedNftInfo = (await SellerNFTMarketContractStub.GetListedNFTInfoList.CallAsync( - new GetListedNFTInfoListInput + { + var executionResult = await SellerNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync( + new ListWithFixedPriceInput { Symbol = symbol, TokenId = 233, - Owner = DefaultAddress - })).Value.First(); - listedNftInfo.Price.Symbol.ShouldBe("ELF"); - listedNftInfo.Price.Amount.ShouldBe(100_00000000); - listedNftInfo.Quantity.ShouldBe(1); - listedNftInfo.ListType.ShouldBe(ListType.FixedPrice); - listedNftInfo.Duration.StartTime.ShouldNotBeNull(); - listedNftInfo.Duration.DurationHours.ShouldBe(24); + Price = new Price + { + Symbol = "ELF", + Amount = 100_00000000 + }, + Duration = new ListDuration + { + DurationHours = 24 + }, + Quantity = 1 + }); + executionResult.TransactionResult.Error.ShouldContain("Check sender NFT balance failed."); + } + + return symbol; + } + + [Fact] + public async Task DealWithFixedPriceTest() + { + var symbol = await ListWithFixedPriceTest(); + + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { - var executionResult = await SellerNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync( - new ListWithFixedPriceInput - { - Symbol = symbol, - TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Duration = new ListDuration - { - DurationHours = 24 - }, - Quantity = 1 - }); - executionResult.TransactionResult.Error.ShouldContain("Check sender NFT balance failed."); + Symbol = "ELF", + Amount = 200_00000000 } + }); - return symbol; + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput + { + Symbol = "ELF", + Owner = User2Address + }); + balance.Balance.ShouldBe(InitialELFAmount - 100_00000000); } - [Fact] - public async Task DealWithFixedPriceTest() { - var symbol = await ListWithFixedPriceTest(); - - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Owner = DefaultAddress }); + // Because of 10/10000 service fee. + balance.Balance.ShouldBe(InitialELFAmount + 100_00000000 - 100_00000000 / 1000); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - }, + Owner = User2Address }); + nftBalance.Balance.ShouldBe(1); + } + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 100_00000000); - } + Symbol = symbol, + TokenId = 233, + Owner = DefaultAddress + }); + nftBalance.Balance.ShouldBe(0); + } + } - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // Because of 10/10000 service fee. - balance.Balance.ShouldBe(InitialELFAmount + 100_00000000 - 100_00000000 / 1000); - } + [Fact] + public async Task MakeOfferToFixedPrice() + { + var symbol = await ListWithFixedPriceTest(); - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); - } + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 2, + Price = new Price { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); + Symbol = "ELF", + Amount = 90_00000000 } - } + }); - [Fact] - public async Task MakeOfferToFixedPrice() + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput { - var symbol = await ListWithFixedPriceTest(); - - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); - - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 90_00000000 - }, - }); + Amount = 99_00000000 + } + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + var offerAddressList = await BuyerNFTMarketContractStub.GetOfferAddressList.CallAsync( + new GetAddressListInput { Symbol = symbol, - TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 99_00000000 - }, + TokenId = 233 }); + offerAddressList.Value.ShouldContain(User2Address); - var offerAddressList = await BuyerNFTMarketContractStub.GetOfferAddressList.CallAsync( - new GetAddressListInput - { - Symbol = symbol, - TokenId = 233 - }); - offerAddressList.Value.ShouldContain(User2Address); + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput + { + Symbol = symbol, + TokenId = 233, + Address = User2Address + }); + offerList.Value.Count.ShouldBe(2); + offerList.Value.First().Quantity.ShouldBe(2); + offerList.Value.Last().Quantity.ShouldBe(1); + + return symbol; + } - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(2); - offerList.Value.First().Quantity.ShouldBe(2); - offerList.Value.Last().Quantity.ShouldBe(1); + [Fact] + public async Task DealToOfferWhenFixedPrice() + { + var symbol = await MakeOfferToFixedPrice(); - return symbol; - } + // Set royalty. + await CreatorNFTMarketContractStub.SetRoyalty.SendAsync(new SetRoyaltyInput + { + Symbol = symbol, + TokenId = 233, + Royalty = 10, + RoyaltyFeeReceiver = MarketServiceFeeReceiverAddress + }); - [Fact] - public async Task DealToOfferWhenFixedPrice() + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { - var symbol = await MakeOfferToFixedPrice(); + Symbol = symbol, + TokenId = 233 + }); + offerList.Value.Count.ShouldBe(2); - // Set royalty. - await CreatorNFTMarketContractStub.SetRoyalty.SendAsync(new SetRoyaltyInput + var offer = offerList.Value.First(); + var executionResult = await SellerNFTMarketContractStub.Deal.SendWithExceptionAsync(new DealInput + { + Symbol = symbol, + TokenId = 233, + OfferFrom = offer.From, + Quantity = 1, + Price = offer.Price + }); + executionResult.TransactionResult.Error.ShouldContain("Need to delist"); + + await SellerNFTMarketContractStub.Delist.SendAsync(new DelistInput + { + Symbol = symbol, + TokenId = 233, + Price = new Price { - Symbol = symbol, - TokenId = 233, - Royalty = 10, - RoyaltyFeeReceiver = MarketServiceFeeReceiverAddress - }); + Symbol = "ELF", + Amount = 100_00000000 + }, + Quantity = 1 + }); + + await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput + { + Symbol = symbol, + TokenId = 233, + OfferFrom = offer.From, + Quantity = 1, + Price = offer.Price + }); - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - Symbol = symbol, - TokenId = 233 + Symbol = "ELF", + Owner = User2Address }); - offerList.Value.Count.ShouldBe(2); + balance.Balance.ShouldBe(InitialELFAmount - 90_00000000); + } - var offer = offerList.Value.First(); - var executionResult = await SellerNFTMarketContractStub.Deal.SendWithExceptionAsync(new DealInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - Symbol = symbol, - TokenId = 233, - OfferFrom = offer.From, - Quantity = 1, - Price = offer.Price + Symbol = "ELF", + Owner = DefaultAddress }); - executionResult.TransactionResult.Error.ShouldContain("Need to delist"); + // Because of 10/10000 service fee. + balance.Balance.ShouldBe(InitialELFAmount + 90_00000000 - 90_00000000 / 1000 - 90_00000000 / 1000); + } - await SellerNFTMarketContractStub.Delist.SendAsync(new DelistInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Quantity = 1 + Owner = User2Address }); - - await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput + nftBalance.Balance.ShouldBe(1); + } + + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - OfferFrom = offer.From, - Quantity = 1, - Price = offer.Price + Owner = DefaultAddress }); + nftBalance.Balance.ShouldBe(0); + } + } - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 90_00000000); - } + [Fact] + public async Task DealToOfferWhenNotListed() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + { + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // Because of 10/10000 service fee. - balance.Balance.ShouldBe(InitialELFAmount + 90_00000000 - 90_00000000 / 1000 - 90_00000000 / 1000); - } + var symbol = await MintBadgeTest(); - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); - } + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 233, + Amount = 1, + Spender = NFTMarketContractAddress + }); + + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); + Symbol = "ELF", + Amount = 1000_00000000 } - } + }); - [Fact] - public async Task DealToOfferWhenNotListed() + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + Symbol = symbol, + TokenId = 233 + }); + offerList.Value.Count.ShouldBe(1); - var symbol = await MintBadgeTest(); + var offer = offerList.Value.First(); + await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput + { + Symbol = symbol, + TokenId = 233, + OfferFrom = offer.From, + Quantity = 1, + Price = offer.Price + }); - await TokenContractStub.Issue.SendAsync(new IssueInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, + Owner = User2Address }); - await TokenContractStub.Issue.SendAsync(new IssueInput + balance.Balance.ShouldBe(InitialELFAmount - 1000_00000000); + } + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, + Owner = DefaultAddress }); + // Because of 10/10000 service fee. + balance.Balance.ShouldBe(InitialELFAmount + 1000_00000000 - 1000_00000000 / 1000); + } - await NFTContractStub.Approve.SendAsync(new ApproveInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Amount = 1, - Spender = NFTMarketContractAddress - }); - - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Owner = User2Address }); + nftBalance.Balance.ShouldBe(1); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 1000_00000000 - }, + Owner = DefaultAddress }); + nftBalance.Balance.ShouldBe(0); + } + } - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233 - }); - offerList.Value.Count.ShouldBe(1); + [Fact] + public async Task TokenWhiteListTest() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + { + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - var offer = offerList.Value.First(); - await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput - { - Symbol = symbol, - TokenId = 233, - OfferFrom = offer.From, - Quantity = 1, - Price = offer.Price - }); + await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList + { + Value = { "USDT", "EAN" } + }); - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 1000_00000000); - } + var globalTokenWhiteList = await AdminNFTMarketContractStub.GetGlobalTokenWhiteList.CallAsync(new Empty()); + globalTokenWhiteList.Value.Count.ShouldBe(3); + globalTokenWhiteList.Value.ShouldContain("EAN"); + globalTokenWhiteList.Value.ShouldContain("ELF"); + globalTokenWhiteList.Value.ShouldContain("USDT"); - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // Because of 10/10000 service fee. - balance.Balance.ShouldBe(InitialELFAmount + 1000_00000000 - 1000_00000000 / 1000); - } + var symbol = await CreateArtistsTest(); + await CreatorNFTMarketContractStub.SetTokenWhiteList.SendAsync(new SetTokenWhiteListInput + { + Symbol = symbol, + TokenWhiteList = new StringList { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); + Value = { "TEST" } } + }); - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); - } + { + var tokenWhiteList = + await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue { Value = symbol }); + tokenWhiteList.Value.Count.ShouldBe(4); + tokenWhiteList.Value.ShouldContain("ELF"); + tokenWhiteList.Value.ShouldContain("TEST"); } - [Fact] - public async Task TokenWhiteListTest() + await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); - - await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList - { - Value = {"USDT", "EAN"} - }); - - var globalTokenWhiteList = await AdminNFTMarketContractStub.GetGlobalTokenWhiteList.CallAsync(new Empty()); - globalTokenWhiteList.Value.Count.ShouldBe(3); - globalTokenWhiteList.Value.ShouldContain("EAN"); - globalTokenWhiteList.Value.ShouldContain("ELF"); - globalTokenWhiteList.Value.ShouldContain("USDT"); - - var symbol = await CreateArtistsTest(); - - await CreatorNFTMarketContractStub.SetTokenWhiteList.SendAsync(new SetTokenWhiteListInput - { - Symbol = symbol, - TokenWhiteList = new StringList - { - Value = {"TEST"} - } - }); + Value = { "USDT", "EAN", "NEW" } + }); - { - var tokenWhiteList = - await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue {Value = symbol}); - tokenWhiteList.Value.Count.ShouldBe(4); - tokenWhiteList.Value.ShouldContain("ELF"); - tokenWhiteList.Value.ShouldContain("TEST"); - } - - await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList - { - Value = {"USDT", "EAN", "NEW"} - }); + { + var tokenWhiteList = + await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue { Value = symbol }); + tokenWhiteList.Value.Count.ShouldBe(5); + tokenWhiteList.Value.ShouldContain("NEW"); + tokenWhiteList.Value.ShouldContain("TEST"); + } - { - var tokenWhiteList = - await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue {Value = symbol}); - tokenWhiteList.Value.Count.ShouldBe(5); - tokenWhiteList.Value.ShouldContain("NEW"); - tokenWhiteList.Value.ShouldContain("TEST"); - } - - await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList - { - Value = {"ELF"} - }); + await AdminNFTMarketContractStub.SetGlobalTokenWhiteList.SendAsync(new StringList + { + Value = { "ELF" } + }); - { - var tokenWhiteList = - await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue {Value = symbol}); - tokenWhiteList.Value.Count.ShouldBe(2); - tokenWhiteList.Value.ShouldContain("ELF"); - tokenWhiteList.Value.ShouldContain("TEST"); - } + { + var tokenWhiteList = + await CreatorNFTMarketContractStub.GetTokenWhiteList.CallAsync(new StringValue { Value = symbol }); + tokenWhiteList.Value.Count.ShouldBe(2); + tokenWhiteList.Value.ShouldContain("ELF"); + tokenWhiteList.Value.ShouldContain("TEST"); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Auction.cs b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Auction.cs index 03387d8fb0..79d7bac43a 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Auction.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Auction.cs @@ -2,487 +2,485 @@ using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.Contracts.NFTMarket; -using AElf.Kernel; using Shouldly; using Xunit; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + [Fact] + public async Task ListWithEnglishAuctionTest() { - [Fact] - public async Task ListWithEnglishAuctionTest() + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - var symbol = await CreateArtistsTest(); + var symbol = await CreateArtistsTest(); + + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User3Address + }); + + await NFTContractStub.Mint.SendAsync(new MintInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Alias = "Gift2" + }); + + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 2, + Amount = 1, + Spender = NFTMarketContractAddress + }); - await TokenContractStub.Issue.SendAsync(new IssueInput + await SellerNFTMarketContractStub.ListWithEnglishAuction.SendAsync(new ListWithEnglishAuctionInput + { + Symbol = symbol, + TokenId = 2, + Duration = new ListDuration { - Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + DurationHours = 100 + }, + PurchaseSymbol = "ELF", + StartingPrice = 100_00000000, + EarnestMoney = 10_00000000 + }); + + var auctionInfo = await SellerNFTMarketContractStub.GetEnglishAuctionInfo.CallAsync( + new GetEnglishAuctionInfoInput { - Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, + Symbol = symbol, + TokenId = 2 }); - await TokenContractStub.Issue.SendAsync(new IssueInput + auctionInfo.Owner.ShouldBe(DefaultAddress); + auctionInfo.PurchaseSymbol.ShouldBe("ELF"); + auctionInfo.StartingPrice.ShouldBe(100_00000000); + auctionInfo.Duration.DurationHours.ShouldBe(100); + + return symbol; + } + + [Fact] + public async Task PlaceBidForEnglishAuctionTest() + { + var symbol = await ListWithEnglishAuctionTest(); + + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = User3Address, - }); + Amount = 90_00000000 + } + }); - await NFTContractStub.Mint.SendAsync(new MintInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, - TokenId = 2, - Quantity = 1, - Alias = "Gift2" + TokenId = 2 }); + offerList.Value.Count.ShouldBe(1); + offerList.Value.First().From.ShouldBe(User2Address); + offerList.Value.First().Price.Amount.ShouldBe(90_00000000); + } - await NFTContractStub.Approve.SendAsync(new ApproveInput + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await NFTBuyer2TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { - Symbol = symbol, - TokenId = 2, - Amount = 1, - Spender = NFTMarketContractAddress - }); + Symbol = "ELF", + Amount = 110_00000000 + } + }); - await SellerNFTMarketContractStub.ListWithEnglishAuction.SendAsync(new ListWithEnglishAuctionInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, - TokenId = 2, - Duration = new ListDuration - { - DurationHours = 100 - }, - PurchaseSymbol = "ELF", - StartingPrice = 100_00000000, - EarnestMoney = 10_00000000 + TokenId = 2 }); - - var auctionInfo = await SellerNFTMarketContractStub.GetEnglishAuctionInfo.CallAsync( - new GetEnglishAuctionInfoInput - { - Symbol = symbol, - TokenId = 2 - }); - auctionInfo.Owner.ShouldBe(DefaultAddress); - auctionInfo.PurchaseSymbol.ShouldBe("ELF"); - auctionInfo.StartingPrice.ShouldBe(100_00000000); - auctionInfo.Duration.DurationHours.ShouldBe(100); - - return symbol; + offerList.Value.Count.ShouldBe(1); } - [Fact] - public async Task PlaceBidForEnglishAuctionTest() { - var symbol = await ListWithEnglishAuctionTest(); - - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + var bidList = await BuyerNFTMarketContractStub.GetBidList.CallAsync(new GetBidListInput { Symbol = symbol, - TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 90_00000000 - } + TokenId = 2 }); + bidList.Value.Count.ShouldBe(1); + } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 2 - }); - offerList.Value.Count.ShouldBe(1); - offerList.Value.First().From.ShouldBe(User2Address); - offerList.Value.First().Price.Amount.ShouldBe(90_00000000); + Symbol = "ELF", + Amount = 109_00000000 } + }); - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); - await NFTBuyer2TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Symbol = symbol, + TokenId = 2 }); + offerList.Value.Count.ShouldBe(2); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var bidList = await BuyerNFTMarketContractStub.GetBidList.CallAsync(new GetBidListInput { Symbol = symbol, - TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 110_00000000 - } + TokenId = 2 }); + bidList.Value.Count.ShouldBe(1); + } - { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 2 - }); - offerList.Value.Count.ShouldBe(1); - } + return symbol; + } - { - var bidList = await BuyerNFTMarketContractStub.GetBidList.CallAsync(new GetBidListInput - { - Symbol = symbol, - TokenId = 2 - }); - bidList.Value.Count.ShouldBe(1); - } + [Fact] + public async Task DealToEnglishAuctionTest() + { + var symbol = await PlaceBidForEnglishAuctionTest(); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 109_00000000 - } - }); + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await Buyer2NFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 2 - }); - offerList.Value.Count.ShouldBe(2); + Symbol = "ELF", + Amount = 105_00000000 } + }); + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - var bidList = await BuyerNFTMarketContractStub.GetBidList.CallAsync(new GetBidListInput - { - Symbol = symbol, - TokenId = 2 - }); - bidList.Value.Count.ShouldBe(1); - } - - return symbol; + Symbol = "ELF", + Owner = User2Address + }); + balance.Balance.ShouldBe(InitialELFAmount - 10_00000000); } - [Fact] - public async Task DealToEnglishAuctionTest() + await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput { - var symbol = await PlaceBidForEnglishAuctionTest(); + Symbol = symbol, + TokenId = 2, + OfferFrom = User2Address, + Price = new Price + { + Symbol = "ELF", + Amount = 110_00000000 + }, + Quantity = 1 + }); - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Owner = User2Address }); + balance.Balance.ShouldBe(InitialELFAmount - 110_00000000); + } - await Buyer2NFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 105_00000000 - } + Owner = User2Address }); + balance.Balance.ShouldBe(1); + } - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 10_00000000); - } - - await SellerNFTMarketContractStub.Deal.SendAsync(new DealInput + { + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 2, - OfferFrom = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 110_00000000 - }, - Quantity = 1 + Owner = DefaultAddress }); + balance.Balance.ShouldBe(0); + } + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 110_00000000); - } + Symbol = "ELF", + Owner = User3Address + }); + balance.Balance.ShouldBe(InitialELFAmount); + } + } - { - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = User2Address - }); - balance.Balance.ShouldBe(1); - } + [Fact] + public async Task ListWithDutchAuctionTest() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + { + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - { - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = DefaultAddress - }); - balance.Balance.ShouldBe(0); - } + var symbol = await CreateArtistsTest(); - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User3Address - }); - balance.Balance.ShouldBe(InitialELFAmount); - } - } + await NFTContractStub.Mint.SendAsync(new MintInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Alias = "Gift2" + }); - [Fact] - public async Task ListWithDutchAuctionTest() + await TokenContractStub.Issue.SendAsync(new IssueInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); - var symbol = await CreateArtistsTest(); + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 2, + Amount = 1, + Spender = NFTMarketContractAddress + }); - await NFTContractStub.Mint.SendAsync(new MintInput + await SellerNFTMarketContractStub.ListWithDutchAuction.SendAsync(new ListWithDutchAuctionInput + { + Symbol = symbol, + TokenId = 2, + Duration = new ListDuration { - Symbol = symbol, - TokenId = 2, - Quantity = 1, - Alias = "Gift2" - }); + DurationHours = 100 + }, + PurchaseSymbol = "ELF", + StartingPrice = 100_00000000, + EndingPrice = 50_00000000 + }); - await TokenContractStub.Issue.SendAsync(new IssueInput + var auctionInfo = await SellerNFTMarketContractStub.GetDutchAuctionInfo.CallAsync( + new GetDutchAuctionInfoInput { - Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, + Symbol = symbol, + TokenId = 2 }); - await TokenContractStub.Issue.SendAsync(new IssueInput + auctionInfo.Owner.ShouldBe(DefaultAddress); + auctionInfo.PurchaseSymbol.ShouldBe("ELF"); + auctionInfo.StartingPrice.ShouldBe(100_00000000); + auctionInfo.EndingPrice.ShouldBe(50_00000000); + auctionInfo.Duration.DurationHours.ShouldBe(100); + + return symbol; + } + + [Fact] + public async Task PlaceBidForDutchAuctionTest() + { + var symbol = await ListWithDutchAuctionTest(); + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, - }); + Amount = 49_00000000 + }, + Quantity = 1 + }); - await NFTContractStub.Approve.SendAsync(new ApproveInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, - TokenId = 2, - Amount = 1, - Spender = NFTMarketContractAddress + TokenId = 2 }); + offerList.Value.Count.ShouldBe(1); + } - await SellerNFTMarketContractStub.ListWithDutchAuction.SendAsync(new ListWithDutchAuctionInput - { - Symbol = symbol, - TokenId = 2, - Duration = new ListDuration - { - DurationHours = 100 - }, - PurchaseSymbol = "ELF", - StartingPrice = 100_00000000, - EndingPrice = 50_00000000 - }); + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); - var auctionInfo = await SellerNFTMarketContractStub.GetDutchAuctionInfo.CallAsync( - new GetDutchAuctionInfoInput - { - Symbol = symbol, - TokenId = 2 - }); - auctionInfo.Owner.ShouldBe(DefaultAddress); - auctionInfo.PurchaseSymbol.ShouldBe("ELF"); - auctionInfo.StartingPrice.ShouldBe(100_00000000); - auctionInfo.EndingPrice.ShouldBe(50_00000000); - auctionInfo.Duration.DurationHours.ShouldBe(100); - - return symbol; - } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Price = new Price + { + Symbol = "ELF", + Amount = 100_00000000 + }, + Quantity = 1 + }); - [Fact] - public async Task PlaceBidForDutchAuctionTest() { - var symbol = await ListWithDutchAuctionTest(); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 49_00000000 - }, - Quantity = 1 + Owner = User2Address }); + balance.Balance.ShouldBe(1); + } + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 2 - }); - offerList.Value.Count.ShouldBe(1); - } - - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Symbol = symbol, + TokenId = 2 }); + offerList.Value.Count.ShouldBe(1); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Quantity = 1 + Owner = DefaultAddress }); + balance.Balance.ShouldBe(0); + } + } - { - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = User2Address - }); - balance.Balance.ShouldBe(1); - } + [Fact] + public async Task DelistEnglishAuctionNFTTest() + { + var symbol = await ListWithEnglishAuctionTest(); - { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 2 - }); - offerList.Value.Count.ShouldBe(1); - } + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await NFTBuyer2TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = DefaultAddress - }); - balance.Balance.ShouldBe(0); + Symbol = "ELF", + Amount = 200_00000000 } - } + }); - [Fact] - public async Task DelistEnglishAuctionNFTTest() + await Buyer2NFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput { - var symbol = await ListWithEnglishAuctionTest(); - - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); - await NFTBuyer2TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); + Amount = 300_00000000 + } + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - } - }); - - await Buyer2NFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 300_00000000 - } - }); + await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Spender = NFTMarketContractAddress, + Amount = 1_00000000 + }); - await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + await SellerNFTMarketContractStub.Delist.SendAsync(new DelistInput + { + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Price = new Price { Symbol = "ELF", - Spender = NFTMarketContractAddress, - Amount = 1_00000000 - }); + Amount = 100_00000000 + } + }); - await SellerNFTMarketContractStub.Delist.SendAsync(new DelistInput + var listedNftList = await SellerNFTMarketContractStub.GetListedNFTInfoList.CallAsync( + new GetListedNFTInfoListInput { Symbol = symbol, TokenId = 2, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - } + Owner = DefaultAddress }); - - var listedNftList = (await SellerNFTMarketContractStub.GetListedNFTInfoList.CallAsync( - new GetListedNFTInfoListInput - { - Symbol = symbol, - TokenId = 2, - Owner = DefaultAddress - })); - listedNftList.Value.Count.ShouldBe(0); - } + listedNftList.Value.Count.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Customize.cs b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Customize.cs index b134a15927..e404fb2b55 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Customize.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_Customize.cs @@ -1,347 +1,344 @@ using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.Contracts.NFTMarket; -using AElf.Contracts.NFTMinter; using AElf.CSharp.Core.Extension; using AElf.Kernel; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -using InitializeInput = AElf.Contracts.NFTMarket.InitializeInput; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + [Fact] + public async Task SetCustomizeInfoTest() { - [Fact] - public async Task SetCustomizeInfoTest() + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - var symbol = await CreateArtistsTest(); + var symbol = await CreateArtistsTest(); + + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); + await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); - await TokenContractStub.Issue.SendAsync(new IssueInput + await CreatorNFTMarketContractStub.SetCustomizeInfo.SendAsync(new CustomizeInfo + { + Symbol = symbol, + DepositRate = 2000, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + Amount = 100_00000000 + }, + StakingAmount = 10_00000000, + WhiteListHours = 10, + WorkHours = 7 + }); + + var customizeInfo = + await CreatorNFTMarketContractStub.GetCustomizeInfo.CallAsync(new StringValue { Value = symbol }); + customizeInfo.Symbol.ShouldBe(symbol); + return symbol; + } + + [Fact] + public async Task RequestNewNFTTest() + { + var symbol = await SetCustomizeInfoTest(); + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, - }); - await TokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + Amount = 200_00000000 + }, + ExpireTime = TimestampHelper.GetUtcNow().AddMinutes(30) + }); + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Owner = User2Address }); - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + balance.Balance.ShouldBe(InitialELFAmount - 40_00000000); + } + + var requestInfo = await BuyerNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + Symbol = symbol, + TokenId = 2 + }); + requestInfo.DepositRate.ShouldBe(2000); + requestInfo.IsConfirmed.ShouldBeFalse(); + return symbol; + } + + [Fact] + public async Task ConfirmRequestTest() + { + var symbol = await RequestNewNFTTest(); + await CreatorNFTMarketContractStub.HandleRequest.SendAsync(new HandleRequestInput + { + Symbol = symbol, + TokenId = 2, + IsConfirm = true, + Requester = User2Address + }); + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress + Owner = DefaultAddress }); + // Received 50% deposit, but need to sub 10_00000000 staking tokens and 2000000 service fees. + balance.Balance.ShouldBe(InitialELFAmount + 20_00000000 - 10_00000000 - 2000000); + } - await CreatorNFTMarketContractStub.SetCustomizeInfo.SendAsync(new CustomizeInfo - { - Symbol = symbol, - DepositRate = 2000, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - StakingAmount = 10_00000000, - WhiteListHours = 10, - WorkHours = 7 - }); + var requestInfo = await BuyerNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + Symbol = symbol, + TokenId = 2 + }); + requestInfo.IsConfirmed.ShouldBeTrue(); + return symbol; + } - var customizeInfo = - await CreatorNFTMarketContractStub.GetCustomizeInfo.CallAsync(new StringValue {Value = symbol}); - customizeInfo.Symbol.ShouldBe(symbol); - return symbol; - } + [Fact] + public async Task ListForRequestedNFTTest() + { + var symbol = await ConfirmRequestTest(); - [Fact] - public async Task RequestNewNFTTest() + // Need to mint this token id first. + await NFTContractStub.Mint.SendAsync(new MintInput { - var symbol = await SetCustomizeInfoTest(); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 2, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - }, - ExpireTime = TimestampHelper.GetUtcNow().AddMinutes(30) - }); + Symbol = symbol, + TokenId = 2, + Quantity = 1, + Alias = "Gift" + }); + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 2, + Amount = 1, + Spender = NFTMarketContractAddress + }); - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput + { + var executionResult = await CreatorNFTMarketContractStub.ListWithEnglishAuction.SendWithExceptionAsync( + new ListWithEnglishAuctionInput { - Symbol = "ELF", - Owner = User2Address + Symbol = symbol, + TokenId = 2, + StartingPrice = 100_00000000, + PurchaseSymbol = "ELF", + Duration = new ListDuration + { + StartTime = TimestampHelper.GetUtcNow(), + PublicTime = TimestampHelper.GetUtcNow(), + DurationHours = 7 + } }); - balance.Balance.ShouldBe(InitialELFAmount - 40_00000000); - } - - var requestInfo = await BuyerNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput - { - Symbol = symbol, - TokenId = 2 - }); - requestInfo.DepositRate.ShouldBe(2000); - requestInfo.IsConfirmed.ShouldBeFalse(); - return symbol; + executionResult.TransactionResult.Error.ShouldContain( + "This NFT cannot be listed with auction for now."); } - [Fact] - public async Task ConfirmRequestTest() { - var symbol = await RequestNewNFTTest(); - await CreatorNFTMarketContractStub.HandleRequest.SendAsync(new HandleRequestInput - { - Symbol = symbol, - TokenId = 2, - IsConfirm = true, - Requester = User2Address - }); - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput + var executionResult = await CreatorNFTMarketContractStub.ListWithDutchAuction.SendWithExceptionAsync( + new ListWithDutchAuctionInput { - Symbol = "ELF", - Owner = DefaultAddress + Symbol = symbol, + TokenId = 2, + StartingPrice = 100_00000000, + EndingPrice = 50_00000000, + PurchaseSymbol = "ELF", + Duration = new ListDuration + { + StartTime = TimestampHelper.GetUtcNow(), + PublicTime = TimestampHelper.GetUtcNow(), + DurationHours = 7 + } }); - // Received 50% deposit, but need to sub 10_00000000 staking tokens and 2000000 service fees. - balance.Balance.ShouldBe(InitialELFAmount + 20_00000000 - 10_00000000 - 2000000); - } - - var requestInfo = await BuyerNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput - { - Symbol = symbol, - TokenId = 2 - }); - requestInfo.IsConfirmed.ShouldBeTrue(); - return symbol; + executionResult.TransactionResult.Error.ShouldContain( + "This NFT cannot be listed with auction for now."); } - [Fact] - public async Task ListForRequestedNFTTest() + var listInput = new ListWithFixedPriceInput { - var symbol = await ConfirmRequestTest(); - - // Need to mint this token id first. - await NFTContractStub.Mint.SendAsync(new MintInput + Symbol = symbol, + TokenId = 2, + Price = new Price { - Symbol = symbol, - TokenId = 2, - Quantity = 1, - Alias = "Gift" - }); - await NFTContractStub.Approve.SendAsync(new ApproveInput + Symbol = "ELF", + Amount = 200_00000000 + }, + Duration = new ListDuration { - Symbol = symbol, - TokenId = 2, - Amount = 1, - Spender = NFTMarketContractAddress - }); + StartTime = TimestampHelper.GetUtcNow(), + PublicTime = TimestampHelper.GetUtcNow().AddHours(11), + DurationHours = 100 + }, + Quantity = 1 + }; - { - var executionResult = await CreatorNFTMarketContractStub.ListWithEnglishAuction.SendWithExceptionAsync( - new ListWithEnglishAuctionInput - { - Symbol = symbol, - TokenId = 2, - StartingPrice = 100_00000000, - PurchaseSymbol = "ELF", - Duration = new ListDuration - { - StartTime = TimestampHelper.GetUtcNow(), - PublicTime = TimestampHelper.GetUtcNow(), - DurationHours = 7 - } - }); - executionResult.TransactionResult.Error.ShouldContain( - "This NFT cannot be listed with auction for now."); - } + { + var executionResult = + await CreatorNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync(listInput); + executionResult.TransactionResult.Error.ShouldContain("Incorrect white list address price list."); + } + listInput.Price.Amount = 100_00000000; + listInput.WhiteListAddressPriceList = new WhiteListAddressPriceList + { + Value = { - var executionResult = await CreatorNFTMarketContractStub.ListWithDutchAuction.SendWithExceptionAsync( - new ListWithDutchAuctionInput + new WhiteListAddressPrice + { + Address = User2Address, + Price = new Price { - Symbol = symbol, - TokenId = 2, - StartingPrice = 100_00000000, - EndingPrice = 50_00000000, - PurchaseSymbol = "ELF", - Duration = new ListDuration - { - StartTime = TimestampHelper.GetUtcNow(), - PublicTime = TimestampHelper.GetUtcNow(), - DurationHours = 7 - } - }); - executionResult.TransactionResult.Error.ShouldContain( - "This NFT cannot be listed with auction for now."); + Symbol = "ELF", + Amount = 200_00000000 + } + } } + }; + + { + var executionResult = + await CreatorNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync(listInput); + executionResult.TransactionResult.Error.ShouldContain("too low"); + } - var listInput = new ListWithFixedPriceInput + listInput.Price.Amount = 200_00000000; + await CreatorNFTMarketContractStub.ListWithFixedPrice.SendAsync(listInput); + + var requestInfo = await CreatorNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + Symbol = symbol, + TokenId = 2 + }); + requestInfo.ListTime.ShouldNotBeNull(); + + var whiteListPriceList = await CreatorNFTMarketContractStub.GetWhiteListAddressPriceList.CallAsync( + new GetWhiteListAddressPriceListInput { Symbol = symbol, TokenId = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - }, - Duration = new ListDuration - { - StartTime = TimestampHelper.GetUtcNow(), - PublicTime = TimestampHelper.GetUtcNow().AddHours(11), - DurationHours = 100 - }, - Quantity = 1, - }; - - { - var executionResult = - await CreatorNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync(listInput); - executionResult.TransactionResult.Error.ShouldContain("Incorrect white list address price list."); - } + Owner = DefaultAddress + }); + whiteListPriceList.Value.Count.ShouldBe(1); + whiteListPriceList.Value[0].Address.ShouldBe(User2Address); + whiteListPriceList.Value[0].Price.Symbol.ShouldBe("ELF"); + // Instead of 200_00000000. + whiteListPriceList.Value[0].Price.Amount.ShouldBe(160_00000000); + return symbol; + } - listInput.Price.Amount = 100_00000000; - listInput.WhiteListAddressPriceList = new WhiteListAddressPriceList + [Fact] + public async Task BuyRequestedNFTTest() + { + var symbol = await ListForRequestedNFTTest(); + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - Value = - { - new WhiteListAddressPrice - { - Address = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - } - } - } - }; + Symbol = "ELF", + Owner = User2Address + }); + balance.Balance.ShouldBe(InitialELFAmount - 40_00000000); + } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 2, + OfferTo = DefaultAddress, + Price = new Price { - var executionResult = - await CreatorNFTMarketContractStub.ListWithFixedPrice.SendWithExceptionAsync(listInput); - executionResult.TransactionResult.Error.ShouldContain("too low"); - } + Symbol = "ELF", + Amount = 160_00000000 + }, + Quantity = 1 + }); - listInput.Price.Amount = 200_00000000; - await CreatorNFTMarketContractStub.ListWithFixedPrice.SendAsync(listInput); + var requestInfo = await CreatorNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + Symbol = symbol, + TokenId = 2 + }); + // Removed after dealing. + requestInfo.Price.ShouldBeNull(); - var requestInfo = await CreatorNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - Symbol = symbol, - TokenId = 2 + Symbol = "ELF", + Owner = User2Address }); - requestInfo.ListTime.ShouldNotBeNull(); - - var whiteListPriceList = await CreatorNFTMarketContractStub.GetWhiteListAddressPriceList.CallAsync( - new GetWhiteListAddressPriceListInput - { - Symbol = symbol, - TokenId = 2, - Owner = DefaultAddress - }); - whiteListPriceList.Value.Count.ShouldBe(1); - whiteListPriceList.Value[0].Address.ShouldBe(User2Address); - whiteListPriceList.Value[0].Price.Symbol.ShouldBe("ELF"); - // Instead of 200_00000000. - whiteListPriceList.Value[0].Price.Amount.ShouldBe(160_00000000); - return symbol; + balance.Balance.ShouldBe(InitialELFAmount - 200_00000000); } - [Fact] - public async Task BuyRequestedNFTTest() { - var symbol = await ListForRequestedNFTTest(); - + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 40_00000000); - } + Symbol = "ELF", + Owner = DefaultAddress + }); + // NFT price 200 ELF - Staking 10 ELF - 0.2 Service Fee ELF. + balance.Balance.ShouldBe(InitialELFAmount + 200_00000000 - 10_00000000 - 20000000); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 2, - OfferTo = DefaultAddress, - Price = new Price - { - Symbol = "ELF", - Amount = 160_00000000 - }, - Quantity = 1 + Owner = User2Address }); + nftBalance.Balance.ShouldBe(1); + } - var requestInfo = await CreatorNFTMarketContractStub.GetRequestInfo.CallAsync(new GetRequestInfoInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, - TokenId = 2 + TokenId = 2, + Owner = DefaultAddress }); - // Removed after dealing. - requestInfo.Price.ShouldBeNull(); - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 200_00000000); - } - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // NFT price 200 ELF - Staking 10 ELF - 0.2 Service Fee ELF. - balance.Balance.ShouldBe(InitialELFAmount + 200_00000000 - 10_00000000 - 20000000); - } - - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); - } - - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 2, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); - } + nftBalance.Balance.ShouldBe(0); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_WhiteList.cs b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_WhiteList.cs index e412e222c7..758fe709b0 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_WhiteList.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMarketContractTests_WhiteList.cs @@ -6,530 +6,528 @@ using AElf.Kernel; using Shouldly; using Xunit; -using InitializeInput = AElf.Contracts.NFTMarket.InitializeInput; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + [Fact] + public async Task DealToFixedPriceBuyerInWhiteList() { - [Fact] - public async Task DealToFixedPriceBuyerInWhiteList() + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - var symbol = await MintBadgeTest(); + var symbol = await MintBadgeTest(); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); + + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 233, + Amount = 1, + Spender = NFTMarketContractAddress + }); + + await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + Symbol = symbol, + TokenId = 233, + Price = new Price { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, - }); - - await NFTContractStub.Approve.SendAsync(new ApproveInput + Amount = 100_00000000 + }, + Duration = new ListDuration { - Symbol = symbol, - TokenId = 233, - Amount = 1, - Spender = NFTMarketContractAddress - }); - - await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + DurationHours = 24 + }, + Quantity = 1, + WhiteListAddressPriceList = new WhiteListAddressPriceList { - Symbol = symbol, - TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Duration = new ListDuration + Value = { - DurationHours = 24 - }, - Quantity = 1, - WhiteListAddressPriceList = new WhiteListAddressPriceList - { - Value = + new WhiteListAddressPrice { - new WhiteListAddressPrice + Address = User2Address, + Price = new Price { - Address = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 10_00000000 - } + Symbol = "ELF", + Amount = 10_00000000 } } } - }); + } + }); - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); + + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 2, + Price = new Price { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); + Amount = 10_00000000 + } + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 10_00000000 - }, + Address = User2Address }); - - { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(1); - } - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 10_00000000); - } - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // Because of 10/10000 service fee. - balance.Balance.ShouldBe(InitialELFAmount + 10_00000000 - 10_00000000 / 1000); - } - - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); - } - - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); - } + offerList.Value.Count.ShouldBe(1); } - [Fact] - public async Task DealToFixedPriceBuyerInWhiteList_HigherPrice() { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); - - var symbol = await MintBadgeTest(); - - await TokenContractStub.Issue.SendAsync(new IssueInput + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, + Owner = User2Address }); - await TokenContractStub.Issue.SendAsync(new IssueInput + balance.Balance.ShouldBe(InitialELFAmount - 10_00000000); + } + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, + Owner = DefaultAddress }); + // Because of 10/10000 service fee. + balance.Balance.ShouldBe(InitialELFAmount + 10_00000000 - 10_00000000 / 1000); + } - await NFTContractStub.Approve.SendAsync(new ApproveInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Amount = 1, - Spender = NFTMarketContractAddress + Owner = User2Address }); + nftBalance.Balance.ShouldBe(1); + } - await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Duration = new ListDuration - { - DurationHours = 24 - }, - Quantity = 1, - WhiteListAddressPriceList = new WhiteListAddressPriceList - { - Value = - { - new WhiteListAddressPrice - { - Address = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 110_00000000 - } - } - } - } + Owner = DefaultAddress }); + nftBalance.Balance.ShouldBe(0); + } + } - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); + [Fact] + public async Task DealToFixedPriceBuyerInWhiteList_HigherPrice() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + { + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - }); + var symbol = await MintBadgeTest(); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput - { - Symbol = symbol, - TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 110_00000000 - }, - }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); - { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(2); - } + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 233, + Amount = 1, + Spender = NFTMarketContractAddress + }); + await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + Symbol = symbol, + TokenId = 233, + Price = new Price { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 110_00000000); - } - + Symbol = "ELF", + Amount = 100_00000000 + }, + Duration = new ListDuration { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = DefaultAddress - }); - // Because of 10/10000 service fee. - balance.Balance.ShouldBe(InitialELFAmount + 110_00000000 - 110_00000000 / 1000); - } - + DurationHours = 24 + }, + Quantity = 1, + WhiteListAddressPriceList = new WhiteListAddressPriceList { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput + Value = { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); + new WhiteListAddressPrice + { + Address = User2Address, + Price = new Price + { + Symbol = "ELF", + Amount = 110_00000000 + } + } + } } + }); - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(0); - } - } + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); - [Fact] - public async Task DealToFixedPriceBuyerInWhiteList_Complicated() + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput { - await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 2, + Price = new Price { - NftContractAddress = NFTContractAddress, - ServiceFeeReceiver = MarketServiceFeeReceiverAddress - }); + Symbol = "ELF", + Amount = 100_00000000 + } + }); - var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 2, + Price = new Price { - ProtocolName = "aelf Collections", - NftType = NFTType.Collectables.ToString(), - TotalSupply = 1000, - IsBurnable = false, - IsTokenIdReuse = true - }); - var symbol = executionResult.Output.Value; + Symbol = "ELF", + Amount = 110_00000000 + } + }); - await NFTContractStub.Mint.SendAsync(new MintInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, - Alias = "test", - Quantity = 10, - TokenId = 233 + TokenId = 233, + Address = User2Address }); + offerList.Value.Count.ShouldBe(2); + } - await TokenContractStub.Issue.SendAsync(new IssueInput + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = DefaultAddress, + Owner = User2Address }); - await TokenContractStub.Issue.SendAsync(new IssueInput + balance.Balance.ShouldBe(InitialELFAmount - 110_00000000); + } + + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { Symbol = "ELF", - Amount = InitialELFAmount, - To = User2Address, + Owner = DefaultAddress }); + // Because of 10/10000 service fee. + balance.Balance.ShouldBe(InitialELFAmount + 110_00000000 - 110_00000000 / 1000); + } - await NFTContractStub.Approve.SendAsync(new ApproveInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Amount = 10, - Spender = NFTMarketContractAddress + Owner = User2Address }); + nftBalance.Balance.ShouldBe(1); + } - await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - Price = new Price - { - Symbol = "ELF", - Amount = 100_00000000 - }, - Duration = new ListDuration - { - DurationHours = 24, - PublicTime = TimestampHelper.GetUtcNow().AddDays((1)) - }, - Quantity = 10, - WhiteListAddressPriceList = new WhiteListAddressPriceList + Owner = DefaultAddress + }); + nftBalance.Balance.ShouldBe(0); + } + } + + [Fact] + public async Task DealToFixedPriceBuyerInWhiteList_Complicated() + { + await AdminNFTMarketContractStub.Initialize.SendAsync(new InitializeInput + { + NftContractAddress = NFTContractAddress, + ServiceFeeReceiver = MarketServiceFeeReceiverAddress + }); + + var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + { + ProtocolName = "aelf Collections", + NftType = NFTType.Collectables.ToString(), + TotalSupply = 1000, + IsBurnable = false, + IsTokenIdReuse = true + }); + var symbol = executionResult.Output.Value; + + await NFTContractStub.Mint.SendAsync(new MintInput + { + Symbol = symbol, + Alias = "test", + Quantity = 10, + TokenId = 233 + }); + + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = DefaultAddress + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = InitialELFAmount, + To = User2Address + }); + + await NFTContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = symbol, + TokenId = 233, + Amount = 10, + Spender = NFTMarketContractAddress + }); + + await SellerNFTMarketContractStub.ListWithFixedPrice.SendAsync(new ListWithFixedPriceInput + { + Symbol = symbol, + TokenId = 233, + Price = new Price + { + Symbol = "ELF", + Amount = 100_00000000 + }, + Duration = new ListDuration + { + DurationHours = 24, + PublicTime = TimestampHelper.GetUtcNow().AddDays(1) + }, + Quantity = 10, + WhiteListAddressPriceList = new WhiteListAddressPriceList + { + Value = { - Value = + new WhiteListAddressPrice { - new WhiteListAddressPrice + Address = User2Address, + Price = new Price { - Address = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 90_00000000 - } - }, - new WhiteListAddressPrice + Symbol = "ELF", + Amount = 90_00000000 + } + }, + new WhiteListAddressPrice + { + Address = User2Address, + Price = new Price { - Address = User2Address, - Price = new Price - { - Symbol = "ELF", - Amount = 91_00000000 - } + Symbol = "ELF", + Amount = 91_00000000 } } } - }); + } + }); + + await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = long.MaxValue, + Spender = NFTMarketContractAddress + }); - await NFTBuyerTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 2, + Price = new Price { Symbol = "ELF", - Amount = long.MaxValue, - Spender = NFTMarketContractAddress - }); + Amount = 101_00000000 + } + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 2, - Price = new Price - { - Symbol = "ELF", - Amount = 101_00000000 - }, + Address = User2Address }); + offerList.Value.Count.ShouldBe(1); + offerList.Value.First().Price.Amount.ShouldBe(101_00000000); + } + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(1); - offerList.Value.First().Price.Amount.ShouldBe(101_00000000); - } - - { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 90_00000000); - } - - { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(1); - } + Symbol = "ELF", + Owner = User2Address + }); + balance.Balance.ShouldBe(InitialELFAmount - 90_00000000); + } + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = DefaultAddress - }); - nftBalance.Balance.ShouldBe(9); - } + Symbol = symbol, + TokenId = 233, + Owner = User2Address + }); + nftBalance.Balance.ShouldBe(1); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 3, - Price = new Price - { - Symbol = "ELF", - Amount = 110_00000000 - }, + Owner = DefaultAddress }); + nftBalance.Balance.ShouldBe(9); + } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 3, + Price = new Price { - var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput - { - Symbol = "ELF", - Owner = User2Address - }); - balance.Balance.ShouldBe(InitialELFAmount - 90_00000000 - 91_00000000); + Symbol = "ELF", + Amount = 110_00000000 } + }); + { + var balance = await TokenContractStub.GetBalance.CallAsync(new MultiToken.GetBalanceInput { - var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User2Address - }); - nftBalance.Balance.ShouldBe(2); - } + Symbol = "ELF", + Owner = User2Address + }); + balance.Balance.ShouldBe(InitialELFAmount - 90_00000000 - 91_00000000); + } + { + var nftBalance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(2); - offerList.Value.Last().Price.Amount.ShouldBe(110_00000000); - offerList.Value.Last().Quantity.ShouldBe(2); - } + Symbol = symbol, + TokenId = 233, + Owner = User2Address + }); + nftBalance.Balance.ShouldBe(2); + } - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 201_00000000 - }, + Address = User2Address }); + offerList.Value.Count.ShouldBe(2); + offerList.Value.Last().Price.Amount.ShouldBe(110_00000000); + offerList.Value.Last().Quantity.ShouldBe(2); + } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(3); + Symbol = "ELF", + Amount = 201_00000000 } + }); - await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput { Symbol = symbol, TokenId = 233, - OfferTo = DefaultAddress, - Quantity = 1, - Price = new Price - { - Symbol = "ELF", - Amount = 200_00000000 - }, + Address = User2Address }); + offerList.Value.Count.ShouldBe(3); + } + await BuyerNFTMarketContractStub.MakeOffer.SendAsync(new MakeOfferInput + { + Symbol = symbol, + TokenId = 233, + OfferTo = DefaultAddress, + Quantity = 1, + Price = new Price { - var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - offerList.Value.Count.ShouldBe(3); - offerList.Value.Last().Quantity.ShouldBe(2); + Symbol = "ELF", + Amount = 200_00000000 } + }); + + { + var offerList = await BuyerNFTMarketContractStub.GetOfferList.CallAsync(new GetOfferListInput + { + Symbol = symbol, + TokenId = 233, + Address = User2Address + }); + offerList.Value.Count.ShouldBe(3); + offerList.Value.Last().Quantity.ShouldBe(2); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMinterContractInitializationProvider.cs b/test/AElf.Contracts.NFT.Tests/NFTMinterContractInitializationProvider.cs index cf2854ad5d..79bba1a47e 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMinterContractInitializationProvider.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMinterContractInitializationProvider.cs @@ -3,16 +3,15 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public class NFTMinterContractInitializationProvider : IContractInitializationProvider, ITransientDependency { - public class NFTMinterContractInitializationProvider : IContractInitializationProvider, ITransientDependency - { - public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter"); - public string ContractCodeName { get; } = "AElf.Contracts.NFTMinter"; + public Hash SystemSmartContractName { get; } = HashHelper.ComputeFrom("AElf.ContractNames.NFTMinter"); + public string ContractCodeName { get; } = "AElf.Contracts.NFTMinter"; - public List GetInitializeMethodList(byte[] contractCode) - { - return new List(); - } + public List GetInitializeMethodList(byte[] contractCode) + { + return new List(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMinterContractTests.cs b/test/AElf.Contracts.NFT.Tests/NFTMinterContractTests.cs index 2941e5810a..7606d8a938 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMinterContractTests.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMinterContractTests.cs @@ -5,135 +5,135 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + [Fact] + public async Task CreateBadgeTest() { - [Fact] - public async Task CreateBadgeTest() - { - await InitializeNFTMinterContractAsync(); + await InitializeNFTMinterContractAsync(); - var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + { + ProtocolName = "Top of OASIS", + NftType = NFTType.Badges.ToString(), + TotalSupply = 100_000, + IsBurnable = false, + IsTokenIdReuse = true, + MinterList = new MinterList { - ProtocolName = "Top of OASIS", - NftType = NFTType.Badges.ToString(), - TotalSupply = 100_000, - IsBurnable = false, - IsTokenIdReuse = true, - MinterList = new MinterList - { - Value = { NFTMinterContractAddress} - } - }); - var symbol = executionResult.Output.Value; + Value = { NFTMinterContractAddress } + } + }); + var symbol = executionResult.Output.Value; - await CreatorNFTMinterContractStub.CreateBadge.SendAsync(new CreateBadgeInput + await CreatorNFTMinterContractStub.CreateBadge.SendAsync(new CreateBadgeInput + { + Symbol = symbol, + TokenId = 233, + Alias = "Participant", + Metadata = new BadgeMetadata { - Symbol = symbol, - TokenId = 233, - Alias = "Participant", - Metadata = new BadgeMetadata - { - Value = {["Role"] = "Developer"} - }, - Uri = "https://hackerlink.io/hackathon/13" - }); + Value = { ["Role"] = "Developer" } + }, + Uri = "https://hackerlink.io/hackathon/13" + }); - var nftProtocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue {Value = symbol}); - nftProtocolInfo.TotalSupply.ShouldBe(100_000); + var nftProtocolInfo = await NFTContractStub.GetNFTProtocolInfo.CallAsync(new StringValue { Value = symbol }); + nftProtocolInfo.TotalSupply.ShouldBe(100_000); - return symbol; - } + return symbol; + } - [Fact] - public async Task ConfigBadgeTest() - { - var symbol = await CreateBadgeTest(); + [Fact] + public async Task ConfigBadgeTest() + { + var symbol = await CreateBadgeTest(); - await CreatorNFTMinterContractStub.ConfigBadge.SendAsync(new ConfigBadgeInput - { - Symbol = symbol, - TokenId = 233, - Limit = int.MaxValue, - IsPublic = false - }); + await CreatorNFTMinterContractStub.ConfigBadge.SendAsync(new ConfigBadgeInput + { + Symbol = symbol, + TokenId = 233, + Limit = int.MaxValue, + IsPublic = false + }); - var badgeInfo = await CreatorNFTMinterContractStub.GetBadgeInfo.CallAsync(new GetBadgeInfoInput - { - Symbol = symbol, - TokenId = 233 - }); - badgeInfo.Limit.ShouldBe(int.MaxValue); - badgeInfo.IsPublic.ShouldBe(false); + var badgeInfo = await CreatorNFTMinterContractStub.GetBadgeInfo.CallAsync(new GetBadgeInfoInput + { + Symbol = symbol, + TokenId = 233 + }); + badgeInfo.Limit.ShouldBe(int.MaxValue); + badgeInfo.IsPublic.ShouldBe(false); - return symbol; - } + return symbol; + } - [Fact] - public async Task ManageWhiteListTest() - { - var symbol = await ConfigBadgeTest(); - var executionResult = await CreatorNFTMinterContractStub.ManageMintingWhiteList.SendAsync(new ManageMintingWhiteListInput + [Fact] + public async Task ManageWhiteListTest() + { + var symbol = await ConfigBadgeTest(); + var executionResult = await CreatorNFTMinterContractStub.ManageMintingWhiteList.SendAsync( + new ManageMintingWhiteListInput { Symbol = symbol, TokenId = 233, - AddressList = new NFTMinter.AddressList {Value = {User1Address}} + AddressList = new NFTMinter.AddressList { Value = { User1Address } } }); - var logEvent = - MintingWhiteListChanged.Parser.ParseFrom(executionResult.TransactionResult.Logs.Single().NonIndexed); - logEvent.AddressList.Value.ShouldContain(User1Address); + var logEvent = + MintingWhiteListChanged.Parser.ParseFrom(executionResult.TransactionResult.Logs.Single().NonIndexed); + logEvent.AddressList.Value.ShouldContain(User1Address); - { - var isInWhiteList = await CreatorNFTMinterContractStub.IsInMintingWhiteList.CallAsync( - new IsInMintingWhiteListInput - { - Symbol = symbol, - TokenId = 233, - Address = User1Address - }); - isInWhiteList.Value.ShouldBeTrue(); - } - { - var isInWhiteList = await CreatorNFTMinterContractStub.IsInMintingWhiteList.CallAsync( - new IsInMintingWhiteListInput - { - Symbol = symbol, - TokenId = 233, - Address = User2Address - }); - isInWhiteList.Value.ShouldBeFalse(); - } - return symbol; + { + var isInWhiteList = await CreatorNFTMinterContractStub.IsInMintingWhiteList.CallAsync( + new IsInMintingWhiteListInput + { + Symbol = symbol, + TokenId = 233, + Address = User1Address + }); + isInWhiteList.Value.ShouldBeTrue(); } + { + var isInWhiteList = await CreatorNFTMinterContractStub.IsInMintingWhiteList.CallAsync( + new IsInMintingWhiteListInput + { + Symbol = symbol, + TokenId = 233, + Address = User2Address + }); + isInWhiteList.Value.ShouldBeFalse(); + } + return symbol; + } - [Fact] - public async Task MintBadgeTest() + [Fact] + public async Task MintBadgeTest() + { + var symbol = await ManageWhiteListTest(); + await UserNFTMinterContractStub.MintBadge.SendAsync(new MintBadgeInput { - var symbol = await ManageWhiteListTest(); - await UserNFTMinterContractStub.MintBadge.SendAsync(new MintBadgeInput - { - Symbol = symbol, - TokenId = 233 - }); - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 233, - Owner = User1Address - }); - balance.Balance.ShouldBe(1); + Symbol = symbol, + TokenId = 233 + }); + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = symbol, + TokenId = 233, + Owner = User1Address + }); + balance.Balance.ShouldBe(1); - return symbol; - } + return symbol; + } - private async Task InitializeNFTMinterContractAsync() + private async Task InitializeNFTMinterContractAsync() + { + await CreatorNFTMinterContractStub.Initialize.SendAsync(new InitializeInput { - await CreatorNFTMinterContractStub.Initialize.SendAsync(new InitializeInput - { - NftContractAddress = NFTContractAddress, - AdminAddress = DefaultAddress - }); - } + NftContractAddress = NFTContractAddress, + AdminAddress = DefaultAddress + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.NFT.Tests/NFTMinterContract_BlindBox.cs b/test/AElf.Contracts.NFT.Tests/NFTMinterContract_BlindBox.cs index c1a6e621ca..3ecf0f8350 100644 --- a/test/AElf.Contracts.NFT.Tests/NFTMinterContract_BlindBox.cs +++ b/test/AElf.Contracts.NFT.Tests/NFTMinterContract_BlindBox.cs @@ -4,120 +4,119 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.NFT +namespace AElf.Contracts.NFT; + +public partial class NFTContractTests { - public partial class NFTContractTests + [Fact] + public async Task BoxTest() { - [Fact] - public async Task BoxTest() - { - await InitializeNFTMinterContractAsync(); + await InitializeNFTMinterContractAsync(); - var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + var executionResult = await NFTContractStub.Create.SendAsync(new CreateInput + { + ProtocolName = "Virtual World Something", + NftType = NFTType.VirtualWorlds.ToString(), + TotalSupply = 100_000, + IsBurnable = false, + IsTokenIdReuse = false, + MinterList = new MinterList { - ProtocolName = "Virtual World Something", - NftType = NFTType.VirtualWorlds.ToString(), - TotalSupply = 100_000, - IsBurnable = false, - IsTokenIdReuse = false, - MinterList = new MinterList - { - Value = {NFTMinterContractAddress} - } - }); - var symbol = executionResult.Output.Value; + Value = { NFTMinterContractAddress } + } + }); + var symbol = executionResult.Output.Value; - await CreatorNFTMinterContractStub.Box.SendAsync(new BoxInput + await CreatorNFTMinterContractStub.Box.SendAsync(new BoxInput + { + Symbol = symbol, + IsTokenIdFixed = false, + TemplateList = new NFTTemplateList { - Symbol = symbol, - IsTokenIdFixed = false, - TemplateList = new NFTTemplateList + Value = { - Value = + new NFTTemplate { - new NFTTemplate + Symbol = symbol, + Alias = "Normal", + Metadata = new TemplateMetadata { - Symbol = symbol, - Alias = "Normal", - Metadata = new TemplateMetadata - { - Value = {["Quality"] = "Normal", ["Value"] = "10"} - }, - Quantity = 700, - TokenId = 1, - Weight = 100 + Value = { ["Quality"] = "Normal", ["Value"] = "10" } }, - new NFTTemplate + Quantity = 700, + TokenId = 1, + Weight = 100 + }, + new NFTTemplate + { + Symbol = symbol, + Alias = "Rare", + Metadata = new TemplateMetadata { - Symbol = symbol, - Alias = "Rare", - Metadata = new TemplateMetadata - { - Value = {["Quality"] = "Rare", ["Value"] = "200"} - }, - Quantity = 200, - TokenId = 701, - Weight = 10 + Value = { ["Quality"] = "Rare", ["Value"] = "200" } }, - new NFTTemplate + Quantity = 200, + TokenId = 701, + Weight = 10 + }, + new NFTTemplate + { + Symbol = symbol, + Alias = "Legend", + Metadata = new TemplateMetadata { - Symbol = symbol, - Alias = "Legend", - Metadata = new TemplateMetadata - { - Value = {["Quality"] = "Legend", ["Value"] = "1000"} - }, - Quantity = 100, - TokenId = 901, - Weight = 1 - } + Value = { ["Quality"] = "Legend", ["Value"] = "1000" } + }, + Quantity = 100, + TokenId = 901, + Weight = 1 } - }, - CostSymbol = "ELF", - CostAmount = 1_00000000, - }); + } + }, + CostSymbol = "ELF", + CostAmount = 1_00000000 + }); - var blindBoxInfo = await CreatorNFTMinterContractStub.GetBlindBoxInfo.CallAsync(new GetBlindBoxInfoInput - { - Symbol = symbol - }); - blindBoxInfo.SupposedEndTokenId.ShouldBe(1000); - return symbol; - } + var blindBoxInfo = await CreatorNFTMinterContractStub.GetBlindBoxInfo.CallAsync(new GetBlindBoxInfoInput + { + Symbol = symbol + }); + blindBoxInfo.SupposedEndTokenId.ShouldBe(1000); + return symbol; + } + + [Fact] + public async Task UnboxTest() + { + var symbol = await BoxTest(); - [Fact] - public async Task UnboxTest() + await TokenContractStub.Issue.SendAsync(new IssueInput { - var symbol = await BoxTest(); + Symbol = "ELF", + To = User1Address, + Amount = 10000_00000000 + }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - To = User1Address, - Amount = 10000_00000000 - }); + await UserTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput + { + Symbol = "ELF", + Amount = 10000_00000000, + Spender = NFTMinterContractAddress + }); - await UserTokenContractStub.Approve.SendAsync(new MultiToken.ApproveInput - { - Symbol = "ELF", - Amount = 10000_00000000, - Spender = NFTMinterContractAddress - }); + await UserNFTMinterContractStub.Unbox.SendAsync(new UnboxInput + { + Symbol = symbol + }); - await UserNFTMinterContractStub.Unbox.SendAsync(new UnboxInput + { + var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput { - Symbol = symbol + Symbol = symbol, + TokenId = 1, + Owner = User1Address }); - - { - var balance = await NFTContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - TokenId = 1, - Owner = User1Address - }); - balance.Balance.ShouldBe(1); - } + balance.Balance.ShouldBe(1); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Parliament.Tests/AElf.Contracts.Parliament.Tests.csproj b/test/AElf.Contracts.Parliament.Tests/AElf.Contracts.Parliament.Tests.csproj index 3bf7beda48..193cf20dfa 100644 --- a/test/AElf.Contracts.Parliament.Tests/AElf.Contracts.Parliament.Tests.csproj +++ b/test/AElf.Contracts.Parliament.Tests/AElf.Contracts.Parliament.Tests.csproj @@ -10,16 +10,16 @@ 0436 - - - - - - + + + + + + - - + + @@ -85,6 +85,6 @@ Protobuf\Proto\configuration_contract_impl.proto - - + + diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractPrivilegeTest.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractPrivilegeTest.cs index 04435b7633..3e764f8555 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractPrivilegeTest.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractPrivilegeTest.cs @@ -1,201 +1,198 @@ using System.Threading.Tasks; -using AElf.Standards.ACS3; -using AElf.ContractTestKit; using AElf.Cryptography; -using AElf.Cryptography.ECDSA; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public class ParliamentContractPrivilegeTest : ParliamentContractPrivilegeTestBase { - public class ParliamentContractPrivilegeTest : ParliamentContractPrivilegeTestBase + [Fact] + public async Task CreateProposal_WithPrivileged_Test() { - [Fact] - public async Task CreateProposal_WithPrivileged_Test() - { - var organizationAddress = await GetDefaultOrganizationAddressAsync(); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var otherTester = Tester.CreateNewContractTester(ecKeyPair); - var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); - var createProposalInput = CreateProposalInput(transferInput, organizationAddress); - - var result = await otherTester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Unauthorized to propose.").ShouldBeTrue(); - - //verify with view method - var byteString = await otherTester.CallContractMethodAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateProposerInWhiteList), - new ValidateProposerInWhiteListInput - { - OrganizationAddress = organizationAddress, - Proposer = Address.FromPublicKey(ecKeyPair.PublicKey) - }); - var verifyResult = BoolValue.Parser.ParseFrom(byteString); - verifyResult.Value.ShouldBeFalse(); - } - - [Fact] - public async Task CreateProposal_Creator_Test() - { - var organizationAddress = await GetDefaultOrganizationAddressAsync(); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var otherTester = Tester.CreateNewContractTester(ecKeyPair); - var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); - var createProposalInput = CreateProposalInput(transferInput, organizationAddress); - - var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Mined); - } - - [Fact] - public async Task CreateProposal_Miner_Test() - { - var organizationAddress = await GetDefaultOrganizationAddressAsync(); - var miner = Tester.CreateNewContractTester(Tester.InitialMinerList[0]); - var transferInput = TransferInput(miner.GetCallOwnerAddress()); - var createProposalInput = CreateProposalInput(transferInput, organizationAddress); - - var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Mined); - } - - [Fact] - public async Task CreateProposal_WithoutPrivilege_Test() - { - var organizationAddress = await CreateOrganizationAsync(true); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var otherTester = Tester.CreateNewContractTester(ecKeyPair); - var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); - var createProposalInput = CreateProposalInput(transferInput, organizationAddress); - - var result = await otherTester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - createProposalInput); - result.Status.ShouldBe(TransactionResultStatus.Failed); - } - - [Fact] - public async Task ChangeOrganizationProposerWhiteList_Without_Authority_Test() - { - var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ChangeOrganizationProposerWhiteList), - new ProposerWhiteList()); - result.Error.ShouldContain("No permission"); - } - - [Fact] - public async Task Change_OrganizationProposalWhiteList_Test() - { - var organizationAddress = await GetDefaultOrganizationAddressAsync(); - var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetProposerWhiteList), new Empty()); - var proposers = ProposerWhiteList.Parser.ParseFrom(result.ReturnValue).Proposers; + var organizationAddress = await GetDefaultOrganizationAddressAsync(); + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + var otherTester = Tester.CreateNewContractTester(ecKeyPair); + var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); + var createProposalInput = CreateProposalInput(transferInput, organizationAddress); + + var result = await otherTester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Unauthorized to propose.").ShouldBeTrue(); + + //verify with view method + var byteString = await otherTester.CallContractMethodAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateProposerInWhiteList), + new ValidateProposerInWhiteListInput + { + OrganizationAddress = organizationAddress, + Proposer = Address.FromPublicKey(ecKeyPair.PublicKey) + }); + var verifyResult = BoolValue.Parser.ParseFrom(byteString); + verifyResult.Value.ShouldBeFalse(); + } - proposers.Count.ShouldBe(1); - proposers.Contains(Tester.GetCallOwnerAddress()).ShouldBeTrue(); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); + [Fact] + public async Task CreateProposal_Creator_Test() + { + var organizationAddress = await GetDefaultOrganizationAddressAsync(); + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + var otherTester = Tester.CreateNewContractTester(ecKeyPair); + var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); + var createProposalInput = CreateProposalInput(transferInput, organizationAddress); + + var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Mined); + } - var proposerWhiteList = new ProposerWhiteList - { - Proposers = {Tester.GetAddress(ecKeyPair)} - }; - var proposalInput = CreateParliamentProposalInput(proposerWhiteList, organizationAddress); - var createResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - proposalInput); - createResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = Hash.Parser.ParseFrom(createResult.ReturnValue); - await ParliamentMemberApprove(proposalId); - var releaseResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); - releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); - - result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetProposerWhiteList), new Empty()); - proposers = ProposerWhiteList.Parser.ParseFrom(result.ReturnValue).Proposers; - proposers.Count.ShouldBe(1); - proposers.Contains(Tester.GetAddress(ecKeyPair)).ShouldBeTrue(); - } - - [Fact] - public async Task ValidateAddressIsParliamentMember_Test() + [Fact] + public async Task CreateProposal_Miner_Test() + { + var organizationAddress = await GetDefaultOrganizationAddressAsync(); + var miner = Tester.CreateNewContractTester(Tester.InitialMinerList[0]); + var transferInput = TransferInput(miner.GetCallOwnerAddress()); + var createProposalInput = CreateProposalInput(transferInput, organizationAddress); + + var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task CreateProposal_WithoutPrivilege_Test() + { + var organizationAddress = await CreateOrganizationAsync(true); + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + var otherTester = Tester.CreateNewContractTester(ecKeyPair); + var transferInput = TransferInput(otherTester.GetCallOwnerAddress()); + var createProposalInput = CreateProposalInput(transferInput, organizationAddress); + + var result = await otherTester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + createProposalInput); + result.Status.ShouldBe(TransactionResultStatus.Failed); + } + + [Fact] + public async Task ChangeOrganizationProposerWhiteList_Without_Authority_Test() + { + var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ChangeOrganizationProposerWhiteList), + new ProposerWhiteList()); + result.Error.ShouldContain("No permission"); + } + + [Fact] + public async Task Change_OrganizationProposalWhiteList_Test() + { + var organizationAddress = await GetDefaultOrganizationAddressAsync(); + var result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetProposerWhiteList), new Empty()); + var proposers = ProposerWhiteList.Parser.ParseFrom(result.ReturnValue).Proposers; + + proposers.Count.ShouldBe(1); + proposers.Contains(Tester.GetCallOwnerAddress()).ShouldBeTrue(); + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + + var proposerWhiteList = new ProposerWhiteList { - //miner member - var byteResult = await Tester.CallContractMethodAsync( - ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateAddressIsParliamentMember), - Address.FromPublicKey(Tester.InitialMinerList[0].PublicKey)); - var checkMinerResult = BoolValue.Parser.ParseFrom(byteResult); - checkMinerResult.Value.ShouldBeTrue(); - - //none miner member - var tester = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey); - byteResult = await Tester.CallContractMethodAsync( - ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateAddressIsParliamentMember), - tester); - var checkTesterResult = BoolValue.Parser.ParseFrom(byteResult); - checkTesterResult.Value.ShouldBeFalse(); - } - - private async Task
CreateOrganizationAsync(bool proposerAuthorityRequired = false) + Proposers = { Tester.GetAddress(ecKeyPair) } + }; + var proposalInput = CreateParliamentProposalInput(proposerWhiteList, organizationAddress); + var createResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + proposalInput); + createResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = Hash.Parser.ParseFrom(createResult.ReturnValue); + await ParliamentMemberApprove(proposalId); + var releaseResult = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); + releaseResult.Status.ShouldBe(TransactionResultStatus.Mined); + + result = await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetProposerWhiteList), new Empty()); + proposers = ProposerWhiteList.Parser.ParseFrom(result.ReturnValue).Proposers; + proposers.Count.ShouldBe(1); + proposers.Contains(Tester.GetAddress(ecKeyPair)).ShouldBeTrue(); + } + + [Fact] + public async Task ValidateAddressIsParliamentMember_Test() + { + //miner member + var byteResult = await Tester.CallContractMethodAsync( + ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateAddressIsParliamentMember), + Address.FromPublicKey(Tester.InitialMinerList[0].PublicKey)); + var checkMinerResult = BoolValue.Parser.ParseFrom(byteResult); + checkMinerResult.Value.ShouldBeTrue(); + + //none miner member + var tester = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey); + byteResult = await Tester.CallContractMethodAsync( + ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ValidateAddressIsParliamentMember), + tester); + var checkTesterResult = BoolValue.Parser.ParseFrom(byteResult); + checkTesterResult.Value.ShouldBeFalse(); + } + + private async Task
CreateOrganizationAsync(bool proposerAuthorityRequired = false) + { + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var createOrganizationInput = new CreateOrganizationInput { - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var createOrganizationInput = new CreateOrganizationInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApprovalThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold, - MinimalVoteThreshold = minimalVoteThreshold - }, - ProposerAuthorityRequired = proposerAuthorityRequired - }; - var transactionResult = - await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), - createOrganizationInput); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - return Address.Parser.ParseFrom(transactionResult.ReturnValue); - } - - private async Task
GetDefaultOrganizationAddressAsync() - { - var result = (await Tester.ExecuteContractWithMiningAsync( - ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), - new Empty())); - return Address.Parser.ParseFrom(result.ReturnValue); - } - - private async Task ParliamentMemberApprove(Hash proposalId) - { - var miner = Tester.CreateNewContractTester(Tester.InitialMinerList[0]); - (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status - .ShouldBe(TransactionResultStatus.Mined); - miner = Tester.CreateNewContractTester(Tester.InitialMinerList[1]); - (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status - .ShouldBe(TransactionResultStatus.Mined); - miner = Tester.CreateNewContractTester(Tester.InitialMinerList[2]); - (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status - .ShouldBe(TransactionResultStatus.Mined); - } + MinimalApprovalThreshold = minimalApprovalThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold, + MinimalVoteThreshold = minimalVoteThreshold + }, + ProposerAuthorityRequired = proposerAuthorityRequired + }; + var transactionResult = + await Tester.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateOrganization), + createOrganizationInput); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + return Address.Parser.ParseFrom(transactionResult.ReturnValue); + } + + private async Task
GetDefaultOrganizationAddressAsync() + { + var result = await Tester.ExecuteContractWithMiningAsync( + ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), + new Empty()); + return Address.Parser.ParseFrom(result.ReturnValue); + } + + private async Task ParliamentMemberApprove(Hash proposalId) + { + var miner = Tester.CreateNewContractTester(Tester.InitialMinerList[0]); + (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status + .ShouldBe(TransactionResultStatus.Mined); + miner = Tester.CreateNewContractTester(Tester.InitialMinerList[1]); + (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status + .ShouldBe(TransactionResultStatus.Mined); + miner = Tester.CreateNewContractTester(Tester.InitialMinerList[2]); + (await miner.ExecuteContractWithMiningAsync(ParliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), proposalId)).Status + .ShouldBe(TransactionResultStatus.Mined); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs index f91bb90eea..d7d0439103 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs @@ -1,8 +1,6 @@ using System; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; @@ -10,1097 +8,1064 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Parliament -{ - public class ParliamentContractTest : ParliamentContractTestBase - { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ISmartContractAddressNameProvider _smartContractAddressNameProvider; - public ParliamentContractTest() - { - _blockchainService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _smartContractAddressNameProvider = GetRequiredService(); - InitializeContracts(); - } - - [Fact] - public async Task Get_DefaultOrganizationAddress_Test() - { - var transactionResult = - await ParliamentContractStub.GetDefaultOrganizationAddress.SendWithExceptionAsync(new Empty()); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Not initialized.").ShouldBeTrue(); - - await InitializeParliamentContracts(); - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - defaultParliamentAddress.ShouldNotBeNull(); - } - - [Fact] - public async Task ParliamentContract_Initialize_Test() - { - var result = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - [Fact] - public async Task ParliamentContract_InitializeTwice_Test() - { - await ParliamentContract_Initialize_Test(); +namespace AElf.Contracts.Parliament; - var result = await ParliamentContractStub.Initialize.SendWithExceptionAsync(new InitializeInput()); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); - } +public class ParliamentContractTest : ParliamentContractTestBase +{ + private readonly IBlockchainService _blockchainService; + private readonly ISmartContractAddressNameProvider _smartContractAddressNameProvider; + private readonly ISmartContractAddressService _smartContractAddressService; - [Fact] - public async Task Get_Organization_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 10000 / MinersCount; - var maximalAbstentionThreshold = 2000 / MinersCount; - var maximalRejectionThreshold = 3000 / MinersCount; - var minimalVoteThreshold = 11000 / MinersCount; + public ParliamentContractTest() + { + _blockchainService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _smartContractAddressNameProvider = GetRequiredService(); + InitializeContracts(); + } - var createOrganizationInput = new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApprovalThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold, - MinimalVoteThreshold = minimalVoteThreshold - } - }; - var minerParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs.First()); - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); - var organizationCalculated = ParliamentContractStub.CalculateOrganizationAddress - .CallAsync(createOrganizationInput).Result; - var organizationAddress = transactionResult.Output; - organizationCalculated.ShouldBe(organizationAddress); - var getOrganization = await ParliamentContractStub.GetOrganization.CallAsync(organizationAddress); - - getOrganization.OrganizationAddress.ShouldBe(organizationAddress); - getOrganization.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApprovalThreshold); - getOrganization.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(minimalVoteThreshold); - getOrganization.ProposalReleaseThreshold.MaximalAbstentionThreshold.ShouldBe(maximalAbstentionThreshold); - getOrganization.ProposalReleaseThreshold.MaximalRejectionThreshold.ShouldBe(maximalRejectionThreshold); - getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); - } + [Fact] + public async Task Get_DefaultOrganizationAddress_Test() + { + var transactionResult = + await ParliamentContractStub.GetDefaultOrganizationAddress.SendWithExceptionAsync(new Empty()); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Not initialized.").ShouldBeTrue(); + + await InitializeParliamentContracts(); + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + defaultParliamentAddress.ShouldNotBeNull(); + } - [Fact] - public async Task Get_OrganizationFailed_Test() - { - var organization = - await ParliamentContractStub.GetOrganization.CallAsync(Accounts[0].Address); - organization.ShouldBe(new Organization()); - } + [Fact] + public async Task ParliamentContract_Initialize_Test() + { + var result = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - [Fact] - public async Task Get_Proposal_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = Tester - }; - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var getProposal = await ParliamentContractStub.GetProposal.SendAsync(proposalId); - - getProposal.Output.Proposer.ShouldBe(DefaultSender); - getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContractStub.Transfer)); - getProposal.Output.ProposalId.ShouldBe(proposalId); - getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); - getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); - - var transferParam = TransferInput.Parser.ParseFrom(getProposal.Output.Params); - transferParam.Symbol.ShouldBe(transferInput.Symbol); - transferParam.Amount.ShouldBe(transferInput.Amount); - transferParam.To.ShouldBe(transferInput.To); - } - - [Fact] - public async Task ApproveMultiProposals_Without_Authority_Test() - { - var invalidSenderStub = - GetTester(ParliamentContractAddress, TesterKeyPair); - var approveRet = - await invalidSenderStub.ApproveMultiProposals.SendWithExceptionAsync(new ProposalIdList()); - approveRet.TransactionResult.Error.ShouldContain("No permission"); - } + [Fact] + public async Task ParliamentContract_InitializeTwice_Test() + { + await ParliamentContract_Initialize_Test(); - [Fact] - public async Task ApproveMultiProposals_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId1 = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var proposalId2 = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var transactionResult = - await ParliamentContractStub.ApproveMultiProposals.SendAsync(new ProposalIdList - { - ProposalIds = {proposalId1, proposalId2} - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposal1 = await ParliamentContractStub.GetProposal.CallAsync(proposalId1); - proposal1.ApprovalCount.ShouldBe(1); - var proposal2 = await ParliamentContractStub.GetProposal.CallAsync(proposalId1); - proposal2.ApprovalCount.ShouldBe(1); - } + var result = await ParliamentContractStub.Initialize.SendWithExceptionAsync(new InitializeInput()); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); + } - [Fact] - public async Task Get_ProposalFailed_Test() - { - var proposalOutput = await ParliamentContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); - proposalOutput.ShouldBe(new ProposalOutput()); - } + [Fact] + public async Task Get_Organization_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 10000 / MinersCount; + var maximalAbstentionThreshold = 2000 / MinersCount; + var maximalRejectionThreshold = 3000 / MinersCount; + var minimalVoteThreshold = 11000 / MinersCount; - [Fact] - public async Task Create_OrganizationFailed_Test() + var createOrganizationInput = new CreateOrganizationInput { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var proposalReleaseThreshold = new ProposalReleaseThreshold + ProposalReleaseThreshold = new ProposalReleaseThreshold { MinimalApprovalThreshold = minimalApprovalThreshold, MaximalAbstentionThreshold = maximalAbstentionThreshold, MaximalRejectionThreshold = maximalRejectionThreshold, MinimalVoteThreshold = minimalVoteThreshold - }; - - var createOrganizationInput = new CreateOrganizationInput - { - ProposalReleaseThreshold = proposalReleaseThreshold.Clone() - }; - - var minerParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - - { - var transactionResult = - await ParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to create organization."); - } - - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 10000; - createOrganizationInput.ProposalReleaseThreshold.MinimalVoteThreshold = 10000; - createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = 0; - createOrganizationInput.ProposalReleaseThreshold.MaximalRejectionThreshold = 0; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 0; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } + }; + var minerParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs.First()); + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); + var organizationCalculated = ParliamentContractStub.CalculateOrganizationAddress + .CallAsync(createOrganizationInput).Result; + var organizationAddress = transactionResult.Output; + organizationCalculated.ShouldBe(organizationAddress); + var getOrganization = await ParliamentContractStub.GetOrganization.CallAsync(organizationAddress); + + getOrganization.OrganizationAddress.ShouldBe(organizationAddress); + getOrganization.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApprovalThreshold); + getOrganization.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(minimalVoteThreshold); + getOrganization.ProposalReleaseThreshold.MaximalAbstentionThreshold.ShouldBe(maximalAbstentionThreshold); + getOrganization.ProposalReleaseThreshold.MaximalRejectionThreshold.ShouldBe(maximalRejectionThreshold); + getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); + } - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = -1; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + [Fact] + public async Task Get_OrganizationFailed_Test() + { + var organization = + await ParliamentContractStub.GetOrganization.CallAsync(Accounts[0].Address); + organization.ShouldBe(new Organization()); + } - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = -1; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + [Fact] + public async Task Get_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var transferInput = new TransferInput + { + Symbol = "ELF", + Amount = 100, + To = Tester + }; + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var getProposal = await ParliamentContractStub.GetProposal.SendAsync(proposalId); + + getProposal.Output.Proposer.ShouldBe(DefaultSender); + getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContractStub.Transfer)); + getProposal.Output.ProposalId.ShouldBe(proposalId); + getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); + getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); + + var transferParam = TransferInput.Parser.ParseFrom(getProposal.Output.Params); + transferParam.Symbol.ShouldBe(transferInput.Symbol); + transferParam.Amount.ShouldBe(transferInput.Amount); + transferParam.To.ShouldBe(transferInput.To); + } - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = 3334; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + [Fact] + public async Task ApproveMultiProposals_Without_Authority_Test() + { + var invalidSenderStub = + GetTester(ParliamentContractAddress, + TesterKeyPair); + var approveRet = + await invalidSenderStub.ApproveMultiProposals.SendWithExceptionAsync(new ProposalIdList()); + approveRet.TransactionResult.Error.ShouldContain("No permission"); + } + [Fact] + public async Task ApproveMultiProposals_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId1 = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var proposalId2 = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var transactionResult = + await ParliamentContractStub.ApproveMultiProposals.SendAsync(new ProposalIdList { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MaximalRejectionThreshold = 3334; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } + ProposalIds = { proposalId1, proposalId2 } + }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposal1 = await ParliamentContractStub.GetProposal.CallAsync(proposalId1); + proposal1.ApprovalCount.ShouldBe(1); + var proposal2 = await ParliamentContractStub.GetProposal.CallAsync(proposalId1); + proposal2.ApprovalCount.ShouldBe(1); + } - { - createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; - createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 10001; - var transactionResult = - await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); - } - } + [Fact] + public async Task Get_ProposalFailed_Test() + { + var proposalOutput = await ParliamentContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); + proposalOutput.ShouldBe(new ProposalOutput()); + } - [Fact] - public async Task Create_ProposalFailed_Test() + [Fact] + public async Task Create_OrganizationFailed_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var proposalReleaseThreshold = new ProposalReleaseThreshold { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var blockTime = BlockTimeProvider.GetBlockTime(); - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = blockTime.AddDays(1), - OrganizationAddress = organizationAddress - }; - //"Invalid proposal." - //ContractMethodName is null or white space - { - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //ToAddress is null - { - createProposalInput.ContractMethodName = "Test"; - createProposalInput.ToAddress = null; + MinimalApprovalThreshold = minimalApprovalThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold, + MinimalVoteThreshold = minimalVoteThreshold + }; - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //ExpiredTime is null - { - createProposalInput.ExpiredTime = null; - createProposalInput.ToAddress = Accounts[0].Address; + var createOrganizationInput = new CreateOrganizationInput + { + ProposalReleaseThreshold = proposalReleaseThreshold.Clone() + }; - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - //"Expired proposal." - { - createProposalInput.ExpiredTime = TimestampHelper.GetUtcNow().AddSeconds(-1); - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - //"No registered organization." - { - createProposalInput.ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1); - createProposalInput.OrganizationAddress = Accounts[1].Address; + var minerParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("No registered organization.").ShouldBeTrue(); - } - //"Proposal with same input." - { - createProposalInput.OrganizationAddress = organizationAddress; - var transactionResult1 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var transactionResult = + await ParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to create organization."); + } - var transactionResult2 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - // invalid proposal description url - { - createProposalInput.ProposalDescriptionUrl = "www.abc.com"; - var transactionResult = - await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - - createProposalInput.ProposalDescriptionUrl = "http://www.abc.com"; - var transactionResult1 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + { + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 10000; + createOrganizationInput.ProposalReleaseThreshold.MinimalVoteThreshold = 10000; + createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = 0; + createOrganizationInput.ProposalReleaseThreshold.MaximalRejectionThreshold = 0; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact] - public async Task Approve_Proposal_NotFoundProposal_Test() { + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 0; var transactionResult = - await ParliamentContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Approve_Proposal_NotAuthorizedApproval_Test() { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); - var transactionResult = await ParliamentContractStub.Approve.SendWithExceptionAsync(proposalId); + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = -1; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Unauthorized sender.").ShouldBeTrue(); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Approve_Proposal_ExpiredTime_Test() { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var error = await parliamentContractStub.Approve.CallWithExceptionAsync(proposalId); - error.Value.ShouldContain("Invalid proposal."); + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = -1; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Approve_Proposal_ApprovalAlreadyExists_Test() { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var transactionResult1 = - await ParliamentContractStub.Approve.SendAsync(proposalId); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transactionResult2 = - await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Error.Contains("Already approved").ShouldBeTrue(); - - var transactionResult3 = - await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); - transactionResult3.TransactionResult.Error.Contains("Already approved").ShouldBeTrue(); + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = 3334; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - [Fact] - public async Task Reject_Without_Authority_Test() { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); - var transactionResult1 = - await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Unauthorized sender"); + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MaximalRejectionThreshold = 3334; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } - - [Fact] - public async Task Reject_With_Invalid_Proposal_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - - // proposal does not exist - { - var transactionResult1 = await ParliamentContractStub.Reject.SendWithExceptionAsync(new Hash()); - transactionResult1.TransactionResult.Error.ShouldContain("Proposal not found"); - } - - //proposal expired - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var transactionResult1 = - await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Invalid proposal"); - } + { + createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; + createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 10001; + var transactionResult = + await minerParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid organization.").ShouldBeTrue(); } + } - [Fact] - public async Task Reject_Approved_Proposal_Test() + [Fact] + public async Task Create_ProposalFailed_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var blockTime = BlockTimeProvider.GetBlockTime(); + var createProposalInput = new CreateProposalInput { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = blockTime.AddDays(1), + OrganizationAddress = organizationAddress + }; + //"Invalid proposal." + //ContractMethodName is null or white space + { + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); + } + //ToAddress is null + { + createProposalInput.ContractMethodName = "Test"; + createProposalInput.ToAddress = null; - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var transactionResult1 = - await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Already approved"); + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); } - - [Fact] - public async Task Reject_Success_Test() + //ExpiredTime is null { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + createProposalInput.ExpiredTime = null; + createProposalInput.ToAddress = Accounts[0].Address; - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ParliamentContractStub.Reject.SendAsync(proposalId); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.RejectionCount.ShouldBe(1); + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); } - - [Fact] - public async Task Abstain_Without_Authority_Test() + //"Expired proposal." { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); - var transactionResult1 = - await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Unauthorized sender"); + createProposalInput.ExpiredTime = TimestampHelper.GetUtcNow().AddSeconds(-1); + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); } - - [Fact] - public async Task Abstain_With_Invalid_Proposal_Test() + //"No registered organization." { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + createProposalInput.ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(1); + createProposalInput.OrganizationAddress = Accounts[1].Address; - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - - // proposal does not exist - { - var transactionResult1 = await ParliamentContractStub.Abstain.SendWithExceptionAsync(new Hash()); - transactionResult1.TransactionResult.Error.ShouldContain("Proposal not found"); - } - - //proposal expired - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var transactionResult1 = - await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Invalid proposal"); - } + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("No registered organization.").ShouldBeTrue(); } - - [Fact] - public async Task Abstain_Approved_Proposal_Test() + //"Proposal with same input." { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + createProposalInput.OrganizationAddress = organizationAddress; + var transactionResult1 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var transactionResult1 = - await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); - transactionResult1.TransactionResult.Error.ShouldContain("Already approved"); + var transactionResult2 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - [Fact] - public async Task Abstain_Success_Test() + // invalid proposal description url { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + createProposalInput.ProposalDescriptionUrl = "www.abc.com"; + var transactionResult = + await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ParliamentContractStub.Abstain.SendAsync(proposalId); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.AbstentionCount.ShouldBe(1); + createProposalInput.ProposalDescriptionUrl = "http://www.abc.com"; + var transactionResult1 = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - [Fact] - public async Task Check_Proposal_ToBeReleased() - { - await InitializeParliamentContracts(); + [Fact] + public async Task Approve_Proposal_NotFoundProposal_Test() + { + var transactionResult = + await ParliamentContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } - { - var minimalApprovalThreshold = 3000; - var maximalAbstentionThreshold = 3000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 6000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - - // Rejection probability > maximalRejectionThreshold - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - //Voted reviewer is not enough - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - //Approve probability > minimalApprovalThreshold - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); - //Rejection probability > maximalRejectionThreshold - await RejectionAsync(InitialMinersKeyPairs[2], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - } - // Abstain probability > maximalAbstentionThreshold - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - //Voted reviewer is not enough - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - //Approve probability > minimalApprovalThreshold - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); - //Abstain probability > maximalAbstentionThreshold - await AbstainAsync(InitialMinersKeyPairs[2], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - } - } - { - var minimalApprovalThreshold = 3000; - var maximalAbstentionThreshold = 6000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 6000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - //Approve probability > minimalApprovalThreshold - await AbstainAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); - } - } - } + [Fact] + public async Task Approve_Proposal_NotAuthorizedApproval_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); + var transactionResult = await ParliamentContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Unauthorized sender.").ShouldBeTrue(); + } - [Fact] - public async Task Release_NotEnoughApprove_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - //Reviewer Shares < ReleaseThreshold, release failed - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); - } + [Fact] + public async Task Approve_Proposal_ExpiredTime_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var error = await parliamentContractStub.Approve.CallWithExceptionAsync(proposalId); + error.Value.ShouldContain("Invalid proposal."); + } - [Fact] - public async Task Release_NotFound_Test() - { - var proposalId = HashHelper.ComputeFrom("test"); - var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - //Proposal not found - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); - } + [Fact] + public async Task Approve_Proposal_ApprovalAlreadyExists_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var transactionResult1 = + await ParliamentContractStub.Approve.SendAsync(proposalId); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transactionResult2 = + await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Error.Contains("Already approved").ShouldBeTrue(); + + var transactionResult3 = + await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); + transactionResult3.TransactionResult.Error.Contains("Already approved").ShouldBeTrue(); + } - [Fact] - public async Task Release_WrongSender_Test() + [Fact] + public async Task Reject_Without_Authority_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); + var transactionResult1 = + await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Unauthorized sender"); + } + + [Fact] + public async Task Reject_With_Invalid_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + + // proposal does not exist { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - - ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); - var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + var transactionResult1 = await ParliamentContractStub.Reject.SendWithExceptionAsync(new Hash()); + transactionResult1.TransactionResult.Error.ShouldContain("Proposal not found"); } - - [Fact] - public async Task Release_Expired_Proposal_Test() + + //proposal expired { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Error.ShouldContain("Invalid proposal"); + var transactionResult1 = + await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Invalid proposal"); } + } - [Fact] - public async Task Release_Proposal_Test() - { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + [Fact] + public async Task Reject_Approved_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ParliamentContractStub.Approve.SendAsync(proposalId); + var transactionResult1 = + await ParliamentContractStub.Reject.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Already approved"); + } - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var result = await ParliamentContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Reject_Success_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ParliamentContractStub.Reject.SendAsync(proposalId); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.RejectionCount.ShouldBe(1); + } - // Check inline transaction result - var getBalance = TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = "ELF", - Owner = Tester - }).Result.Balance; - getBalance.ShouldBe(100); + [Fact] + public async Task Abstain_Without_Authority_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); + var transactionResult1 = + await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Unauthorized sender"); + } - var proposalInfo = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposalInfo.ShouldBe(new ProposalOutput()); - } + [Fact] + public async Task Abstain_With_Invalid_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - [Fact] - public async Task Release_Proposal_AlreadyReleased_Test() + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + + // proposal does not exist { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); - - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var txResult1 = await ParliamentContractStub.Release.SendAsync(proposalId); - txResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); - var transactionResult2 = - await ParliamentContractStub.Approve.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult2.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); - - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - var transactionResult3 = - await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - transactionResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult3.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); + var transactionResult1 = await ParliamentContractStub.Abstain.SendWithExceptionAsync(new Hash()); + transactionResult1.TransactionResult.Error.ShouldContain("Proposal not found"); } - [Fact] - public async Task Change_OrganizationThreshold_With_Invalid_Sender_Test() + //proposal expired { - var changeOrganizationThresholdRet = - await ParliamentContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( - new ProposalReleaseThreshold()); - changeOrganizationThresholdRet.TransactionResult.Error.ShouldContain("Organization not found"); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var transactionResult1 = + await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Invalid proposal"); } - - [Fact] - public async Task Change_OrganizationThreshold_Test() + } + + [Fact] + public async Task Abstain_Approved_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ParliamentContractStub.Approve.SendAsync(proposalId); + var transactionResult1 = + await ParliamentContractStub.Abstain.SendWithExceptionAsync(proposalId); + transactionResult1.TransactionResult.Error.ShouldContain("Already approved"); + } + + [Fact] + public async Task Abstain_Success_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ParliamentContractStub.Abstain.SendAsync(proposalId); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.AbstentionCount.ShouldBe(1); + } + + [Fact] + public async Task Check_Proposal_ToBeReleased() + { + await InitializeParliamentContracts(); + { - await InitializeParliamentContracts(); var minimalApprovalThreshold = 3000; var maximalAbstentionThreshold = 3000; var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 3000; + var minimalVoteThreshold = 6000; var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); + // Rejection probability > maximalRejectionThreshold { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 6000 - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(ParliamentContractStub.ChangeOrganizationThreshold), - ToAddress = ParliamentContractAddress, - Params = proposalReleaseThresholdInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var changeProposal = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); - changeProposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var changeProposalId = changeProposal.Output; - await ApproveAsync(InitialMinersKeyPairs[0], changeProposalId); - var result = await ParliamentContractStub.Release.SendWithExceptionAsync(changeProposalId); - result.TransactionResult.Error.ShouldContain("Invalid organization."); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + //Voted reviewer is not enough + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); + //Approve probability > minimalApprovalThreshold + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); + //Rejection probability > maximalRejectionThreshold + await RejectionAsync(InitialMinersKeyPairs[2], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); } + // Abstain probability > maximalAbstentionThreshold { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 6000, - MinimalApprovalThreshold = minimalApprovalThreshold - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(ParliamentContractStub.ChangeOrganizationThreshold), - ToAddress = ParliamentContractAddress, - Params = proposalReleaseThresholdInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var changeProposal = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); - changeProposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var changeProposalId = changeProposal.Output; - await ApproveAsync(InitialMinersKeyPairs[0], changeProposalId); - var result = await ParliamentContractStub.Release.SendAsync(changeProposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var organizationInfo = await ParliamentContractStub.GetOrganization.CallAsync(organizationAddress); - organizationInfo.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(proposalReleaseThresholdInput.MinimalVoteThreshold); - organizationInfo.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApprovalThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + //Voted reviewer is not enough + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); + //Approve probability > minimalApprovalThreshold + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); + //Abstain probability > maximalAbstentionThreshold + await AbstainAsync(InitialMinersKeyPairs[2], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); } } - - [Fact] - public async Task Check_ValidProposal_Test() { - await InitializeParliamentContracts(); - - var minimalApprovalThreshold = 6000; - var maximalAbstentionThreshold = 2000; + var minimalApprovalThreshold = 3000; + var maximalAbstentionThreshold = 6000; var maximalRejectionThreshold = 3000; var minimalVoteThreshold = 6000; var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await TransferToOrganizationAddressAsync(organizationAddress); - - //Get valid Proposal - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); - var validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalId} - }); - validProposals.ProposalIds.Count.ShouldBe(1); - var notVotedProposals = await parliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList { - ProposalIds = {proposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(1); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + //Approve probability > minimalApprovalThreshold + await AbstainAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); + } + } + } - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalId} - }); - validProposals.ProposalIds.Count.ShouldBe(0); + [Fact] + public async Task Release_NotEnoughApprove_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + //Reviewer Shares < ReleaseThreshold, release failed + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); + } - parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); - validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalId} - }); - validProposals.ProposalIds.Count.ShouldBe(0); - notVotedProposals = await parliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(1); - } + [Fact] + public async Task Release_NotFound_Test() + { + var proposalId = HashHelper.ComputeFrom("test"); + var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + //Proposal not found + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); + } - [Fact] - public async Task Clear_NotExpiredProposal_Test() - { - await InitializeParliamentContracts(); - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var miner = InitialMinersKeyPairs[1]; - // proposal does not exist - { - var clearProposalRet = await ParliamentContractStub.ClearProposal.SendWithExceptionAsync(new Hash()); - clearProposalRet.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } - - // proposal is not expired - { var proposalId = await CreateProposalAsync(miner, defaultParliamentAddress); - var clearProposalRet = await ParliamentContractStub.ClearProposal.SendWithExceptionAsync(proposalId); - clearProposalRet.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } - } + [Fact] + public async Task Release_WrongSender_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + + ParliamentContractStub = GetParliamentContractTester(TesterKeyPair); + var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + } + + [Fact] + public async Task Release_Expired_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var result = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Error.ShouldContain("Invalid proposal"); + } - [Fact] - public async Task Clear_ExpiredProposal_Test() + [Fact] + public async Task Release_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var result = await ParliamentContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check inline transaction result + var getBalance = TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await InitializeParliamentContracts(); + Symbol = "ELF", + Owner = Tester + }).Result.Balance; + getBalance.ShouldBe(100); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var proposalInfo = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposalInfo.ShouldBe(new ProposalOutput()); + } - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var error = await ParliamentContractStub.Approve.CallWithExceptionAsync(proposalId); - error.Value.ShouldContain("Invalid proposal."); + [Fact] + public async Task Release_Proposal_AlreadyReleased_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var txResult1 = await ParliamentContractStub.Release.SendAsync(proposalId); + txResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); + var transactionResult2 = + await ParliamentContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult2.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); + + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + var transactionResult3 = + await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + transactionResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult3.TransactionResult.Error.Contains("Proposal not found.").ShouldBeTrue(); + } - var clear = await ParliamentContractStub.ClearProposal.SendAsync(proposalId); - clear.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); - proposal.ShouldBe(new ProposalOutput()); - } + [Fact] + public async Task Change_OrganizationThreshold_With_Invalid_Sender_Test() + { + var changeOrganizationThresholdRet = + await ParliamentContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( + new ProposalReleaseThreshold()); + changeOrganizationThresholdRet.TransactionResult.Error.ShouldContain("Organization not found"); + } - [Fact] - public async Task ChangeMethodFeeController_Test() - { - await InitializeParliamentContracts(); - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var createOrganizationResult = - await parliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(parliamentContractStub.ChangeMethodFeeController); - var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress - }); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + [Fact] + public async Task Change_OrganizationThreshold_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 3000; + var maximalAbstentionThreshold = 3000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 3000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); - var releaseResult = await parliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + { + var proposalReleaseThresholdInput = new ProposalReleaseThreshold + { + MinimalVoteThreshold = 6000 + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(ParliamentContractStub.ChangeOrganizationThreshold), + ToAddress = ParliamentContractAddress, + Params = proposalReleaseThresholdInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var changeProposal = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + changeProposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var changeProposalId = changeProposal.Output; + await ApproveAsync(InitialMinersKeyPairs[0], changeProposalId); + var result = await ParliamentContractStub.Release.SendWithExceptionAsync(changeProposalId); + result.TransactionResult.Error.ShouldContain("Invalid organization."); + } + { + var proposalReleaseThresholdInput = new ProposalReleaseThreshold + { + MinimalVoteThreshold = 6000, + MinimalApprovalThreshold = minimalApprovalThreshold + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(ParliamentContractStub.ChangeOrganizationThreshold), + ToAddress = ParliamentContractAddress, + Params = proposalReleaseThresholdInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var changeProposal = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + changeProposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var changeProposalId = changeProposal.Output; + await ApproveAsync(InitialMinersKeyPairs[0], changeProposalId); + var result = await ParliamentContractStub.Release.SendAsync(changeProposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var newMethodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + var organizationInfo = await ParliamentContractStub.GetOrganization.CallAsync(organizationAddress); + organizationInfo.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(proposalReleaseThresholdInput + .MinimalVoteThreshold); + organizationInfo.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApprovalThreshold); } + } - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() + [Fact] + public async Task Check_ValidProposal_Test() + { + await InitializeParliamentContracts(); + + var minimalApprovalThreshold = 6000; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 6000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await TransferToOrganizationAddressAsync(organizationAddress); + + //Get valid Proposal + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); + var validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + ProposalIds = { proposalId } + }); + validProposals.ProposalIds.Count.ShouldBe(1); + var notVotedProposals = await parliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList + { + ProposalIds = { proposalId } + }); + notVotedProposals.ProposalIds.Count.ShouldBe(1); - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var result = await parliamentContractStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress - }); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList + { + ProposalIds = { proposalId } + }); + validProposals.ProposalIds.Count.ShouldBe(0); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } - - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Authority_Test() + parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); + validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList { - await InitializeParliamentContracts(); - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - - - var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(parliamentContractStub.ChangeMethodFeeController); - var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = ParliamentContractAddress, - ContractAddress = ParliamentContractAddress - }); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + ProposalIds = { proposalId } + }); + validProposals.ProposalIds.Count.ShouldBe(0); + notVotedProposals = await parliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList + { + ProposalIds = { proposalId } + }); + notVotedProposals.ProposalIds.Count.ShouldBe(1); + } - var releaseResult = await parliamentContractStub.Release.SendWithExceptionAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); + [Fact] + public async Task Clear_NotExpiredProposal_Test() + { + await InitializeParliamentContracts(); + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var miner = InitialMinersKeyPairs[1]; + // proposal does not exist + { + var clearProposalRet = await ParliamentContractStub.ClearProposal.SendWithExceptionAsync(new Hash()); + clearProposalRet.TransactionResult.Error.ShouldContain("Proposal clear failed"); } - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() + // proposal is not expired { - // token symbol does not exist - { - var tokenSymbol = "NOTEXIST"; - var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + var proposalId = await CreateProposalAsync(miner, defaultParliamentAddress); + var clearProposalRet = await ParliamentContractStub.ClearProposal.SendWithExceptionAsync(proposalId); + clearProposalRet.TransactionResult.Error.ShouldContain("Proposal clear failed"); + } + } + + [Fact] + public async Task Clear_ExpiredProposal_Test() + { + await InitializeParliamentContracts(); + + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var error = await ParliamentContractStub.Approve.CallWithExceptionAsync(proposalId); + error.Value.ShouldContain("Invalid proposal."); + + var clear = await ParliamentContractStub.ClearProposal.SendAsync(proposalId); + clear.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposal = await ParliamentContractStub.GetProposal.CallAsync(proposalId); + proposal.ShouldBe(new ProposalOutput()); + } + + [Fact] + public async Task ChangeMethodFeeController_Test() + { + await InitializeParliamentContracts(); + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var createOrganizationResult = + await parliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - MethodName = nameof(ParliamentContractStub.Abstain), - Fees = + ProposalReleaseThreshold = new ProposalReleaseThreshold { - new MethodFee - { - Symbol = tokenSymbol, - BasicFee = 100 - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("token is not found"); - } - - // amount < 0 + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + + var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); + + const string proposalCreationMethodName = nameof(parliamentContractStub.ChangeMethodFeeController); + var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { - var invalidAmount = -1; - var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees - { - MethodName = nameof(ParliamentContractStub.Abstain), - Fees = - { - new MethodFee - { - Symbol = "ELF", - BasicFee = invalidAmount - } - } - }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount"); - } - } + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); - [Fact] - public async Task SetMethodFee_Without_Authority_Test() + var releaseResult = await parliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMethodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var result = await parliamentContractStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Authority_Test() + { + await InitializeParliamentContracts(); + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + + + var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); + + const string proposalCreationMethodName = nameof(parliamentContractStub.ChangeMethodFeeController); + var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + { + OwnerAddress = ParliamentContractAddress, + ContractAddress = ParliamentContractAddress + }); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + + var releaseResult = await parliamentContractStub.Release.SendWithExceptionAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + // token symbol does not exist { - await InitializeParliamentContracts(); + var tokenSymbol = "NOTEXIST"; var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { MethodName = nameof(ParliamentContractStub.Abstain), @@ -1108,288 +1073,270 @@ public async Task SetMethodFee_Without_Authority_Test() { new MethodFee { - Symbol = "ELF", + Symbol = tokenSymbol, BasicFee = 100 } } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); + setMethodFeeRet.TransactionResult.Error.ShouldContain("token is not found"); } - [Fact] - public async Task SetMethodFee_Success_Test() + // amount < 0 { - await InitializeParliamentContracts(); - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); - var methodFeeName = nameof(parliamentContractStub.Abstain); - var tokenSymbol = "ELF"; - var fee = 100; - var methodFees = new MethodFees + var invalidAmount = -1; + var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - MethodName = methodFeeName, + MethodName = nameof(ParliamentContractStub.Abstain), Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = fee + Symbol = "ELF", + BasicFee = invalidAmount } } - }; - const string proposalCreationMethodName = nameof(parliamentContractStub.SetMethodFee); - var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, methodFees); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); - await parliamentContractStub.Release.SendAsync(proposalId); - var methodFee = await parliamentContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodFeeName - }); - methodFee.MethodName.ShouldBe(methodFeeName); - methodFee.Fees.Count.ShouldBe(1); - methodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - methodFee.Fees[0].BasicFee.ShouldBe(fee); - - // method name = ApproveMultiProposals - var specialMethodName = nameof(parliamentContractStub.ApproveMultiProposals); - methodFees.MethodName = specialMethodName; - proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, methodFees); - await ApproveAsync(InitialMinersKeyPairs[0], proposalId); - await ApproveAsync(InitialMinersKeyPairs[1], proposalId); - await ApproveAsync(InitialMinersKeyPairs[2], proposalId); - await parliamentContractStub.Release.SendAsync(proposalId); - methodFee = await parliamentContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = specialMethodName }); - methodFee.Fees.Count.ShouldBe(0); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount"); } + } - [Fact] - public async Task CreateOrganizationBySystemContract_Fail_Test() - { - var createOrganizationRet = - await ParliamentContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync( - new CreateOrganizationBySystemContractInput()); - createOrganizationRet.TransactionResult.Error.ShouldContain("Unauthorized"); - } - - [Fact] - public async Task CreateOrganizationBySystemContract_Success_Test() + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + await InitializeParliamentContracts(); + var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex + MethodName = nameof(ParliamentContractStub.Abstain), + Fees = { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); + new MethodFee + { + Symbol = "ELF", + BasicFee = 100 + } + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee"); + } - var createOrganizationInput = new CreateOrganizationBySystemContractInput + [Fact] + public async Task SetMethodFee_Success_Test() + { + await InitializeParliamentContracts(); + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); + var methodFeeName = nameof(parliamentContractStub.Abstain); + var tokenSymbol = "ELF"; + var fee = 100; + var methodFees = new MethodFees + { + MethodName = methodFeeName, + Fees = { - OrganizationCreationInput = new CreateOrganizationInput + new MethodFee { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000, - } - }, - OrganizationAddressFeedbackMethod = string.Empty - }; - var createOrganizationRet = - await ParliamentContractStub.CreateOrganizationBySystemContract.SendAsync(createOrganizationInput); - createOrganizationRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = tokenSymbol, + BasicFee = fee + } + } + }; + const string proposalCreationMethodName = nameof(parliamentContractStub.SetMethodFee); + var proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, methodFees); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + await parliamentContractStub.Release.SendAsync(proposalId); + var methodFee = await parliamentContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodFeeName + }); + methodFee.MethodName.ShouldBe(methodFeeName); + methodFee.Fees.Count.ShouldBe(1); + methodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + methodFee.Fees[0].BasicFee.ShouldBe(fee); + + // method name = ApproveMultiProposals + var specialMethodName = nameof(parliamentContractStub.ApproveMultiProposals); + methodFees.MethodName = specialMethodName; + proposalId = await CreateFeeProposalAsync(ParliamentContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, methodFees); + await ApproveAsync(InitialMinersKeyPairs[0], proposalId); + await ApproveAsync(InitialMinersKeyPairs[1], proposalId); + await ApproveAsync(InitialMinersKeyPairs[2], proposalId); + await parliamentContractStub.Release.SendAsync(proposalId); + methodFee = await parliamentContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = specialMethodName + }); + methodFee.Fees.Count.ShouldBe(0); + } + + [Fact] + public async Task CreateOrganizationBySystemContract_Fail_Test() + { + var createOrganizationRet = + await ParliamentContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync( + new CreateOrganizationBySystemContractInput()); + createOrganizationRet.TransactionResult.Error.ShouldContain("Unauthorized"); + } - [Fact] - public async Task ValidateOrganizationExist_Test() + [Fact] + public async Task CreateOrganizationBySystemContract_Success_Test() + { + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var isOrganizationExist = - await ParliamentContractStub.ValidateOrganizationExist.CallAsync(organizationAddress); - isOrganizationExist.Value.ShouldBeTrue(); - - isOrganizationExist = - await ParliamentContractStub.ValidateOrganizationExist.CallAsync(ParliamentContractAddress); - isOrganizationExist.Value.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateProposerInWhiteList_Test() + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + + var createOrganizationInput = new CreateOrganizationBySystemContractInput { - var proposer = DefaultSender; - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + OrganizationCreationInput = new CreateOrganizationInput { - PrivilegedProposer = proposer - }); - var isProposerInWhitelist = - await ParliamentContractStub.ValidateProposerInWhiteList.CallAsync(new ValidateProposerInWhiteListInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - Proposer = proposer - }); - isProposerInWhitelist.Value.ShouldBeTrue(); - - isProposerInWhitelist = - await ParliamentContractStub.ValidateProposerInWhiteList.CallAsync(new ValidateProposerInWhiteListInput()); - isProposerInWhitelist.Value.ShouldBeFalse(); - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }, + OrganizationAddressFeedbackMethod = string.Empty + }; + var createOrganizationRet = + await ParliamentContractStub.CreateOrganizationBySystemContract.SendAsync(createOrganizationInput); + createOrganizationRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task ValidateOrganizationExist_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var isOrganizationExist = + await ParliamentContractStub.ValidateOrganizationExist.CallAsync(organizationAddress); + isOrganizationExist.Value.ShouldBeTrue(); + + isOrganizationExist = + await ParliamentContractStub.ValidateOrganizationExist.CallAsync(ParliamentContractAddress); + isOrganizationExist.Value.ShouldBeFalse(); + } - [Fact] - public async Task CreateProposalBySystemContract_Fail_Test() + [Fact] + public async Task ValidateProposerInWhiteList_Test() + { + var proposer = DefaultSender; + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput { - // not be authorized - { - var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendWithExceptionAsync( - new CreateProposalBySystemContractInput()); - ret.TransactionResult.Error.ShouldContain("Unauthorized to propose"); - } - - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - - // invalid organization + PrivilegedProposer = proposer + }); + var isProposerInWhitelist = + await ParliamentContractStub.ValidateProposerInWhiteList.CallAsync(new ValidateProposerInWhiteListInput { - var invalidInput = new CreateProposalBySystemContractInput - { - ProposalInput = new CreateProposalInput - { - OrganizationAddress = ParliamentContractAddress - }, - OriginProposer = DefaultSender, - }; - var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendWithExceptionAsync( - invalidInput); - ret.TransactionResult.Error.ShouldContain("No registered organization"); - } + Proposer = proposer + }); + isProposerInWhitelist.Value.ShouldBeTrue(); + + isProposerInWhitelist = + await ParliamentContractStub.ValidateProposerInWhiteList.CallAsync(new ValidateProposerInWhiteListInput()); + isProposerInWhitelist.Value.ShouldBeFalse(); + } + + [Fact] + public async Task CreateProposalBySystemContract_Fail_Test() + { + // not be authorized + { + var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendWithExceptionAsync( + new CreateProposalBySystemContractInput()); + ret.TransactionResult.Error.ShouldContain("Unauthorized to propose"); } - [Fact] - public async Task CreateProposalBySystemContract_Success_Test() + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex { - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput - { - PrivilegedProposer = DefaultSender - }); - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var chain = _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - var input = new CreateProposalBySystemContractInput + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + + // invalid organization + { + var invalidInput = new CreateProposalBySystemContractInput { ProposalInput = new CreateProposalInput { - OrganizationAddress = defaultParliamentAddress, - ToAddress = TokenContractAddress, - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), - Params = new TransferInput - { - Amount = 100, - Symbol = "ELF", - To = DefaultSender - }.ToByteString(), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + OrganizationAddress = ParliamentContractAddress }, OriginProposer = DefaultSender }; - var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendAsync( - input); - ret.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendWithExceptionAsync( + invalidInput); + ret.TransactionResult.Error.ShouldContain("No registered organization"); } + } - [Fact] - public async Task GetNotVotedProposals_With_Invalid_Proposal_Test() + [Fact] + public async Task CreateProposalBySystemContract_Success_Test() + { + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput { - // proposal does not exist - { - var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); - var notVotedProposals = await ParliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList - { - ProposalIds = {invalidProposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(0); - } - - //fail to validate proposal, proposal expires + PrivilegedProposer = DefaultSender + }); + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + var input = new CreateProposalBySystemContractInput + { + ProposalInput = new CreateProposalInput { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var notVotedProposals = await ParliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList + OrganizationAddress = defaultParliamentAddress, + ToAddress = TokenContractAddress, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), + Params = new TransferInput { - ProposalIds = {proposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(0); - } - } + Amount = 100, + Symbol = "ELF", + To = DefaultSender + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }, + OriginProposer = DefaultSender + }; + var ret = await ParliamentContractStub.CreateProposalBySystemContract.SendAsync( + input); + ret.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - [Fact] - public async Task GetNotVotedPendingProposals_With_Invalid_Proposal_Test() + [Fact] + public async Task GetNotVotedProposals_With_Invalid_Proposal_Test() + { + // proposal does not exist { - // proposal does not exist - { - var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); - var notVotedProposals = await ParliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {invalidProposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(0); - } - //fail to validate proposal, proposal expires + var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); + var notVotedProposals = await ParliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList { - await InitializeParliamentContracts(); - var minimalApprovalThreshold = 6667; - var maximalAbstentionThreshold = 2000; - var maximalRejectionThreshold = 3000; - var minimalVoteThreshold = 8000; - var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); - var notVotedProposals = await ParliamentContractStub.GetNotVotedPendingProposals.CallAsync( - new ProposalIdList - { - ProposalIds = {proposalId} - }); - notVotedProposals.ProposalIds.Count.ShouldBe(0); - } + ProposalIds = { invalidProposalId } + }); + notVotedProposals.ProposalIds.Count.ShouldBe(0); } - [Fact] - public async Task ApproveMultiProposals_With_Invalid_Proposal_Test() + //fail to validate proposal, proposal expires { await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; @@ -1398,193 +1345,249 @@ public async Task ApproveMultiProposals_With_Invalid_Proposal_Test() var minimalVoteThreshold = 8000; var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); - var expiredProposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var transactionResult = - await ParliamentContractStub.ApproveMultiProposals.SendAsync(new ProposalIdList + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var notVotedProposals = await ParliamentContractStub.GetNotVotedProposals.CallAsync(new ProposalIdList + { + ProposalIds = { proposalId } + }); + notVotedProposals.ProposalIds.Count.ShouldBe(0); + } + } + + [Fact] + public async Task GetNotVotedPendingProposals_With_Invalid_Proposal_Test() + { + // proposal does not exist + { + var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); + var notVotedProposals = await ParliamentContractStub.GetNotVotedPendingProposals.CallAsync( + new ProposalIdList { - ProposalIds = {invalidProposalId, expiredProposalId} + ProposalIds = { invalidProposalId } }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + notVotedProposals.ProposalIds.Count.ShouldBe(0); } - - [Fact] - public async Task Check_ValidProposal_With_Rejected_Test() + //fail to validate proposal, proposal expires { await InitializeParliamentContracts(); - - var minimalApprovalThreshold = 6000; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var minimalVoteThreshold = 6000; + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); - - //reject proposal - var proposalTobeRejectedId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); - var validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalTobeRejectedId} - }); - validProposals.ProposalIds.Count.ShouldBe(1); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await RejectionAsync(InitialMinersKeyPairs[0], proposalTobeRejectedId); - validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalTobeRejectedId} - }); - validProposals.ProposalIds.Count.ShouldBe(0); - - //abstain proposal - var proposalTobeAbstainedId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList - { - ProposalIds = {proposalTobeAbstainedId} - }); - validProposals.ProposalIds.Count.ShouldBe(1); + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + BlockTimeProvider.SetBlockTime(BlockTimeProvider.GetBlockTime().AddDays(5)); + var notVotedProposals = await ParliamentContractStub.GetNotVotedPendingProposals.CallAsync( + new ProposalIdList + { + ProposalIds = { proposalId } + }); + notVotedProposals.ProposalIds.Count.ShouldBe(0); + } + } - await AbstainAsync(InitialMinersKeyPairs[0], proposalTobeAbstainedId); - validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList + [Fact] + public async Task ApproveMultiProposals_With_Invalid_Proposal_Test() + { + await InitializeParliamentContracts(); + var minimalApprovalThreshold = 6667; + var maximalAbstentionThreshold = 2000; + var maximalRejectionThreshold = 3000; + var minimalVoteThreshold = 8000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + var invalidProposalId = HashHelper.ComputeFrom("invalid hash"); + var expiredProposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + ParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var transactionResult = + await ParliamentContractStub.ApproveMultiProposals.SendAsync(new ProposalIdList { - ProposalIds = {proposalTobeAbstainedId} + ProposalIds = { invalidProposalId, expiredProposalId } }); - validProposals.ProposalIds.Count.ShouldBe(0); - } - - private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress) + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task Check_ValidProposal_With_Rejected_Test() + { + await InitializeParliamentContracts(); + + var minimalApprovalThreshold = 6000; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var minimalVoteThreshold = 6000; + var organizationAddress = await CreateOrganizationAsync(minimalApprovalThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, minimalVoteThreshold); + + //reject proposal + var proposalTobeRejectedId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[2]); + var validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList { - var transferInput = new TransferInput() - { - Symbol = "ELF", - Amount = 100, - To = Tester, - Memo = Guid.NewGuid().ToString() //In order to generate different proposal - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var parliamentContractStub = GetParliamentContractTester(proposalKeyPair); - var proposal = await parliamentContractStub.CreateProposal.SendAsync(createProposalInput); - proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposal.Output.ShouldBe(proposalCreated); - - return proposal.Output; - } + ProposalIds = { proposalTobeRejectedId } + }); + validProposals.ProposalIds.Count.ShouldBe(1); - private async Task
CreateOrganizationAsync(int minimalApprovalThreshold, - int maximalAbstentionThreshold, int maximalRejectionThreshold, int minimalVoteThreshold) + await RejectionAsync(InitialMinersKeyPairs[0], proposalTobeRejectedId); + validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList { - var createOrganizationInput = new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApprovalThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold, - MinimalVoteThreshold = minimalVoteThreshold - } - }; - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var transactionResult = - await parliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + ProposalIds = { proposalTobeRejectedId } + }); + validProposals.ProposalIds.Count.ShouldBe(0); - return transactionResult.Output; - } + //abstain proposal + var proposalTobeAbstainedId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList + { + ProposalIds = { proposalTobeAbstainedId } + }); + validProposals.ProposalIds.Count.ShouldBe(1); - private async Task TransferToOrganizationAddressAsync(Address to) + await AbstainAsync(InitialMinersKeyPairs[0], proposalTobeAbstainedId); + validProposals = await parliamentContractStub.GetNotVotedPendingProposals.CallAsync(new ProposalIdList { - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "ELF", - Amount = 200, - To = to, - Memo = "transfer organization address" - }); - } + ProposalIds = { proposalTobeAbstainedId } + }); + validProposals.ProposalIds.Count.ShouldBe(0); + } - private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) + private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress) + { + var transferInput = new TransferInput { - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var parliamentContractStub = GetParliamentContractTester(reviewer); - var transactionResult = - await parliamentContractStub.Approve.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(parliamentContractStub.Approve)); - } + Symbol = "ELF", + Amount = 100, + To = Tester, + Memo = Guid.NewGuid().ToString() //In order to generate different proposal + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var parliamentContractStub = GetParliamentContractTester(proposalKeyPair); + var proposal = await parliamentContractStub.CreateProposal.SendAsync(createProposalInput); + proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposal.Output.ShouldBe(proposalCreated); + + return proposal.Output; + } - private async Task RejectionAsync(ECKeyPair reviewer, Hash proposalId) + private async Task
CreateOrganizationAsync(int minimalApprovalThreshold, + int maximalAbstentionThreshold, int maximalRejectionThreshold, int minimalVoteThreshold) + { + var createOrganizationInput = new CreateOrganizationInput { - var parliamentContractStub = GetParliamentContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = - await parliamentContractStub.Reject.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(parliamentContractStub.Reject)); - } + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = minimalApprovalThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold, + MinimalVoteThreshold = minimalVoteThreshold + } + }; + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var transactionResult = + await parliamentContractStub.CreateOrganization.SendAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) + return transactionResult.Output; + } + + private async Task TransferToOrganizationAddressAsync(Address to) + { + await TokenContractStub.Transfer.SendAsync(new TransferInput { - var parliamentContractStub = GetParliamentContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = - await parliamentContractStub.Abstain.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) - ?.NonIndexed); - ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(parliamentContractStub.Abstain)); - } - - private void ValidateReceiptCreated(ReceiptCreated receiptCreated, Address sender, Hash proposalId, - Timestamp blockTime, string receiptType) - { - receiptCreated.Address.ShouldBe(sender); - receiptCreated.ProposalId.ShouldBe(proposalId); - receiptCreated.Time.ShouldBe(blockTime); - receiptCreated.ReceiptType.ShouldBe(receiptType); - } + Symbol = "ELF", + Amount = 200, + To = to, + Memo = "transfer organization address" + }); + } - private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) + { + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var parliamentContractStub = GetParliamentContractTester(reviewer); + var transactionResult = + await parliamentContractStub.Approve.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(parliamentContractStub.Approve)); + } + + private async Task RejectionAsync(ECKeyPair reviewer, Hash proposalId) + { + var parliamentContractStub = GetParliamentContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = + await parliamentContractStub.Reject.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(parliamentContractStub.Reject)); + } + + private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) + { + var parliamentContractStub = GetParliamentContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = + await parliamentContractStub.Abstain.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReceiptCreated)) + ?.NonIndexed); + ValidateReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(parliamentContractStub.Abstain)); + } + + private void ValidateReceiptCreated(ReceiptCreated receiptCreated, Address sender, Hash proposalId, + Timestamp blockTime, string receiptType) + { + receiptCreated.Address.ShouldBe(sender); + receiptCreated.ProposalId.ShouldBe(proposalId); + receiptCreated.Time.ShouldBe(blockTime); + receiptCreated.ReceiptType.ShouldBe(receiptType); + } + + private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); + var proposal = new CreateProposalInput { - var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await parliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await parliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; - } + return proposalId; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestAElfModule.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestAElfModule.cs index 1897add12e..e7874dfc22 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestAElfModule.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestAElfModule.cs @@ -1,28 +1,27 @@ -using AElf.ContractTestKit; using AElf.Contracts.TestBase; +using AElf.ContractTestKit; using AElf.GovernmentSystem; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +[DependsOn(typeof(ContractTestModule), + typeof(GovernmentSystemAElfModule))] +public class ParliamentContractTestAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule), - typeof(GovernmentSystemAElfModule))] - public class ParliamentContractTestAElfModule : ContractTestModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.RemoveAll(); - } - } - - [DependsOn( - typeof(ContractTestAElfModule) - )] - public class ParliamentContractPrivilegeTestAElfModule : ContractTestAElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); } +} + +[DependsOn( + typeof(ContractTestAElfModule) +)] +public class ParliamentContractPrivilegeTestAElfModule : ContractTestAElfModule +{ } \ No newline at end of file diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs index 595df99c82..4cc77daaa3 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS3; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; @@ -14,200 +12,201 @@ using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Threading; -namespace AElf.Contracts.Parliament +namespace AElf.Contracts.Parliament; + +public class ParliamentContractTestBase : ContractTestKit.ContractTestBase { - public class ParliamentContractTestBase : ContractTestKit.ContractTestBase + protected const int MinersCount = 3; + protected const int MiningInterval = 4000; + protected DateTime BlockchainStartTime => DateTime.Parse("2019-01-01 00:00:00.000").ToUniversalTime(); + + protected byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + protected byte[] ParliamentCode => Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + protected byte[] DPoSConsensusCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; + + protected ECKeyPair DefaultSenderKeyPair => Accounts[10].KeyPair; + protected ECKeyPair TesterKeyPair => Accounts[MinersCount + 1].KeyPair; + protected List InitialMinersKeyPairs => Accounts.Take(MinersCount).Select(a => a.KeyPair).ToList(); + protected Address DefaultSender => Accounts[10].Address; + protected Address Tester => Accounts[MinersCount + 1].Address; + + protected Address TokenContractAddress { get; set; } + protected Address ConsensusContractAddress { get; set; } + protected Address ParliamentContractAddress { get; set; } + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractStub { get; set; } + internal AEDPoSContractContainer.AEDPoSContractStub ConsensusContractStub { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + + + protected void InitializeContracts() { - protected const int MinersCount = 3; - protected const int MiningInterval = 4000; - protected DateTime BlockchainStartTime => DateTime.Parse("2019-01-01 00:00:00.000").ToUniversalTime(); - - protected byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - protected byte[] ParliamentCode => Codes.Single(kv => kv.Key.Contains("Parliament")).Value; - protected byte[] DPoSConsensusCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; - - protected ECKeyPair DefaultSenderKeyPair => Accounts[10].KeyPair; - protected ECKeyPair TesterKeyPair => Accounts[MinersCount + 1].KeyPair; - protected List InitialMinersKeyPairs => Accounts.Take(MinersCount).Select(a => a.KeyPair).ToList(); - protected Address DefaultSender => Accounts[10].Address; - protected Address Tester => Accounts[MinersCount + 1].Address; - - protected Address TokenContractAddress { get; set; } - protected Address ConsensusContractAddress { get; set; } - protected Address ParliamentContractAddress { get; set; } - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractStub { get; set; } - internal AEDPoSContractContainer.AEDPoSContractStub ConsensusContractStub { get; set; } - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } - - - protected void InitializeContracts() - { - //get basic stub - BasicContractStub = - GetContractZeroTester(DefaultSenderKeyPair); - - //deploy Parliament contract - ParliamentContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - ParliamentCode, - ParliamentSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair - )); - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - //deploy token contract - TokenContractAddress = AsyncHelper.RunSync(() => - DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - TokenContractCode, - TokenSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair)); - TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeTokenAsync()); - - ConsensusContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( + //get basic stub + BasicContractStub = + GetContractZeroTester(DefaultSenderKeyPair); + + //deploy Parliament contract + ParliamentContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + ParliamentCode, + ParliamentSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair + )); + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + //deploy token contract + TokenContractAddress = AsyncHelper.RunSync(() => + DeploySystemSmartContract( KernelConstants.CodeCoverageRunnerCategory, - DPoSConsensusCode, - ConsensusSmartContractAddressNameProvider.Name, + TokenContractCode, + TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair)); - ConsensusContractStub = GetConsensusContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeConsensusAsync()); - } + TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeTokenAsync()); + + ConsensusContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + DPoSConsensusCode, + ConsensusSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair)); + ConsensusContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeConsensusAsync()); + } - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal AEDPoSContractContainer.AEDPoSContractStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal AEDPoSContractContainer.AEDPoSContractStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - private async Task InitializeTokenAsync() + private async Task InitializeTokenAsync() + { + const string symbol = "ELF"; + const long totalSupply = 100_000_000; + await TokenContractStub.Create.SendAsync(new CreateInput { - const string symbol = "ELF"; - const long totalSupply = 100_000_000; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - Amount = totalSupply - 20 * 100_000L, - To = DefaultSender, - Memo = "Issue token to default user.", - }); - } - - private async Task InitializeConsensusAsync() + Symbol = symbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender + }); + await TokenContractStub.Issue.SendAsync(new IssueInput { - await ConsensusContractStub.InitialAElfConsensusContract.SendAsync(new InitialAElfConsensusContractInput - { - IsTermStayOne = true - }); - var minerList = new MinerList - {Pubkeys = {InitialMinersKeyPairs.Select(m => ByteStringHelper.FromHexString(m.PublicKey.ToHex()))}}; - await ConsensusContractStub.FirstRound.SendAsync( - minerList.GenerateFirstRoundOfNewTerm(MiningInterval, BlockchainStartTime)); - } - - internal async Task InitializeParliamentContracts() + Symbol = symbol, + Amount = totalSupply - 20 * 100_000L, + To = DefaultSender, + Memo = "Issue token to default user." + }); + } + + private async Task InitializeConsensusAsync() + { + await ConsensusContractStub.InitialAElfConsensusContract.SendAsync(new InitialAElfConsensusContractInput { - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); - } + IsTermStayOne = true + }); + var minerList = new MinerList + { Pubkeys = { InitialMinersKeyPairs.Select(m => ByteStringHelper.FromHexString(m.PublicKey.ToHex())) } }; + await ConsensusContractStub.FirstRound.SendAsync( + minerList.GenerateFirstRoundOfNewTerm(MiningInterval, BlockchainStartTime)); } - public class ParliamentContractPrivilegeTestBase : TestBase.ContractTestBase + internal async Task InitializeParliamentContracts() { - protected Address ParliamentAddress; - protected Address TokenContractAddress; + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); + } +} - protected long TotalSupply; - protected long BalanceOfStarter; - protected new ContractTester Tester; +public class ParliamentContractPrivilegeTestBase : TestBase.ContractTestBase +{ + protected long BalanceOfStarter; + protected Address ParliamentAddress; + protected new ContractTester Tester; + protected Address TokenContractAddress; + protected long TotalSupply; - public ParliamentContractPrivilegeTestBase() - { - var mainChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - var chainId = ChainHelper.GetChainId(1); - Tester = new ContractTester(chainId,SampleECKeyPairs.KeyPairs[1]); - AsyncHelper.RunSync(() => - Tester.InitialChainAsyncWithAuthAsync(Tester.GetSideChainSystemContract( - Tester.GetCallOwnerAddress(), - mainChainId,"STA",out TotalSupply,Tester.GetCallOwnerAddress()))); - ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); - TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); - } - - internal TransferInput TransferInput(Address address) + + public ParliamentContractPrivilegeTestBase() + { + var mainChainId = ChainHelper.ConvertBase58ToChainId("AELF"); + var chainId = ChainHelper.GetChainId(1); + Tester = new ContractTester(chainId, SampleECKeyPairs.KeyPairs[1]); + AsyncHelper.RunSync(() => + Tester.InitialChainAsyncWithAuthAsync(Tester.GetSideChainSystemContract( + Tester.GetCallOwnerAddress(), + mainChainId, "STA", out TotalSupply, Tester.GetCallOwnerAddress()))); + ParliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); + TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + } + + internal TransferInput TransferInput(Address address) + { + var transferInput = new TransferInput { - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = address, - Memo = "Transfer" - }; - return transferInput; - } - - internal CreateProposalInput CreateProposalInput(IMessage input, Address organizationAddress) + Symbol = "ELF", + Amount = 100, + To = address, + Memo = "Transfer" + }; + return transferInput; + } + + internal CreateProposalInput CreateProposalInput(IMessage input, Address organizationAddress) + { + var createProposalInput = new CreateProposalInput { - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), - ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), - Params = input.ToByteString(), - ToAddress = TokenContractAddress, - OrganizationAddress = organizationAddress - }; - return createProposalInput; - } - - internal CreateProposalInput CreateParliamentProposalInput(IMessage input, Address organizationAddress) + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), + ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), + Params = input.ToByteString(), + ToAddress = TokenContractAddress, + OrganizationAddress = organizationAddress + }; + return createProposalInput; + } + + internal CreateProposalInput CreateParliamentProposalInput(IMessage input, Address organizationAddress) + { + var createProposalInput = new CreateProposalInput { - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(ParliamentContractImplContainer.ParliamentContractImplStub.ChangeOrganizationProposerWhiteList), - ToAddress = ParliamentAddress, - Params = input.ToByteString(), - ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), - OrganizationAddress = organizationAddress - }; - return createProposalInput; - } + ContractMethodName = nameof(ParliamentContractImplContainer.ParliamentContractImplStub + .ChangeOrganizationProposerWhiteList), + ToAddress = ParliamentAddress, + Params = input.ToByteString(), + ExpiredTime = DateTime.UtcNow.AddDays(1).ToTimestamp(), + OrganizationAddress = organizationAddress + }; + return createProposalInput; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Parliament.Tests/Types/MinerList.cs b/test/AElf.Contracts.Parliament.Tests/Types/MinerList.cs index c3c824dd95..92b22ad84e 100644 --- a/test/AElf.Contracts.Parliament.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.Parliament.Tests/Types/MinerList.cs @@ -4,52 +4,48 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - DateTime currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval).ToTimestamp(); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; - } + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - public Hash GetMinersHash() + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var orderedMiners = Pubkeys.OrderBy(p => p); - return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval).ToTimestamp(); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; + } + + public Hash GetMinersHash() + { + var orderedMiners = Pubkeys.OrderBy(p => p); + return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/AElf.Contracts.Profit.Tests.csproj b/test/AElf.Contracts.Profit.Tests/AElf.Contracts.Profit.Tests.csproj index 8cbf211f3f..e21fa1e8d6 100644 --- a/test/AElf.Contracts.Profit.Tests/AElf.Contracts.Profit.Tests.csproj +++ b/test/AElf.Contracts.Profit.Tests/AElf.Contracts.Profit.Tests.csproj @@ -10,22 +10,22 @@ 0436 - - - - - - + + + + + + - - - - - - - + + + + + + + diff --git a/test/AElf.Contracts.Profit.Tests/BVT/ProfitItemManagementTests.cs b/test/AElf.Contracts.Profit.Tests/BVT/ProfitItemManagementTests.cs index b5e2f6146a..36ba9c7d00 100644 --- a/test/AElf.Contracts.Profit.Tests/BVT/ProfitItemManagementTests.cs +++ b/test/AElf.Contracts.Profit.Tests/BVT/ProfitItemManagementTests.cs @@ -2,277 +2,276 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; -using AElf.ContractTestKit; using AElf.CSharp.Core; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Contracts.Profit.BVT +namespace AElf.Contracts.Profit.BVT; + +public partial class ProfitContractTests : ProfitContractTestBase { - public partial class ProfitContractTests : ProfitContractTestBase + public ProfitContractTests() { - protected Hash schemeId { get; set; } + InitializeContracts(); + } - public ProfitContractTests() - { - InitializeContracts(); - } - [Fact] - public async Task ProfitContract_CreateScheme_With_Invalid_Input_Test() - { - var creator = Creators[0]; + protected Hash schemeId { get; set; } - var createSchemeRet = await creator.CreateScheme.SendWithExceptionAsync(new CreateSchemeInput - { - ProfitReceivingDuePeriodCount = ProfitContractTestConstants.MaximumProfitReceivingDuePeriodCount + 1, - }); - createSchemeRet.TransactionResult.Error.ShouldContain("Invalid profit receiving due period count"); - - createSchemeRet = await creator.CreateScheme.SendWithExceptionAsync(new CreateSchemeInput - { - ProfitReceivingDuePeriodCount = -1, - }); - createSchemeRet.TransactionResult.Error.ShouldContain("Invalid profit receiving due period count"); - } + [Fact] + public async Task ProfitContract_CreateScheme_With_Invalid_Input_Test() + { + var creator = Creators[0]; - [Fact] - public async Task ProfitContract_CreateScheme_Test() + var createSchemeRet = await creator.CreateScheme.SendWithExceptionAsync(new CreateSchemeInput { - var creator = Creators[0]; - var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); + ProfitReceivingDuePeriodCount = ProfitContractTestConstants.MaximumProfitReceivingDuePeriodCount + 1 + }); + createSchemeRet.TransactionResult.Error.ShouldContain("Invalid profit receiving due period count"); - await creator.CreateScheme.SendAsync(new CreateSchemeInput - { - ProfitReceivingDuePeriodCount = 100, - }); + createSchemeRet = await creator.CreateScheme.SendWithExceptionAsync(new CreateSchemeInput + { + ProfitReceivingDuePeriodCount = -1 + }); + createSchemeRet.TransactionResult.Error.ShouldContain("Invalid profit receiving due period count"); + } - var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = creatorAddress - })).SchemeIds; + [Fact] + public async Task ProfitContract_CreateScheme_Test() + { + var creator = Creators[0]; + var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - createdSchemeIds.Count.ShouldBe(1); + await creator.CreateScheme.SendAsync(new CreateSchemeInput + { + ProfitReceivingDuePeriodCount = 100 + }); - schemeId = createdSchemeIds.First(); + var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = creatorAddress + })).SchemeIds; - const long contributeAmount = (long) (ProfitContractTestConstants.NativeTokenTotalSupply * 0.1); + createdSchemeIds.Count.ShouldBe(1); - await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeId = schemeId, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = contributeAmount - }); + schemeId = createdSchemeIds.First(); - var scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); + const long contributeAmount = (long)(ProfitContractTestConstants.NativeTokenTotalSupply * 0.1); - scheme.Manager.ShouldBe(Address.FromPublicKey(CreatorKeyPair[0].PublicKey)); + await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeId = schemeId, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Amount = contributeAmount + }); - var schemeAddress = await ProfitContractStub.GetSchemeAddress.CallAsync( - new SchemePeriod - { - SchemeId = schemeId - }); - var schemeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Owner = schemeAddress - })).Balance; + var scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); - schemeBalance.ShouldBe(contributeAmount); - } - - [Fact] - public async Task ProfitContract_DistributeProfits_Burned_Profit_Test() - { - const int delayDistributePeriodCount = 3; - const int contributeAmountEachTime = 100_000; - var creator = Creators[0]; - var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); + scheme.Manager.ShouldBe(Address.FromPublicKey(CreatorKeyPair[0].PublicKey)); - await creator.CreateScheme.SendAsync(new CreateSchemeInput + var schemeAddress = await ProfitContractStub.GetSchemeAddress.CallAsync( + new SchemePeriod { - IsReleaseAllBalanceEveryTimeByDefault = true, - ProfitReceivingDuePeriodCount = 100, - DelayDistributePeriodCount = delayDistributePeriodCount + SchemeId = schemeId }); + var schemeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Owner = schemeAddress + })).Balance; - var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = creatorAddress - })).SchemeIds; + schemeBalance.ShouldBe(contributeAmount); + } - schemeId = createdSchemeIds.First(); - var period = 1; - var beforeBurnToken = (await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Supply; - await ContributeAndDistribute(creator, contributeAmountEachTime, period); - var afterBurnToken = (await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Supply; - beforeBurnToken.Sub(afterBurnToken).ShouldBe(contributeAmountEachTime); - } + [Fact] + public async Task ProfitContract_DistributeProfits_Burned_Profit_Test() + { + const int delayDistributePeriodCount = 3; + const int contributeAmountEachTime = 100_000; + var creator = Creators[0]; + var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - [Fact] - public async Task ProfitContract_DelayDistribution_Test() + await creator.CreateScheme.SendAsync(new CreateSchemeInput { - const int delayDistributePeriodCount = 3; - const int contributeAmountEachTime = 100_000; - var creator = Creators[0]; - var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); + IsReleaseAllBalanceEveryTimeByDefault = true, + ProfitReceivingDuePeriodCount = 100, + DelayDistributePeriodCount = delayDistributePeriodCount + }); - await creator.CreateScheme.SendAsync(new CreateSchemeInput - { - IsReleaseAllBalanceEveryTimeByDefault = true, - ProfitReceivingDuePeriodCount = 100, - DelayDistributePeriodCount = delayDistributePeriodCount - }); + var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = creatorAddress + })).SchemeIds; - var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = creatorAddress - })).SchemeIds; + schemeId = createdSchemeIds.First(); + var period = 1; + var beforeBurnToken = (await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Supply; + await ContributeAndDistribute(creator, contributeAmountEachTime, period); + var afterBurnToken = (await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Supply; + beforeBurnToken.Sub(afterBurnToken).ShouldBe(contributeAmountEachTime); + } - schemeId = createdSchemeIds.First(); + [Fact] + public async Task ProfitContract_DelayDistribution_Test() + { + const int delayDistributePeriodCount = 3; + const int contributeAmountEachTime = 100_000; + var creator = Creators[0]; + var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - var periodToTotalShares = new Dictionary(); - var currentShares = 0L; + await creator.CreateScheme.SendAsync(new CreateSchemeInput + { + IsReleaseAllBalanceEveryTimeByDefault = true, + ProfitReceivingDuePeriodCount = 100, + DelayDistributePeriodCount = delayDistributePeriodCount + }); - // Distribute 3 times. - for (var period = 1; period <= 3; period++) - { - currentShares += await AddBeneficiaries(creator); - periodToTotalShares.Add(period, currentShares); + var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = creatorAddress + })).SchemeIds; - await ContributeAndDistribute(creator, contributeAmountEachTime, period); + schemeId = createdSchemeIds.First(); - // Check distributed information. - var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - Period = period, - SchemeId = schemeId - }); - distributedInformation.IsReleased.ShouldBeTrue(); - distributedInformation.TotalShares.ShouldBe(0); - distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(-contributeAmountEachTime); - } + var periodToTotalShares = new Dictionary(); + var currentShares = 0L; - // Distribution of period 4 will use the total shares of period 1. - { - await ContributeAndDistribute(creator, contributeAmountEachTime, 4); - // Check distributed information. - var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - Period = 4, - SchemeId = schemeId - }); - distributedInformation.IsReleased.ShouldBeTrue(); - distributedInformation.TotalShares.ShouldBe(periodToTotalShares[1]); - distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(contributeAmountEachTime); - } + // Distribute 3 times. + for (var period = 1; period <= 3; period++) + { + currentShares += await AddBeneficiaries(creator); + periodToTotalShares.Add(period, currentShares); + + await ContributeAndDistribute(creator, contributeAmountEachTime, period); - // Distribution of period 5 will use the total shares of period 2. + // Check distributed information. + var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - await ContributeAndDistribute(creator, contributeAmountEachTime, 5); - // Check distributed information. - var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - Period = 5, - SchemeId = schemeId - }); - distributedInformation.TotalShares.ShouldBe(periodToTotalShares[2]); - distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(contributeAmountEachTime); - } + Period = period, + SchemeId = schemeId + }); + distributedInformation.IsReleased.ShouldBeTrue(); + distributedInformation.TotalShares.ShouldBe(0); + distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(-contributeAmountEachTime); + } - // Distribution of period 6 will use the total shares of period 3. + // Distribution of period 4 will use the total shares of period 1. + { + await ContributeAndDistribute(creator, contributeAmountEachTime, 4); + // Check distributed information. + var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - await ContributeAndDistribute(creator, contributeAmountEachTime, 6); - // Check distributed information. - var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - Period = 6, - SchemeId = schemeId - }); - distributedInformation.TotalShares.ShouldBe(periodToTotalShares[3]); - distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(contributeAmountEachTime); - } + Period = 4, + SchemeId = schemeId + }); + distributedInformation.IsReleased.ShouldBeTrue(); + distributedInformation.TotalShares.ShouldBe(periodToTotalShares[1]); + distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(contributeAmountEachTime); + } - // Distribution of period 7 will use the total shares of period 4 (same with period 3). + // Distribution of period 5 will use the total shares of period 2. + { + await ContributeAndDistribute(creator, contributeAmountEachTime, 5); + // Check distributed information. + var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - await ContributeAndDistribute(creator, contributeAmountEachTime, 7); - // Check distributed information. - var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod - { - Period = 7, - SchemeId = schemeId - }); - distributedInformation.TotalShares.ShouldBe(periodToTotalShares[3]); - distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(contributeAmountEachTime); - } + Period = 5, + SchemeId = schemeId + }); + distributedInformation.TotalShares.ShouldBe(periodToTotalShares[2]); + distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(contributeAmountEachTime); } - private async Task ContributeAndDistribute(ProfitContractImplContainer.ProfitContractImplStub creator, - int contributeAmountEachTime, int period) + // Distribution of period 6 will use the total shares of period 3. { - await creator.ContributeProfits.SendAsync(new ContributeProfitsInput + await ContributeAndDistribute(creator, contributeAmountEachTime, 6); + // Check distributed information. + var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - Amount = contributeAmountEachTime, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Period = 6, SchemeId = schemeId }); + distributedInformation.TotalShares.ShouldBe(periodToTotalShares[3]); + distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(contributeAmountEachTime); + } - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + // Distribution of period 7 will use the total shares of period 4 (same with period 3). + { + await ContributeAndDistribute(creator, contributeAmountEachTime, 7); + // Check distributed information. + var distributedInformation = await creator.GetDistributedProfitsInfo.CallAsync(new SchemePeriod { - SchemeId = schemeId, - Period = period, + Period = 7, + SchemeId = schemeId }); + distributedInformation.TotalShares.ShouldBe(periodToTotalShares[3]); + distributedInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(contributeAmountEachTime); } + } + + private async Task ContributeAndDistribute(ProfitContractImplContainer.ProfitContractImplStub creator, + int contributeAmountEachTime, int period) + { + await creator.ContributeProfits.SendAsync(new ContributeProfitsInput + { + Amount = contributeAmountEachTime, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + SchemeId = schemeId + }); - private async Task AddBeneficiaries(ProfitContractImplContainer.ProfitContractImplStub creator) + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - await creator.AddBeneficiaries.SendAsync(new AddBeneficiariesInput + SchemeId = schemeId, + Period = period + }); + } + + private async Task AddBeneficiaries(ProfitContractImplContainer.ProfitContractImplStub creator) + { + await creator.AddBeneficiaries.SendAsync(new AddBeneficiariesInput + { + SchemeId = schemeId, + BeneficiaryShares = { - SchemeId = schemeId, - BeneficiaryShares = + new BeneficiaryShare + { + Beneficiary = Accounts[11].Address, + Shares = 1 + }, + new BeneficiaryShare + { + Beneficiary = Accounts[12].Address, + Shares = 1 + }, + new BeneficiaryShare { - new BeneficiaryShare - { - Beneficiary = Accounts[11].Address, - Shares = 1 - }, - new BeneficiaryShare - { - Beneficiary = Accounts[12].Address, - Shares = 1 - }, - new BeneficiaryShare - { - Beneficiary = Accounts[13].Address, - Shares = 1 - }, - new BeneficiaryShare - { - Beneficiary = Accounts[14].Address, - Shares = 1 - }, - new BeneficiaryShare - { - Beneficiary = Accounts[15].Address, - Shares = 1 - }, + Beneficiary = Accounts[13].Address, + Shares = 1 + }, + new BeneficiaryShare + { + Beneficiary = Accounts[14].Address, + Shares = 1 + }, + new BeneficiaryShare + { + Beneficiary = Accounts[15].Address, + Shares = 1 } - }); + } + }); - return 5; - } + return 5; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/BVT/ProfitTests.cs b/test/AElf.Contracts.Profit.Tests/BVT/ProfitTests.cs index f306a1226d..1aa3f08d84 100644 --- a/test/AElf.Contracts.Profit.Tests/BVT/ProfitTests.cs +++ b/test/AElf.Contracts.Profit.Tests/BVT/ProfitTests.cs @@ -1,160 +1,162 @@ -using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Profit.BVT +namespace AElf.Contracts.Profit.BVT; + +public partial class ProfitContractTests { - public partial class ProfitContractTests + [Fact] + public async Task ProfitContract_SetMethodFee_WithoutPermission_Test() { - [Fact] - public async Task ProfitContract_SetMethodFee_WithoutPermission_Test() + //no permission + var transactionResult = await ProfitContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - //no permission - var transactionResult = await ProfitContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + MethodName = "OnlyTest" + }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task ProfitContract_SetMethodFee_Success_Test() + { + var methodName = "OnlyTest"; + var fee = 100; + var tokenSymbol = "ELF"; + var methodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(ProfitContractAddress, + methodFeeController.OwnerAddress, nameof(ProfitContractStub.SetMethodFee), new MethodFees { - MethodName = "OnlyTest" - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); - } - [Fact] - public async Task ProfitContract_SetMethodFee_Success_Test() - { - var methodName = "OnlyTest"; - var fee = 100; - var tokenSymbol = "ELF"; - var methodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(ProfitContractAddress, - methodFeeController.OwnerAddress, nameof(ProfitContractStub.SetMethodFee), new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = {new MethodFee + new MethodFee { Symbol = tokenSymbol, BasicFee = fee - }} - }); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - var getMethodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName + } + } }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(fee); - } - - [Fact] - public async Task ChangeMethodFeeController_Test() + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var getMethodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(fee); + } - const string proposalCreationMethodName = nameof(ProfitContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(ProfitContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var methodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await ProfitContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo + const string proposalCreationMethodName = nameof(ProfitContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(ProfitContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, ContractAddress = ParliamentContractAddress }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + var newMethodFeeController = await ProfitContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task GetMethodFee_Test() + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await ProfitContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo { - var methodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ProfitContractStub.CreateScheme) - }); - methodFee.Fees[0].BasicFee.ShouldBe(10_00000000); - - var defaultMethodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = "Test" - }); - defaultMethodFee.Fees[0].BasicFee.ShouldBe(1_00000000); - } + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + [Fact] + public async Task GetMethodFee_Test() + { + var methodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + Value = nameof(ProfitContractStub.CreateScheme) + }); + methodFee.Fees[0].BasicFee.ShouldBe(10_00000000); - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var defaultMethodFee = await ProfitContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = "Test" + }); + defaultMethodFee.Fees[0].BasicFee.ShouldBe(1_00000000); + } - return proposalId; - } + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput + { + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + + return proposalId; + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in CreatorKeyPair) { - foreach (var bp in CreatorKeyPair) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/GenesisContractDtoExtensions.cs b/test/AElf.Contracts.Profit.Tests/GenesisContractDtoExtensions.cs index 8c7bfa8d42..c13b07d3be 100644 --- a/test/AElf.Contracts.Profit.Tests/GenesisContractDtoExtensions.cs +++ b/test/AElf.Contracts.Profit.Tests/GenesisContractDtoExtensions.cs @@ -1,18 +1,19 @@ using AElf.Standards.ACS0; using Google.Protobuf; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public static class GenesisContractDtoExtensions { - public static class GenesisContractDtoExtensions + internal static void Add( + this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, + string methodName, + IMessage input) { - internal static void Add(this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, string methodName, - IMessage input) + systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall() - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/ProfitContractTestAElfModule.cs b/test/AElf.Contracts.Profit.Tests/ProfitContractTestAElfModule.cs index 207d555948..249a300624 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitContractTestAElfModule.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitContractTestAElfModule.cs @@ -4,15 +4,14 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +[DependsOn(typeof(ContractTestModule))] +public class ProfitContractTestAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - public class ProfitContractTestAElfModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(); - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - } + context.Services.RemoveAll(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs b/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs index f585568598..96b350bfab 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; @@ -14,206 +12,211 @@ using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Volo.Abp.Threading; using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public class ProfitContractTestBase : ContractTestBase { - public class ProfitContractTestBase : ContractTestBase - { - protected ECKeyPair StarterKeyPair => Accounts[0].KeyPair; - protected Address Starter => Accounts[0].Address; + protected ECKeyPair StarterKeyPair => Accounts[0].KeyPair; + protected Address Starter => Accounts[0].Address; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(5).Select(a => a.KeyPair).ToList(); - protected Address TokenContractAddress { get; set; } - protected Address ProfitContractAddress { get; set; } - - protected Address ParliamentContractAddress{ get; set; } + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(5).Select(a => a.KeyPair).ToList(); - protected Address ConsensusContractAddress { get; set; } - internal List Creators => CreatorKeyPair - .Select(p => GetTester(ProfitContractAddress, p)).ToList(); + protected Address TokenContractAddress { get; set; } + protected Address ProfitContractAddress { get; set; } - internal List Normal => NormalKeyPair - .Select(p => GetTester(ProfitContractAddress, p)).ToList(); + protected Address ParliamentContractAddress { get; set; } - protected List CreatorKeyPair => Accounts.Skip(1).Take(4).Select(a => a.KeyPair).ToList(); + protected Address ConsensusContractAddress { get; set; } - protected List NormalKeyPair => Accounts.Skip(5).Take(5).Select(a => a.KeyPair).ToList(); + internal List Creators => CreatorKeyPair + .Select(p => GetTester(ProfitContractAddress, p)).ToList(); - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } + internal List Normal => NormalKeyPair + .Select(p => GetTester(ProfitContractAddress, p)).ToList(); - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + protected List CreatorKeyPair => Accounts.Skip(1).Take(4).Select(a => a.KeyPair).ToList(); - internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub { get; set; } - - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + protected List NormalKeyPair => Accounts.Skip(5).Take(5).Select(a => a.KeyPair).ToList(); - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } - protected void InitializeContracts() - { - BasicContractZeroStub = GetContractZeroTester(StarterKeyPair); - - ProfitContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ProfitContract).Assembly.Location)), - Name = ProfitSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateProfitInitializationCallList() - })).Output; - ProfitContractStub = GetProfitContractTester(StarterKeyPair); - - //deploy token contract - TokenContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), - Name = TokenSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateTokenInitializationCallList() - })).Output; - TokenContractStub = GetTokenContractTester(StarterKeyPair); - - //deploy parliament auth contract - ParliamentContractAddress = AsyncHelper.RunSync(()=>GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), - Name = ParliamentSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateParliamentInitializationCallList() - })).Output; - ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); - - //deploy consensus contract - ConsensusContractAddress = AsyncHelper.RunSync(()=>GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), - Name = ConsensusSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateConsensusInitializationCallList() - })).Output; - AEDPoSContractStub = GetConsensusContractTester(StarterKeyPair); - } - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } - internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, keyPair); - } + internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub { get; set; } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + + protected void InitializeContracts() + { + BasicContractZeroStub = GetContractZeroTester(StarterKeyPair); + + ProfitContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ProfitContract).Assembly.Location)), + Name = ProfitSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateProfitInitializationCallList() + })).Output; + ProfitContractStub = GetProfitContractTester(StarterKeyPair); + + //deploy token contract + TokenContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), + Name = TokenSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateTokenInitializationCallList() + })).Output; + TokenContractStub = GetTokenContractTester(StarterKeyPair); + + //deploy parliament auth contract + ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), + Name = ParliamentSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateParliamentInitializationCallList() + })).Output; + ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); + + //deploy consensus contract + ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), + Name = ConsensusSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateConsensusInitializationCallList() + })).Output; + AEDPoSContractStub = GetConsensusContractTester(StarterKeyPair); + } + + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } + + internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } + + internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateProfitInitializationCallList() + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateProfitInitializationCallList() + { + return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateTokenInitializationCallList() + { + const string symbol = "ELF"; + var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput { - return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - } + Symbol = symbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = ProfitContractTestConstants.NativeTokenTotalSupply, + Issuer = Starter, + LockWhiteList = + { + ProfitContractAddress + } + }); - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateTokenInitializationCallList() + // For creating `Treasury` profit scheme. + tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput { - const string symbol = "ELF"; - var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + Symbol = symbol, + Amount = (long)(ProfitContractTestConstants.NativeTokenTotalSupply * 0.12), + To = Address.FromPublicKey(StarterKeyPair.PublicKey), + Memo = "Issue token to default user for vote." + }); + + CreatorKeyPair.ForEach(creatorKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), + new IssueInput { Symbol = symbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = ProfitContractTestConstants.NativeTokenTotalSupply, - Issuer = Starter, - LockWhiteList = - { - ProfitContractAddress - } - }); + Amount = (long)(ProfitContractTestConstants.NativeTokenTotalSupply * 0.1), + To = Address.FromPublicKey(creatorKeyPair.PublicKey), + Memo = "set voters few amount for voting." + })); - // For creating `Treasury` profit scheme. - tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + NormalKeyPair.ForEach(normalKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), + new IssueInput { Symbol = symbol, - Amount = (long) (ProfitContractTestConstants.NativeTokenTotalSupply * 0.12), - To = Address.FromPublicKey(StarterKeyPair.PublicKey), - Memo = "Issue token to default user for vote.", - }); + Amount = (long)(ProfitContractTestConstants.NativeTokenTotalSupply * 0.05), + To = Address.FromPublicKey(normalKeyPair.PublicKey), + Memo = "set voters few amount for voting." + })); - CreatorKeyPair.ForEach(creatorKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), - new IssueInput - { - Symbol = symbol, - Amount = (long) (ProfitContractTestConstants.NativeTokenTotalSupply * 0.1), - To = Address.FromPublicKey(creatorKeyPair.PublicKey), - Memo = "set voters few amount for voting." - })); - - NormalKeyPair.ForEach(normalKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), - new IssueInput - { - Symbol = symbol, - Amount = (long) (ProfitContractTestConstants.NativeTokenTotalSupply * 0.05), - To = Address.FromPublicKey(normalKeyPair.PublicKey), - Memo = "set voters few amount for voting." - })); - - return tokenContractCallList; - } + return tokenContractCallList; + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateParliamentInitializationCallList() + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateParliamentInitializationCallList() + { + var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new InitializeInput { - var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new InitializeInput - { - PrivilegedProposer = Starter, - ProposerAuthorityRequired = true - }); + PrivilegedProposer = Starter, + ProposerAuthorityRequired = true + }); - return parliamentContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateConsensusInitializationCallList() - { - var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), new InitialAElfConsensusContractInput + return parliamentContractCallList; + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateConsensusInitializationCallList() + { + var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput { PeriodSeconds = 604800L, MinerIncreaseInterval = 31536000 }); - - consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList - { - Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); - return consensusContractCallList; - } + consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList + { + Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); + + return consensusContractCallList; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/ProfitContractTestConstants.cs b/test/AElf.Contracts.Profit.Tests/ProfitContractTestConstants.cs index 0a13cea09f..d4f937117a 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitContractTestConstants.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitContractTestConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Profit +namespace AElf.Contracts.Profit; + +public class ProfitContractTestConstants { - public class ProfitContractTestConstants - { - public const string NativeTokenSymbol = "ELF"; - public const long NativeTokenTotalSupply = 1_000_000_000_00000000; - public const int MaximumProfitReceivingDuePeriodCount = 1024; - } + public const string NativeTokenSymbol = "ELF"; + public const long NativeTokenTotalSupply = 1_000_000_000_00000000; + public const int MaximumProfitReceivingDuePeriodCount = 1024; } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/ProfitTests.cs b/test/AElf.Contracts.Profit.Tests/ProfitTests.cs index 769952ab41..eb2a492860 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitTests.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitTests.cs @@ -6,1798 +6,1791 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Profit -{ - public class ProfitTests : ProfitContractTestBase - { - //private const long ClaimTransactionFee = 1_00000000; - - public ProfitTests() - { - InitializeContracts(); - } +namespace AElf.Contracts.Profit; - /// - /// Of course it's okay for an address to creator many profit schemes. - /// - /// - [Fact] - public async Task ProfitContract_CreateManyProfitItems_Test() - { - const int createTimes = 5; +public class ProfitTests : ProfitContractTestBase +{ + //private const long ClaimTransactionFee = 1_00000000; - var creator = Creators[0]; - var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); + public ProfitTests() + { + InitializeContracts(); + } - for (var i = 0; i < createTimes; i++) - { - var executionResult = await creator.CreateScheme.SendAsync(new CreateSchemeInput - { - }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + /// + /// Of course it's okay for an address to creator many profit schemes. + /// + /// + [Fact] + public async Task ProfitContract_CreateManyProfitItems_Test() + { + const int createTimes = 5; - var createdSchemeIds = await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = creatorAddress - }); + var creator = Creators[0]; + var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - createdSchemeIds.SchemeIds.Count.ShouldBe(createTimes); + for (var i = 0; i < createTimes; i++) + { + var executionResult = await creator.CreateScheme.SendAsync(new CreateSchemeInput()); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact] - public async Task ProfitContract_DistributeProfits_Test() + var createdSchemeIds = await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput { - const int amount = 1000; + Manager = creatorAddress + }); - var creator = Creators[0]; + createdSchemeIds.SchemeIds.Count.ShouldBe(createTimes); + } - var schemeId = await CreateScheme(); + [Fact] + public async Task ProfitContract_DistributeProfits_Test() + { + const int amount = 1000; - // Add profits to virtual address of this profit scheme. - await creator.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeId = schemeId, - Amount = amount, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - }); + var creator = Creators[0]; - // Check profit scheme and corresponding balance. - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = profitItem.VirtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(amount); - } + var schemeId = await CreateScheme(); - // Add profits to release profits virtual address of this profit scheme. - const int period = 3; - await creator.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeId = schemeId, - Amount = amount, - Period = period, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - }); + // Add profits to virtual address of this profit scheme. + await creator.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeId = schemeId, + Amount = amount, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + }); - // Check profit scheme and corresponding balance. + // Check profit scheme and corresponding balance. + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var virtualAddress = await creator.GetSchemeAddress.CallAsync( - new SchemePeriod - { - SchemeId = schemeId, - Period = period - }); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = virtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(amount); - - var releasedProfitInformation = await creator.GetDistributedProfitsInfo.CallAsync( - new SchemePeriod - { - SchemeId = schemeId, - Period = period - }); - releasedProfitInformation.IsReleased.ShouldBe(false); - releasedProfitInformation.TotalShares.ShouldBe(0); - releasedProfitInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol].ShouldBe(amount); - } + Owner = profitItem.VirtualAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amount); } - /// - /// It's valid for a third party account to add profits to any profit scheme. - /// - /// - [Fact] - public async Task ProfitContract_ContributeProfits_ByThirdParty_Test() + // Add profits to release profits virtual address of this profit scheme. + const int period = 3; + await creator.ContributeProfits.SendAsync(new ContributeProfitsInput { - const long amountReleasedByCreator = 1000; - const long amountAddedByGoodGuy = 1000; - const long shares = 100; + SchemeId = schemeId, + Amount = amount, + Period = period, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + }); - var creator = Creators[0]; - var goodGuy = Creators[1]; - - var schemeId = await CreateScheme(); - - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput() + // Check profit scheme and corresponding balance. + { + var virtualAddress = await creator.GetSchemeAddress.CallAsync( + new SchemePeriod + { + SchemeId = schemeId, + Period = period + }); + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = shares} - }); + Owner = virtualAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amount); - // Add profits to virtual address of this profit scheme. - await goodGuy.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeId = schemeId, - Amount = amountAddedByGoodGuy, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - }); + var releasedProfitInformation = await creator.GetDistributedProfitsInfo.CallAsync( + new SchemePeriod + { + SchemeId = schemeId, + Period = period + }); + releasedProfitInformation.IsReleased.ShouldBe(false); + releasedProfitInformation.TotalShares.ShouldBe(0); + releasedProfitInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol].ShouldBe(amount); + } + } - // Add profits to release profits virtual address of this profit scheme. - await goodGuy.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeId = schemeId, - Amount = amountAddedByGoodGuy, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Period = 1 - }); + /// + /// It's valid for a third party account to add profits to any profit scheme. + /// + /// + [Fact] + public async Task ProfitContract_ContributeProfits_ByThirdParty_Test() + { + const long amountReleasedByCreator = 1000; + const long amountAddedByGoodGuy = 1000; + const long shares = 100; - // Check balance of period 1 - { - var releasedProfitsInformation = await creator.GetDistributedProfitsInfo.CallAsync( - new SchemePeriod - { - SchemeId = schemeId, - Period = 1 - }); - releasedProfitsInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(amountReleasedByCreator); - // total_Shares is 0 before releasing. - releasedProfitsInformation.TotalShares.ShouldBe(0); - releasedProfitsInformation.IsReleased.ShouldBe(false); - - var virtualAddress = await creator.GetSchemeAddress.CallAsync( - new SchemePeriod - { - SchemeId = schemeId, - Period = 1 - }); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = virtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(amountReleasedByCreator); - } + var creator = Creators[0]; + var goodGuy = Creators[1]; - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - Period = 1, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amountReleasedByCreator} - } - }); + var schemeId = await CreateScheme(); - // Creator can release profits of this period. - { - var releasedProfitsInformation = await creator.GetDistributedProfitsInfo.CallAsync( - new SchemePeriod - { - SchemeId = schemeId, - Period = 1 - }); - releasedProfitsInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] - .ShouldBe(amountReleasedByCreator + amountAddedByGoodGuy); - releasedProfitsInformation.TotalShares.ShouldBe(shares); - releasedProfitsInformation.IsReleased.ShouldBe(true); - } - } + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + SchemeId = schemeId, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = shares } + }); + // Add profits to virtual address of this profit scheme. + await goodGuy.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeId = schemeId, + Amount = amountAddedByGoodGuy, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + }); - [Fact] - public async Task ProfitContract_AddSubScheme_Fail_Test() + // Add profits to release profits virtual address of this profit scheme. + await goodGuy.ContributeProfits.SendAsync(new ContributeProfitsInput { - var creator = Creators[0]; - var schemeId = await CreateScheme(); - var subSchemeId1 = await CreateScheme(1); + SchemeId = schemeId, + Amount = amountAddedByGoodGuy, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Period = 1 + }); - // scheme id == subScheme Id - { - var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput + // Check balance of period 1 + { + var releasedProfitsInformation = await creator.GetDistributedProfitsInfo.CallAsync( + new SchemePeriod { SchemeId = schemeId, - SubSchemeId = schemeId, + Period = 1 }); - addSubSchemeRet.TransactionResult.Error.ShouldContain("Two schemes cannot be same"); - } + releasedProfitsInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(amountReleasedByCreator); + // total_Shares is 0 before releasing. + releasedProfitsInformation.TotalShares.ShouldBe(0); + releasedProfitsInformation.IsReleased.ShouldBe(false); - // input.Shares <= 0 - { - var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput + var virtualAddress = await creator.GetSchemeAddress.CallAsync( + new SchemePeriod { SchemeId = schemeId, - SubSchemeId = subSchemeId1, - SubSchemeShares = 0 + Period = 1 }); - addSubSchemeRet.TransactionResult.Error.ShouldContain("Shares of sub scheme should greater than 0"); - } + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = virtualAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amountReleasedByCreator); + } - // scheme id or subScheme Id does not exist. + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + Period = 1, + AmountsMap = { - var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput - { - SchemeId = new Hash(), - SubSchemeId = subSchemeId1, - SubSchemeShares = 100 - }); - addSubSchemeRet.TransactionResult.Error.ShouldContain("Scheme not found"); + { ProfitContractTestConstants.NativeTokenSymbol, amountReleasedByCreator } + } + }); - addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput + // Creator can release profits of this period. + { + var releasedProfitsInformation = await creator.GetDistributedProfitsInfo.CallAsync( + new SchemePeriod { SchemeId = schemeId, - SubSchemeId = new Hash(), - SubSchemeShares = 100 + Period = 1 }); - addSubSchemeRet.TransactionResult.Error.ShouldContain("Scheme not found"); - } - - // not the scheme manager - { - var creatorWithoutAuthority = Creators[1]; - var addSubSchemeRet = await creatorWithoutAuthority.AddSubScheme.SendWithExceptionAsync( - new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId1, - SubSchemeShares = 100 - }); - addSubSchemeRet.TransactionResult.Error.ShouldContain("Only manager can add sub-scheme"); - } + releasedProfitsInformation.AmountsMap[ProfitContractTestConstants.NativeTokenSymbol] + .ShouldBe(amountReleasedByCreator + amountAddedByGoodGuy); + releasedProfitsInformation.TotalShares.ShouldBe(shares); + releasedProfitsInformation.IsReleased.ShouldBe(true); } + } - [Fact] - public async Task ProfitContract_AddSubScheme_Success_Test() - { - const int shares1 = 80; - const int shares2 = 20; - - var creator = Creators[0]; - - var schemeId = await CreateScheme(); - var subSchemeId1 = await CreateScheme(1); - var subSchemeId2 = await CreateScheme(2); - - var subProfitItem1 = await creator.GetScheme.CallAsync(subSchemeId1); - var subProfitItem2 = await creator.GetScheme.CallAsync(subSchemeId2); - - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId1, - SubSchemeShares = shares1 - }); - - var profitDetails1 = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = subProfitItem1.VirtualAddress - }); - - // Check the total_weight of profit scheme. - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares1); - } - profitDetails1.Details.Count.ShouldBe(1); - profitDetails1.Details.First().StartPeriod.ShouldBe(1); - profitDetails1.Details.First().EndPeriod.ShouldBe(long.MaxValue); - profitDetails1.Details.First().LastProfitPeriod.ShouldBe(0); - profitDetails1.Details.First().Shares.ShouldBe(shares1); + [Fact] + public async Task ProfitContract_AddSubScheme_Fail_Test() + { + var creator = Creators[0]; + var schemeId = await CreateScheme(); + var subSchemeId1 = await CreateScheme(1); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput() + // scheme id == subScheme Id + { + var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput { SchemeId = schemeId, - SubSchemeId = subSchemeId2, - SubSchemeShares = shares2 + SubSchemeId = schemeId }); + addSubSchemeRet.TransactionResult.Error.ShouldContain("Two schemes cannot be same"); + } - var profitDetails2 = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput + // input.Shares <= 0 + { + var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput { SchemeId = schemeId, - Beneficiary = subProfitItem2.VirtualAddress + SubSchemeId = subSchemeId1, + SubSchemeShares = 0 }); - - // Check the total_weight of profit scheme. - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares1 + shares2); - } - - profitDetails2.Details.Count.ShouldBe(1); - profitDetails2.Details.First().StartPeriod.ShouldBe(1); - profitDetails2.Details.First().EndPeriod.ShouldBe(long.MaxValue); - profitDetails2.Details.First().LastProfitPeriod.ShouldBe(0); - profitDetails2.Details.First().Shares.ShouldBe(shares2); + addSubSchemeRet.TransactionResult.Error.ShouldContain("Shares of sub scheme should greater than 0"); } - [Fact] - public async Task ProfitContract_RemoveSubScheme_With_Invalid_Scheme_Id_Test() + // scheme id or subScheme Id does not exist. { - var shares = 100; - var creator = Creators[0]; - var schemeId = await CreateScheme(); - var subSchemeId1 = await CreateScheme(1); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + var addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput { - SchemeId = schemeId, + SchemeId = new Hash(), SubSchemeId = subSchemeId1, - SubSchemeShares = shares + SubSchemeShares = 100 }); + addSubSchemeRet.TransactionResult.Error.ShouldContain("Scheme not found"); - //schemeId == subSchemeId + addSubSchemeRet = await creator.AddSubScheme.SendWithExceptionAsync(new AddSubSchemeInput { - var removeSubSchemeResult = await creator.RemoveSubScheme.SendWithExceptionAsync( - new RemoveSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = schemeId, - }); - removeSubSchemeResult.TransactionResult.Error.ShouldContain("Two schemes cannot be same"); - } + SchemeId = schemeId, + SubSchemeId = new Hash(), + SubSchemeShares = 100 + }); + addSubSchemeRet.TransactionResult.Error.ShouldContain("Scheme not found"); } - [Fact] - public async Task ProfitContract_RemoveSubScheme_Without_Authority_Test() + // not the scheme manager { - var shares = 100; - var schemeId = await CreateScheme(); var creatorWithoutAuthority = Creators[1]; - var removeSubSchemeResult = await creatorWithoutAuthority.RemoveSubScheme.SendWithExceptionAsync( - new RemoveSubSchemeInput + var addSubSchemeRet = await creatorWithoutAuthority.AddSubScheme.SendWithExceptionAsync( + new AddSubSchemeInput { SchemeId = schemeId, - SubSchemeId = new Hash(), + SubSchemeId = subSchemeId1, + SubSchemeShares = 100 }); - removeSubSchemeResult.TransactionResult.Error.ShouldContain("Only manager can remove sub-scheme"); + addSubSchemeRet.TransactionResult.Error.ShouldContain("Only manager can add sub-scheme"); } + } - [Fact] - public async Task ProfitContract_RemoveSubScheme_Success_Test() - { - const int shares1 = 80; - const int shares2 = 20; - - var creator = Creators[0]; + [Fact] + public async Task ProfitContract_AddSubScheme_Success_Test() + { + const int shares1 = 80; + const int shares2 = 20; - var schemeId = await CreateScheme(); - var subSchemeId1 = await CreateScheme(1); - var subSchemeId2 = await CreateScheme(2); + var creator = Creators[0]; - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId1, - SubSchemeShares = shares1 - }); + var schemeId = await CreateScheme(); + var subSchemeId1 = await CreateScheme(1); + var subSchemeId2 = await CreateScheme(2); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput() - { - SchemeId = schemeId, - SubSchemeId = subSchemeId2, - SubSchemeShares = shares2 - }); + var subProfitItem1 = await creator.GetScheme.CallAsync(subSchemeId1); + var subProfitItem2 = await creator.GetScheme.CallAsync(subSchemeId2); - //remove sub scheme1 - { - var removeSubSchemeResult = await creator.RemoveSubScheme.SendAsync(new RemoveSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId1 - }); - removeSubSchemeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares2); - profitItem.SubSchemes.Count.ShouldBe(1); - profitItem.SubSchemes.First().Shares.ShouldBe(shares2); - } - } - - [Fact] - public async Task ProfitContract_AddBeneficiary_Without_Authority_Test() + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput { - var creator = Creators[0]; - var receiver = Accounts[0].Address; - var schemeId = await CreateScheme(); - // without authorized - { - var senderWithoutAuthority = Creators[1]; - var ret = await senderWithoutAuthority.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = receiver, - Shares = 100 - }, - SchemeId = schemeId - }); - ret.TransactionResult.Error.ShouldContain("Only manager can add beneficiary"); - } - } + SchemeId = schemeId, + SubSchemeId = subSchemeId1, + SubSchemeShares = shares1 + }); - [Fact] - public async Task ProfitContract_AddBeneficiary_With_Invalid_Input_Test() + var profitDetails1 = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - var creator = Creators[0]; - var receiver = Accounts[0].Address; - // input.SchemeId == null - { - var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = receiver, - Shares = 1 - }, - SchemeId = null - }); - ret.TransactionResult.Error.ShouldContain("Invalid scheme id"); - } - var schemeId = await CreateScheme(); - - // Invalid beneficiary address - { - var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput - { - BeneficiaryShare = null, - SchemeId = schemeId - }); - ret.TransactionResult.Error.ShouldContain("Invalid beneficiary address"); - - ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = null, - Shares = 1 - }, - SchemeId = schemeId - }); - ret.TransactionResult.Error.ShouldContain("Invalid beneficiary address"); - } + SchemeId = schemeId, + Beneficiary = subProfitItem1.VirtualAddress + }); - //Invalid share - { - var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = receiver, - Shares = -1 - }, - SchemeId = schemeId - }); - ret.TransactionResult.Error.ShouldContain("Invalid share"); - } + // Check the total_weight of profit scheme. + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares1); } - [Fact] - public async Task ProfitContract_AddWeight_Test() + profitDetails1.Details.Count.ShouldBe(1); + profitDetails1.Details.First().StartPeriod.ShouldBe(1); + profitDetails1.Details.First().EndPeriod.ShouldBe(long.MaxValue); + profitDetails1.Details.First().LastProfitPeriod.ShouldBe(0); + profitDetails1.Details.First().Shares.ShouldBe(shares1); + + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput { - var creator = Creators[0]; + SchemeId = schemeId, + SubSchemeId = subSchemeId2, + SubSchemeShares = shares2 + }); - var schemeId = await CreateScheme(); + var profitDetails2 = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = schemeId, + Beneficiary = subProfitItem2.VirtualAddress + }); - const int shares1 = 100; - const int shares2 = 200; - var receiver1 = Accounts[0].Address; - var receiver2 = Accounts[1].Address; + // Check the total_weight of profit scheme. + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares1 + shares2); + } - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiver1, Shares = shares1}, - SchemeId = schemeId, - }); + profitDetails2.Details.Count.ShouldBe(1); + profitDetails2.Details.First().StartPeriod.ShouldBe(1); + profitDetails2.Details.First().EndPeriod.ShouldBe(long.MaxValue); + profitDetails2.Details.First().LastProfitPeriod.ShouldBe(0); + profitDetails2.Details.First().Shares.ShouldBe(shares2); + } - // Check total_weight and profit_detail - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares1); + [Fact] + public async Task ProfitContract_RemoveSubScheme_With_Invalid_Scheme_Id_Test() + { + var shares = 100; + var creator = Creators[0]; + var schemeId = await CreateScheme(); + var subSchemeId1 = await CreateScheme(1); + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId1, + SubSchemeShares = shares + }); - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput + //schemeId == subSchemeId + { + var removeSubSchemeResult = await creator.RemoveSubScheme.SendWithExceptionAsync( + new RemoveSubSchemeInput { SchemeId = schemeId, - Beneficiary = receiver1 + SubSchemeId = schemeId }); - profitDetails.Details.Count.ShouldBe(1); - profitDetails.Details[0].Shares.ShouldBe(shares1); - profitDetails.Details[0].EndPeriod.ShouldBe(long.MaxValue); - profitDetails.Details[0].StartPeriod.ShouldBe(1); - profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); - } + removeSubSchemeResult.TransactionResult.Error.ShouldContain("Two schemes cannot be same"); + } + } - const int endPeriod = 100; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + [Fact] + public async Task ProfitContract_RemoveSubScheme_Without_Authority_Test() + { + var shares = 100; + var schemeId = await CreateScheme(); + var creatorWithoutAuthority = Creators[1]; + var removeSubSchemeResult = await creatorWithoutAuthority.RemoveSubScheme.SendWithExceptionAsync( + new RemoveSubSchemeInput { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiver2, Shares = shares2}, SchemeId = schemeId, - EndPeriod = endPeriod + SubSchemeId = new Hash() }); + removeSubSchemeResult.TransactionResult.Error.ShouldContain("Only manager can remove sub-scheme"); + } - // Check total_shares and profit_detail - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares1 + shares2); + [Fact] + public async Task ProfitContract_RemoveSubScheme_Success_Test() + { + const int shares1 = 80; + const int shares2 = 20; - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiver2 - }); - profitDetails.Details.Count.ShouldBe(1); - profitDetails.Details[0].Shares.ShouldBe(shares2); - profitDetails.Details[0].EndPeriod.ShouldBe(endPeriod); - profitDetails.Details[0].StartPeriod.ShouldBe(1); - profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); - } - } + var creator = Creators[0]; - [Fact] - public async Task ProfitContract_AddBeneficiary_IncorrectEndPeriod_Test() - { - const long amount = 100; - const long shares = 10; + var schemeId = await CreateScheme(); + var subSchemeId1 = await CreateScheme(1); + var subSchemeId2 = await CreateScheme(2); - var creator = Creators[0]; - var beneficiary = Accounts[0].Address; + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId1, + SubSchemeShares = shares1 + }); - var schemeId = await CreateScheme(); + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId2, + SubSchemeShares = shares2 + }); + //remove sub scheme1 + { + var removeSubSchemeResult = await creator.RemoveSubScheme.SendAsync(new RemoveSubSchemeInput { - var scheme = await creator.GetScheme.CallAsync(schemeId); - scheme.CurrentPeriod.ShouldBe(1); - } + SchemeId = schemeId, + SubSchemeId = subSchemeId1 + }); + removeSubSchemeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await ContributeProfits(schemeId); + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares2); + profitItem.SubSchemes.Count.ShouldBe(1); + profitItem.SubSchemes.First().Shares.ShouldBe(shares2); + } + } - // Current period: 1 + [Fact] + public async Task ProfitContract_AddBeneficiary_Without_Authority_Test() + { + var creator = Creators[0]; + var receiver = Accounts[0].Address; + var schemeId = await CreateScheme(); + // without authorized + { + var senderWithoutAuthority = Creators[1]; + var ret = await senderWithoutAuthority.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - var executionResult = await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + BeneficiaryShare = new BeneficiaryShare { - SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiary, Shares = shares}, - EndPeriod = 1 - }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - // We need to add Shares successfully for further testing. - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiary, Shares = shares}, + Beneficiary = receiver, + Shares = 100 + }, + SchemeId = schemeId }); + ret.TransactionResult.Error.ShouldContain("Only manager can add beneficiary"); + } + } - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + [Fact] + public async Task ProfitContract_AddBeneficiary_With_Invalid_Input_Test() + { + var creator = Creators[0]; + var receiver = Accounts[0].Address; + // input.SchemeId == null + { + var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - SchemeId = schemeId, - AmountsMap = + BeneficiaryShare = new BeneficiaryShare { - {ProfitContractTestConstants.NativeTokenSymbol, amount} + Beneficiary = receiver, + Shares = 1 }, - Period = 1 + SchemeId = null }); + ret.TransactionResult.Error.ShouldContain("Invalid scheme id"); + } + var schemeId = await CreateScheme(); + // Invalid beneficiary address + { + var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - var scheme = await creator.GetScheme.CallAsync(schemeId); - scheme.CurrentPeriod.ShouldBe(2); - } + BeneficiaryShare = null, + SchemeId = schemeId + }); + ret.TransactionResult.Error.ShouldContain("Invalid beneficiary address"); - // Current period: 2 + ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - var executionResult = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput + BeneficiaryShare = new BeneficiaryShare { - SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiary, Shares = shares}, - EndPeriod = 1 - }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Invalid end period."); - } + Beneficiary = null, + Shares = 1 + }, + SchemeId = schemeId + }); + ret.TransactionResult.Error.ShouldContain("Invalid beneficiary address"); } - [Fact] - public async Task ProfitContract_AddWeight_ProfitItemNotFound_Test() + //Invalid share { - var creator = Creators[0]; - - var executionResult = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput + var ret = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - SchemeId = HashHelper.ComputeFrom("SchemeId"), - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = 100}, + BeneficiaryShare = new BeneficiaryShare + { + Beneficiary = receiver, + Shares = -1 + }, + SchemeId = schemeId }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); + ret.TransactionResult.Error.ShouldContain("Invalid share"); } + } - /// - /// Every time adding Shares to a Beneficiary, will remove expired and used up profit details. - /// - /// - [Fact] - public async Task ProfitContract_AddWeight_RemoveExpiredProfitDetails_Test() - { - const long expiredPeriodNumber = 1; - const long amount = 150; - const long shares = 10; + [Fact] + public async Task ProfitContract_AddWeight_Test() + { + var creator = Creators[0]; - var creator = Creators[0]; - var beneficiary = Creators[1]; + var schemeId = await CreateScheme(); - var receiverAddress = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); + const int shares1 = 100; + const int shares2 = 200; + var receiver1 = Accounts[0].Address; + var receiver2 = Accounts[1].Address; + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiver1, Shares = shares1 }, + SchemeId = schemeId + }); - var schemeId = await CreateScheme(0, expiredPeriodNumber); + // Check total_weight and profit_detail + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares1); - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiverAddress, Shares = shares}, - EndPeriod = 1 + Beneficiary = receiver1 }); + profitDetails.Details.Count.ShouldBe(1); + profitDetails.Details[0].Shares.ShouldBe(shares1); + profitDetails.Details[0].EndPeriod.ShouldBe(long.MaxValue); + profitDetails.Details[0].StartPeriod.ShouldBe(1); + profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); + } - await ContributeProfits(schemeId, amount); + const int endPeriod = 100; + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiver2, Shares = shares2 }, + SchemeId = schemeId, + EndPeriod = endPeriod + }); - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + // Check total_shares and profit_detail + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares1 + shares2); + + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount / 3} - }, - Period = 1 + Beneficiary = receiver2 }); + profitDetails.Details.Count.ShouldBe(1); + profitDetails.Details[0].Shares.ShouldBe(shares2); + profitDetails.Details[0].EndPeriod.ShouldBe(endPeriod); + profitDetails.Details[0].StartPeriod.ShouldBe(1); + profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); + } + } - // Check details - { - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); + [Fact] + public async Task ProfitContract_AddBeneficiary_IncorrectEndPeriod_Test() + { + const long amount = 100; + const long shares = 10; - profitDetails.Details.Count.ShouldBe(1); - profitDetails.Details[0].Shares.ShouldBe(shares); - profitDetails.Details[0].StartPeriod.ShouldBe(1); - profitDetails.Details[0].EndPeriod.ShouldBe(1); - profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); - } + var creator = Creators[0]; + var beneficiary = Accounts[0].Address; - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount / 3} - }, - Period = 2 - }); + var schemeId = await CreateScheme(); - // Check details - { - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); + { + var scheme = await creator.GetScheme.CallAsync(schemeId); + scheme.CurrentPeriod.ShouldBe(1); + } - profitDetails.Details.Count.ShouldBe(1); - profitDetails.Details[0].Shares.ShouldBe(shares); - profitDetails.Details[0].StartPeriod.ShouldBe(1); - profitDetails.Details[0].EndPeriod.ShouldBe(1); - profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); - } + await ContributeProfits(schemeId); - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + // Current period: 1 + { + var executionResult = await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput { SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount / 3} - }, - Period = 3 + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiary, Shares = shares }, + EndPeriod = 1 }); - await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + // We need to add Shares successfully for further testing. + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + SchemeId = schemeId, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiary, Shares = shares } + }); + + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - SchemeId = schemeId, - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); + + { + var scheme = await creator.GetScheme.CallAsync(schemeId); + scheme.CurrentPeriod.ShouldBe(2); + } - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + // Current period: 2 + { + var executionResult = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiverAddress, Shares = shares * 2}, - EndPeriod = 4 + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiary, Shares = shares }, + EndPeriod = 1 }); - // Check details - { - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); - - profitDetails.Details.Count.ShouldBe(1); - profitDetails.Details[0].Shares.ShouldBe(shares * 2); - profitDetails.Details[0].StartPeriod.ShouldBe(4); - profitDetails.Details[0].EndPeriod.ShouldBe(4); - profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); - } + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Invalid end period."); } + } - [Fact] - public async Task ProfitContract_RemoveBeneficiary_Test() + [Fact] + public async Task ProfitContract_AddWeight_ProfitItemNotFound_Test() + { + var creator = Creators[0]; + + var executionResult = await creator.AddBeneficiary.SendWithExceptionAsync(new AddBeneficiaryInput { - const int shares = 100; - const int amount = 100; + SchemeId = HashHelper.ComputeFrom("SchemeId"), + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = 100 } + }); - var creator = Creators[0]; - var beneficiary = Normal[0]; - var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); + } - var schemeId = await CreateScheme(); + /// + /// Every time adding Shares to a Beneficiary, will remove expired and used up profit details. + /// + /// + [Fact] + public async Task ProfitContract_AddWeight_RemoveExpiredProfitDetails_Test() + { + const long expiredPeriodNumber = 1; + const long amount = 150; + const long shares = 10; - await ContributeProfits(schemeId); + var creator = Creators[0]; + var beneficiary = Creators[1]; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiverAddress, Shares = shares}, - SchemeId = schemeId, - EndPeriod = 1 - }); + var receiverAddress = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + var schemeId = await CreateScheme(0, expiredPeriodNumber); - // Check total_weight and profit_detail - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(shares); + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + SchemeId = schemeId, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiverAddress, Shares = shares }, + EndPeriod = 1 + }); - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); - profitDetails.Details.Count.ShouldBe(1); - } + await ContributeProfits(schemeId, amount); - await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = + { + { ProfitContractTestConstants.NativeTokenSymbol, amount / 3 } + }, + Period = 1 + }); + + // Check details + { + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = schemeId, + Beneficiary = receiverAddress }); - await creator.RemoveBeneficiary.SendAsync(new RemoveBeneficiaryInput + profitDetails.Details.Count.ShouldBe(1); + profitDetails.Details[0].Shares.ShouldBe(shares); + profitDetails.Details[0].StartPeriod.ShouldBe(1); + profitDetails.Details[0].EndPeriod.ShouldBe(1); + profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); + } + + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - Beneficiary = receiverAddress, - SchemeId = schemeId - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount / 3 } + }, + Period = 2 + }); - // Check total_weight and profit_detail + // Check details + { + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - profitItem.TotalShares.ShouldBe(0); + SchemeId = schemeId, + Beneficiary = receiverAddress + }); - var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); - profitDetails.Details.Count.ShouldBe(0); - } + profitDetails.Details.Count.ShouldBe(1); + profitDetails.Details[0].Shares.ShouldBe(shares); + profitDetails.Details[0].StartPeriod.ShouldBe(1); + profitDetails.Details[0].EndPeriod.ShouldBe(1); + profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); } - [Fact] - public async Task ProfitContract_RemoveBeneficiary_SchemeNotFound_Test() + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - var creator = Creators[0]; - - var executionResult = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput + SchemeId = schemeId, + AmountsMap = { - SchemeId = HashHelper.ComputeFrom("SchemeId"), - Beneficiary = Accounts[0].Address - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount / 3 } + }, + Period = 3 + }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); - } + await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); - [Fact] - public async Task ProfitContract_RemoveBeneficiary_Without_Authority_Test() + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput { - var creator = Creators[0]; - var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var schemeId = await CreateScheme(); + SchemeId = schemeId, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiverAddress, Shares = shares * 2 }, + EndPeriod = 4 + }); - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + // Check details + { + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - BeneficiaryShare = new BeneficiaryShare - { - Beneficiary = receiverAddress, - Shares = 1 - }, - SchemeId = schemeId + SchemeId = schemeId, + Beneficiary = receiverAddress }); - var creatorWithoutAuthority = Creators[2]; - var ret = await creatorWithoutAuthority.RemoveBeneficiary.SendWithExceptionAsync( - new RemoveBeneficiaryInput - { - SchemeId = schemeId, - Beneficiary = receiverAddress - }); - ret.TransactionResult.Error.ShouldContain("Only manager can remove beneficiary"); + + profitDetails.Details.Count.ShouldBe(1); + profitDetails.Details[0].Shares.ShouldBe(shares * 2); + profitDetails.Details[0].StartPeriod.ShouldBe(4); + profitDetails.Details[0].EndPeriod.ShouldBe(4); + profitDetails.Details[0].LastProfitPeriod.ShouldBe(0); } + } + + [Fact] + public async Task ProfitContract_RemoveBeneficiary_Test() + { + const int shares = 100; + const int amount = 100; + + var creator = Creators[0]; + var beneficiary = Normal[0]; + var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - [Fact] - public async Task ProfitContract_RemoveBeneficiary_With_Invalid_Input_Test() + var schemeId = await CreateScheme(); + + await ContributeProfits(schemeId); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput { - var creator = Creators[0]; - var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var schemeId = await CreateScheme(); + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiverAddress, Shares = shares }, + SchemeId = schemeId, + EndPeriod = 1 + }); - //Invalid scheme id + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - var ret = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput - { - SchemeId = null, - Beneficiary = receiverAddress - }); - ret.TransactionResult.Error.ShouldContain("Invalid scheme id"); - } + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); + + // Check total_weight and profit_detail + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(shares); - //Invalid Beneficiary address. + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - var ret = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput - { - SchemeId = schemeId, - Beneficiary = null - }); - ret.TransactionResult.Error.ShouldContain("Invalid Beneficiary address."); - } + SchemeId = schemeId, + Beneficiary = receiverAddress + }); + profitDetails.Details.Count.ShouldBe(1); } - [Fact] - public async Task ProfitContract_ReleaseProfits_WithoutEnoughBalance_Test() + await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput { - const long amount = 100; + SchemeId = schemeId + }); - var creator = Creators[0]; + await creator.RemoveBeneficiary.SendAsync(new RemoveBeneficiaryInput + { + Beneficiary = receiverAddress, + SchemeId = schemeId + }); - var schemeId = await CreateScheme(); + // Check total_weight and profit_detail + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + profitItem.TotalShares.ShouldBe(0); - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + var profitDetails = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = 100}, SchemeId = schemeId, + Beneficiary = receiverAddress }); + profitDetails.Details.Count.ShouldBe(0); + } + } + + [Fact] + public async Task ProfitContract_RemoveBeneficiary_SchemeNotFound_Test() + { + var creator = Creators[0]; - var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + var executionResult = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput + { + SchemeId = HashHelper.ComputeFrom("SchemeId"), + Beneficiary = Accounts[0].Address + }); + + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); + } + + [Fact] + public async Task ProfitContract_RemoveBeneficiary_Without_Authority_Test() + { + var creator = Creators[0]; + var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var schemeId = await CreateScheme(); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare + { + Beneficiary = receiverAddress, + Shares = 1 + }, + SchemeId = schemeId + }); + var creatorWithoutAuthority = Creators[2]; + var ret = await creatorWithoutAuthority.RemoveBeneficiary.SendWithExceptionAsync( + new RemoveBeneficiaryInput { SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 + Beneficiary = receiverAddress }); + ret.TransactionResult.Error.ShouldContain("Only manager can remove beneficiary"); + } - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Insufficient balance"); - } + [Fact] + public async Task ProfitContract_RemoveBeneficiary_With_Invalid_Input_Test() + { + var creator = Creators[0]; + var receiverAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var schemeId = await CreateScheme(); - [Fact] - public async Task ProfitContract_ReleaseProfits_InvalidTokenSymbol_Test() + //Invalid scheme id { - const long amount = 100; - var creator = Creators[0]; - var schemeId = await CreateScheme(); - var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + var ret = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput { - SchemeId = schemeId, - AmountsMap = - { - {"", amount} - }, - Period = 2 + SchemeId = null, + Beneficiary = receiverAddress }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Invalid token symbol"); + ret.TransactionResult.Error.ShouldContain("Invalid scheme id"); } - [Fact] - public async Task ProfitContract_ReleaseProfits_InvalidPeriod_Test() + //Invalid Beneficiary address. { - const long amount = 100; + var ret = await creator.RemoveBeneficiary.SendWithExceptionAsync(new RemoveBeneficiaryInput + { + SchemeId = schemeId, + Beneficiary = null + }); + ret.TransactionResult.Error.ShouldContain("Invalid Beneficiary address."); + } + } - var creator = Creators[0]; + [Fact] + public async Task ProfitContract_ReleaseProfits_WithoutEnoughBalance_Test() + { + const long amount = 100; - var schemeId = await CreateScheme(); + var creator = Creators[0]; - await ContributeProfits(schemeId); + var schemeId = await CreateScheme(); - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = 100}, - SchemeId = schemeId, - }); + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = 100 }, + SchemeId = schemeId + }); - var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 2 - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Invalid period."); - } + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Insufficient balance"); + } - [Fact] - public async Task ProfitContract_ReleaseProfits_NotCreator_Test() + [Fact] + public async Task ProfitContract_ReleaseProfits_InvalidTokenSymbol_Test() + { + const long amount = 100; + var creator = Creators[0]; + var schemeId = await CreateScheme(); + var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput { - const long amount = 100; + SchemeId = schemeId, + AmountsMap = + { + { "", amount } + }, + Period = 2 + }); - var schemeId = await CreateScheme(); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Invalid token symbol"); + } - await ContributeProfits(schemeId); + [Fact] + public async Task ProfitContract_ReleaseProfits_InvalidPeriod_Test() + { + const long amount = 100; - // The actual creator is Creators[0] - var anotherGuy = Creators[1]; + var creator = Creators[0]; - var executionResult = await anotherGuy.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + var schemeId = await CreateScheme(); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Only manager"); - } + await ContributeProfits(schemeId); - [Fact] - public async Task ProfitContract_ReleaseProfits_ProfitItemNotFound_Test() + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput { - const long amount = 100; - - var user = Creators[0]; + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = 100 }, + SchemeId = schemeId + }); - var executionResult = await user.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + var executionResult = await creator.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - SchemeId = HashHelper.ComputeFrom("SchemeId"), - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 2 + }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); - } + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Invalid period."); + } - [Fact] - public async Task ProfitContract_ReleaseProfits_Test() - { - const long amount = 100; + [Fact] + public async Task ProfitContract_ReleaseProfits_NotCreator_Test() + { + const long amount = 100; - var creator = Creators[0]; + var schemeId = await CreateScheme(); - var schemeId = await CreateScheme(); + await ContributeProfits(schemeId); - await ContributeProfits(schemeId, amount * 2); + // The actual creator is Creators[0] + var anotherGuy = Creators[1]; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + var executionResult = await anotherGuy.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = 100}, - SchemeId = schemeId, - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); - // First time. - { - var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Only manager"); + } - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + [Fact] + public async Task ProfitContract_ReleaseProfits_ProfitItemNotFound_Test() + { + const long amount = 100; - // Second time. - { - var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 2 - }); - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } + var user = Creators[0]; - [Fact] - public async Task ProfitContract_ReleaseProfits_WithSubProfitItems_Test() + var executionResult = await user.DistributeProfits.SendWithExceptionAsync(new DistributeProfitsInput { - const long amount = 100; - const long weight1 = 80; - const long weight2 = 20; - - var creator = Creators[0]; + SchemeId = HashHelper.ComputeFrom("SchemeId"), + AmountsMap = + { + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); - var schemeId = await CreateScheme(); - var subSchemeId1 = await CreateScheme(1); - var subSchemeId2 = await CreateScheme(2); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); + } - await ContributeProfits(schemeId); + [Fact] + public async Task ProfitContract_ReleaseProfits_Test() + { + const long amount = 100; - // Check balance of main profit scheme. - { - var profitItem = await creator.GetScheme.CallAsync(schemeId); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = profitItem.VirtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; + var creator = Creators[0]; - balance.ShouldBe(amount); - } + var schemeId = await CreateScheme(); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId1, - SubSchemeShares = weight1 - }); + await ContributeProfits(schemeId, amount * 2); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId2, - SubSchemeShares = weight2 - }); + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = 100 }, + SchemeId = schemeId + }); + // First time. + { var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { SchemeId = schemeId, AmountsMap = { - {ProfitContractTestConstants.NativeTokenSymbol, amount} + { ProfitContractTestConstants.NativeTokenSymbol, amount } }, Period = 1 }); executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - // Check balance of first sub profit scheme. + // Second time. + { + var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - var subProfitItem = await creator.GetScheme.CallAsync(subSchemeId1); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + SchemeId = schemeId, + AmountsMap = { - Owner = subProfitItem.VirtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 2 + }); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + } - balance.ShouldBe(amount.Mul(weight1).Div(weight1 + weight2)); - } + [Fact] + public async Task ProfitContract_ReleaseProfits_WithSubProfitItems_Test() + { + const long amount = 100; + const long weight1 = 80; + const long weight2 = 20; - // Check balance of second sub profit scheme. - { - var subProfitItem = await creator.GetScheme.CallAsync(subSchemeId2); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = subProfitItem.VirtualAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; + var creator = Creators[0]; - balance.ShouldBe(amount.Mul(weight2).Div(weight1 + weight2)); - } - } + var schemeId = await CreateScheme(); + var subSchemeId1 = await CreateScheme(1); + var subSchemeId2 = await CreateScheme(2); - [Fact] - public async Task ProfitContract_Profit_Test() - { - const long shares = 100; - const long amount = 100; + await ContributeProfits(schemeId); - var creator = Creators[0]; - var beneficiary = Normal[0]; - var beneficiaryAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var initialBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + // Check balance of main profit scheme. + { + var profitItem = await creator.GetScheme.CallAsync(schemeId); + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Owner = beneficiaryAddress, + Owner = profitItem.VirtualAddress, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; - var schemeId = await CreateScheme(); + balance.ShouldBe(amount); + } - await ContributeProfits(schemeId); + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId1, + SubSchemeShares = weight1 + }); - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress, Shares = shares}, - SchemeId = schemeId, - }); + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId2, + SubSchemeShares = weight2 + }); - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); + + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + // Check balance of first sub profit scheme. + { + var subProfitItem = await creator.GetScheme.CallAsync(subSchemeId1); + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - SchemeId = schemeId, - }); + Owner = subProfitItem.VirtualAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amount.Mul(weight1).Div(weight1 + weight2)); + } + + // Check balance of second sub profit scheme. + { + var subProfitItem = await creator.GetScheme.CallAsync(subSchemeId2); var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Owner = beneficiaryAddress, + Owner = subProfitItem.VirtualAddress, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; - balance.ShouldBe(amount + initialBalance); + + balance.ShouldBe(amount.Mul(weight2).Div(weight1 + weight2)); } + } + + [Fact] + public async Task ProfitContract_Profit_Test() + { + const long shares = 100; + const long amount = 100; - [Fact] - public async Task ProfitContract_Profit_TwoReceivers_Test() + var creator = Creators[0]; + var beneficiary = Normal[0]; + var beneficiaryAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var initialBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - const long weight1 = 100; - const long weight2 = 400; - const long amount = 100; + Owner = beneficiaryAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; - var creator = Creators[0]; - var beneficiary1 = Normal[0]; - var beneficiary2 = Normal[1]; - var beneficiaryAddress1 = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var beneficiaryAddress2 = Address.FromPublicKey(NormalKeyPair[1].PublicKey); + var schemeId = await CreateScheme(); - var initialBalance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + await ContributeProfits(schemeId); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress, Shares = shares }, + SchemeId = schemeId + }); + + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = + { + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); + + await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); + + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amount + initialBalance); + } + + [Fact] + public async Task ProfitContract_Profit_TwoReceivers_Test() + { + const long weight1 = 100; + const long weight2 = 400; + const long amount = 100; + + var creator = Creators[0]; + var beneficiary1 = Normal[0]; + var beneficiary2 = Normal[1]; + var beneficiaryAddress1 = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var beneficiaryAddress2 = Address.FromPublicKey(NormalKeyPair[1].PublicKey); + + var initialBalance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress1, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + var initialBalance2 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress2, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + + var schemeId = await CreateScheme(); + + await ContributeProfits(schemeId); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress1, Shares = weight1 }, + SchemeId = schemeId + }); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress2, Shares = weight2 }, + SchemeId = schemeId + }); + + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = + { + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); + + await beneficiary1.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); + + // Check balance of Beneficiary 1. + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = beneficiaryAddress1, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; - var initialBalance2 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + balance.ShouldBe(weight1.Mul(amount).Div(weight1 + weight2).Add(initialBalance1)); + } + + await beneficiary2.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); + + // Check balance of Beneficiary 2. + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = beneficiaryAddress2, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; + balance.ShouldBe(weight2.Mul(amount).Div(weight1 + weight2).Add(initialBalance2)); + } + } - var schemeId = await CreateScheme(); - - await ContributeProfits(schemeId); - - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress1, Shares = weight1}, - SchemeId = schemeId, - }); + [Fact] + public async Task ProfitContract_Profit_RegisteredSubProfitItems_Test() + { + const long weight1 = 100; + const long weight2 = 400; + const long weight3 = 500; + const long amount = 100; + + var creator = Creators[0]; + var beneficiary1 = Normal[0]; + var beneficiary2 = Normal[1]; + var beneficiaryAddress1 = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var beneficiaryAddress2 = Address.FromPublicKey(NormalKeyPair[1].PublicKey); + + var initialBalance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress1, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + var initialBalance2 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress2, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress2, Shares = weight2}, - SchemeId = schemeId, - }); + var schemeId = await CreateScheme(); + var subSchemeId = await CreateScheme(1); - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + await ContributeProfits(schemeId); - await beneficiary1.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - }); + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress1, Shares = weight1 }, + SchemeId = schemeId + }); - // Check balance of Beneficiary 1. - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress1, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(weight1.Mul(amount).Div(weight1 + weight2).Add(initialBalance1)); - } + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress2, Shares = weight2 }, + SchemeId = schemeId + }); - await beneficiary2.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - }); + await creator.AddSubScheme.SendAsync(new AddSubSchemeInput + { + SchemeId = schemeId, + SubSchemeId = subSchemeId, + SubSchemeShares = weight3 + }); - // Check balance of Beneficiary 2. + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress2, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(weight2.Mul(amount).Div(weight1 + weight2).Add(initialBalance2)); - } - } + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); - [Fact] - public async Task ProfitContract_Profit_RegisteredSubProfitItems_Test() + await beneficiary1.ClaimProfits.SendAsync(new ClaimProfitsInput { - const long weight1 = 100; - const long weight2 = 400; - const long weight3 = 500; - const long amount = 100; - - var creator = Creators[0]; - var beneficiary1 = Normal[0]; - var beneficiary2 = Normal[1]; - var beneficiaryAddress1 = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var beneficiaryAddress2 = Address.FromPublicKey(NormalKeyPair[1].PublicKey); + SchemeId = schemeId + }); - var initialBalance1 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + // Check balance of Beneficiary 1. + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = beneficiaryAddress1, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; - var initialBalance2 = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + balance.ShouldBe(weight1.Mul(amount).Div(weight1.Add(weight2).Add(weight3)).Add(initialBalance1)); + } + + await beneficiary2.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); + + // Check balance of Beneficiary 2. + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = beneficiaryAddress2, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; + balance.ShouldBe(weight2.Mul(amount).Div(weight1.Add(weight2).Add(weight3)).Add(initialBalance2)); + } + } - var schemeId = await CreateScheme(); - var subSchemeId = await CreateScheme(1); - - await ContributeProfits(schemeId); - - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress1, Shares = weight1}, - SchemeId = schemeId, - }); + [Fact] + public async Task ProfitContract_Profit_ProfitItemNotFound_Test() + { + var beneficiary = Normal[0]; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput - { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress2, Shares = weight2}, - SchemeId = schemeId, - }); + var executionResult = await beneficiary.ClaimProfits.SendWithExceptionAsync(new ClaimProfitsInput + { + SchemeId = HashHelper.ComputeFrom("SchemeId") + }); - await creator.AddSubScheme.SendAsync(new AddSubSchemeInput - { - SchemeId = schemeId, - SubSchemeId = subSchemeId, - SubSchemeShares = weight3 - }); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); + } - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 - }); + [Fact] + public async Task ProfitContract_Profit_NotRegisteredBefore_Test() + { + const long amount = 100; - await beneficiary1.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - }); + var creator = Creators[0]; + var beneficiary = Normal[0]; - // Check balance of Beneficiary 1. - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress1, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(weight1.Mul(amount).Div(weight1.Add(weight2).Add(weight3)).Add(initialBalance1)); - } + var schemeId = await CreateScheme(); - await beneficiary2.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - }); + await ContributeProfits(schemeId); - // Check balance of Beneficiary 2. + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeId = schemeId, + AmountsMap = { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress2, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(weight2.Mul(amount).Div(weight1.Add(weight2).Add(weight3)).Add(initialBalance2)); - } - } + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + Period = 1 + }); - [Fact] - public async Task ProfitContract_Profit_ProfitItemNotFound_Test() + var executionResult = await beneficiary.ClaimProfits.SendWithExceptionAsync(new ClaimProfitsInput { - var beneficiary = Normal[0]; + SchemeId = schemeId + }); - var executionResult = await beneficiary.ClaimProfits.SendWithExceptionAsync(new ClaimProfitsInput - { - SchemeId = HashHelper.ComputeFrom("SchemeId"), - }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Scheme not found."); - } + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + executionResult.TransactionResult.Error.ShouldContain("Profit details not found."); + } - [Fact] - public async Task ProfitContract_Profit_NotRegisteredBefore_Test() + [Fact] + public async Task ProfitContract_Profit_MultiplePeriods_Test() + { + const int periodCount = 5; + const long shares = 100; + const long amount = 100; + + var creator = Creators[0]; + var beneficiary = Normal[0]; + var beneficiaryAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); + var initialBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - const long amount = 100; + Owner = beneficiaryAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; - var creator = Creators[0]; - var beneficiary = Normal[0]; + var schemeId = await CreateScheme(); - var schemeId = await CreateScheme(); + await ContributeProfits(schemeId, amount * periodCount + amount); - await ContributeProfits(schemeId); + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + SchemeId = schemeId, + BeneficiaryShare = new BeneficiaryShare { Beneficiary = beneficiaryAddress, Shares = shares } + }); + for (var i = 0; i < periodCount; i++) await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { SchemeId = schemeId, AmountsMap = { - {ProfitContractTestConstants.NativeTokenSymbol, amount} + { ProfitContractTestConstants.NativeTokenSymbol, amount } }, - Period = 1 + Period = i + 1 }); - var executionResult = await beneficiary.ClaimProfits.SendWithExceptionAsync(new ClaimProfitsInput + await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); + + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = beneficiaryAddress, + Symbol = ProfitContractTestConstants.NativeTokenSymbol + })).Balance; + balance.ShouldBe(amount * periodCount + initialBalance); + + var details = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = schemeId, + Beneficiary = beneficiaryAddress }); - - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - executionResult.TransactionResult.Error.ShouldContain("Profit details not found."); + details.Details[0].LastProfitPeriod.ShouldBe(periodCount + 1); } - [Fact] - public async Task ProfitContract_Profit_MultiplePeriods_Test() + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - const int periodCount = 5; - const long shares = 100; - const long amount = 100; + Period = periodCount + 1, + AmountsMap = + { + { ProfitContractTestConstants.NativeTokenSymbol, amount } + }, + SchemeId = schemeId + }); + + await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput + { + SchemeId = schemeId + }); - var creator = Creators[0]; - var beneficiary = Normal[0]; - var beneficiaryAddress = Address.FromPublicKey(NormalKeyPair[0].PublicKey); - var initialBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = beneficiaryAddress, Symbol = ProfitContractTestConstants.NativeTokenSymbol })).Balance; + balance.ShouldBe(amount * periodCount + amount + initialBalance); - var schemeId = await CreateScheme(); - - await ContributeProfits(schemeId, amount * periodCount + amount); - - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + var details = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput { SchemeId = schemeId, - BeneficiaryShare = new BeneficiaryShare {Beneficiary = beneficiaryAddress, Shares = shares}, + Beneficiary = beneficiaryAddress }); + details.Details[0].LastProfitPeriod.ShouldBe(periodCount + 2); + } + } - for (var i = 0; i < periodCount; i++) - { - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = i + 1 - }); - } + private async Task CreateScheme(int returnIndex = 0, + long profitReceivingDuePeriodCount = ProfitContractConstants.DefaultProfitReceivingDuePeriodCount) + { + var creator = Creators[0]; + var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - }); + await creator.CreateScheme.SendAsync(new CreateSchemeInput + { + ProfitReceivingDuePeriodCount = profitReceivingDuePeriodCount + }); - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(amount * periodCount + initialBalance); + var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = creatorAddress + })).SchemeIds; - var details = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = beneficiaryAddress - }); - details.Details[0].LastProfitPeriod.ShouldBe(periodCount + 1); - } + return createdSchemeIds[returnIndex]; + } - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + [Fact] + public async Task ContributeProfits_MultipleTimes_Test() + { + const long amount = 100; + + var creator = Creators[0]; + + var schemeId = await CreateScheme(); + + await ContributeProfits(schemeId, amount * 2); + + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = Accounts[0].Address, Shares = 100 }, + SchemeId = schemeId + }); + + // First time. + { + var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - Period = periodCount + 1, + SchemeId = schemeId, AmountsMap = { - {ProfitContractTestConstants.NativeTokenSymbol, amount} + { ProfitContractTestConstants.NativeTokenSymbol, amount } }, - SchemeId = schemeId - }); - - await beneficiary.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId, + Period = 1 }); - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = beneficiaryAddress, - Symbol = ProfitContractTestConstants.NativeTokenSymbol - })).Balance; - balance.ShouldBe(amount * periodCount + amount + initialBalance); + executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var details = await creator.GetProfitDetails.CallAsync(new GetProfitDetailsInput + var transactionResult = await ProfitContractStub.ContributeProfits.SendWithExceptionAsync( + new ContributeProfitsInput { SchemeId = schemeId, - Beneficiary = beneficiaryAddress + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Amount = 100, + Period = 1 }); - details.Details[0].LastProfitPeriod.ShouldBe(periodCount + 2); - } + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Invalid contributing period."); } - private async Task CreateScheme(int returnIndex = 0, - long profitReceivingDuePeriodCount = ProfitContractConstants.DefaultProfitReceivingDuePeriodCount) + //Second time { - var creator = Creators[0]; - var creatorAddress = Address.FromPublicKey(CreatorKeyPair[0].PublicKey); - - await creator.CreateScheme.SendAsync(new CreateSchemeInput + var transactionResult = await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput { - ProfitReceivingDuePeriodCount = profitReceivingDuePeriodCount + SchemeId = schemeId, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Amount = 100, + Period = 2 }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var createdSchemeIds = (await creator.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = creatorAddress - })).SchemeIds; - - return createdSchemeIds[returnIndex]; - } - - [Fact] - public async Task ContributeProfits_MultipleTimes_Test() - { - const long amount = 100; - - var creator = Creators[0]; - - var schemeId = await CreateScheme(); - - await ContributeProfits(schemeId, amount * 2); - - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + transactionResult = await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = Accounts[0].Address, Shares = 100}, SchemeId = schemeId, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Amount = 100, + Period = 2 }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + } - // First time. - { - var executionResult = await creator.DistributeProfits.SendAsync(new DistributeProfitsInput + [Fact] + public async Task ContributeProfits_With_Invalid_Input_Test() + { + var creator = Creators[0]; + var schemeId = await CreateScheme(); + + // invalid token symbol + { + var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( + new ContributeProfitsInput { SchemeId = schemeId, - AmountsMap = - { - {ProfitContractTestConstants.NativeTokenSymbol, amount} - }, - Period = 1 + Symbol = "" }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Invalid token symbol"); + } - executionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transactionResult = await ProfitContractStub.ContributeProfits.SendWithExceptionAsync( - new ContributeProfitsInput - { - SchemeId = schemeId, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = 100, - Period = 1 - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Invalid contributing period."); - } - - //Second time - { - var transactionResult = await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + // invalid token amount + { + var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( + new ContributeProfitsInput { SchemeId = schemeId, Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = 100, - Period = 2 + Amount = 0 }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Amount need to greater than 0."); + } - transactionResult = await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + //invalid scheme id + { + var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( + new ContributeProfitsInput { - SchemeId = schemeId, + SchemeId = new Hash(), Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = 100, - Period = 2 + Amount = 10 }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Scheme not found."); } + } + + [Fact] + public async Task ResetManager_Without_Authority_Test() + { + var schemeId = await CreateScheme(); + var sendWithoutAuthority = Creators[1]; + var resetRet = await sendWithoutAuthority.ResetManager.SendWithExceptionAsync(new ResetManagerInput + { + NewManager = new Address(), + SchemeId = schemeId + }); + resetRet.TransactionResult.Error.ShouldContain("Only scheme manager can reset manager"); + } + + [Fact] + public async Task ResetManager_With_Invalid_Input_Test() + { + var schemeId = await CreateScheme(); + var creator = Creators[0]; + var newManager = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); + var resetRet = await creator.ResetManager.SendWithExceptionAsync(new ResetManagerInput + { + NewManager = newManager, + SchemeId = new Hash() + }); + resetRet.TransactionResult.Error.ShouldContain("Scheme not found."); - [Fact] - public async Task ContributeProfits_With_Invalid_Input_Test() + resetRet = await creator.ResetManager.SendWithExceptionAsync(new ResetManagerInput { - var creator = Creators[0]; - var schemeId = await CreateScheme(); + NewManager = new Address(), + SchemeId = schemeId + }); + resetRet.TransactionResult.Error.ShouldContain("Invalid new sponsor."); + } - // invalid token symbol + [Fact] + public async Task ResetManager_Success_Test() + { + var schemeId = await CreateScheme(); + var creator = Creators[0]; + var newManager = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); + await creator.ResetManager.SendAsync(new ResetManagerInput + { + NewManager = newManager, + SchemeId = schemeId + }); + var schemeIdForInitialCreator = await ProfitContractStub.GetManagingSchemeIds.CallAsync( + new GetManagingSchemeIdsInput { - var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( - new ContributeProfitsInput - { - SchemeId = schemeId, - Symbol = "", - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Invalid token symbol"); - } + Manager = Address.FromPublicKey(CreatorKeyPair[0].PublicKey) + }); + schemeIdForInitialCreator.SchemeIds.Count.ShouldBe(0); - // invalid token amount - { - var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( - new ContributeProfitsInput - { - SchemeId = schemeId, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = 0, - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Amount need to greater than 0."); - } + var schemeIdForNewManager = await ProfitContractStub.GetManagingSchemeIds.CallAsync( + new GetManagingSchemeIdsInput + { + Manager = newManager + }); + schemeIdForNewManager.SchemeIds.Count.ShouldBe(1); + var schemeInfo = await ProfitContractStub.GetScheme.CallAsync(schemeId); + schemeInfo.Manager.Equals(newManager).ShouldBeTrue(); + } - //invalid scheme id - { - var transactionResult = await creator.ContributeProfits.SendWithExceptionAsync( - new ContributeProfitsInput - { - SchemeId = new Hash(), - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = 10, - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Scheme not found."); - } - } + [Fact] + public async Task GetManagingSchemeIds_Test() + { + var schemeId1 = await CreateScheme(); + var schemeId2 = await CreateScheme(1); + var managerSchemes = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = Address.FromPublicKey(CreatorKeyPair[0].PublicKey) + }); + managerSchemes.SchemeIds.Count.ShouldBe(2); + managerSchemes.SchemeIds.Contains(schemeId1).ShouldBeTrue(); + managerSchemes.SchemeIds.Contains(schemeId2).ShouldBeTrue(); + } - [Fact] - public async Task ResetManager_Without_Authority_Test() + [Fact] + public async Task GetProfitMapAndAmount_Test() + { + const long amount = 100; + var creator = Creators[0]; + var schemeId = await CreateScheme(); + await ContributeProfits(schemeId, amount * 2); + var receiver = Accounts[0].Address; + var tokenSymbol = ProfitContractTestConstants.NativeTokenSymbol; + await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + { + BeneficiaryShare = new BeneficiaryShare { Beneficiary = receiver, Shares = 100 }, + SchemeId = schemeId + }); + + //first time { - var schemeId = await CreateScheme(); - var sendWithoutAuthority = Creators[1]; - var resetRet = await sendWithoutAuthority.ResetManager.SendWithExceptionAsync(new ResetManagerInput + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - NewManager = new Address(), SchemeId = schemeId, + AmountsMap = + { + { tokenSymbol, amount } + }, + Period = 1 }); - resetRet.TransactionResult.Error.ShouldContain("Only scheme manager can reset manager"); - } - - [Fact] - public async Task ResetManager_With_Invalid_Input_Test() - { - var schemeId = await CreateScheme(); - var creator = Creators[0]; - var newManager = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); - var resetRet = await creator.ResetManager.SendWithExceptionAsync(new ResetManagerInput + var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput { - NewManager = newManager, - SchemeId = new Hash() + Beneficiary = receiver, + Symbol = tokenSymbol, + SchemeId = schemeId }); - resetRet.TransactionResult.Error.ShouldContain("Scheme not found."); - - resetRet = await creator.ResetManager.SendWithExceptionAsync(new ResetManagerInput + profitAmount.Value.ShouldBe(amount); + var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput { - NewManager = new Address(), - SchemeId = schemeId + SchemeId = schemeId, + Beneficiary = receiver }); - resetRet.TransactionResult.Error.ShouldContain("Invalid new sponsor."); + profitMap.Value[tokenSymbol].ShouldBe(amount); } - [Fact] - public async Task ResetManager_Success_Test() + // after claim { - var schemeId = await CreateScheme(); - var creator = Creators[0]; - var newManager = Address.FromPublicKey(CreatorKeyPair[1].PublicKey); - await creator.ResetManager.SendAsync(new ResetManagerInput + await ProfitContractStub.ClaimProfits.SendAsync(new ClaimProfitsInput { - NewManager = newManager, SchemeId = schemeId }); - var schemeIdForInitialCreator = await ProfitContractStub.GetManagingSchemeIds.CallAsync( - new GetManagingSchemeIdsInput - { - Manager = Address.FromPublicKey(CreatorKeyPair[0].PublicKey) - }); - schemeIdForInitialCreator.SchemeIds.Count.ShouldBe(0); - - var schemeIdForNewManager = await ProfitContractStub.GetManagingSchemeIds.CallAsync( - new GetManagingSchemeIdsInput - { - Manager = newManager - }); - schemeIdForNewManager.SchemeIds.Count.ShouldBe(1); - var schemeInfo = await ProfitContractStub.GetScheme.CallAsync(schemeId); - schemeInfo.Manager.Equals(newManager).ShouldBeTrue(); - } - - [Fact] - public async Task GetManagingSchemeIds_Test() - { - var schemeId1 = await CreateScheme(); - var schemeId2 = await CreateScheme(1); - var managerSchemes = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput { - Manager = Address.FromPublicKey(CreatorKeyPair[0].PublicKey) + Beneficiary = receiver, + Symbol = tokenSymbol, + SchemeId = schemeId + }); + profitAmount.Value.ShouldBe(0); + var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput + { + SchemeId = schemeId, + Beneficiary = receiver }); - managerSchemes.SchemeIds.Count.ShouldBe(2); - managerSchemes.SchemeIds.Contains(schemeId1).ShouldBeTrue(); - managerSchemes.SchemeIds.Contains(schemeId2).ShouldBeTrue(); + profitMap.Value.ContainsKey(tokenSymbol).ShouldBeFalse(); } - [Fact] - public async Task GetProfitMapAndAmount_Test() + //second time { - const long amount = 100; - var creator = Creators[0]; - var schemeId = await CreateScheme(); - await ContributeProfits(schemeId, amount * 2); - var receiver = Accounts[0].Address; - var tokenSymbol = ProfitContractTestConstants.NativeTokenSymbol; - await creator.AddBeneficiary.SendAsync(new AddBeneficiaryInput + await creator.DistributeProfits.SendAsync(new DistributeProfitsInput { - BeneficiaryShare = new BeneficiaryShare {Beneficiary = receiver, Shares = 100}, SchemeId = schemeId, - }); - - //first time - { - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {tokenSymbol, amount} - }, - Period = 1 - }); - var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - Beneficiary = receiver, - Symbol = tokenSymbol, - SchemeId = schemeId - }); - profitAmount.Value.ShouldBe(amount); - var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - Beneficiary = receiver - }); - profitMap.Value[tokenSymbol].ShouldBe(amount); - } - - // after claim - { - await ProfitContractStub.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeId = schemeId - }); - var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - Beneficiary = receiver, - Symbol = tokenSymbol, - SchemeId = schemeId - }); - profitAmount.Value.ShouldBe(0); - var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput + AmountsMap = { - SchemeId = schemeId, - Beneficiary = receiver - }); - profitMap.Value.ContainsKey(tokenSymbol).ShouldBeFalse(); - } - - //second time + { tokenSymbol, amount } + }, + Period = 2 + }); + var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput { - await creator.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeId = schemeId, - AmountsMap = - { - {tokenSymbol, amount} - }, - Period = 2 - }); - var profitAmount = await ProfitContractStub.GetProfitAmount.CallAsync(new GetProfitAmountInput - { - Beneficiary = receiver, - Symbol = tokenSymbol, - SchemeId = schemeId - }); - profitAmount.Value.ShouldBe(amount); - var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput - { - SchemeId = schemeId, - Beneficiary = receiver - }); - profitMap.Value[tokenSymbol].ShouldBe(amount); - } - - - } - - private async Task ContributeProfits(Hash schemeId, long amount = 100) - { - await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + Beneficiary = receiver, + Symbol = tokenSymbol, + SchemeId = schemeId + }); + profitAmount.Value.ShouldBe(amount); + var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput { SchemeId = schemeId, - Symbol = ProfitContractTestConstants.NativeTokenSymbol, - Amount = amount + Beneficiary = receiver }); + profitMap.Value[tokenSymbol].ShouldBe(amount); } } + + private async Task ContributeProfits(Hash schemeId, long amount = 100) + { + await ProfitContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeId = schemeId, + Symbol = ProfitContractTestConstants.NativeTokenSymbol, + Amount = amount + }); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Profit.Tests/Types/MineList.cs b/test/AElf.Contracts.Profit.Tests/Types/MineList.cs index 4db3af4d4e..ed9c3082b5 100644 --- a/test/AElf.Contracts.Profit.Tests/Types/MineList.cs +++ b/test/AElf.Contracts.Profit.Tests/Types/MineList.cs @@ -1,49 +1,44 @@ using System.Linq; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/AElf.Contracts.Referendum.Tests.csproj b/test/AElf.Contracts.Referendum.Tests/AElf.Contracts.Referendum.Tests.csproj index 373db2fe30..469d1ac6dc 100644 --- a/test/AElf.Contracts.Referendum.Tests/AElf.Contracts.Referendum.Tests.csproj +++ b/test/AElf.Contracts.Referendum.Tests/AElf.Contracts.Referendum.Tests.csproj @@ -10,22 +10,22 @@ 0436 - - - - - - + + + + + + - - - - - - - + + + + + + + diff --git a/test/AElf.Contracts.Referendum.Tests/GenesisContractDtoExtensions.cs b/test/AElf.Contracts.Referendum.Tests/GenesisContractDtoExtensions.cs index e001e8894e..28af9df395 100644 --- a/test/AElf.Contracts.Referendum.Tests/GenesisContractDtoExtensions.cs +++ b/test/AElf.Contracts.Referendum.Tests/GenesisContractDtoExtensions.cs @@ -1,18 +1,19 @@ using AElf.Standards.ACS0; using Google.Protobuf; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public static class GenesisContractDtoExtensions { - public static class GenesisContractDtoExtensions + internal static void Add( + this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, + string methodName, + IMessage input) { - internal static void Add(this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, string methodName, - IMessage input) + systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall() - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index 9510458c2e..9cfd9278d9 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -1,1476 +1,1482 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public sealed class ReferendumContractTest : ReferendumContractTestBase { - public sealed class ReferendumContractTest : ReferendumContractTestBase - { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainService _blockchainService; - private readonly TestDemoSmartContractAddressNameProvider _smartContractAddressNameProvider; - public ReferendumContractTest() - { - _smartContractAddressService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _smartContractAddressNameProvider = GetRequiredService(); - InitializeContracts(); + private readonly IBlockchainService _blockchainService; + private readonly TestDemoSmartContractAddressNameProvider _smartContractAddressNameProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + + public ReferendumContractTest() + { + _smartContractAddressService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _smartContractAddressNameProvider = GetRequiredService(); + InitializeContracts(); + } + + [Fact] + public async Task Get_Organization_Test() + { + //not exist + { + var organization = + await ReferendumContractStub.GetOrganization.CallAsync(Accounts[0].Address); + organization.ShouldBe(new Organization()); + + var result = await ReferendumContractStub.ValidateOrganizationExist.CallAsync(DefaultSender); + result.Value.ShouldBeFalse(); } - [Fact] - public async Task Get_Organization_Test() + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var createOrganizationInput = new CreateOrganizationInput { - //not exist - { - var organization = - await ReferendumContractStub.GetOrganization.CallAsync(Accounts[0].Address); - organization.ShouldBe(new Organization()); + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { DefaultSender } + }, + TokenSymbol = "ELF" + }; + var transactionResult = + await ReferendumContractStub.CreateOrganization.SendAsync(createOrganizationInput); + var organizationAddress = transactionResult.Output; + var getOrganization = await ReferendumContractStub.GetOrganization.CallAsync(organizationAddress); + + getOrganization.OrganizationAddress.ShouldBe(organizationAddress); + getOrganization.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApproveThreshold); + getOrganization.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(minimalVoteThreshold); + getOrganization.ProposalReleaseThreshold.MaximalAbstentionThreshold.ShouldBe(maximalAbstentionThreshold); + getOrganization.ProposalReleaseThreshold.MaximalRejectionThreshold.ShouldBe(maximalRejectionThreshold); + getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); + } - var result = await ReferendumContractStub.ValidateOrganizationExist.CallAsync(DefaultSender); - result.Value.ShouldBeFalse(); - } + [Fact] + public async Task Get_Proposal_Test() + { + //not exist + { + var proposal = await ReferendumContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); + proposal.ShouldBe(new ProposalOutput()); + } + + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var createInput = new CreateInput + { + Symbol = "NEW", + Decimals = 2, + TotalSupply = 10_0000, + TokenName = "new token", + Issuer = organizationAddress, + IsBurnable = true + }; + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var getProposal = await ReferendumContractStub.GetProposal.SendAsync(proposalId); + + getProposal.Output.Proposer.ShouldBe(DefaultSender); + getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContract.Create)); + getProposal.Output.ProposalId.ShouldBe(proposalId); + getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); + getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); + getProposal.Output.Params.ShouldBe(createInput.ToByteString()); + } - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var createOrganizationInput = new CreateOrganizationInput + [Fact] + public async Task Create_ProposalFailed_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var blockTime = BlockTimeProvider.GetBlockTime(); + + { + //"Invalid proposal." + var createProposalInput = new CreateProposalInput { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {DefaultSender} - }, - TokenSymbol = "ELF", + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = blockTime.AddDays(1), + OrganizationAddress = organizationAddress }; var transactionResult = - await ReferendumContractStub.CreateOrganization.SendAsync(createOrganizationInput); - var organizationAddress = transactionResult.Output; - var getOrganization = await ReferendumContractStub.GetOrganization.CallAsync(organizationAddress); - - getOrganization.OrganizationAddress.ShouldBe(organizationAddress); - getOrganization.ProposalReleaseThreshold.MinimalApprovalThreshold.ShouldBe(minimalApproveThreshold); - getOrganization.ProposalReleaseThreshold.MinimalVoteThreshold.ShouldBe(minimalVoteThreshold); - getOrganization.ProposalReleaseThreshold.MaximalAbstentionThreshold.ShouldBe(maximalAbstentionThreshold); - getOrganization.ProposalReleaseThreshold.MaximalRejectionThreshold.ShouldBe(maximalRejectionThreshold); - getOrganization.OrganizationHash.ShouldBe(HashHelper.ComputeFrom(createOrganizationInput)); + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); } - - [Fact] - public async Task Get_Proposal_Test() { - //not exist - { - var proposal = await ReferendumContractStub.GetProposal.CallAsync(HashHelper.ComputeFrom("Test")); - proposal.ShouldBe(new ProposalOutput()); - } - - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var createInput = new CreateInput() + var createProposalInput = new CreateProposalInput { - Symbol = "NEW", - Decimals = 2, - TotalSupply = 10_0000, - TokenName = "new token", - Issuer = organizationAddress, - IsBurnable = true + ToAddress = null, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = blockTime.AddDays(1), + OrganizationAddress = organizationAddress, + ContractMethodName = "Test" }; - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var getProposal = await ReferendumContractStub.GetProposal.SendAsync(proposalId); - - getProposal.Output.Proposer.ShouldBe(DefaultSender); - getProposal.Output.ContractMethodName.ShouldBe(nameof(TokenContract.Create)); - getProposal.Output.ProposalId.ShouldBe(proposalId); - getProposal.Output.OrganizationAddress.ShouldBe(organizationAddress); - getProposal.Output.ToAddress.ShouldBe(TokenContractAddress); - getProposal.Output.Params.ShouldBe(createInput.ToByteString()); + var transactionResult = + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); } - - [Fact] - public async Task Create_ProposalFailed_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var blockTime = BlockTimeProvider.GetBlockTime(); - - { - //"Invalid proposal." - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = blockTime.AddDays(1), - OrganizationAddress = organizationAddress - }; - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - { - var createProposalInput = new CreateProposalInput - { - ToAddress = null, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = blockTime.AddDays(1), - OrganizationAddress = organizationAddress, - ContractMethodName = "Test" - }; - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - { - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = null, - OrganizationAddress = organizationAddress, - ContractMethodName = "Test" - }; - - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - } - { - //"Expired proposal." - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = TimestampHelper.GetUtcNow().AddSeconds(-5), - OrganizationAddress = organizationAddress, - ContractMethodName = "Test" - }; - - BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow()); - - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - { - //"No registered organization." - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = DefaultSender, - ContractMethodName = "Test" - }; - - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Organization not found.").ShouldBeTrue(); - } - { - //"Proposal with same input." - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = organizationAddress, - ContractMethodName = "Test" - }; - var transactionResult1 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transactionResult2 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - + var createProposalInput = new CreateProposalInput { - //"Proposal with invalid url." - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = organizationAddress, - ContractMethodName = "Test", - ProposalDescriptionUrl = "test.com" - }; - var transactionResult = - await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - - createProposalInput.ProposalDescriptionUrl = "https://test.com/test%abcd%&wxyz"; - var transactionResult2 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = null, + OrganizationAddress = organizationAddress, + ContractMethodName = "Test" + }; - { - // unauthorized to propose - var createProposalInput = new CreateProposalInput - { - ToAddress = Accounts[0].Address, - Params = ByteString.CopyFromUtf8("Test"), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - OrganizationAddress = organizationAddress, - ContractMethodName = "Test" - }; - var transactionResult = await GetReferendumContractTester(Accounts.Last().KeyPair) - .CreateProposal.SendWithExceptionAsync(createProposalInput); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to propose."); - } + var transactionResult = + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); } - - [Fact] - public async Task Approve_Proposal_NotFoundProposal_Test() { + //"Expired proposal." + var createProposalInput = new CreateProposalInput + { + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = TimestampHelper.GetUtcNow().AddSeconds(-5), + OrganizationAddress = organizationAddress, + ContractMethodName = "Test" + }; + + BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow()); + var transactionResult = - await ReferendumContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Invalid proposal id").ShouldBeTrue(); } - - [Fact] - public async Task Approve_WithoutAllowance() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var approveTx = await ReferendumContractStub.Approve.SendWithExceptionAsync(proposalId); - approveTx.TransactionResult.Error.ShouldContain("Allowance not enough."); - } + //"No registered organization." + var createProposalInput = new CreateProposalInput + { + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = DefaultSender, + ContractMethodName = "Test" + }; - [Fact] - public async Task Approve_Success() + var transactionResult = + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Organization not found.").ShouldBeTrue(); + } { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var proposalVirtualAddress = await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(proposalId); - long amount = 1000; - await TokenContractStub.Approve.SendAsync(new ApproveInput + //"Proposal with same input." + var createProposalInput = new CreateProposalInput { - Amount = amount, - Spender = proposalVirtualAddress, - Symbol = "ELF" - }); - var balance1 = await GetBalanceAsync("ELF", DefaultSender); - var transactionResult1 = await ReferendumContractStub.Approve.SendAsync(proposalId); + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = organizationAddress, + ContractMethodName = "Test" + }; + var transactionResult1 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var balance2 = await GetBalanceAsync("ELF", DefaultSender); - balance2.ShouldBe(balance1 - amount); - var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - proposal.ApprovalCount.ShouldBe(amount); + var transactionResult2 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact] - public async Task Approve_Proposal_MultiTimes_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - var keyPair = Accounts[1].KeyPair; - var userBalanceBeforeApprove = - await GetBalanceAsync("ELF", Address.FromPublicKey(keyPair.PublicKey)); - long amount = 1000; - - await ApproveAllowanceAsync(keyPair, amount, proposalId); - var referendumContractStub = GetReferendumContractTester(keyPair); - await referendumContractStub.Approve.SendAsync(proposalId); - var userBalance = - await GetBalanceAsync("ELF", Accounts[1].Address); - userBalance.ShouldBe(userBalanceBeforeApprove - amount); - - var transactionResult2 = await referendumContractStub.Approve.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Error.ShouldContain("Allowance not enough."); - - await ApproveAllowanceAsync(keyPair, amount, proposalId); + //"Proposal with invalid url." + var createProposalInput = new CreateProposalInput + { + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = organizationAddress, + ContractMethodName = "Test", + ProposalDescriptionUrl = "test.com" + }; + var transactionResult = + await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal.").ShouldBeTrue(); - var result = await referendumContractStub.Reject.SendWithExceptionAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Already locked."); + createProposalInput.ProposalDescriptionUrl = "https://test.com/test%abcd%&wxyz"; + var transactionResult2 = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact] - public async Task Approve_Proposal_ExpiredTime_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var timeStamp = TimestampHelper.GetUtcNow(); - var proposalId = - await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress, timeStamp.AddSeconds(5)); + // unauthorized to propose + var createProposalInput = new CreateProposalInput + { + ToAddress = Accounts[0].Address, + Params = ByteString.CopyFromUtf8("Test"), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = organizationAddress, + ContractMethodName = "Test" + }; + var transactionResult = await GetReferendumContractTester(Accounts.Last().KeyPair) + .CreateProposal.SendWithExceptionAsync(createProposalInput); + transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to propose."); + } + } - var referendumContractStub = GetReferendumContractTester(Accounts[1].KeyPair); - BlockTimeProvider.SetBlockTime(timeStamp.AddSeconds(10)); + [Fact] + public async Task Approve_Proposal_NotFoundProposal_Test() + { + var transactionResult = + await ReferendumContractStub.Approve.SendWithExceptionAsync(HashHelper.ComputeFrom("Test")); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.Contains("Invalid proposal id").ShouldBeTrue(); + } - var error = await referendumContractStub.Approve.CallWithExceptionAsync(proposalId); - error.Value.ShouldContain("Invalid proposal."); - } + [Fact] + public async Task Approve_WithoutAllowance() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var approveTx = await ReferendumContractStub.Approve.SendWithExceptionAsync(proposalId); + approveTx.TransactionResult.Error.ShouldContain("Allowance not enough."); + } - [Fact] - public async Task Approve_WrongAllowance() + [Fact] + public async Task Approve_Success() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var proposalVirtualAddress = await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(proposalId); + long amount = 1000; + await TokenContractStub.Approve.SendAsync(new ApproveInput { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + Amount = amount, + Spender = proposalVirtualAddress, + Symbol = "ELF" + }); + var balance1 = await GetBalanceAsync("ELF", DefaultSender); + var transactionResult1 = await ReferendumContractStub.Approve.SendAsync(proposalId); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var balance2 = await GetBalanceAsync("ELF", DefaultSender); + balance2.ShouldBe(balance1 - amount); + + var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + proposal.ApprovalCount.ShouldBe(amount); + } - var keyPair = Accounts[1].KeyPair; - long amount = 1000; - await GetTokenContractTester(keyPair).Approve.SendAsync(new ApproveInput - { - Amount = amount, - Spender = ReferendumContractAddress, - Symbol = "ELF" - }); - ReferendumContractStub = GetReferendumContractTester(keyPair); - var approveTransaction = await ReferendumContractStub.Approve.SendWithExceptionAsync(proposalId); - approveTransaction.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - approveTransaction.TransactionResult.Error.Contains("Allowance not enough.").ShouldBeTrue(); - } + [Fact] + public async Task Approve_Proposal_MultiTimes_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + var keyPair = Accounts[1].KeyPair; + var userBalanceBeforeApprove = + await GetBalanceAsync("ELF", Address.FromPublicKey(keyPair.PublicKey)); + long amount = 1000; + + await ApproveAllowanceAsync(keyPair, amount, proposalId); + var referendumContractStub = GetReferendumContractTester(keyPair); + await referendumContractStub.Approve.SendAsync(proposalId); + var userBalance = + await GetBalanceAsync("ELF", Accounts[1].Address); + userBalance.ShouldBe(userBalanceBeforeApprove - amount); + + var transactionResult2 = await referendumContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Error.ShouldContain("Allowance not enough."); + + await ApproveAllowanceAsync(keyPair, amount, proposalId); + + var result = await referendumContractStub.Reject.SendWithExceptionAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Already locked."); + } - [Fact] - public async Task ReclaimVoteToken_AfterRelease() - { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - await AddAddressToCreateTokenWhiteListAsync(organizationAddress); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var amount = 5000; - var accountApprove = Accounts[3]; - await ApproveAllowanceAsync(accountApprove.KeyPair, amount, proposalId); - var balanceApprove1 = await GetBalanceAsync("ELF", accountApprove.Address); - var accountReject = Accounts[4]; - await ApproveAllowanceAsync(accountReject.KeyPair, amount, proposalId); - var balanceReject1 = await GetBalanceAsync("ELF", accountReject.Address); - var accountAbstain = Accounts[5]; - await ApproveAllowanceAsync(accountAbstain.KeyPair, amount, proposalId); - var balanceAbstain1 = await GetBalanceAsync("ELF", accountAbstain.Address); - - await ApproveAsync(accountApprove.KeyPair, proposalId); - await RejectAsync(accountReject.KeyPair, proposalId); - await AbstainAsync(accountAbstain.KeyPair, proposalId); + [Fact] + public async Task Approve_Proposal_ExpiredTime_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var timeStamp = TimestampHelper.GetUtcNow(); + var proposalId = + await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress, timeStamp.AddSeconds(5)); + + var referendumContractStub = GetReferendumContractTester(Accounts[1].KeyPair); + BlockTimeProvider.SetBlockTime(timeStamp.AddSeconds(10)); + + var error = await referendumContractStub.Approve.CallWithExceptionAsync(proposalId); + error.Value.ShouldContain("Invalid proposal."); + } - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await ReferendumContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Approve_WrongAllowance() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + var keyPair = Accounts[1].KeyPair; + long amount = 1000; + await GetTokenContractTester(keyPair).Approve.SendAsync(new ApproveInput + { + Amount = amount, + Spender = ReferendumContractAddress, + Symbol = "ELF" + }); + ReferendumContractStub = GetReferendumContractTester(keyPair); + var approveTransaction = await ReferendumContractStub.Approve.SendWithExceptionAsync(proposalId); + approveTransaction.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + approveTransaction.TransactionResult.Error.Contains("Allowance not enough.").ShouldBeTrue(); + } - var referendumContractStubApprove = GetReferendumContractTester(accountApprove.KeyPair); - var reclaimResult1 = await referendumContractStubApprove.ReclaimVoteToken.SendAsync(proposalId); - reclaimResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task ReclaimVoteToken_AfterRelease() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + await AddAddressToCreateTokenWhiteListAsync(organizationAddress); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var amount = 5000; + var accountApprove = Accounts[3]; + await ApproveAllowanceAsync(accountApprove.KeyPair, amount, proposalId); + var balanceApprove1 = await GetBalanceAsync("ELF", accountApprove.Address); + var accountReject = Accounts[4]; + await ApproveAllowanceAsync(accountReject.KeyPair, amount, proposalId); + var balanceReject1 = await GetBalanceAsync("ELF", accountReject.Address); + var accountAbstain = Accounts[5]; + await ApproveAllowanceAsync(accountAbstain.KeyPair, amount, proposalId); + var balanceAbstain1 = await GetBalanceAsync("ELF", accountAbstain.Address); + + await ApproveAsync(accountApprove.KeyPair, proposalId); + await RejectAsync(accountReject.KeyPair, proposalId); + await AbstainAsync(accountAbstain.KeyPair, proposalId); + + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await ReferendumContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var referendumContractStubApprove = GetReferendumContractTester(accountApprove.KeyPair); + var reclaimResult1 = await referendumContractStubApprove.ReclaimVoteToken.SendAsync(proposalId); + reclaimResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var referendumContractStubReject = GetReferendumContractTester(accountReject.KeyPair); + var reclaimResult2 = await referendumContractStubReject.ReclaimVoteToken.SendAsync(proposalId); + reclaimResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var referendumContractStubAbstain = GetReferendumContractTester(accountAbstain.KeyPair); + var reclaimResult3 = await referendumContractStubAbstain.ReclaimVoteToken.SendAsync(proposalId); + reclaimResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var balanceApprove2 = await GetBalanceAsync("ELF", accountApprove.Address); + balanceApprove2.ShouldBe(balanceApprove1); + var balanceReject2 = await GetBalanceAsync("ELF", accountReject.Address); + balanceReject2.ShouldBe(balanceReject1); + var balanceAbstain2 = await GetBalanceAsync("ELF", accountAbstain.Address); + balanceAbstain2.ShouldBe(balanceAbstain1); + } - var referendumContractStubReject = GetReferendumContractTester(accountReject.KeyPair); - var reclaimResult2 = await referendumContractStubReject.ReclaimVoteToken.SendAsync(proposalId); - reclaimResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task ReclaimVoteToken_AfterExpired() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var timeStamp = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(timeStamp); // set next block time + var proposalId = + await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress, timeStamp.AddSeconds(5)); + var amount = 5000; + var account = Accounts[3]; + await ApproveAllowanceAsync(account.KeyPair, amount, proposalId); + var balance1 = await GetBalanceAsync("ELF", account.Address); + + await ApproveAsync(account.KeyPair, proposalId); + BlockTimeProvider.SetBlockTime(timeStamp.AddSeconds(10)); // set next block time + var referendumContractStubApprove = GetReferendumContractTester(account.KeyPair); + var reclaimResult = await referendumContractStubApprove.ReclaimVoteToken.SendAsync(proposalId); + reclaimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var balance2 = await GetBalanceAsync("ELF", account.Address); + balance2.ShouldBe(balance1); + + //delete expired proposal + var clearResult = await ReferendumContractStub.ClearProposal.SendAsync(proposalId); + clearResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + proposal.ShouldBe(new ProposalOutput()); + } - var referendumContractStubAbstain = GetReferendumContractTester(accountAbstain.KeyPair); - var reclaimResult3 = await referendumContractStubAbstain.ReclaimVoteToken.SendAsync(proposalId); - reclaimResult3.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task ReclaimVoteToken_WithoutRelease() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + var account = Accounts[1]; + var amount = 2000; + await ApproveAllowanceAsync(account.KeyPair, amount, proposalId); + await ApproveAsync(account.KeyPair, proposalId); + + var reclaimResult = await GetReferendumContractTester(account.KeyPair).ReclaimVoteToken + .SendWithExceptionAsync(proposalId); + reclaimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + reclaimResult.TransactionResult.Error.Contains("Unable to reclaim at this time.").ShouldBeTrue(); + } - var balanceApprove2 = await GetBalanceAsync("ELF", accountApprove.Address); - balanceApprove2.ShouldBe(balanceApprove1); - var balanceReject2 = await GetBalanceAsync("ELF", accountReject.Address); - balanceReject2.ShouldBe(balanceReject1); - var balanceAbstain2 = await GetBalanceAsync("ELF", accountAbstain.Address); - balanceAbstain2.ShouldBe(balanceAbstain1); - } + [Fact] + public async Task Reclaim_VoteTokenWithoutVote_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var timeStamp = TimestampHelper.GetUtcNow(); + var proposalId = + await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + var referendumContractStub = GetReferendumContractTester(Accounts[1].KeyPair); + BlockTimeProvider.SetBlockTime(timeStamp.AddDays(1)); // set next block time + + var reclaimResult = await referendumContractStub.ReclaimVoteToken.SendWithExceptionAsync(proposalId); + reclaimResult.TransactionResult.Error.ShouldContain("Nothing to reclaim."); + } - [Fact] - public async Task ReclaimVoteToken_AfterExpired() - { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var timeStamp = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(timeStamp); // set next block time - var proposalId = - await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress, timeStamp.AddSeconds(5)); - var amount = 5000; - var account = Accounts[3]; - await ApproveAllowanceAsync(account.KeyPair, amount, proposalId); - var balance1 = await GetBalanceAsync("ELF", account.Address); - - await ApproveAsync(account.KeyPair, proposalId); - BlockTimeProvider.SetBlockTime(timeStamp.AddSeconds(10)); // set next block time - var referendumContractStubApprove = GetReferendumContractTester(account.KeyPair); - var reclaimResult = await referendumContractStubApprove.ReclaimVoteToken.SendAsync(proposalId); - reclaimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var balance2 = await GetBalanceAsync("ELF", account.Address); - balance2.ShouldBe(balance1); - - //delete expired proposal - var clearResult = await ReferendumContractStub.ClearProposal.SendAsync(proposalId); - clearResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - proposal.ShouldBe(new ProposalOutput()); + [Fact] + public async Task Check_Proposal_ToBeRelease() + { + var minimalApproveThreshold = 1000; + var minimalVoteThreshold = 1000; + var maximalRejectionThreshold = 1000; + var maximalAbstentionThreshold = 1000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + //Abstain probability >= maximalAbstentionThreshold + { + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var keyPair1 = Accounts[1].KeyPair; + var amount = 1001; + await ApproveAllowanceAsync(keyPair1, amount, proposalId); + await ApproveAsync(keyPair1, proposalId); + var result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeTrue(); + var keyPair2 = Accounts[2].KeyPair; + await ApproveAllowanceAsync(keyPair2, amount, proposalId); + await AbstainAsync(keyPair2, proposalId); + result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeFalse(); } - - [Fact] - public async Task ReclaimVoteToken_WithoutRelease() + //Rejection probability > maximalRejectionThreshold { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var keyPair1 = Accounts[1].KeyPair; + var amount = 1001; + await ApproveAllowanceAsync(keyPair1, amount, proposalId); + await ApproveAsync(keyPair1, proposalId); + var result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeTrue(); + var keyPair2 = Accounts[2].KeyPair; + await ApproveAllowanceAsync(keyPair2, amount, proposalId); + await RejectAsync(keyPair2, proposalId); + result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + result.ToBeReleased.ShouldBeFalse(); + } + } - var account = Accounts[1]; - var amount = 2000; - await ApproveAllowanceAsync(account.KeyPair, amount, proposalId); - await ApproveAsync(account.KeyPair, proposalId); + [Fact] + public async Task Release_NotEnoughWeight_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var keyPair = Accounts[3].KeyPair; + var amount = 2000; + await ApproveAllowanceAsync(keyPair, amount, proposalId); + await ApproveAsync(keyPair, proposalId); + + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); + //Reviewer Shares < ReleaseThreshold, release failed + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); + } - var reclaimResult = await GetReferendumContractTester(account.KeyPair).ReclaimVoteToken - .SendWithExceptionAsync(proposalId); - reclaimResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - reclaimResult.TransactionResult.Error.Contains("Unable to reclaim at this time.").ShouldBeTrue(); - } + [Fact] + public async Task Release_NotFound_Test() + { + var proposalId = HashHelper.ComputeFrom("test"); + var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); + //Proposal not found + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Invalid proposal id."); + } - [Fact] - public async Task Reclaim_VoteTokenWithoutVote_Test() - { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var timeStamp = TimestampHelper.GetUtcNow(); - var proposalId = - await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + [Fact] + public async Task Release_WrongSender_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var keyPair = Accounts[3].KeyPair; + var amount = 5000; + await ApproveAllowanceAsync(keyPair, amount, proposalId); + await ApproveAsync(keyPair, proposalId); + + var referendumContractStub = GetReferendumContractTester(keyPair); + var result = await referendumContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); + } - var referendumContractStub = GetReferendumContractTester(Accounts[1].KeyPair); - BlockTimeProvider.SetBlockTime(timeStamp.AddDays(1)); // set next block time + [Fact] + public async Task Release_Proposal_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + await AddAddressToCreateTokenWhiteListAsync(organizationAddress); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + await ApproveAllowanceAsync(Accounts[3].KeyPair, minimalApproveThreshold, proposalId); + + await ApproveAsync(Accounts[3].KeyPair, proposalId); + + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await ReferendumContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // Check inline transaction result + var newToken = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = "NEW" }); + newToken.Issuer.ShouldBe(organizationAddress); + } - var reclaimResult = await referendumContractStub.ReclaimVoteToken.SendWithExceptionAsync(proposalId); - reclaimResult.TransactionResult.Error.ShouldContain("Nothing to reclaim."); - } + private async Task AddAddressToCreateTokenWhiteListAsync(Address address) + { + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var result = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = address.ToByteString(), + ContractMethodName = nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + OrganizationAddress = defaultOrganization + }); + var proposalId = result.Output; + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + } - [Fact] - public async Task Check_Proposal_ToBeRelease() + [Fact] + public async Task Release_Proposal_AlreadyReleased_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + await AddAddressToCreateTokenWhiteListAsync(organizationAddress); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + + // do not reach minimal approve amount { - var minimalApproveThreshold = 1000; - var minimalVoteThreshold = 1000; - var maximalRejectionThreshold = 1000; - var maximalAbstentionThreshold = 1000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - //Abstain probability >= maximalAbstentionThreshold - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var keyPair1 = Accounts[1].KeyPair; - var amount = 1001; - await ApproveAllowanceAsync(keyPair1, amount, proposalId); - await ApproveAsync(keyPair1, proposalId); - var result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeTrue(); - var keyPair2 = Accounts[2].KeyPair; - await ApproveAllowanceAsync(keyPair2, amount, proposalId); - await AbstainAsync(keyPair2, proposalId); - result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeFalse(); - } - //Rejection probability > maximalRejectionThreshold - { - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var keyPair1 = Accounts[1].KeyPair; - var amount = 1001; - await ApproveAllowanceAsync(keyPair1, amount, proposalId); - await ApproveAsync(keyPair1, proposalId); - var result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeTrue(); - var keyPair2 = Accounts[2].KeyPair; - await ApproveAllowanceAsync(keyPair2, amount, proposalId); - await RejectAsync(keyPair2, proposalId); - result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - result.ToBeReleased.ShouldBeFalse(); - } + var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); + result.TransactionResult.Error.ShouldContain("Not approved"); } - [Fact] - public async Task Release_NotEnoughWeight_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var amount = 5000; var keyPair = Accounts[3].KeyPair; - var amount = 2000; await ApproveAllowanceAsync(keyPair, amount, proposalId); await ApproveAsync(keyPair, proposalId); - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); - //Reviewer Shares < ReleaseThreshold, release failed - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Not approved.").ShouldBeTrue(); - } + var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await referendumContractStub.Release.SendAsync(proposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalReleased = ProposalReleased.Parser.ParseFrom(result.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed) + .ProposalId; + proposalReleased.ShouldBe(proposalId); - [Fact] - public async Task Release_NotFound_Test() - { - var proposalId = HashHelper.ComputeFrom("test"); - var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); - //Proposal not found - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Invalid proposal id."); + //After release,the proposal will be deleted + var getProposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + getProposal.ShouldBe(new ProposalOutput()); } - - [Fact] - public async Task Release_WrongSender_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var keyPair = Accounts[3].KeyPair; var amount = 5000; + var keyPair = Accounts[3].KeyPair; await ApproveAllowanceAsync(keyPair, amount, proposalId); - await ApproveAsync(keyPair, proposalId); + //approve the same proposal again var referendumContractStub = GetReferendumContractTester(keyPair); - var result = await referendumContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Error.Contains("No permission.").ShouldBeTrue(); - } - - [Fact] - public async Task Release_Proposal_Test() - { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - await AddAddressToCreateTokenWhiteListAsync(organizationAddress); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - await ApproveAllowanceAsync(Accounts[3].KeyPair, minimalApproveThreshold, proposalId); - - await ApproveAsync(Accounts[3].KeyPair, proposalId); - - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await ReferendumContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionResult = await referendumContractStub.Approve.SendWithExceptionAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.TransactionResult.Error.ShouldContain("Invalid proposal"); - // Check inline transaction result - var newToken = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput {Symbol = "NEW"}); - newToken.Issuer.ShouldBe(organizationAddress); + //release the same proposal again + var anotherReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var transactionResult2 = + await anotherReferendumContractStub.Release.SendWithExceptionAsync(proposalId); + transactionResult2.TransactionResult.Error.ShouldContain("Invalid proposal id."); } + } - private async Task AddAddressToCreateTokenWhiteListAsync(Address address) + [Fact] + public async Task Change_OrganizationThreshold_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); + var keyPair = Accounts[3].KeyPair; + await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, proposalId); + await ApproveAsync(Accounts[3].KeyPair, proposalId); + var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeTrue(); + + // invalid sender { - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var result = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ToAddress = TokenContractAddress, - Params = address.ToByteString(), - ContractMethodName = nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - OrganizationAddress = defaultOrganization - }); - var proposalId = result.Output; - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); + var ret = + await ReferendumContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( + new ProposalReleaseThreshold()); + ret.TransactionResult.Error.ShouldContain("Organization not found"); } - [Fact] - public async Task Release_Proposal_AlreadyReleased_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - await AddAddressToCreateTokenWhiteListAsync(organizationAddress); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - - // do not reach minimal approve amount + var proposalReleaseThresholdInput = new ProposalReleaseThreshold { - var result = await ReferendumContractStub.Release.SendWithExceptionAsync(proposalId); - result.TransactionResult.Error.ShouldContain("Not approved"); - } - - { - var amount = 5000; - var keyPair = Accounts[3].KeyPair; - await ApproveAllowanceAsync(keyPair, amount, proposalId); - await ApproveAsync(keyPair, proposalId); - - var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await referendumContractStub.Release.SendAsync(proposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalReleased = ProposalReleased.Parser.ParseFrom(result.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalReleased))).NonIndexed) - .ProposalId; - proposalReleased.ShouldBe(proposalId); - - //After release,the proposal will be deleted - var getProposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - getProposal.ShouldBe(new ProposalOutput()); - } - { - var amount = 5000; - var keyPair = Accounts[3].KeyPair; - await ApproveAllowanceAsync(keyPair, amount, proposalId); - - //approve the same proposal again - var referendumContractStub = GetReferendumContractTester(keyPair); - var transactionResult = await referendumContractStub.Approve.SendWithExceptionAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.ShouldContain("Invalid proposal"); - - //release the same proposal again - var anotherReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var transactionResult2 = - await anotherReferendumContractStub.Release.SendWithExceptionAsync(proposalId); - transactionResult2.TransactionResult.Error.ShouldContain("Invalid proposal id."); - } + MinimalVoteThreshold = 20000 + }; + + var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, + proposalReleaseThresholdInput, + nameof(ReferendumContractStub.ChangeOrganizationThreshold), organizationAddress); + await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, changeProposalId); + await ApproveAsync(Accounts[3].KeyPair, changeProposalId); + var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await referendumContractStub.Release.SendWithExceptionAsync(changeProposalId); + result.TransactionResult.Error.ShouldContain("Invalid organization."); } - [Fact] - public async Task Change_OrganizationThreshold_Test() { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); - var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); - var keyPair = Accounts[3].KeyPair; - await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, proposalId); - await ApproveAsync(Accounts[3].KeyPair, proposalId); - var proposal = await ReferendumContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeTrue(); - - // invalid sender + var proposalReleaseThresholdInput = new ProposalReleaseThreshold { - var ret = - await ReferendumContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( - new ProposalReleaseThreshold()); - ret.TransactionResult.Error.ShouldContain("Organization not found"); - } + MinimalVoteThreshold = 20000, + MinimalApprovalThreshold = minimalApproveThreshold + }; - { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 20000 - }; - - var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, - proposalReleaseThresholdInput, - nameof(ReferendumContractStub.ChangeOrganizationThreshold), organizationAddress); - await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, changeProposalId); - await ApproveAsync(Accounts[3].KeyPair, changeProposalId); - var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await referendumContractStub.Release.SendWithExceptionAsync(changeProposalId); - result.TransactionResult.Error.ShouldContain("Invalid organization."); - } + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, + proposalReleaseThresholdInput, + nameof(ReferendumContractStub.ChangeOrganizationThreshold), organizationAddress); + await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, changeProposalId); + await ApproveAsync(Accounts[3].KeyPair, changeProposalId); + var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await referendumContractStub.Release.SendAsync(changeProposalId); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - { - var proposalReleaseThresholdInput = new ProposalReleaseThreshold - { - MinimalVoteThreshold = 20000, - MinimalApprovalThreshold = minimalApproveThreshold - }; - - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, - proposalReleaseThresholdInput, - nameof(ReferendumContractStub.ChangeOrganizationThreshold), organizationAddress); - await ApproveAllowanceAsync(keyPair, minimalApproveThreshold, changeProposalId); - await ApproveAsync(Accounts[3].KeyPair, changeProposalId); - var referendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await referendumContractStub.Release.SendAsync(changeProposalId); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - proposal = await referendumContractStub.GetProposal.CallAsync(proposalId); - proposal.ToBeReleased.ShouldBeFalse(); - } + proposal = await referendumContractStub.GetProposal.CallAsync(proposalId); + proposal.ToBeReleased.ShouldBeFalse(); } + } - [Fact] - public async Task ChangeOrganizationProposalWhitelist_Fail_Test() + [Fact] + public async Task ChangeOrganizationProposalWhitelist_Fail_Test() + { + // invalid sender { - // invalid sender - { - var ret = - await ReferendumContractStub.ChangeOrganizationProposerWhiteList.SendWithExceptionAsync( - new ProposerWhiteList()); - ret.TransactionResult.Error.ShouldContain("Organization not found"); - } - - // invalid proposal whitelist - { - var organizationAddress = await CreateOrganizationAsync(); - var newProposalWhitelist = new ProposerWhiteList(); - var changeProposerWhitelistProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, - newProposalWhitelist, - nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); - var keyPair = Accounts[3].KeyPair; - await ApproveAllowanceAsync(keyPair, 5000, changeProposerWhitelistProposalId); - await ApproveAsync(keyPair, changeProposerWhitelistProposalId); - var ret = await ReferendumContractStub.Release.SendWithExceptionAsync( - changeProposerWhitelistProposalId); - ret.TransactionResult.Error.ShouldContain("Invalid organization"); - } + var ret = + await ReferendumContractStub.ChangeOrganizationProposerWhiteList.SendWithExceptionAsync( + new ProposerWhiteList()); + ret.TransactionResult.Error.ShouldContain("Organization not found"); } - [Fact] - public async Task Change_OrganizationProposalWhitelist_Test() + // invalid proposal whitelist { - var minimalApproveThreshold = 5000; - var minimalVoteThreshold = 5000; - var maximalRejectionThreshold = 10000; - var maximalAbstentionThreshold = 10000; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new[] {DefaultSender}); + var organizationAddress = await CreateOrganizationAsync(); + var newProposalWhitelist = new ProposerWhiteList(); + var changeProposerWhitelistProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, + newProposalWhitelist, + nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); + var keyPair = Accounts[3].KeyPair; + await ApproveAllowanceAsync(keyPair, 5000, changeProposerWhitelistProposalId); + await ApproveAsync(keyPair, changeProposerWhitelistProposalId); + var ret = await ReferendumContractStub.Release.SendWithExceptionAsync( + changeProposerWhitelistProposalId); + ret.TransactionResult.Error.ShouldContain("Invalid organization"); + } + } - var whiteAddress = Accounts[3].Address; - var proposerWhiteList = new ProposerWhiteList + [Fact] + public async Task Change_OrganizationProposalWhitelist_Test() + { + var minimalApproveThreshold = 5000; + var minimalVoteThreshold = 5000; + var maximalRejectionThreshold = 10000; + var maximalAbstentionThreshold = 10000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + + var whiteAddress = Accounts[3].Address; + var proposerWhiteList = new ProposerWhiteList + { + Proposers = { whiteAddress } + }; + + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, proposerWhiteList, + nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); + await ApproveAllowanceAsync(Accounts[3].KeyPair, minimalApproveThreshold, changeProposalId); + await ApproveAsync(Accounts[3].KeyPair, changeProposalId); + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var releaseResult = await ReferendumContractStub.Release.SendAsync(changeProposalId); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //verify whiteList + var verifyResult = await ReferendumContractStub.ValidateProposerInWhiteList.CallAsync( + new ValidateProposerInWhiteListInput { - Proposers = {whiteAddress} - }; + OrganizationAddress = organizationAddress, + Proposer = whiteAddress + }); + verifyResult.Value.ShouldBeTrue(); - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var changeProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, proposerWhiteList, - nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); - await ApproveAllowanceAsync(Accounts[3].KeyPair, minimalApproveThreshold, changeProposalId); - await ApproveAsync(Accounts[3].KeyPair, changeProposalId); - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var releaseResult = await ReferendumContractStub.Release.SendAsync(changeProposalId); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var timeStamp = TimestampHelper.GetUtcNow(); + var createInput = new CreateInput + { + Symbol = "NEW", + Decimals = 2, + TotalSupply = 10_0000, + TokenName = "new token", + Issuer = organizationAddress, + IsBurnable = true + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContract.Create), + ToAddress = TokenContractAddress, + Params = createInput.ToByteString(), + ExpiredTime = timeStamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), + OrganizationAddress = organizationAddress + }; + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + var result = await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Unauthorized to propose."); + } - //verify whiteList - var verifyResult = await ReferendumContractStub.ValidateProposerInWhiteList.CallAsync( - new ValidateProposerInWhiteListInput - { - OrganizationAddress = organizationAddress, - Proposer = whiteAddress - }); - verifyResult.Value.ShouldBeTrue(); - - var timeStamp = TimestampHelper.GetUtcNow(); - var createInput = new CreateInput - { - Symbol = "NEW", - Decimals = 2, - TotalSupply = 10_0000, - TokenName = "new token", - Issuer = organizationAddress, - IsBurnable = true - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContract.Create), - ToAddress = TokenContractAddress, - Params = createInput.ToByteString(), - ExpiredTime = timeStamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), - OrganizationAddress = organizationAddress - }; - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - var result = await ReferendumContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("Unauthorized to propose."); + [Fact] + public async Task SetMethodFee_Fail_Test() + { + // invalid token symbol + { + var invalidTokenSymbol = "CPW"; + var inputFee = GetValidMethodFees(); + inputFee.Fees[0].Symbol = invalidTokenSymbol; + var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); + ret.TransactionResult.Error.ShouldContain("Token is not found"); } - [Fact] - public async Task SetMethodFee_Fail_Test() + //invalid fee amount { - // invalid token symbol - { - var invalidTokenSymbol = "CPW"; - var inputFee = GetValidMethodFees(); - inputFee.Fees[0].Symbol = invalidTokenSymbol; - var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); - ret.TransactionResult.Error.ShouldContain("Token is not found"); - } - - //invalid fee amount - { - var inputFee = GetValidMethodFees(); - inputFee.Fees[0].BasicFee = -1; - var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); - ret.TransactionResult.Error.ShouldContain("Invalid amount"); - } - - //invalid sender - { - var inputFee = GetValidMethodFees(); - var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); - ret.TransactionResult.Error.ShouldContain("Unauthorized"); - } + var inputFee = GetValidMethodFees(); + inputFee.Fees[0].BasicFee = -1; + var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); + ret.TransactionResult.Error.ShouldContain("Invalid amount"); } - [Fact] - public async Task SetMethodFee_Test() + //invalid sender { - var inputFee = new MethodFees + var inputFee = GetValidMethodFees(); + var ret = await ReferendumContractStub.SetMethodFee.SendWithExceptionAsync(inputFee); + ret.TransactionResult.Error.ShouldContain("Unauthorized"); + } + } + + [Fact] + public async Task SetMethodFee_Test() + { + var inputFee = new MethodFees + { + MethodName = nameof(ReferendumContractStub.CreateProposal), + Fees = { - MethodName = nameof(ReferendumContractStub.CreateProposal), - Fees = + new MethodFee { - new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - } + Symbol = "ELF", + BasicFee = 5000_0000L } - }; - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var result = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ToAddress = ReferendumContractAddress, - Params = inputFee.ToByteString(), - ContractMethodName = nameof(ReferendumContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - OrganizationAddress = defaultOrganization - }); - var proposalId = result.Output; - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); + } + }; + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var result = await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ToAddress = ReferendumContractAddress, + Params = inputFee.ToByteString(), + ContractMethodName = nameof(ReferendumContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + OrganizationAddress = defaultOrganization + }); + var proposalId = result.Output; + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + + var feeResult = await ReferendumContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = nameof(ReferendumContractStub.CreateProposal) + }); + feeResult.Fees.First().ShouldBe(new MethodFee + { + Symbol = "ELF", + BasicFee = 5000_0000L + }); + } - var feeResult = await ReferendumContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(ReferendumContractStub.CreateProposal) - }); - feeResult.Fees.First().ShouldBe(new MethodFee + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() + { + var methodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalId = await CreateFeeProposalAsync(ReferendumContractAddress, + methodFeeController.OwnerAddress, nameof(ReferendumContractStub.ChangeMethodFeeController), + new AuthorityInfo { - Symbol = "ELF", - BasicFee = 5000_0000L + OwnerAddress = TokenContractAddress, + ContractAddress = ParliamentContractAddress }); - } + await ApproveWithMinersAsync(proposalId); + var ret = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + ret.TransactionResult.Error.ShouldContain("Invalid authority input"); + } - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() - { - var methodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); - var proposalId = await CreateFeeProposalAsync(ReferendumContractAddress, - methodFeeController.OwnerAddress, nameof(ReferendumContractStub.ChangeMethodFeeController), new AuthorityInfo + [Fact] + public async Task ChangeMethodFeeController_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new Parliament.CreateOrganizationInput { - OwnerAddress = TokenContractAddress, - ContractAddress = ParliamentContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var ret = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - ret.TransactionResult.Error.ShouldContain("Invalid authority input"); - } - - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new Parliament.CreateOrganizationInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(ReferendumContractStub.ChangeMethodFeeController); - var proposalId = await CreateFeeProposalAsync(ReferendumContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var methodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new Parliament.CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await ReferendumContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo + const string proposalCreationMethodName = nameof(ReferendumContractStub.ChangeMethodFeeController); + var proposalId = await CreateFeeProposalAsync(ReferendumContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, ContractAddress = ParliamentContractAddress }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + var newMethodFeeController = await ReferendumContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task CreateOrganizationBySystemContract_Test() - { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var createOrganizationInput = new CreateOrganizationInput - { - TokenSymbol = "ELF", - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new Parliament.CreateOrganizationInput { - Proposers = {DefaultSender} - } - }; - var input = new CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = createOrganizationInput, - OrganizationAddressFeedbackMethod = "" - }; - //Unauthorized to create organization - var addressByCalculate = - await ReferendumContractStub.CalculateOrganizationAddress.SendAsync(createOrganizationInput); - var transactionResult = - await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized"); - //success - var chain = await _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - var transactionResult1 = - await ReferendumContractStub.CreateOrganizationBySystemContract.SendAsync(input); - transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - transactionResult1.Output.ShouldBe(addressByCalculate.Output); - var boolResult = - ReferendumContractStub.ValidateOrganizationExist.SendAsync(addressByCalculate.Output); - boolResult.Result.Output.Value.ShouldBeTrue(); - //create again to verify address - var existTransactionResult = - await ReferendumContractStub.CreateOrganizationBySystemContract.SendAsync(input); - existTransactionResult.Output.ShouldBe(addressByCalculate.Output); - //invalid contract - var method = "OrganizationAddressFeedbackMethodName"; - var input2 = new CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = createOrganizationInput, - OrganizationAddressFeedbackMethod = method - }; - var transactionResult2 = - await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input2); - transactionResult2.TransactionResult.Error.ShouldContain("invalid contract"); - //Invalid organization data - var createOrganizationInput3 = new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {DefaultSender} - } - }; - var input3 = new CreateOrganizationBySystemContractInput - { - OrganizationCreationInput = createOrganizationInput3, - OrganizationAddressFeedbackMethod = "" - }; - var transactionResult3 = - await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input3); - transactionResult3.TransactionResult.Error.ShouldContain("Invalid organization data"); - } - - [Fact] - public async Task CreateProposalBySystemContract_Test() + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await ReferendumContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new []{DefaultSender}); - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = TokenContractAddress, - Memo = "Transfer" - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var input =new CreateProposalBySystemContractInput - { - ProposalInput = createProposalInput, OriginProposer = DefaultSender - }; - var chain = await _blockchainService.GetChainAsync(); - var blockIndex= new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - //Unauthorized to propose - var transactionResult = - await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - transactionResult.TransactionResult.Error.ShouldContain("Not authorized to propose."); - //success - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - var transactionResult2 = - await ReferendumContractStub.CreateProposalBySystemContract.SendAsync(input); - transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); - [Fact] - public async Task CreateOrganization_With_Invalid_Input_Test() + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task CreateOrganizationBySystemContract_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var createOrganizationInput = new CreateOrganizationInput { - // token symbol is null or empty + TokenSymbol = "ELF", + ProposalReleaseThreshold = new ProposalReleaseThreshold { - var validInput = GetValidCreateOrganizationInput(); - validInput.TokenSymbol = string.Empty; - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); - } - - // no proposer in proposeWhiteList + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList { - var validInput = GetValidCreateOrganizationInput(); - validInput.ProposerWhiteList.Proposers.Clear(); - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); + Proposers = { DefaultSender } } - - //MinimalApprovalThreshold > MinimalVoteThreshold - { - var validInput = GetValidCreateOrganizationInput(); - validInput.ProposalReleaseThreshold.MinimalApprovalThreshold = - validInput.ProposalReleaseThreshold.MinimalVoteThreshold + 1; - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); - } - - //MinimalApprovalThreshold == 0 - { - var validInput = GetValidCreateOrganizationInput(); - validInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 0; - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); - } - - //MaximalAbstentionThreshold < 0 + }; + var input = new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = createOrganizationInput, + OrganizationAddressFeedbackMethod = "" + }; + //Unauthorized to create organization + var addressByCalculate = + await ReferendumContractStub.CalculateOrganizationAddress.SendAsync(createOrganizationInput); + var transactionResult = + await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input); + transactionResult.TransactionResult.Error.ShouldContain("Unauthorized"); + //success + var chain = await _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + var transactionResult1 = + await ReferendumContractStub.CreateOrganizationBySystemContract.SendAsync(input); + transactionResult1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + transactionResult1.Output.ShouldBe(addressByCalculate.Output); + var boolResult = + ReferendumContractStub.ValidateOrganizationExist.SendAsync(addressByCalculate.Output); + boolResult.Result.Output.Value.ShouldBeTrue(); + //create again to verify address + var existTransactionResult = + await ReferendumContractStub.CreateOrganizationBySystemContract.SendAsync(input); + existTransactionResult.Output.ShouldBe(addressByCalculate.Output); + //invalid contract + var method = "OrganizationAddressFeedbackMethodName"; + var input2 = new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = createOrganizationInput, + OrganizationAddressFeedbackMethod = method + }; + var transactionResult2 = + await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input2); + transactionResult2.TransactionResult.Error.ShouldContain("invalid contract"); + //Invalid organization data + var createOrganizationInput3 = new CreateOrganizationInput + { + ProposalReleaseThreshold = new ProposalReleaseThreshold { - var validInput = GetValidCreateOrganizationInput(); - validInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = -1; - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); - } - - //MaximalRejectionThreshold < 0 + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + ProposerWhiteList = new ProposerWhiteList { - var validInput = GetValidCreateOrganizationInput(); - validInput.ProposalReleaseThreshold.MaximalRejectionThreshold = -1; - var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); - ret.TransactionResult.Error.ShouldContain("Invalid organization data"); + Proposers = { DefaultSender } } + }; + var input3 = new CreateOrganizationBySystemContractInput + { + OrganizationCreationInput = createOrganizationInput3, + OrganizationAddressFeedbackMethod = "" + }; + var transactionResult3 = + await ReferendumContractStub.CreateOrganizationBySystemContract.SendWithExceptionAsync(input3); + transactionResult3.TransactionResult.Error.ShouldContain("Invalid organization data"); + } + + [Fact] + public async Task CreateProposalBySystemContract_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var transferInput = new TransferInput + { + Symbol = "ELF", + Amount = 100, + To = TokenContractAddress, + Memo = "Transfer" + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var input = new CreateProposalBySystemContractInput + { + ProposalInput = createProposalInput, OriginProposer = DefaultSender + }; + var chain = await _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + //Unauthorized to propose + var transactionResult = + await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + transactionResult.TransactionResult.Error.ShouldContain("Not authorized to propose."); + //success + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); + var transactionResult2 = + await ReferendumContractStub.CreateProposalBySystemContract.SendAsync(input); + transactionResult2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task CreateOrganization_With_Invalid_Input_Test() + { + // token symbol is null or empty + { + var validInput = GetValidCreateOrganizationInput(); + validInput.TokenSymbol = string.Empty; + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } - [Fact] - public async Task CreateProposalBySystemContract_With_Invalid_Proposal_Test() + // no proposer in proposeWhiteList { - var minimalApproveThreshold = 2; - var minimalVoteThreshold = 3; - var maximalAbstentionThreshold = 1; - var maximalRejectionThreshold = 1; - var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, - maximalAbstentionThreshold, maximalRejectionThreshold, new []{DefaultSender}); - var input =new CreateProposalBySystemContractInput - { - OriginProposer = DefaultSender - }; - var chain = _blockchainService.GetChainAsync(); - var blockIndex= new BlockIndex - { - BlockHash = chain.Result.BestChainHash, - BlockHeight = chain.Result.BestChainHeight - }; - await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, - _smartContractAddressNameProvider.ContractStringName, DefaultSender); - - //invalid organization - { - var proposal = GetValidCreateProposalInput(organizationAddress); - proposal.OrganizationAddress = ReferendumContractAddress; - input.ProposalInput = proposal; - var ret = - await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Organization not found"); - } - - //method name = string.Empty - { - var proposal = GetValidCreateProposalInput(organizationAddress); - proposal.ContractMethodName = string.Empty; - input.ProposalInput = proposal; - var ret = - await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } - - //invalid expire time - { - var proposal = GetValidCreateProposalInput(organizationAddress); - proposal.ExpiredTime = new Timestamp(); - input.ProposalInput = proposal; - var ret = - await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } - - //invalid url - { - var proposal = GetValidCreateProposalInput(organizationAddress); - proposal.ProposalDescriptionUrl = "ppp"; - input.ProposalInput = proposal; - var ret = - await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); - ret.TransactionResult.Error.ShouldContain("Invalid proposal"); - } + var validInput = GetValidCreateOrganizationInput(); + validInput.ProposerWhiteList.Proposers.Clear(); + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } - [Fact] - public async Task ClearProposal_Fail_Test() + //MinimalApprovalThreshold > MinimalVoteThreshold { - // the proposal that is not exist - { - var proposalId = new Hash(); - var ret = await ReferendumContractStub.ClearProposal.SendWithExceptionAsync(proposalId); - ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } - - // the proposal that is not expired - { - var organizationAddress = await CreateOrganizationAsync(); - var newProposalWhitelist = new ProposerWhiteList(); - var changeProposerWhitelistProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, - newProposalWhitelist, - nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); - var ret = await ReferendumContractStub.ClearProposal.SendWithExceptionAsync(changeProposerWhitelistProposalId); - ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); - } + var validInput = GetValidCreateOrganizationInput(); + validInput.ProposalReleaseThreshold.MinimalApprovalThreshold = + validInput.ProposalReleaseThreshold.MinimalVoteThreshold + 1; + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } - private CreateOrganizationInput GetValidCreateOrganizationInput(Address sender = null) + //MinimalApprovalThreshold == 0 { - var validSender = sender ?? DefaultSender; - return new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 5000, - MinimalVoteThreshold = 5000, - MaximalAbstentionThreshold = 10000, - MaximalRejectionThreshold = 10000 - }, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {validSender} - }, - TokenSymbol = "ELF", - }; + var validInput = GetValidCreateOrganizationInput(); + validInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 0; + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } - - private CreateProposalInput GetValidCreateProposalInput(Address organizationAddress) + + //MaximalAbstentionThreshold < 0 { - var transferInput = new TransferInput - { - Symbol = "ELF", - Amount = 100, - To = TokenContractAddress, - Memo = "Transfer" - }; - return new CreateProposalInput - { - ContractMethodName = nameof(TokenContractStub.Transfer), - ToAddress = TokenContractAddress, - Params = transferInput.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; + var validInput = GetValidCreateOrganizationInput(); + validInput.ProposalReleaseThreshold.MaximalAbstentionThreshold = -1; + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } - private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress, - Timestamp timestamp = null) + //MaximalRejectionThreshold < 0 { - var createInput = new CreateInput() - { - Symbol = "NEW", - Decimals = 2, - TotalSupply = 10_0000, - TokenName = "new token", - Issuer = organizationAddress, - IsBurnable = true - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContract.Create), - ToAddress = TokenContractAddress, - Params = createInput.ToByteString(), - ExpiredTime = timestamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), - OrganizationAddress = organizationAddress - }; - ReferendumContractStub = GetReferendumContractTester(proposalKeyPair); - var proposal = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); - proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - return proposal.Output; + var validInput = GetValidCreateOrganizationInput(); + validInput.ProposalReleaseThreshold.MaximalRejectionThreshold = -1; + var ret = await ReferendumContractStub.CreateOrganization.SendWithExceptionAsync(validInput); + ret.TransactionResult.Error.ShouldContain("Invalid organization data"); } + } - private async Task CreateReferendumProposalAsync(ECKeyPair proposalKeyPair, IMessage input, - string method, Address organizationAddress) + [Fact] + public async Task CreateProposalBySystemContract_With_Invalid_Proposal_Test() + { + var minimalApproveThreshold = 2; + var minimalVoteThreshold = 3; + var maximalAbstentionThreshold = 1; + var maximalRejectionThreshold = 1; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); + var input = new CreateProposalBySystemContractInput { - var referendumContractStub = GetReferendumContractTester(proposalKeyPair); - var createProposalInput = new CreateProposalInput - { - ContractMethodName = method, - ToAddress = ReferendumContractAddress, - Params = input.ToByteString(), - ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), - OrganizationAddress = organizationAddress - }; - var proposal = await referendumContractStub.CreateProposal.SendAsync(createProposalInput); - var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs - .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) - .ProposalId; - proposal.Output.ShouldBe(proposalCreated); + OriginProposer = DefaultSender + }; + var chain = _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex + { + BlockHash = chain.Result.BestChainHash, + BlockHeight = chain.Result.BestChainHeight + }; + await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, + _smartContractAddressNameProvider.ContractStringName, DefaultSender); - return proposal.Output; + //invalid organization + { + var proposal = GetValidCreateProposalInput(organizationAddress); + proposal.OrganizationAddress = ReferendumContractAddress; + input.ProposalInput = proposal; + var ret = + await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Organization not found"); } - private async Task
CreateOrganizationAsync(long minimalApproveThreshold = 5000, long minimalVoteThreshold = 5000, - long maximalAbstentionThreshold = 10000, long maximalRejectionThreshold = 10000, Address[] proposerWhiteList = null, - string symbol = "ELF") + //method name = string.Empty { - if (proposerWhiteList == null) - proposerWhiteList = new[] {DefaultSender}; - var createOrganizationInput = new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = minimalApproveThreshold, - MinimalVoteThreshold = minimalVoteThreshold, - MaximalAbstentionThreshold = maximalAbstentionThreshold, - MaximalRejectionThreshold = maximalRejectionThreshold - }, - TokenSymbol = symbol, - ProposerWhiteList = new ProposerWhiteList - { - Proposers = {proposerWhiteList} - } - }; - var transactionResult = - await ReferendumContractStub.CreateOrganization.SendAsync(createOrganizationInput); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - return transactionResult.Output; + var proposal = GetValidCreateProposalInput(organizationAddress); + proposal.ContractMethodName = string.Empty; + input.ProposalInput = proposal; + var ret = + await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } - private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) - { - var referendumContractStub = GetReferendumContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = await referendumContractStub.Approve.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) - ?.NonIndexed); - ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(referendumContractStub.Approve)); + //invalid expire time + { + var proposal = GetValidCreateProposalInput(organizationAddress); + proposal.ExpiredTime = new Timestamp(); + input.ProposalInput = proposal; + var ret = + await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } - private async Task RejectAsync(ECKeyPair reviewer, Hash proposalId) - { - var referendumContractStub = GetReferendumContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = await referendumContractStub.Reject.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) - ?.NonIndexed); - ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(referendumContractStub.Reject)); + //invalid url + { + var proposal = GetValidCreateProposalInput(organizationAddress); + proposal.ProposalDescriptionUrl = "ppp"; + input.ProposalInput = proposal; + var ret = + await ReferendumContractStub.CreateProposalBySystemContract.SendWithExceptionAsync(input); + ret.TransactionResult.Error.ShouldContain("Invalid proposal"); } + } - private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) - { - var referendumContractStub = GetReferendumContractTester(reviewer); - var utcNow = TimestampHelper.GetUtcNow(); - BlockTimeProvider.SetBlockTime(utcNow); - var transactionResult = await referendumContractStub.Abstain.SendAsync(proposalId); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs - .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) - ?.NonIndexed); - ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, - nameof(referendumContractStub.Abstain));} - - private void ValidateReferendumReceiptCreated(ReferendumReceiptCreated referendumReceiptCreated, Address sender, Hash proposalId, - Timestamp blockTime, string receiptType) - { - referendumReceiptCreated.Address.ShouldBe(sender); - referendumReceiptCreated.ProposalId.ShouldBe(proposalId); - referendumReceiptCreated.Time.ShouldBe(blockTime); - referendumReceiptCreated.ReceiptType.ShouldBe(receiptType); + [Fact] + public async Task ClearProposal_Fail_Test() + { + // the proposal that is not exist + { + var proposalId = new Hash(); + var ret = await ReferendumContractStub.ClearProposal.SendWithExceptionAsync(proposalId); + ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); } - - private async Task ApproveAllowanceAsync(ECKeyPair keyPair, long amount, Hash proposalId, string symbol = "ELF") + + // the proposal that is not expired { - var proposalVirtualAddress = await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(proposalId); - await GetTokenContractTester(keyPair).Approve.SendAsync(new ApproveInput - { - Amount = amount, - Spender = proposalVirtualAddress, - Symbol = symbol - }); + var organizationAddress = await CreateOrganizationAsync(); + var newProposalWhitelist = new ProposerWhiteList(); + var changeProposerWhitelistProposalId = await CreateReferendumProposalAsync(DefaultSenderKeyPair, + newProposalWhitelist, + nameof(ReferendumContractStub.ChangeOrganizationProposerWhiteList), organizationAddress); + var ret = await ReferendumContractStub.ClearProposal.SendWithExceptionAsync( + changeProposerWhitelistProposalId); + ret.TransactionResult.Error.ShouldContain("Proposal clear failed"); } + } - private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private CreateOrganizationInput GetValidCreateOrganizationInput(Address sender = null) + { + var validSender = sender ?? DefaultSender; + return new CreateOrganizationInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 5000, + MinimalVoteThreshold = 5000, + MaximalAbstentionThreshold = 10000, + MaximalRejectionThreshold = 10000 + }, + ProposerWhiteList = new ProposerWhiteList + { + Proposers = { validSender } + }, + TokenSymbol = "ELF" + }; + } - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + private CreateProposalInput GetValidCreateProposalInput(Address organizationAddress) + { + var transferInput = new TransferInput + { + Symbol = "ELF", + Amount = 100, + To = TokenContractAddress, + Memo = "Transfer" + }; + return new CreateProposalInput + { + ContractMethodName = nameof(TokenContractStub.Transfer), + ToAddress = TokenContractAddress, + Params = transferInput.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + } - return proposalId; - } + private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress, + Timestamp timestamp = null) + { + var createInput = new CreateInput + { + Symbol = "NEW", + Decimals = 2, + TotalSupply = 10_0000, + TokenName = "new token", + Issuer = organizationAddress, + IsBurnable = true + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContract.Create), + ToAddress = TokenContractAddress, + Params = createInput.ToByteString(), + ExpiredTime = timestamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), + OrganizationAddress = organizationAddress + }; + ReferendumContractStub = GetReferendumContractTester(proposalKeyPair); + var proposal = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); + proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + return proposal.Output; + } + + private async Task CreateReferendumProposalAsync(ECKeyPair proposalKeyPair, IMessage input, + string method, Address organizationAddress) + { + var referendumContractStub = GetReferendumContractTester(proposalKeyPair); + var createProposalInput = new CreateProposalInput + { + ContractMethodName = method, + ToAddress = ReferendumContractAddress, + Params = input.ToByteString(), + ExpiredTime = BlockTimeProvider.GetBlockTime().AddDays(2), + OrganizationAddress = organizationAddress + }; + var proposal = await referendumContractStub.CreateProposal.SendAsync(createProposalInput); + var proposalCreated = ProposalCreated.Parser.ParseFrom(proposal.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(ProposalCreated))).NonIndexed) + .ProposalId; + proposal.Output.ShouldBe(proposalCreated); + + return proposal.Output; + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task
CreateOrganizationAsync(long minimalApproveThreshold = 5000, + long minimalVoteThreshold = 5000, + long maximalAbstentionThreshold = 10000, long maximalRejectionThreshold = 10000, + Address[] proposerWhiteList = null, + string symbol = "ELF") + { + if (proposerWhiteList == null) + proposerWhiteList = new[] { DefaultSender }; + var createOrganizationInput = new CreateOrganizationInput { - foreach (var bp in InitialCoreDataCenterKeyPairs) + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = minimalApproveThreshold, + MinimalVoteThreshold = minimalVoteThreshold, + MaximalAbstentionThreshold = maximalAbstentionThreshold, + MaximalRejectionThreshold = maximalRejectionThreshold + }, + TokenSymbol = symbol, + ProposerWhiteList = new ProposerWhiteList { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + Proposers = { proposerWhiteList } } + }; + var transactionResult = + await ReferendumContractStub.CreateOrganization.SendAsync(createOrganizationInput); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + return transactionResult.Output; + } + + private async Task ApproveAsync(ECKeyPair reviewer, Hash proposalId) + { + var referendumContractStub = GetReferendumContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = await referendumContractStub.Approve.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) + ?.NonIndexed); + ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(referendumContractStub.Approve)); + } + + private async Task RejectAsync(ECKeyPair reviewer, Hash proposalId) + { + var referendumContractStub = GetReferendumContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = await referendumContractStub.Reject.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) + ?.NonIndexed); + ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(referendumContractStub.Reject)); + } + + private async Task AbstainAsync(ECKeyPair reviewer, Hash proposalId) + { + var referendumContractStub = GetReferendumContractTester(reviewer); + var utcNow = TimestampHelper.GetUtcNow(); + BlockTimeProvider.SetBlockTime(utcNow); + var transactionResult = await referendumContractStub.Abstain.SendAsync(proposalId); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var receiptCreated = ReferendumReceiptCreated.Parser.ParseFrom(transactionResult.TransactionResult.Logs + .FirstOrDefault(l => l.Name == nameof(ReferendumReceiptCreated)) + ?.NonIndexed); + ValidateReferendumReceiptCreated(receiptCreated, Address.FromPublicKey(reviewer.PublicKey), proposalId, utcNow, + nameof(referendumContractStub.Abstain)); + } + + private void ValidateReferendumReceiptCreated(ReferendumReceiptCreated referendumReceiptCreated, Address sender, + Hash proposalId, + Timestamp blockTime, string receiptType) + { + referendumReceiptCreated.Address.ShouldBe(sender); + referendumReceiptCreated.ProposalId.ShouldBe(proposalId); + referendumReceiptCreated.Time.ShouldBe(blockTime); + referendumReceiptCreated.ReceiptType.ShouldBe(receiptType); + } + + private async Task ApproveAllowanceAsync(ECKeyPair keyPair, long amount, Hash proposalId, string symbol = "ELF") + { + var proposalVirtualAddress = await ReferendumContractStub.GetProposalVirtualAddress.CallAsync(proposalId); + await GetTokenContractTester(keyPair).Approve.SendAsync(new ApproveInput + { + Amount = amount, + Spender = proposalVirtualAddress, + Symbol = symbol + }); + } + + private async Task CreateFeeProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput + { + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + + return proposalId; + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } + } - private MethodFees GetValidMethodFees() + private MethodFees GetValidMethodFees() + { + return new MethodFees { - return new MethodFees + MethodName = nameof(ReferendumContractStub.CreateProposal), + Fees = { - MethodName = nameof(ReferendumContractStub.CreateProposal), - Fees = + new MethodFee { - new MethodFee - { - Symbol = "ELF", - BasicFee = 5000_0000L - } + Symbol = "ELF", + BasicFee = 5000_0000L } - }; - } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestAElfModule.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestAElfModule.cs index d1a6c5bda1..2854ff681d 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestAElfModule.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestAElfModule.cs @@ -4,15 +4,14 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +[DependsOn(typeof(ContractTestModule))] +public class ReferendumContractTestAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - public class ReferendumContractTestAElfModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.RemoveAll(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs index 00ae6f4aef..870f61fade 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs @@ -2,210 +2,210 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; +using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; -using AElf.Contracts.Referendum; +using AElf.Contracts.Parliament; using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; +using AElf.GovernmentSystem; using AElf.Kernel; +using AElf.Kernel.Consensus; +using AElf.Kernel.Proposal; using AElf.Kernel.Token; -using AElf.OS.Node.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Threading; -using AElf.Contracts.Parliament; -using AElf.Contracts.Consensus.AEDPoS; -using AElf.GovernmentSystem; -using AElf.Kernel.Consensus; -using AElf.Kernel.Proposal; +using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.Referendum +namespace AElf.Contracts.Referendum; + +public class ReferendumContractTestBase : ContractTestBase { - public class ReferendumContractTestBase : ContractTestBase - { - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(5).Select(a => a.KeyPair).ToList(); - protected Address TokenContractAddress { get; set; } - protected Address ReferendumContractAddress { get; set; } + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(5).Select(a => a.KeyPair).ToList(); - protected Address ParliamentContractAddress { get; set; } + protected Address TokenContractAddress { get; set; } + protected Address ReferendumContractAddress { get; set; } - protected Address ConsensusContractAddress { get; set; } - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected Address ParliamentContractAddress { get; set; } - protected IBlockTimeProvider BlockTimeProvider => - Application.ServiceProvider.GetRequiredService(); + protected Address ConsensusContractAddress { get; set; } + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal ReferendumContractImplContainer.ReferendumContractImplStub ReferendumContractStub { get; set; } + protected IBlockTimeProvider BlockTimeProvider => + Application.ServiceProvider.GetRequiredService(); - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal ReferendumContractImplContainer.ReferendumContractImplStub ReferendumContractStub { get; set; } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } - protected void InitializeContracts() - { - BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - - // deploy token contract - TokenContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), - Name = TokenSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateTokenInitializationCallList() - })).Output; - TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - - //deploy Referendum contract - ReferendumContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync(new SystemContractDeploymentInput + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + + protected void InitializeContracts() + { + BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); + + // deploy token contract + TokenContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput { Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ReferendumContract).Assembly.Location)), - Name = ReferendumSmartContractAddressNameProvider.Name, - // TransactionMethodCallList = GenerateReferendumInitializationCallList() + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), + Name = TokenSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateTokenInitializationCallList() })).Output; - ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); - - //deploy parliament auth contract - ParliamentContractAddress = AsyncHelper.RunSync(()=>GetContractZeroTester(DefaultSenderKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), - Name = ParliamentSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateParliamentInitializationCallList() - })).Output; - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - - //deploy consensus contract - ConsensusContractAddress = AsyncHelper.RunSync(()=>GetContractZeroTester(DefaultSenderKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), - Name = ConsensusSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateConsensusInitializationCallList() - })).Output; - AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); - } - - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + //deploy Referendum contract + ReferendumContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync(new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ReferendumContract).Assembly.Location)), + Name = ReferendumSmartContractAddressNameProvider.Name + // TransactionMethodCallList = GenerateReferendumInitializationCallList() + })).Output; + ReferendumContractStub = GetReferendumContractTester(DefaultSenderKeyPair); + + //deploy parliament auth contract + ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(DefaultSenderKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), + Name = ParliamentSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateParliamentInitializationCallList() + })).Output; + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - internal ReferendumContractImplContainer.ReferendumContractImplStub GetReferendumContractTester(ECKeyPair keyPair) - { - return GetTester(ReferendumContractAddress, keyPair); - } + //deploy consensus contract + ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(DefaultSenderKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), + Name = ConsensusSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateConsensusInitializationCallList() + })).Output; + AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, keyPair); - } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateTokenInitializationCallList() - { - const string symbol = "ELF"; - const long totalSupply = 100_000_000; - var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput - { - Symbol = symbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - }); + internal ReferendumContractImplContainer.ReferendumContractImplStub GetReferendumContractTester(ECKeyPair keyPair) + { + return GetTester(ReferendumContractAddress, + keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - //issue default user + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateTokenInitializationCallList() + { + const string symbol = "ELF"; + const long totalSupply = 100_000_000; + var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + { + Symbol = symbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender + }); + + //issue default user + tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + { + Symbol = symbol, + Amount = totalSupply - 20 * 100_000L, + To = DefaultSender, + Memo = "Issue token to default user." + }); + + //issue some user + for (var i = 1; i < 6; i++) tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput { Symbol = symbol, - Amount = totalSupply - 20 * 100_000L, - To = DefaultSender, - Memo = "Issue token to default user.", + Amount = 100_000, + To = Accounts[i].Address, + Memo = "Issue token to users" }); - //issue some user - for (int i = 1; i < 6; i++) - { - tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput - { - Symbol = symbol, - Amount = 100_000, - To = Accounts[i].Address, - Memo = "Issue token to users" - }); - } - - return tokenContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateParliamentInitializationCallList() - { - var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new Parliament.InitializeInput - { - PrivilegedProposer = DefaultSender, - ProposerAuthorityRequired = true - }); + return tokenContractCallList; + } - return parliamentContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateConsensusInitializationCallList() + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateParliamentInitializationCallList() + { + var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new InitializeInput { - var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), new InitialAElfConsensusContractInput + PrivilegedProposer = DefaultSender, + ProposerAuthorityRequired = true + }); + + return parliamentContractCallList; + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateConsensusInitializationCallList() + { + var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput { PeriodSeconds = 604800L, MinerIncreaseInterval = 31536000 }); - - consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList - { - Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); - return consensusContractCallList; - } - - protected async Task GetBalanceAsync(string symbol, Address owner) + consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList { - var balanceResult = await TokenContractStub.GetBalance.CallAsync( - new GetBalanceInput() - { - Owner = owner, - Symbol = symbol - }); - return balanceResult.Balance; - } + Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); + + return consensusContractCallList; + } + + protected async Task GetBalanceAsync(string symbol, Address owner) + { + var balanceResult = await TokenContractStub.GetBalance.CallAsync( + new GetBalanceInput + { + Owner = owner, + Symbol = symbol + }); + return balanceResult.Balance; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/TestDemoSmartContractAddressNameProvider.cs b/test/AElf.Contracts.Referendum.Tests/TestDemoSmartContractAddressNameProvider.cs index dc8d279d2e..bb64cfbed6 100644 --- a/test/AElf.Contracts.Referendum.Tests/TestDemoSmartContractAddressNameProvider.cs +++ b/test/AElf.Contracts.Referendum.Tests/TestDemoSmartContractAddressNameProvider.cs @@ -2,13 +2,13 @@ using AElf.Kernel.SmartContract; using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.Referendum + +namespace AElf.Contracts.Referendum; + +public class TestDemoSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TestDemoSmartContractAddressNameProvider:ISmartContractAddressNameProvider,ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TestDemo"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.TestDemo"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/Types/MinerList.cs b/test/AElf.Contracts.Referendum.Tests/Types/MinerList.cs index 4db3af4d4e..ed9c3082b5 100644 --- a/test/AElf.Contracts.Referendum.Tests/Types/MinerList.cs +++ b/test/AElf.Contracts.Referendum.Tests/Types/MinerList.cs @@ -1,49 +1,44 @@ using System.Linq; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase.Tests/AElf.Contracts.TestBase.Tests.csproj b/test/AElf.Contracts.TestBase.Tests/AElf.Contracts.TestBase.Tests.csproj index cdee12b11a..04a4d5338a 100644 --- a/test/AElf.Contracts.TestBase.Tests/AElf.Contracts.TestBase.Tests.csproj +++ b/test/AElf.Contracts.TestBase.Tests/AElf.Contracts.TestBase.Tests.csproj @@ -5,17 +5,17 @@ false - - - - - - + + + + + + - - + + false Contract @@ -33,5 +33,5 @@ - + diff --git a/test/AElf.Contracts.TestBase.Tests/ContractTesterTest.cs b/test/AElf.Contracts.TestBase.Tests/ContractTesterTest.cs index a8d9ef52f4..8a9df961c3 100644 --- a/test/AElf.Contracts.TestBase.Tests/ContractTesterTest.cs +++ b/test/AElf.Contracts.TestBase.Tests/ContractTesterTest.cs @@ -1,175 +1,174 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.MultiToken; using AElf.Cryptography; using AElf.Kernel.Consensus; using AElf.Kernel.Token; -using AElf.OS.Node.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Xunit; -namespace AElf.Contracts.TestBase.Tests +namespace AElf.Contracts.TestBase.Tests; + +public class ContractTesterTest { - public class ContractTesterTest - { - private IReadOnlyDictionary _codes; + private IReadOnlyDictionary _codes; - public IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); + public IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - public byte[] ConsensusContractCode => - Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("Consensus.AEDPoS")).Value; - public byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - private int ChainId { get; } = ChainHelper.ConvertBase58ToChainId("AELF"); - private int DefaultCategory { get; } = SmartContractTestConstants.TestRunnerCategory; + public byte[] ConsensusContractCode => + Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("Consensus.AEDPoS")).Value; - [Fact] - public async Task InitialChain_Test() - { - var tester = new ContractTester(); - await tester.InitialChainAsync(); + public byte[] TokenContractCode => Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + private int ChainId { get; } = ChainHelper.ConvertBase58ToChainId("AELF"); + private int DefaultCategory { get; } = SmartContractTestConstants.TestRunnerCategory; - var chain = await tester.GetChainAsync(); - var longestChainHeight = chain.LongestChainHeight; + [Fact] + public async Task InitialChain_Test() + { + var tester = new ContractTester(); + await tester.InitialChainAsync(); - Assert.Equal(1, longestChainHeight); - } + var chain = await tester.GetChainAsync(); + var longestChainHeight = chain.LongestChainHeight; - [Fact] - public async Task Mine_Test() - { - var tester = new ContractTester(); - await tester.InitialChainAsync(); + Assert.Equal(1, longestChainHeight); + } - var zeroContractAddress = tester.GetContractAddress(Hash.Empty); - // Create a transaction to deploy token contract. - var tx = await tester.GenerateTransactionAsync(zeroContractAddress, - "DeploySmartContract", - new ContractDeploymentInput() - { - Category = SmartContractTestConstants.TestRunnerCategory, - Code = ByteString.CopyFrom(TokenContractCode) - }); + [Fact] + public async Task Mine_Test() + { + var tester = new ContractTester(); + await tester.InitialChainAsync(); + + var zeroContractAddress = tester.GetContractAddress(Hash.Empty); + // Create a transaction to deploy token contract. + var tx = await tester.GenerateTransactionAsync(zeroContractAddress, + "DeploySmartContract", + new ContractDeploymentInput + { + Category = SmartContractTestConstants.TestRunnerCategory, + Code = ByteString.CopyFrom(TokenContractCode) + }); - var chain = await tester.GetChainAsync(); - var longestChainHeight = chain.LongestChainHeight; + var chain = await tester.GetChainAsync(); + var longestChainHeight = chain.LongestChainHeight; - Assert.Equal(1, longestChainHeight); + Assert.Equal(1, longestChainHeight); - await tester.MineAsync(new List {tx}); + await tester.MineAsync(new List { tx }); - chain = await tester.GetChainAsync(); - longestChainHeight = chain.LongestChainHeight; + chain = await tester.GetChainAsync(); + longestChainHeight = chain.LongestChainHeight; - // The longest chain height increased from 1 to 2. - Assert.Equal(2, longestChainHeight); - } + // The longest chain height increased from 1 to 2. + Assert.Equal(2, longestChainHeight); + } - [Fact] - public async Task MultipleNodes_Test() - { - var tester1 = new ContractTester(); - await tester1.InitialChainAsync(); + [Fact] + public async Task MultipleNodes_Test() + { + var tester1 = new ContractTester(); + await tester1.InitialChainAsync(); - var tester2 = new ContractTester(); - await tester2.InitialChainAsync(); + var tester2 = new ContractTester(); + await tester2.InitialChainAsync(); - var zeroContractAddress = tester1.GetContractAddress(Hash.Empty); + var zeroContractAddress = tester1.GetContractAddress(Hash.Empty); - var tx = await tester1.GenerateTransactionAsync(zeroContractAddress, - "DeploySmartContract", - new ContractDeploymentInput() - { - Category = SmartContractTestConstants.TestRunnerCategory, - Code = ByteString.CopyFrom(TokenContractCode) - }); + var tx = await tester1.GenerateTransactionAsync(zeroContractAddress, + "DeploySmartContract", + new ContractDeploymentInput + { + Category = SmartContractTestConstants.TestRunnerCategory, + Code = ByteString.CopyFrom(TokenContractCode) + }); - await tester1.MineAsync(new List {tx}); + await tester1.MineAsync(new List { tx }); - var chain1 = await tester1.GetChainAsync(); - var chain2 = await tester2.GetChainAsync(); + var chain1 = await tester1.GetChainAsync(); + var chain2 = await tester2.GetChainAsync(); - // For different nodes, the chain information are different. - Assert.Equal(2, chain1.BestChainHeight); - Assert.Equal(1, chain2.BestChainHeight); - } + // For different nodes, the chain information are different. + Assert.Equal(2, chain1.BestChainHeight); + Assert.Equal(1, chain2.BestChainHeight); + } - [Fact] - public async Task CallContract_Test() + [Fact] + public async Task CallContract_Test() + { + var callerKeyPair = CryptoHelper.GenerateKeyPair(); + var tester = new ContractTester(ChainId, callerKeyPair); + await tester.InitialChainAsync(list => { - var callerKeyPair = CryptoHelper.GenerateKeyPair(); - var tester = new ContractTester(ChainId, callerKeyPair); - await tester.InitialChainAsync(list => + list.AddGenesisSmartContract( + ConsensusContractCode, + ConsensusSmartContractAddressNameProvider.Name); + list.AddGenesisSmartContract( + TokenContractCode, + TokenSmartContractAddressNameProvider.Name); + }); + + var tokenContractAddress = tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + + var bytes = await tester.CallContractMethodAsync(tokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.GetBalance), + new GetBalanceInput { - list.AddGenesisSmartContract( - ConsensusContractCode, - ConsensusSmartContractAddressNameProvider.Name); - list.AddGenesisSmartContract( - TokenContractCode, - TokenSmartContractAddressNameProvider.Name); + Symbol = "ELF", + Owner = tester.GetCallOwnerAddress() }); - var tokenContractAddress = tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + var balanceOutput = GetBalanceOutput.Parser.ParseFrom(bytes); - var bytes = await tester.CallContractMethodAsync(tokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.GetBalance), - new GetBalanceInput - { - Symbol = "ELF", - Owner = tester.GetCallOwnerAddress(), - }); + Assert.Equal(0L, balanceOutput.Balance); + } + + [Fact] + public async Task GetTransactionResult_Test() + { + var tester = new ContractTester(); + await tester.InitialChainAsync(); - var balanceOutput = GetBalanceOutput.Parser.ParseFrom(bytes); + var zeroContractAddress = tester.GetContractAddress(Hash.Empty); + var tx = await tester.GenerateTransactionAsync(zeroContractAddress, "DeploySmartContract", + new ContractDeploymentInput + { + Category = DefaultCategory, + Code = ByteString.CopyFrom(TokenContractCode) + } + ); - Assert.Equal(0L, balanceOutput.Balance); - } + await tester.MineAsync(new List { tx }); - [Fact] - public async Task GetTransactionResult_Test() - { - var tester = new ContractTester(); - await tester.InitialChainAsync(); + var txResult = await tester.GetTransactionResultAsync(tx.GetHash()); - var zeroContractAddress = tester.GetContractAddress(Hash.Empty); - var tx = await tester.GenerateTransactionAsync(zeroContractAddress, "DeploySmartContract", - new ContractDeploymentInput - { - Category = DefaultCategory, - Code = ByteString.CopyFrom(TokenContractCode) - } - ); + Assert.Equal(TransactionResultStatus.Mined, txResult.Status); + } - await tester.MineAsync(new List {tx}); + [Fact] + public async Task CreateContractTester_Test() + { + var tester = new ContractTester(); + await tester.InitialChainAsync(); + var zeroContractAddress = tester.GetContractAddress(Hash.Empty); + var tx = await tester.GenerateTransactionAsync(zeroContractAddress, + "DeploySmartContract", + new ContractDeploymentInput + { + Category = SmartContractTestConstants.TestRunnerCategory, + Code = ByteString.CopyFrom(TokenContractCode) + }); - var txResult = await tester.GetTransactionResultAsync(tx.GetHash()); + await tester.MineAsync(new List { tx }); - Assert.Equal(TransactionResultStatus.Mined, txResult.Status); - } + var newTester = tester.CreateNewContractTester(CryptoHelper.GenerateKeyPair()); + var chain = await newTester.GetChainAsync(); - [Fact] - public async Task CreateContractTester_Test() - { - var tester = new ContractTester(); - await tester.InitialChainAsync(); - var zeroContractAddress = tester.GetContractAddress(Hash.Empty); - var tx = await tester.GenerateTransactionAsync(zeroContractAddress, - "DeploySmartContract", - new ContractDeploymentInput() - { - Category = SmartContractTestConstants.TestRunnerCategory, - Code = ByteString.CopyFrom(TokenContractCode) - }); - - await tester.MineAsync(new List {tx}); - - var newTester = tester.CreateNewContractTester(CryptoHelper.GenerateKeyPair()); - var chain = await newTester.GetChainAsync(); - - Assert.Equal(2L, chain.BestChainHeight); - } + Assert.Equal(2L, chain.BestChainHeight); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase.Tests/TestBaseTestAElfModule.cs b/test/AElf.Contracts.TestBase.Tests/TestBaseTestAElfModule.cs index 0e6cb93cc3..cbbc1df4f7 100644 --- a/test/AElf.Contracts.TestBase.Tests/TestBaseTestAElfModule.cs +++ b/test/AElf.Contracts.TestBase.Tests/TestBaseTestAElfModule.cs @@ -1,13 +1,12 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Contracts.TestBase.Tests +namespace AElf.Contracts.TestBase.Tests; + +[DependsOn(typeof(ContractTestAElfModule))] +public class TestBaseTestAElfModule : AElfModule { - [DependsOn(typeof(ContractTestAElfModule))] - public class TestBaseTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/AElf.Contracts.TestBase.csproj b/test/AElf.Contracts.TestBase/AElf.Contracts.TestBase.csproj index 41be70be59..2f987b9204 100644 --- a/test/AElf.Contracts.TestBase/AElf.Contracts.TestBase.csproj +++ b/test/AElf.Contracts.TestBase/AElf.Contracts.TestBase.csproj @@ -15,7 +15,7 @@ Contract PreserveNewest - + false Contract @@ -28,17 +28,17 @@ - - - - - - - - - - - + + + + + + + + + + + false Contract diff --git a/test/AElf.Contracts.TestBase/ContractTestAElfModule.cs b/test/AElf.Contracts.TestBase/ContractTestAElfModule.cs index 956047701a..408a788559 100644 --- a/test/AElf.Contracts.TestBase/ContractTestAElfModule.cs +++ b/test/AElf.Contracts.TestBase/ContractTestAElfModule.cs @@ -8,7 +8,6 @@ using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Kernel.TransactionPool.Infrastructure; using AElf.Modularity; using AElf.OS; using AElf.OS.Network.Application; @@ -19,55 +18,55 @@ using Microsoft.Extensions.Options; using Moq; using Volo.Abp.Modularity; +using UnitTestContractZeroCodeProvider = AElf.Kernel.UnitTestContractZeroCodeProvider; -namespace AElf.Contracts.TestBase +namespace AElf.Contracts.TestBase; + +[DependsOn( + typeof(CSharpRuntimeAElfModule), + typeof(CoreOSAElfModule), + typeof(KernelTestAElfModule) +)] +public class ContractTestAElfModule : AElfModule { - [DependsOn( - typeof(CSharpRuntimeAElfModule), - typeof(CoreOSAElfModule), - typeof(KernelTestAElfModule) - )] - public class ContractTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(o => Mock.Of()); - services.AddSingleton(o => Mock.Of()); + var services = context.Services; + services.AddSingleton(o => Mock.Of()); + services.AddSingleton(o => Mock.Of()); + + services.AddSingleton(o => Mock.Of()); - services.AddSingleton(o => Mock.Of()); + // When testing contract and packaging transactions, no need to generate and schedule real consensus stuff. + context.Services.AddSingleton(o => Mock.Of()); + context.Services.AddSingleton(o => Mock.Of()); - // When testing contract and packaging transactions, no need to generate and schedule real consensus stuff. - context.Services.AddSingleton(o => Mock.Of()); - context.Services.AddSingleton(o => Mock.Of()); + var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); + context.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, data))); + + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(ecKeyPair.PublicKey); - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, data))); + return mockService.Object; + }); - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(ecKeyPair.PublicKey); + context.Services.RemoveAll(); - return mockService.Object; - }); - - context.Services.RemoveAll(); - - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new UnitTestCSharpSmartContractRunner( - option.Value.SdkDir); - }); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services - .AddSingleton(); - context.Services - .AddSingleton(); - } + context.Services.AddSingleton(provider => + { + var option = provider.GetService>(); + return new UnitTestCSharpSmartContractRunner( + option.Value.SdkDir); + }); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services + .AddSingleton(); + context.Services + .AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/ContractTestBase.cs b/test/AElf.Contracts.TestBase/ContractTestBase.cs index 994e52b3b3..e2e1b89d20 100644 --- a/test/AElf.Contracts.TestBase/ContractTestBase.cs +++ b/test/AElf.Contracts.TestBase/ContractTestBase.cs @@ -2,15 +2,15 @@ using AElf.ContractDeployer; using AElf.TestBase; -namespace AElf.Contracts.TestBase +namespace AElf.Contracts.TestBase; + +public class ContractTestBase : AElfIntegratedTest + where TContractTestAElfModule : ContractTestAElfModule { - public class ContractTestBase : AElfIntegratedTest - where TContractTestAElfModule : ContractTestAElfModule - { - private IReadOnlyDictionary _codes; + private IReadOnlyDictionary _codes; + + public IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - public IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - protected ContractTester Tester { get; set; } = new ContractTester(); - } + protected ContractTester Tester { get; set; } = new(); } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/ContractTester.cs b/test/AElf.Contracts.TestBase/ContractTester.cs index ffbefe5a90..f850cdbab5 100644 --- a/test/AElf.Contracts.TestBase/ContractTester.cs +++ b/test/AElf.Contracts.TestBase/ContractTester.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.CrossChain; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.CrossChain; using AElf.Cryptography; using AElf.Cryptography.ECDSA; @@ -26,10 +25,8 @@ using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; using AElf.Kernel.SmartContractExecution.Application; using AElf.Kernel.Token; -using AElf.Kernel.TransactionPool.Application; using AElf.OS.Node.Application; using AElf.OS.Node.Domain; using AElf.Types; @@ -43,822 +40,808 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; using TokenContract = AElf.Contracts.MultiToken.TokenContractContainer.TokenContractStub; -using ParliamentContractStub = AElf.Contracts.Parliament.ParliamentContractContainer.ParliamentContractStub; using CrossChainContract = AElf.Contracts.CrossChain.CrossChainContractContainer.CrossChainContractStub; - -namespace AElf.Contracts.TestBase +using InitializeInput = AElf.Contracts.CrossChain.InitializeInput; + +namespace AElf.Contracts.TestBase; + +/// +/// For testing contracts. +/// Basically we can use this class to: +/// Create a new chain with provided smart contracts deployed, +/// Package chosen transactions and mine a block, +/// execute a block if transactions in block body provided, +/// call a contract method and get the execution result, +/// generate a new tester using exists context, +/// etc. +/// +/// +public class ContractTester : ITransientDependency + where TContractTestAElfModule : ContractTestAElfModule { - /// - /// For testing contracts. - /// Basically we can use this class to: - /// - /// Create a new chain with provided smart contracts deployed, - /// Package chosen transactions and mine a block, - /// execute a block if transactions in block body provided, - /// call a contract method and get the execution result, - /// generate a new tester using exists context, - /// etc. - /// - /// - public class ContractTester : ITransientDependency - where TContractTestAElfModule : ContractTestAElfModule - { - private IReadOnlyDictionary _codes; - - public IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); + private IReadOnlyDictionary _codes; + public long InitialBalanceOfStarter = 800_000_000_00000000L; + public List InitialMinerList = new(); + public long InitialTreasuryAmount = 200_000_000_00000000L; + public bool IsPrivilegePreserved = true; - public byte[] ConsensusContractCode => GetContractCodeByName(SmartContractTestConstants.Consensus); + public long TokenTotalSupply = 1_000_000_000_00000000L; - public byte[] TokenContractCode => GetContractCodeByName(SmartContractTestConstants.MultiToken); - - public byte[] CrossChainContractCode => GetContractCodeByName(SmartContractTestConstants.CrossChain); + public ContractTester() : this(0, null) + { + } - public byte[] ParliamentContractCode => GetContractCodeByName(SmartContractTestConstants.Parliament); + public ContractTester(int chainId, ECKeyPair keyPair) + { + var sampleKeyPairs = SampleECKeyPairs.KeyPairs.Take(3).ToList(); + InitialMinerList.AddRange(sampleKeyPairs); + KeyPair = keyPair ?? InitialMinerList[1]; - public byte[] ConfigurationContractCode => GetContractCodeByName(SmartContractTestConstants.Configuration); + Application = + AbpApplicationFactory.Create(options => + { + options.UseAutofac(); + if (chainId != 0) options.Services.Configure(o => { o.ChainId = chainId; }); - public byte[] AssociationContractCode => GetContractCodeByName(SmartContractTestConstants.Association); + options.Services.Configure(o => + { + var miners = new List(); - public byte[] ReferendumContractCode => GetContractCodeByName(SmartContractTestConstants.Referendum); + foreach (var minerKeyPair in InitialMinerList) miners.Add(minerKeyPair.PublicKey.ToHex()); - private byte[] GetContractCodeByName(string contractName) - { - return Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith(contractName)).Value; - } + o.InitialMinerList = miners; + o.MiningInterval = 4000; + o.StartTimestamp = new Timestamp { Seconds = 0 }; + }); - private IAbpApplicationWithInternalServiceProvider Application { get; } + if (keyPair != null) + options.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, data))); - public ECKeyPair KeyPair { get; } - public List InitialMinerList = new List(); + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(KeyPair.PublicKey); - public string PublicKey => KeyPair.PublicKey.ToHex(); + return mockService.Object; + }); + }); - public long TokenTotalSupply = 1_000_000_000_00000000L; - public long InitialTreasuryAmount = 200_000_000_00000000L; - public long InitialBalanceOfStarter = 800_000_000_00000000L; - public bool IsPrivilegePreserved = true; + Application.Initialize(); + } - public ContractTester() : this(0, null) + private ContractTester(IAbpApplicationWithInternalServiceProvider application, ECKeyPair keyPair) + { + application.Services.AddTransient(o => { - } + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, data))); - public ContractTester(int chainId, ECKeyPair keyPair) - { - var sampleKeyPairs = SampleECKeyPairs.KeyPairs.Take(3).ToList(); - InitialMinerList.AddRange(sampleKeyPairs); - KeyPair = keyPair ?? InitialMinerList[1]; + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(keyPair.PublicKey); - Application = - AbpApplicationFactory.Create(options => - { - options.UseAutofac(); - if (chainId != 0) - { - options.Services.Configure(o => { o.ChainId = chainId; }); - } + return mockService.Object; + }); - options.Services.Configure(o => - { - var miners = new List(); + Application = application; - foreach (var minerKeyPair in InitialMinerList) - { - miners.Add(minerKeyPair.PublicKey.ToHex()); - } + KeyPair = keyPair; + } - o.InitialMinerList = miners; - o.MiningInterval = 4000; - o.StartTimestamp = new Timestamp {Seconds = 0}; - }); + private ContractTester(IAbpApplicationWithInternalServiceProvider application, int chainId) + { + application.Services.Configure(o => { o.ChainId = chainId; }); - if (keyPair != null) - { - options.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, data))); + Application = application; + } - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(KeyPair.PublicKey); + /// + /// Use default chain id. + /// + /// + public ContractTester(ECKeyPair keyPair) + { + Application = + AbpApplicationFactory.Create(options => + { + options.UseAutofac(); + options.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, data))); + + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(keyPair.PublicKey); - return mockService.Object; - }); - } + return mockService.Object; }); + }); - Application.Initialize(); - } + Application.Initialize(); - private ContractTester(IAbpApplicationWithInternalServiceProvider application, ECKeyPair keyPair) - { - application.Services.AddTransient(o => + KeyPair = keyPair; + } + + /// + /// Use randomized ECKeyPair. + /// + /// + public ContractTester(int chainId) + { + Application = + AbpApplicationFactory.Create(options => { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, data))); + options.UseAutofac(); + options.Services.Configure(o => { o.ChainId = chainId; }); + }); + Application.Initialize(); + } - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(keyPair.PublicKey); + public IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - return mockService.Object; - }); + public byte[] ConsensusContractCode => GetContractCodeByName(SmartContractTestConstants.Consensus); - Application = application; + public byte[] TokenContractCode => GetContractCodeByName(SmartContractTestConstants.MultiToken); - KeyPair = keyPair; - } + public byte[] CrossChainContractCode => GetContractCodeByName(SmartContractTestConstants.CrossChain); - private ContractTester(IAbpApplicationWithInternalServiceProvider application, int chainId) - { - application.Services.Configure(o => { o.ChainId = chainId; }); + public byte[] ParliamentContractCode => GetContractCodeByName(SmartContractTestConstants.Parliament); - Application = application; - } + public byte[] ConfigurationContractCode => GetContractCodeByName(SmartContractTestConstants.Configuration); - /// - /// Use default chain id. - /// - /// - public ContractTester(ECKeyPair keyPair) - { - Application = - AbpApplicationFactory.Create(options => - { - options.UseAutofac(); - options.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, data))); + public byte[] AssociationContractCode => GetContractCodeByName(SmartContractTestConstants.Association); - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(keyPair.PublicKey); + public byte[] ReferendumContractCode => GetContractCodeByName(SmartContractTestConstants.Referendum); - return mockService.Object; - }); - }); + private IAbpApplicationWithInternalServiceProvider Application { get; } - Application.Initialize(); + public ECKeyPair KeyPair { get; } - KeyPair = keyPair; - } + public string PublicKey => KeyPair.PublicKey.ToHex(); - /// - /// Initial a chain with given chain id (passed to ctor), - /// and produce the genesis block with provided smart contract configuration. - /// Will deploy consensus contract by default. - /// - /// Return contract addresses as the param order. - public async Task InitialChainAsync( - Action> configureSmartContract = null) - { - var osBlockchainNodeContextService = - Application.ServiceProvider.GetRequiredService(); - var chainOptions = Application.ServiceProvider.GetService>().Value; - var consensusOptions = Application.ServiceProvider.GetService>().Value; - var dto = new OsBlockchainNodeContextStartDto - { - ChainId = chainOptions.ChainId, - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory - }; - - dto.InitializationSmartContracts.AddGenesisSmartContract( - ConsensusContractCode, - ConsensusSmartContractAddressNameProvider.Name, - GenerateConsensusInitializationCallList(consensusOptions)); - configureSmartContract?.Invoke(dto.InitializationSmartContracts); - - return await osBlockchainNodeContextService.StartAsync(dto); - } + private byte[] GetContractCodeByName(string contractName) + { + return Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith(contractName)).Value; + } - public async Task InitialChainAsyncWithAuthAsync( - Action> configureSmartContract = null) - { - var osBlockchainNodeContextService = - Application.ServiceProvider.GetRequiredService(); - var contractOptions = Application.ServiceProvider.GetService>().Value; - var consensusOptions = Application.ServiceProvider.GetService>().Value; - consensusOptions.StartTimestamp = TimestampHelper.GetUtcNow(); + /// + /// Initial a chain with given chain id (passed to ctor), + /// and produce the genesis block with provided smart contract configuration. + /// Will deploy consensus contract by default. + /// + /// Return contract addresses as the param order. + public async Task InitialChainAsync( + Action> configureSmartContract = null) + { + var osBlockchainNodeContextService = + Application.ServiceProvider.GetRequiredService(); + var chainOptions = Application.ServiceProvider.GetService>().Value; + var consensusOptions = Application.ServiceProvider.GetService>().Value; + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = chainOptions.ChainId, + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory + }; + + dto.InitializationSmartContracts.AddGenesisSmartContract( + ConsensusContractCode, + ConsensusSmartContractAddressNameProvider.Name, + GenerateConsensusInitializationCallList(consensusOptions)); + configureSmartContract?.Invoke(dto.InitializationSmartContracts); + + return await osBlockchainNodeContextService.StartAsync(dto); + } - var dto = new OsBlockchainNodeContextStartDto - { - ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, - ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired - }; - dto.InitializationSmartContracts.AddGenesisSmartContract( - ConsensusContractCode, - ConsensusSmartContractAddressNameProvider.Name, - GenerateConsensusInitializationCallList(consensusOptions)); - configureSmartContract?.Invoke(dto.InitializationSmartContracts); - - var result = await osBlockchainNodeContextService.StartAsync(dto); - var blockChainService = Application.ServiceProvider.GetRequiredService(); - var transactionManager = Application.ServiceProvider.GetRequiredService(); - var chain = await blockChainService.GetChainAsync(); - var block = await blockChainService.GetBlockByHashAsync(chain.GenesisBlockHash); - foreach (var transactionId in block.TransactionIds) - { - var transactionResult = - await transactionManager.GetTransactionResultAsync(transactionId, block.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined,transactionResult.Error); - } - return result; - } + public async Task InitialChainAsyncWithAuthAsync( + Action> configureSmartContract = null) + { + var osBlockchainNodeContextService = + Application.ServiceProvider.GetRequiredService(); + var contractOptions = Application.ServiceProvider.GetService>().Value; + var consensusOptions = Application.ServiceProvider.GetService>().Value; + consensusOptions.StartTimestamp = TimestampHelper.GetUtcNow(); + + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, + ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired + }; + dto.InitializationSmartContracts.AddGenesisSmartContract( + ConsensusContractCode, + ConsensusSmartContractAddressNameProvider.Name, + GenerateConsensusInitializationCallList(consensusOptions)); + configureSmartContract?.Invoke(dto.InitializationSmartContracts); + + var result = await osBlockchainNodeContextService.StartAsync(dto); + var blockChainService = Application.ServiceProvider.GetRequiredService(); + var transactionManager = Application.ServiceProvider.GetRequiredService(); + var chain = await blockChainService.GetChainAsync(); + var block = await blockChainService.GetBlockByHashAsync(chain.GenesisBlockHash); + foreach (var transactionId in block.TransactionIds) + { + var transactionResult = + await transactionManager.GetTransactionResultAsync(transactionId, block.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined, transactionResult.Error); + } + + return result; + } - public async Task InitialCustomizedChainAsync(int chainId, - List initialMiners = null, int miningInterval = 4000, - Timestamp startTimestamp = null, Action> configureSmartContract = null) - { - if (initialMiners == null) - { - initialMiners = Enumerable.Range(0, 3).Select(i => SampleECKeyPairs.KeyPairs[i].PublicKey.ToHex()) - .ToList(); - } + public async Task InitialCustomizedChainAsync(int chainId, + List initialMiners = null, int miningInterval = 4000, + Timestamp startTimestamp = null, Action> configureSmartContract = null) + { + if (initialMiners == null) + initialMiners = Enumerable.Range(0, 3).Select(i => SampleECKeyPairs.KeyPairs[i].PublicKey.ToHex()) + .ToList(); + + if (startTimestamp == null) startTimestamp = TimestampHelper.GetUtcNow(); + + var osBlockchainNodeContextService = + Application.ServiceProvider.GetRequiredService(); + var contractOptions = Application.ServiceProvider.GetService>().Value; + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = chainId, + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, + ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired + }; + + dto.InitializationSmartContracts.AddGenesisSmartContract( + ConsensusContractCode, + ConsensusSmartContractAddressNameProvider.Name, + GenerateConsensusInitializationCallList(initialMiners, miningInterval, startTimestamp)); + configureSmartContract?.Invoke(dto.InitializationSmartContracts); + + return await osBlockchainNodeContextService.StartAsync(dto); + } - if (startTimestamp == null) + private List + GenerateConsensusInitializationCallList(ConsensusOptions consensusOptions) + { + var consensusMethodCallList = new List(); + consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput { - startTimestamp = TimestampHelper.GetUtcNow(); - } - - var osBlockchainNodeContextService = - Application.ServiceProvider.GetRequiredService(); - var contractOptions = Application.ServiceProvider.GetService>().Value; - var dto = new OsBlockchainNodeContextStartDto + IsTermStayOne = true + }); + consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), + new MinerList { - ChainId = chainId, - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory, - ContractDeploymentAuthorityRequired = contractOptions.ContractDeploymentAuthorityRequired - }; - - dto.InitializationSmartContracts.AddGenesisSmartContract( - ConsensusContractCode, - ConsensusSmartContractAddressNameProvider.Name, - GenerateConsensusInitializationCallList(initialMiners, miningInterval, startTimestamp)); - configureSmartContract?.Invoke(dto.InitializationSmartContracts); - - return await osBlockchainNodeContextService.StartAsync(dto); - } - - private List - GenerateConsensusInitializationCallList(ConsensusOptions consensusOptions) - { - var consensusMethodCallList = new List(); - consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), - new InitialAElfConsensusContractInput + Pubkeys = { - IsTermStayOne = true - }); - consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), - new MinerList - { - Pubkeys = - { - consensusOptions.InitialMinerList.Select(ByteStringHelper.FromHexString) - } - }.GenerateFirstRoundOfNewTerm(consensusOptions.MiningInterval, - consensusOptions.StartTimestamp)); - return consensusMethodCallList; - } + consensusOptions.InitialMinerList.Select(ByteStringHelper.FromHexString) + } + }.GenerateFirstRoundOfNewTerm(consensusOptions.MiningInterval, + consensusOptions.StartTimestamp)); + return consensusMethodCallList; + } - private List - GenerateConsensusInitializationCallList(List initialMiners, - int miningInterval, Timestamp startTimestamp) - { - var consensusMethodCallList = new List(); - consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), - new InitialAElfConsensusContractInput - { - IsSideChain = true - }); - consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), - new MinerList + private List + GenerateConsensusInitializationCallList(List initialMiners, + int miningInterval, Timestamp startTimestamp) + { + var consensusMethodCallList = new List(); + consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput + { + IsSideChain = true + }); + consensusMethodCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), + new MinerList + { + Pubkeys = { - Pubkeys = - { - initialMiners.Select(ByteStringHelper.FromHexString) - } - }.GenerateFirstRoundOfNewTerm(miningInterval, startTimestamp)); - return consensusMethodCallList; - } + initialMiners.Select(ByteStringHelper.FromHexString) + } + }.GenerateFirstRoundOfNewTerm(miningInterval, startTimestamp)); + return consensusMethodCallList; + } - public async Task InitialSideChainAsync(int chainId, - Action> configureSmartContract = null) - { - var osBlockchainNodeContextService = - Application.ServiceProvider.GetRequiredService(); - var dto = new OsBlockchainNodeContextStartDto + public async Task InitialSideChainAsync(int chainId, + Action> configureSmartContract = null) + { + var osBlockchainNodeContextService = + Application.ServiceProvider.GetRequiredService(); + var dto = new OsBlockchainNodeContextStartDto + { + ChainId = chainId, + ZeroSmartContract = typeof(BasicContractZero), + SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory + }; + + dto.InitializationSmartContracts.AddGenesisSmartContract( + ConsensusContractCode, + ConsensusSmartContractAddressNameProvider.Name, + new List { - ChainId = chainId, - ZeroSmartContract = typeof(BasicContractZero), - SmartContractRunnerCategory = SmartContractTestConstants.TestRunnerCategory - }; - - dto.InitializationSmartContracts.AddGenesisSmartContract( - ConsensusContractCode, - ConsensusSmartContractAddressNameProvider.Name, - new List() + new() { - new ContractInitializationMethodCall - { - MethodName = - nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), - Params = new InitialAElfConsensusContractInput {IsSideChain = true}.ToByteString() - } - }); - configureSmartContract?.Invoke(dto.InitializationSmartContracts); + MethodName = + nameof(AEDPoSContractContainer.AEDPoSContractStub.InitialAElfConsensusContract), + Params = new InitialAElfConsensusContractInput { IsSideChain = true }.ToByteString() + } + }); + configureSmartContract?.Invoke(dto.InitializationSmartContracts); - await osBlockchainNodeContextService.StartAsync(dto); - } + await osBlockchainNodeContextService.StartAsync(dto); + } - /// - /// Use randomized ECKeyPair. - /// - /// - public ContractTester(int chainId) - { - Application = - AbpApplicationFactory.Create(options => - { - options.UseAutofac(); - options.Services.Configure(o => { o.ChainId = chainId; }); - }); - Application.Initialize(); - } + /// + /// Same chain, different key pair. + /// + /// + /// + public ContractTester CreateNewContractTester(ECKeyPair keyPair) + { + return new ContractTester(Application, keyPair); + } - /// - /// Same chain, different key pair. - /// - /// - /// - public ContractTester CreateNewContractTester(ECKeyPair keyPair) - { - return new ContractTester(Application, keyPair); - } + /// + /// Same key pair, different chain. + /// + /// + /// + public ContractTester CreateNewContractTester(int chainId) + { + return new ContractTester(Application, chainId); + } - /// - /// Same key pair, different chain. - /// - /// - /// - public ContractTester CreateNewContractTester(int chainId) - { - return new ContractTester(Application, chainId); - } + // TODO: This can be deprecated after Tester reconstructed. + public T GetService() + { + return Application.ServiceProvider.GetService(); + } - // TODO: This can be deprecated after Tester reconstructed. - public T GetService() - { - return Application.ServiceProvider.GetService(); - } + public async Task GetPublicKeyAsync() + { + var accountService = Application.ServiceProvider.GetRequiredService(); + return await accountService.GetPublicKeyAsync(); + } - public async Task GetPublicKeyAsync() - { - var accountService = Application.ServiceProvider.GetRequiredService(); - return await accountService.GetPublicKeyAsync(); - } + public Address GetContractAddress(Hash name) + { + return AsyncHelper.RunSync(() => GetContractAddressAsync(name)); + } - public Address GetContractAddress(Hash name) - { - return AsyncHelper.RunSync(() => GetContractAddressAsync(name)); - } - - private async Task
GetContractAddressAsync(Hash name) - { - var smartContractAddressService = - Application.ServiceProvider.GetRequiredService(); - var blockChainService = Application.ServiceProvider.GetRequiredService(); - var chain = await blockChainService.GetChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - return name == Hash.Empty - ? smartContractAddressService.GetZeroSmartContractAddress() - : await smartContractAddressService.GetAddressByContractNameAsync(chainContext, name.ToStorageKey()); - } + private async Task
GetContractAddressAsync(Hash name) + { + var smartContractAddressService = + Application.ServiceProvider.GetRequiredService(); + var blockChainService = Application.ServiceProvider.GetRequiredService(); + var chain = await blockChainService.GetChainAsync(); + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + return name == Hash.Empty + ? smartContractAddressService.GetZeroSmartContractAddress() + : await smartContractAddressService.GetAddressByContractNameAsync(chainContext, name.ToStorageKey()); + } - public Address GetZeroContractAddress() - { - var smartContractAddressService = - Application.ServiceProvider.GetRequiredService(); - return smartContractAddressService.GetZeroSmartContractAddress(); - } + public Address GetZeroContractAddress() + { + var smartContractAddressService = + Application.ServiceProvider.GetRequiredService(); + return smartContractAddressService.GetZeroSmartContractAddress(); + } - public Address GetCallOwnerAddress() - { - return Address.FromPublicKey(KeyPair.PublicKey); - } + public Address GetCallOwnerAddress() + { + return Address.FromPublicKey(KeyPair.PublicKey); + } - public async Task GenerateTransactionAsync(Address contractAddress, string methodName, - IMessage input) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var refBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var tx = new Transaction - { - From = Address.FromPublicKey(KeyPair.PublicKey), - To = contractAddress, - MethodName = methodName, - Params = input.ToByteString(), - RefBlockNumber = refBlock.Height, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()) - }; - - var signature = CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, tx.GetHash().ToByteArray()); - tx.Signature = ByteString.CopyFrom(signature); - - return tx; - } + public async Task GenerateTransactionAsync(Address contractAddress, string methodName, + IMessage input) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var refBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var tx = new Transaction + { + From = Address.FromPublicKey(KeyPair.PublicKey), + To = contractAddress, + MethodName = methodName, + Params = input.ToByteString(), + RefBlockNumber = refBlock.Height, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()) + }; + + var signature = CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, tx.GetHash().ToByteArray()); + tx.Signature = ByteString.CopyFrom(signature); + + return tx; + } - /// - /// Generate a transaction and sign it by provided key pair. - /// - /// - /// - /// - /// - /// - public async Task GenerateTransactionAsync(Address contractAddress, string methodName, - ECKeyPair ecKeyPair, IMessage input) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var refBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var paramInfo = - input == null ? ByteString.Empty : input.ToByteString(); //Add input parameter is null situation - var tx = new Transaction - { - From = Address.FromPublicKey(ecKeyPair.PublicKey), - To = contractAddress, - MethodName = methodName, - Params = paramInfo, - RefBlockNumber = refBlock.Height, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()) - }; - - var signature = CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, tx.GetHash().ToByteArray()); - tx.Signature = ByteString.CopyFrom(signature); - - return tx; - } + /// + /// Generate a transaction and sign it by provided key pair. + /// + /// + /// + /// + /// + /// + public async Task GenerateTransactionAsync(Address contractAddress, string methodName, + ECKeyPair ecKeyPair, IMessage input) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var refBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var paramInfo = + input == null ? ByteString.Empty : input.ToByteString(); //Add input parameter is null situation + var tx = new Transaction + { + From = Address.FromPublicKey(ecKeyPair.PublicKey), + To = contractAddress, + MethodName = methodName, + Params = paramInfo, + RefBlockNumber = refBlock.Height, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()) + }; + + var signature = CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, tx.GetHash().ToByteArray()); + tx.Signature = ByteString.CopyFrom(signature); + + return tx; + } - /// - /// Mine a block with given normal txs and system txs. - /// Normal txs will use tx pool while system txs not. - /// - /// - /// - /// - public async Task MineAsync(List txs, Timestamp blockTime = null) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - return await MineAsync(txs, blockTime, preBlock.GetHash(), preBlock.Height); - } + /// + /// Mine a block with given normal txs and system txs. + /// Normal txs will use tx pool while system txs not. + /// + /// + /// + /// + public async Task MineAsync(List txs, Timestamp blockTime = null) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + return await MineAsync(txs, blockTime, preBlock.GetHash(), preBlock.Height); + } - /// - /// Mine a block with only system txs. - /// - /// - public async Task MineEmptyBlockAsync() - { - return await MineAsync(new List { }); - } + /// + /// Mine a block with only system txs. + /// + /// + public async Task MineEmptyBlockAsync() + { + return await MineAsync(new List()); + } - public async Task MineEmptyBlockAsync(Hash preBlockHash, long preBlockHeight) - { - return await MineAsync(new List { }, null, preBlockHash, preBlockHeight); - } - - private async Task MineAsync(List txs, Timestamp blockTime, Hash preBlockHash, - long preBlockHeight) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var miningService = Application.ServiceProvider.GetRequiredService(); - var blockAttachService = Application.ServiceProvider.GetRequiredService(); + public async Task MineEmptyBlockAsync(Hash preBlockHash, long preBlockHeight) + { + return await MineAsync(new List(), null, preBlockHash, preBlockHeight); + } - var executedBlockSet = await miningService.MineAsync(new RequestMiningDto - { - PreviousBlockHash = preBlockHash, - PreviousBlockHeight = preBlockHeight, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = int.MaxValue - }, txs, blockTime ?? DateTime.UtcNow.ToTimestamp()); - - var block = executedBlockSet.Block; - - await blockchainService.AddTransactionsAsync(txs); - await blockchainService.AddBlockAsync(block); - await blockAttachService.AttachBlockAsync(block); - - return executedBlockSet; - } + private async Task MineAsync(List txs, Timestamp blockTime, Hash preBlockHash, + long preBlockHeight) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var miningService = Application.ServiceProvider.GetRequiredService(); + var blockAttachService = Application.ServiceProvider.GetRequiredService(); - /// - /// Gets a specified transactions from their ids - /// - /// - /// - public async Task> GetTransactionsAsync(IEnumerable txs) + var executedBlockSet = await miningService.MineAsync(new RequestMiningDto { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - return await blockchainService.GetTransactionsAsync(txs); - } + PreviousBlockHash = preBlockHash, + PreviousBlockHeight = preBlockHeight, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, txs, blockTime ?? DateTime.UtcNow.ToTimestamp()); - /// - /// Generate a tx then package the new tx to a new block. - /// - /// - /// - /// - /// - /// - public async Task ExecuteContractWithMiningAsync(Address contractAddress, string methodName, - IMessage input, Timestamp blockTime = null) - { - var tx = await GenerateTransactionAsync(contractAddress, methodName, KeyPair, input); - var blockExecutedSet = await MineAsync(new List {tx}, blockTime); - var result = blockExecutedSet.TransactionResultMap[tx.GetHash()]; + var block = executedBlockSet.Block; - return result; - } + await blockchainService.AddTransactionsAsync(txs); + await blockchainService.AddBlockAsync(block); + await blockAttachService.AttachBlockAsync(block); - /// - /// Generate a tx then package the new tx to a new block. - /// - /// - /// - /// - /// - /// - public async Task<(BlockExecutedSet, Transaction)> ExecuteContractWithMiningReturnBlockAsync(Address contractAddress, - string methodName, IMessage input, ECKeyPair keyPair = null) - { - var usingKeyPair = keyPair ?? KeyPair; - var tx = await GenerateTransactionAsync(contractAddress, methodName, usingKeyPair, input); - return (await MineAsync(new List {tx}), tx); - } + return executedBlockSet; + } - /// - /// Using tx to call a method without mining. - /// The state database won't change. - /// - /// - /// - /// - /// - public async Task CallContractMethodAsync(Address contractAddress, string methodName, - IMessage input) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var transactionReadOnlyExecutionService = - Application.ServiceProvider.GetRequiredService(); - var tx = await GenerateTransactionAsync(contractAddress, methodName, input); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = preBlock.GetHash(), - BlockHeight = preBlock.Height - }, tx, DateTime.UtcNow.ToTimestamp()); + /// + /// Gets a specified transactions from their ids + /// + /// + /// + public async Task> GetTransactionsAsync(IEnumerable txs) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + return await blockchainService.GetTransactionsAsync(txs); + } - return transactionTrace.ReturnValue; - } + /// + /// Generate a tx then package the new tx to a new block. + /// + /// + /// + /// + /// + /// + public async Task ExecuteContractWithMiningAsync(Address contractAddress, string methodName, + IMessage input, Timestamp blockTime = null) + { + var tx = await GenerateTransactionAsync(contractAddress, methodName, KeyPair, input); + var blockExecutedSet = await MineAsync(new List { tx }, blockTime); + var result = blockExecutedSet.TransactionResultMap[tx.GetHash()]; - public async Task CallContractMethodAsync(Address contractAddress, string methodName, - IMessage input, DateTime dateTime) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var transactionReadOnlyExecutionService = - Application.ServiceProvider.GetRequiredService(); - var tx = await GenerateTransactionAsync(contractAddress, methodName, input); - var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); - var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = preBlock.GetHash(), - BlockHeight = preBlock.Height - }, tx, dateTime.ToTimestamp()); + return result; + } - return transactionTrace.ReturnValue; - } + /// + /// Generate a tx then package the new tx to a new block. + /// + /// + /// + /// + /// + /// + public async Task<(BlockExecutedSet, Transaction)> ExecuteContractWithMiningReturnBlockAsync( + Address contractAddress, + string methodName, IMessage input, ECKeyPair keyPair = null) + { + var usingKeyPair = keyPair ?? KeyPair; + var tx = await GenerateTransactionAsync(contractAddress, methodName, usingKeyPair, input); + return (await MineAsync(new List { tx }), tx); + } - public void SignTransaction(ref List transactions, ECKeyPair callerKeyPair) - { - foreach (var transaction in transactions) - { - var signature = - CryptoHelper.SignWithPrivateKey(callerKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - } - } + /// + /// Using tx to call a method without mining. + /// The state database won't change. + /// + /// + /// + /// + /// + public async Task CallContractMethodAsync(Address contractAddress, string methodName, + IMessage input) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var transactionReadOnlyExecutionService = + Application.ServiceProvider.GetRequiredService(); + var tx = await GenerateTransactionAsync(contractAddress, methodName, input); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext + { + BlockHash = preBlock.GetHash(), + BlockHeight = preBlock.Height + }, tx, DateTime.UtcNow.ToTimestamp()); + + return transactionTrace.ReturnValue; + } - public void SupplyTransactionParameters(ref List transactions) - { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var refBlock = AsyncHelper.RunSync(() => blockchainService.GetBestChainLastBlockHeaderAsync()); - foreach (var transaction in transactions) - { - transaction.RefBlockNumber = refBlock.Height; - transaction.RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()); - } - } + public async Task CallContractMethodAsync(Address contractAddress, string methodName, + IMessage input, DateTime dateTime) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var transactionReadOnlyExecutionService = + Application.ServiceProvider.GetRequiredService(); + var tx = await GenerateTransactionAsync(contractAddress, methodName, input); + var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); + var transactionTrace = await transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext + { + BlockHash = preBlock.GetHash(), + BlockHeight = preBlock.Height + }, tx, dateTime.ToTimestamp()); + + return transactionTrace.ReturnValue; + } - public async Task GetChainAsync() + public void SignTransaction(ref List transactions, ECKeyPair callerKeyPair) + { + foreach (var transaction in transactions) { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - return await blockchainService.GetChainAsync(); + var signature = + CryptoHelper.SignWithPrivateKey(callerKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); } + } - /// - /// Execute a block and add it to chain database. - /// - /// - /// - /// - public async Task ExecuteBlock(Block block, List txs) + public void SupplyTransactionParameters(ref List transactions) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var refBlock = AsyncHelper.RunSync(() => blockchainService.GetBestChainLastBlockHeaderAsync()); + foreach (var transaction in transactions) { - var blockchainService = Application.ServiceProvider.GetRequiredService(); - var transactionManager = Application.ServiceProvider.GetRequiredService(); - var blockAttachService = - Application.ServiceProvider.GetRequiredService(); - await transactionManager.AddTransactionsAsync(txs); - await blockchainService.AddBlockAsync(block); - await blockAttachService.AttachBlockAsync(block); + transaction.RefBlockNumber = refBlock.Height; + transaction.RefBlockPrefix = BlockHelper.GetRefBlockPrefix(refBlock.GetHash()); } + } - /// - /// Get the execution result of a tx by its tx id. - /// - /// - /// - public async Task GetTransactionResultAsync(Hash txId) - { - var transactionResultQueryService = - Application.ServiceProvider.GetRequiredService(); - return await transactionResultQueryService.GetTransactionResultAsync(txId); - } + public async Task GetChainAsync() + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + return await blockchainService.GetChainAsync(); + } - public Address GetAddress(ECKeyPair keyPair) - { - return Address.FromPublicKey(keyPair.PublicKey); - } + /// + /// Execute a block and add it to chain database. + /// + /// + /// + /// + public async Task ExecuteBlock(Block block, List txs) + { + var blockchainService = Application.ServiceProvider.GetRequiredService(); + var transactionManager = Application.ServiceProvider.GetRequiredService(); + var blockAttachService = + Application.ServiceProvider.GetRequiredService(); + await transactionManager.AddTransactionsAsync(txs); + await blockchainService.AddBlockAsync(block); + await blockAttachService.AttachBlockAsync(block); + } - /// - /// Zero Contract and Consensus Contract will deploy independently, thus this list won't contain this two contracts. - /// - /// - public Action> GetDefaultContractTypes(Address issuer, out long totalSupply, - out long dividend, out long balanceOfStarter, bool addDefaultPrivilegedProposer = false) - { - totalSupply = TokenTotalSupply; - dividend = InitialTreasuryAmount; - balanceOfStarter = InitialBalanceOfStarter; + /// + /// Get the execution result of a tx by its tx id. + /// + /// + /// + public async Task GetTransactionResultAsync(Hash txId) + { + var transactionResultQueryService = + Application.ServiceProvider.GetRequiredService(); + return await transactionResultQueryService.GetTransactionResultAsync(txId); + } - var tokenContractCallList = new List(); - tokenContractCallList.Add(nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput - { - Symbol = "ELF", - TokenName = "Native token", - TotalSupply = totalSupply, - Decimals = 8, - Issuer = issuer, - IsBurnable = true, - }); - tokenContractCallList.Add(nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - new SetPrimaryTokenSymbolInput {Symbol = "ELF"}); - tokenContractCallList.Add(nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput - { - Symbol = "ELF", - Amount = balanceOfStarter, - To = Address.FromPublicKey(KeyPair.PublicKey) - }); - tokenContractCallList.Add(nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), new Empty()); - var crossChainContractCallList = new List - { - { - nameof(CrossChainContractContainer.CrossChainContractStub.Initialize), - new CrossChain.InitializeInput {IsPrivilegePreserved = true} - } - }; + public Address GetAddress(ECKeyPair keyPair) + { + return Address.FromPublicKey(keyPair.PublicKey); + } - var parliamentContractCallList = new List(); - var parliamentContractInitializeInput = new Parliament.InitializeInput(); - if (addDefaultPrivilegedProposer) + /// + /// Zero Contract and Consensus Contract will deploy independently, thus this list won't contain this two contracts. + /// + /// + public Action> GetDefaultContractTypes(Address issuer, out long totalSupply, + out long dividend, out long balanceOfStarter, bool addDefaultPrivilegedProposer = false) + { + totalSupply = TokenTotalSupply; + dividend = InitialTreasuryAmount; + balanceOfStarter = InitialBalanceOfStarter; + + var tokenContractCallList = new List(); + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + { + Symbol = "ELF", + TokenName = "Native token", + TotalSupply = totalSupply, + Decimals = 8, + Issuer = issuer, + IsBurnable = true + }); + tokenContractCallList.Add(nameof(TokenContract.SetPrimaryTokenSymbol), + new SetPrimaryTokenSymbolInput { Symbol = "ELF" }); + tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + { + Symbol = "ELF", + Amount = balanceOfStarter, + To = Address.FromPublicKey(KeyPair.PublicKey) + }); + tokenContractCallList.Add(nameof(TokenContract.InitialCoefficients), new Empty()); + var crossChainContractCallList = new List + { { - parliamentContractInitializeInput.PrivilegedProposer = SampleAddress.AddressList[0]; + nameof(CrossChainContract.Initialize), + new InitializeInput { IsPrivilegePreserved = true } } - - parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), - parliamentContractInitializeInput); - return list => + }; + + var parliamentContractCallList = new List(); + var parliamentContractInitializeInput = new Parliament.InitializeInput(); + if (addDefaultPrivilegedProposer) + parliamentContractInitializeInput.PrivilegedProposer = SampleAddress.AddressList[0]; + + parliamentContractCallList.Add(nameof(ParliamentContractContainer.ParliamentContractStub.Initialize), + parliamentContractInitializeInput); + return list => + { + list.AddGenesisSmartContract(TokenContractCode, TokenSmartContractAddressNameProvider.Name, + tokenContractCallList); + list.AddGenesisSmartContract(ParliamentContractCode, ParliamentSmartContractAddressNameProvider.Name, + parliamentContractCallList); + list.AddGenesisSmartContract(CrossChainContractCode, CrossChainSmartContractAddressNameProvider.Name, + crossChainContractCallList); + list.AddGenesisSmartContract(ConfigurationContractCode, + ConfigurationSmartContractAddressNameProvider.Name, + new List()); + list.AddGenesisSmartContract(AssociationContractCode, AssociationSmartContractAddressNameProvider.Name); + list.AddGenesisSmartContract(ReferendumContractCode, ReferendumSmartContractAddressNameProvider.Name); + }; + } + + /// + /// System contract dto for side chain initialization. + /// + /// + public Action> GetSideChainSystemContract(Address issuer, int mainChainId, + string symbol, + out long totalSupply, + Address proposer, long parentChainHeightOfCreation = 1, Address parentChainTokenContractAddress = null) + { + totalSupply = TokenTotalSupply; + var nativeTokenInfo = new TokenInfo + { + Symbol = "ELF", + Decimals = 2, + Issuer = issuer, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = TokenTotalSupply, + IssueChainId = ChainHelper.ConvertBase58ToChainId("AELF") + }; + var chainOptions = Application.ServiceProvider.GetService>().Value; + var tokenInitializationCallList = new List(); + tokenInitializationCallList.Add( + nameof(TokenContract.Create), + new CreateInput { - list.AddGenesisSmartContract(TokenContractCode, TokenSmartContractAddressNameProvider.Name, - tokenContractCallList); - list.AddGenesisSmartContract(ParliamentContractCode, ParliamentSmartContractAddressNameProvider.Name, - parliamentContractCallList); - list.AddGenesisSmartContract(CrossChainContractCode, CrossChainSmartContractAddressNameProvider.Name, - crossChainContractCallList); - list.AddGenesisSmartContract(ConfigurationContractCode, - ConfigurationSmartContractAddressNameProvider.Name, - new List()); - list.AddGenesisSmartContract(AssociationContractCode, AssociationSmartContractAddressNameProvider.Name); - list.AddGenesisSmartContract(ReferendumContractCode, ReferendumSmartContractAddressNameProvider.Name); - }; - } + Decimals = nativeTokenInfo.Decimals, + IssueChainId = nativeTokenInfo.IssueChainId, + Issuer = nativeTokenInfo.Issuer, + IsBurnable = nativeTokenInfo.IsBurnable, + Symbol = nativeTokenInfo.Symbol, + TokenName = nativeTokenInfo.TokenName, + TotalSupply = nativeTokenInfo.TotalSupply + }); - /// - /// System contract dto for side chain initialization. - /// - /// - public Action> GetSideChainSystemContract(Address issuer, int mainChainId, - string symbol, - out long totalSupply, - Address proposer, long parentChainHeightOfCreation = 1, Address parentChainTokenContractAddress = null) - { - totalSupply = TokenTotalSupply; - var nativeTokenInfo = new TokenInfo + tokenInitializationCallList.Add( + nameof(TokenContract.Create), + new CreateInput { - Symbol = "ELF", Decimals = 2, - Issuer = issuer, IsBurnable = true, - TokenName = "elf token", - TotalSupply = TokenTotalSupply, - IssueChainId = ChainHelper.ConvertBase58ToChainId("AELF") - }; - var chainOptions = Application.ServiceProvider.GetService>().Value; - var tokenInitializationCallList = new List(); - tokenInitializationCallList.Add( - nameof(TokenContractContainer.TokenContractStub.Create), - new CreateInput - { - Decimals = nativeTokenInfo.Decimals, - IssueChainId = nativeTokenInfo.IssueChainId, - Issuer = nativeTokenInfo.Issuer, - IsBurnable = nativeTokenInfo.IsBurnable, - Symbol = nativeTokenInfo.Symbol, - TokenName = nativeTokenInfo.TokenName, - TotalSupply = nativeTokenInfo.TotalSupply - }); - - tokenInitializationCallList.Add( - nameof(TokenContractContainer.TokenContractStub.Create), - new CreateInput - { - Decimals = 2, - IsBurnable = true, - Issuer = Address.FromPublicKey(KeyPair.PublicKey), - TotalSupply = 1_000_000_000, - Symbol = symbol, - TokenName = "TEST", - IssueChainId = chainOptions.ChainId - } - ); + Issuer = Address.FromPublicKey(KeyPair.PublicKey), + TotalSupply = 1_000_000_000, + Symbol = symbol, + TokenName = "TEST", + IssueChainId = chainOptions.ChainId + } + ); - tokenInitializationCallList.Add(nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - new SetPrimaryTokenSymbolInput - { - Symbol = symbol - }); - // side chain creator should not be null - - // if(parentChainTokenContractAddress != null) - // tokenInitializationCallList.Add(nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), - // new InitializeFromParentChainInput - // { - // RegisteredOtherTokenContractAddresses = {[mainChainId] = parentChainTokenContractAddress} - // }); - tokenInitializationCallList.Add(nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), - new Empty()); - - var parliamentContractCallList = new List(); - var contractOptions = Application.ServiceProvider.GetService>().Value; - parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new Parliament.InitializeInput + tokenInitializationCallList.Add(nameof(TokenContract.SetPrimaryTokenSymbol), + new SetPrimaryTokenSymbolInput + { + Symbol = symbol + }); + // side chain creator should not be null + + // if(parentChainTokenContractAddress != null) + // tokenInitializationCallList.Add(nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), + // new InitializeFromParentChainInput + // { + // RegisteredOtherTokenContractAddresses = {[mainChainId] = parentChainTokenContractAddress} + // }); + tokenInitializationCallList.Add(nameof(TokenContract.InitialCoefficients), + new Empty()); + + var parliamentContractCallList = new List(); + var contractOptions = Application.ServiceProvider.GetService>().Value; + parliamentContractCallList.Add(nameof(ParliamentContractContainer.ParliamentContractStub.Initialize), + new Parliament.InitializeInput { PrivilegedProposer = proposer, ProposerAuthorityRequired = true }); - var crossChainContractCallList = new List(); - crossChainContractCallList.Add(nameof(CrossChainContractContainer.CrossChainContractStub.Initialize), - new CrossChain.InitializeInput - { - IsPrivilegePreserved = IsPrivilegePreserved, - ParentChainId = mainChainId, - CreationHeightOnParentChain = parentChainHeightOfCreation - }); - return list => + var crossChainContractCallList = new List(); + crossChainContractCallList.Add(nameof(CrossChainContract.Initialize), + new InitializeInput { - list.AddGenesisSmartContract(TokenContractCode, TokenSmartContractAddressNameProvider.Name, - tokenInitializationCallList); - list.AddGenesisSmartContract(ParliamentContractCode, - ParliamentSmartContractAddressNameProvider.Name, - parliamentContractCallList); - list.AddGenesisSmartContract(CrossChainContractCode, CrossChainSmartContractAddressNameProvider.Name, - crossChainContractCallList); - }; - } + IsPrivilegePreserved = IsPrivilegePreserved, + ParentChainId = mainChainId, + CreationHeightOnParentChain = parentChainHeightOfCreation + }); + return list => + { + list.AddGenesisSmartContract(TokenContractCode, TokenSmartContractAddressNameProvider.Name, + tokenInitializationCallList); + list.AddGenesisSmartContract(ParliamentContractCode, + ParliamentSmartContractAddressNameProvider.Name, + parliamentContractCallList); + list.AddGenesisSmartContract(CrossChainContractCode, CrossChainSmartContractAddressNameProvider.Name, + crossChainContractCallList); + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/GenesisSmartContractDtoExtensions.cs b/test/AElf.Contracts.TestBase/GenesisSmartContractDtoExtensions.cs index 278cc1e4c8..ef9fd51c1d 100644 --- a/test/AElf.Contracts.TestBase/GenesisSmartContractDtoExtensions.cs +++ b/test/AElf.Contracts.TestBase/GenesisSmartContractDtoExtensions.cs @@ -1,33 +1,28 @@ using System.Collections.Generic; -using AElf.Standards.ACS0; using AElf.Kernel.SmartContract.Application; using AElf.OS.Node.Application; using AElf.Types; -using Google.Protobuf; -namespace AElf.Contracts.TestBase +namespace AElf.Contracts.TestBase; + +public static class GenesisSmartContractDtoExtensions { - public static class GenesisSmartContractDtoExtensions + public static void AddGenesisSmartContract(this List genesisSmartContracts, + byte[] code, Hash name = null, + List contractInitializationMethodCallList = null) { - public static void AddGenesisSmartContract(this List genesisSmartContracts, - byte[] code, Hash name = null, - List contractInitializationMethodCallList = null) + var genesisSmartContractDto = new GenesisSmartContractDto { - var genesisSmartContractDto = new GenesisSmartContractDto - { - Code = code, - SystemSmartContractName = name, - ContractInitializationMethodCallList = new List() - }; - genesisSmartContracts.Add(genesisSmartContractDto); + Code = code, + SystemSmartContractName = name, + ContractInitializationMethodCallList = new List() + }; + genesisSmartContracts.Add(genesisSmartContractDto); - if (contractInitializationMethodCallList == null) - return; - genesisSmartContractDto.ContractInitializationMethodCallList = new List(); - foreach (var contractInitializationMethodCall in contractInitializationMethodCallList) - { - genesisSmartContractDto.AddGenesisTransactionMethodCall(contractInitializationMethodCall); - } - } + if (contractInitializationMethodCallList == null) + return; + genesisSmartContractDto.ContractInitializationMethodCallList = new List(); + foreach (var contractInitializationMethodCall in contractInitializationMethodCallList) + genesisSmartContractDto.AddGenesisTransactionMethodCall(contractInitializationMethodCall); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/SampleECKeyPairs.cs b/test/AElf.Contracts.TestBase/SampleECKeyPairs.cs index e2825c7ae7..b0759c4348 100644 --- a/test/AElf.Contracts.TestBase/SampleECKeyPairs.cs +++ b/test/AElf.Contracts.TestBase/SampleECKeyPairs.cs @@ -5,126 +5,125 @@ using AElf.Cryptography; using AElf.Cryptography.ECDSA; -namespace AElf.Contracts.TestBase +namespace AElf.Contracts.TestBase; + +[SuppressMessage("ReSharper", "InconsistentNaming")] +public static class SampleECKeyPairs { - [SuppressMessage("ReSharper", "InconsistentNaming")] - public static class SampleECKeyPairs - { - static SampleECKeyPairs() - { - KeyPairs = new ReadOnlyCollection( - _keys.Select(x => - { - var privateKeyHex = x.Split(",").First(); - var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); - return CryptoHelper.FromPrivateKey(privateKey); - }).ToList()); - } + public static IReadOnlyList KeyPairs; - public static IReadOnlyList KeyPairs; + private static readonly string[] _keys = + { + "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", + "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", + "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", + "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", + "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", + "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", + "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", + "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", + "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", + "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", + "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", + "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", + "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", + "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", + "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", + "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", + "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", + "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", + "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", + "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", + "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", + "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", + "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", + "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", + "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", + "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", + "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", + "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", + "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", + "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", + "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", + "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", + "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", + "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", + "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", + "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", + "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", + "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", + "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", + "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", + "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", + "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", + "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", + "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", + "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", + "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", + "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", + "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", + "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", + "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", + "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", + "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", + "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", + "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", + "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", + "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", + "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", + "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", + "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", + "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", + "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", + "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", + "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", + "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", + "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", + "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", + "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", + "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", + "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", + "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", + "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", + "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", + "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", + "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", + "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", + "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", + "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", + "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", + "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", + "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", + "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", + "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", + "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", + "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", + "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", + "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", + "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", + "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", + "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", + "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", + "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", + "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", + "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", + "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", + "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", + "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", + "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", + "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", + "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", + "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1" + }; - private static readonly string[] _keys = - { - "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f,042dc50fd7d211f16bf4ad870f7790d4f9d98170f3712038c45830947f7d96c691ef2d1ab4880eeeeafb63ab77571be6cbe6bed89d5f89844b0fb095a7015713c8", - "60e244471c7bbd3439c026477d0264c1d704111545aa459a86bdddb5e514d6d1,04c683806f919e58f2e374fcba44e0fa36629bf438407b82c1713b0ebd9b6b8185f7df52c2d65bb0f36e8f648dd8f9e9864340c1d718e1faf0e4a5b4821f4b2272", - "e564821857a4a4d660be92f29c61c939f4f3c94e9107da7246eaf6d6ebc30080,0438d5486a6ed5bf49f19c17d8cec834f10b86c9c6d3e6f9567b2e55f135bcd6296306e203306555ac8a110e2c89fbc7b71c2208d2e34eb8f077de1b07321abede", - "4a904e016609e93962554945a369944f4b0b33869193da0c69638794cf2a1701,046b53de5ce0b577d25d8625b0403c29ce594f17ebbe3d2720cf7bb1362d1211da44e8a29f64dd5fe68fa55fd67870d253e6bc0303e388970eb6180d92faf8c907", - "b220433fb90578929f157bbe378363ba4d6ec718dc12826b6243e8deaf956617,0480baa7fc508b61da77b804e4ec5ab069934b48939cb9c63127d6edfcf682e2475ea185485d3e9cba614645d4350ce1828d4aa49bf63c05ddbd9a2a3040afe4a8", - "439eaa81279be5d3e16af4baa091c315f45a374cd9dadd9dad80ea067586179c,0433ded681e9009d609be0588441ce2af88c910d5200351a2cd8b94cc501bc77313fc903c723fe31c67feea051d6d9415c07ebd509756d5233e6bd7e0bd4c9702c", - "db9d8d5c7e79651a5d145270128b3ed2ac5c8e65590942eaed6d799b0ec9eaf7,04797a2799e1d81ed200440f2fff40b0546a1bf082e125d3f256e8223bd2ac7ddcc5f2222af4311db8f79f0f7453ccb12d7a8fee31bd8af8fb9f785929543e35f2", - "5cb3d56e39f69c821311e1f50fa79b2ee33409ce8f1db257634fc939178300cc,04a57a55c76fb339d421eccbb080ff664dabc743d075d3be669ca7be1636d28956af2c2975cd05a217a984d362aa3ee06242f22beee69b7641dae5d2aa2e6551c3", - "fc1fcc425b0d5d950ef9db964df94a77d4cbe937d0cea970a3b3ea574247ea44,04672b9dadf848cd453af613d08ebaba5e38bbbe9d7ea7c894d75f9a948d0c5a6c4012c3e8cc2a29df16a254080959d53451a30d780863c5b1649ab68773a20192", - "801bb68dea46586b613f09cd8c6ea95db59a41f51782b0bc7b386277db06bdc9,04a2ecc52abb8bea30f993f6ba0148181d38ffe2a1c9cb1fd4144108ae113fde11f8c8ff8f9e044c85d44b4d3d1887649ad7bfc81955bd53effdac1dec7ba82b2f", - "daa7fb43e91bfc2a2eb2032bad2a27d39c4232c72428d2076b7739acbb26c76d,04e800cdef4e06aefebd41d7fb824832af102f3569d3d86acee528c6469215f722f4cc36d15def8744482333d55a50db82a910b0dd740ef59766ffc093d51265fb", - "d7dd523709b12f0f604886920560a0a566375031dbfff163deb10470942f6687,040d3d66f1d2051efff947796b2ce5676065072f4c6fdea4a162ea037f08544ff8a154b22c15edd6335de6fb5bb582c23275b4bd0bff325b3137af3001df1e52d8", - "1997d4a7a118ecce60a74c501af2339a0bb13c6f2b54a4e3b43ac7274da9e4c0,049607759582160ee7bc08e8047c21a0f0aa0bfd3ec9e5e275978435809c574e0dd5de90bb5777a3d725ca352008d43e3a9481e1656d7469f780a855cdb9b36467", - "0b408aaf6adff7621e30132d702deb709dc80557c6dfaed7aee5dc17ac48209a,04ea3f83d92151d806225169f9d9f1a5b9df20c7bcb1605ae5c041812e715f029df5eff44b3abcd9375644b0aabef6888d8503d82428be85641240c82f202edb80", - "881a7f6a70eb618bff9c958cb04c0fb144424254fe26025bf6f73875d9d438fe,04de2782cd791cbdb84924449b82564cedf0e663db39d9e0b311e811d527efebce59520bfd9acda383093889a6e13c19bfc6b437efa369755f358a33d670603691", - "0bc13e583939c36de7af0d3e641d9a3d4e46ede22749634006b9cef5a921d098,041eb6251260cb14839ccc63043f02084e54206eb24ab647c70e21e1386232cb08260e25830ce699ca86220727c722279fcb23a8bb468874713ba357a88426cffc", - "8d729c6fdb4cca80963695b1ca82ca77960a9fb8af3b104061b304868eabd57a,04dc139191eae6d8a71f1132651e005d4754a4c8905cd2ded2edc00d28a4edccc35dc242f5e77fee2bb517ed680ca5fd083c47336e7d3ea0e0bb8d5db99ecb55bb", - "1c459228f086f04c371f2fdeb954760c6b48bdbe2ddc9c361431c6ec0e4aa513,0405d65483be18faed0c4d0cb55ebe2955f2cce9e80c46258843b057abc8c6ead063c5ecd00d2517da0e76a379f0b33d3bfb3e143483e26c389d9d9d9f1a445886", - "75d0fb677358f6bf3f443fde85ec463e268cb88e8e3f6c3180efc9174a367d38,048f9af568bf89eabfb6e61f8b70c99f52e256714c5d9a23f6101a6c3055e3c4bd5b5c255745e5176b0ab7137a3766724d3674d94332b086d720997b93f5186308", - "9f05f19914aabeaea045322dc1187fae1541d0cca8d9ce9e716dbcd80f753952,0478009a3e88c1d9187cd8cd92e08b0985007f27c07c058551ea2f14e91c9d085414ea5e005afc299181f5ae4d9f29d66ab9dcad4615a7086f42b461833311c487", - "f4caad86db14adf54a37966b254da6c5aee45c2c460f5d1aa72063d460a248c1,0462a75840a0ff3c2b8390bb8c93c3e7d742777f55905952af5373c5de5eac1b02d773e1f7de0b8f7bdd7b4f486d14cbea1500f8ff868fb08eb382d0c468769c0e", - "573b67fc4e86743260b34eb24d9f7abec544b0ca736373d0728271efbc75e521,043a03397458a8da3dd0f729c847505a900aa48745c96461bd10a54381c387b7749ec27694cd3de313a65f9b24266f88cffc47387f14e527d5395cbf72976f8542", - "d4686481e1899aaa57a994049649a74990c64e528a0d3ff7aa8e0f232c2c2885,04d864beafca1627d41f93bfecd5e5b6217d0855bfba271ca6ae1d1bb8fa9e80db160cfa44ac97ddb31bff658cded1bf903cc1cb906a4fc86a1753067ced6d8eb2", - "8f00763737dc35d1fa98f900f5d8e0ec524e8929a116022638ee69f4bc9945dd,04bff0e985a53b5230ec0ed6c4d43b09f13236600f88a012db80f4c239cf7d6cd429da0b446e4cc8ea8ee57817706d745d7540126165a46c7629cab2792ce30d9c", - "a01550397a5c8ab630b62205e5f3e9e5f787b9e195ac9311056481bbe35a38ff,04abeee69bdb8247bb3cba7173e39c29067891264e8802c3dd4a27a25afeb43c67b45dfd1a11b69c660e32f2e2f06dcae66f979265bd89e857c5dba4e2c590981d", - "abbfcad8a9408b316d83eb39ec3a0f7fc8d89439b14f84ceb604622c6d02e883,047c248e971bc9d6676b775fac7a44f41420feb962837b45612c7002fad505ca68ce65e6964f689836af25ce389c4c21f05441979fb59eec0576dc62f67e0910af", - "7c4724966a5f36e4f353fc8e35590b71959a4f5c03c2ce4ae029f069ee74d520,042b74866bf005ce83fcd7f67004a910f527c9a876658b6f731d8c4febddb56d16319bbc8587e8a7a972c52da37ceaca769dc7fc5453b67262604263229a1a3037", - "1404412fb9ce3e215dbdad430e8198cd28cc64c36f6d2b06ff0ceb8954e8991a,0488fbbac4184e40a2d3aec7ebf3b5728eb8f7857f82bdc5f947595b4ad4f17b12602d0dd0a2ff0b64e4c35d447c08895c74b2e3df6bcf388621b216f9e53765a4", - "bfd0645ed9a54300fa25d824143f8902d5a18e0827b5f8c07018ebf76f9f754a,04259d63b897651fc2f35f08a0ee9371593ab7f7042d4100bd489bd6d3727301138f6625f610c178844a0c12df19c77e29c172b9a2125762a5a116b48823f2cbe7", - "8472ccfe96d0679e1c8fe4c5b813d0ef3cd5eb19fc02b4b75c57ebabc09e51dc,04e3b27f14d7bf69d5261341e062de6bacc306b14678e63d1477662787351c4df7376a942709d3ac11afc9f78f70e586386d10f28c62a6857159d6167c9faacf66", - "fafad2a1f6ed2a6e32efb1b2c66be60b7cd5b5f10fcc1ab3801ce92efb21185e,04025b18acd9cae756804f2f71e6b8530e06135e27c740adf2eeb961c06d72a67097d20822fc44cc8f2e9702539bdd4f1638ba347e322713355ad9684b7ff3b6d0", - "3bb099eecf884d43ac6eff09e49fd6b02e4f899a87284e2de6357621a4ba475c,0429b847554b9f73d48ca72af9381d677972ebcb0abc30283efce4311c4b9820acb5301b506d0df69d705719cc2eb69353c3b9fa4db4a564da7a502cb8ab6e6b9c", - "0a8684757504f5c9c3665e8a163268bab40fff7f964eabe2b376f9e7023a0628,043b3a4abf9322e27622614e3f5271c822d859979ac69c24eb324816e8b59af8238cb2b8e31db518fc4621e2f9d6aa7bc336ae0be9990d0f986496d6f5e3ca9c18", - "a4ec7bd4de41d15936cb6d8a5f726c855451c91254082b18af6b469224f233e9,04640c2243d55fdebb649babfe7808e583ae98c1acdcf01089a7276887100c94c97ea32b0020f484ab286cfaa3a818502ad48fdde2f869a3535159426785425f1f", - "23cd03104aa30154ac4645a15721c34975bd6524e204ed55a26c4125f621ee2f,041074e0c8ea9f5ea4d0cc21238c1e09d8b3f9f47ad2e5474c84276368221bc5e3f1d0953a9b3d922e706e05f6d6c4f0fd502fa658e307fb68915be4569ff7ae4f", - "966ffa272cb70948c8c0a11929c393509dda7813b813e67b622dd2304b17f254,04de1d8c2faabf09e73fd0204d65158aea614978a5935b5eaa27c6930bb7c7c42b447ca2a90e4faf5f74f3fe15b6af620652150f43345ab4aa7234e9d76e869291", - "6a1ac54b87caa2b223ba35d132adfc341d0de4c1c48f4044890b9f852fdbfd76,046a3071e064d6d5f08b03181a4c6a94593073345d2bedb3bae38a7171e5b1ab36ae634d4f47d8a4040c1dd943112c869d8f17faf8673f59370bddf1bbb132105f", - "f0b1285150f917e28e0ee462cf9f1c59647d9c1364eb73b64918fe6f051af53c,048361e23c6b93fe50356d66c700525cc9e954d6c1a2181930bb09b383fc45219a10c6f8cf9a0dde12d4040dedb14d1eca3e03069d405f09fba5bedd535ff5bcde", - "17a84629998cd5f0dc00d4176fb68681094fb7567ee3fbccfcfcc7de9d1b5ed0,0402d587b9ee9f20593de58c513cdce842296f8bf4620641656c4f9d46de34fecb807951b8dcd99e204d6e1f31731550456961d08b00c19a6ad93e632e97ff975d", - "3e3f6c693b9beec15120190e56f0e8a8ee38e8938301fb7286064dc9caf143fb,04f6ac097ce14905338477a19e1aec8043dcb37c94543932b124de7ac75baf8bfbcc02cfa50f715c86858fd8aadc81c48324de925ee9f079f477dfed3d0c3afceb", - "834b12c59e0d9d7ca4ef6187f0685d51a0bfbfd176d9d3d1c84b8eb1bdd1602a,047d06bf13ec716bc3caed680c896334fd72452c229947444cb0bb989f5c1e46ae3a1203cd308dfe18c64849f7ea9c62c2065e811725a91cbb73216844c6f666c3", - "a1b4cd5be383d68e43c4d0c4a4197a09e71ea3d7e93bf3bde3d167a5a305a7bb,04cf8a8b19956c6736a9acf9dacdd5ba04e46b37a861e640c1b91a20eb156cfe94f61b6bbdff5f5b1d30d7ae41c28572e6525864cd91122590b9a061c4f65ee47b", - "2fb43b013f732cf1245b865287378d19069cdd1cd7f24b604d8ce2be9aa71bda,04a41f460f5657793ffe4c2ece28fe8bbd1dd6e1a5837ea7a3792c9c506ab29e1f35891209c71cd8b79f519704fb3ca5fe370dc911679477826632715f23ca6adc", - "ea3ff232d8b04e5885f7438b2267da514132c1362d6c837172076877c88342f3,04c4ae4fa18511dd9bc9888a980d09e9dbde12dafc082844980ef1471afe409f0442a4874b5e835b47d3178be5010aadfff7590ae473f58b006031556fa2f6277e", - "149f4cd9972696320b660918f1d7f4ed41170ab974689f7b06f8f2647cb6a93c,04b18b07cf6c22d467d29e17ea5cffca45eca4dfcb59303e5e11788967fdf72286e4cce333883fa48c5d45f74ff3d3dea0ead073e4a08fe96430356c36a793f65f", - "e50ddad6700a597fc0d984b03c994859ee96750761214d8064e6b34b213ae5fe,0474c84a2e2c9d4eb9b956a2ac1ae38f896982b199e68f0d633de1bf118766d40c08cb1b59d4f48f62287a39daa58d05ad3b3fb1578d47d5f1749f13366e569e67", - "3a7b93bd1df3cbffc5ad6dc10e07b88051a70492cdfe0f6d0013b63478c494e2,04f6a8cf64346052aef742845c0869e8c5d796007367602f378ea6933b89711e37da5f1b431273fe38189c54960847ba860a068dcfd03f333513ca84c3abd662e4", - "616889a7582bf17aae74a12e6ef1b1594d30ee22d4d3aae08464f118c9256ea6,0468db2a3f3f78c382a6febfc51549ea6f21595a622f8c7720d86bf5e590aa465f575ab3a59ed81e6974c6dd53cfc6ac929cdcb70c8fc0404e41e15c9ca96f7b2b", - "0505d50b741841d0f880f8a8a832d337dfb2b60c557ae8d6aa25b8abdcf87ba9,043ec726c6ef6465bbec193db8471d46392b54d872120ee5e741959d8dfee34247ddfb512a37c5b57d273f860c76dbc109ec9f080d0e706927e39ccd6e8c45706f", - "9ac1900b3c47fa61e8e4a97d29d3aa868849c68d6be0412cf7005cddad787607,0415bda4fd1a5c478a41399ac34082de7b878388b74ed2512f3bcafa56547ed069248d0d1023986604f82f3ce7caf5f6caf11138ba72077ee58fd8038237f7e8f3", - "000a2a0fa92e5c915222adec1c262ab48ece45e5c755d350accf64508247e60e,041ee8a733b81693d17393a231342cd0a4c0ee593ec99d6cac588e347a192b557ece2e5481cbd5853dcbdfd6436720909fe60cc24b0cbb0af8fcce77c3792aba6e", - "f0c2b2c819afd1f8d3343022f4a85b23bf851bedae3fc88884523aa72cb20669,0484cbf10c8e01cefae34045ed9ea606ab2510a8f27c5d542b27452130f95c5516b3622386227a8908b169a5f8da46a1f8beaed3f65214886a864922b286efa943", - "f15d4ab5613789867df1d54e1f0f2b3d8afae79a814b47846183712fa9ead41d,04c7b199aaf6b6757ef2dfc3c5f5b3834571b3a0b7b8dcfe49fc971ce2fad4b2363420e3bf9ce417245b17ec4bea731250978858c54f0139ed63d90829afcdb005", - "1a49446849cc0523818b0180335fc1b90d3028799c5ebbc215183001e00c93af,04bfbf9d6deaa3d731d45caa7f8a0ae7bad616fe52c2b833d7fed036a06283db309af8efe0a30588b572d0fd5406beb56b98e8e1059519b17f11180f5a6ec171d0", - "93651bab9e6b9ca4e02c0cc560345a5c9ba03fff270447e735a9e27fd6acdf55,04bd44bace7c09c83885fc9f60da1092991ea71a9e930f10c58741ae8a76b8d93519ddb81b101b1da22ef821e634a694547ef32fb1db719996b5303154c266db1f", - "2c71421e2c4791e819bdce584716ea7f7a5256066a1e4694f3248e56df052504,04da30f5a119d187f2a38fd327359c0282b1d60ce1b9a39e1c6bb956c7b77b36146a41d89d5192218d34d9b28838bae139c7ae6471f7a09c30305001ef2702dad9", - "75830c441fb5c465a1df706618930ee0a997b5551b4cf8b90eff51756f615cae,04ac8d60fd525abcaa01fdcff50054a7c0044f55cf4860adc0db28970d4aca8102f7b83ed688601e6d8a1dd5162a77a6a311bd9a6d96823c563ea0dcbed537aa20", - "2b256d8d234d467608f4131aff67f2785142d8a9cd7e618e06628e2efb0dc76b,0493d9ea0c6fdc648eee65c86f072d8a2146172ff84f2b91bac12cd145329b633275f17c56442fc978162a63be901db1640534fe3a48a9287ded4bfdbf632f1a08", - "e46bb96380ca90dae0eba15c60261395147b4c9c38bdee3902aec0f69de15796,0435711be6a81b1a8988b1e9e7b23dbbe68521d5aae49d72a51481effac03c35c148583a111af2ed2efc6174474abfb5a6c2a92ffa1e21df4a8cb4cbb3c0f90d3c", - "cdc2911679811e6c516535a427ba5e147feffeb4bb3343fc34994aa42896d284,04927c8b4d05bcba753dc56c552625c6940ae842a0fac19ba881e08563435ca1da4364b057451122242068103b24363ad5ac2de9104cb1e97b1920a2493443c5ff", - "2e42fc017cf6ee2c4293825bfa70c2f9c80a245701f1c52cfbd15d133b71131d,041601b1d27913cac92a297ac6a8dbd8f131f0bd50e752b5ac70e6ffc3aa6900eb39a0b4f4623fb059fbfde5fa6655aa8838e874a72bff4e4dd69ad97e444a6583", - "3f9207cf5bc47c7aa7502074f819857c99c1d6225aeaa52b4e5dc18775150076,046bae25d8f8da62ee4a6ef38d465a9e8eb1800839bc80cc516dbf6c937d4f1a7dcc4d3d0a5a5f355a91eac0573f52169e9e933a95ab825c8d3747be0a0205e066", - "cb07e3f6add8a24b4ac83fa1d44ba582e12977ae851bbd6b119d51f717194842,04c8308d2e5210a76e980833f58256d6b574b100dbe05971155209d25ef94241f4422208d53a443306bdbc4fc5b111617b358bf7f6e0b0d878f5020b40eeb73885", - "f70a5a488dcddc73265ad910719b1acf06584854e14e81f4740f52630df3aec2,0422eb5c4ff62eb04ffa2ac1b1cecc9dbced7e56dd562890bd2331af1e1375fe8703952eb698a0e50387baa0b7dbb221acff0d8b13e19786778df58f25bbba308c", - "660c8b6bc7e3de69539bca03cfc74cfb40e1e1eef25c3ea2bcd8e6ede4467095,04130d2b0be22c9e0492023ef17ee6a56795ad241c7b8ea57fa1f657d5ec549ce0366a62845545802b57828c3224d2d53bb679bea3eb34c9c2398c66d0108f6f71", - "de92ff41ed5c1c7d6e069719bb3a104d2a15085e032b7b47fda929a7dde917b7,04ad0cb80e645ff904493fb4960bcbc9bd137f0993674cfeb364de7c79aef03b4476afe634626335ed5293ed2239291ef52a10a02ac958c321f6a9552b228a720e", - "598c9bc334a1b11c995fd3ded13839af973a8bf1f8ee67c19ef22896f6453dcb,04fe582b70ea91f518140766cf260174eecab01048b504043b15d989d10e6186560e3f4e7f0ad7ce1df77b1a4ddf0167356184ec29fcb3089865ffdc939c68c45c", - "980e98cb95e0f68698b46d18d8cf17700023021ff59860199db3dece0dcec7e7,04b6982f0bb9bfd7557d31241ae4c1b6a6296a72760cab409c5e61f1b8623a4cbaebca2f7ec663ab0302c460a722c9ae227a6f215dcc187434231e8a9897b15ea6", - "36d62db0e890eb3ad60fcce3be10a2fe53576f3f77c53623a8571a377776af39,04a3e6b3aa2382c3d2ee9424446da8f1e741d1ac624216f41077577af52f891e984707a0c97fce5f04b16d27c76f522a6bb8cbca4fd7df594201d063de44f3fe22", - "e1f2eab0a857586a9261af9c0600c52a09b1ccb075ca7086f2647b4291cf2d5f,042e35e9cf8af064014958d33892e96ee1288bc5757fb03fc6bd9750ecf71dddb4b60314f57005492228389220663334510b3e594a685f9fd5db12124b951500b7", - "9f18b3961f40ec79912c36b42d6686d7dd0fbc40fe119aa138dae6480838c99b,048c9c629164524e93c9e2486d9fc735e99916b284befc3cd2bb44e5bcb6196a60797bf4bd00ce31ba736d2f4e7e9c41eb77960e8571d4f7a7b5960e350bf3d788", - "6acde707a0e8bfae703c6c8edb78e5bb531f21348040f107432affb2ff7058b7,04780ec926f537168b78bab39506e21f6e2fa85cffb26d68c59f2c79b24fccf16ace157ef57718b98ca178d99ffc5bdfc01ef681a6e59857bfe7f8941bdfa6dfcd", - "bfe176e154c77d3e66655cc10072cf0fb73d84f5c8d0f09efa2d7974189aaf74,04f8ff08a3d07acdd6c953c52c8bdbc8926db7d2d33cb14c1e64a7467bb88448467985d2ff236003070b379f28e2e6e1ae9885cd53d103c3b409b7ae5ce6ed990d", - "8bec552f56417618be4e3a47cb8f4ff36fb7c6b02349db5025eebe0c4cb59623,04b6ee3d204ba6b2ab755aafd0a85acd7e0caacc1303367d7296a6f0d513885183443196b11e603685adfbf711b9abc98fa38c31a2c0abf9d7c0de937a92ae9cde", - "dbe6bf93288e23c30fb286cb89e5dd20334b906cd7db8f8347f8bf915ef42b84,0446b03b50557b7735762fd9cebfb8af38074e974c1ddd55816c05ff67702a519d5bc9ba70000339cdc8745b7712745ba117c4ed5a90df64ea9ed3d40c0db48925", - "989ca26be092deaaef045b713db5637653ba80acc7cd20622bfe72c1bab390a1,043f27317ebf6538b28a958384ed6ebd0fab4fe8fc59e8336ddab1d7309505e99945f4a772e3734c21ec183e36c989268d84b5e98fcea05a0bfbaa99f4ae568847", - "cd607266085216d61ffb07c762d2c6ef84b55c0b3e9a1dd84e91526c19836c58,04f11a30b2d5081f8ada4145cd26dedb776dd66e5f95d3356de6637294fc9c75cbbbf729c6733fbc5f8da1daca6f5cbcf7ce3b7138946afce8d88b936c7c1e8190", - "25f24e26221b481c56d4fd7a377a3523d9bf6eefe215f71f8bb611f3e378011a,049594c6ebf7549f636140f5acfcfcf2253639423f207aaa320d97cf6b4e260d39988ff7d4c497e3e2564fc8eaf0ddf921ab8e09fe254966eef643ef88756a4645", - "620052aabd0c581398dfd350fb1eb30c9010e2fb1a8b12a19273e138a1261307,04e25ba1d51ce044d73ec3b551bc6c55e29e15aba77d13c1728a160ea21a4b36a30bd912cb272e892209f229562fdd07d64d0db9c8dbc37b41c2dd31a6f6d59ec2", - "fdef9e5d1bc040678610a47806f042ef1fbd6091f43d5df5a295cb1b347f774b,041bac343d2da175f5ab5b921fee26cc18b664b22e8b59bb86628eb5ec5ec13d3fe2f376b928312a1f259e72b976588a95d0a6880d1540e6517f1c3d195a82474e", - "3d6161e7e9fe2cf4d8c2e9a317dd42089be1544a98a8365199b85f12a99f519c,04fbdb482b5b725621e388e4cac64df258596c476fd6e1de4f531c345ddd810411dbfe824d9ab4cf10f77c03d2c50e41ec58991bc147e04d7ed6da20140468144a", - "4ee0222ab3cca3da0437099f550e6548926f00ecc110d2b31884dbe763147916,04cae506447c014a6525b230a2044fd34be1959ba6590fa27cb150507d9d0e62ed13bbaf8d9ae1af3f33bc7371d8a926fe4d9b543d061454ae7460268636799446", - "5911809521ef86959e7f0475cc18b9218b44c4b4deee9ed5a4e56928c4ea00c6,042f93cbc5bfe374ed0baff2df7a3d43bef1e75bece54041cd6b7ffdfe9e271a608e06b5f10292efc9ea4dc2528d84fe7a6eb2cb5d3bcffcfb68b635e52877b5e6", - "c33d1a059fd3a3bca52475f6e9289466ca1415ca89b2666f32ceacd0402836f7,04db0003e44bebf67a5ee9016e8fcc76a42692c3d83a567698166c5b2130728453c1662f5ca56b0ca74e6ffd9c4882dca445d14b0e67835ffae9799093ec7dbd95", - "032cc911d98480c15b452e707699df45a3ecb46765acba047f11ca9afc4feedc,04c7e849976ed3beeaad8019e0d34bb87020861678433b7fce089cde54058dfe612c879bf1dd4cba3d23a221dc4f9083907ec70de9db976de26deaedb107360d47", - "2c8bebedd29e277840f4c725d5b4ee9ea9bf0d86984664e39da87ce1dfc87ab7,04d875c3cec9b4c1482103760585eecd4b2b7886bb8a4cf258acb9cd43e9f6c93fce3a6236b5ae1d8c8e7b726652eea70eeddea2f058de8e4bbf512ea52282ed26", - "4ce7295892ce8bd20c2ad69e7b628ed68fce2a70b363b006b93e69b6ce54bd5d,0489837b96271cb9611add4c48250aba5e381bbade2e2e5abd9ef849507197dc2d621e4b6fd7dd2d34565d424afd47d5eeeab8d21e979e2d473826eb29aec6a361", - "f08c5dc229ab21fdae3e13fdb2457c90909c66d3251406e491a8cd2b7a29d5c9,04399516c440d7d1b9fb1a1bfdaccb23f7390c26406ce1c85671cb2ddd8a6084475ba7cd8aed72bc7fe137f13e22a79ac83685bf0fc9af7848b0c07e2d0dbe0679", - "df8484b1b74fc892afec0298e342f72261d7856d40028398fdc33020d1b26296,04bd91f2ae18326ffdd964298c3713a791e2657465e2bdbb5df74a8c0dff7095d5e6d62b2fac1ba4cd60a0ad1c05b58a4069ef710c59e5635f06ea6ff183271e8f", - "6ddb9a0ad903fbcd5a81e6f8d611a7f9746f1233f83e20193ff1346634811143,042d31d536ae37ce1be4eb65ab70d00dee26af9b16fedffa46049cc8dc055cff68428be667ae953966246b5061dd4082ec8cd449cf317e4258952b88fb4675831a", - "8362437458ca9994390e6f2ccbc77f0d40e52ee0a43e7f8a55f49f29645a9b6a,041500409dd9a32b91587e1a4f0de45b386ffbe86034d2c8d49d48f1f082b99d235f2620188ddd90a9c86f020309a8676c905dbba40d9e4e224dfe56066f79a2dd", - "e08258ad561675102a902e2605b16e6a1aaac4d9ac908a89be3e25994b706d87,049914b0b3ecb23c281f626fe511d8346f9c42d9fcb811d10cc3f39cdbba4d029d121d916f6fee2a265d69e7af259c6ab284be2c7d794a065ed72ff301e7e342ab", - "10b80e94d0abc3e00886f2eb711f58b7af26e3fa4acb119948608318fbf0e912,042489c2882a447a339509b2cbade74e9b7b21121735190f7263d50a2e906690fa78eafda46bf341552d4b820810a734eca7b296c03e28dbcde2dc88cda9599bfd", - "3a7fb3d353756276c75684f7ce240d61c071c691814685dae5a18ea067f40aab,04498def80eac2ddd47ab0e985a104200dd72cc46528e291195066e3ef8ccf456dd5f254ff78bf2c259e9583a99c9778edf883be73afca6fbb0024671cdec8b50a", - "72346a6c066570ae51f566c676c12390e5c08dedf3b9980e76bdacc263754f9d,04b27d0bad237d14a3dfabf4ba464c7a2878889520c815dbcc4c735f306811646acf934fb66ba53282c1e52fbc7a26de5b9dff19c732af3cf376aea16869b56e29", - "9b1f5e00f64804d88d35603dd38972f586b9aecee2a2530b2ef999baa911a726,041632c2868b9c497aa63cba66c175d7cbbf0188fec868bd0bc2424d3522f1e2ac5baad6f5296beb27024b12668f8557b07948092f8f932aa6ef2a7bf5d2b03f4a", - "dd7f3ba6853b7cbeda7d89d0b8870ce149ab947c1633190bf95efe2f23f16797,046bdd17c66fa599f547a030194c562e7b01e326d3937b726a9fa6d1e894529bae40032c95008b2d4e07e78ef126e029d876a4c407af244e16cbf0b3b7d8774bae", - "6c1d6084d3976fb45a5554c41aa9b8bcd12581aff20b539911856809714543e8,042670ff1401fa8b20699784318affafc9156d5a6151690493d81f2275b15701d68d298105544f273a606df101792a7ebab939b74cae5d20cf06e0928bbbac9d5e", - "b8f0494f9cf177805ef44b1cfbc3b56f1c2b65e41efd1611097141e0b5e0a7d4,04fdb18cabb707daae7bcd2ac10f3d89fc9bf84ed761dd83cb02e441d346da7bc4454bb86c2d142c2f11b89497e1a4840252a80b76ae38dca2345f78a3f35e99c7", - "97ca2faf11dbbb4438ef32d0fad52d92d2fcfd63227a2e9c4b5cc624b614c3cb,04f6ffe5110fe36099d8b53b1768404656eec9ae998beb55e905093132c8f5aa419f21d832d0baff0bf2a5c705e8117e41bb2b506c6dba6dff61fb2a95ddc15cd1" - }; + static SampleECKeyPairs() + { + KeyPairs = new ReadOnlyCollection( + _keys.Select(x => + { + var privateKeyHex = x.Split(",").First(); + var privateKey = ByteArrayHelper.HexStringToByteArray(privateKeyHex); + return CryptoHelper.FromPrivateKey(privateKey); + }).ToList()); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/SmartContractTestConstants.cs b/test/AElf.Contracts.TestBase/SmartContractTestConstants.cs index 638b1c30f9..9118fbab4f 100644 --- a/test/AElf.Contracts.TestBase/SmartContractTestConstants.cs +++ b/test/AElf.Contracts.TestBase/SmartContractTestConstants.cs @@ -1,22 +1,21 @@ using AElf.Kernel; -namespace AElf.Contracts.TestBase +namespace AElf.Contracts.TestBase; + +public static class SmartContractTestConstants { - public static class SmartContractTestConstants - { - /// - /// 30 means use default assembly loader context, for code coverage - /// - public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; + /// + /// 30 means use default assembly loader context, for code coverage + /// + public const int TestRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; - public const int ResourceSupply = 10000; + public const int ResourceSupply = 10000; - public const string Consensus = "Consensus.AEDPoS"; - public const string MultiToken = "MultiToken"; - public const string CrossChain = "CrossChain"; - public const string Parliament = "Parliament"; - public const string Configuration = "Configuration"; - public const string Association = "Association"; - public const string Referendum = "Referendum"; - } + public const string Consensus = "Consensus.AEDPoS"; + public const string MultiToken = "MultiToken"; + public const string CrossChain = "CrossChain"; + public const string Parliament = "Parliament"; + public const string Configuration = "Configuration"; + public const string Association = "Association"; + public const string Referendum = "Referendum"; } \ No newline at end of file diff --git a/test/AElf.Contracts.TestBase/Types/MinerList.cs b/test/AElf.Contracts.TestBase/Types/MinerList.cs index cd590084d9..936708cfd6 100644 --- a/test/AElf.Contracts.TestBase/Types/MinerList.cs +++ b/test/AElf.Contracts.TestBase/Types/MinerList.cs @@ -1,50 +1,45 @@ -using AElf.Sdk.CSharp; using System.Linq; using AElf.CSharp.Core.Extension; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = - currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = + currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.A/AElf.Contracts.TestContract.A.csproj b/test/AElf.Contracts.TestContract.A/AElf.Contracts.TestContract.A.csproj index 68164ab6e3..2d93fecc34 100644 --- a/test/AElf.Contracts.TestContract.A/AElf.Contracts.TestContract.A.csproj +++ b/test/AElf.Contracts.TestContract.A/AElf.Contracts.TestContract.A.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.A/ContractA.cs b/test/AElf.Contracts.TestContract.A/ContractA.cs index e703c8ffce..093c236fab 100644 --- a/test/AElf.Contracts.TestContract.A/ContractA.cs +++ b/test/AElf.Contracts.TestContract.A/ContractA.cs @@ -1,108 +1,108 @@ -using AElf.Standards.ACS1; -using AElf.Sdk.CSharp; +using AElf.Sdk.CSharp; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.A +namespace AElf.Contracts.TestContract.A; + +public class AContract : AContractContainer.AContractBase { - public class AContract : AContractContainer.AContractBase + private static string ConcatMsg(StringValue input) { - #region Action - public override Empty InitializeA(Address input) - { - State.AState = new MappedState(); - State.BContract.Value = input; + return AElfString.Concat("A", input.Value); + } + + #region Action + + public override Empty InitializeA(Address input) + { + State.AState = new MappedState(); + State.BContract.Value = input; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteAA(StringValue input) + public override Empty ExecuteAA(StringValue input) + { + State.AState[Context.Sender] = new StringValue { - State.AState[Context.Sender] = new StringValue - { - Value = ConcatMsg(input) - }; + Value = ConcatMsg(input) + }; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteAB(StringValue input) + public override Empty ExecuteAB(StringValue input) + { + State.BContract.ExecuteBB.Send(new StringValue { - State.BContract.ExecuteBB.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteAC(StringValue input) + public override Empty ExecuteAC(StringValue input) + { + State.BContract.ExecuteBC.Send(new StringValue { - State.BContract.ExecuteBC.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteLoopABC(StringValue input) + public override Empty ExecuteLoopABC(StringValue input) + { + State.BContract.ExecuteLoopABC.Send(new StringValue { - State.BContract.ExecuteLoopABC.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) + public override MethodFees GetMethodFee(StringValue input) + { + return new MethodFees { - return new MethodFees + Fees = { - Fees = - { - new MethodFee - {Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000} //default 0.1 native symbol - } - }; - } - - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } - - #endregion - - #region View - - public override StringValue CallAA(Address input) - { - return State.AState[input] ?? new StringValue(); - } + new MethodFee + { Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000 } //default 0.1 native symbol + } + }; + } - public override StringValue CallAB(Address input) - { - return State.BContract.CallBB.Call(input); - } + public override Empty SetMethodFee(MethodFees input) + { + return new Empty(); + } - public override StringValue CallAC(Address input) - { - return State.BContract.CallBC.Call(input); - } + #endregion - public override StringValue CallLoopABC(Address input) - { - return State.BContract.CallLoopABC.Call(input); - } + #region View - #endregion + public override StringValue CallAA(Address input) + { + return State.AState[input] ?? new StringValue(); + } - private static string ConcatMsg(StringValue input) - { - return AElfString.Concat("A", input.Value); - } + public override StringValue CallAB(Address input) + { + return State.BContract.CallBB.Call(input); + } + + public override StringValue CallAC(Address input) + { + return State.BContract.CallBC.Call(input); } + + public override StringValue CallLoopABC(Address input) + { + return State.BContract.CallLoopABC.Call(input); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.A/ContractReference.cs b/test/AElf.Contracts.TestContract.A/ContractReference.cs index d4b41ba936..ce7051fcc8 100644 --- a/test/AElf.Contracts.TestContract.A/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.A/ContractReference.cs @@ -3,11 +3,10 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.A +namespace AElf.Contracts.TestContract.A; + +public class AContractState : ContractState { - public class AContractState : ContractState - { - public MappedState AState { get; set; } - internal BContractContainer.BContractReferenceState BContract { get; set; } - } + public MappedState AState { get; set; } + internal BContractContainer.BContractReferenceState BContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.B/AElf.Contracts.TestContract.B.csproj b/test/AElf.Contracts.TestContract.B/AElf.Contracts.TestContract.B.csproj index a84153e417..3315de616a 100644 --- a/test/AElf.Contracts.TestContract.B/AElf.Contracts.TestContract.B.csproj +++ b/test/AElf.Contracts.TestContract.B/AElf.Contracts.TestContract.B.csproj @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\test_c_contract.proto diff --git a/test/AElf.Contracts.TestContract.B/ContractB.cs b/test/AElf.Contracts.TestContract.B/ContractB.cs index b976ef0af1..857869b955 100644 --- a/test/AElf.Contracts.TestContract.B/ContractB.cs +++ b/test/AElf.Contracts.TestContract.B/ContractB.cs @@ -1,108 +1,108 @@ -using AElf.Standards.ACS1; -using AElf.Sdk.CSharp; +using AElf.Sdk.CSharp; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.B +namespace AElf.Contracts.TestContract.B; + +public class BContract : BContractContainer.BContractBase { - public class BContract : BContractContainer.BContractBase + private static string ConcatMsg(StringValue input) { - #region Action - public override Empty InitializeB(Address input) - { - State.BState = new MappedState(); - State.CContract.Value = input; + return AElfString.Concat("B", input.Value); + } + + #region Action + + public override Empty InitializeB(Address input) + { + State.BState = new MappedState(); + State.CContract.Value = input; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteBB(StringValue input) + public override Empty ExecuteBB(StringValue input) + { + State.BState[Context.Sender] = new StringValue { - State.BState[Context.Sender] = new StringValue - { - Value = ConcatMsg(input) - }; + Value = ConcatMsg(input) + }; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteBC(StringValue input) + public override Empty ExecuteBC(StringValue input) + { + State.CContract.ExecuteCC.Send(new StringValue { - State.CContract.ExecuteCC.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteBA(StringValue input) + public override Empty ExecuteBA(StringValue input) + { + State.CContract.ExecuteCA.Send(new StringValue { - State.CContract.ExecuteCA.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteLoopABC(StringValue input) + public override Empty ExecuteLoopABC(StringValue input) + { + State.CContract.ExecuteLoopABC.Send(new StringValue { - State.CContract.ExecuteLoopABC.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) + public override MethodFees GetMethodFee(StringValue input) + { + return new MethodFees { - return new MethodFees + Fees = { - Fees = - { - new MethodFee - {Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000} //default 0.1 native symbol - } - }; - } - - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } - - #endregion - - #region View - - public override StringValue CallBB(Address input) - { - return State.BState[input] ?? new StringValue(); - } + new MethodFee + { Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000 } //default 0.1 native symbol + } + }; + } - public override StringValue CallBA(Address input) - { - return State.CContract.CallCA.Call(input); - } + public override Empty SetMethodFee(MethodFees input) + { + return new Empty(); + } - public override StringValue CallBC(Address input) - { - return State.CContract.CallCC.Call(input); - } + #endregion - public override StringValue CallLoopABC(Address input) - { - return State.CContract.CallLoopABC.Call(input); - } + #region View - #endregion + public override StringValue CallBB(Address input) + { + return State.BState[input] ?? new StringValue(); + } - private static string ConcatMsg(StringValue input) - { - return AElfString.Concat("B", input.Value); - } + public override StringValue CallBA(Address input) + { + return State.CContract.CallCA.Call(input); + } + + public override StringValue CallBC(Address input) + { + return State.CContract.CallCC.Call(input); } + + public override StringValue CallLoopABC(Address input) + { + return State.CContract.CallLoopABC.Call(input); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.B/ContractReference.cs b/test/AElf.Contracts.TestContract.B/ContractReference.cs index d6a440960c..e369fe58fc 100644 --- a/test/AElf.Contracts.TestContract.B/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.B/ContractReference.cs @@ -3,11 +3,10 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.B +namespace AElf.Contracts.TestContract.B; + +public class BContractState : ContractState { - public class BContractState : ContractState - { - public MappedState BState { get; set; } - internal CContractContainer.CContractReferenceState CContract { get; set; } - } + public MappedState BState { get; set; } + internal CContractContainer.CContractReferenceState CContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunction/AElf.Contracts.TestContract.BasicFunction.csproj b/test/AElf.Contracts.TestContract.BasicFunction/AElf.Contracts.TestContract.BasicFunction.csproj index e80da18a8b..151577ce67 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/AElf.Contracts.TestContract.BasicFunction.csproj +++ b/test/AElf.Contracts.TestContract.BasicFunction/AElf.Contracts.TestContract.BasicFunction.csproj @@ -6,15 +6,15 @@ - true + true - true + true - + diff --git a/test/AElf.Contracts.TestContract.BasicFunction/BasicContractState.cs b/test/AElf.Contracts.TestContract.BasicFunction/BasicContractState.cs index 3f893c4bbb..3e611557f6 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/BasicContractState.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/BasicContractState.cs @@ -1,24 +1,23 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.TestContract.BasicFunction +namespace AElf.Contracts.TestContract.BasicFunction; + +public partial class BasicFunctionContractState : ContractState { - public partial class BasicFunctionContractState : ContractState - { - public BoolState Initialized { get; set; } - public StringState ContractName { get; set; } - public ProtobufState
ContractManager { get; set; } - public Int64State MinBet { get; set; } - public Int64State MaxBet { get; set; } + public BoolState Initialized { get; set; } + public StringState ContractName { get; set; } + public ProtobufState
ContractManager { get; set; } + public Int64State MinBet { get; set; } + public Int64State MaxBet { get; set; } + + public Int64State MortgageBalance { get; set; } + public Int64State TotalBetBalance { get; set; } + public Int64State RewardBalance { get; set; } - public Int64State MortgageBalance { get; set; } - public Int64State TotalBetBalance { get; set; } - public Int64State RewardBalance { get; set; } + public MappedState WinerHistory { get; set; } + public MappedState LoserHistory { get; set; } - public MappedState WinerHistory { get; set; } - public MappedState LoserHistory { get; set; } - - public MappedState TransactionFees { get; set; } - } + public MappedState TransactionFees { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs index 98a2223eba..c4bdb5728f 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs @@ -4,147 +4,146 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunction +namespace AElf.Contracts.TestContract.BasicFunction; + +/// +/// Action methods +/// +public partial class BasicFunctionContract : BasicFunctionContractContainer.BasicFunctionContractBase { - /// - /// Action methods - /// - public partial class BasicFunctionContract : BasicFunctionContractContainer.BasicFunctionContractBase + public override Empty InitialBasicFunctionContract(InitialBasicContractInput input) { - public override Empty InitialBasicFunctionContract(InitialBasicContractInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); - Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, - "Invalid min/max value input setting."); - - State.Initialized.Value = true; - State.ContractName.Value = input.ContractName; - State.ContractManager.Value = input.Manager; - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; - State.MortgageBalance.Value = input.MortgageValue; - - return new Empty(); - } + Assert(!State.Initialized.Value, "Already initialized."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); + + State.Initialized.Value = true; + State.ContractName.Value = input.ContractName; + State.ContractManager.Value = input.Manager; + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; + State.MortgageBalance.Value = input.MortgageValue; + + return new Empty(); + } - public override Empty UpdateBetLimit(BetLimitInput input) - { - Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); - Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, - "Invalid min/max value input setting."); + public override Empty UpdateBetLimit(BetLimitInput input) + { + Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; - return new Empty(); - } + return new Empty(); + } - public override Empty UserPlayBet(BetInput input) - { - Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <= State.MaxBet.Value, - $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); - //Assert(input.Int64Value > State.WinerHistory[Context.Sender], "Should bet bigger than your reward money."); - State.TotalBetBalance.Value = State.TotalBetBalance.Value.Add(input.Int64Value); - - var result = WinOrLose(input.Int64Value); - - if (result == 0) - { - State.LoserHistory[Context.Sender] = State.LoserHistory[Context.Sender].Add(input.Int64Value); - } - else - { - State.RewardBalance.Value = State.RewardBalance.Value.Add(result); - State.WinerHistory[Context.Sender] = State.WinerHistory[Context.Sender].Add(result); - } - - return new Empty(); - } + public override Empty UserPlayBet(BetInput input) + { + Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <= State.MaxBet.Value, + $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); + //Assert(input.Int64Value > State.WinerHistory[Context.Sender], "Should bet bigger than your reward money."); + State.TotalBetBalance.Value = State.TotalBetBalance.Value.Add(input.Int64Value); - public override Empty LockToken(LockTokenInput input) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - - State.TokenContract.Lock.Send(new LockInput - { - Symbol = input.Symbol, - Address = input.Address, - Amount = input.Amount, - LockId = input.LockId, - Usage = input.Usage - }); - - return new Empty(); - } + var result = WinOrLose(input.Int64Value); - public override Empty UnlockToken(UnlockTokenInput input) + if (result == 0) { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - - State.TokenContract.Unlock.Send(new UnlockInput - { - Symbol = input.Symbol, - Address = input.Address, - Amount = input.Amount, - LockId = input.LockId, - Usage = input.Usage - }); - return new Empty(); + State.LoserHistory[Context.Sender] = State.LoserHistory[Context.Sender].Add(input.Int64Value); } - - public override GetLockedTokenAmountOutput GetLockedAmount(GetLockedTokenAmountInput input) + else { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - var output = State.TokenContract.GetLockedAmount.Call(new GetLockedAmountInput - { - Symbol = input.Symbol, - Address = input.Address, - LockId = input.LockId - }); - return new GetLockedTokenAmountOutput - { - Address = output.Address, - Symbol = output.Symbol, - LockId = output.LockId, - Amount = output.Amount - }; + State.RewardBalance.Value = State.RewardBalance.Value.Add(result); + State.WinerHistory[Context.Sender] = State.WinerHistory[Context.Sender].Add(result); } - public override Empty ValidateOrigin(Address address) + return new Empty(); + } + + public override Empty LockToken(LockTokenInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + State.TokenContract.Lock.Send(new LockInput { - Assert(address == Context.Origin, "Validation failed, origin is not expected."); - return new Empty(); - } + Symbol = input.Symbol, + Address = input.Address, + Amount = input.Amount, + LockId = input.LockId, + Usage = input.Usage + }); + + return new Empty(); + } + + public override Empty UnlockToken(UnlockTokenInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - private long WinOrLose(long betAmount) + State.TokenContract.Unlock.Send(new UnlockInput { - var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); - if (data < 0) - data = data.Mul(-1); - - if (data % 100 == 1) - return betAmount.Mul(1000); - if (data % 50 == 5) - return betAmount.Mul(50); - return 0; - } + Symbol = input.Symbol, + Address = input.Address, + Amount = input.Amount, + LockId = input.LockId, + Usage = input.Usage + }); + return new Empty(); + } - public override Empty TransferTokenToContract(TransferTokenToContractInput input) + public override GetLockedTokenAmountOutput GetLockedAmount(GetLockedTokenAmountInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + var output = State.TokenContract.GetLockedAmount.Call(new GetLockedAmountInput + { + Symbol = input.Symbol, + Address = input.Address, + LockId = input.LockId + }); + return new GetLockedTokenAmountOutput { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + Address = output.Address, + Symbol = output.Symbol, + LockId = output.LockId, + Amount = output.Amount + }; + } + + public override Empty ValidateOrigin(Address address) + { + Assert(address == Context.Origin, "Validation failed, origin is not expected."); + return new Empty(); + } - State.TokenContract.TransferToContract.Send(new TransferToContractInput - { - Symbol = input.Symbol, - Amount = input.Amount, - Memo = input.Memo - }); + private long WinOrLose(long betAmount) + { + var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); + if (data < 0) + data = data.Mul(-1); + + if (data % 100 == 1) + return betAmount.Mul(1000); + if (data % 50 == 5) + return betAmount.Mul(50); + return 0; + } - return new Empty(); - } + public override Empty TransferTokenToContract(TransferTokenToContractInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + State.TokenContract.TransferToContract.Send(new TransferToContractInput + { + Symbol = input.Symbol, + Amount = input.Amount, + Memo = input.Memo + }); + + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_FeeProvider.cs b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_FeeProvider.cs index ff0b2554c3..f08dd610fd 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_FeeProvider.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_FeeProvider.cs @@ -1,33 +1,32 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunction +namespace AElf.Contracts.TestContract.BasicFunction; + +public partial class BasicFunctionContract { - public partial class BasicFunctionContract + [View] + public override MethodFees GetMethodFee(StringValue input) { - [View] - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - return methodFees; + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) + return methodFees; - //set default tx fee - return new MethodFees + //set default tx fee + return new MethodFees + { + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = - { - new MethodFee {Symbol = "ELF", BasicFee = 1000_0000} - } - }; - } + new MethodFee { Symbol = "ELF", BasicFee = 1000_0000 } + } + }; + } - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_View.cs b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_View.cs index 093592aa9f..55bd6d766e 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_View.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_View.cs @@ -1,59 +1,58 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunction +namespace AElf.Contracts.TestContract.BasicFunction; + +/// +/// View methods +/// +public partial class BasicFunctionContract { - /// - /// View methods - /// - public partial class BasicFunctionContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(BasicFunctionContract) - }; - } + Value = nameof(BasicFunctionContract) + }; + } - public override MoneyOutput QueryWinMoney(Empty input) + public override MoneyOutput QueryWinMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.TotalBetBalance.Value - }; - } + Int64Value = State.TotalBetBalance.Value + }; + } - public override MoneyOutput QueryRewardMoney(Empty input) + public override MoneyOutput QueryRewardMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.RewardBalance.Value - }; - } + Int64Value = State.RewardBalance.Value + }; + } - public override MoneyOutput QueryUserWinMoney(Address address) + public override MoneyOutput QueryUserWinMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.WinerHistory[address] - }; - } + Int64Value = State.WinerHistory[address] + }; + } - public override MoneyOutput QueryUserLoseMoney(Address address) + public override MoneyOutput QueryUserLoseMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.LoserHistory[address] - }; - } + Int64Value = State.LoserHistory[address] + }; + } - public override OtherResourceInfo GetResourceInfo(Transaction input) + public override OtherResourceInfo GetResourceInfo(Transaction input) + { + return new OtherResourceInfo { - return new OtherResourceInfo - { - Address = Context.Self - }; - } + Address = Context.Self + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunction/ContractReference.cs b/test/AElf.Contracts.TestContract.BasicFunction/ContractReference.cs index ebba53dbb9..b46164cecc 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/ContractReference.cs @@ -1,9 +1,8 @@ using AElf.Contracts.MultiToken; -namespace AElf.Contracts.TestContract.BasicFunction +namespace AElf.Contracts.TestContract.BasicFunction; + +public partial class BasicFunctionContractState { - public partial class BasicFunctionContractState - { - internal TokenContractImplContainer.TokenContractImplReferenceState TokenContract { get; set; } - } + internal TokenContractImplContainer.TokenContractImplReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj index 7d51d3219a..af22ae709f 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/AElf.Contracts.TestContract.BasicFunctionWithParallel.csproj @@ -6,15 +6,15 @@ - true + true - true + true - + @@ -22,7 +22,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs0.proto diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContractState.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContractState.cs index a929dd4450..605ae68ba5 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContractState.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContractState.cs @@ -1,27 +1,26 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +public partial class BasicFunctionWithParallelContractState : ContractState { - public partial class BasicFunctionWithParallelContractState : ContractState - { - public BoolState Initialized { get; set; } - public StringState ContractName { get; set; } - public ProtobufState
ContractManager { get; set; } - public Int64State MinBet { get; set; } - public Int64State MaxBet { get; set; } - - public Int64State MortgageBalance { get; set; } - public Int64State TotalBetBalance { get; set; } - public Int64State RewardBalance { get; set; } - - public MappedState WinnerHistory { get; set; } - public MappedState LoserHistory { get; set; } - - public MappedState StringValueMap { get; set; } - - public MappedState LongValueMap { get; set; } + public BoolState Initialized { get; set; } + public StringState ContractName { get; set; } + public ProtobufState
ContractManager { get; set; } + public Int64State MinBet { get; set; } + public Int64State MaxBet { get; set; } + + public Int64State MortgageBalance { get; set; } + public Int64State TotalBetBalance { get; set; } + public Int64State RewardBalance { get; set; } + + public MappedState WinnerHistory { get; set; } + public MappedState LoserHistory { get; set; } + + public MappedState StringValueMap { get; set; } + + public MappedState LongValueMap { get; set; } - public MappedState MessageValueMap { get; set; } - } + public MappedState MessageValueMap { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS1_StatePathsProvider.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS1_StatePathsProvider.cs index 6aae0df0b7..a29e4b56d6 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS1_StatePathsProvider.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS1_StatePathsProvider.cs @@ -1,19 +1,17 @@ using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +public partial class BasicFunctionWithParallelContract { - public partial class BasicFunctionWithParallelContract + public override MethodFees GetMethodFee(StringValue input) { - public override MethodFees GetMethodFee(StringValue input) - { - return new MethodFees(); - } - - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } + return new MethodFees(); + } + public override Empty SetMethodFee(MethodFees input) + { + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS2_StatePathsProvider.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS2_StatePathsProvider.cs index cf7511e16d..3e2cf3b390 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS2_StatePathsProvider.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_ACS2_StatePathsProvider.cs @@ -1,102 +1,101 @@ -using AElf.Standards.ACS2; -using AElf.Sdk.CSharp; +using AElf.Sdk.CSharp; +using AElf.Standards.ACS2; using AElf.Types; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +public partial class BasicFunctionWithParallelContract { - public partial class BasicFunctionWithParallelContract + public override ResourceInfo GetResourceInfo(Transaction txn) { - public override ResourceInfo GetResourceInfo(Transaction txn) + switch (txn.MethodName) { - switch (txn.MethodName) + case nameof(QueryTwoUserWinMoney): { - case nameof(QueryTwoUserWinMoney): + var args = QueryTwoUserWinMoneyInput.Parser.ParseFrom(txn.Params); + return new ResourceInfo { - var args = QueryTwoUserWinMoneyInput.Parser.ParseFrom(txn.Params); - return new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(BasicFunctionWithParallelContractState.WinnerHistory),args.Second.ToString()) - } - }; - } + GetPath(nameof(BasicFunctionWithParallelContractState.WinnerHistory), args.Second.ToString()) + } + }; + } - case nameof(IncreaseWinMoney): + case nameof(IncreaseWinMoney): + { + var args = IncreaseWinMoneyInput.Parser.ParseFrom(txn.Params); + return new ResourceInfo { - var args = IncreaseWinMoneyInput.Parser.ParseFrom(txn.Params); - return new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(BasicFunctionWithParallelContractState.WinnerHistory), args.Second.ToString()) - } - }; - } + GetPath(nameof(BasicFunctionWithParallelContractState.WinnerHistory), args.Second.ToString()) + } + }; + } - case nameof(SetValue): + case nameof(SetValue): + { + var args = SetValueInput.Parser.ParseFrom(txn.Params); + return new ResourceInfo { - var args = SetValueInput.Parser.ParseFrom(txn.Params); - return new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap),args.Key) - } - }; - } - case nameof(RemoveValueParallel): - case nameof(RemoveValueParallelFromPostPlugin): + GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap), args.Key) + } + }; + } + case nameof(RemoveValueParallel): + case nameof(RemoveValueParallelFromPostPlugin): + { + var args = RemoveValueInput.Parser.ParseFrom(txn.Params); + return new ResourceInfo { - var args = RemoveValueInput.Parser.ParseFrom(txn.Params); - return new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap),args.Key) - } - }; - } - - case nameof(IncreaseValueParallel): - case nameof(IncreaseValueParallelWithInlineAndPlugin): - case nameof(IncreaseValueFailedParallelWithInlineAndPlugin): - case nameof(IncreaseValueParallelFailed): - case nameof(IncreaseValueParallelWithFailedInlineAndPlugin): + GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap), args.Key) + } + }; + } + + case nameof(IncreaseValueParallel): + case nameof(IncreaseValueParallelWithInlineAndPlugin): + case nameof(IncreaseValueFailedParallelWithInlineAndPlugin): + case nameof(IncreaseValueParallelFailed): + case nameof(IncreaseValueParallelWithFailedInlineAndPlugin): + { + var args = IncreaseValueInput.Parser.ParseFrom(txn.Params); + return new ResourceInfo { - var args = IncreaseValueInput.Parser.ParseFrom(txn.Params); - return new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap),args.Key), - GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap),args.Key) - } - }; - } - default: - throw new AssertionException($"invalid method: {txn.MethodName}"); + GetPath(nameof(BasicFunctionWithParallelContractState.LongValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.StringValueMap), args.Key), + GetPath(nameof(BasicFunctionWithParallelContractState.MessageValueMap), args.Key) + } + }; } + default: + throw new AssertionException($"invalid method: {txn.MethodName}"); } + } - private ScopedStatePath GetPath(params string[] parts) + private ScopedStatePath GetPath(params string[] parts) + { + return new ScopedStatePath { - return new ScopedStatePath + Address = Context.Self, + Path = new StatePath { - Address = Context.Self, - Path = new StatePath + Parts = { - Parts = - { - parts - } + parts } - }; - } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_Action.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_Action.cs index 641fb5fcca..c3b589c8c6 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_Action.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_Action.cs @@ -1,432 +1,433 @@ -using System; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; using AElf.Sdk.CSharp; -using AElf.Sdk.CSharp.State; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +/// +/// Action methods +/// +public partial class + BasicFunctionWithParallelContract : BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractBase { - /// - /// Action methods - /// - public partial class BasicFunctionWithParallelContract : BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractBase + public override Empty InitialBasicFunctionWithParallelContract(InitialBasicFunctionWithParallelContractInput input) { - public override Empty InitialBasicFunctionWithParallelContract(InitialBasicFunctionWithParallelContractInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); - Assert(input.MinValue >0 && input.MaxValue >0 && input.MaxValue >= input.MinValue, "Invalid min/max value input setting."); - - State.Initialized.Value = true; - State.ContractName.Value = input.ContractName; - State.ContractManager.Value = input.Manager; - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; - State.MortgageBalance.Value = input.MortgageValue; - - return new Empty(); - } + Assert(!State.Initialized.Value, "Already initialized."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); + + State.Initialized.Value = true; + State.ContractName.Value = input.ContractName; + State.ContractManager.Value = input.Manager; + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; + State.MortgageBalance.Value = input.MortgageValue; + + return new Empty(); + } - public override Empty UpdateBetLimit(BetLimitInput input) - { - Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); - Assert(input.MinValue >0 && input.MaxValue >0 && input.MaxValue >= input.MinValue, "Invalid min/max value input setting."); - - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; + public override Empty UpdateBetLimit(BetLimitInput input) + { + Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); - return new Empty(); - } + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; - public override Empty UserPlayBet(BetInput input) - { - Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <=State.MaxBet.Value, $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); - //Assert(input.Int64Value > State.WinerHistory[Context.Sender], "Should bet bigger than your reward money."); - State.TotalBetBalance.Value = State.TotalBetBalance.Value.Add(input.Int64Value); - - var result = WinOrLose(input.Int64Value); - - if (result == 0) - { - State.LoserHistory[Context.Sender] = State.LoserHistory[Context.Sender].Add(input.Int64Value); - } - else - { - State.RewardBalance.Value = State.RewardBalance.Value.Add(result); - State.WinnerHistory[Context.Sender] = State.WinnerHistory[Context.Sender].Add(result); - } - - return new Empty(); - } + return new Empty(); + } - public override Empty LockToken(LockTokenInput input) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - - State.TokenContract.Lock.Send(new LockInput - { - Symbol = input.Symbol, - Address = input.Address, - Amount = input.Amount, - LockId = input.LockId, - Usage = input.Usage - }); - - return new Empty(); - } + public override Empty UserPlayBet(BetInput input) + { + Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <= State.MaxBet.Value, + $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); + //Assert(input.Int64Value > State.WinerHistory[Context.Sender], "Should bet bigger than your reward money."); + State.TotalBetBalance.Value = State.TotalBetBalance.Value.Add(input.Int64Value); - public override Empty UnlockToken(UnlockTokenInput input) - { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - - State.TokenContract.Unlock.Send(new UnlockInput - { - Symbol = input.Symbol, - Address = input.Address, - Amount = input.Amount, - LockId = input.LockId, - Usage = input.Usage - }); - return new Empty(); - } + var result = WinOrLose(input.Int64Value); - public override Empty ValidateOrigin(Address address) + if (result == 0) { - Assert(address == Context.Origin, "Validation failed, origin is not expected."); - return new Empty(); + State.LoserHistory[Context.Sender] = State.LoserHistory[Context.Sender].Add(input.Int64Value); } - - public override Empty IncreaseWinMoney(IncreaseWinMoneyInput input) + else { - State.WinnerHistory[input.First] = State.WinnerHistory[input.First] + 1; - State.WinnerHistory[input.Second] = State.WinnerHistory[input.Second] + 1; - return new Empty(); + State.RewardBalance.Value = State.RewardBalance.Value.Add(result); + State.WinnerHistory[Context.Sender] = State.WinnerHistory[Context.Sender].Add(result); } - public override Empty SetValue(SetValueInput input) - { - State.LongValueMap[input.Key] = input.Int64Value; - State.StringValueMap[input.Key] = input.StringValue; - State.MessageValueMap[input.Key] = input.MessageValue; - return new Empty(); - } + return new Empty(); + } - public override Empty IncreaseValue(IncreaseValueInput input) - { - var longValue = State.LongValueMap[input.Key]; - longValue++; - State.LongValueMap[input.Key] = longValue; - State.StringValueMap[input.Key] = longValue.ToString(); - var messageValue = State.MessageValueMap[input.Key] ?? new MessageValue(); - messageValue.Int64Value = longValue; - messageValue.StringValue = State.StringValueMap[input.Key]; - State.MessageValueMap[input.Key] = messageValue; - return new Empty(); - } + public override Empty LockToken(LockTokenInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - public override Empty IncreaseValueParallel(IncreaseValueInput input) + State.TokenContract.Lock.Send(new LockInput { - return IncreaseValue(input); - } - - public override Empty IncreaseValueWithInline(IncreaseValueInput input) - { - IncreaseValue(input); - Context.SendInline(Context.Self, nameof(IncreaseValue), input); - return new Empty(); - } + Symbol = input.Symbol, + Address = input.Address, + Amount = input.Amount, + LockId = input.LockId, + Usage = input.Usage + }); - public override Empty IncreaseValueWithPrePlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } - - public override Empty IncreaseValueWithPostPlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + return new Empty(); + } - public override Empty IncreaseValueWithInlineAndPrePlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } - - public override Empty IncreaseValueWithInlineAndPostPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty UnlockToken(UnlockTokenInput input) + { + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + + State.TokenContract.Unlock.Send(new UnlockInput + { + Symbol = input.Symbol, + Address = input.Address, + Amount = input.Amount, + LockId = input.LockId, + Usage = input.Usage + }); + return new Empty(); + } - public override Empty IncreaseValueWithPlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + public override Empty ValidateOrigin(Address address) + { + Assert(address == Context.Origin, "Validation failed, origin is not expected."); + return new Empty(); + } - public override Empty IncreaseValueWithInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } - - public override Empty IncreaseValueParallelWithInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty IncreaseWinMoney(IncreaseWinMoneyInput input) + { + State.WinnerHistory[input.First] = State.WinnerHistory[input.First] + 1; + State.WinnerHistory[input.Second] = State.WinnerHistory[input.Second] + 1; + return new Empty(); + } - public override Empty IncreaseValueFailed(IncreaseValueInput input) - { - Assert(false); - return new Empty(); - } + public override Empty SetValue(SetValueInput input) + { + State.LongValueMap[input.Key] = input.Int64Value; + State.StringValueMap[input.Key] = input.StringValue; + State.MessageValueMap[input.Key] = input.MessageValue; + return new Empty(); + } - public override Empty IncreaseValueParallelFailed(IncreaseValueInput input) - { - return IncreaseValueFailed(input); - } + public override Empty IncreaseValue(IncreaseValueInput input) + { + var longValue = State.LongValueMap[input.Key]; + longValue++; + State.LongValueMap[input.Key] = longValue; + State.StringValueMap[input.Key] = longValue.ToString(); + var messageValue = State.MessageValueMap[input.Key] ?? new MessageValue(); + messageValue.Int64Value = longValue; + messageValue.StringValue = State.StringValueMap[input.Key]; + State.MessageValueMap[input.Key] = messageValue; + return new Empty(); + } - public override Empty IncreaseValueFailedWithInline(IncreaseValueInput input) - { - Context.SendInline(Context.Self, nameof(IncreaseValue), input); - return IncreaseValueFailed(input); - } + public override Empty IncreaseValueParallel(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty IncreaseValueFailedWithPlugin(IncreaseValueInput input) - { - return IncreaseValueFailed(input); - } + public override Empty IncreaseValueWithInline(IncreaseValueInput input) + { + IncreaseValue(input); + Context.SendInline(Context.Self, nameof(IncreaseValue), input); + return new Empty(); + } - public override Empty IncreaseValueFailedWithPostPlugin(IncreaseValueInput input) - { - return IncreaseValueFailed(input); - } + public override Empty IncreaseValueWithPrePlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty IncreaseValueFailedWithPrePlugin(IncreaseValueInput input) - { - return IncreaseValueFailed(input); - } + public override Empty IncreaseValueWithPostPlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty IncreaseValueFailedWithInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueFailedWithInline(input); - } - - public override Empty IncreaseValueWithFailedInline(IncreaseValueInput input) - { - IncreaseValue(input); - Context.SendInline(Context.Self, nameof(IncreaseValueFailed), input); - return new Empty(); - } + public override Empty IncreaseValueWithInlineAndPrePlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } - public override Empty IncreaseValueWithFailedInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueWithFailedInline(input); - } + public override Empty IncreaseValueWithInlineAndPostPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } - public override Empty IncreaseValueFailedParallelWithInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueFailedWithInline(input); - } + public override Empty IncreaseValueWithPlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty IncreaseValueFailedWithInlineAndPostPlugin(IncreaseValueInput input) - { - return IncreaseValueFailedWithInline(input); - } + public override Empty IncreaseValueWithInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } - public override Empty IncreaseValueFailedWithInlineAndPrePlugin(IncreaseValueInput input) - { - return IncreaseValueFailedWithInline(input); - } - - public override Empty IncreaseValueParallelWithFailedInlineAndPlugin(IncreaseValueInput input) - { - return IncreaseValueWithFailedInline(input); - } + public override Empty IncreaseValueParallelWithInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } - public override Empty IncreaseValueWithFailedInlineAndPostPlugin(IncreaseValueInput input) - { - return IncreaseValueWithFailedInline(input); - } + public override Empty IncreaseValueFailed(IncreaseValueInput input) + { + Assert(false); + return new Empty(); + } - public override Empty IncreaseValueWithFailedInlineAndPrePlugin(IncreaseValueInput input) - { - return IncreaseValueWithFailedInline(input); - } + public override Empty IncreaseValueParallelFailed(IncreaseValueInput input) + { + return IncreaseValueFailed(input); + } - public override Empty IncreaseValueWithFailedPrePlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + public override Empty IncreaseValueFailedWithInline(IncreaseValueInput input) + { + Context.SendInline(Context.Self, nameof(IncreaseValue), input); + return IncreaseValueFailed(input); + } - public override Empty IncreaseValueWithInlineAndFailedPrePlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty IncreaseValueFailedWithPlugin(IncreaseValueInput input) + { + return IncreaseValueFailed(input); + } - public override Empty IncreaseValueWithFailedPrePluginAndPostPlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + public override Empty IncreaseValueFailedWithPostPlugin(IncreaseValueInput input) + { + return IncreaseValueFailed(input); + } - public override Empty IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty IncreaseValueFailedWithPrePlugin(IncreaseValueInput input) + { + return IncreaseValueFailed(input); + } - public override Empty IncreaseValueWithFailedPostPlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + public override Empty IncreaseValueFailedWithInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueFailedWithInline(input); + } - public override Empty IncreaseValueWithInlineAndFailedPostPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty IncreaseValueWithFailedInline(IncreaseValueInput input) + { + IncreaseValue(input); + Context.SendInline(Context.Self, nameof(IncreaseValueFailed), input); + return new Empty(); + } - public override Empty IncreaseValueWithPrePluginAndFailedPostPlugin(IncreaseValueInput input) - { - return IncreaseValue(input); - } + public override Empty IncreaseValueWithFailedInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueWithFailedInline(input); + } - public override Empty IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin(IncreaseValueInput input) - { - return IncreaseValueWithInline(input); - } + public override Empty IncreaseValueFailedParallelWithInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueFailedWithInline(input); + } - public override Empty RemoveValue(RemoveValueInput input) - { - State.LongValueMap.Remove(input.Key); - State.StringValueMap.Remove(input.Key); - State.MessageValueMap.Remove(input.Key); - return new Empty(); - } + public override Empty IncreaseValueFailedWithInlineAndPostPlugin(IncreaseValueInput input) + { + return IncreaseValueFailedWithInline(input); + } - public override Empty RemoveValueFromInlineWithPlugin(RemoveValueInput input) - { - IncreaseValue(new IncreaseValueInput - { - Key = input.Key - }); - Context.SendInline(Context.Self, nameof(RemoveValue), input); - return new Empty(); - } + public override Empty IncreaseValueFailedWithInlineAndPrePlugin(IncreaseValueInput input) + { + return IncreaseValueFailedWithInline(input); + } - public override Empty RemoveValueFromPrePlugin(RemoveValueInput input) - { - var increaseValueInput = new IncreaseValueInput - { - Key = input.Key - }; - IncreaseValue(increaseValueInput); - Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); - return new Empty(); - } - - public override Empty RemoveValueFromPostPlugin(RemoveValueInput input) - { - var increaseValueInput = new IncreaseValueInput - { - Key = input.Key - }; - IncreaseValue(increaseValueInput); - Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); - return new Empty(); - } + public override Empty IncreaseValueParallelWithFailedInlineAndPlugin(IncreaseValueInput input) + { + return IncreaseValueWithFailedInline(input); + } - public override Empty RemoveValueParallelFromPostPlugin(RemoveValueInput input) - { - var increaseValueInput = new IncreaseValueInput - { - Key = input.Key - }; - IncreaseValue(increaseValueInput); - Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); - return new Empty(); - } + public override Empty IncreaseValueWithFailedInlineAndPostPlugin(IncreaseValueInput input) + { + return IncreaseValueWithFailedInline(input); + } - public override Empty RemoveValueWithPlugin(RemoveValueInput input) - { - RemoveValue(input); - var increaseValueInput = new IncreaseValueInput - { - Key = input.Key - }; - Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); - return new Empty(); - } + public override Empty IncreaseValueWithFailedInlineAndPrePlugin(IncreaseValueInput input) + { + return IncreaseValueWithFailedInline(input); + } - public override Empty RemoveAfterSetValue(RemoveAfterSetValueInput input) - { - State.LongValueMap[input.Key] = input.Int64Value; - State.StringValueMap[input.Key] = input.StringValue; - State.MessageValueMap[input.Key] = input.MessageValue; - - State.LongValueMap.Remove(input.Key); - State.StringValueMap.Remove(input.Key); - State.MessageValueMap.Remove(input.Key); - - return new Empty(); - } + public override Empty IncreaseValueWithFailedPrePlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty SetAfterRemoveValue(SetAfterRemoveValueInput input) - { - State.LongValueMap.Remove(input.Key); - State.StringValueMap.Remove(input.Key); - State.MessageValueMap.Remove(input.Key); - - State.LongValueMap[input.Key] = input.Int64Value; - State.StringValueMap[input.Key] = input.StringValue; - State.MessageValueMap[input.Key] = input.MessageValue; - - return new Empty(); - } + public override Empty IncreaseValueWithInlineAndFailedPrePlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } + + public override Empty IncreaseValueWithFailedPrePluginAndPostPlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } + + public override Empty IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } + + public override Empty IncreaseValueWithFailedPostPlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } - public override Empty RemoveValueParallel(RemoveValueInput input) + public override Empty IncreaseValueWithInlineAndFailedPostPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } + + public override Empty IncreaseValueWithPrePluginAndFailedPostPlugin(IncreaseValueInput input) + { + return IncreaseValue(input); + } + + public override Empty IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin(IncreaseValueInput input) + { + return IncreaseValueWithInline(input); + } + + public override Empty RemoveValue(RemoveValueInput input) + { + State.LongValueMap.Remove(input.Key); + State.StringValueMap.Remove(input.Key); + State.MessageValueMap.Remove(input.Key); + return new Empty(); + } + + public override Empty RemoveValueFromInlineWithPlugin(RemoveValueInput input) + { + IncreaseValue(new IncreaseValueInput { - return RemoveValue(input); - } + Key = input.Key + }); + Context.SendInline(Context.Self, nameof(RemoveValue), input); + return new Empty(); + } - public override Empty ComplexChangeWithDeleteValue1(ComplexChangeInput input) + public override Empty RemoveValueFromPrePlugin(RemoveValueInput input) + { + var increaseValueInput = new IncreaseValueInput { - State.LongValueMap[input.Key] = input.Int64Value; - State.StringValueMap[input.Key] = input.StringValue; - - State.MessageValueMap.Remove(input.Key); - - return new Empty(); - } + Key = input.Key + }; + IncreaseValue(increaseValueInput); + Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); + return new Empty(); + } - public override Empty ComplexChangeWithDeleteValue2(ComplexChangeInput input) + public override Empty RemoveValueFromPostPlugin(RemoveValueInput input) + { + var increaseValueInput = new IncreaseValueInput { - State.LongValueMap.Remove(input.Key); - - State.StringValueMap[input.Key] = input.StringValue; - State.MessageValueMap[input.Key] = input.MessageValue; - - return new Empty(); - } + Key = input.Key + }; + IncreaseValue(increaseValueInput); + Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); + return new Empty(); + } - public override Empty ComplexChangeWithDeleteValue3(ComplexChangeInput input) + public override Empty RemoveValueParallelFromPostPlugin(RemoveValueInput input) + { + var increaseValueInput = new IncreaseValueInput { - State.LongValueMap[input.Key] = input.Int64Value; - - State.StringValueMap.Remove(input.Key); - State.MessageValueMap.Remove(input.Key); - - return new Empty(); - } + Key = input.Key + }; + IncreaseValue(increaseValueInput); + Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); + return new Empty(); + } - private long WinOrLose(long betAmount) + public override Empty RemoveValueWithPlugin(RemoveValueInput input) + { + RemoveValue(input); + var increaseValueInput = new IncreaseValueInput { - var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); - if(data < 0) - data = data.Mul(-1); - - if (data % 100 == 1) - return betAmount.Mul(1000); - if (data % 50 == 5) - return betAmount.Mul(50); - return 0; - } + Key = input.Key + }; + Context.SendInline(Context.Self, nameof(IncreaseValue), increaseValueInput); + return new Empty(); + } + + public override Empty RemoveAfterSetValue(RemoveAfterSetValueInput input) + { + State.LongValueMap[input.Key] = input.Int64Value; + State.StringValueMap[input.Key] = input.StringValue; + State.MessageValueMap[input.Key] = input.MessageValue; + + State.LongValueMap.Remove(input.Key); + State.StringValueMap.Remove(input.Key); + State.MessageValueMap.Remove(input.Key); + + return new Empty(); + } + + public override Empty SetAfterRemoveValue(SetAfterRemoveValueInput input) + { + State.LongValueMap.Remove(input.Key); + State.StringValueMap.Remove(input.Key); + State.MessageValueMap.Remove(input.Key); + + State.LongValueMap[input.Key] = input.Int64Value; + State.StringValueMap[input.Key] = input.StringValue; + State.MessageValueMap[input.Key] = input.MessageValue; + + return new Empty(); + } + + public override Empty RemoveValueParallel(RemoveValueInput input) + { + return RemoveValue(input); + } + + public override Empty ComplexChangeWithDeleteValue1(ComplexChangeInput input) + { + State.LongValueMap[input.Key] = input.Int64Value; + State.StringValueMap[input.Key] = input.StringValue; + + State.MessageValueMap.Remove(input.Key); + + return new Empty(); + } + + public override Empty ComplexChangeWithDeleteValue2(ComplexChangeInput input) + { + State.LongValueMap.Remove(input.Key); + + State.StringValueMap[input.Key] = input.StringValue; + State.MessageValueMap[input.Key] = input.MessageValue; + + return new Empty(); + } + + public override Empty ComplexChangeWithDeleteValue3(ComplexChangeInput input) + { + State.LongValueMap[input.Key] = input.Int64Value; + + State.StringValueMap.Remove(input.Key); + State.MessageValueMap.Remove(input.Key); + + return new Empty(); + } + + private long WinOrLose(long betAmount) + { + var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); + if (data < 0) + data = data.Mul(-1); + + if (data % 100 == 1) + return betAmount.Mul(1000); + if (data % 50 == 5) + return betAmount.Mul(50); + return 0; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_View.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_View.cs index d6520edad8..3245b27129 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_View.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/BasicFunctionWithParallelContract_View.cs @@ -1,70 +1,69 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +/// +/// View methods +/// +public partial class BasicFunctionWithParallelContract { - /// - /// View methods - /// - public partial class BasicFunctionWithParallelContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(BasicFunctionWithParallelContract) - }; - } + Value = nameof(BasicFunctionWithParallelContract) + }; + } - public override MoneyOutput QueryWinMoney(Empty input) + public override MoneyOutput QueryWinMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.TotalBetBalance.Value - }; - } + Int64Value = State.TotalBetBalance.Value + }; + } - public override MoneyOutput QueryRewardMoney(Empty input) + public override MoneyOutput QueryRewardMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.RewardBalance.Value - }; - } + Int64Value = State.RewardBalance.Value + }; + } - public override MoneyOutput QueryUserWinMoney(Address address) + public override MoneyOutput QueryUserWinMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.WinnerHistory[address] - }; - } + Int64Value = State.WinnerHistory[address] + }; + } - public override MoneyOutput QueryUserLoseMoney(Address address) + public override MoneyOutput QueryUserLoseMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.LoserHistory[address] - }; - } + Int64Value = State.LoserHistory[address] + }; + } - public override TwoUserMoneyOut QueryTwoUserWinMoney(QueryTwoUserWinMoneyInput input) + public override TwoUserMoneyOut QueryTwoUserWinMoney(QueryTwoUserWinMoneyInput input) + { + return new TwoUserMoneyOut { - return new TwoUserMoneyOut - { - FirstInt64Value = State.WinnerHistory[input.First], - SecondInt64Value = State.WinnerHistory[input.Second] - }; - } + FirstInt64Value = State.WinnerHistory[input.First], + SecondInt64Value = State.WinnerHistory[input.Second] + }; + } - public override GetValueOutput GetValue(GetValueInput input) + public override GetValueOutput GetValue(GetValueInput input) + { + return new GetValueOutput { - return new GetValueOutput - { - StringValue = State.StringValueMap[input.Key] ?? string.Empty, - Int64Value = State.LongValueMap[input.Key], - MessageValue = State.MessageValueMap[input.Key] - }; - } + StringValue = State.StringValueMap[input.Key] ?? string.Empty, + Int64Value = State.LongValueMap[input.Key], + MessageValue = State.MessageValueMap[input.Key] + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/ContractReference.cs b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/ContractReference.cs index 9572464bee..52d2e4f865 100644 --- a/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.BasicFunctionWithParallel/ContractReference.cs @@ -1,9 +1,8 @@ using AElf.Contracts.MultiToken; -namespace AElf.Contracts.TestContract.BasicFunctionWithParallel +namespace AElf.Contracts.TestContract.BasicFunctionWithParallel; + +public partial class BasicFunctionWithParallelContractState { - public partial class BasicFunctionWithParallelContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/AElf.Contracts.TestContract.BasicSecurity.csproj b/test/AElf.Contracts.TestContract.BasicSecurity/AElf.Contracts.TestContract.BasicSecurity.csproj index d56a5a01c6..af75594a41 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/AElf.Contracts.TestContract.BasicSecurity.csproj +++ b/test/AElf.Contracts.TestContract.BasicSecurity/AElf.Contracts.TestContract.BasicSecurity.csproj @@ -6,29 +6,29 @@ - true + true - true + true - + - + Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\test_basic_function_contract.proto - + Protobuf\Proto\acs1.proto diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContractState.cs b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContractState.cs index fdeadbfe6a..9dd60fce89 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContractState.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContractState.cs @@ -1,35 +1,33 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; -using Google.Protobuf.WellKnownTypes; +using AElf.Standards.ACS1; + +namespace AElf.Contracts.TestContract.BasicSecurity; -namespace AElf.Contracts.TestContract.BasicSecurity +public partial class BasicSecurityContractState : ContractState { - public partial class BasicSecurityContractState : ContractState - { - public BoolState Initialized { get; set; } - public BoolState BoolInfo { get; set; } - public Int32State Int32Info { get; set; } - public UInt32State UInt32Info { get; set; } - public Int64State Int64Info { get; set; } - public UInt64State UInt64Info { get; set; } - public StringState StringInfo { get; set; } - public BytesState BytesInfo { get; set; } - - public SingletonState Int32SingletonState { get; set; } - public SingletonState EnumState { get; set; } - - public SingletonState BytesSingletonState { get; set; } - public SingletonState ProtoInfo { get; set; } - - public SingletonStateLoopInt32Value { get; set; } - public ProtobufState ProtoInfo2 { get; set; } - - public MappedState MappedState { get; set; } - public MappedState Complex3Info { get; set; } - - public MappedState Complex4Info { get; set; } - public MappedState Complex5Info { get; set; } - - public MappedState TransactionFees { get; set; } - } + public BoolState Initialized { get; set; } + public BoolState BoolInfo { get; set; } + public Int32State Int32Info { get; set; } + public UInt32State UInt32Info { get; set; } + public Int64State Int64Info { get; set; } + public UInt64State UInt64Info { get; set; } + public StringState StringInfo { get; set; } + public BytesState BytesInfo { get; set; } + + public SingletonState Int32SingletonState { get; set; } + public SingletonState EnumState { get; set; } + + public SingletonState BytesSingletonState { get; set; } + public SingletonState ProtoInfo { get; set; } + + public SingletonState LoopInt32Value { get; set; } + public ProtobufState ProtoInfo2 { get; set; } + + public MappedState MappedState { get; set; } + public MappedState Complex3Info { get; set; } + + public MappedState Complex4Info { get; set; } + public MappedState Complex5Info { get; set; } + + public MappedState TransactionFees { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_Action.cs b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_Action.cs index 822f56d152..0896bca0ad 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_Action.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_Action.cs @@ -4,450 +4,426 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicSecurity +namespace AElf.Contracts.TestContract.BasicSecurity; + +public partial class BasicSecurityContract : BasicSecurityContractContainer.BasicSecurityContractBase { - public partial class BasicSecurityContract : BasicSecurityContractContainer.BasicSecurityContractBase - { - private const int Number = 1; - private const string String = "TEST"; - private static int _number; - private long _field1; - private string _field2; - private bool _field3; - private BasicContractTestType _basicTestType; - private InnerContractType _innerContractType; - private List _list; - - private Dictionary dict { get; set; } - - public static InnerContractType _innerContractTypeStaticField; - - public override Empty InitialBasicSecurityContract(Address input) - { - Assert(!State.Initialized.Value, "Already initialized."); - - //set basic1 contract reference - Assert(input != null, "Basic1Contract address is not exist."); - State.BasicFunctionContract.Value = input; - - State.Initialized.Value = true; - State.BoolInfo.Value = true; - State.Int32Info.Value = 0; - State.UInt32Info.Value = 0; - State.Int64Info.Value = 0; - State.UInt64Info.Value = 0; - State.StringInfo.Value = string.Empty; - State.BytesInfo.Value = new byte[] { }; - return new Empty(); - } + private const int Number = 1; + private const string String = "TEST"; + private static int _number; - public override Empty TestBoolState(BoolInput input) - { - State.BoolInfo.Value = input.BoolValue; + public static InnerContractType _innerContractTypeStaticField; + private BasicContractTestType _basicTestType; + private long _field1; + private string _field2; + private bool _field3; + private InnerContractType _innerContractType; + private List _list; - return new Empty(); - } + private Dictionary dict { get; set; } - public override Empty TestInt32State(Int32Input input) - { - State.Int32Info.Value = State.Int32Info.Value.Add(input.Int32Value); + public override Empty InitialBasicSecurityContract(Address input) + { + Assert(!State.Initialized.Value, "Already initialized."); + + //set basic1 contract reference + Assert(input != null, "Basic1Contract address is not exist."); + State.BasicFunctionContract.Value = input; + + State.Initialized.Value = true; + State.BoolInfo.Value = true; + State.Int32Info.Value = 0; + State.UInt32Info.Value = 0; + State.Int64Info.Value = 0; + State.UInt64Info.Value = 0; + State.StringInfo.Value = string.Empty; + State.BytesInfo.Value = new byte[] { }; + return new Empty(); + } - return new Empty(); - } + public override Empty TestBoolState(BoolInput input) + { + State.BoolInfo.Value = input.BoolValue; - public override Empty TestUInt32State(UInt32Input input) - { - State.UInt32Info.Value = State.UInt32Info.Value.Add(input.UInt32Value); + return new Empty(); + } - return new Empty(); - } + public override Empty TestInt32State(Int32Input input) + { + State.Int32Info.Value = State.Int32Info.Value.Add(input.Int32Value); - public override Empty TestInt64State(Int64Input input) - { - State.Int64Info.Value = State.Int64Info.Value.Add(input.Int64Value); + return new Empty(); + } - return new Empty(); - } + public override Empty TestUInt32State(UInt32Input input) + { + State.UInt32Info.Value = State.UInt32Info.Value.Add(input.UInt32Value); - public override Empty TestUInt64State(UInt64Input input) - { - State.UInt64Info.Value = State.UInt64Info.Value.Add(input.UInt64Value); + return new Empty(); + } - return new Empty(); - } + public override Empty TestInt64State(Int64Input input) + { + State.Int64Info.Value = State.Int64Info.Value.Add(input.Int64Value); - public override Empty TestStringState(StringInput input) - { - State.StringInfo.Value = input.StringValue; - return new Empty(); - } + return new Empty(); + } - public override Empty TestBytesState(BytesInput input) - { - State.BytesInfo.Value = input.BytesValue.ToByteArray(); + public override Empty TestUInt64State(UInt64Input input) + { + State.UInt64Info.Value = State.UInt64Info.Value.Add(input.UInt64Value); - return new Empty(); - } + return new Empty(); + } - public override Empty TestBytesSingletonState(BytesInput input) - { - State.BytesSingletonState.Value = input.BytesValue.ToByteArray(); + public override Empty TestStringState(StringInput input) + { + State.StringInfo.Value = input.StringValue; + return new Empty(); + } - return new Empty(); - } + public override Empty TestBytesState(BytesInput input) + { + State.BytesInfo.Value = input.BytesValue.ToByteArray(); - public override Empty TestInt32SingletonState(Int32Input input) - { - State.Int32SingletonState.Value = input.Int32Value; - return new Empty(); - } + return new Empty(); + } - public override Empty TestEnumState(Int32Input input) - { - State.EnumState.Value = (StateEnum) input.Int32Value; - return new Empty(); - } + public override Empty TestBytesSingletonState(BytesInput input) + { + State.BytesSingletonState.Value = input.BytesValue.ToByteArray(); - public override Empty TestProtobufState(ProtobufInput input) - { - State.ProtoInfo2.Value = input.ProtobufValue; + return new Empty(); + } - return new Empty(); - } + public override Empty TestInt32SingletonState(Int32Input input) + { + State.Int32SingletonState.Value = input.Int32Value; + return new Empty(); + } - public override Empty TestSingletonState(ProtobufInput input) - { - State.ProtoInfo.Value = input.ProtobufValue; + public override Empty TestEnumState(Int32Input input) + { + State.EnumState.Value = (StateEnum)input.Int32Value; + return new Empty(); + } - return new Empty(); - } + public override Empty TestProtobufState(ProtobufInput input) + { + State.ProtoInfo2.Value = input.ProtobufValue; - public override Empty TestComplex1State(Complex1Input input) - { - State.BoolInfo.Value = input.BoolValue; - State.Int32Info.Value = input.Int32Value; + return new Empty(); + } - return new Empty(); - } + public override Empty TestSingletonState(ProtobufInput input) + { + State.ProtoInfo.Value = input.ProtobufValue; - public override Empty TestComplex2State(Complex2Input input) - { - State.BoolInfo.Value = input.BoolData.BoolValue; - State.Int32Info.Value = input.Int32Data.Int32Value; + return new Empty(); + } - return new Empty(); - } + public override Empty TestComplex1State(Complex1Input input) + { + State.BoolInfo.Value = input.BoolValue; + State.Int32Info.Value = input.Int32Value; - public override Empty TestMappedState(ProtobufInput input) - { - var protobufMessage = State.MappedState[input.ProtobufValue.Int64Value]; - if (protobufMessage == null) - { - State.MappedState[input.ProtobufValue.Int64Value] = - new ProtobufMessage - { - BoolValue = true, - Int64Value = input.ProtobufValue.Int64Value, - StringValue = input.ProtobufValue.StringValue - }; - } - else - { - State.MappedState[input.ProtobufValue.Int64Value] = - new ProtobufMessage - { - BoolValue = true, - Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] - .Int64Value - .Add(input.ProtobufValue.Int64Value), - StringValue = input.ProtobufValue.StringValue - }; - } - - return new Empty(); - } + return new Empty(); + } - public override Empty TestMapped1State(ProtobufInput input) - { - var protobufMessage = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; - if (protobufMessage == null) - { - State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = - new ProtobufMessage() - { - BoolValue = true, - Int64Value = input.ProtobufValue.Int64Value, - StringValue = input.ProtobufValue.StringValue - }; - } - else - { - State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = - new ProtobufMessage - { - BoolValue = true, - Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] - .Int64Value - .Add(input.ProtobufValue.Int64Value), - StringValue = input.ProtobufValue.StringValue - }; - } - - return new Empty(); - } + public override Empty TestComplex2State(Complex2Input input) + { + State.BoolInfo.Value = input.BoolData.BoolValue; + State.Int32Info.Value = input.Int32Data.Int32Value; + + return new Empty(); + } + + public override Empty TestMappedState(ProtobufInput input) + { + var protobufMessage = State.MappedState[input.ProtobufValue.Int64Value]; + if (protobufMessage == null) + State.MappedState[input.ProtobufValue.Int64Value] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = input.ProtobufValue.Int64Value, + StringValue = input.ProtobufValue.StringValue + }; + else + State.MappedState[input.ProtobufValue.Int64Value] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] + .Int64Value + .Add(input.ProtobufValue.Int64Value), + StringValue = input.ProtobufValue.StringValue + }; + + return new Empty(); + } - public override Empty TestMapped2State(ProtobufInput input) + public override Empty TestMapped1State(ProtobufInput input) + { + var protobufMessage = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; + if (protobufMessage == null) + State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = input.ProtobufValue.Int64Value, + StringValue = input.ProtobufValue.StringValue + }; + else + State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] + .Int64Value + .Add(input.ProtobufValue.Int64Value), + StringValue = input.ProtobufValue.StringValue + }; + + return new Empty(); + } + + public override Empty TestMapped2State(ProtobufInput input) + { + var protobufMessage = + State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ + input.ProtobufValue.StringValue]; + if (protobufMessage == null) + State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ + input.ProtobufValue.StringValue] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = input.ProtobufValue.Int64Value, + StringValue = input.ProtobufValue.StringValue + }; + else + State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ + input.ProtobufValue.StringValue] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] + .Int64Value + .Add(input.ProtobufValue.Int64Value), + StringValue = input.ProtobufValue.StringValue + }; + + return new Empty(); + } + + public override Empty TestMapped3State(Complex3Input input) + { + var tradeMessage = State.Complex5Info[input.From][input.PairA][input.To][input.PairB]; + if (tradeMessage == null) { - var protobufMessage = - State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ - input.ProtobufValue.StringValue]; - if (protobufMessage == null) - { - State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ - input.ProtobufValue.StringValue] = - new ProtobufMessage - { - BoolValue = true, - Int64Value = input.ProtobufValue.Int64Value, - StringValue = input.ProtobufValue.StringValue - }; - } - else - { - State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ - input.ProtobufValue.StringValue] = - new ProtobufMessage - { - BoolValue = true, - Int64Value = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] - .Int64Value - .Add(input.ProtobufValue.Int64Value), - StringValue = input.ProtobufValue.StringValue - }; - } - - return new Empty(); + input.TradeDetails.Timestamp = Context.CurrentBlockTime; + State.Complex5Info[input.From][input.PairA][input.To][input.PairB] = input.TradeDetails; } - - public override Empty TestMapped3State(Complex3Input input) + else { - var tradeMessage = State.Complex5Info[input.From][input.PairA][input.To][input.PairB]; - if (tradeMessage == null) - { - input.TradeDetails.Timestamp = Context.CurrentBlockTime; - State.Complex5Info[input.From][input.PairA][input.To][input.PairB] = input.TradeDetails; - } - else - { - tradeMessage.FromAmount = tradeMessage.FromAmount.Add(input.TradeDetails.FromAmount); - tradeMessage.ToAmount = tradeMessage.ToAmount.Add(input.TradeDetails.ToAmount); - tradeMessage.Timestamp = Context.CurrentBlockTime; - - State.Complex5Info[input.From][input.PairA][input.To][input.PairB] = tradeMessage; - } - - return new Empty(); + tradeMessage.FromAmount = tradeMessage.FromAmount.Add(input.TradeDetails.FromAmount); + tradeMessage.ToAmount = tradeMessage.ToAmount.Add(input.TradeDetails.ToAmount); + tradeMessage.Timestamp = Context.CurrentBlockTime; + + State.Complex5Info[input.From][input.PairA][input.To][input.PairB] = tradeMessage; } - //Reference call action - public override Empty TestExecuteExternalMethod(Int64Input input) + return new Empty(); + } + + //Reference call action + public override Empty TestExecuteExternalMethod(Int64Input input) + { + var feeValue = input.Int64Value.Mul(5).Div(100); + var betValue = input.Int64Value.Sub(feeValue); + + State.Int64Info.Value.Add(feeValue); + State.BasicFunctionContract.UserPlayBet.Send(new BetInput { - var feeValue = input.Int64Value.Mul(5).Div(100); - var betValue = input.Int64Value.Sub(feeValue); + Int64Value = betValue + }); - State.Int64Info.Value.Add(feeValue); - State.BasicFunctionContract.UserPlayBet.Send(new BetInput - { - Int64Value = betValue - }); + return new Empty(); + } - return new Empty(); - } + public override Empty TestOriginAddress(Address address) + { + State.BasicFunctionContract.ValidateOrigin.Send(address); + return new Empty(); + } - public override Empty TestOriginAddress(Address address) - { - State.BasicFunctionContract.ValidateOrigin.Send(address); - return new Empty(); - } + public override Empty TestResetFields(ResetInput input) + { + _number = input.Int32Value; + _field1 = input.Int64Value; + _field2 = input.StringValue; + _field3 = input.BoolValue; + State.Int64Info.Value = Number; + State.StringInfo.Value = String; + dict = new Dictionary(); + _list = new List { 1 }; + return new Empty(); + } - public override Empty TestResetFields(ResetInput input) - { - _number = input.Int32Value; - _field1 = input.Int64Value; - _field2 = input.StringValue; - _field3 = input.BoolValue; - State.Int64Info.Value = Number; - State.StringInfo.Value = String; - dict = new Dictionary(); - _list = new List {1}; - return new Empty(); - } + public override ResetNestedOutput TestResetNestedFields(ResetNestedInput input) + { + _innerContractType = new InnerContractType(); + _innerContractType.SetValue(input.Int32Value, input.StringValue); + var number = _innerContractType.CheckNumberValue(); + var staticString = _innerContractType.CheckStaticValue(); - public override ResetNestedOutput TestResetNestedFields(ResetNestedInput input) + return new ResetNestedOutput { - _innerContractType = new InnerContractType(); - _innerContractType.SetValue(input.Int32Value, input.StringValue); - var number = _innerContractType.CheckNumberValue(); - var staticString = _innerContractType.CheckStaticValue(); - - return new ResetNestedOutput - { - Int32Value = number, - StringValue = staticString - }; - } + Int32Value = number, + StringValue = staticString + }; + } - public override ResetOtherTypeNestedOutput TestResetOtherTypeFields(ResetNestedInput input) - { - _basicTestType = new BasicContractTestType(); - _basicTestType.SetBasicContractTestType(input.Int32Value); - var s = _basicTestType.CheckFunc().Invoke(input.StringValue); - var testType = _basicTestType.CheckTypeValue(); - _basicTestType.SetStaticField(); - BasicContractTestType.BasicContractTestTypePublicStaticField = new BasicContractTestType(); - - var innerTestTypeObj = new BasicContractTestType.InnerTestType(1); - innerTestTypeObj.SetStaticField(); - BasicContractTestType.InnerTestType.InnerTestTypePublicStaticField = - new BasicContractTestType.InnerTestType(2); - - var innerContractTypeObj = new InnerContractType(); - innerContractTypeObj.SetStaticField(); - InnerContractType.InnerContractTypePublicStaticField = new InnerContractType(); - - return new ResetOtherTypeNestedOutput - { - TypeConst = testType.CheckConstNumberValue(), - TypeNumber = testType.CheckNumberValue(), - BasicTypeNumber = _basicTestType.CheckNumberValue(), - BasicTypeStaticNumber = _basicTestType.CheckStaticNumberValue(), - StringValue = s - }; - } - - public override Int32Output TestWhileInfiniteLoop(Int32Input input) - { - int i = 0; - var count = input.Int32Value; - while (i < count) - { - i++; - } - - return new Int32Output {Int32Value = i}; - } + public override ResetOtherTypeNestedOutput TestResetOtherTypeFields(ResetNestedInput input) + { + _basicTestType = new BasicContractTestType(); + _basicTestType.SetBasicContractTestType(input.Int32Value); + var s = _basicTestType.CheckFunc().Invoke(input.StringValue); + var testType = _basicTestType.CheckTypeValue(); + _basicTestType.SetStaticField(); + BasicContractTestType.BasicContractTestTypePublicStaticField = new BasicContractTestType(); + + var innerTestTypeObj = new BasicContractTestType.InnerTestType(1); + innerTestTypeObj.SetStaticField(); + BasicContractTestType.InnerTestType.InnerTestTypePublicStaticField = + new BasicContractTestType.InnerTestType(2); + + var innerContractTypeObj = new InnerContractType(); + innerContractTypeObj.SetStaticField(); + InnerContractType.InnerContractTypePublicStaticField = new InnerContractType(); + + return new ResetOtherTypeNestedOutput + { + TypeConst = testType.CheckConstNumberValue(), + TypeNumber = testType.CheckNumberValue(), + BasicTypeNumber = _basicTestType.CheckNumberValue(), + BasicTypeStaticNumber = _basicTestType.CheckStaticNumberValue(), + StringValue = s + }; + } - public override Int32Output TestWhileInfiniteLoopWithState(Int32Input input) - { - int i = 0; - var count = input.Int32Value; - while (i++ < count) - { - if (i % 7 == 0) - State.LoopInt32Value.Value = i; - } - - return new Int32Output {Int32Value = State.LoopInt32Value.Value}; - } + public override Int32Output TestWhileInfiniteLoop(Int32Input input) + { + var i = 0; + var count = input.Int32Value; + while (i < count) i++; - public override Int32Output TestForInfiniteLoop(Int32Input input) - { - int i = 0; - var count = input.Int32Value; - for (i = 0; i < count; i++) - { - } + return new Int32Output { Int32Value = i }; + } - return new Int32Output {Int32Value = i}; - } + public override Int32Output TestWhileInfiniteLoopWithState(Int32Input input) + { + var i = 0; + var count = input.Int32Value; + while (i++ < count) + if (i % 7 == 0) + State.LoopInt32Value.Value = i; - public override Int32Output TestForInfiniteLoopInSeparateClass(Int32Input input) + return new Int32Output { Int32Value = State.LoopInt32Value.Value }; + } + + public override Int32Output TestForInfiniteLoop(Int32Input input) + { + var i = 0; + var count = input.Int32Value; + for (i = 0; i < count; i++) { - SeparateClass.UseInfiniteLoopInSeparateClass(input.Int32Value); - return new Int32Output(); } - public override Int32Output TestForeachInfiniteLoop(ListInput input) - { - int i = 1; - foreach (var t in input.List) - { - i++; - } + return new Int32Output { Int32Value = i }; + } + + public override Int32Output TestForInfiniteLoopInSeparateClass(Int32Input input) + { + SeparateClass.UseInfiniteLoopInSeparateClass(input.Int32Value); + return new Int32Output(); + } + + public override Int32Output TestForeachInfiniteLoop(ListInput input) + { + var i = 1; + foreach (var t in input.List) i++; + + return new Int32Output { Int32Value = i }; + } - return new Int32Output {Int32Value = i}; + public override Empty TestInfiniteRecursiveCall(Int32Input input) + { + RecursiveCall(input.Int32Value); + return new Empty(); + } + + public override Empty TestInfiniteRecursiveCallInSeparateClass(Int32Input input) + { + SeparateClass.UseInfiniteRecursiveCallInSeparateClass(input.Int32Value); + return new Empty(); + } + + private void RecursiveCall(int value) + { + if (value > 0) + RecursiveCall(value - 1); + } + + public class InnerContractType + { + private static string _testTypeString; + + private static InnerContractType _innerContractTypePrivateStaticField; + public static InnerContractType InnerContractTypePublicStaticField; + private int _testTypeNumber; + + public void SetValue(int number, string s) + { + _testTypeNumber = number; + _testTypeString = s; } - - public override Empty TestInfiniteRecursiveCall(Int32Input input) + + public int CheckNumberValue() { - RecursiveCall(input.Int32Value); - return new Empty(); + return _testTypeNumber; } - public override Empty TestInfiniteRecursiveCallInSeparateClass(Int32Input input) + public string CheckStaticValue() { - SeparateClass.UseInfiniteRecursiveCallInSeparateClass(input.Int32Value); - return new Empty(); + return _testTypeString; } - private void RecursiveCall(int value) + public void SetStaticField() { - if (value > 0) - RecursiveCall(value - 1); + _innerContractTypePrivateStaticField = this; } - public class InnerContractType + public static bool CheckAllStaticFieldsReset() { - private int _testTypeNumber; - private static string _testTypeString; - - private static InnerContractType _innerContractTypePrivateStaticField; - public static InnerContractType InnerContractTypePublicStaticField; - - public void SetValue(int number, string s) - { - _testTypeNumber = number; - _testTypeString = s; - } - - public int CheckNumberValue() - { - return _testTypeNumber; - } - - public string CheckStaticValue() - { - return _testTypeString; - } - - public void SetStaticField() - { - _innerContractTypePrivateStaticField = this; - } - - public static bool CheckAllStaticFieldsReset() - { - return _testTypeString == null && _innerContractTypePrivateStaticField == null && - InnerContractTypePublicStaticField == null; - } + return _testTypeString == null && _innerContractTypePrivateStaticField == null && + InnerContractTypePublicStaticField == null; } } +} - class SeparateClass +internal class SeparateClass +{ + public static void UseInfiniteLoopInSeparateClass(int count) { - public static void UseInfiniteLoopInSeparateClass(int count) - { - for (int i = 0; i < count;) - { - i++; - } - } + for (var i = 0; i < count;) i++; + } - public static void UseInfiniteRecursiveCallInSeparateClass(int count) - { - if (count <= 0) - return; - UseInfiniteRecursiveCallInSeparateClass(count -1); - } + public static void UseInfiniteRecursiveCallInSeparateClass(int count) + { + if (count <= 0) + return; + UseInfiniteRecursiveCallInSeparateClass(count - 1); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_FeeProvider.cs b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_FeeProvider.cs index 11c0443ee7..6d16c0c6e3 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_FeeProvider.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_FeeProvider.cs @@ -1,33 +1,32 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicSecurity +namespace AElf.Contracts.TestContract.BasicSecurity; + +public partial class BasicSecurityContract { - public partial class BasicSecurityContract + [View] + public override MethodFees GetMethodFee(StringValue input) { - [View] - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - return methodFees; + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) + return methodFees; - //set default tx fee - return new MethodFees + //set default tx fee + return new MethodFees + { + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = - { - new MethodFee {Symbol = "ELF", BasicFee = 1000_0000} - } - }; - } + new MethodFee { Symbol = "ELF", BasicFee = 1000_0000 } + } + }; + } - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_TestType.cs b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_TestType.cs index 2fe8d24351..2fdf5de891 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_TestType.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_TestType.cs @@ -1,91 +1,90 @@ using System; -namespace AElf.Contracts.TestContract.BasicSecurity +namespace AElf.Contracts.TestContract.BasicSecurity; + +public class BasicContractTestType { - public class BasicContractTestType + private static int _testTypeStaticNumber; + private static Func _strFunc; + + private static InnerTestType _innerTypePrivateStaticField; + private static BasicContractTestType _basicContractTestTypePrivateStaticField; + public static BasicContractTestType BasicContractTestTypePublicStaticField; + private int _number = 1; + + + public void SetBasicContractTestType(int number) { - private int _number = 1; - private static int _testTypeStaticNumber; - private static Func _strFunc; + _number = number; + _testTypeStaticNumber = number; + _strFunc = s => s.ToLower(); + _innerTypePrivateStaticField = new InnerTestType(number); + } - private static InnerTestType _innerTypePrivateStaticField; - private static BasicContractTestType _basicContractTestTypePrivateStaticField; - public static BasicContractTestType BasicContractTestTypePublicStaticField; - + public int CheckNumberValue() + { + return _number; + } - public void SetBasicContractTestType(int number) - { - _number = number; - _testTypeStaticNumber = number; - _strFunc = s => s.ToLower(); - _innerTypePrivateStaticField = new InnerTestType(number); - } + public int CheckStaticNumberValue() + { + return _testTypeStaticNumber; + } - public int CheckNumberValue() - { - return _number; - } + public Func CheckFunc() + { + return _strFunc; + } - public int CheckStaticNumberValue() + public InnerTestType CheckTypeValue() + { + return _innerTypePrivateStaticField; + } + + public void SetStaticField() + { + _basicContractTestTypePrivateStaticField = this; + } + + public static bool CheckAllStaticFieldsReset() + { + return _strFunc == null && _innerTypePrivateStaticField == null && + _basicContractTestTypePrivateStaticField == null && + BasicContractTestTypePublicStaticField == null; + } + + public class InnerTestType + { + private const int TypeConstNumber = 1; + + private static InnerTestType _innerTestTypePrivateStaticField; + public static InnerTestType InnerTestTypePublicStaticField; + private readonly int _typeNumber; + + + public InnerTestType(int typeNumber) { - return _testTypeStaticNumber; + _typeNumber = typeNumber; } - public Func CheckFunc() + public int CheckNumberValue() { - return _strFunc; + return _typeNumber; } - public InnerTestType CheckTypeValue() + public int CheckConstNumberValue() { - return _innerTypePrivateStaticField; + return TypeConstNumber; } public void SetStaticField() { - _basicContractTestTypePrivateStaticField = this; - } - - public static bool CheckAllStaticFieldsReset() - { - return _strFunc == null && _innerTypePrivateStaticField == null && - _basicContractTestTypePrivateStaticField == null && - BasicContractTestTypePublicStaticField == null; + _innerTestTypePrivateStaticField = this; } - public class InnerTestType + public static bool CheckInnerTypeStaticFieldsReset() { - private readonly int _typeNumber; - private const int TypeConstNumber = 1; - - private static InnerTestType _innerTestTypePrivateStaticField; - public static InnerTestType InnerTestTypePublicStaticField; - - - public InnerTestType(int typeNumber) - { - _typeNumber = typeNumber; - } - - public int CheckNumberValue() - { - return _typeNumber; - } - - public int CheckConstNumberValue() - { - return TypeConstNumber; - } - - public void SetStaticField() - { - _innerTestTypePrivateStaticField = this; - } - - public static bool CheckInnerTypeStaticFieldsReset() - { - return _innerTestTypePrivateStaticField == null && InnerTestTypePublicStaticField == null; - } + return _innerTestTypePrivateStaticField == null && InnerTestTypePublicStaticField == null; } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_View.cs b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_View.cs index 8165fd1a91..3d387635f7 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_View.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/BasicContract_View.cs @@ -3,220 +3,219 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicSecurity +namespace AElf.Contracts.TestContract.BasicSecurity; + +public partial class BasicSecurityContract { - public partial class BasicSecurityContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(BasicSecurityContract) - }; - } + Value = nameof(BasicSecurityContract) + }; + } - public override BoolOutput QueryBoolState(Empty input) + public override BoolOutput QueryBoolState(Empty input) + { + return new BoolOutput { - return new BoolOutput - { - BoolValue = State.BoolInfo.Value - }; - } + BoolValue = State.BoolInfo.Value + }; + } - public override BytesOutput QueryBytesState(Empty input) + public override BytesOutput QueryBytesState(Empty input) + { + return new BytesOutput { - return new BytesOutput - { - BytesValue = ByteString.CopyFrom(State.BytesInfo.Value) - }; - } + BytesValue = ByteString.CopyFrom(State.BytesInfo.Value) + }; + } - public override BytesOutput QueryBytesSingletonState(Empty input) + public override BytesOutput QueryBytesSingletonState(Empty input) + { + return new BytesOutput { - return new BytesOutput - { - BytesValue = ByteString.CopyFrom(State.BytesSingletonState.Value) - }; - } - - public override Int32Output QueryInt32SingletonState(Empty input) + BytesValue = ByteString.CopyFrom(State.BytesSingletonState.Value) + }; + } + + public override Int32Output QueryInt32SingletonState(Empty input) + { + return new Int32Output { - return new Int32Output - { - Int32Value = State.Int32SingletonState.Value - }; - } + Int32Value = State.Int32SingletonState.Value + }; + } - public override Int32Value QueryEnumState(Empty input) + public override Int32Value QueryEnumState(Empty input) + { + return new Int32Value { - return new Int32Value - { - Value = (int) State.EnumState.Value - }; - } + Value = (int)State.EnumState.Value + }; + } - public override Int32Output QueryInt32State(Empty input) + public override Int32Output QueryInt32State(Empty input) + { + return new Int32Output { - return new Int32Output - { - Int32Value = State.Int32Info.Value - }; - } + Int32Value = State.Int32Info.Value + }; + } - public override Int64Output QueryInt64State(Empty input) + public override Int64Output QueryInt64State(Empty input) + { + return new Int64Output { - return new Int64Output - { - Int64Value = State.Int64Info.Value - }; - } + Int64Value = State.Int64Info.Value + }; + } - public override StringOutput QueryStringState(Empty input) + public override StringOutput QueryStringState(Empty input) + { + return new StringOutput { - return new StringOutput - { - StringValue = State.StringInfo.Value - }; - } + StringValue = State.StringInfo.Value + }; + } - public override Complex1Output QueryComplex1State(Empty input) + public override Complex1Output QueryComplex1State(Empty input) + { + return new Complex1Output { - return new Complex1Output - { - BoolValue = State.BoolInfo.Value, - Int32Value = State.Int32Info.Value - }; - } + BoolValue = State.BoolInfo.Value, + Int32Value = State.Int32Info.Value + }; + } - public override Complex2Output QueryComplex2State(Empty input) + public override Complex2Output QueryComplex2State(Empty input) + { + return new Complex2Output { - return new Complex2Output + BoolData = new BoolOutput { - BoolData = new BoolOutput - { - BoolValue = State.BoolInfo.Value - }, - Int32Data = new Int32Output - { - Int32Value = State.Int32Info.Value - } - }; - } - - public override ProtobufOutput QueryProtobufState(Empty input) - { - return new ProtobufOutput + BoolValue = State.BoolInfo.Value + }, + Int32Data = new Int32Output { - ProtobufValue = State.ProtoInfo2.Value - }; - } + Int32Value = State.Int32Info.Value + } + }; + } - public override UInt32Output QueryUInt32State(Empty input) + public override ProtobufOutput QueryProtobufState(Empty input) + { + return new ProtobufOutput { - return new UInt32Output - { - UInt32Value = State.UInt32Info.Value - }; - } + ProtobufValue = State.ProtoInfo2.Value + }; + } - public override UInt64Output QueryUInt64State(Empty input) + public override UInt32Output QueryUInt32State(Empty input) + { + return new UInt32Output { - return new UInt64Output - { - UInt64Value = State.UInt64Info.Value - }; - } + UInt32Value = State.UInt32Info.Value + }; + } - public override ProtobufMessage QueryMappedState(ProtobufInput input) + public override UInt64Output QueryUInt64State(Empty input) + { + return new UInt64Output { - var message = State.MappedState[input.ProtobufValue.Int64Value]; - return message ?? new ProtobufMessage(); - } + UInt64Value = State.UInt64Info.Value + }; + } - public override ProtobufMessage QueryMappedState1(ProtobufInput input) - { - var result = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; - return result ?? new ProtobufMessage(); - } + public override ProtobufMessage QueryMappedState(ProtobufInput input) + { + var message = State.MappedState[input.ProtobufValue.Int64Value]; + return message ?? new ProtobufMessage(); + } - public override ProtobufMessage QueryMappedState2(ProtobufInput input) - { - var message = State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ - input.ProtobufValue.StringValue]; - - return message ?? new ProtobufMessage(); - } + public override ProtobufMessage QueryMappedState1(ProtobufInput input) + { + var result = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; + return result ?? new ProtobufMessage(); + } - public override TradeMessage QueryMappedState3(Complex3Input input) - { - var tradeMessage = State.Complex5Info[input.From][input.PairA][input.To][input.PairB]; - return tradeMessage ?? new TradeMessage(); - } + public override ProtobufMessage QueryMappedState2(ProtobufInput input) + { + var message = State.Complex4Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue][ + input.ProtobufValue.StringValue]; - public override Int64Output QueryExternalMethod1(Address input) - { - var data = State.BasicFunctionContract.QueryUserWinMoney.Call(input); + return message ?? new ProtobufMessage(); + } - return new Int64Output - { - Int64Value = data.Int64Value - }; - } + public override TradeMessage QueryMappedState3(Complex3Input input) + { + var tradeMessage = State.Complex5Info[input.From][input.PairA][input.To][input.PairB]; + return tradeMessage ?? new TradeMessage(); + } + + public override Int64Output QueryExternalMethod1(Address input) + { + var data = State.BasicFunctionContract.QueryUserWinMoney.Call(input); - public override Int64Output QueryExternalMethod2(Address input) + return new Int64Output { - var data = State.BasicFunctionContract.QueryUserLoseMoney.Call(input); + Int64Value = data.Int64Value + }; + } - return new Int64Output - { - Int64Value = data.Int64Value - }; - } + public override Int64Output QueryExternalMethod2(Address input) + { + var data = State.BasicFunctionContract.QueryUserLoseMoney.Call(input); - public override ResetOutput QueryFields(Empty input) + return new Int64Output { - return new ResetOutput - { - Int32Value = _number, - Int64Value = _field1, - StringValue = _field2 ?? string.Empty, - BoolValue = _field3, - List = {_list ?? new List()} - }; - } + Int64Value = data.Int64Value + }; + } - public override ConstOutput QueryConst(Empty input) - { - return new ConstOutput - { - Int64Const = Number, - StringConst = String - }; - } + public override ResetOutput QueryFields(Empty input) + { + return new ResetOutput + { + Int32Value = _number, + Int64Value = _field1, + StringValue = _field2 ?? string.Empty, + BoolValue = _field3, + List = { _list ?? new List() } + }; + } - public override ResetNestedOutput QueryNestedFields(Empty input) + public override ConstOutput QueryConst(Empty input) + { + return new ConstOutput { - _innerContractType = new InnerContractType(); - return new ResetNestedOutput - { - Int32Value = _innerContractType.CheckNumberValue(), - StringValue = _innerContractType.CheckStaticValue() ?? string.Empty - }; - } + Int64Const = Number, + StringConst = String + }; + } - public override BoolValue CheckNonContractTypesStaticFieldsReset(Empty input) + public override ResetNestedOutput QueryNestedFields(Empty input) + { + _innerContractType = new InnerContractType(); + return new ResetNestedOutput { - var res = InnerContractType.CheckAllStaticFieldsReset() - && BasicContractTestType.CheckAllStaticFieldsReset() - && BasicContractTestType.InnerTestType.CheckInnerTypeStaticFieldsReset(); - return new BoolValue {Value = res}; - } + Int32Value = _innerContractType.CheckNumberValue(), + StringValue = _innerContractType.CheckStaticValue() ?? string.Empty + }; + } - public override BoolValue CheckFieldsAlreadyReset(Empty input) - { - var res = _field1 == 0 && _field2 == null && _field3 == false && _basicTestType == null && - _innerContractType == null && dict == null; - return new BoolValue {Value = res}; - } + public override BoolValue CheckNonContractTypesStaticFieldsReset(Empty input) + { + var res = InnerContractType.CheckAllStaticFieldsReset() + && BasicContractTestType.CheckAllStaticFieldsReset() + && BasicContractTestType.InnerTestType.CheckInnerTypeStaticFieldsReset(); + return new BoolValue { Value = res }; + } + + public override BoolValue CheckFieldsAlreadyReset(Empty input) + { + var res = _field1 == 0 && _field2 == null && _field3 == false && _basicTestType == null && + _innerContractType == null && dict == null; + return new BoolValue { Value = res }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicSecurity/ContractReference.cs b/test/AElf.Contracts.TestContract.BasicSecurity/ContractReference.cs index a3923fed4c..5f304dbd2c 100644 --- a/test/AElf.Contracts.TestContract.BasicSecurity/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.BasicSecurity/ContractReference.cs @@ -1,8 +1,8 @@ using AElf.Contracts.TestContract.BasicFunction; -namespace AElf.Contracts.TestContract.BasicSecurity +namespace AElf.Contracts.TestContract.BasicSecurity; + +public partial class BasicSecurityContractState { - public partial class BasicSecurityContractState { - internal BasicFunctionContractContainer.BasicFunctionContractReferenceState BasicFunctionContract { get; set; } - } + internal BasicFunctionContractContainer.BasicFunctionContractReferenceState BasicFunctionContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicUpdate/AElf.Contracts.TestContract.BasicUpdate.csproj b/test/AElf.Contracts.TestContract.BasicUpdate/AElf.Contracts.TestContract.BasicUpdate.csproj index 2ff61aa610..c24d85579b 100644 --- a/test/AElf.Contracts.TestContract.BasicUpdate/AElf.Contracts.TestContract.BasicUpdate.csproj +++ b/test/AElf.Contracts.TestContract.BasicUpdate/AElf.Contracts.TestContract.BasicUpdate.csproj @@ -6,17 +6,17 @@ - true + true - true + true - + - + Protobuf\Proto\authority_info.proto diff --git a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContractState.cs b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContractState.cs index e52eccc24c..a4eaeb0555 100644 --- a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContractState.cs +++ b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContractState.cs @@ -1,24 +1,23 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.TestContract.BasicUpdate +namespace AElf.Contracts.TestContract.BasicUpdate; + +public class BasicUpdateContractState : ContractState { - public class BasicUpdateContractState : ContractState - { - public BoolState Initialized { get; set; } - public StringState ContractName { get; set; } - public ProtobufState
ContractManager { get; set; } - public Int64State MinBet { get; set; } - public Int64State MaxBet { get; set; } - - public Int64State MortgageBalance { get; set; } - public Int64State TotalBetBalance { get; set; } - public Int64State RewardBalance { get; set; } - - public MappedState WinerHistory { get; set; } - public MappedState LoserHistory { get; set; } - - public MappedState TransactionFees { get; set; } - } + public BoolState Initialized { get; set; } + public StringState ContractName { get; set; } + public ProtobufState
ContractManager { get; set; } + public Int64State MinBet { get; set; } + public Int64State MaxBet { get; set; } + + public Int64State MortgageBalance { get; set; } + public Int64State TotalBetBalance { get; set; } + public Int64State RewardBalance { get; set; } + + public MappedState WinerHistory { get; set; } + public MappedState LoserHistory { get; set; } + + public MappedState TransactionFees { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_Action.cs b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_Action.cs index 423aed69d7..3d04b18408 100644 --- a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_Action.cs +++ b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_Action.cs @@ -1,95 +1,93 @@ using AElf.CSharp.Core; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicUpdate +namespace AElf.Contracts.TestContract.BasicUpdate; + +/// +/// Action methods +/// +public partial class BasicUpdateContract : BasicUpdateContractContainer.BasicUpdateContractBase { - /// - /// Action methods - /// - public partial class BasicUpdateContract : BasicUpdateContractContainer.BasicUpdateContractBase + public override Empty InitialBasicUpdateContract(InitialBasicContractInput input) { - public override Empty InitialBasicUpdateContract(InitialBasicContractInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); - Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, - "Invalid min/max value input setting."); - - State.Initialized.Value = true; - State.ContractName.Value = input.ContractName; - State.ContractManager.Value = input.Manager; - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; - State.MortgageBalance.Value = input.MortgageValue; - - return new Empty(); - } + Assert(!State.Initialized.Value, "Already initialized."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); + + State.Initialized.Value = true; + State.ContractName.Value = input.ContractName; + State.ContractManager.Value = input.Manager; + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; + State.MortgageBalance.Value = input.MortgageValue; + + return new Empty(); + } - public override Empty UpdateBetLimit(BetLimitInput input) - { - Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); - Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, - "Invalid min/max value input setting."); + public override Empty UpdateBetLimit(BetLimitInput input) + { + Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); + Assert(input.MinValue > 0 && input.MaxValue > 0 && input.MaxValue >= input.MinValue, + "Invalid min/max value input setting."); - State.MinBet.Value = input.MinValue; - State.MaxBet.Value = input.MaxValue; + State.MinBet.Value = input.MinValue; + State.MaxBet.Value = input.MaxValue; - return new Empty(); - } + return new Empty(); + } + + public override Empty UserPlayBet(BetInput input) + { + Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <= State.MaxBet.Value, + $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); + //Assert(input.Int64Value > State.WinerHistory[Context.Sender]); - public override Empty UserPlayBet(BetInput input) + var result = WinOrLose(input.Int64Value); + State.LoserHistory[Context.Sender] += input.Int64Value; + + if (result == 0) { - Assert(input.Int64Value >= State.MinBet.Value && input.Int64Value <= State.MaxBet.Value, - $"Input balance not in boundary({State.MinBet.Value}, {State.MaxBet.Value})."); - //Assert(input.Int64Value > State.WinerHistory[Context.Sender]); - - var result = WinOrLose(input.Int64Value); - State.LoserHistory[Context.Sender] += input.Int64Value; - - if (result == 0) - { - State.TotalBetBalance.Value += input.Int64Value; - State.LoserHistory[Context.Sender] += result; - } - else - { - State.RewardBalance.Value += result; - State.WinerHistory[Context.Sender] += result; - } - - return new Empty(); + State.TotalBetBalance.Value += input.Int64Value; + State.LoserHistory[Context.Sender] += result; } - - public override Empty UpdateMortgage(BetInput input) + else { - Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); - Assert(input.Int64Value > 0, "Update mortgage value should be more than 0."); + State.RewardBalance.Value += result; + State.WinerHistory[Context.Sender] += result; + } - State.MortgageBalance.Value += input.Int64Value; + return new Empty(); + } - return new Empty(); - } + public override Empty UpdateMortgage(BetInput input) + { + Assert(Context.Sender == State.ContractManager.Value, "Only manager can perform this action."); + Assert(input.Int64Value > 0, "Update mortgage value should be more than 0."); - public override Empty UpdateStopBet(Empty input) - { - Assert(Context.Sender != State.ContractManager.Value, "Only manager can perform this action."); - State.MinBet.Value = 0; - State.MaxBet.Value = 0; + State.MortgageBalance.Value += input.Int64Value; - return new Empty(); - } + return new Empty(); + } - private long WinOrLose(long betAmount) - { - var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); - if (data < 0) - data = data.Mul(-1); - - if (data % 100 == 1) - return betAmount.Mul(1000); - if (data % 50 == 5) - return betAmount.Mul(50); - return 0; - } + public override Empty UpdateStopBet(Empty input) + { + Assert(Context.Sender != State.ContractManager.Value, "Only manager can perform this action."); + State.MinBet.Value = 0; + State.MaxBet.Value = 0; + + return new Empty(); + } + + private long WinOrLose(long betAmount) + { + var data = State.TotalBetBalance.Value.Sub(State.RewardBalance.Value); + if (data < 0) + data = data.Mul(-1); + + if (data % 100 == 1) + return betAmount.Mul(1000); + if (data % 50 == 5) + return betAmount.Mul(50); + return 0; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_FeeProvider.cs b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_FeeProvider.cs index 01f6365cf0..8e62a94def 100644 --- a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_FeeProvider.cs +++ b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_FeeProvider.cs @@ -1,33 +1,32 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicUpdate +namespace AElf.Contracts.TestContract.BasicUpdate; + +public partial class BasicUpdateContract { - public partial class BasicUpdateContract + [View] + public override MethodFees GetMethodFee(StringValue input) { - [View] - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - return methodFees; + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) + return methodFees; - //set default tx fee - return new MethodFees + //set default tx fee + return new MethodFees + { + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = - { - new MethodFee {Symbol = "ELF", BasicFee = 1000_0000} - } - }; - } + new MethodFee { Symbol = "ELF", BasicFee = 1000_0000 } + } + }; + } - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_View.cs b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_View.cs index b76db64f42..450a6b9031 100644 --- a/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_View.cs +++ b/test/AElf.Contracts.TestContract.BasicUpdate/BasicContract_View.cs @@ -1,60 +1,58 @@ -using System; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BasicUpdate +namespace AElf.Contracts.TestContract.BasicUpdate; + +/// +/// View methods +/// +public partial class BasicUpdateContract { - /// - /// View methods - /// - public partial class BasicUpdateContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(BasicUpdateContract) - }; - } + Value = nameof(BasicUpdateContract) + }; + } - public override MoneyOutput QueryWinMoney(Empty input) + public override MoneyOutput QueryWinMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.TotalBetBalance.Value - }; - } + Int64Value = State.TotalBetBalance.Value + }; + } - public override MoneyOutput QueryRewardMoney(Empty input) + public override MoneyOutput QueryRewardMoney(Empty input) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.RewardBalance.Value - }; - } + Int64Value = State.RewardBalance.Value + }; + } - public override MoneyOutput QueryUserWinMoney(Address address) + public override MoneyOutput QueryUserWinMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.WinerHistory[address] - }; - } + Int64Value = State.WinerHistory[address] + }; + } - public override MoneyOutput QueryUserLoseMoney(Address address) + public override MoneyOutput QueryUserLoseMoney(Address address) + { + return new MoneyOutput { - return new MoneyOutput - { - Int64Value = State.LoserHistory[address] - }; - } + Int64Value = State.LoserHistory[address] + }; + } - public override BetStatus QueryBetStatus(Empty input) + public override BetStatus QueryBetStatus(Empty input) + { + return new BetStatus { - return new BetStatus - { - BoolValue = (State.MinBet.Value == 0 && State.MaxBet.Value == 0) - }; - } + BoolValue = State.MinBet.Value == 0 && State.MaxBet.Value == 0 + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BigIntValue/AElf.Contracts.TestContract.BigIntValue.csproj b/test/AElf.Contracts.TestContract.BigIntValue/AElf.Contracts.TestContract.BigIntValue.csproj index 08995792a1..0de8c68964 100644 --- a/test/AElf.Contracts.TestContract.BigIntValue/AElf.Contracts.TestContract.BigIntValue.csproj +++ b/test/AElf.Contracts.TestContract.BigIntValue/AElf.Contracts.TestContract.BigIntValue.csproj @@ -15,7 +15,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContract.cs b/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContract.cs index eccff860c7..d06a7a2630 100644 --- a/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContract.cs +++ b/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContract.cs @@ -1,43 +1,42 @@ using AElf.CSharp.Core; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.BigIntValue +namespace AElf.Contracts.TestContract.BigIntValue; + +public class BigIntValueContract : BigIntValueContractContainer.BigIntValueContractBase { - public class BigIntValueContract : BigIntValueContractContainer.BigIntValueContractBase + public override Empty Add(BigIntValueInput input) { - public override Empty Add(BigIntValueInput input) - { - State.BigIntState.Value = input.Foo.Add(input.Bar); - return new Empty(); - } + State.BigIntState.Value = input.Foo.Add(input.Bar); + return new Empty(); + } - public override Empty Sub(BigIntValueInput input) - { - State.BigIntState.Value = input.Foo.Sub(input.Bar); - return new Empty(); - } + public override Empty Sub(BigIntValueInput input) + { + State.BigIntState.Value = input.Foo.Sub(input.Bar); + return new Empty(); + } - public override Empty Mul(BigIntValueInput input) - { - State.BigIntState.Value = input.Foo.Mul(input.Bar); - return new Empty(); - } + public override Empty Mul(BigIntValueInput input) + { + State.BigIntState.Value = input.Foo.Mul(input.Bar); + return new Empty(); + } - public override Empty Div(BigIntValueInput input) - { - State.BigIntState.Value = input.Foo.Div(input.Bar); - return new Empty(); - } + public override Empty Div(BigIntValueInput input) + { + State.BigIntState.Value = input.Foo.Div(input.Bar); + return new Empty(); + } - public override Empty Pow(BigIntValuePowInput input) - { - State.BigIntState.Value = input.Value.Pow(input.Exponent); - return new Empty(); - } + public override Empty Pow(BigIntValuePowInput input) + { + State.BigIntState.Value = input.Value.Pow(input.Exponent); + return new Empty(); + } - public override Types.BigIntValue Get(Empty input) - { - return State.BigIntState.Value; - } + public override Types.BigIntValue Get(Empty input) + { + return State.BigIntState.Value; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContractState.cs b/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContractState.cs index 186146882e..3023326ede 100644 --- a/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContractState.cs +++ b/test/AElf.Contracts.TestContract.BigIntValue/BigIntValueContractState.cs @@ -1,9 +1,8 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Contracts.TestContract.BigIntValue +namespace AElf.Contracts.TestContract.BigIntValue; + +public class BigIntValueContractState : ContractState { - public class BigIntValueContractState : ContractState - { - public SingletonState BigIntState { get; set; } - } + public SingletonState BigIntState { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.C/AElf.Contracts.TestContract.C.csproj b/test/AElf.Contracts.TestContract.C/AElf.Contracts.TestContract.C.csproj index 0d424ad8ab..9c006d0980 100644 --- a/test/AElf.Contracts.TestContract.C/AElf.Contracts.TestContract.C.csproj +++ b/test/AElf.Contracts.TestContract.C/AElf.Contracts.TestContract.C.csproj @@ -9,7 +9,7 @@ - + @@ -17,7 +17,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\test_a_contract.proto diff --git a/test/AElf.Contracts.TestContract.C/ContractC.cs b/test/AElf.Contracts.TestContract.C/ContractC.cs index 270564d135..0d1f1d9027 100644 --- a/test/AElf.Contracts.TestContract.C/ContractC.cs +++ b/test/AElf.Contracts.TestContract.C/ContractC.cs @@ -1,107 +1,108 @@ -using AElf.Standards.ACS1; -using AElf.Sdk.CSharp; +using AElf.Sdk.CSharp; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.C +namespace AElf.Contracts.TestContract.C; + +public class CContract : CContractContainer.CContractBase { - public class CContract : CContractContainer.CContractBase + private static string ConcatMsg(StringValue input) { - #region Action - public override Empty InitializeC(Address input) - { - State.CState = new MappedState(); - State.AContract.Value = input; + return AElfString.Concat("C", input.Value); + } + + #region Action + + public override Empty InitializeC(Address input) + { + State.CState = new MappedState(); + State.AContract.Value = input; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteCC(StringValue input) + public override Empty ExecuteCC(StringValue input) + { + State.CState[Context.Sender] = new StringValue { - State.CState[Context.Sender] = new StringValue - { - Value = ConcatMsg(input) - }; + Value = ConcatMsg(input) + }; - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteCA(StringValue input) + public override Empty ExecuteCA(StringValue input) + { + State.AContract.ExecuteAA.Send(new StringValue { - State.AContract.ExecuteAA.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteCB(StringValue input) + public override Empty ExecuteCB(StringValue input) + { + State.AContract.ExecuteAB.Send(new StringValue { - State.AContract.ExecuteAB.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override Empty ExecuteLoopABC(StringValue input) + public override Empty ExecuteLoopABC(StringValue input) + { + State.AContract.ExecuteLoopABC.Send(new StringValue { - State.AContract.ExecuteLoopABC.Send(new StringValue - { - Value = ConcatMsg(input) - }); + Value = ConcatMsg(input) + }); - return new Empty(); - } + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) + public override MethodFees GetMethodFee(StringValue input) + { + return new MethodFees { - return new MethodFees + Fees = { - Fees = - { - new MethodFee - {Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000} //default 0.1 native symbol - } - }; - } - - public override Empty SetMethodFee(MethodFees input) - { - return new Empty(); - } - - #endregion - - #region View - - public override StringValue CallCC(Address input) - { - return State.CState[input] ?? new StringValue(); - } + new MethodFee + { Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000 } //default 0.1 native symbol + } + }; + } - public override StringValue CallCA(Address input) - { - return State.AContract.CallAA.Call(input); - } + public override Empty SetMethodFee(MethodFees input) + { + return new Empty(); + } - public override StringValue CallCB(Address input) - { - return State.AContract.CallAB.Call(input); - } + #endregion - public override StringValue CallLoopABC(Address input) - { - return State.AContract.CallLoopABC.Call(input); - } + #region View - #endregion - private static string ConcatMsg(StringValue input) - { - return AElfString.Concat("C", input.Value); - } + public override StringValue CallCC(Address input) + { + return State.CState[input] ?? new StringValue(); } + + public override StringValue CallCA(Address input) + { + return State.AContract.CallAA.Call(input); + } + + public override StringValue CallCB(Address input) + { + return State.AContract.CallAB.Call(input); + } + + public override StringValue CallLoopABC(Address input) + { + return State.AContract.CallLoopABC.Call(input); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.C/ContractReference.cs b/test/AElf.Contracts.TestContract.C/ContractReference.cs index b5b66b6588..09a5ea1bc5 100644 --- a/test/AElf.Contracts.TestContract.C/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.C/ContractReference.cs @@ -3,11 +3,10 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.C +namespace AElf.Contracts.TestContract.C; + +public class CContractState : ContractState { - public class CContractState : ContractState - { - public MappedState CState { get; set; } - internal AContractContainer.AContractReferenceState AContract { get; set; } - } + public MappedState CState { get; set; } + internal AContractContainer.AContractReferenceState AContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.DApp/AElf.Contracts.TestContract.DApp.csproj b/test/AElf.Contracts.TestContract.DApp/AElf.Contracts.TestContract.DApp.csproj index b56f3c5c82..055e91deb0 100644 --- a/test/AElf.Contracts.TestContract.DApp/AElf.Contracts.TestContract.DApp.csproj +++ b/test/AElf.Contracts.TestContract.DApp/AElf.Contracts.TestContract.DApp.csproj @@ -9,11 +9,11 @@ - true + true - + @@ -21,7 +21,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\token_holder_contract.proto diff --git a/test/AElf.Contracts.TestContract.DApp/DAppConstants.cs b/test/AElf.Contracts.TestContract.DApp/DAppConstants.cs index eea8ce45f7..07fc5b2625 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppConstants.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppConstants.cs @@ -1,10 +1,9 @@ -namespace AElf.Contracts.TestContract.DApp +namespace AElf.Contracts.TestContract.DApp; + +public static class DAppConstants { - public static class DAppConstants - { - public const long TotalSupply = 1_000_000_000_00000000; - public const int Decimal = 8; - public const long ForNewUser = 10_00000000; - public const long UseFee = 3000_0000; - } + public const long TotalSupply = 1_000_000_000_00000000; + public const int Decimal = 8; + public const long ForNewUser = 10_00000000; + public const long UseFee = 3000_0000; } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.DApp/DAppContract.cs b/test/AElf.Contracts.TestContract.DApp/DAppContract.cs index ec801a9f22..cc367411f6 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppContract.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppContract.cs @@ -1,233 +1,232 @@ using System.Collections.Generic; -using AElf.Standards.ACS9; using AElf.Contracts.MultiToken; using AElf.Contracts.TokenHolder; using AElf.CSharp.Core; using AElf.Sdk.CSharp; +using AElf.Standards.ACS9; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.DApp +namespace AElf.Contracts.TestContract.DApp; + +public partial class DAppContract : DAppContainer.DAppBase { - public partial class DAppContract : DAppContainer.DAppBase + //just for unit cases + public override Empty InitializeForUnitTest(InitializeInput input) { - //just for unit cases - public override Empty InitializeForUnitTest(InitializeInput input) - { - State.TokenHolderContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.DividendPoolContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - State.Symbol.Value = input.Symbol == string.Empty ? "APP" : input.Symbol; - State.ProfitReceiver.Value = input.ProfitReceiver; - - CreateToken(input.ProfitReceiver,true); - // To test TokenHolder Contract. - CreateTokenHolderProfitScheme(); - // To test ACS9 workflow. - SetProfitConfig(); - State.ProfitReceiver.Value = input.ProfitReceiver; - return new Empty(); - } - - public override Empty Initialize(InitializeInput input) - { - State.TokenHolderContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.DividendPoolContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - State.Symbol.Value = input.Symbol == string.Empty ? "APP" : input.Symbol; - State.ProfitReceiver.Value = input.ProfitReceiver; - - CreateToken(input.ProfitReceiver); - CreateTokenHolderProfitScheme(); - SetProfitConfig(); - State.ProfitReceiver.Value = input.ProfitReceiver; - return new Empty(); - } - - /// - /// When user sign up, give him 10 APP tokens, then initialize his profile. - /// - /// - /// - public override Empty SignUp(Empty input) - { - Assert(State.Profiles[Context.Sender] == null, "Already registered."); - var profile = new Profile - { - UserAddress = Context.Sender - }; - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = State.Symbol.Value, - Amount = DAppConstants.ForNewUser, - To = Context.Sender - }); + State.TokenHolderContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.DividendPoolContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + State.Symbol.Value = input.Symbol == string.Empty ? "APP" : input.Symbol; + State.ProfitReceiver.Value = input.ProfitReceiver; + + CreateToken(input.ProfitReceiver, true); + // To test TokenHolder Contract. + CreateTokenHolderProfitScheme(); + // To test ACS9 workflow. + SetProfitConfig(); + State.ProfitReceiver.Value = input.ProfitReceiver; + return new Empty(); + } - // Update profile. - profile.Records.Add(new Record - { - Type = RecordType.SignUp, - Timestamp = Context.CurrentBlockTime, - Description = $"{State.Symbol.Value} +{DAppConstants.ForNewUser}" - }); - State.Profiles[Context.Sender] = profile; + public override Empty Initialize(InitializeInput input) + { + State.TokenHolderContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName); + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.DividendPoolContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); + State.Symbol.Value = input.Symbol == string.Empty ? "APP" : input.Symbol; + State.ProfitReceiver.Value = input.ProfitReceiver; + + CreateToken(input.ProfitReceiver); + CreateTokenHolderProfitScheme(); + SetProfitConfig(); + State.ProfitReceiver.Value = input.ProfitReceiver; + return new Empty(); + } - return new Empty(); - } + /// + /// When user sign up, give him 10 APP tokens, then initialize his profile. + /// + /// + /// + public override Empty SignUp(Empty input) + { + Assert(State.Profiles[Context.Sender] == null, "Already registered."); + var profile = new Profile + { + UserAddress = Context.Sender + }; + State.TokenContract.Issue.Send(new IssueInput + { + Symbol = State.Symbol.Value, + Amount = DAppConstants.ForNewUser, + To = Context.Sender + }); - public override Empty Deposit(DepositInput input) + // Update profile. + profile.Records.Add(new Record { - // User Address -> DApp Contract. - State.TokenContract.TransferToContract.Send(new TransferToContractInput - { - Symbol = "ELF", - Amount = input.Amount - }); + Type = RecordType.SignUp, + Timestamp = Context.CurrentBlockTime, + Description = $"{State.Symbol.Value} +{DAppConstants.ForNewUser}" + }); + State.Profiles[Context.Sender] = profile; - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = State.Symbol.Value, - Amount = input.Amount, - To = Context.Sender - }); - - // Update profile. - var profile = State.Profiles[Context.Sender]; - profile.Records.Add(new Record - { - Type = RecordType.Deposit, - Timestamp = Context.CurrentBlockTime, - Description = $"{State.Symbol.Value} +{input.Amount}" - }); - State.Profiles[Context.Sender] = profile; + return new Empty(); + } - return new Empty(); - } + public override Empty Deposit(DepositInput input) + { + // User Address -> DApp Contract. + State.TokenContract.TransferToContract.Send(new TransferToContractInput + { + Symbol = "ELF", + Amount = input.Amount + }); - public override Empty Withdraw(WithdrawInput input) + State.TokenContract.Issue.Send(new IssueInput { - State.TokenContract.TransferToContract.Send(new TransferToContractInput - { - Symbol = State.Symbol.Value, - Amount = input.Amount - }); + Symbol = State.Symbol.Value, + Amount = input.Amount, + To = Context.Sender + }); + + // Update profile. + var profile = State.Profiles[Context.Sender]; + profile.Records.Add(new Record + { + Type = RecordType.Deposit, + Timestamp = Context.CurrentBlockTime, + Description = $"{State.Symbol.Value} +{input.Amount}" + }); + State.Profiles[Context.Sender] = profile; - State.TokenContract.Transfer.Send(new TransferInput - { - To = Context.Sender, - Symbol = input.Symbol, - Amount = input.Amount - }); + return new Empty(); + } - State.TokenHolderContract.RemoveBeneficiary.Send(new RemoveTokenHolderBeneficiaryInput - { - Beneficiary = Context.Sender, - Amount = input.Amount - }); + public override Empty Withdraw(WithdrawInput input) + { + State.TokenContract.TransferToContract.Send(new TransferToContractInput + { + Symbol = State.Symbol.Value, + Amount = input.Amount + }); - // Update profile. - var profile = State.Profiles[Context.Sender]; - profile.Records.Add(new Record - { - Type = RecordType.Withdraw, - Timestamp = Context.CurrentBlockTime, - Description = $"{State.Symbol.Value} -{input.Amount}" - }); - State.Profiles[Context.Sender] = profile; + State.TokenContract.Transfer.Send(new TransferInput + { + To = Context.Sender, + Symbol = input.Symbol, + Amount = input.Amount + }); - return new Empty(); - } + State.TokenHolderContract.RemoveBeneficiary.Send(new RemoveTokenHolderBeneficiaryInput + { + Beneficiary = Context.Sender, + Amount = input.Amount + }); - public override Empty Use(Record input) + // Update profile. + var profile = State.Profiles[Context.Sender]; + profile.Records.Add(new Record { - State.TokenContract.TransferToContract.Send(new TransferToContractInput - { - Symbol = State.Symbol.Value, - Amount = DAppConstants.UseFee - }); - if (input.Symbol == string.Empty) - input.Symbol = State.TokenContract.GetPrimaryTokenSymbol.Call(new Empty()).Value; - var contributeAmount = DAppConstants.UseFee.Div(3); - State.TokenContract.Approve.Send(new ApproveInput - { - Spender = State.TokenHolderContract.Value, - Symbol = input.Symbol, - Amount = contributeAmount - }); + Type = RecordType.Withdraw, + Timestamp = Context.CurrentBlockTime, + Description = $"{State.Symbol.Value} -{input.Amount}" + }); + State.Profiles[Context.Sender] = profile; - // Contribute 1/3 profits (ELF) to profit scheme. - State.TokenHolderContract.ContributeProfits.Send(new ContributeProfitsInput - { - SchemeManager = Context.Self, - Amount = contributeAmount, - Symbol = input.Symbol - }); - - // Update profile. - var profile = State.Profiles[Context.Sender]; - profile.Records.Add(new Record - { - Type = RecordType.Withdraw, - Timestamp = Context.CurrentBlockTime, - Description = $"{State.Symbol.Value} -{DAppConstants.UseFee}", - Symbol = input.Symbol - }); - State.Profiles[Context.Sender] = profile; - - return new Empty(); - } - - private void CreateToken(Address profitReceiver, bool isLockWhiteListIncludingSelf = false) - { - var lockWhiteList = new List
- {Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName)}; - if (isLockWhiteListIncludingSelf) - lockWhiteList.Add(Context.Self); - State.TokenContract.Create.Send(new CreateInput - { - Symbol = State.Symbol.Value, - TokenName = "DApp Token", - Decimals = DAppConstants.Decimal, - Issuer = Context.Self, - IsBurnable = true, - TotalSupply = DAppConstants.TotalSupply, - LockWhiteList = - { - lockWhiteList - } - }); - - State.TokenContract.Issue.Send(new IssueInput - { - To = profitReceiver, - Amount = DAppConstants.TotalSupply / 5, - Symbol = State.Symbol.Value, - Memo = "Issue token for profit receiver" - }); - } + return new Empty(); + } - private void CreateTokenHolderProfitScheme() + public override Empty Use(Record input) + { + State.TokenContract.TransferToContract.Send(new TransferToContractInput { - State.TokenHolderContract.CreateScheme.Send(new CreateTokenHolderProfitSchemeInput - { - Symbol = State.Symbol.Value - }); - } + Symbol = State.Symbol.Value, + Amount = DAppConstants.UseFee + }); + if (input.Symbol == string.Empty) + input.Symbol = State.TokenContract.GetPrimaryTokenSymbol.Call(new Empty()).Value; + var contributeAmount = DAppConstants.UseFee.Div(3); + State.TokenContract.Approve.Send(new ApproveInput + { + Spender = State.TokenHolderContract.Value, + Symbol = input.Symbol, + Amount = contributeAmount + }); - private void SetProfitConfig() + // Contribute 1/3 profits (ELF) to profit scheme. + State.TokenHolderContract.ContributeProfits.Send(new ContributeProfitsInput { - State.ProfitConfig.Value = new ProfitConfig - { - DonationPartsPerHundred = 1, - StakingTokenSymbol = "APP", - ProfitsTokenSymbolList = {"ELF"} - }; - } + SchemeManager = Context.Self, + Amount = contributeAmount, + Symbol = input.Symbol + }); + + // Update profile. + var profile = State.Profiles[Context.Sender]; + profile.Records.Add(new Record + { + Type = RecordType.Withdraw, + Timestamp = Context.CurrentBlockTime, + Description = $"{State.Symbol.Value} -{DAppConstants.UseFee}", + Symbol = input.Symbol + }); + State.Profiles[Context.Sender] = profile; + + return new Empty(); + } + + private void CreateToken(Address profitReceiver, bool isLockWhiteListIncludingSelf = false) + { + var lockWhiteList = new List
+ { Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName) }; + if (isLockWhiteListIncludingSelf) + lockWhiteList.Add(Context.Self); + State.TokenContract.Create.Send(new CreateInput + { + Symbol = State.Symbol.Value, + TokenName = "DApp Token", + Decimals = DAppConstants.Decimal, + Issuer = Context.Self, + IsBurnable = true, + TotalSupply = DAppConstants.TotalSupply, + LockWhiteList = + { + lockWhiteList + } + }); + + State.TokenContract.Issue.Send(new IssueInput + { + To = profitReceiver, + Amount = DAppConstants.TotalSupply / 5, + Symbol = State.Symbol.Value, + Memo = "Issue token for profit receiver" + }); + } + + private void CreateTokenHolderProfitScheme() + { + State.TokenHolderContract.CreateScheme.Send(new CreateTokenHolderProfitSchemeInput + { + Symbol = State.Symbol.Value + }); + } + + private void SetProfitConfig() + { + State.ProfitConfig.Value = new ProfitConfig + { + DonationPartsPerHundred = 1, + StakingTokenSymbol = "APP", + ProfitsTokenSymbolList = { "ELF" } + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.DApp/DAppContractState.cs b/test/AElf.Contracts.TestContract.DApp/DAppContractState.cs index f8f6e5df0f..0d3c19b689 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppContractState.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppContractState.cs @@ -1,26 +1,24 @@ -using AElf.Standards.ACS1; -using AElf.Standards.ACS10; -using AElf.Standards.ACS9; -using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.MultiToken; +using AElf.Contracts.MultiToken; using AElf.Contracts.TokenHolder; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; +using AElf.Standards.ACS10; +using AElf.Standards.ACS9; using AElf.Types; -namespace AElf.Contracts.TestContract.DApp +namespace AElf.Contracts.TestContract.DApp; + +public class DAppContractState : ContractState { - public class DAppContractState : ContractState - { - internal TokenHolderContractContainer.TokenHolderContractReferenceState TokenHolderContract { get; set; } - internal TokenContractImplContainer.TokenContractImplReferenceState TokenContract { get; set; } - internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } + internal TokenHolderContractContainer.TokenHolderContractReferenceState TokenHolderContract { get; set; } + internal TokenContractImplContainer.TokenContractImplReferenceState TokenContract { get; set; } + internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } + + public SingletonState Symbol { get; set; } + public SingletonState
ProfitReceiver { get; set; } + public MappedState Profiles { get; set; } - public SingletonState Symbol { get; set; } - public SingletonState
ProfitReceiver { get; set; } - public MappedState Profiles { get; set; } - - public MappedState TransactionFees { get; set; } + public MappedState TransactionFees { get; set; } - public SingletonState ProfitConfig { get; set; } - } + public SingletonState ProfitConfig { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.DApp/DAppContract_ACS9.cs b/test/AElf.Contracts.TestContract.DApp/DAppContract_ACS9.cs index e19a4e1054..8d370f5de2 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppContract_ACS9.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppContract_ACS9.cs @@ -1,68 +1,67 @@ -using AElf.Standards.ACS9; -using AElf.Standards.ACS10; using AElf.Contracts.MultiToken; using AElf.Contracts.TokenHolder; using AElf.CSharp.Core; +using AElf.Standards.ACS10; +using AElf.Standards.ACS9; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.DApp +namespace AElf.Contracts.TestContract.DApp; + +public partial class DAppContract { - public partial class DAppContract + public override Empty TakeContractProfits(TakeContractProfitsInput input) { - public override Empty TakeContractProfits(TakeContractProfitsInput input) - { - var config = State.ProfitConfig.Value; + var config = State.ProfitConfig.Value; - // For Side Chain Dividends Pool. - var amountForSideChainDividendsPool = input.Amount.Mul(config.DonationPartsPerHundred).Div(100); - State.TokenContract.Approve.Send(new ApproveInput - { - Symbol = input.Symbol, - Amount = amountForSideChainDividendsPool, - Spender = State.DividendPoolContract.Value - }); - State.DividendPoolContract.Donate.Send(new DonateInput - { - Symbol = input.Symbol, - Amount = amountForSideChainDividendsPool - }); - - // For receiver. - var amountForReceiver = input.Amount.Sub(amountForSideChainDividendsPool); - State.TokenContract.Transfer.Send(new TransferInput - { - To = State.ProfitReceiver.Value, - Amount = amountForReceiver, - Symbol = input.Symbol - }); + // For Side Chain Dividends Pool. + var amountForSideChainDividendsPool = input.Amount.Mul(config.DonationPartsPerHundred).Div(100); + State.TokenContract.Approve.Send(new ApproveInput + { + Symbol = input.Symbol, + Amount = amountForSideChainDividendsPool, + Spender = State.DividendPoolContract.Value + }); + State.DividendPoolContract.Donate.Send(new DonateInput + { + Symbol = input.Symbol, + Amount = amountForSideChainDividendsPool + }); - // For Token Holder Profit Scheme. (To distribute.) - State.TokenHolderContract.DistributeProfits.Send(new DistributeProfitsInput - { - SchemeManager = Context.Self - }); - return new Empty(); - } + // For receiver. + var amountForReceiver = input.Amount.Sub(amountForSideChainDividendsPool); + State.TokenContract.Transfer.Send(new TransferInput + { + To = State.ProfitReceiver.Value, + Amount = amountForReceiver, + Symbol = input.Symbol + }); - public override ProfitConfig GetProfitConfig(Empty input) + // For Token Holder Profit Scheme. (To distribute.) + State.TokenHolderContract.DistributeProfits.Send(new DistributeProfitsInput { - return State.ProfitConfig.Value; - } + SchemeManager = Context.Self + }); + return new Empty(); + } - public override ProfitsMap GetProfitsAmount(Empty input) + public override ProfitConfig GetProfitConfig(Empty input) + { + return State.ProfitConfig.Value; + } + + public override ProfitsMap GetProfitsAmount(Empty input) + { + var profitsMap = new ProfitsMap(); + foreach (var symbol in State.ProfitConfig.Value.ProfitsTokenSymbolList) { - var profitsMap = new ProfitsMap(); - foreach (var symbol in State.ProfitConfig.Value.ProfitsTokenSymbolList) + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput { - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = Context.Self, - Symbol = symbol - }).Balance; - profitsMap.Value[symbol] = balance; - } - - return profitsMap; + Owner = Context.Self, + Symbol = symbol + }).Balance; + profitsMap.Value[symbol] = balance; } + + return profitsMap; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.DApp/DAppFeeProvider.cs b/test/AElf.Contracts.TestContract.DApp/DAppFeeProvider.cs index 148ac79b5d..a8c9fae323 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppFeeProvider.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppFeeProvider.cs @@ -1,26 +1,22 @@ using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.DApp +namespace AElf.Contracts.TestContract.DApp; + +public partial class DAppContract { - public partial class DAppContract + public override MethodFees GetMethodFee(StringValue input) + { + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) return methodFees; + + return new MethodFees(); + } + + public override Empty SetMethodFee(MethodFees input) { - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - { - return methodFees; - } - - return new MethodFees(); - } + State.TransactionFees[input.MethodName] = input; - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - - return new Empty(); - } + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Events/AElf.Contracts.TestContract.Events.csproj b/test/AElf.Contracts.TestContract.Events/AElf.Contracts.TestContract.Events.csproj index bd12f61fd3..55554c6d93 100644 --- a/test/AElf.Contracts.TestContract.Events/AElf.Contracts.TestContract.Events.csproj +++ b/test/AElf.Contracts.TestContract.Events/AElf.Contracts.TestContract.Events.csproj @@ -6,7 +6,7 @@ - true + true @@ -27,7 +27,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.Events/ContractReference.cs b/test/AElf.Contracts.TestContract.Events/ContractReference.cs index 7a91f5def1..17d4f27541 100644 --- a/test/AElf.Contracts.TestContract.Events/ContractReference.cs +++ b/test/AElf.Contracts.TestContract.Events/ContractReference.cs @@ -2,16 +2,15 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Contracts.TestContract.Events +namespace AElf.Contracts.TestContract.Events; + +public class EventsContractState : ContractState { - public class EventsContractState : ContractState - { - public BoolState Initialized { get; set; } - - public MappedState OrderIds { get; set; } - public MappedState AllOrders { get; set; } - - public MappedState SubOrders { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + public BoolState Initialized { get; set; } + + public MappedState OrderIds { get; set; } + public MappedState AllOrders { get; set; } + + public MappedState SubOrders { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Events/EventsContract_Action.cs b/test/AElf.Contracts.TestContract.Events/EventsContract_Action.cs index 8625102603..7b80a78165 100644 --- a/test/AElf.Contracts.TestContract.Events/EventsContract_Action.cs +++ b/test/AElf.Contracts.TestContract.Events/EventsContract_Action.cs @@ -4,173 +4,173 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.Events +namespace AElf.Contracts.TestContract.Events; + +public partial class EventsContract : EventsContractContainer.EventsContractBase { - public partial class EventsContract : EventsContractContainer.EventsContractBase + //action + public override Empty InitializeEvents(InitializeInput input) { - //action - public override Empty InitializeEvents(InitializeInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); + Assert(!State.Initialized.Value, "Already initialized."); - State.Initialized.Value = true; + State.Initialized.Value = true; - return new Empty(); - } + return new Empty(); + } - public override Empty IssueOrder(OrderInput input) - { - //sent token to contract first - var hash = GetIssueOrderId(input); + public override Empty IssueOrder(OrderInput input) + { + //sent token to contract first + var hash = GetIssueOrderId(input); - //transfer from - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - Symbol = input.SymbolPaid, - Amount = input.BalancePaid, - From = Context.Sender, - To = Context.Self, - Memo = "issue new order" - }); - - State.AllOrders[hash] = new OrderInfo - { - OrderId = hash, - Issuer = Context.Sender, - SymbolPaid = input.SymbolPaid, - SymbolObtain = input.SymbolObtain, - BalancePaid = input.BalancePaid, - BalanceObtain = input.BalanceObtain, - BalanceAchieved = 0, - Status = OrderStatus.Created - }; - - Context.Fire(new OrderIssued - { - Issuer = Context.Sender, - SymbolPaid = input.SymbolPaid, - SymbolObtain = input.SymbolObtain, - BalancePaid = input.BalancePaid, - BalanceObtain = input.BalanceObtain - }); - - Context.Fire(new Transferred - { - From = Context.Sender, - To = Context.Self, - Symbol = input.SymbolPaid, - Amount = input.BalancePaid, - Memo = "Same name event for test" //same with token event transfer - }); - return new Empty(); - } + //transfer from + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + Symbol = input.SymbolPaid, + Amount = input.BalancePaid, + From = Context.Sender, + To = Context.Self, + Memo = "issue new order" + }); + + State.AllOrders[hash] = new OrderInfo + { + OrderId = hash, + Issuer = Context.Sender, + SymbolPaid = input.SymbolPaid, + SymbolObtain = input.SymbolObtain, + BalancePaid = input.BalancePaid, + BalanceObtain = input.BalanceObtain, + BalanceAchieved = 0, + Status = OrderStatus.Created + }; + + Context.Fire(new OrderIssued + { + Issuer = Context.Sender, + SymbolPaid = input.SymbolPaid, + SymbolObtain = input.SymbolObtain, + BalancePaid = input.BalancePaid, + BalanceObtain = input.BalanceObtain + }); + + Context.Fire(new Transferred + { + From = Context.Sender, + To = Context.Self, + Symbol = input.SymbolPaid, + Amount = input.BalancePaid, + Memo = "Same name event for test" //same with token event transfer + }); + return new Empty(); + } - public override Empty DealOrder(DealOrderInput input) + public override Empty DealOrder(DealOrderInput input) + { + var order = CheckDealOrderInput(input.OrderId); + order.BalanceAchieved.Add(input.Amount); + State.AllOrders[input.OrderId] = order; + if (order.BalanceAchieved == order.BalanceObtain) { - var order = CheckDealOrderInput(input.OrderId); - order.BalanceAchieved.Add(input.Amount); + order.Status = OrderStatus.Done; State.AllOrders[input.OrderId] = order; - if (order.BalanceAchieved == order.BalanceObtain) - { - order.Status = OrderStatus.Done; - State.AllOrders[input.OrderId] = order; - UpdateOrderId(input.OrderId, OrderStatus.Done); - } - else + UpdateOrderId(input.OrderId, OrderStatus.Done); + } + else + { + if (order.Status == OrderStatus.Created) { - if (order.Status == OrderStatus.Created) - { - order.Status = OrderStatus.Ongoing; - State.AllOrders[input.OrderId] = order; - } + order.Status = OrderStatus.Ongoing; + State.AllOrders[input.OrderId] = order; } - //add sub order record - var subOrders = State.SubOrders[input.OrderId]; - subOrders.SubOrders.Add(new DealtOrder - { - Dealer = Context.Sender, - Amount = input.Amount - }); - - //transfer from - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - Symbol = order.SymbolObtain, - Amount = input.Amount, - From = Context.Sender, - To = Context.Self, - Memo = "sent order token to contract first" - }); - - //transfer to issuer - State.TokenContract.Transfer.Send(new TransferInput - { - Symbol = order.SymbolObtain, - Amount = input.Amount, - To = order.Issuer, - Memo = "deal order" - }); - - //transfer to dealer - var paidAmount = order.BalancePaid.Div(order.BalanceObtain).Mul(input.Amount); - State.TokenContract.Transfer.Send(new TransferInput - { - Symbol = order.SymbolPaid, - Amount = paidAmount, - To = Context.Sender, - Memo = "got token" - }); + } - Context.Fire(new OrderDealt - { - OrderId = input.OrderId, - Dealer = Context.Sender, - Amount = input.Amount - }); + //add sub order record + var subOrders = State.SubOrders[input.OrderId]; + subOrders.SubOrders.Add(new DealtOrder + { + Dealer = Context.Sender, + Amount = input.Amount + }); - return new Empty(); - } + //transfer from + State.TokenContract.TransferFrom.Send(new TransferFromInput + { + Symbol = order.SymbolObtain, + Amount = input.Amount, + From = Context.Sender, + To = Context.Self, + Memo = "sent order token to contract first" + }); + + //transfer to issuer + State.TokenContract.Transfer.Send(new TransferInput + { + Symbol = order.SymbolObtain, + Amount = input.Amount, + To = order.Issuer, + Memo = "deal order" + }); + + //transfer to dealer + var paidAmount = order.BalancePaid.Div(order.BalanceObtain).Mul(input.Amount); + State.TokenContract.Transfer.Send(new TransferInput + { + Symbol = order.SymbolPaid, + Amount = paidAmount, + To = Context.Sender, + Memo = "got token" + }); - public override Empty CancelOrder(Hash input) + Context.Fire(new OrderDealt { - var order = CheckDealOrderInput(input); + OrderId = input.OrderId, + Dealer = Context.Sender, + Amount = input.Amount + }); + + return new Empty(); + } - //update status - order.Status = OrderStatus.Canceled; - State.AllOrders[input] = order; - UpdateOrderId(order.OrderId, OrderStatus.Canceled); + public override Empty CancelOrder(Hash input) + { + var order = CheckDealOrderInput(input); - //transfer back left token - State.TokenContract.Transfer.Send(new TransferInput - { - Symbol = order.SymbolPaid, - Amount = order.BalancePaid.Sub(order.BalanceAchieved), - To = order.Issuer, - Memo = "redeem back margin token" - }); + //update status + order.Status = OrderStatus.Canceled; + State.AllOrders[input] = order; + UpdateOrderId(order.OrderId, OrderStatus.Canceled); - Context.Fire(new OrderCanceled - { - OrderId = input - }); + //transfer back left token + State.TokenContract.Transfer.Send(new TransferInput + { + Symbol = order.SymbolPaid, + Amount = order.BalancePaid.Sub(order.BalanceAchieved), + To = order.Issuer, + Memo = "redeem back margin token" + }); - return new Empty(); - } + Context.Fire(new OrderCanceled + { + OrderId = input + }); + + return new Empty(); + } - public override Empty InlineTransferFrom(InlineTransferFromInput input) + public override Empty InlineTransferFrom(InlineTransferFromInput input) + { + State.TokenContract.Value = Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.TokenContract.TransferFrom.Send(new TransferFromInput { - State.TokenContract.Value = Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.TokenContract.TransferFrom.Send(new TransferFromInput - { - Amount = input.Amount, - From = input.From, - To = input.To, - Symbol = input.Symbol, - Memo = input.Memo - }); - - return new Empty(); - } + Amount = input.Amount, + From = input.From, + To = input.To, + Symbol = input.Symbol, + Memo = input.Memo + }); + + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Events/EventsContract_View.cs b/test/AElf.Contracts.TestContract.Events/EventsContract_View.cs index b0e84d0aa2..6aa5c3c850 100644 --- a/test/AElf.Contracts.TestContract.Events/EventsContract_View.cs +++ b/test/AElf.Contracts.TestContract.Events/EventsContract_View.cs @@ -1,88 +1,85 @@ -using System; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.Events +namespace AElf.Contracts.TestContract.Events; + +public partial class EventsContract { - public partial class EventsContract + //view + public override StringValue GetContractName(Empty input) { - //view - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(EventsContract) - }; - } - public override OrdersOutput QueryIssueOrders(Empty input) - { - var orders = new OrdersOutput(); + Value = nameof(EventsContract) + }; + } - var createOrders = State.OrderIds[OrderStatus.Created]; - if (createOrders != null && createOrders.Ids.Count > 0) - { - foreach (var id in createOrders.Ids) - { - var order = State.AllOrders[id]; - orders.Orders.Add(order); - } - } + public override OrdersOutput QueryIssueOrders(Empty input) + { + var orders = new OrdersOutput(); - var ongoingOrders = State.OrderIds[OrderStatus.Ongoing]; - if (ongoingOrders == null || ongoingOrders.Ids.Count <= 0) return orders; - - foreach (var id in ongoingOrders.Ids) + var createOrders = State.OrderIds[OrderStatus.Created]; + if (createOrders != null && createOrders.Ids.Count > 0) + foreach (var id in createOrders.Ids) { var order = State.AllOrders[id]; orders.Orders.Add(order); } - return orders; - } + var ongoingOrders = State.OrderIds[OrderStatus.Ongoing]; + if (ongoingOrders == null || ongoingOrders.Ids.Count <= 0) return orders; - public override OrdersOutput QueryDoneOrders(Empty input) + foreach (var id in ongoingOrders.Ids) { - var orders = new OrdersOutput(); + var order = State.AllOrders[id]; + orders.Orders.Add(order); + } - var doneOrders = State.OrderIds[OrderStatus.Done]; - if (doneOrders == null || doneOrders.Ids.Count <= 0) return orders; + return orders; + } - foreach (var id in doneOrders.Ids) - { - var order = State.AllOrders[id]; - orders.Orders.Add(order); - } + public override OrdersOutput QueryDoneOrders(Empty input) + { + var orders = new OrdersOutput(); - return orders; - } + var doneOrders = State.OrderIds[OrderStatus.Done]; + if (doneOrders == null || doneOrders.Ids.Count <= 0) return orders; - public override OrdersOutput QueryCanceledOrders(Empty input) + foreach (var id in doneOrders.Ids) { - var orders = new OrdersOutput(); + var order = State.AllOrders[id]; + orders.Orders.Add(order); + } - var cancelOrders = State.OrderIds[OrderStatus.Canceled]; - if (cancelOrders == null || cancelOrders.Ids.Count <= 0) return orders; + return orders; + } - foreach (var id in cancelOrders.Ids) - { - var order = State.AllOrders[id]; - orders.Orders.Add(order); - } + public override OrdersOutput QueryCanceledOrders(Empty input) + { + var orders = new OrdersOutput(); - return orders; - } + var cancelOrders = State.OrderIds[OrderStatus.Canceled]; + if (cancelOrders == null || cancelOrders.Ids.Count <= 0) return orders; - public override OrderInfo QueryOrderById(Hash input) + foreach (var id in cancelOrders.Ids) { - var order = State.AllOrders[input]; - return order ?? new OrderInfo(); + var order = State.AllOrders[id]; + orders.Orders.Add(order); } - public override DealtOrders QueryOrderSubOrders(Hash input) - { - var orders = State.SubOrders[input]; + return orders; + } - return orders ?? new DealtOrders(); - } + public override OrderInfo QueryOrderById(Hash input) + { + var order = State.AllOrders[input]; + return order ?? new OrderInfo(); + } + + public override DealtOrders QueryOrderSubOrders(Hash input) + { + var orders = State.SubOrders[input]; + + return orders ?? new DealtOrders(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Events/Events_Helper.cs b/test/AElf.Contracts.TestContract.Events/Events_Helper.cs index ff7504fdff..d6ff51cccc 100644 --- a/test/AElf.Contracts.TestContract.Events/Events_Helper.cs +++ b/test/AElf.Contracts.TestContract.Events/Events_Helper.cs @@ -1,67 +1,66 @@ using AElf.Types; -namespace AElf.Contracts.TestContract.Events +namespace AElf.Contracts.TestContract.Events; + +public partial class EventsContract { - public partial class EventsContract + public Hash GetIssueOrderId(OrderInput input) { - public Hash GetIssueOrderId(OrderInput input) - { - var hash1 = HashHelper.ComputeFrom(input); - var hash2 = Context.TransactionId; + var hash1 = HashHelper.ComputeFrom(input); + var hash2 = Context.TransactionId; - return HashHelper.ConcatAndCompute(hash1, hash2); - } + return HashHelper.ConcatAndCompute(hash1, hash2); + } - public void NewOrderId(Hash orderId) + public void NewOrderId(Hash orderId) + { + var orderIds = State.OrderIds[OrderStatus.Created]; + if (orderIds == null) { - var orderIds = State.OrderIds[OrderStatus.Created]; - if (orderIds == null) + State.OrderIds[OrderStatus.Created] = new OrderIds { - State.OrderIds[OrderStatus.Created] = new OrderIds - { - Ids = {orderId} - }; - return; - } - - orderIds.Ids.Add(orderId); - State.OrderIds[OrderStatus.Created] = orderIds; + Ids = { orderId } + }; + return; } - public void UpdateOrderId(Hash orderId, OrderStatus status) + orderIds.Ids.Add(orderId); + State.OrderIds[OrderStatus.Created] = orderIds; + } + + public void UpdateOrderId(Hash orderId, OrderStatus status) + { + var createdIds = State.OrderIds[OrderStatus.Created]; + Assert(createdIds != null, "no such status ids"); + Assert(createdIds.Ids.Contains(orderId), "Not exist such order id"); + + //remove first + createdIds.Ids.Remove(orderId); + State.OrderIds[OrderStatus.Created] = createdIds; + + //then add + var statusIds = State.OrderIds[status]; + if (statusIds == null) { - var createdIds = State.OrderIds[OrderStatus.Created]; - Assert(createdIds != null, "no such status ids"); - Assert(createdIds.Ids.Contains(orderId), "Not exist such order id"); - - //remove first - createdIds.Ids.Remove(orderId); - State.OrderIds[OrderStatus.Created] = createdIds; - - //then add - var statusIds = State.OrderIds[status]; - if (statusIds == null) - { - State.OrderIds[status] = new OrderIds - { - Ids = { orderId } - }; - } - else + State.OrderIds[status] = new OrderIds { - statusIds.Ids.Add(orderId); - State.OrderIds[status] = statusIds; - } + Ids = { orderId } + }; } - - public OrderInfo CheckDealOrderInput(Hash input) + else { - var ids = State.OrderIds[OrderStatus.Created]; - Assert(ids.Ids.Contains(input), "Not contain such order or order completed or canceled."); - - var order = State.AllOrders[input]; - - return order; + statusIds.Ids.Add(orderId); + State.OrderIds[status] = statusIds; } } + + public OrderInfo CheckDealOrderInput(Hash input) + { + var ids = State.OrderIds[OrderStatus.Created]; + Assert(ids.Ids.Contains(input), "Not contain such order or order completed or canceled."); + + var order = State.AllOrders[input]; + + return order; + } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.MethodCallThreshold/AElf.Contracts.TestContract.MethodCallThreshold.csproj b/test/AElf.Contracts.TestContract.MethodCallThreshold/AElf.Contracts.TestContract.MethodCallThreshold.csproj index b3ef51ba92..0d545b6fec 100644 --- a/test/AElf.Contracts.TestContract.MethodCallThreshold/AElf.Contracts.TestContract.MethodCallThreshold.csproj +++ b/test/AElf.Contracts.TestContract.MethodCallThreshold/AElf.Contracts.TestContract.MethodCallThreshold.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.MethodCallThreshold/ContractsReferences.cs b/test/AElf.Contracts.TestContract.MethodCallThreshold/ContractsReferences.cs index 4edfbea4c2..04d1c7e134 100644 --- a/test/AElf.Contracts.TestContract.MethodCallThreshold/ContractsReferences.cs +++ b/test/AElf.Contracts.TestContract.MethodCallThreshold/ContractsReferences.cs @@ -1,13 +1,12 @@ -using AElf.Standards.ACS0; using AElf.Contracts.MultiToken; using AElf.Contracts.Treasury; +using AElf.Standards.ACS0; + +namespace AElf.Contracts.TestContract.MethodCallThreshold; -namespace AElf.Contracts.TestContract.MethodCallThreshold +public partial class MethodCallThresholdContractState { - public partial class MethodCallThresholdContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal TreasuryContractContainer.TreasuryContractReferenceState TreasuryContract { get; set; } - internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + internal TreasuryContractContainer.TreasuryContractReferenceState TreasuryContract { get; set; } + internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContract.cs b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContract.cs index cbc646f0aa..12faae1f92 100644 --- a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContract.cs +++ b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContract.cs @@ -1,39 +1,35 @@ using AElf.Standards.ACS5; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.MethodCallThreshold +namespace AElf.Contracts.TestContract.MethodCallThreshold; + +public class MethodCallThresholdContract : MethodCallThresholdContractContainer.MethodCallThresholdContractBase { - public class MethodCallThresholdContract : MethodCallThresholdContractContainer.MethodCallThresholdContractBase + public override Empty SetMethodCallingThreshold(SetMethodCallingThresholdInput input) { - public override Empty SetMethodCallingThreshold(SetMethodCallingThresholdInput input) + AssertPerformedByContractOwner(); + State.MethodCallingThresholds[input.Method] = new MethodCallingThreshold { - AssertPerformedByContractOwner(); - State.MethodCallingThresholds[input.Method] = new MethodCallingThreshold - { - SymbolToAmount = {input.SymbolToAmount} - }; - return new Empty(); - } + SymbolToAmount = { input.SymbolToAmount } + }; + return new Empty(); + } - public override MethodCallingThreshold GetMethodCallingThreshold(StringValue input) - { - return State.MethodCallingThresholds[input.Value]; - } + public override MethodCallingThreshold GetMethodCallingThreshold(StringValue input) + { + return State.MethodCallingThresholds[input.Value]; + } - public override Empty SendForFun(Empty input) - { - return new Empty(); - } - - private void AssertPerformedByContractOwner() - { - if (State.Acs0Contract.Value == null) - { - State.Acs0Contract.Value = Context.GetZeroSmartContractAddress(); - } - - var contractInfo = State.Acs0Contract.GetContractInfo.Call(Context.Self); - Assert(Context.Sender == contractInfo.Author, "Only owner are permitted to call this method."); - } + public override Empty SendForFun(Empty input) + { + return new Empty(); + } + + private void AssertPerformedByContractOwner() + { + if (State.Acs0Contract.Value == null) State.Acs0Contract.Value = Context.GetZeroSmartContractAddress(); + + var contractInfo = State.Acs0Contract.GetContractInfo.Call(Context.Self); + Assert(Context.Sender == contractInfo.Author, "Only owner are permitted to call this method."); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractConstants.cs b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractConstants.cs index 618f74c8ac..b6b11b9347 100644 --- a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractConstants.cs +++ b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractConstants.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.TestContract.MethodCallThreshold +namespace AElf.Contracts.TestContract.MethodCallThreshold; + +public class MethodCallThresholdContractConstants { - public class MethodCallThresholdContractConstants - { - public const long TotalSupply = 1_000_000_000_00000000; - public const long AmountIssueToTokenConverterContract = 100_000_00000000; - } + public const long TotalSupply = 1_000_000_000_00000000; + public const long AmountIssueToTokenConverterContract = 100_000_00000000; } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractState.cs b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractState.cs index 964bedc103..99bb088f75 100644 --- a/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractState.cs +++ b/test/AElf.Contracts.TestContract.MethodCallThreshold/MethodCallThresholdContractState.cs @@ -1,11 +1,9 @@ -using AElf.Standards.ACS5; -using AElf.Sdk.CSharp.State; -using AElf.Types; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS5; -namespace AElf.Contracts.TestContract.MethodCallThreshold +namespace AElf.Contracts.TestContract.MethodCallThreshold; + +public partial class MethodCallThresholdContractState : ContractState { - public partial class MethodCallThresholdContractState : ContractState - { - public MappedState MethodCallingThresholds { get; set; } - } + public MappedState MethodCallingThresholds { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Performance/AElf.Contracts.TestContract.Performance.csproj b/test/AElf.Contracts.TestContract.Performance/AElf.Contracts.TestContract.Performance.csproj index c8037ccef7..b7f3170b75 100644 --- a/test/AElf.Contracts.TestContract.Performance/AElf.Contracts.TestContract.Performance.csproj +++ b/test/AElf.Contracts.TestContract.Performance/AElf.Contracts.TestContract.Performance.csproj @@ -6,11 +6,11 @@ - true + true - + @@ -18,7 +18,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs3.proto diff --git a/test/AElf.Contracts.TestContract.Performance/PerformanceContractState.cs b/test/AElf.Contracts.TestContract.Performance/PerformanceContractState.cs index 9c3e4e274c..1d01c495fe 100644 --- a/test/AElf.Contracts.TestContract.Performance/PerformanceContractState.cs +++ b/test/AElf.Contracts.TestContract.Performance/PerformanceContractState.cs @@ -1,24 +1,23 @@ -using AElf.Standards.ACS1; using AElf.Contracts.Parliament; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; using AElf.Types; -namespace AElf.Contracts.TestContract.Performance +namespace AElf.Contracts.TestContract.Performance; + +public class PerformanceContractState : ContractState { - public class PerformanceContractState : ContractState - { - public BoolState Initialized { get; set; } - - public StringState ContractName { get; set; } - - public ProtobufState
ContractManager { get; set; } - - public MappedState Content { get; set; } - - public MappedState MapContent { get; set; } - - public MappedState TransactionFees { get; set; } - - internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } - } + public BoolState Initialized { get; set; } + + public StringState ContractName { get; set; } + + public ProtobufState
ContractManager { get; set; } + + public MappedState Content { get; set; } + + public MappedState MapContent { get; set; } + + public MappedState TransactionFees { get; set; } + + internal ParliamentContractContainer.ParliamentContractReferenceState ParliamentContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_Action.cs b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_Action.cs index 1ccf92fae8..3e3876d8d3 100644 --- a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_Action.cs +++ b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_Action.cs @@ -1,126 +1,122 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.Performance +namespace AElf.Contracts.TestContract.Performance; + +public partial class PerformanceContract : PerformanceContractContainer.PerformanceContractBase { - public partial class PerformanceContract : PerformanceContractContainer.PerformanceContractBase + public override Empty InitialPerformanceContract(InitialPerformanceInput input) { - public override Empty InitialPerformanceContract(InitialPerformanceInput input) - { - Assert(!State.Initialized.Value, "Already initialized."); - State.ContractName.Value = input.ContractName; - State.ContractManager.Value = input.Manager; + Assert(!State.Initialized.Value, "Already initialized."); + State.ContractName.Value = input.ContractName; + State.ContractManager.Value = input.Manager; - return new Empty(); - } + return new Empty(); + } - public override Empty WriteKContentByte(WriteInput input) - { - State.Content[Context.Sender] = input.Content.ToHex(); - return new Empty(); - } + public override Empty WriteKContentByte(WriteInput input) + { + State.Content[Context.Sender] = input.Content.ToHex(); + return new Empty(); + } - public override Empty Write1KContentByte(WriteInput input) - { - Assert(input.Content.Length == 1000, $"input length not correct, {input.Content.Length}/1k"); - State.Content[Context.Sender] = input.Content.ToHex(); - return new Empty(); - } + public override Empty Write1KContentByte(WriteInput input) + { + Assert(input.Content.Length == 1000, $"input length not correct, {input.Content.Length}/1k"); + State.Content[Context.Sender] = input.Content.ToHex(); + return new Empty(); + } - public override Empty Write2KContentByte(WriteInput input) - { - Assert(input.Content.Length == 2000, $"input length not correct, {input.Content.Length}/2k"); - State.Content[Context.Sender] = input.Content.ToHex(); - return new Empty(); - } + public override Empty Write2KContentByte(WriteInput input) + { + Assert(input.Content.Length == 2000, $"input length not correct, {input.Content.Length}/2k"); + State.Content[Context.Sender] = input.Content.ToHex(); + return new Empty(); + } - public override Empty Write5KContentByte(WriteInput input) - { - Assert(input.Content.Length == 5000, $"input length not correct, {input.Content.Length}/5k"); - State.Content[Context.Sender] = input.Content.ToHex(); - return new Empty(); - } + public override Empty Write5KContentByte(WriteInput input) + { + Assert(input.Content.Length == 5000, $"input length not correct, {input.Content.Length}/5k"); + State.Content[Context.Sender] = input.Content.ToHex(); + return new Empty(); + } - public override Empty Write10KContentByte(WriteInput input) - { - Assert(input.Content.Length == 10000, $"input length not correct, {input.Content.Length}/10k"); - State.Content[Context.Sender] = input.Content.ToHex(); - return new Empty(); - } + public override Empty Write10KContentByte(WriteInput input) + { + Assert(input.Content.Length == 10000, $"input length not correct, {input.Content.Length}/10k"); + State.Content[Context.Sender] = input.Content.ToHex(); + return new Empty(); + } - public override Empty ComputeLevel(NumberInput input) - { - var result = CalculateFibonacci(input.Number); - State.MapContent[Context.Sender][input.Number] = result; + public override Empty ComputeLevel(NumberInput input) + { + var result = CalculateFibonacci(input.Number); + State.MapContent[Context.Sender][input.Number] = result; - return new Empty(); - } + return new Empty(); + } - public override Empty ComputeLevel1(Empty input) - { - var result = CalculateFibonacci(20); // 0ms - Assert(result == 6765, $"ComputeLevel1 calculate error, result: {result}/6765"); - State.MapContent[Context.Sender][20] = result; + public override Empty ComputeLevel1(Empty input) + { + var result = CalculateFibonacci(20); // 0ms + Assert(result == 6765, $"ComputeLevel1 calculate error, result: {result}/6765"); + State.MapContent[Context.Sender][20] = result; - return new Empty(); - } + return new Empty(); + } - public override Empty ComputeLevel2(Empty input) - { - var result = CalculateFibonacci(24); //1ms - Assert(result == 46368, $"ComputeLevel2 calculate error, result: {result}/46368"); - State.MapContent[Context.Sender][24] = result; + public override Empty ComputeLevel2(Empty input) + { + var result = CalculateFibonacci(24); //1ms + Assert(result == 46368, $"ComputeLevel2 calculate error, result: {result}/46368"); + State.MapContent[Context.Sender][24] = result; - return new Empty(); - } + return new Empty(); + } - public override Empty ComputeLevel3(Empty input) - { - var result = CalculateFibonacci(28); //12ms - Assert(result == 317811, $"ComputeLevel3 calculate error, result: {result}/317811"); - State.MapContent[Context.Sender][28] = result; + public override Empty ComputeLevel3(Empty input) + { + var result = CalculateFibonacci(28); //12ms + Assert(result == 317811, $"ComputeLevel3 calculate error, result: {result}/317811"); + State.MapContent[Context.Sender][28] = result; - return new Empty(); - } + return new Empty(); + } - public override Empty ComputeLevel4(Empty input) - { - var result = CalculateFibonacci(32); //85ms - Assert(result == 2178309, $"ComputeLevel4 calculate error, result: {result}/2178309"); - State.MapContent[Context.Sender][32] = result; + public override Empty ComputeLevel4(Empty input) + { + var result = CalculateFibonacci(32); //85ms + Assert(result == 2178309, $"ComputeLevel4 calculate error, result: {result}/2178309"); + State.MapContent[Context.Sender][32] = result; - return new Empty(); - } + return new Empty(); + } - public override Empty InfiniteLoopWhile(NumberInput input) + public override Empty InfiniteLoopWhile(NumberInput input) + { + var count = input.Number; + while (true) { - var count = input.Number; - while (true) - { - count--; - if(count <=0) break; - - CalculateFibonacci(10); - } - - return new Empty(); - } + count--; + if (count <= 0) break; - public override Empty InfiniteLoopFor(NumberInput input) - { - for (var i = 0; i < input.Number; i++) - { - CalculateFibonacci(10); - } - - return new Empty(); + CalculateFibonacci(10); } - private static long CalculateFibonacci(long n) - { - if (n == 0 || n == 1) - return n; + return new Empty(); + } - return CalculateFibonacci(n - 2) + CalculateFibonacci(n - 1); - } + public override Empty InfiniteLoopFor(NumberInput input) + { + for (var i = 0; i < input.Number; i++) CalculateFibonacci(10); + + return new Empty(); + } + + private static long CalculateFibonacci(long n) + { + if (n == 0 || n == 1) + return n; + + return CalculateFibonacci(n - 2) + CalculateFibonacci(n - 1); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_FeeProvider.cs b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_FeeProvider.cs index 9196985444..84b8ef3f45 100644 --- a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_FeeProvider.cs +++ b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_FeeProvider.cs @@ -1,40 +1,35 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.Performance +namespace AElf.Contracts.TestContract.Performance; + +public partial class PerformanceContract { - public partial class PerformanceContract + public override MethodFees GetMethodFee(StringValue input) { - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - { - return methodFees; - } + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) return methodFees; - return new MethodFees - { - Fees = - { - new MethodFee {Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000} //default 0.1 native symbol - } - }; - } - - public override Empty SetMethodFee(MethodFees input) + return new MethodFees { - if (State.ParliamentContract.Value == null) + Fees = { - State.ParliamentContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); + new MethodFee + { Symbol = Context.Variables.NativeSymbol, BasicFee = 1000_0000 } //default 0.1 native symbol } + }; + } + + public override Empty SetMethodFee(MethodFees input) + { + if (State.ParliamentContract.Value == null) + State.ParliamentContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ParliamentContractSystemName); - Assert(Context.Sender == State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty())); - State.TransactionFees[input.MethodName] = input; + Assert(Context.Sender == State.ParliamentContract.GetDefaultOrganizationAddress.Call(new Empty())); + State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_View.cs b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_View.cs index 71b8d6d398..73c0062239 100644 --- a/test/AElf.Contracts.TestContract.Performance/PerformanceContract_View.cs +++ b/test/AElf.Contracts.TestContract.Performance/PerformanceContract_View.cs @@ -1,40 +1,39 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.Performance +namespace AElf.Contracts.TestContract.Performance; + +public partial class PerformanceContract { - public partial class PerformanceContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(PerformanceContract) - }; - } + Value = nameof(PerformanceContract) + }; + } + + public override ReadOutput QueryReadInfo(Address input) + { + if (State.Content[input] == null) + return new ReadOutput(); - public override ReadOutput QueryReadInfo(Address input) + return new ReadOutput { - if(State.Content[input] == null) - return new ReadOutput(); - - return new ReadOutput - { - Content = State.Content[input] - }; - } + Content = State.Content[input] + }; + } + + public override NumberOutput QueryFibonacci(NumberInput input) + { + Assert(input.Number < 50, $"Query number should less than 50. Actual number: {input.Number}"); + + var result = CalculateFibonacci(input.Number); - public override NumberOutput QueryFibonacci(NumberInput input) + return new NumberOutput { - Assert(input.Number < 50, $"Query number should less than 50. Actual number: {input.Number}"); - - var result = CalculateFibonacci(input.Number); - - return new NumberOutput - { - Number = input.Number, - Result = result - }; - } + Number = input.Number, + Result = result + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.RandomNumberProvider/AElf.Contracts.TestContract.RandomNumberProvider.csproj b/test/AElf.Contracts.TestContract.RandomNumberProvider/AElf.Contracts.TestContract.RandomNumberProvider.csproj index 508395c167..7a8ce3c515 100644 --- a/test/AElf.Contracts.TestContract.RandomNumberProvider/AElf.Contracts.TestContract.RandomNumberProvider.csproj +++ b/test/AElf.Contracts.TestContract.RandomNumberProvider/AElf.Contracts.TestContract.RandomNumberProvider.csproj @@ -8,7 +8,7 @@ - + @@ -16,7 +16,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\reference\acs1.proto diff --git a/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContract.cs b/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContract.cs index d03c67f260..7b235bdcce 100644 --- a/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContract.cs +++ b/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContract.cs @@ -2,25 +2,24 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.RandomNumberProvider +namespace AElf.Contracts.TestContract.RandomNumberProvider; + +// ReSharper disable InconsistentNaming +public class RandomNumberProviderContract : RandomNumberProviderContractContainer.RandomNumberProviderContractBase { - // ReSharper disable InconsistentNaming - public class RandomNumberProviderContract : RandomNumberProviderContractContainer.RandomNumberProviderContractBase + public override BytesValue GetRandomBytes(BytesValue input) { - public override BytesValue GetRandomBytes(BytesValue input) - { - var serializedInput = new GetRandomBytesInput(); - serializedInput.MergeFrom(input.Value); - var value = new Hash(); - value.MergeFrom(serializedInput.Value); - var randomHashFromContext = Context.GetRandomHash(value); + var serializedInput = new GetRandomBytesInput(); + serializedInput.MergeFrom(input.Value); + var value = new Hash(); + value.MergeFrom(serializedInput.Value); + var randomHashFromContext = Context.GetRandomHash(value); - return new BytesValue - { - Value = serializedInput.Kind == 1 - ? new BytesValue {Value = randomHashFromContext.Value}.ToByteString() - : new Int64Value {Value = Context.ConvertHashToInt64(randomHashFromContext, 1, 10000)}.ToByteString() - }; - } + return new BytesValue + { + Value = serializedInput.Kind == 1 + ? new BytesValue { Value = randomHashFromContext.Value }.ToByteString() + : new Int64Value { Value = Context.ConvertHashToInt64(randomHashFromContext, 1, 10000) }.ToByteString() + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContractState.cs b/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContractState.cs index c1670d9473..71294a8c8a 100644 --- a/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContractState.cs +++ b/test/AElf.Contracts.TestContract.RandomNumberProvider/RandomNumberProviderContractState.cs @@ -1,9 +1,7 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Contracts.TestContract.RandomNumberProvider -{ - public class RandomNumberProviderContractState : ContractState - { +namespace AElf.Contracts.TestContract.RandomNumberProvider; - } +public class RandomNumberProviderContractState : ContractState +{ } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.ResourceSpender/AElf.Contracts.TestContract.ResourceSpender.csproj b/test/AElf.Contracts.TestContract.ResourceSpender/AElf.Contracts.TestContract.ResourceSpender.csproj index a98084d9c2..0576361b4c 100644 --- a/test/AElf.Contracts.TestContract.ResourceSpender/AElf.Contracts.TestContract.ResourceSpender.csproj +++ b/test/AElf.Contracts.TestContract.ResourceSpender/AElf.Contracts.TestContract.ResourceSpender.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContract.cs b/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContract.cs index 0703060bf2..ed04b6f54a 100644 --- a/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContract.cs +++ b/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContract.cs @@ -1,13 +1,11 @@ -using AElf.Standards.ACS8; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.ResourceSpender +namespace AElf.Contracts.TestContract.ResourceSpender; + +public class ResourceSpenderContract : ResourceSpenderContractContainer.ResourceSpenderContractBase { - public class ResourceSpenderContract : ResourceSpenderContractContainer.ResourceSpenderContractBase + public override Empty SendForFun(Empty input) { - public override Empty SendForFun(Empty input) - { - return new Empty(); - } + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContractState.cs b/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContractState.cs index 1f68956fb4..b53a2a2539 100644 --- a/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContractState.cs +++ b/test/AElf.Contracts.TestContract.ResourceSpender/ResourceSpenderContractState.cs @@ -1,12 +1,9 @@ -using AElf.Standards.ACS0; -using AElf.Standards.ACS8; -using AElf.Sdk.CSharp.State; -using AElf.Types; +using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS0; -namespace AElf.Contracts.TestContract.ResourceSpender +namespace AElf.Contracts.TestContract.ResourceSpender; + +public class ResourceSpenderContractState : ContractState { - public partial class ResourceSpenderContractState : ContractState - { - internal ACS0Container.ACS0ReferenceState ACS0Contract { get; set; } - } + internal ACS0Container.ACS0ReferenceState ACS0Contract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/AElf.Contracts.TestContract.Tests.csproj b/test/AElf.Contracts.TestContract.Tests/AElf.Contracts.TestContract.Tests.csproj index eefacd3581..d0b4715852 100644 --- a/test/AElf.Contracts.TestContract.Tests/AElf.Contracts.TestContract.Tests.csproj +++ b/test/AElf.Contracts.TestContract.Tests/AElf.Contracts.TestContract.Tests.csproj @@ -11,13 +11,13 @@ 0436 - - - - - - - + + + + + + + @@ -41,8 +41,8 @@ Contract PreserveNewest - - + + false Contract @@ -95,7 +95,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\transaction_fee.proto @@ -154,7 +154,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.Tests/BigIntValueTests.cs b/test/AElf.Contracts.TestContract.Tests/BigIntValueTests.cs index dd90a0879a..7cdd6faa9f 100644 --- a/test/AElf.Contracts.TestContract.Tests/BigIntValueTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/BigIntValueTests.cs @@ -5,58 +5,57 @@ using Shouldly; using Xunit; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public class BigIntValueTests : TestContractTestBase { - public class BigIntValueTests : TestContractTestBase + public BigIntValueTests() { - public BigIntValueTests() - { - InitializeTestContracts(); - } + InitializeTestContracts(); + } - [Fact] - public async Task BasicOperationTest() + [Fact] + public async Task BasicOperationTest() + { { + var transactionResult = (await BigIntValueContractStub.Add.SendAsync(new BigIntValueInput { - var transactionResult = (await BigIntValueContractStub.Add.SendAsync(new BigIntValueInput - { - Foo = - "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000", - Bar = "100" - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Foo = + "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000", + Bar = "100" + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var result = (await BigIntValueContractStub.Get.CallAsync( - new Empty())).Value; - result.ShouldBe( - "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100" - .Replace("_", string.Empty)); - } + var result = (await BigIntValueContractStub.Get.CallAsync( + new Empty())).Value; + result.ShouldBe( + "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100" + .Replace("_", string.Empty)); + } + { + var transactionResult = (await BigIntValueContractStub.Sub.SendAsync(new BigIntValueInput { - var transactionResult = (await BigIntValueContractStub.Sub.SendAsync(new BigIntValueInput - { - Foo = - "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100", - Bar = "100" - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Foo = + "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100", + Bar = "100" + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var result = (await BigIntValueContractStub.Get.CallAsync( - new Empty())).Value; - result.ShouldBe( - "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000" - .Replace("_", string.Empty)); - } + var result = (await BigIntValueContractStub.Get.CallAsync( + new Empty())).Value; + result.ShouldBe( + "100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000" + .Replace("_", string.Empty)); } + } - [Fact] - public async Task CompareTest() - { - var foo = new BigIntValue {Value = "100"}; - var bar = new BigIntValue {Value = "101"}; - (foo > bar).ShouldBeFalse(); - (foo <= bar).ShouldBeTrue(); - } + [Fact] + public async Task CompareTest() + { + var foo = new BigIntValue { Value = "100" }; + var bar = new BigIntValue { Value = "101" }; + (foo > bar).ShouldBeFalse(); + (foo <= bar).ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/ContractBasicTests.cs b/test/AElf.Contracts.TestContract.Tests/ContractBasicTests.cs index 8ccc0fff3f..0600f1dc8f 100644 --- a/test/AElf.Contracts.TestContract.Tests/ContractBasicTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/ContractBasicTests.cs @@ -4,9 +4,7 @@ using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicFunction; using AElf.Contracts.TestContract.BasicFunctionWithParallel; -using AElf.ContractTestKit; using AElf.Cryptography; -using AElf.CSharp.Core; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; @@ -19,238 +17,155 @@ using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; +using BetInput = AElf.Contracts.TestContract.BasicFunction.BetInput; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public sealed class ContractBasicTests : TestContractTestBase { - public sealed class ContractBasicTests : TestContractTestBase + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IMiningService _miningService; + private readonly ITransactionResultManager _transactionResultManager; + + public ContractBasicTests() { - private readonly IBlockchainService _blockchainService; - private readonly IMiningService _miningService; - private readonly IBlockAttachService _blockAttachService; - private readonly ITransactionResultManager _transactionResultManager; + _blockchainService = GetRequiredService(); + _miningService = GetRequiredService(); + _blockAttachService = GetRequiredService(); + _transactionResultManager = GetRequiredService(); + InitializeTestContracts(); + } - public ContractBasicTests() - { - _blockchainService = GetRequiredService(); - _miningService = GetRequiredService(); - _blockAttachService = GetRequiredService(); - _transactionResultManager = GetRequiredService(); - InitializeTestContracts(); - } + [Fact] + public async Task Initialize_MultiTimesContract_Test() + { + var transactionResult = + (await TestBasicFunctionContractStub.InitialBasicFunctionContract.SendWithExceptionAsync( + new InitialBasicContractInput + { + ContractName = "Test initialize again", + MinValue = 1000, + MaxValue = 10000, + Manager = Accounts[0].Address + })).TransactionResult; - [Fact] - public async Task Initialize_MultiTimesContract_Test() - { - var transactionResult = - (await TestBasicFunctionContractStub.InitialBasicFunctionContract.SendWithExceptionAsync( - new AElf.Contracts.TestContract.BasicFunction.InitialBasicContractInput - { - ContractName = "Test initialize again", - MinValue = 1000, - MaxValue = 10000, - Manager = Accounts[0].Address - })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); - } + [Fact] + public async Task DeployContract_With_Two_Branch() + { + var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + var startBlockHeight = blockHeader.Height; + var startBlockHash = blockHeader.GetHash(); - [Fact] - public async Task DeployContract_With_Two_Branch() + Address contractAddress; + //branch one { - var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - var startBlockHeight = blockHeader.Height; - var startBlockHash = blockHeader.GetHash(); - - Address contractAddress; - //branch one - { - var t = (await BasicContractZeroStub.DeploySmartContract.SendAsync( - new ContractDeploymentInput - { - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunctionWithParallel")) - .Value), - Category = KernelConstants.CodeCoverageRunnerCategory - } - )); - var transactionResult = t.TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - contractAddress = Address.Parser.ParseFrom(transactionResult.ReturnValue); - blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - - var queryTwoUserWinMoneyInput = new QueryTwoUserWinMoneyInput + var t = await BasicContractZeroStub.DeploySmartContract.SendAsync( + new ContractDeploymentInput { - First = Accounts[0].Address, - Second = Accounts[1].Address - }.ToByteString(); - var queryTwoUserWinMoneyTransaction = CreateTransaction(DefaultSender, contractAddress, - "QueryTwoUserWinMoney", queryTwoUserWinMoneyInput, blockHeader.Height, blockHeader.GetHash()); - var branchOneBlock = await ExecuteAsync(queryTwoUserWinMoneyTransaction, blockHeader.Height, - blockHeader.GetHash()); - await _blockAttachService.AttachBlockAsync(branchOneBlock); - - var queryTwoUserWinMoneyTransactionResult = - await _transactionResultManager.GetTransactionResultAsync(queryTwoUserWinMoneyTransaction - .GetHash(), branchOneBlock.Header.GetHash()); - queryTwoUserWinMoneyTransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunctionWithParallel")) + .Value), + Category = KernelConstants.CodeCoverageRunnerCategory + } + ); + var transactionResult = t.TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + contractAddress = Address.Parser.ParseFrom(transactionResult.ReturnValue); + blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - //branch two + var queryTwoUserWinMoneyInput = new QueryTwoUserWinMoneyInput { - var transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), startBlockHeight, - startBlockHash); - var branchTwoBlock = await ExecuteAsync(transaction, startBlockHeight, startBlockHash); - await _blockAttachService.AttachBlockAsync(branchTwoBlock); - - transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), - branchTwoBlock.Height, - branchTwoBlock.GetHash()); - branchTwoBlock = await ExecuteAsync(transaction, branchTwoBlock.Height, branchTwoBlock.GetHash()); - await _blockAttachService.AttachBlockAsync(branchTwoBlock); - - transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), - branchTwoBlock.Height, - branchTwoBlock.GetHash()); - branchTwoBlock = await ExecuteAsync(transaction, branchTwoBlock.Height, branchTwoBlock.GetHash()); - await _blockAttachService.AttachBlockAsync(branchTwoBlock); - - var queryTwoUserWinMoneyInput = new QueryTwoUserWinMoneyInput - { - First = Accounts[0].Address, - Second = Accounts[1].Address - }.ToByteString(); - var queryTwoUserWinMoneyTransaction = CreateTransaction(DefaultSender, contractAddress, - "QueryTwoUserWinMoney", queryTwoUserWinMoneyInput, branchTwoBlock.Height, branchTwoBlock.GetHash()); - - branchTwoBlock = await ExecuteAsync(queryTwoUserWinMoneyTransaction, branchTwoBlock.Height, - branchTwoBlock.GetHash()); - await _blockAttachService.AttachBlockAsync(branchTwoBlock); - var queryTwoUserWinMoneyTransactionResult = - await _transactionResultManager.GetTransactionResultAsync(queryTwoUserWinMoneyTransaction.GetHash(), - branchTwoBlock.Header.GetDisambiguatingHash()); - queryTwoUserWinMoneyTransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - queryTwoUserWinMoneyTransactionResult.Error.ShouldContain("Invalid contract address"); - } + First = Accounts[0].Address, + Second = Accounts[1].Address + }.ToByteString(); + var queryTwoUserWinMoneyTransaction = CreateTransaction(DefaultSender, contractAddress, + "QueryTwoUserWinMoney", queryTwoUserWinMoneyInput, blockHeader.Height, blockHeader.GetHash()); + var branchOneBlock = await ExecuteAsync(queryTwoUserWinMoneyTransaction, blockHeader.Height, + blockHeader.GetHash()); + await _blockAttachService.AttachBlockAsync(branchOneBlock); + + var queryTwoUserWinMoneyTransactionResult = + await _transactionResultManager.GetTransactionResultAsync(queryTwoUserWinMoneyTransaction + .GetHash(), branchOneBlock.Header.GetHash()); + queryTwoUserWinMoneyTransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact] - public async Task UpdateContract_WithOwner_Test() + //branch two { - //update with same code - { - var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendWithExceptionAsync( - new ContractUpdateInput - { - Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value) - } - )).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Code is not changed").ShouldBeTrue(); - } + var transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), startBlockHeight, + startBlockHash); + var branchTwoBlock = await ExecuteAsync(transaction, startBlockHeight, startBlockHash); + await _blockAttachService.AttachBlockAsync(branchTwoBlock); - //different code + transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), + branchTwoBlock.Height, + branchTwoBlock.GetHash()); + branchTwoBlock = await ExecuteAsync(transaction, branchTwoBlock.Height, branchTwoBlock.GetHash()); + await _blockAttachService.AttachBlockAsync(branchTwoBlock); + + transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), + branchTwoBlock.Height, + branchTwoBlock.GetHash()); + branchTwoBlock = await ExecuteAsync(transaction, branchTwoBlock.Height, branchTwoBlock.GetHash()); + await _blockAttachService.AttachBlockAsync(branchTwoBlock); + + var queryTwoUserWinMoneyInput = new QueryTwoUserWinMoneyInput { - var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( - new ContractUpdateInput - { - Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) - } - )).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); - //execute new action method - var transactionResult1 = (await basic11ContractStub.UpdateStopBet.SendAsync( - new Empty())).TransactionResult; - transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); - - //call new view method - var result = (await basic11ContractStub.QueryBetStatus.CallAsync( - new Empty())).BoolValue; - result.ShouldBeTrue(); - } + First = Accounts[0].Address, + Second = Accounts[1].Address + }.ToByteString(); + var queryTwoUserWinMoneyTransaction = CreateTransaction(DefaultSender, contractAddress, + "QueryTwoUserWinMoney", queryTwoUserWinMoneyInput, branchTwoBlock.Height, branchTwoBlock.GetHash()); + + branchTwoBlock = await ExecuteAsync(queryTwoUserWinMoneyTransaction, branchTwoBlock.Height, + branchTwoBlock.GetHash()); + await _blockAttachService.AttachBlockAsync(branchTwoBlock); + var queryTwoUserWinMoneyTransactionResult = + await _transactionResultManager.GetTransactionResultAsync(queryTwoUserWinMoneyTransaction.GetHash(), + branchTwoBlock.Header.GetDisambiguatingHash()); + queryTwoUserWinMoneyTransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + queryTwoUserWinMoneyTransactionResult.Error.ShouldContain("Invalid contract address"); } + } - [Fact] - public async Task UpdateContract_And_Call_Old_Method_Test() + [Fact] + public async Task UpdateContract_WithOwner_Test() + { + //update with same code { - var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( + var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendWithExceptionAsync( new ContractUpdateInput { Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value) } )).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //execute new action method - transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( - new AElf.Contracts.TestContract.BasicFunction.BetInput - { - Int64Value = 100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //check result - var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( - DefaultSender)).Int64Value; - if (winData > 0) - { - winData.ShouldBeGreaterThanOrEqualTo(100); - return; - } - - var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( - DefaultSender)).Int64Value; - (winData + loseData).ShouldBe(100); - - //execute again - transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( - new AElf.Contracts.TestContract.BasicFunction.BetInput - { - Int64Value = 100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //check result - loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( - DefaultSender)).Int64Value; - (winData + loseData).ShouldBe(200); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Code is not changed").ShouldBeTrue(); } - [Fact] - public async Task UpdateContract_Attach_After_ReadOnly_Transaction() + //different code { - var chain = await _blockchainService.GetChainAsync(); - var blockHeight = chain.BestChainHeight; - var blockHash = chain.BestChainHash; - - var input = new ContractUpdateInput - { - Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) - }.ToByteString(); - var transaction = CreateTransaction(DefaultSender, ContractZeroAddress, - nameof(BasicContractZeroStub.UpdateSmartContract), input, blockHeight, blockHash); - var block = await ExecuteAsync(transaction, blockHeight, blockHash); - var transactionResult = - await _transactionResultManager.GetTransactionResultAsync(transaction.GetHash(), - block.Header.GetDisambiguatingHash()); - - var basicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); - await basicFunctionContractStub.QueryWinMoney.CallAsync(new Empty()); + var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( + new ContractUpdateInput + { + Address = BasicFunctionContractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) + } + )).TransactionResult; - await _blockAttachService.AttachBlockAsync(block); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); -// //execute new action method + //execute new action method var transactionResult1 = (await basic11ContractStub.UpdateStopBet.SendAsync( new Empty())).TransactionResult; transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); @@ -259,136 +174,219 @@ await _transactionResultManager.GetTransactionResultAsync(transaction.GetHash(), var result = (await basic11ContractStub.QueryBetStatus.CallAsync( new Empty())).BoolValue; result.ShouldBeTrue(); - - await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, block.GetHash()); } + } + + [Fact] + public async Task UpdateContract_And_Call_Old_Method_Test() + { + var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( + new ContractUpdateInput + { + Address = BasicFunctionContractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) + } + )).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task UpdateContract_With_Two_Branch() + //execute new action method + transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( + new BetInput + { + Int64Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //check result + var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( + DefaultSender)).Int64Value; + if (winData > 0) { - var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - var startBlockHeight = blockHeader.Height; - var startBlockHash = blockHeader.GetHash(); + winData.ShouldBeGreaterThanOrEqualTo(100); + return; + } - var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( - new ContractUpdateInput - { - Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) - } - )).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( + DefaultSender)).Int64Value; + (winData + loseData).ShouldBe(100); - var basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); + //execute again + transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( + new BetInput + { + Int64Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + //check result + loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( + DefaultSender)).Int64Value; + (winData + loseData).ShouldBe(200); + } + + [Fact] + public async Task UpdateContract_Attach_After_ReadOnly_Transaction() + { + var chain = await _blockchainService.GetChainAsync(); + var blockHeight = chain.BestChainHeight; + var blockHash = chain.BestChainHash; + + var input = new ContractUpdateInput + { + Address = BasicFunctionContractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) + }.ToByteString(); + var transaction = CreateTransaction(DefaultSender, ContractZeroAddress, + nameof(BasicContractZeroStub.UpdateSmartContract), input, blockHeight, blockHash); + var block = await ExecuteAsync(transaction, blockHeight, blockHash); + var transactionResult = + await _transactionResultManager.GetTransactionResultAsync(transaction.GetHash(), + block.Header.GetDisambiguatingHash()); + + var basicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); + await basicFunctionContractStub.QueryWinMoney.CallAsync(new Empty()); + + await _blockAttachService.AttachBlockAsync(block); + + var basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); // //execute new action method - var transactionResult1 = (await basic11ContractStub.UpdateStopBet.SendAsync( - new Empty())).TransactionResult; - transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionResult1 = (await basic11ContractStub.UpdateStopBet.SendAsync( + new Empty())).TransactionResult; + transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); - var transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), startBlockHeight, - startBlockHash); - var block = await ExecuteAsync(transaction, startBlockHeight, startBlockHash); - await _blockAttachService.AttachBlockAsync(block); + //call new view method + var result = (await basic11ContractStub.QueryBetStatus.CallAsync( + new Empty())).BoolValue; + result.ShouldBeTrue(); - transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), block.Height, - block.GetHash()); - block = await ExecuteAsync(transaction, block.Height, block.GetHash()); - await _blockAttachService.AttachBlockAsync(block); - - var input = new Empty().ToByteString(); - var failedTransaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, - nameof(basic11ContractStub.UpdateStopBet), input, block.Height, block.GetHash()); - block = await ExecuteAsync(failedTransaction, block.Height, block.GetHash()); - await _blockAttachService.AttachBlockAsync(block); - - transactionResult = - await _transactionResultManager.GetTransactionResultAsync(failedTransaction.GetHash(), - block.Header.GetDisambiguatingHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Failed to find handler for UpdateStopBet."); + await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, block.GetHash()); + } - input = new ContractUpdateInput - { - Address = BasicFunctionContractAddress, - Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value) - }.ToByteString(); - var updateTransaction = CreateTransaction(DefaultSender, ContractZeroAddress, - nameof(BasicContractZeroStub.UpdateSmartContract), input, block.Height, block.GetHash()); - var updateBlock = await ExecuteAsync(updateTransaction, block.Height, block.GetHash()); - await _blockAttachService.AttachBlockAsync(updateBlock); -// - transactionResult = - await _transactionResultManager.GetTransactionResultAsync(updateTransaction.GetHash(), - updateBlock.Header.GetDisambiguatingHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Code is not changed").ShouldBeTrue(); + [Fact] + public async Task UpdateContract_With_Two_Branch() + { + var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + var startBlockHeight = blockHeader.Height; + var startBlockHash = blockHeader.GetHash(); - input = new ContractUpdateInput + var transactionResult = (await BasicContractZeroStub.UpdateSmartContract.SendAsync( + new ContractUpdateInput { Address = BasicFunctionContractAddress, Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) - }.ToByteString(); - updateTransaction = CreateTransaction(DefaultSender, ContractZeroAddress, - nameof(BasicContractZeroStub.UpdateSmartContract), input, updateBlock.Height, updateBlock.GetHash()); - updateBlock = await ExecuteAsync(updateTransaction, updateBlock.Height, updateBlock.GetHash()); - await _blockAttachService.AttachBlockAsync(updateBlock); - - transactionResult = - await _transactionResultManager.GetTransactionResultAsync(updateTransaction.GetHash(), - updateBlock.Header.GetDisambiguatingHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); - //execute new action method - transactionResult = (await basic11ContractStub.UpdateStopBet.SendAsync( - new Empty())).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + )).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //call new view method - var result = (await basic11ContractStub.QueryBetStatus.CallAsync( - new Empty())).BoolValue; - result.ShouldBeTrue(); - } + var basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); +// //execute new action method + var transactionResult1 = (await basic11ContractStub.UpdateStopBet.SendAsync( + new Empty())).TransactionResult; + transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); + + var transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), startBlockHeight, + startBlockHash); + var block = await ExecuteAsync(transaction, startBlockHeight, startBlockHash); + await _blockAttachService.AttachBlockAsync(block); + + transaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(TestBasicFunctionContractStub.QueryWinMoney), new Empty().ToByteString(), block.Height, + block.GetHash()); + block = await ExecuteAsync(transaction, block.Height, block.GetHash()); + await _blockAttachService.AttachBlockAsync(block); + + var input = new Empty().ToByteString(); + var failedTransaction = CreateTransaction(DefaultSender, BasicFunctionContractAddress, + nameof(basic11ContractStub.UpdateStopBet), input, block.Height, block.GetHash()); + block = await ExecuteAsync(failedTransaction, block.Height, block.GetHash()); + await _blockAttachService.AttachBlockAsync(block); + + transactionResult = + await _transactionResultManager.GetTransactionResultAsync(failedTransaction.GetHash(), + block.Header.GetDisambiguatingHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Failed to find handler for UpdateStopBet."); + + input = new ContractUpdateInput + { + Address = BasicFunctionContractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value) + }.ToByteString(); + var updateTransaction = CreateTransaction(DefaultSender, ContractZeroAddress, + nameof(BasicContractZeroStub.UpdateSmartContract), input, block.Height, block.GetHash()); + var updateBlock = await ExecuteAsync(updateTransaction, block.Height, block.GetHash()); + await _blockAttachService.AttachBlockAsync(updateBlock); +// + transactionResult = + await _transactionResultManager.GetTransactionResultAsync(updateTransaction.GetHash(), + updateBlock.Header.GetDisambiguatingHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Code is not changed").ShouldBeTrue(); - private Transaction CreateTransaction(Address from, Address to, string methodName, - ByteString parameters, long blockHeight, Hash blockHash) + input = new ContractUpdateInput { - var transaction = new Transaction() - { - From = from, - To = to, - MethodName = methodName, - Params = parameters, - RefBlockNumber = blockHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(blockHash), - }; - var signature = CryptoHelper.SignWithPrivateKey(DefaultSenderKeyPair.PrivateKey, - transaction.GetHash().Value.ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - return transaction; - } + Address = BasicFunctionContractAddress, + Code = ByteString.CopyFrom(Codes.Single(kv => kv.Key.EndsWith("BasicUpdate")).Value) + }.ToByteString(); + updateTransaction = CreateTransaction(DefaultSender, ContractZeroAddress, + nameof(BasicContractZeroStub.UpdateSmartContract), input, updateBlock.Height, updateBlock.GetHash()); + updateBlock = await ExecuteAsync(updateTransaction, updateBlock.Height, updateBlock.GetHash()); + await _blockAttachService.AttachBlockAsync(updateBlock); + + transactionResult = + await _transactionResultManager.GetTransactionResultAsync(updateTransaction.GetHash(), + updateBlock.Header.GetDisambiguatingHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + basic11ContractStub = GetTestBasicUpdateContractStub(DefaultSenderKeyPair); + //execute new action method + transactionResult = (await basic11ContractStub.UpdateStopBet.SendAsync( + new Empty())).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //call new view method + var result = (await basic11ContractStub.QueryBetStatus.CallAsync( + new Empty())).BoolValue; + result.ShouldBeTrue(); + } - private async Task ExecuteAsync(Transaction transaction, long previousBlockHeight, - Hash previousBlockHash) + private Transaction CreateTransaction(Address from, Address to, string methodName, + ByteString parameters, long blockHeight, Hash blockHash) + { + var transaction = new Transaction { - var transactionList = new List(); - if (transaction != null) transactionList.Add(transaction); - var block = (await _miningService.MineAsync( - new RequestMiningDto - { - PreviousBlockHash = previousBlockHash, PreviousBlockHeight = previousBlockHeight, - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - TransactionCountLimit = int.MaxValue - }, - transactionList, - DateTime.UtcNow.ToTimestamp())).Block; - - if (transaction != null) - await _blockchainService.AddTransactionsAsync(new List {transaction}); - await _blockchainService.AddBlockAsync(block); - return block; - } + From = from, + To = to, + MethodName = methodName, + Params = parameters, + RefBlockNumber = blockHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(blockHash) + }; + var signature = CryptoHelper.SignWithPrivateKey(DefaultSenderKeyPair.PrivateKey, + transaction.GetHash().Value.ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + return transaction; + } + + private async Task ExecuteAsync(Transaction transaction, long previousBlockHeight, + Hash previousBlockHash) + { + var transactionList = new List(); + if (transaction != null) transactionList.Add(transaction); + var block = (await _miningService.MineAsync( + new RequestMiningDto + { + PreviousBlockHash = previousBlockHash, PreviousBlockHeight = previousBlockHeight, + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + TransactionCountLimit = int.MaxValue + }, + transactionList, + DateTime.UtcNow.ToTimestamp())).Block; + + if (transaction != null) + await _blockchainService.AddTransactionsAsync(new List { transaction }); + await _blockchainService.AddBlockAsync(block); + return block; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/ContractExternalCallTests.cs b/test/AElf.Contracts.TestContract.Tests/ContractExternalCallTests.cs index b4fdebe08b..8a330e139c 100644 --- a/test/AElf.Contracts.TestContract.Tests/ContractExternalCallTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/ContractExternalCallTests.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicFunction; using AElf.Contracts.TestContract.BasicSecurity; @@ -7,101 +6,99 @@ using Shouldly; using Xunit; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public class ContractExternalCallTests : TestContractTestBase { - public class ContractExternalCallTests : TestContractTestBase + public ContractExternalCallTests() { - public ContractExternalCallTests() - { - InitializeTestContracts(); - } + InitializeTestContracts(); + } - [Fact] - public async Task Internal_Execute_And_Call_Test() - { - //execute method - var transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( - new BetInput - { - Int64Value = 100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Internal_Execute_And_Call_Test() + { + //execute method + var transactionResult = (await TestBasicFunctionContractStub.UserPlayBet.SendAsync( + new BetInput + { + Int64Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //call method - var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( - DefaultSender)).Int64Value; - var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( - DefaultSender)).Int64Value; - (winData + loseData).ShouldBeGreaterThanOrEqualTo(100); - } + //call method + var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( + DefaultSender)).Int64Value; + var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( + DefaultSender)).Int64Value; + (winData + loseData).ShouldBeGreaterThanOrEqualTo(100); + } + + [Fact] + public async Task External_Execute_And_Call_Test() + { + //execute method + var transactionResult = (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendAsync( + new Int64Input + { + Int64Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task External_Execute_And_Call_Test() + //call method + var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( + DefaultSender)).Int64Value; + if (winData > 0) { - //execute method - var transactionResult = (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendAsync( + winData.ShouldBeGreaterThanOrEqualTo(100); + return; + } + + var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( + DefaultSender)).Int64Value; + (winData + loseData).ShouldBeLessThan(100); + } + + [Fact] + public async Task Internal_ExecuteFailed_Test() + { + var transactionResult = + (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendWithExceptionAsync( new Int64Input { - Int64Value = 100 + Int64Value = 5 })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //call method - var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( - DefaultSender)).Int64Value; - if (winData > 0) - { - winData.ShouldBeGreaterThanOrEqualTo(100); - return; - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( - DefaultSender)).Int64Value; - (winData + loseData).ShouldBeLessThan(100); - - } - - [Fact] - public async Task Internal_ExecuteFailed_Test() - { - var transactionResult = - (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendWithExceptionAsync( - new Int64Input - { - Int64Value = 5 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + var result = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( + new Empty())).Int64Value; + result.ShouldBe(0); + } - var result = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( - new Empty())).Int64Value; - result.ShouldBe(0); - } + [Fact] + public async Task External_ExecuteFailed_Test() + { + await TestBasicSecurityContractStub.TestInt64State.SendAsync( + new Int64Input + { + Int64Value = long.MaxValue + }); - [Fact] - public async Task External_ExecuteFailed_Test() - { - await TestBasicSecurityContractStub.TestInt64State.SendAsync( + var transactionResult = + (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendWithExceptionAsync( new Int64Input { - Int64Value = Int64.MaxValue - }); - - var transactionResult = - (await TestBasicSecurityContractStub.TestExecuteExternalMethod.SendWithExceptionAsync( - new Int64Input - { - Int64Value = 500 - })).TransactionResult; + Int64Value = 500 + })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( - DefaultSender)).Int64Value; - winData.ShouldBe(0); + var winData = (await TestBasicFunctionContractStub.QueryUserWinMoney.CallAsync( + DefaultSender)).Int64Value; + winData.ShouldBe(0); - var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( - DefaultSender)).Int64Value; - loseData.ShouldBe(0); - } + var loseData = (await TestBasicFunctionContractStub.QueryUserLoseMoney.CallAsync( + DefaultSender)).Int64Value; + loseData.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/ContractMethodTests.cs b/test/AElf.Contracts.TestContract.Tests/ContractMethodTests.cs index 8d390ba89b..e8852abc7c 100644 --- a/test/AElf.Contracts.TestContract.Tests/ContractMethodTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/ContractMethodTests.cs @@ -1,362 +1,359 @@ using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicFunction; using AElf.Contracts.TestContract.BasicSecurity; -using AElf.ContractTestKit; -using AElf.Kernel; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -using StringInput = AElf.Contracts.TestContract.BasicSecurity.StringInput; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public class ContractMethodTests : TestContractTestBase { - public class ContractMethodTests : TestContractTestBase + public ContractMethodTests() + { + InitializeTestContracts(); + } + + #region Basic1 methods Test + + [Fact] + public async Task Basic1Contract_UpdateBetLimit_WithoutPermission_Test() + { + var transactionResult = (await TestBasicFunctionContractStub.UpdateBetLimit.SendWithExceptionAsync( + new BetLimitInput + { + MinValue = 50, + MaxValue = 100 + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Only manager can perform this action").ShouldBeTrue(); + } + + [Fact] + public async Task Basic1Contract_UpdateBetLimit_WithException_Test() + { + var managerStub = GetTestBasicFunctionContractStub(Accounts[1].KeyPair); + var transactionResult = (await managerStub.UpdateBetLimit.SendWithExceptionAsync( + new BetLimitInput + { + MinValue = 100, + MaxValue = 50 + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Invalid min/max value input setting").ShouldBeTrue(); + } + + [Fact] + public async Task Basic1Contract_UpdateBetLimit_Success_Test() + { + var managerStub = GetTestBasicFunctionContractStub(Accounts[1].KeyPair); + var transactionResult = (await managerStub.UpdateBetLimit.SendAsync( + new BetLimitInput + { + MinValue = 100, + MaxValue = 200 + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task Basic1Contract_QueryMethod_Test() { - public ContractMethodTests() + for (var i = 0; i < 10; i++) { - InitializeTestContracts(); + var testUser = Accounts[i].KeyPair; + var basicStub = GetTestBasicFunctionContractStub(testUser); + await basicStub.UserPlayBet.SendAsync(new BetInput + { + Int64Value = 100 + }); } - #region Basic1 methods Test - [Fact] - public async Task Basic1Contract_UpdateBetLimit_WithoutPermission_Test() + var winMoney = (await TestBasicFunctionContractStub.QueryWinMoney.CallAsync( + new Empty())).Int64Value; + winMoney.ShouldBe(1000); + + var rewardMoney = (await TestBasicFunctionContractStub.QueryRewardMoney.CallAsync( + new Empty())).Int64Value; + rewardMoney.ShouldBeGreaterThanOrEqualTo(0); + } + + [Fact] + public async Task BasicContract_ValidateOrigin_Success_Test() + { + var transaction1 = await TestBasicSecurityContractStub.TestOriginAddress.SendAsync(DefaultSender); + transaction1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transaction2 = await TestBasicFunctionContractStub.ValidateOrigin.SendAsync(DefaultSender); + transaction2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + #endregion + + #region BasicSecurity methods Test + + [Fact] + public async Task BasicSecurity_BoolType_Test() + { + await TestBasicSecurityContractStub.TestBoolState.SendAsync(new BoolInput { - var transactionResult = (await TestBasicFunctionContractStub.UpdateBetLimit.SendWithExceptionAsync( - new BetLimitInput - { - MinValue = 50, - MaxValue = 100 - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Only manager can perform this action").ShouldBeTrue(); - } + BoolValue = false + }); + + var queryResult = (await TestBasicSecurityContractStub.QueryBoolState.CallAsync(new Empty() + )).BoolValue; + + queryResult.ShouldBeFalse(); + } - [Fact] - public async Task Basic1Contract_UpdateBetLimit_WithException_Test() + [Fact] + public async Task BasicSecurity_Int32Type_Test() + { + await TestBasicSecurityContractStub.TestInt32State.SendAsync(new Int32Input { - var managerStub = GetTestBasicFunctionContractStub(Accounts[1].KeyPair); - var transactionResult = (await managerStub.UpdateBetLimit.SendWithExceptionAsync( - new BetLimitInput - { - MinValue = 100, - MaxValue = 50 - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Invalid min/max value input setting").ShouldBeTrue(); - } + Int32Value = 30 + }); + + var queryResult = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync(new Empty() + )).Int32Value; + + queryResult.ShouldBe(30); + } - [Fact] - public async Task Basic1Contract_UpdateBetLimit_Success_Test() + [Fact] + public async Task BasicSecurity_UInt32Type_Test() + { + await TestBasicSecurityContractStub.TestUInt32State.SendAsync(new UInt32Input { - var managerStub = GetTestBasicFunctionContractStub(Accounts[1].KeyPair); - var transactionResult = (await managerStub.UpdateBetLimit.SendAsync( - new BetLimitInput - { - MinValue = 100, - MaxValue = 200 - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + UInt32Value = 45 + }); + + var queryResult = (await TestBasicSecurityContractStub.QueryUInt32State.CallAsync(new Empty() + )).UInt32Value; - [Fact] - public async Task Basic1Contract_QueryMethod_Test() + queryResult.ShouldBe(45U); + } + + [Fact] + public async Task BasicSecurity_Int64Type_Test() + { + await TestBasicSecurityContractStub.TestInt64State.SendAsync(new Int64Input { - for (int i = 0; i < 10; i++) - { - var testUser = Accounts[i].KeyPair; - var basicStub = GetTestBasicFunctionContractStub(testUser); - await basicStub.UserPlayBet.SendAsync(new BetInput - { - Int64Value = 100 - }); - } + Int64Value = 45 + }); - var winMoney = (await TestBasicFunctionContractStub.QueryWinMoney.CallAsync( - new Empty())).Int64Value; - winMoney.ShouldBe(1000); + var queryResult = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync(new Empty() + )).Int64Value; - var rewardMoney = (await TestBasicFunctionContractStub.QueryRewardMoney.CallAsync( - new Empty())).Int64Value; - rewardMoney.ShouldBeGreaterThanOrEqualTo(0); - } + queryResult.ShouldBe(45L); + } - [Fact] - public async Task BasicContract_ValidateOrigin_Success_Test() + [Fact] + public async Task BasicSecurity_UInt64Type_Test() + { + await TestBasicSecurityContractStub.TestUInt64State.SendAsync(new UInt64Input { - var transaction1 = await TestBasicSecurityContractStub.TestOriginAddress.SendAsync(DefaultSender); - transaction1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + UInt64Value = 45 + }); - var transaction2 = await TestBasicFunctionContractStub.ValidateOrigin.SendAsync(DefaultSender); - transaction2.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var queryResult = (await TestBasicSecurityContractStub.QueryUInt64State.CallAsync(new Empty() + )).UInt64Value; - #endregion - - #region BasicSecurity methods Test + queryResult.ShouldBe(45UL); + } - [Fact] - public async Task BasicSecurity_BoolType_Test() + [Fact] + public async Task BasicSecurity_StringType_Test() + { + await TestBasicSecurityContractStub.TestStringState.SendAsync(new StringInput { - await TestBasicSecurityContractStub.TestBoolState.SendAsync(new BoolInput - { - BoolValue = false - }); + StringValue = "TestContract" + }); - var queryResult = (await TestBasicSecurityContractStub.QueryBoolState.CallAsync(new Empty() - )).BoolValue; - - queryResult.ShouldBeFalse(); - } + var queryResult = (await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty() + )).StringValue; + queryResult.ShouldBe("TestContract"); + } - [Fact] - public async Task BasicSecurity_Int32Type_Test() + [Fact] + public async Task BasicSecurity_BytesType_Test() + { + await TestBasicSecurityContractStub.TestBytesState.SendAsync(new BytesInput { - await TestBasicSecurityContractStub.TestInt32State.SendAsync(new Int32Input - { - Int32Value = 30 - }); + BytesValue = ByteString.CopyFromUtf8("test") + }); - var queryResult = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync(new Empty() - )).Int32Value; - - queryResult.ShouldBe(30); - } + var queryResult = (await TestBasicSecurityContractStub.QueryBytesState.CallAsync(new Empty() + )).BytesValue; + queryResult.ShouldBe(ByteString.CopyFromUtf8("test")); + } - [Fact] - public async Task BasicSecurity_UInt32Type_Test() + [Fact] + public async Task BasicSecurity_ProtobufType_Test() + { + await TestBasicSecurityContractStub.TestProtobufState.SendAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestUInt32State.SendAsync(new UInt32Input + ProtobufValue = new ProtobufMessage { - UInt32Value = 45 - }); + BoolValue = false, + Int64Value = 100L, + StringValue = "proto buf" + } + }); - var queryResult = (await TestBasicSecurityContractStub.QueryUInt32State.CallAsync(new Empty() - )).UInt32Value; - - queryResult.ShouldBe(45U); - } - - [Fact] - public async Task BasicSecurity_Int64Type_Test() + var queryResult = (await TestBasicSecurityContractStub.QueryProtobufState.CallAsync(new Empty() + )).ProtobufValue; + queryResult.BoolValue.ShouldBeFalse(); + queryResult.Int64Value.ShouldBe(100L); + queryResult.StringValue.ShouldBe("proto buf"); + } + + [Fact] + public async Task BasicSecurity_Complex1Type_Test() + { + await TestBasicSecurityContractStub.TestComplex1State.SendAsync(new Complex1Input { - await TestBasicSecurityContractStub.TestInt64State.SendAsync(new Int64Input - { - Int64Value = 45 - }); + BoolValue = true, + Int32Value = 80 + }); - var queryResult = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync(new Empty() - )).Int64Value; - - queryResult.ShouldBe(45L); - } - - [Fact] - public async Task BasicSecurity_UInt64Type_Test() + var queryResult = await TestBasicSecurityContractStub.QueryComplex1State.CallAsync(new Empty()); + queryResult.BoolValue.ShouldBeTrue(); + queryResult.Int32Value.ShouldBe(80); + } + + [Fact] + public async Task BasicSecurity_Complex2Type_Test() + { + await TestBasicSecurityContractStub.TestComplex2State.SendAsync(new Complex2Input { - await TestBasicSecurityContractStub.TestUInt64State.SendAsync(new UInt64Input + BoolData = new BoolInput { - UInt64Value = 45 - }); + BoolValue = true + }, + Int32Data = new Int32Input + { + Int32Value = 80 + } + }); - var queryResult = (await TestBasicSecurityContractStub.QueryUInt64State.CallAsync(new Empty() - )).UInt64Value; - - queryResult.ShouldBe(45UL); - } + var queryResult = await TestBasicSecurityContractStub.QueryComplex2State.CallAsync(new Empty()); + queryResult.BoolData.BoolValue.ShouldBeTrue(); + queryResult.Int32Data.Int32Value.ShouldBe(80); + } - [Fact] - public async Task BasicSecurity_StringType_Test() + [Fact] + public async Task Basic_MappedType_Test() + { + await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestStringState.SendAsync(new StringInput + ProtobufValue = new ProtobufMessage { - StringValue = "TestContract" - }); + StringValue = "test1", + Int64Value = 100 + } + }); - var queryResult = (await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty() - )).StringValue; - queryResult.ShouldBe("TestContract"); - } - - [Fact] - public async Task BasicSecurity_BytesType_Test() + //query check + var queryResult = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestBytesState.SendAsync(new BytesInput + ProtobufValue = new ProtobufMessage { - BytesValue = ByteString.CopyFromUtf8("test") - }); - - var queryResult = (await TestBasicSecurityContractStub.QueryBytesState.CallAsync(new Empty() - )).BytesValue; - queryResult.ShouldBe(ByteString.CopyFromUtf8("test")); - } + StringValue = "test0", + Int64Value = 100 + } + }); + queryResult.Int64Value.ShouldBe(0); - [Fact] - public async Task BasicSecurity_ProtobufType_Test() + var queryResult1 = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestProtobufState.SendAsync(new ProtobufInput + ProtobufValue = new ProtobufMessage { - ProtobufValue = new ProtobufMessage - { - BoolValue = false, - Int64Value = 100L, - StringValue = "proto buf" - } - }); + StringValue = "test1", + Int64Value = 100 + } + }); + queryResult1.Int64Value.ShouldBe(100); - var queryResult = (await TestBasicSecurityContractStub.QueryProtobufState.CallAsync(new Empty() - )).ProtobufValue; - queryResult.BoolValue.ShouldBeFalse(); - queryResult.Int64Value.ShouldBe(100L); - queryResult.StringValue.ShouldBe("proto buf"); - } - - [Fact] - public async Task BasicSecurity_Complex1Type_Test() + await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestComplex1State.SendAsync(new Complex1Input - { - BoolValue = true, - Int32Value = 80 - }); - - var queryResult = await TestBasicSecurityContractStub.QueryComplex1State.CallAsync(new Empty()); - queryResult.BoolValue.ShouldBeTrue(); - queryResult.Int32Value.ShouldBe(80); - } + ProtobufValue = new ProtobufMessage + { + StringValue = "test1", + Int64Value = 100 + } + }); - [Fact] - public async Task BasicSecurity_Complex2Type_Test() + queryResult1 = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestComplex2State.SendAsync(new Complex2Input + ProtobufValue = new ProtobufMessage { - BoolData = new BoolInput - { - BoolValue = true - }, - Int32Data = new Int32Input - { - Int32Value = 80 - } - }); + StringValue = "test1", + Int64Value = 100 + } + }); + queryResult1.Int64Value.ShouldBe(200); + } - var queryResult = await TestBasicSecurityContractStub.QueryComplex2State.CallAsync(new Empty()); - queryResult.BoolData.BoolValue.ShouldBeTrue(); - queryResult.Int32Data.Int32Value.ShouldBe(80); - } + [Fact] + public async Task Basic_Mapped1Type_Test() + { + var from = Accounts[0].Address.ToBase58(); + var pairA = "ELF"; + var to = Accounts[1].Address.ToBase58(); + var pairB = "USDT"; - [Fact] - public async Task Basic_MappedType_Test() + var protobufMessage = new ProtobufMessage { - await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = "test1", - Int64Value = 100 - } - }); + Int64Value = 1, + StringValue = "string", + BoolValue = true + }; - //query check - var queryResult = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = "test0", - Int64Value = 100 - } - }); - queryResult.Int64Value.ShouldBe(0); - - var queryResult1 = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = "test1", - Int64Value = 100 - } - }); - queryResult1.Int64Value.ShouldBe(100); - - await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = "test1", - Int64Value = 100 - } - }); - - queryResult1 = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = "test1", - Int64Value = 100 - } - }); - queryResult1.Int64Value.ShouldBe(200); - } - - [Fact] - public async Task Basic_Mapped1Type_Test() + await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput + { + ProtobufValue = protobufMessage + }); + + var queryResult = await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput { - var from = Accounts[0].Address.ToBase58(); - var pairA = "ELF"; - var to = Accounts[1].Address.ToBase58(); - var pairB = "USDT"; + ProtobufValue = protobufMessage + }); + queryResult.ShouldBe(protobufMessage); - var protobufMessage = new ProtobufMessage + queryResult = await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput + { + ProtobufValue = new ProtobufMessage { - Int64Value = 1, + Int64Value = 0, StringValue = "string", BoolValue = true - }; - - await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput() + } + }); + queryResult.ShouldBe(new ProtobufMessage()); + } + + [Fact] + public async Task QueryExternalMethod_Tests() + { + var transactionResult = await TestBasicFunctionContractStub.UserPlayBet.SendAsync( + new BetInput { - ProtobufValue = protobufMessage + Int64Value = 125 }); + transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var queryResult = (await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput - { - ProtobufValue = protobufMessage - })); - queryResult.ShouldBe(protobufMessage); - - queryResult = (await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - Int64Value = 0, - StringValue = "string", - BoolValue = true - } - })); - queryResult.ShouldBe(new ProtobufMessage()); - } + var queryResult1 = await TestBasicSecurityContractStub.QueryExternalMethod1.CallAsync(DefaultSender); + queryResult1.Int64Value.ShouldBe(0); - [Fact] - public async Task QueryExternalMethod_Tests() - { - var transactionResult = await TestBasicFunctionContractStub.UserPlayBet.SendAsync( - new BetInput - { - Int64Value = 125 - }); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var queryResult1 = await TestBasicSecurityContractStub.QueryExternalMethod1.CallAsync(DefaultSender); - queryResult1.Int64Value.ShouldBe(0); - - var queryResult2 = await TestBasicSecurityContractStub.QueryExternalMethod2.CallAsync(DefaultSender); - queryResult2.Int64Value.ShouldBe(125); - } - - #endregion + var queryResult2 = await TestBasicSecurityContractStub.QueryExternalMethod2.CallAsync(DefaultSender); + queryResult2.Int64Value.ShouldBe(125); } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/ContractSecurityTests.cs b/test/AElf.Contracts.TestContract.Tests/ContractSecurityTests.cs index f654a67fa1..81cad8208c 100644 --- a/test/AElf.Contracts.TestContract.Tests/ContractSecurityTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/ContractSecurityTests.cs @@ -1,127 +1,124 @@ -using System; using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicSecurity; -using AElf.Kernel; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public class ContractSecurityTests : TestContractTestBase { - public class ContractSecurityTests : TestContractTestBase + public ContractSecurityTests() + { + InitializeTestContracts(); + } + + [Fact] + public async Task Int32_OverFlow_UpperLimit_Test() + { + await TestBasicSecurityContractStub.TestInt32State.SendAsync( + new Int32Input + { + Int32Value = int.MaxValue + }); + + var resultValue = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( + new Empty())).Int32Value; + resultValue.ShouldBe(int.MaxValue); + + var transactionResult = (await TestBasicSecurityContractStub.TestInt32State.SendWithExceptionAsync( + new Int32Input + { + Int32Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); + + //state not change + var resultValue1 = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( + new Empty())).Int32Value; + resultValue1.ShouldBe(int.MaxValue); + } + + [Fact] + public async Task Int32_OverFlow_LowerLimit_Test() + { + await TestBasicSecurityContractStub.TestInt32State.SendAsync( + new Int32Input + { + Int32Value = int.MinValue + }); + + var resultValue = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( + new Empty())).Int32Value; + resultValue.ShouldBe(int.MinValue); + + var transactionResult = (await TestBasicSecurityContractStub.TestInt32State.SendWithExceptionAsync( + new Int32Input + { + Int32Value = -100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); + + //state not change + var resultValue1 = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( + new Empty())).Int32Value; + resultValue1.ShouldBe(int.MinValue); + } + + [Fact] + public async Task Int64_OverFlow_UpperLimit_Test() + { + await TestBasicSecurityContractStub.TestInt64State.SendAsync( + new Int64Input + { + Int64Value = long.MaxValue + }); + + var resultValue = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( + new Empty())).Int64Value; + resultValue.ShouldBe(long.MaxValue); + + var transactionResult = (await TestBasicSecurityContractStub.TestInt64State.SendWithExceptionAsync( + new Int64Input + { + Int64Value = 100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); + + //state not change + var resultValue1 = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( + new Empty())).Int64Value; + resultValue1.ShouldBe(long.MaxValue); + } + + [Fact] + public async Task Int64_OverFlow_LowerLimit_Test() { - public ContractSecurityTests() - { - InitializeTestContracts(); - } - - [Fact] - public async Task Int32_OverFlow_UpperLimit_Test() - { - await TestBasicSecurityContractStub.TestInt32State.SendAsync( - new Int32Input - { - Int32Value = Int32.MaxValue - }); - - var resultValue = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( - new Empty())).Int32Value; - resultValue.ShouldBe(Int32.MaxValue); - - var transactionResult = (await TestBasicSecurityContractStub.TestInt32State.SendWithExceptionAsync( - new Int32Input - { - Int32Value = 100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); - - //state not change - var resultValue1 = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( - new Empty())).Int32Value; - resultValue1.ShouldBe(Int32.MaxValue); - } - - [Fact] - public async Task Int32_OverFlow_LowerLimit_Test() - { - await TestBasicSecurityContractStub.TestInt32State.SendAsync( - new Int32Input - { - Int32Value = int.MinValue - }); - - var resultValue = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( - new Empty())).Int32Value; - resultValue.ShouldBe(int.MinValue); - - var transactionResult = (await TestBasicSecurityContractStub.TestInt32State.SendWithExceptionAsync( - new Int32Input - { - Int32Value = -100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); - - //state not change - var resultValue1 = (await TestBasicSecurityContractStub.QueryInt32State.CallAsync( - new Empty())).Int32Value; - resultValue1.ShouldBe(int.MinValue); - } - - [Fact] - public async Task Int64_OverFlow_UpperLimit_Test() - { - await TestBasicSecurityContractStub.TestInt64State.SendAsync( - new Int64Input() - { - Int64Value = Int64.MaxValue - }); - - var resultValue = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( - new Empty())).Int64Value; - resultValue.ShouldBe(Int64.MaxValue); - - var transactionResult = (await TestBasicSecurityContractStub.TestInt64State.SendWithExceptionAsync( - new Int64Input - { - Int64Value = 100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); - - //state not change - var resultValue1 = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( - new Empty())).Int64Value; - resultValue1.ShouldBe(Int64.MaxValue); - } - - [Fact] - public async Task Int64_OverFlow_LowerLimit_Test() - { - await TestBasicSecurityContractStub.TestInt64State.SendAsync( - new Int64Input() - { - Int64Value = long.MinValue - }); - - var resultValue = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( - new Empty())).Int64Value; - resultValue.ShouldBe(long.MinValue); - - var transactionResult = (await TestBasicSecurityContractStub.TestInt64State.SendWithExceptionAsync( - new Int64Input - { - Int64Value = -100 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); - - //state not change - var resultValue1 = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( - new Empty())).Int64Value; - resultValue1.ShouldBe(long.MinValue); - } + await TestBasicSecurityContractStub.TestInt64State.SendAsync( + new Int64Input + { + Int64Value = long.MinValue + }); + + var resultValue = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( + new Empty())).Int64Value; + resultValue.ShouldBe(long.MinValue); + + var transactionResult = (await TestBasicSecurityContractStub.TestInt64State.SendWithExceptionAsync( + new Int64Input + { + Int64Value = -100 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("System.OverflowException").ShouldBeTrue(); + + //state not change + var resultValue1 = (await TestBasicSecurityContractStub.QueryInt64State.CallAsync( + new Empty())).Int64Value; + resultValue1.ShouldBe(long.MinValue); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/PatchedContractSecurityTests.cs b/test/AElf.Contracts.TestContract.Tests/PatchedContractSecurityTests.cs index 2126682dba..566f9b6d90 100644 --- a/test/AElf.Contracts.TestContract.Tests/PatchedContractSecurityTests.cs +++ b/test/AElf.Contracts.TestContract.Tests/PatchedContractSecurityTests.cs @@ -1,4 +1,3 @@ -using System; using System.Text; using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicSecurity; @@ -10,450 +9,448 @@ using Xunit; using SmartContractConstants = AElf.Kernel.SmartContract.SmartContractConstants; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +public class PatchedContractSecurityTests : TestContractTestBase { - public class PatchedContractSecurityTests : TestContractTestBase + public PatchedContractSecurityTests() + { + InitializePatchedContracts(); + } + + [Fact] + public async Task ResetFields_Test() { - public PatchedContractSecurityTests() + var result = await TestBasicSecurityContractStub.TestResetFields.SendAsync(new ResetInput { - InitializePatchedContracts(); - } + BoolValue = true, + Int32Value = 100, + Int64Value = 1000, + StringValue = "TEST" + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var int64 = await TestBasicSecurityContractStub.QueryInt64State.CallAsync(new Empty()); + var s = await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty()); + var constValue = await TestBasicSecurityContractStub.QueryConst.CallAsync(new Empty()); + int64.Int64Value.Equals(constValue.Int64Const).ShouldBeTrue(); + s.StringValue.Equals(constValue.StringConst).ShouldBeTrue(); + + var fields = await TestBasicSecurityContractStub.QueryFields.CallAsync(new Empty()); + fields.BoolValue.ShouldBeFalse(); + fields.Int32Value.ShouldBe(0); + fields.Int64Value.ShouldBe(0); + fields.StringValue.ShouldBe(string.Empty); + fields.List.ShouldBeEmpty(); + + var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); + allFieldReset.Value.ShouldBeTrue(); + } - [Fact] - public async Task ResetFields_Test() + [Fact] + public async Task Reset_NestedFields_Test() + { + var result = await TestBasicSecurityContractStub.TestResetNestedFields.SendAsync(new ResetNestedInput { - var result = await TestBasicSecurityContractStub.TestResetFields.SendAsync(new ResetInput - { - BoolValue = true, - Int32Value = 100, - Int64Value = 1000, - StringValue = "TEST" - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var int64 = await TestBasicSecurityContractStub.QueryInt64State.CallAsync(new Empty()); - var s = await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty()); - var constValue = await TestBasicSecurityContractStub.QueryConst.CallAsync(new Empty()); - int64.Int64Value.Equals(constValue.Int64Const).ShouldBeTrue(); - s.StringValue.Equals(constValue.StringConst).ShouldBeTrue(); - - var fields = await TestBasicSecurityContractStub.QueryFields.CallAsync(new Empty()); - fields.BoolValue.ShouldBeFalse(); - fields.Int32Value.ShouldBe(0); - fields.Int64Value.ShouldBe(0); - fields.StringValue.ShouldBe(string.Empty); - fields.List.ShouldBeEmpty(); - - var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); - allFieldReset.Value.ShouldBeTrue(); - } + Int32Value = 100, + StringValue = "TEST" + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + result.Output.Int32Value.ShouldBe(100); + result.Output.StringValue.ShouldBe("TEST"); + var fields = await TestBasicSecurityContractStub.QueryNestedFields.CallAsync(new Empty()); + fields.Int32Value.ShouldBe(0); + fields.StringValue.ShouldBe(string.Empty); + + var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); + allFieldReset.Value.ShouldBeTrue(); + } - [Fact] - public async Task Reset_NestedFields_Test() + [Fact] + public async Task Reset_OtherType_NestedFields_Test() + { + var result = await TestBasicSecurityContractStub.TestResetOtherTypeFields.SendAsync(new ResetNestedInput { - var result = await TestBasicSecurityContractStub.TestResetNestedFields.SendAsync(new ResetNestedInput - { - Int32Value = 100, - StringValue = "TEST" - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.Output.Int32Value.ShouldBe(100); - result.Output.StringValue.ShouldBe("TEST"); - var fields = await TestBasicSecurityContractStub.QueryNestedFields.CallAsync(new Empty()); - fields.Int32Value.ShouldBe(0); - fields.StringValue.ShouldBe(string.Empty); - - var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); - allFieldReset.Value.ShouldBeTrue(); - } + Int32Value = 100, + StringValue = "TEST" + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + result.Output.StringValue.ShouldBe("test"); + result.Output.BasicTypeNumber.ShouldBe(100); + result.Output.BasicTypeStaticNumber.ShouldBe(100); + result.Output.TypeConst.ShouldBe(1); + result.Output.TypeNumber.ShouldBe(100); + + + var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); + allFieldReset.Value.ShouldBeTrue(); + + var allStaticFieldsReset = + await TestBasicSecurityContractStub.CheckNonContractTypesStaticFieldsReset.CallAsync(new Empty()); + allStaticFieldsReset.Value.ShouldBeTrue(); + } + + [Fact] + public async Task TestSingletonStateSizeLimit() + { + var stateSizeLimit = SmartContractConstants.StateSizeLimit; - [Fact] - public async Task Reset_OtherType_NestedFields_Test() + // bytes { - var result = await TestBasicSecurityContractStub.TestResetOtherTypeFields.SendAsync(new ResetNestedInput + var txResult = await TestBasicSecurityContractStub.TestBytesState.SendWithExceptionAsync(new BytesInput { - Int32Value = 100, - StringValue = "TEST" + BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit]) }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.Output.StringValue.ShouldBe("test"); - result.Output.BasicTypeNumber.ShouldBe(100); - result.Output.BasicTypeStaticNumber.ShouldBe(100); - result.Output.TypeConst.ShouldBe(1); - result.Output.TypeNumber.ShouldBe(100); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + await TestBasicSecurityContractStub.TestBytesState.SendAsync(new BytesInput + { + BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit - 3]) + }); - var allFieldReset = await TestBasicSecurityContractStub.CheckFieldsAlreadyReset.CallAsync(new Empty()); - allFieldReset.Value.ShouldBeTrue(); + var queryResult = await TestBasicSecurityContractStub.QueryBytesState.CallAsync(new Empty()); + queryResult.BytesValue.ShouldBe(new byte[stateSizeLimit - 3]); - var allStaticFieldsReset = - await TestBasicSecurityContractStub.CheckNonContractTypesStaticFieldsReset.CallAsync(new Empty()); - allStaticFieldsReset.Value.ShouldBeTrue(); + var txResult2 = await TestBasicSecurityContractStub.TestBytesState.SendWithExceptionAsync(new BytesInput + { + BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit]) + }); + txResult2.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); } - [Fact] - public async Task TestSingletonStateSizeLimit() + // string { - var stateSizeLimit = SmartContractConstants.StateSizeLimit; + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit + 1]); - // bytes - { - var txResult = await TestBasicSecurityContractStub.TestBytesState.SendWithExceptionAsync(new BytesInput + var txResult = await TestBasicSecurityContractStub.TestStringState.SendWithExceptionAsync( + new StringInput { - BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit]) + StringValue = str }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - await TestBasicSecurityContractStub.TestBytesState.SendAsync(new BytesInput - { - BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit - 3]) - }); + var str1 = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var queryResult = await TestBasicSecurityContractStub.QueryBytesState.CallAsync(new Empty()); - queryResult.BytesValue.ShouldBe(new byte[stateSizeLimit - 3]); + await TestBasicSecurityContractStub.TestStringState.SendAsync(new StringInput + { + StringValue = str1 + }); - var txResult2 = await TestBasicSecurityContractStub.TestBytesState.SendWithExceptionAsync(new BytesInput - { - BytesValue = ByteString.CopyFrom(new byte[stateSizeLimit]) - }); - txResult2.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - } + var queryResult = await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty()); + queryResult.StringValue.ShouldBe(str1); - // string + txResult = await TestBasicSecurityContractStub.TestStringState.SendWithExceptionAsync(new StringInput { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit + 1]); + StringValue = str + }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + } - var txResult = await TestBasicSecurityContractStub.TestStringState.SendWithExceptionAsync( - new StringInput() + // proto type + { + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var txResult = await TestBasicSecurityContractStub.TestProtobufState.SendWithExceptionAsync( + new ProtobufInput + { + ProtobufValue = new ProtobufMessage { StringValue = str - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + } + }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - var str1 = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var str1 = Encoding.UTF8.GetString(new byte[stateSizeLimit - 10]); - await TestBasicSecurityContractStub.TestStringState.SendAsync(new StringInput() + await TestBasicSecurityContractStub.TestProtobufState.SendAsync(new ProtobufInput + { + ProtobufValue = new ProtobufMessage { StringValue = str1 - }); + } + }); - var queryResult = await TestBasicSecurityContractStub.QueryStringState.CallAsync(new Empty()); - queryResult.StringValue.ShouldBe(str1); + var queryResult = await TestBasicSecurityContractStub.QueryProtobufState.CallAsync(new Empty()); + queryResult.ProtobufValue.ShouldBe(new ProtobufMessage + { + StringValue = str1 + }); - txResult = await TestBasicSecurityContractStub.TestStringState.SendWithExceptionAsync(new StringInput + txResult = await TestBasicSecurityContractStub.TestProtobufState.SendWithExceptionAsync( + new ProtobufInput { - StringValue = str + ProtobufValue = new ProtobufMessage + { + StringValue = str + } }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - } + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + } - // proto type + { + await TestBasicSecurityContractStub.TestInt32SingletonState.SendAsync(new Int32Input { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var txResult = await TestBasicSecurityContractStub.TestProtobufState.SendWithExceptionAsync( - new ProtobufInput() - { - ProtobufValue = new ProtobufMessage - { - StringValue = str - } - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + Int32Value = int.MaxValue + }); + + var queryResult = await TestBasicSecurityContractStub.QueryInt32SingletonState.CallAsync(new Empty()); + queryResult.Int32Value.ShouldBe(int.MaxValue); + } + + // enum + { + await TestBasicSecurityContractStub.TestEnumState.SendAsync(new Int32Input + { + Int32Value = (int)StateEnum.Foo + }); + + var queryResult = await TestBasicSecurityContractStub.QueryEnumState.CallAsync(new Empty()); + queryResult.Value.ShouldBe((int)StateEnum.Foo); + } + } - var str1 = Encoding.UTF8.GetString(new byte[stateSizeLimit - 10]); + [Fact] + public async Task TestMappedStateSizeLimit() + { + var stateSizeLimit = SmartContractConstants.StateSizeLimit; - await TestBasicSecurityContractStub.TestProtobufState.SendAsync(new ProtobufInput() + { + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var txResult = await TestBasicSecurityContractStub.TestMappedState.SendWithExceptionAsync( + new ProtobufInput { ProtobufValue = new ProtobufMessage { - StringValue = str1 + StringValue = str } }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - var queryResult = await TestBasicSecurityContractStub.QueryProtobufState.CallAsync(new Empty()); - queryResult.ProtobufValue.ShouldBe(new ProtobufMessage + await TestBasicSecurityContractStub.TestMappedState.SendAsync(new ProtobufInput + { + ProtobufValue = new ProtobufMessage { - StringValue = str1 - }); - - txResult = await TestBasicSecurityContractStub.TestProtobufState.SendWithExceptionAsync( - new ProtobufInput() - { - ProtobufValue = new ProtobufMessage - { - StringValue = str - } - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - } + Int64Value = 1 + } + }); + var queryResult = await TestBasicSecurityContractStub.QueryMappedState.CallAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestInt32SingletonState.SendAsync(new Int32Input + ProtobufValue = new ProtobufMessage { - Int32Value = Int32.MaxValue - }); + Int64Value = 1 + } + }); - var queryResult = await TestBasicSecurityContractStub.QueryInt32SingletonState.CallAsync(new Empty()); - queryResult.Int32Value.ShouldBe(Int32.MaxValue); - } + queryResult.Int64Value.ShouldBe(1); - // enum + (await TestBasicSecurityContractStub.QueryMappedState.CallAsync(new ProtobufInput { - await TestBasicSecurityContractStub.TestEnumState.SendAsync(new Int32Input + ProtobufValue = new ProtobufMessage { - Int32Value = (int) StateEnum.Foo - }); - - var queryResult = await TestBasicSecurityContractStub.QueryEnumState.CallAsync(new Empty()); - queryResult.Value.ShouldBe((int) StateEnum.Foo); - } + Int64Value = 2 + } + })).ShouldBe(new ProtobufMessage()); } - [Fact] - public async Task TestMappedStateSizeLimit() { - var stateSizeLimit = SmartContractConstants.StateSizeLimit; - - { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var txResult = await TestBasicSecurityContractStub.TestMappedState.SendWithExceptionAsync( - new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = str - } - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - - await TestBasicSecurityContractStub.TestMappedState.SendAsync(new ProtobufInput + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var txResult = await TestBasicSecurityContractStub.TestMapped1State.SendWithExceptionAsync( + new ProtobufInput { ProtobufValue = new ProtobufMessage { - Int64Value = 1 + StringValue = str } }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - var queryResult = await TestBasicSecurityContractStub.QueryMappedState.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - Int64Value = 1 - } - }); + var str1 = Encoding.UTF8.GetString(new byte[10]); + var message = new ProtobufMessage + { + BoolValue = true, + Int64Value = 1, + StringValue = str1 + }; + await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput + { + ProtobufValue = message + }); - queryResult.Int64Value.ShouldBe(1); + var queryResult = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput + { + ProtobufValue = message + }); - (await TestBasicSecurityContractStub.QueryMappedState.CallAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - Int64Value = 2 - } - })).ShouldBe(new ProtobufMessage()); - } + queryResult.ShouldBe(message); + (await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var txResult = await TestBasicSecurityContractStub.TestMapped1State.SendWithExceptionAsync( - new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = str - } - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - - var str1 = Encoding.UTF8.GetString(new byte[10]); - var message = new ProtobufMessage + ProtobufValue = new ProtobufMessage { BoolValue = true, - Int64Value = 1, + Int64Value = 2, StringValue = str1 - }; - await TestBasicSecurityContractStub.TestMapped1State.SendAsync(new ProtobufInput - { - ProtobufValue = message - }); - - var queryResult = await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput - { - ProtobufValue = message - }); - - queryResult.ShouldBe(message); + } + })).ShouldBe(new ProtobufMessage()); + } - (await TestBasicSecurityContractStub.QueryMappedState1.CallAsync(new ProtobufInput + { + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var txResult = await TestBasicSecurityContractStub.TestMapped2State.SendWithExceptionAsync( + new ProtobufInput { ProtobufValue = new ProtobufMessage { - BoolValue = true, - Int64Value = 2, - StringValue = str1 + StringValue = str } - })).ShouldBe(new ProtobufMessage()); - } + }); + await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var txResult = await TestBasicSecurityContractStub.TestMapped2State.SendWithExceptionAsync( - new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - StringValue = str - } - }); + ProtobufValue = new ProtobufMessage() + }); + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput - { - ProtobufValue = new ProtobufMessage - { - } - }); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + var str1 = Encoding.UTF8.GetString(new byte[10]); + var message = new ProtobufMessage + { + BoolValue = true, + Int64Value = 1, + StringValue = str1 + }; - var str1 = Encoding.UTF8.GetString(new byte[10]); - var message = new ProtobufMessage - { - BoolValue = true, - Int64Value = 1, - StringValue = str1 - }; + await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput + { + ProtobufValue = message + }); - await TestBasicSecurityContractStub.TestMapped2State.SendAsync(new ProtobufInput - { - ProtobufValue = message - }); + var queryResult = await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput + { + ProtobufValue = message + }); - var queryResult = await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput + queryResult.ShouldBe(message); + + (await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput + { + ProtobufValue = new ProtobufMessage { - ProtobufValue = message - }); + BoolValue = true, + Int64Value = 2, + StringValue = str1 + } + })).ShouldBe(new ProtobufMessage()); + } - queryResult.ShouldBe(message); + { + var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); + var message = new TradeMessage + { + FromAmount = 1024 + }; - (await TestBasicSecurityContractStub.QueryMappedState2.CallAsync(new ProtobufInput + var txResult = await TestBasicSecurityContractStub.TestMapped3State.SendWithExceptionAsync( + new Complex3Input { - ProtobufValue = new ProtobufMessage + TradeDetails = new TradeMessage { - BoolValue = true, - Int64Value = 2, - StringValue = str1 + FromAmount = 1, + Memo = str } - })).ShouldBe(new ProtobufMessage()); - } + }); - { - var str = Encoding.UTF8.GetString(new byte[stateSizeLimit]); - var message = new TradeMessage - { - FromAmount = 1024 - }; + txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); - var txResult = await TestBasicSecurityContractStub.TestMapped3State.SendWithExceptionAsync( - new Complex3Input - { - TradeDetails = new TradeMessage - { - FromAmount = 1, - Memo = str - } - }); + var str1 = Encoding.UTF8.GetString(new byte[10]); - txResult.TransactionResult.Error.ShouldContain($"exceeds limit of {stateSizeLimit}"); + var complex3Input = new Complex3Input + { + From = str1, + To = str1, + TradeDetails = message + }; + await TestBasicSecurityContractStub.TestMapped3State.SendAsync(complex3Input); - var str1 = Encoding.UTF8.GetString(new byte[10]); + var queryResult = await TestBasicSecurityContractStub.QueryMappedState3.CallAsync(complex3Input); - var complex3Input = new Complex3Input - { - From = str1, - To = str1, - TradeDetails = message - }; - await TestBasicSecurityContractStub.TestMapped3State.SendAsync(complex3Input); + queryResult.FromAmount.ShouldBe(message.FromAmount); - var queryResult = await TestBasicSecurityContractStub.QueryMappedState3.CallAsync(complex3Input); + (await TestBasicSecurityContractStub.QueryMappedState3.CallAsync(new Complex3Input + { + From = str1, + To = str1, + PairA = str1, + TradeDetails = message + })).ShouldBe(new TradeMessage()); + } + } - queryResult.FromAmount.ShouldBe(message.FromAmount); + [Fact] + public async Task TestBranchCount() + { + { + await TestBasicSecurityContractStub.TestWhileInfiniteLoop.SendAsync(new Int32Input + { Int32Value = 14999 }); + var txResult = await TestBasicSecurityContractStub.TestWhileInfiniteLoop.SendWithExceptionAsync( + new Int32Input + { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); + } - (await TestBasicSecurityContractStub.QueryMappedState3.CallAsync(new Complex3Input - { - From = str1, - To = str1, - PairA = str1, - TradeDetails = message - })).ShouldBe(new TradeMessage()); - } + { + await TestBasicSecurityContractStub.TestForInfiniteLoop.SendAsync(new Int32Input { Int32Value = 14999 }); + var txResult = await TestBasicSecurityContractStub.TestForInfiniteLoop.SendWithExceptionAsync( + new Int32Input + { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); } - [Fact] - public async Task TestBranchCount() { - { - await TestBasicSecurityContractStub.TestWhileInfiniteLoop.SendAsync(new Int32Input - {Int32Value = 14999}); - var txResult = await TestBasicSecurityContractStub.TestWhileInfiniteLoop.SendWithExceptionAsync( - new Int32Input - {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); - } + await TestBasicSecurityContractStub.TestForInfiniteLoopInSeparateClass.SendAsync(new Int32Input + { Int32Value = 14999 }); + var txResult = await TestBasicSecurityContractStub.TestForInfiniteLoop.SendWithExceptionAsync( + new Int32Input + { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); + } - { - await TestBasicSecurityContractStub.TestForInfiniteLoop.SendAsync(new Int32Input {Int32Value = 14999}); - var txResult = await TestBasicSecurityContractStub.TestForInfiniteLoop.SendWithExceptionAsync( - new Int32Input - {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); - } - - { - await TestBasicSecurityContractStub.TestForInfiniteLoopInSeparateClass.SendAsync(new Int32Input {Int32Value = 14999}); - var txResult = await TestBasicSecurityContractStub.TestForInfiniteLoop.SendWithExceptionAsync( + { + await TestBasicSecurityContractStub.TestWhileInfiniteLoopWithState.SendAsync(new Int32Input + { Int32Value = 14999 }); + var txResult = + await TestBasicSecurityContractStub.TestWhileInfiniteLoopWithState.SendWithExceptionAsync( new Int32Input - {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); - } + { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); + } - { - await TestBasicSecurityContractStub.TestWhileInfiniteLoopWithState.SendAsync(new Int32Input - {Int32Value = 14999}); - var txResult = - await TestBasicSecurityContractStub.TestWhileInfiniteLoopWithState.SendWithExceptionAsync( - new Int32Input - {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); - } + { + await TestBasicSecurityContractStub.TestForeachInfiniteLoop.SendAsync(new ListInput + { List = { new int[14999] } }); + var txResult = + await TestBasicSecurityContractStub.TestForeachInfiniteLoop.SendWithExceptionAsync( + new ListInput { List = { new int[15000] } }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); + } + } - { - await TestBasicSecurityContractStub.TestForeachInfiniteLoop.SendAsync(new ListInput - {List = {new int[14999]}}); - var txResult = - await TestBasicSecurityContractStub.TestForeachInfiniteLoop.SendWithExceptionAsync( - new ListInput{List = {new int[15000]}}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeBranchThresholdExceededException)); - } + [Fact] + public async Task TestMethodCallCount() + { + { + await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendAsync(new Int32Input + { Int32Value = 14900 }); + var txResult = await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendWithExceptionAsync( + new Int32Input { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeCallThresholdExceededException)); } - [Fact] - public async Task TestMethodCallCount() { - { - await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendAsync(new Int32Input - {Int32Value = 14900}); - var txResult = await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendWithExceptionAsync( - new Int32Input {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeCallThresholdExceededException)); - } - - { - await TestBasicSecurityContractStub.TestInfiniteRecursiveCallInSeparateClass.SendAsync(new Int32Input - {Int32Value = 14900}); - var txResult = await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendWithExceptionAsync( - new Int32Input {Int32Value = 15000}); - txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeCallThresholdExceededException)); - } + await TestBasicSecurityContractStub.TestInfiniteRecursiveCallInSeparateClass.SendAsync(new Int32Input + { Int32Value = 14900 }); + var txResult = await TestBasicSecurityContractStub.TestInfiniteRecursiveCall.SendWithExceptionAsync( + new Int32Input { Int32Value = 15000 }); + txResult.TransactionResult.Error.ShouldContain(nameof(RuntimeCallThresholdExceededException)); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/TestContractAElfModule.cs b/test/AElf.Contracts.TestContract.Tests/TestContractAElfModule.cs index c5613eb9dc..ef56eaf3b9 100644 --- a/test/AElf.Contracts.TestContract.Tests/TestContractAElfModule.cs +++ b/test/AElf.Contracts.TestContract.Tests/TestContractAElfModule.cs @@ -3,7 +3,6 @@ using AElf.CSharp.CodeOps; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.FeeCalculation; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; @@ -13,35 +12,34 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contract.TestContract +namespace AElf.Contract.TestContract; + +[DependsOn(typeof(ContractTestModule))] +[DependsOn(typeof(CSharpCodeOpsAElfModule))] +public class TestContractAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - [DependsOn(typeof(CSharpCodeOpsAElfModule))] - public class TestContractAElfModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); } +} - [DependsOn( - typeof(ContractTestModule), - typeof(ExecutionPluginForMethodFeeModule), - typeof(ExecutionPluginForResourceFeeModule), - typeof(FeeCalculationModule))] - public class TestFeesContractAElfModule : ContractTestModule +[DependsOn( + typeof(ContractTestModule), + typeof(ExecutionPluginForMethodFeeModule), + typeof(ExecutionPluginForResourceFeeModule), + typeof(FeeCalculationModule))] +public class TestFeesContractAElfModule : ContractTestModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.AddSingleton(); - context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); - //TODO Fix never claim transaction fee - context.Services.RemoveAll(s => - s.ImplementationType != null && s.ImplementationType.FullName != null && - s.ImplementationType.FullName.Contains("TransactionFeeChargedLogEventProcessor")); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); + context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); + //TODO Fix never claim transaction fee + context.Services.RemoveAll(s => + s.ImplementationType != null && s.ImplementationType.FullName != null && + s.ImplementationType.FullName.Contains("TransactionFeeChargedLogEventProcessor")); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs b/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs index 24c2bfa2f7..8ebd7a63e2 100644 --- a/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs +++ b/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; -using AElf.Standards.ACS0; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; @@ -12,312 +10,346 @@ using AElf.Contracts.TestContract.BasicUpdate; using AElf.Contracts.TestContract.BigIntValue; using AElf.Contracts.TestContract.TransactionFees; -using AElf.ContractTestKit; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; +using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.EconomicSystem; using AElf.Kernel; using AElf.Kernel.CodeCheck.Infrastructure; using AElf.Kernel.SmartContract; -using AElf.Kernel.SmartContract.Application; +using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; using Xunit; -using InitializeInput = AElf.Contracts.TokenConverter.InitializeInput; +using InitialBasicContractInput = AElf.Contracts.TestContract.BasicFunction.InitialBasicContractInput; +using InitializeInput = AElf.Contracts.Parliament.InitializeInput; using SmartContractConstants = AElf.Sdk.CSharp.SmartContractConstants; -namespace AElf.Contract.TestContract -{ - public class TestContractTestBase : ContractTestBase - { - protected readonly Hash TestBasicFunctionContractSystemName = - HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BasicFunction"); +namespace AElf.Contract.TestContract; - protected readonly Hash TestBasicSecurityContractSystemName = - HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BasicSecurity"); +public class TestContractTestBase : ContractTestBase +{ + private const string ContractPatchedDllDir = "../../../../patched/"; - protected readonly Hash TestBigIntValueContractSystemName = - HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BigIntValue"); + protected readonly Hash TestBasicFunctionContractSystemName = + HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BasicFunction"); - public TestContractTestBase() - { - PatchedCodes = GetPatchedCodes(ContractPatchedDllDir); - } + protected readonly Hash TestBasicSecurityContractSystemName = + HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BasicSecurity"); - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - protected Address BasicFunctionContractAddress { get; set; } - protected Address BasicSecurityContractAddress { get; set; } - protected Address BigIntValueContractAddress { get; set; } + protected readonly Hash TestBigIntValueContractSystemName = + HashHelper.ComputeFrom("AElf.ContractNames.TestContract.BigIntValue"); - internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } + public TestContractTestBase() + { + PatchedCodes = GetPatchedCodes(ContractPatchedDllDir); + } - internal BasicFunctionContractContainer.BasicFunctionContractStub TestBasicFunctionContractStub { get; set; } + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected Address BasicFunctionContractAddress { get; set; } + protected Address BasicSecurityContractAddress { get; set; } + protected Address BigIntValueContractAddress { get; set; } - internal BasicSecurityContractContainer.BasicSecurityContractStub TestBasicSecurityContractStub { get; set; } + internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } - internal BigIntValueContractContainer.BigIntValueContractStub BigIntValueContractStub { get; set; } + internal BasicFunctionContractContainer.BasicFunctionContractStub TestBasicFunctionContractStub { get; set; } - internal ACS0Container.ACS0Stub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal BasicSecurityContractContainer.BasicSecurityContractStub TestBasicSecurityContractStub { get; set; } - internal BasicFunctionContractContainer.BasicFunctionContractStub GetTestBasicFunctionContractStub( - ECKeyPair keyPair) - { - return GetTester(BasicFunctionContractAddress, - keyPair); - } + internal BigIntValueContractContainer.BigIntValueContractStub BigIntValueContractStub { get; set; } - internal BasicUpdateContractContainer.BasicUpdateContractStub GetTestBasicUpdateContractStub(ECKeyPair keyPair) - { - return GetTester(BasicFunctionContractAddress, - keyPair); - } + private IReadOnlyDictionary PatchedCodes { get; } - internal BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub - GetTestBasicFunctionWithParallelContractStub(ECKeyPair keyPair) - { - return GetTester( - BasicFunctionContractAddress, - keyPair); - } + internal ACS0Container.ACS0Stub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal BasicSecurityContractContainer.BasicSecurityContractStub GetTestBasicSecurityContractStub( - ECKeyPair keyPair) - { - return GetTester(BasicSecurityContractAddress, - keyPair); - } - - internal BigIntValueContractContainer.BigIntValueContractStub GetBigIntValueContractStub( - ECKeyPair keyPair) - { - return GetTester(BigIntValueContractAddress, - keyPair); - } + internal BasicFunctionContractContainer.BasicFunctionContractStub GetTestBasicFunctionContractStub( + ECKeyPair keyPair) + { + return GetTester(BasicFunctionContractAddress, + keyPair); + } - private const string ContractPatchedDllDir = "../../../../patched/"; - - private IReadOnlyDictionary PatchedCodes {get;} + internal BasicUpdateContractContainer.BasicUpdateContractStub GetTestBasicUpdateContractStub(ECKeyPair keyPair) + { + return GetTester(BasicFunctionContractAddress, + keyPair); + } - protected void InitializeTestContracts() - { - BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - - //deploy test contract1 - BasicFunctionContractAddress = AsyncHelper.RunSync(async () => - await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value, - TestBasicFunctionContractSystemName, - DefaultSenderKeyPair)); - TestBasicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitialBasicFunctionContract()); - - //deploy test contract2 - BasicSecurityContractAddress = AsyncHelper.RunSync(async () => - await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("BasicSecurity")).Value, - TestBasicSecurityContractSystemName, - DefaultSenderKeyPair)); - TestBasicSecurityContractStub = GetTestBasicSecurityContractStub(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeSecurityContract()); - - //deploy test contract3 - BigIntValueContractAddress = AsyncHelper.RunSync(async () => - await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("BigIntValue")).Value, - TestBigIntValueContractSystemName, - DefaultSenderKeyPair)); - BigIntValueContractStub = GetBigIntValueContractStub(DefaultSenderKeyPair); - } + internal BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + GetTestBasicFunctionWithParallelContractStub(ECKeyPair keyPair) + { + return GetTester( + BasicFunctionContractAddress, + keyPair); + } - protected void InitializePatchedContracts() - { - BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - - //deploy test contract1 - var basicFunctionPatchedCode = PatchedCodes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value; - CheckCode(basicFunctionPatchedCode); - BasicFunctionContractAddress = AsyncHelper.RunSync(async () => - await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - basicFunctionPatchedCode, - TestBasicFunctionContractSystemName, - DefaultSenderKeyPair)); - TestBasicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitialBasicFunctionContract()); - - //deploy test contract2 - var basicSecurityContractCode = PatchedCodes.Single(kv => kv.Key.EndsWith("BasicSecurity")).Value; - BasicSecurityContractAddress = AsyncHelper.RunSync(async () => - await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - basicSecurityContractCode, - TestBasicSecurityContractSystemName, - DefaultSenderKeyPair)); - TestBasicSecurityContractStub = GetTestBasicSecurityContractStub(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeSecurityContract()); - - CheckCode(basicSecurityContractCode); - } - - - protected void CheckCode(byte[] code) - { - var auditor = GetRequiredService(); - auditor.Audit(code, new RequiredAcs { AcsList = new List() }, false); - } - - private async Task InitialBasicFunctionContract() - { - await TestBasicFunctionContractStub.InitialBasicFunctionContract.SendAsync( - new AElf.Contracts.TestContract.BasicFunction.InitialBasicContractInput() - { - ContractName = "Test Contract1", - MinValue = 10L, - MaxValue = 1000L, - MortgageValue = 1000_000_000L, - Manager = Accounts[1].Address - }); - } + internal BasicSecurityContractContainer.BasicSecurityContractStub GetTestBasicSecurityContractStub( + ECKeyPair keyPair) + { + return GetTester(BasicSecurityContractAddress, + keyPair); + } - private async Task InitializeSecurityContract() - { - await TestBasicSecurityContractStub.InitialBasicSecurityContract.SendAsync(BasicFunctionContractAddress); - } + internal BigIntValueContractContainer.BigIntValueContractStub GetBigIntValueContractStub( + ECKeyPair keyPair) + { + return GetTester(BigIntValueContractAddress, + keyPair); } - public class TestFeesContractTestBase : ContractTestBase + protected void InitializeTestContracts() { - protected const long Supply = 1_000_000_00000000L; - protected const long VirtualElfSupplyToken = 1_000_000_00000000L; - protected const long ResourceTokenTotalSupply = 1_000_000_000_00000000; - protected const long VirtualResourceToken = 100_000; - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(1).Select(a => a.KeyPair).ToList(); - protected Address OtherTester => Accounts[1].Address; - protected Address ManagerTester => Accounts[10].Address; - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - protected Address Acs8ContractAddress { get; set; } - protected Address TokenContractAddress { get; set; } - protected Address TokenConverterContractAddress { get; set; } - protected Address TransactionFeesContractAddress { get; set; } - protected Address TreasuryContractAddress { get; set; } - internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } - internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub { get; set; } - internal ParliamentContractContainer.ParliamentContractStub ParliamentContractStub { get; set; } - - internal Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.ContractContainer.ContractStub - Acs8ContractStub { get; set; } - - internal TransactionFeesContractContainer.TransactionFeesContractStub TransactionFeesContractStub { get; set; } - internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } - - internal static readonly List ResourceTokenSymbols = new List {"WRITE", "READ", "TRAFFIC", "STORAGE"}; - internal static readonly List NativTokenToSourceSymbols = new List {"NTWRITE", "NTREAD", "NTTRAFFIC", "NTSTORAGE"}; - - protected async Task DeployTestContracts() - { - BasicContractZeroStub = GetTester(ContractZeroAddress, DefaultSenderKeyPair); + BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - var code = Codes.Single(kv => kv.Key.Contains("Profit")).Value; - await DeploySystemSmartContract(KernelConstants.CodeCoverageRunnerCategory, code, - ProfitSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - - TokenContractAddress = await DeploySystemSmartContract( + //deploy test contract1 + BasicFunctionContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value, + TestBasicFunctionContractSystemName, + DefaultSenderKeyPair)); + TestBasicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitialBasicFunctionContract()); + + //deploy test contract2 + BasicSecurityContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("MultiToken")).Value, - SmartContractConstants.TokenContractSystemHashName, - DefaultSenderKeyPair - ); - TokenContractStub = - GetTester(TokenContractAddress, DefaultSenderKeyPair); - - TokenConverterContractAddress = await DeploySystemSmartContract( + Codes.Single(kv => kv.Key.EndsWith("BasicSecurity")).Value, + TestBasicSecurityContractSystemName, + DefaultSenderKeyPair)); + TestBasicSecurityContractStub = GetTestBasicSecurityContractStub(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeSecurityContract()); + + //deploy test contract3 + BigIntValueContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("TokenConverter")).Value, - TokenConverterSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair - ); + Codes.Single(kv => kv.Key.EndsWith("BigIntValue")).Value, + TestBigIntValueContractSystemName, + DefaultSenderKeyPair)); + BigIntValueContractStub = GetBigIntValueContractStub(DefaultSenderKeyPair); + } + + protected void InitializePatchedContracts() + { + BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - TreasuryContractAddress = await DeploySystemSmartContract( + //deploy test contract1 + var basicFunctionPatchedCode = PatchedCodes.Single(kv => kv.Key.EndsWith("BasicFunction")).Value; + CheckCode(basicFunctionPatchedCode); + BasicFunctionContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("Treasury")).Value, - SmartContractConstants.TreasuryContractSystemHashName, + basicFunctionPatchedCode, + TestBasicFunctionContractSystemName, + DefaultSenderKeyPair)); + TestBasicFunctionContractStub = GetTestBasicFunctionContractStub(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitialBasicFunctionContract()); + + //deploy test contract2 + var basicSecurityContractCode = PatchedCodes.Single(kv => kv.Key.EndsWith("BasicSecurity")).Value; + BasicSecurityContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( + KernelConstants.CodeCoverageRunnerCategory, + basicSecurityContractCode, + TestBasicSecurityContractSystemName, + DefaultSenderKeyPair)); + TestBasicSecurityContractStub = GetTestBasicSecurityContractStub(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeSecurityContract()); + + CheckCode(basicSecurityContractCode); + } + + + protected void CheckCode(byte[] code) + { + var auditor = GetRequiredService(); + auditor.Audit(code, new RequiredAcs { AcsList = new List() }, false); + } + + private async Task InitialBasicFunctionContract() + { + await TestBasicFunctionContractStub.InitialBasicFunctionContract.SendAsync( + new InitialBasicContractInput + { + ContractName = "Test Contract1", + MinValue = 10L, + MaxValue = 1000L, + MortgageValue = 1000_000_000L, + Manager = Accounts[1].Address + }); + } + + private async Task InitializeSecurityContract() + { + await TestBasicSecurityContractStub.InitialBasicSecurityContract.SendAsync(BasicFunctionContractAddress); + } +} + +public class TestFeesContractTestBase : ContractTestBase +{ + protected const long Supply = 1_000_000_00000000L; + protected const long VirtualElfSupplyToken = 1_000_000_00000000L; + protected const long ResourceTokenTotalSupply = 1_000_000_000_00000000; + protected const long VirtualResourceToken = 100_000; + + internal static readonly List ResourceTokenSymbols = new() { "WRITE", "READ", "TRAFFIC", "STORAGE" }; + + internal static readonly List NativTokenToSourceSymbols = + new() { "NTWRITE", "NTREAD", "NTTRAFFIC", "NTSTORAGE" }; + + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(1).Select(a => a.KeyPair).ToList(); + + protected Address OtherTester => Accounts[1].Address; + protected Address ManagerTester => Accounts[10].Address; + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected Address Acs8ContractAddress { get; set; } + protected Address TokenContractAddress { get; set; } + protected Address TokenConverterContractAddress { get; set; } + protected Address TransactionFeesContractAddress { get; set; } + protected Address TreasuryContractAddress { get; set; } + internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } + internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub { get; set; } + internal ParliamentContractContainer.ParliamentContractStub ParliamentContractStub { get; set; } + + internal ContractContainer.ContractStub + Acs8ContractStub { get; set; } + + internal TransactionFeesContractContainer.TransactionFeesContractStub TransactionFeesContractStub { get; set; } + internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } + + protected async Task DeployTestContracts() + { + BasicContractZeroStub = GetTester(ContractZeroAddress, DefaultSenderKeyPair); + + var code = Codes.Single(kv => kv.Key.Contains("Profit")).Value; + await DeploySystemSmartContract(KernelConstants.CodeCoverageRunnerCategory, code, + ProfitSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + + TokenContractAddress = await DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("MultiToken")).Value, + SmartContractConstants.TokenContractSystemHashName, + DefaultSenderKeyPair + ); + TokenContractStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); + + TokenConverterContractAddress = await DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("TokenConverter")).Value, + TokenConverterSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair + ); + + TreasuryContractAddress = await DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("Treasury")).Value, + SmartContractConstants.TreasuryContractSystemHashName, + DefaultSenderKeyPair); + TreasuryContractStub = + GetTester(TreasuryContractAddress, DefaultSenderKeyPair); - TreasuryContractStub = - GetTester(TreasuryContractAddress, - DefaultSenderKeyPair); - TokenConverterContractStub = - GetTester(TokenConverterContractAddress, - DefaultSenderKeyPair); - - var parliamentAddress = await DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - Codes.Single(kv => kv.Key.EndsWith("Parliament")).Value, - SmartContractConstants.ParliamentContractSystemHashName, + TokenConverterContractStub = + GetTester(TokenConverterContractAddress, DefaultSenderKeyPair); - ParliamentContractStub = GetTester(parliamentAddress, + + var parliamentAddress = await DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("Parliament")).Value, + SmartContractConstants.ParliamentContractSystemHashName, + DefaultSenderKeyPair); + ParliamentContractStub = GetTester(parliamentAddress, + DefaultSenderKeyPair); + + var acs8Code = Codes.Single(kv => kv.Key.Contains("Tests.TestContract")).Value; + Acs8ContractAddress = await DeployContractAsync( + KernelConstants.CodeCoverageRunnerCategory, + acs8Code, + null, + DefaultSenderKeyPair + ); + Acs8ContractStub = + GetTester(Acs8ContractAddress, DefaultSenderKeyPair); + + var feesCode = Codes.Single(kv => kv.Key.Contains("TransactionFees")).Value; + TransactionFeesContractAddress = await DeployContractAsync( + KernelConstants.CodeCoverageRunnerCategory, + feesCode, + null, + DefaultSenderKeyPair + ); + TransactionFeesContractStub = + GetTester(TransactionFeesContractAddress, DefaultSenderKeyPair); - var acs8Code = Codes.Single(kv => kv.Key.Contains("Tests.TestContract")).Value; - Acs8ContractAddress = await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - acs8Code, - null, - DefaultSenderKeyPair - ); - Acs8ContractStub = - GetTester(Acs8ContractAddress, DefaultSenderKeyPair); - - var feesCode = Codes.Single(kv => kv.Key.Contains("TransactionFees")).Value; - TransactionFeesContractAddress = await DeployContractAsync( - KernelConstants.CodeCoverageRunnerCategory, - feesCode, - null, - DefaultSenderKeyPair - ); - TransactionFeesContractStub = - GetTester(TransactionFeesContractAddress, + //Consensus + { + var consensusCode = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; + var consensusContractAddress = await DeploySystemSmartContract(KernelConstants.CodeCoverageRunnerCategory, + consensusCode, + HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); + AEDPoSContractStub = + GetTester(consensusContractAddress, DefaultSenderKeyPair); - - //Consensus - { - var consensusCode = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; - var consensusContractAddress = await DeploySystemSmartContract(KernelConstants.CodeCoverageRunnerCategory, consensusCode, - HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); - AEDPoSContractStub = - GetTester(consensusContractAddress, - DefaultSenderKeyPair); - } } + } - protected async Task InitializeTestContracts() + protected async Task InitializeTestContracts() + { + //initialize token { - //initialize token + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "ELF", + Decimals = 8, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = Supply * 10, + Issuer = DefaultSender, + LockWhiteList = + { + TokenConverterContractAddress, + TreasuryContractAddress + } + }); + CheckResult(createResult.TransactionResult); + + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = Supply / 2, + To = DefaultSender, + Memo = "Set for token converter." + }); + CheckResult(issueResult.TransactionResult); + + foreach (var resourceRelatedNativeToken in NativTokenToSourceSymbols) { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput() + createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = "ELF", + Symbol = resourceRelatedNativeToken, Decimals = 8, IsBurnable = true, - TokenName = "elf token", + TokenName = resourceRelatedNativeToken + " elf token", TotalSupply = Supply * 10, Issuer = DefaultSender, LockWhiteList = @@ -327,191 +359,162 @@ protected async Task InitializeTestContracts() } }); CheckResult(createResult.TransactionResult); - - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() + issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - Symbol = "ELF", + Symbol = resourceRelatedNativeToken, Amount = Supply / 2, To = DefaultSender, - Memo = "Set for token converter." + Memo = $"Set for {resourceRelatedNativeToken} token converter." }); CheckResult(issueResult.TransactionResult); + } - foreach (var resourceRelatedNativeToken in NativTokenToSourceSymbols) + foreach (var symbol in ResourceTokenSymbols) + { + var resourceCreateResult = await TokenContractStub.Create.SendAsync(new CreateInput { - createResult = await TokenContractStub.Create.SendAsync(new CreateInput() - { - Symbol = resourceRelatedNativeToken, - Decimals = 8, - IsBurnable = true, - TokenName = resourceRelatedNativeToken + " elf token", - TotalSupply = Supply * 10, - Issuer = DefaultSender, - LockWhiteList = - { - TokenConverterContractAddress, - TreasuryContractAddress - } - }); - CheckResult(createResult.TransactionResult); - issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() + Symbol = symbol, + TokenName = $"{symbol} Token", + TotalSupply = ResourceTokenTotalSupply, + Decimals = 8, + Issuer = DefaultSender, + IsBurnable = true, + LockWhiteList = { - Symbol = resourceRelatedNativeToken, - Amount = Supply / 2, - To = DefaultSender, - Memo = $"Set for {resourceRelatedNativeToken} token converter." - }); - CheckResult(issueResult.TransactionResult); - } - foreach (var symbol in ResourceTokenSymbols) + TokenConverterContractAddress, + TreasuryContractAddress + } + }); + CheckResult(resourceCreateResult.TransactionResult); + + var resourceIssueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - var resourceCreateResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - TokenName = $"{symbol} Token", - TotalSupply = ResourceTokenTotalSupply, - Decimals = 8, - Issuer = DefaultSender, - IsBurnable = true, - LockWhiteList = - { - TokenConverterContractAddress, - TreasuryContractAddress - } - }); - CheckResult(resourceCreateResult.TransactionResult); - - var resourceIssueResult = await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - To = TokenConverterContractAddress, - Amount = ResourceTokenTotalSupply, - Memo = "Initialize for resources trade" - }); - CheckResult(resourceIssueResult.TransactionResult); - } - } - - //initialize parliament - { - var result = await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput()); - CheckResult(result.TransactionResult); + Symbol = symbol, + To = TokenConverterContractAddress, + Amount = ResourceTokenTotalSupply, + Memo = "Initialize for resources trade" + }); + CheckResult(resourceIssueResult.TransactionResult); } + } - //initialize token converter + //initialize parliament + { + var result = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); + CheckResult(result.TransactionResult); + } + + //initialize token converter + { + var connectors = new List(); + var elfConnector = new Connector + { + Symbol = "ELF", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + Weight = "0.5", + VirtualBalance = VirtualElfSupplyToken + }; + connectors.Add(elfConnector); + foreach (var resourceRelatedNativeToken in NativTokenToSourceSymbols) { - var connectors = new List(); - var elfConnector = new Connector + elfConnector = new Connector { - Symbol = "ELF", + Symbol = resourceRelatedNativeToken, IsPurchaseEnabled = true, IsVirtualBalanceEnabled = true, Weight = "0.5", VirtualBalance = VirtualElfSupplyToken }; + elfConnector.RelatedSymbol = ResourceTokenSymbols.First(x => elfConnector.Symbol.Contains(x)); connectors.Add(elfConnector); - foreach (var resourceRelatedNativeToken in NativTokenToSourceSymbols) - { - elfConnector = new Connector - { - Symbol = resourceRelatedNativeToken, - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - Weight = "0.5", - VirtualBalance = VirtualElfSupplyToken - }; - elfConnector.RelatedSymbol = ResourceTokenSymbols.First(x => elfConnector.Symbol.Contains(x)); - connectors.Add(elfConnector); - } - foreach (var symbol in ResourceTokenSymbols) - { - var connector = new Connector - { - Symbol = symbol, - VirtualBalance = ResourceTokenTotalSupply, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false - }; - connector.RelatedSymbol = NativTokenToSourceSymbols.First(x => x.Contains(connector.Symbol)); - connectors.Add(connector); - } - - await TokenConverterContractStub.Initialize.SendAsync(new InitializeInput - { - FeeRate = "0.005", - Connectors = {connectors}, - BaseTokenSymbol = "ELF", - }); } - //initialize treasury contract + foreach (var symbol in ResourceTokenSymbols) { - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); + var connector = new Connector + { + Symbol = symbol, + VirtualBalance = ResourceTokenTotalSupply, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false + }; + connector.RelatedSymbol = NativTokenToSourceSymbols.First(x => x.Contains(connector.Symbol)); + connectors.Add(connector); } - - // initialize AEDPos + + await TokenConverterContractStub.Initialize.SendAsync(new Contracts.TokenConverter.InitializeInput { - await InitializeAElfConsensus(); - } + FeeRate = "0.005", + Connectors = { connectors }, + BaseTokenSymbol = "ELF" + }); } - protected void CheckResult(TransactionResult result) + //initialize treasury contract { - if (result.Status != TransactionResultStatus.Mined) - { - Assert.True(false, $"Status: {result.Status}, Message: {result.Error}"); - } + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); } - private async Task InitializeAElfConsensus() + + // initialize AEDPos { - { - await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000 - }); - } - { - await AEDPoSContractStub.FirstRound.SendAsync( - GenerateFirstRoundOfNewTerm( - new MinerList - {Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))}}, - 4000, TimestampHelper.GetUtcNow())); - } + await InitializeAElfConsensus(); } - private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + } + + protected void CheckResult(TransactionResult result) + { + if (result.Status != TransactionResultStatus.Mined) + Assert.True(false, $"Status: {result.Status}, Message: {result.Error}"); + } + + private async Task InitializeAElfConsensus() + { { - var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The third miner will be the extra block producer of first round of each term. - if (i == 0) + await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; - - return round; + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000 + }); } + { + await AEDPoSContractStub.FirstRound.SendAsync( + GenerateFirstRoundOfNewTerm( + new MinerList + { Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } }, + 4000, TimestampHelper.GetUtcNow())); + } + } + + private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) + { + var minerInRound = new MinerInRound(); + + // The third miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); + } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFeeCharging/AElf.Contracts.TestContract.TransactionFeeCharging.csproj b/test/AElf.Contracts.TestContract.TransactionFeeCharging/AElf.Contracts.TestContract.TransactionFeeCharging.csproj index ed8687f7fe..3671ada17c 100644 --- a/test/AElf.Contracts.TestContract.TransactionFeeCharging/AElf.Contracts.TestContract.TransactionFeeCharging.csproj +++ b/test/AElf.Contracts.TestContract.TransactionFeeCharging/AElf.Contracts.TestContract.TransactionFeeCharging.csproj @@ -8,7 +8,7 @@ - + diff --git a/test/AElf.Contracts.TestContract.TransactionFeeCharging/ContractsReferences.cs b/test/AElf.Contracts.TestContract.TransactionFeeCharging/ContractsReferences.cs index 83bcd8003c..1fb6fe2524 100644 --- a/test/AElf.Contracts.TestContract.TransactionFeeCharging/ContractsReferences.cs +++ b/test/AElf.Contracts.TestContract.TransactionFeeCharging/ContractsReferences.cs @@ -1,9 +1,8 @@ using AElf.Contracts.MultiToken; -namespace AElf.Contracts.TestContract.TransactionFeeCharging +namespace AElf.Contracts.TestContract.TransactionFeeCharging; + +public partial class TransactionFeeChargingContractState { - public partial class TransactionFeeChargingContractState - { - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContract.cs b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContract.cs index cb2823a94c..7509fd3f57 100644 --- a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContract.cs +++ b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContract.cs @@ -1,73 +1,71 @@ -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; using AElf.Sdk.CSharp; -using AElf.Types; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.TransactionFeeCharging +namespace AElf.Contracts.TestContract.TransactionFeeCharging; + +public class + TransactionFeeChargingContract : TransactionFeeChargingContractContainer.TransactionFeeChargingContractBase { - public class - TransactionFeeChargingContract : TransactionFeeChargingContractContainer.TransactionFeeChargingContractBase + public override Empty InitializeTransactionFeeChargingContract( + InitializeTransactionFeeChargingContractInput input) { - public override Empty InitializeTransactionFeeChargingContract( - InitializeTransactionFeeChargingContractInput input) + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + State.TokenContract.Create.Send(new CreateInput { - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - State.TokenContract.Create.Send(new CreateInput + Symbol = input.Symbol, + TokenName = "Token of Transaction Fee Charging Contract", + Decimals = 2, + Issuer = Context.Self, + IsBurnable = true, + TotalSupply = TransactionFeeChargingContractConstants.TotalSupply, + LockWhiteList = { - Symbol = input.Symbol, - TokenName = "Token of Transaction Fee Charging Contract", - Decimals = 2, - Issuer = Context.Self, - IsBurnable = true, - TotalSupply = TransactionFeeChargingContractConstants.TotalSupply, - LockWhiteList = - { - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName), - Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) - } - }); - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = input.Symbol, - Amount = TransactionFeeChargingContractConstants.AmountIssueToTokenConverterContract, - To = Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) - }); - return new Empty(); - } - - public override Empty SetMethodFee(MethodFees input) + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName), + Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) + } + }); + State.TokenContract.Issue.Send(new IssueInput { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + Symbol = input.Symbol, + Amount = TransactionFeeChargingContractConstants.AmountIssueToTokenConverterContract, + To = Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) + }); + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); + } - public override Empty SendForFun(Empty input) - { - return new Empty(); - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; + } - public override Empty SupposedToFail(Empty input) - { - Assert(false, "Fate!"); - return new Empty(); - } + public override Empty SendForFun(Empty input) + { + return new Empty(); + } - public override Empty IssueToTokenConvert(IssueAmount input) + public override Empty SupposedToFail(Empty input) + { + Assert(false, "Fate!"); + return new Empty(); + } + + public override Empty IssueToTokenConvert(IssueAmount input) + { + State.TokenContract.Issue.Send(new IssueInput { - State.TokenContract.Issue.Send(new IssueInput - { - Symbol = input.Symbol, - Amount = input.Amount, - To = Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) - }); - return new Empty(); - } + Symbol = input.Symbol, + Amount = input.Amount, + To = Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName) + }); + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractConstants.cs b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractConstants.cs index 8754f119f3..d2818d8db0 100644 --- a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractConstants.cs +++ b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractConstants.cs @@ -1,8 +1,7 @@ -namespace AElf.Contracts.TestContract.TransactionFeeCharging +namespace AElf.Contracts.TestContract.TransactionFeeCharging; + +public class TransactionFeeChargingContractConstants { - public class TransactionFeeChargingContractConstants - { - public const long TotalSupply = 1_000_000_000; - public const long AmountIssueToTokenConverterContract = 100_000; - } + public const long TotalSupply = 1_000_000_000; + public const long AmountIssueToTokenConverterContract = 100_000; } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractState.cs b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractState.cs index f038d95569..66089790ee 100644 --- a/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractState.cs +++ b/test/AElf.Contracts.TestContract.TransactionFeeCharging/TransactionFeeChargingContractState.cs @@ -1,11 +1,9 @@ -using System; +using AElf.Sdk.CSharp.State; using AElf.Standards.ACS1; -using AElf.Sdk.CSharp.State; -namespace AElf.Contracts.TestContract.TransactionFeeCharging +namespace AElf.Contracts.TestContract.TransactionFeeCharging; + +public partial class TransactionFeeChargingContractState : ContractState { - public partial class TransactionFeeChargingContractState : ContractState - { - public MappedState TransactionFees { get; set; } - } + public MappedState TransactionFees { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFees/AElf.Contracts.TestContract.TransactionFees.csproj b/test/AElf.Contracts.TestContract.TransactionFees/AElf.Contracts.TestContract.TransactionFees.csproj index c950d840e2..80cbb8a162 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/AElf.Contracts.TestContract.TransactionFees.csproj +++ b/test/AElf.Contracts.TestContract.TransactionFees/AElf.Contracts.TestContract.TransactionFees.csproj @@ -4,14 +4,14 @@ AElf.Contracts.TestContract.TransactionFees - true + true - true + true - + - + @@ -19,7 +19,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\stub\acs0.proto diff --git a/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs b/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs index 320f7ab6e6..5e572de329 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs +++ b/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs @@ -1,161 +1,151 @@ using AElf.Contracts.MultiToken; using AElf.CSharp.Core; +using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; -namespace AElf.Contracts.TestContract.TransactionFees +namespace AElf.Contracts.TestContract.TransactionFees; + +public partial class TransactionFeesContract : TransactionFeesContractContainer.TransactionFeesContractBase { - public partial class TransactionFeesContract : TransactionFeesContractContainer.TransactionFeesContractBase + public override Empty InitializeFeesContract(Address input) { - public override Empty InitializeFeesContract(Address input) - { - State.Acs8Contract.Value = input; - State.TokenContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); - //init state - for (var i = 0; i <= 100; i++) - { - State.TestInfo[i] = 5 * i; - } - - return new Empty(); - } - - public override Empty MessCpuNetConsuming(NetBytesInput input) - { - State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); - - State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput - { - Blob = input.NetPackage - }); - - return new Empty(); - } - - public override Empty MessCpuStoConsuming(Empty input) - { - State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); - - State.Acs8Contract.StoConsumingMethod.Send(new Empty()); - - return new Empty(); - } - - public override Empty MessNetStoConsuming(NetBytesInput input) - { - State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput - { - Blob = input.NetPackage - }); - - State.Acs8Contract.StoConsumingMethod.Send(new Empty()); - - return new Empty(); - } - - public override Empty FailInlineTransfer(TransferInput input) + State.Acs8Contract.Value = input; + State.TokenContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); + //init state + for (var i = 0; i <= 100; i++) State.TestInfo[i] = 5 * i; + + return new Empty(); + } + + public override Empty MessCpuNetConsuming(NetBytesInput input) + { + State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); + + State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput { - State.TokenContract.Transfer.Send(new MultiToken.TransferInput - { - Symbol = "ELF", - Amount = input.Amount, - To = input.To, - Memo = input.Memo - }); - - Context.SendInline(State.TokenContract.Value, "Burn", new BurnInput - { - Symbol = "ELF", - Amount = input.Amount.Div(10) - }.ToByteString()); - - return new Empty(); - } - - public override Empty FailNetStoConsuming(NetBytesInput input) + Blob = input.NetPackage + }); + + return new Empty(); + } + + public override Empty MessCpuStoConsuming(Empty input) + { + State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); + + State.Acs8Contract.StoConsumingMethod.Send(new Empty()); + + return new Empty(); + } + + public override Empty MessNetStoConsuming(NetBytesInput input) + { + State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput { - State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput - { - Blob = input.NetPackage - }); - - Context.SendInline(State.Acs8Contract.Value, "InvalidMethod", ByteString.CopyFromUtf8("fail")); - - Assert(false, ""); - return new Empty(); - } - - public override Empty FailCpuNetConsuming(NetBytesInput input) + Blob = input.NetPackage + }); + + State.Acs8Contract.StoConsumingMethod.Send(new Empty()); + + return new Empty(); + } + + public override Empty FailInlineTransfer(TransferInput input) + { + State.TokenContract.Transfer.Send(new MultiToken.TransferInput { - State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); - - Context.SendInline(State.TokenContract.Value, "Transfer", new MultiToken.TransferInput - { - Symbol = "ELF", - To = Context.Self, - Amount = 1000, - Memo = "failed inline test" - }.ToByteString()); - - return new Empty(); - } - - public override Empty FailCpuStoConsuming(Empty input) + Symbol = "ELF", + Amount = input.Amount, + To = input.To, + Memo = input.Memo + }); + + Context.SendInline(State.TokenContract.Value, "Burn", new BurnInput { - State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); - - State.Acs8Contract.StoConsumingMethod.Send(new Empty()); - - Context.SendInline(State.TokenContract.Value, "NotExist", ByteString.CopyFromUtf8("fake parameter")); - - return new Empty(); - } - - public override Empty ReadCpuCountTest(Int32Value input) + Symbol = "ELF", + Amount = input.Amount.Div(10) + }.ToByteString()); + + return new Empty(); + } + + public override Empty FailNetStoConsuming(NetBytesInput input) + { + State.Acs8Contract.TrafficConsumingMethod.Send(new TrafficConsumingMethodInput { - Assert(input.Value>0, $"Invalid read state count {input.Value}"); - var sum = 0; - for (var i = 0; i <= input.Value % 100; i++) - { - sum = sum.Add(State.TestInfo[i]); - } - - return new Empty(); - } - - public override Empty WriteRamCountTest(Int32Value input) + Blob = input.NetPackage + }); + + Context.SendInline(State.Acs8Contract.Value, "InvalidMethod", ByteString.CopyFromUtf8("fail")); + + Assert(false, ""); + return new Empty(); + } + + public override Empty FailCpuNetConsuming(NetBytesInput input) + { + State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); + + Context.SendInline(State.TokenContract.Value, "Transfer", new MultiToken.TransferInput { - Assert(input.Value>0, $"Invalid write state count {input.Value}"); - for (var i = 0; i <= input.Value % 100; i++) - { - State.TestInfo[i] = input.Value * i; - } - - return new Empty(); - } - - public override Empty ComplexCountTest(ReadWriteInput input) + Symbol = "ELF", + To = Context.Self, + Amount = 1000, + Memo = "failed inline test" + }.ToByteString()); + + return new Empty(); + } + + public override Empty FailCpuStoConsuming(Empty input) + { + State.Acs8Contract.CpuConsumingMethod.Send(new Empty()); + + State.Acs8Contract.StoConsumingMethod.Send(new Empty()); + + Context.SendInline(State.TokenContract.Value, "NotExist", ByteString.CopyFromUtf8("fake parameter")); + + return new Empty(); + } + + public override Empty ReadCpuCountTest(Int32Value input) + { + Assert(input.Value > 0, $"Invalid read state count {input.Value}"); + var sum = 0; + for (var i = 0; i <= input.Value % 100; i++) sum = sum.Add(State.TestInfo[i]); + + return new Empty(); + } + + public override Empty WriteRamCountTest(Int32Value input) + { + Assert(input.Value > 0, $"Invalid write state count {input.Value}"); + for (var i = 0; i <= input.Value % 100; i++) State.TestInfo[i] = input.Value * i; + + return new Empty(); + } + + public override Empty ComplexCountTest(ReadWriteInput input) + { + Assert(input.Read > 0 && input.Write > 0, "Invalid write/read state count input."); + WriteRamCountTest(new Int32Value { - Assert(input.Read>0 && input.Write>0, "Invalid write/read state count input."); - WriteRamCountTest(new Int32Value - { - Value = input.Write - }); - ReadCpuCountTest(new Int32Value - { - Value = input.Read - }); - - return new Empty(); - } - - public override Empty NoReadWriteCountTest(StringValue input) + Value = input.Write + }); + ReadCpuCountTest(new Int32Value { - return new Empty(); - } + Value = input.Read + }); + + return new Empty(); + } + + public override Empty NoReadWriteCountTest(StringValue input) + { + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFees/Contract_IFeeCharged.cs b/test/AElf.Contracts.TestContract.TransactionFees/Contract_IFeeCharged.cs index 4437405e8b..2dd8b0b6ac 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/Contract_IFeeCharged.cs +++ b/test/AElf.Contracts.TestContract.TransactionFees/Contract_IFeeCharged.cs @@ -1,33 +1,32 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.TransactionFees +namespace AElf.Contracts.TestContract.TransactionFees; + +public partial class TransactionFeesContract { - public partial class TransactionFeesContract + [View] + public override MethodFees GetMethodFee(StringValue input) { - [View] - public override MethodFees GetMethodFee(StringValue input) - { - var methodFees = State.TransactionFees[input.Value]; - if (methodFees != null) - return methodFees; + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) + return methodFees; - //set default tx fee - return new MethodFees + //set default tx fee + return new MethodFees + { + MethodName = input.Value, + Fees = { - MethodName = input.Value, - Fees = - { - new MethodFee {Symbol = "ELF", BasicFee = 1_00000000} - } - }; - } + new MethodFee { Symbol = "ELF", BasicFee = 1_00000000 } + } + }; + } - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFees/Contract_View.cs b/test/AElf.Contracts.TestContract.TransactionFees/Contract_View.cs index 64e12b36bc..9c6aa5c105 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/Contract_View.cs +++ b/test/AElf.Contracts.TestContract.TransactionFees/Contract_View.cs @@ -1,40 +1,39 @@ using AElf.Contracts.MultiToken; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.TransactionFees +namespace AElf.Contracts.TestContract.TransactionFees; + +public partial class TransactionFeesContract { - public partial class TransactionFeesContract + public override StringValue GetContractName(Empty input) { - public override StringValue GetContractName(Empty input) + return new StringValue { - return new StringValue - { - Value = nameof(TransactionFeesContract) - }; - } + Value = nameof(TransactionFeesContract) + }; + } - public override ResourcesOutput QueryContractResource(Empty input) + public override ResourcesOutput QueryContractResource(Empty input) + { + var symbols = new[] { "READ", "WRITE", "STORAGE", "TRAFFIC" }; + var resources = new ResourcesOutput(); + if (State.TokenContract.Value == null) + return resources; + + foreach (var symbol in symbols) { - var symbols = new[] {"READ", "WRITE", "STORAGE", "TRAFFIC"}; - var resources = new ResourcesOutput(); - if (State.TokenContract.Value == null) - return resources; - - foreach (var symbol in symbols) + var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput { - var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput - { - Owner = Context.Self, - Symbol = symbol - }); - resources.Resources.Add(new TokenInfo - { - Symbol = symbol, - Amount = balance.Balance - }); - } - - return resources; + Owner = Context.Self, + Symbol = symbol + }); + resources.Resources.Add(new TokenInfo + { + Symbol = symbol, + Amount = balance.Balance + }); } + + return resources; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TransactionFees/TransactionFeesContractState.cs b/test/AElf.Contracts.TestContract.TransactionFees/TransactionFeesContractState.cs index dca9e6dd41..c79bb9430b 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/TransactionFeesContractState.cs +++ b/test/AElf.Contracts.TestContract.TransactionFees/TransactionFeesContractState.cs @@ -1,18 +1,15 @@ -using AElf.Standards.ACS1; -using AElf.Contracts.MultiToken; +using AElf.Contracts.MultiToken; +using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; -namespace AElf.Contracts.TestContract.TransactionFees +namespace AElf.Contracts.TestContract.TransactionFees; + +public class TransactionFeesContractState : ContractState { - public class TransactionFeesContractState : ContractState - { - public MappedState TestInfo { get; set; } - public MappedState TransactionFees { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - internal AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.ContractContainer.ContractReferenceState Acs8Contract - { - get; - set; - } - } + public MappedState TestInfo { get; set; } + public MappedState TransactionFees { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } + + internal ContractContainer.ContractReferenceState Acs8Contract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Internal.Tests/AElf.Contracts.TokenConverter.Internal.Tests.csproj b/test/AElf.Contracts.TokenConverter.Internal.Tests/AElf.Contracts.TokenConverter.Internal.Tests.csproj index 7de6f8f96f..ee0c3b426f 100644 --- a/test/AElf.Contracts.TokenConverter.Internal.Tests/AElf.Contracts.TokenConverter.Internal.Tests.csproj +++ b/test/AElf.Contracts.TokenConverter.Internal.Tests/AElf.Contracts.TokenConverter.Internal.Tests.csproj @@ -6,15 +6,15 @@ - - - - - + + + + + - + diff --git a/test/AElf.Contracts.TokenConverter.Internal.Tests/BancorHelperTest.cs b/test/AElf.Contracts.TokenConverter.Internal.Tests/BancorHelperTest.cs index b8c6cb071c..751ce6825e 100644 --- a/test/AElf.Contracts.TokenConverter.Internal.Tests/BancorHelperTest.cs +++ b/test/AElf.Contracts.TokenConverter.Internal.Tests/BancorHelperTest.cs @@ -1,97 +1,95 @@ -using System; -using Xunit; using Shouldly; +using Xunit; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class BancorHelperTest { - public class BancorHelperTest - { - //init connector - private Connector _elfConnector; + //init connector + private readonly Connector _elfConnector; - private Connector _writeConnector; + private readonly Connector _writeConnector; - public BancorHelperTest() + public BancorHelperTest() + { + _writeConnector = new Connector { - _writeConnector = new Connector - { - Symbol = "WRITE", - VirtualBalance = 50_0000, - Weight = "0.5", - IsVirtualBalanceEnabled = false, - IsPurchaseEnabled = true - }; - - _elfConnector = new Connector - { - Symbol = "ELF", - VirtualBalance = 100_0000, - Weight = "0.6", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false - }; - } - - [Fact] - public void Pow_Test() + Symbol = "WRITE", + VirtualBalance = 50_0000, + Weight = "0.5", + IsVirtualBalanceEnabled = false, + IsPurchaseEnabled = true + }; + + _elfConnector = new Connector { - var result1 = BancorHelper.Pow(1.5m, 1); - result1.ShouldBe(1.5m); + Symbol = "ELF", + VirtualBalance = 100_0000, + Weight = "0.6", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false + }; + } - BancorHelper.Pow(1.5m, 2); - } + [Fact] + public void Pow_Test() + { + var result1 = BancorHelper.Pow(1.5m, 1); + result1.ShouldBe(1.5m); - [Fact] - public void GetAmountToPay_GetReturnFromPaid_Failed() - { - //fromConnectorBalance <= 0 - Should.Throw(() => BancorHelper.GetAmountToPayFromReturn(0, 1000, 1000, 1000, 1000)); - //paidAmount <= 0 - Should.Throw(() => BancorHelper.GetAmountToPayFromReturn(1000, 1000, 1000, 1000, 0)); - //toConnectorBalance <= 0 - Should.Throw(() => BancorHelper.GetReturnFromPaid(1000, 1000, 0, 1000, 1000)); - //amountToReceive <= 0 - Should.Throw(() => BancorHelper.GetReturnFromPaid(1000, 1000, 1000, 1000, 0)); - } - - [Theory] - [InlineData(100L)] - [InlineData(1000L)] - [InlineData(10000L)] - public void BuyResource_Test(long paidElf) - { - var resourceAmount1 = BuyOperation(paidElf); - var resourceAmount2 = BuyOperation(paidElf); - resourceAmount1.ShouldBeGreaterThanOrEqualTo(resourceAmount2); - } + BancorHelper.Pow(1.5m, 2); + } - [Theory] - [InlineData(100L)] - [InlineData(1000L)] - [InlineData(10000L)] - public void SellResource_Test(long paidRes) - { - var elfAmount1 = SellOperation(paidRes); - var elfAmount2 = SellOperation(paidRes); - elfAmount1.ShouldBeGreaterThanOrEqualTo(elfAmount2); - } - - private long BuyOperation(long paidElf) - { - var getAmountToPayout = BancorHelper.GetAmountToPayFromReturn( - _elfConnector.VirtualBalance, Decimal.Parse(_elfConnector.Weight), - _writeConnector.VirtualBalance, Decimal.Parse(_writeConnector.Weight), - paidElf); - return getAmountToPayout; - } + [Fact] + public void GetAmountToPay_GetReturnFromPaid_Failed() + { + //fromConnectorBalance <= 0 + Should.Throw(() => BancorHelper.GetAmountToPayFromReturn(0, 1000, 1000, 1000, 1000)); + //paidAmount <= 0 + Should.Throw(() => BancorHelper.GetAmountToPayFromReturn(1000, 1000, 1000, 1000, 0)); + //toConnectorBalance <= 0 + Should.Throw(() => BancorHelper.GetReturnFromPaid(1000, 1000, 0, 1000, 1000)); + //amountToReceive <= 0 + Should.Throw(() => BancorHelper.GetReturnFromPaid(1000, 1000, 1000, 1000, 0)); + } - private long SellOperation(long paidRes) - { - var getReturnFromPaid = BancorHelper.GetReturnFromPaid( - _writeConnector.VirtualBalance, Decimal.Parse(_writeConnector.Weight), - _elfConnector.VirtualBalance, Decimal.Parse(_elfConnector.Weight), - paidRes); - return getReturnFromPaid; - } + [Theory] + [InlineData(100L)] + [InlineData(1000L)] + [InlineData(10000L)] + public void BuyResource_Test(long paidElf) + { + var resourceAmount1 = BuyOperation(paidElf); + var resourceAmount2 = BuyOperation(paidElf); + resourceAmount1.ShouldBeGreaterThanOrEqualTo(resourceAmount2); + } + + [Theory] + [InlineData(100L)] + [InlineData(1000L)] + [InlineData(10000L)] + public void SellResource_Test(long paidRes) + { + var elfAmount1 = SellOperation(paidRes); + var elfAmount2 = SellOperation(paidRes); + elfAmount1.ShouldBeGreaterThanOrEqualTo(elfAmount2); + } + + private long BuyOperation(long paidElf) + { + var getAmountToPayout = BancorHelper.GetAmountToPayFromReturn( + _elfConnector.VirtualBalance, decimal.Parse(_elfConnector.Weight), + _writeConnector.VirtualBalance, decimal.Parse(_writeConnector.Weight), + paidElf); + return getAmountToPayout; + } + + private long SellOperation(long paidRes) + { + var getReturnFromPaid = BancorHelper.GetReturnFromPaid( + _writeConnector.VirtualBalance, decimal.Parse(_writeConnector.Weight), + _elfConnector.VirtualBalance, decimal.Parse(_elfConnector.Weight), + paidRes); + return getReturnFromPaid; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/ACS1_ImplementTest.cs b/test/AElf.Contracts.TokenConverter.Tests/ACS1_ImplementTest.cs index 0286fd2125..ac1d66db71 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/ACS1_ImplementTest.cs @@ -1,220 +1,218 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContractTests { - public partial class TokenConverterContractTests + [Fact] + public async Task ChangeMethodFeeController_Test() { - [Fact] - public async Task ChangeMethodFeeController_Test() - { - //await InitializeParliamentContractAsync(); - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync( - new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(DefaultStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(TokenConverterContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + //await InitializeParliamentContractAsync(); + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var newMethodFeeController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } - - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - //await InitializeParliamentContractAsync(); - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput + ProposalReleaseThreshold = new ProposalReleaseThreshold { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await DefaultStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } - - [Fact] - public async Task GetMethodFeeController_Test() - { - var defaultController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); - defaultController.ContractAddress.ShouldBe(ParliamentContractAddress); - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - defaultController.OwnerAddress.ShouldBe(defaultParliament); - } - - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() - { - var releaseResult = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, nameof(DefaultStub.ChangeMethodFeeController), new AuthorityInfo - { - OwnerAddress = DefaultSender, - ContractAddress = ParliamentContractAddress - }); - releaseResult.Error.ShouldContain("Invalid authority input"); - } + var methodFeeController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync( + new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() - { - // Invalid amount + const string proposalCreationMethodName = nameof(DefaultStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(TokenConverterContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { - var setMethodFeeRet = await DefaultStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var newMethodFeeController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } + + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + //await InitializeParliamentContractAsync(); + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - MethodName = "Test", - Fees = + ProposalReleaseThreshold = new ProposalReleaseThreshold { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = -111 - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); - } - - // token does not exist + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await DefaultStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo { - var setMethodFeeRet = await DefaultStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task GetMethodFeeController_Test() + { + var defaultController = await DefaultStub.GetMethodFeeController.CallAsync(new Empty()); + defaultController.ContractAddress.ShouldBe(ParliamentContractAddress); + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + defaultController.OwnerAddress.ShouldBe(defaultParliament); + } + + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() + { + var releaseResult = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, nameof(DefaultStub.ChangeMethodFeeController), new AuthorityInfo + { + OwnerAddress = DefaultSender, + ContractAddress = ParliamentContractAddress + }); + releaseResult.Error.ShouldContain("Invalid authority input"); + } + + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + // Invalid amount + { + var setMethodFeeRet = await DefaultStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + { + MethodName = "Test", + Fees = { - MethodName = "Test", - Fees = + new MethodFee { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = 111 - } + Symbol = "NOTEXIST", + BasicFee = -111 } - }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); - } + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); } - - [Fact] - public async Task SetMethodFee_Without_Authority_Test() + + // token does not exist { - var tokenSymbol = "KYO"; - var methodName = "Test"; - var basicFee = 111; - await CreateTokenAsync(tokenSymbol, 1000_000L); var setMethodFeeRet = await DefaultStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - MethodName = methodName, + MethodName = "Test", Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = basicFee + Symbol = "NOTEXIST", + BasicFee = 111 } } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); } + } - [Fact] - public async Task SetMethodFee_Success_Test() + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + var tokenSymbol = "KYO"; + var methodName = "Test"; + var basicFee = 111; + await CreateTokenAsync(tokenSymbol, 1000_000L); + var setMethodFeeRet = await DefaultStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - var tokenSymbol = "KYO"; - var methodName = "Test"; - var basicFee = 111; - await CreateTokenAsync(tokenSymbol, 1000_000L); - await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetMethodFee), new MethodFees + MethodName = methodName, + Fees = + { + new MethodFee { - MethodName = methodName, - Fees = + Symbol = tokenSymbol, + BasicFee = basicFee + } + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task SetMethodFee_Success_Test() + { + var tokenSymbol = "KYO"; + var methodName = "Test"; + var basicFee = 111; + await CreateTokenAsync(tokenSymbol, 1000_000L); + await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetMethodFee), new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee { - new MethodFee - { - Symbol = tokenSymbol, - BasicFee = basicFee - } + Symbol = tokenSymbol, + BasicFee = basicFee } - }); - var getMethodFee = await DefaultStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName + } }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); - } + var getMethodFee = await DefaultStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); + } - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; - } + return proposalId; + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/AElf.Contracts.TokenConverter.Tests.csproj b/test/AElf.Contracts.TokenConverter.Tests/AElf.Contracts.TokenConverter.Tests.csproj index 96bc105652..bb28570387 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/AElf.Contracts.TokenConverter.Tests.csproj +++ b/test/AElf.Contracts.TokenConverter.Tests/AElf.Contracts.TokenConverter.Tests.csproj @@ -6,17 +6,17 @@ - - - - - - + + + + + + - - + + @@ -41,9 +41,9 @@ - - Protobuf\Proto\token_contract.proto - + + Protobuf\Proto\token_contract.proto + Protobuf\Proto\token_converter_contract.proto @@ -70,5 +70,5 @@ - + diff --git a/test/AElf.Contracts.TokenConverter.Tests/BancorHelper.cs b/test/AElf.Contracts.TokenConverter.Tests/BancorHelper.cs index 2d7622bac3..0b173d3ad7 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/BancorHelper.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/BancorHelper.cs @@ -1,186 +1,170 @@ using System; using System.Collections; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class BancorHelper { - public class BancorHelper + /// + /// Get token return: + /// Return = (1 - (fromConnectorBalance / (fromConnectorBalance + paidAmount)) + /// ^(fromConnectorWeight/toConnectorWeight))*toConnectorBalance + /// + /// + /// + /// + /// + /// + /// + public static long GetReturnFromPaid(long fromConnectorBalance, decimal fromConnectorWeight, + long toConnectorBalance, decimal toConnectorWeight, long paidAmount) { - /// - /// Get token return: - /// Return = (1 - (fromConnectorBalance / (fromConnectorBalance + paidAmount)) ^(fromConnectorWeight/toConnectorWeight))*toConnectorBalance - /// - /// - /// - /// - /// - /// - /// - public static long GetReturnFromPaid(long fromConnectorBalance, decimal fromConnectorWeight, - long toConnectorBalance, decimal toConnectorWeight, long paidAmount) - { - if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) - { - throw new InvalidValueException("Connector balance needs to be a positive number."); - } - - if (paidAmount <= 0) - { - throw new InvalidValueException("Amount needs to be a positive number."); - } - - decimal bf = fromConnectorBalance; - decimal wf = fromConnectorWeight; - decimal bt = toConnectorBalance; - decimal wt = toConnectorWeight; - decimal a = paidAmount; - if (wf == wt) - { - // if both weights are the same, the formula can be reduced - return (long) (bt * a / (bf + a)); - } - - decimal x = bf / (bf + a); - decimal y = wf / wt; - return (long) (bt * (Decimal.One - Exp(y * Ln(x)))); - } + if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) + throw new InvalidValueException("Connector balance needs to be a positive number."); + + if (paidAmount <= 0) throw new InvalidValueException("Amount needs to be a positive number."); + + decimal bf = fromConnectorBalance; + var wf = fromConnectorWeight; + decimal bt = toConnectorBalance; + var wt = toConnectorWeight; + decimal a = paidAmount; + if (wf == wt) + // if both weights are the same, the formula can be reduced + return (long)(bt * a / (bf + a)); + + var x = bf / (bf + a); + var y = wf / wt; + return (long)(bt * (decimal.One - Exp(y * Ln(x)))); + } - /// - /// Get amount of token to pay: - /// amountToPay = ((toConnectorBalance / (toConnectorBalance - amountToReceive)) ^(toConnectorWeight/fromConnectorWeight) - 1)*fromConnectorBalance - /// - /// - /// - /// - /// - /// - /// - public static long GetAmountToPayFromReturn(long fromConnectorBalance, decimal fromConnectorWeight, - long toConnectorBalance, decimal toConnectorWeight, long amountToReceive) - { - if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) - { - throw new InvalidValueException("Connector balance needs to be a positive number."); - } - - if (amountToReceive <= 0) - { - throw new InvalidValueException("Amount needs to be a positive number."); - } - - decimal bf = fromConnectorBalance; - decimal wf = fromConnectorWeight; - decimal bt = toConnectorBalance; - decimal wt = toConnectorWeight; - decimal a = amountToReceive; - if (wf == wt) - { - // if both weights are the same, the formula can be reduced - return (long) (bf * a / (bt - a)); - } - - decimal x = bt / (bt - a); - decimal y = wt / wf; - return (long) (bf * (Exp(y * Ln(x)) - Decimal.One)); - } + /// + /// Get amount of token to pay: + /// amountToPay = ((toConnectorBalance / (toConnectorBalance - amountToReceive)) + /// ^(toConnectorWeight/fromConnectorWeight) - 1)*fromConnectorBalance + /// + /// + /// + /// + /// + /// + /// + public static long GetAmountToPayFromReturn(long fromConnectorBalance, decimal fromConnectorWeight, + long toConnectorBalance, decimal toConnectorWeight, long amountToReceive) + { + if (fromConnectorBalance <= 0 || toConnectorBalance <= 0) + throw new InvalidValueException("Connector balance needs to be a positive number."); + + if (amountToReceive <= 0) throw new InvalidValueException("Amount needs to be a positive number."); + + decimal bf = fromConnectorBalance; + var wf = fromConnectorWeight; + decimal bt = toConnectorBalance; + var wt = toConnectorWeight; + decimal a = amountToReceive; + if (wf == wt) + // if both weights are the same, the formula can be reduced + return (long)(bf * a / (bt - a)); + + var x = bt / (bt - a); + var y = wt / wf; + return (long)(bf * (Exp(y * Ln(x)) - decimal.One)); + } - #region Exponential Helpers + #region Exponential Helpers - static readonly uint _LOOPS = 20; // Max = 20 + private static readonly uint _LOOPS = 20; // Max = 20 - private static long[] Fact = - { - 1L, - 1L * 2, - 1L * 2 * 3, - 1L * 2 * 3 * 4, - 1L * 2 * 3 * 4 * 5, - 1L * 2 * 3 * 4 * 5 * 6, - 1L * 2 * 3 * 4 * 5 * 6 * 7, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19, - 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20, - //14197454024290336768L, //1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21, // NOTE: Overflow during compilation - //17196083355034583040L, //1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 // NOTE: Overflow during compilation - }; - - // http://www.daimi.au.dk/~ivan/FastExpproject.pdf - // Left to Right Binary Exponentiation - public static decimal Pow(decimal x, uint y) + private static readonly long[] Fact = + { + 1L, + 1L * 2, + 1L * 2 * 3, + 1L * 2 * 3 * 4, + 1L * 2 * 3 * 4 * 5, + 1L * 2 * 3 * 4 * 5 * 6, + 1L * 2 * 3 * 4 * 5 * 6 * 7, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19, + 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 + //14197454024290336768L, //1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21, // NOTE: Overflow during compilation + //17196083355034583040L, //1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 // NOTE: Overflow during compilation + }; + + // http://www.daimi.au.dk/~ivan/FastExpproject.pdf + // Left to Right Binary Exponentiation + public static decimal Pow(decimal x, uint y) + { + if (y == 1) + return x; + + var A = 1m; + var e = new BitArray(y.ToBytes(false)); + var t = e.Count; + + for (var i = t - 1; i >= 0; --i) { - if (y == 1) - return x; - - decimal A = 1m; - BitArray e = new BitArray(y.ToBytes(false)); - int t = e.Count; - - for (int i = t - 1; i >= 0; --i) - { - A *= A; - if (e[i] == true) - { - A *= x; - } - } - - return A; + A *= A; + if (e[i]) A *= x; } - // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal - // natural logarithm series - private static decimal Ln(decimal a) + return A; + } + + // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal + // natural logarithm series + private static decimal Ln(decimal a) + { + /* + ln(a) = log(1-x) = - x - x^2/2 - x^3/3 - ... (where |x| < 1) + x: a = 1-x => x = 1-a = 1 - 1.004 = -.004 + */ + var x = 1 - a; + if (Math.Abs(x) >= 1) + throw new Exception("must be 0 < a < 2"); + + decimal result = 0; + var iteration = _LOOPS; + while (iteration > 0) { - /* - ln(a) = log(1-x) = - x - x^2/2 - x^3/3 - ... (where |x| < 1) - x: a = 1-x => x = 1-a = 1 - 1.004 = -.004 - */ - decimal x = 1 - a; - if (Math.Abs(x) >= 1) - throw new Exception("must be 0 < a < 2"); - - decimal result = 0; - uint iteration = _LOOPS; - while (iteration > 0) - { - result -= Pow(x, iteration) / iteration; - iteration--; - } - - return result; + result -= Pow(x, iteration) / iteration; + iteration--; } + return result; + } + - // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal - // power series - private static decimal Exp(decimal y) + // http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal + // power series + private static decimal Exp(decimal y) + { + /* + exp(y) = 1 + y + y^2/2 + x^3/3! + y^4/4! + y^5/5! + ... + */ + + var iteration = _LOOPS; + decimal result = 1; + while (iteration > 0) { - /* - exp(y) = 1 + y + y^2/2 + x^3/3! + y^4/4! + y^5/5! + ... - */ - - uint iteration = _LOOPS; - decimal result = 1; - while (iteration > 0) - { - //uint fatorial = Factorial(iteration); - var fatorial = Fact[iteration - 1]; - result += (Pow(y, iteration) / fatorial); - iteration--; - } - - return result; + //uint fatorial = Factorial(iteration); + var fatorial = Fact[iteration - 1]; + result += Pow(y, iteration) / fatorial; + iteration--; } - #endregion Exponential Helpers + return result; } + + #endregion Exponential Helpers } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/InvalidValueException.cs b/test/AElf.Contracts.TokenConverter.Tests/InvalidValueException.cs index b2d8597001..bd18d566d7 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/InvalidValueException.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/InvalidValueException.cs @@ -1,11 +1,10 @@ using AElf.Sdk.CSharp; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class InvalidValueException : BaseAElfException { - public class InvalidValueException : BaseAElfException + public InvalidValueException(string message) : base(message) { - public InvalidValueException(string message) : base(message) - { - } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs index 5b2606e835..fdefbd921a 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Standards.ACS3; @@ -11,595 +11,593 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContractTests { - public partial class TokenConverterContractTests + public TokenConverterContractTests() { - public TokenConverterContractTests() - { - AsyncHelper.RunSync(InitializeParliamentContractAsync); - } + AsyncHelper.RunSync(InitializeParliamentContractAsync); + } - [Fact] - public async Task DefaultController_Test() - { - var defaultController = await DefaultStub.GetControllerForManageConnector.CallAsync(new Empty()); - defaultController.ContractAddress.ShouldBe(ParliamentContractAddress); - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - defaultController.OwnerAddress.ShouldBe(defaultParliament); - } + [Fact] + public async Task DefaultController_Test() + { + var defaultController = await DefaultStub.GetControllerForManageConnector.CallAsync(new Empty()); + defaultController.ContractAddress.ShouldBe(ParliamentContractAddress); + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + defaultController.OwnerAddress.ShouldBe(defaultParliament); + } - [Fact] - public async Task TransferAuthorizationForTokenConvert_Fail_Test() + [Fact] + public async Task TransferAuthorizationForTokenConvert_Fail_Test() + { + // sender is not authorized { - // sender is not authorized - { - var changeControllerRet = - await DefaultStub.ChangeConnectorController.SendWithExceptionAsync(new AuthorityInfo()); - changeControllerRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); - } - - //invalid authority - { - var newAuthority = new AuthorityInfo - { - ContractAddress = ParliamentContractAddress, - OwnerAddress = DefaultSender - }; - var changeControllerRet = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub - .ChangeConnectorController), - newAuthority); - changeControllerRet.Error.ShouldContain("new controller does not exist"); - } + var changeControllerRet = + await DefaultStub.ChangeConnectorController.SendWithExceptionAsync(new AuthorityInfo()); + changeControllerRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); } - [Fact] - public async Task TransferAuthorizationForTokenConvert_Success_Test() + //invalid authority { - var newParliament = new Parliament.CreateOrganizationInput - { - ProposerAuthorityRequired = false, - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MaximalAbstentionThreshold = 1, - MaximalRejectionThreshold = 1, - MinimalApprovalThreshold = 1, - MinimalVoteThreshold = 1 - }, - ParliamentMemberProposingAllowed = false - }; - var createNewParliament = - (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; - createNewParliament.Status.ShouldBe(TransactionResultStatus.Mined); - var calculatedNewParliamentAddress = - await ParliamentContractStub.CalculateOrganizationAddress.CallAsync(newParliament); var newAuthority = new AuthorityInfo { ContractAddress = ParliamentContractAddress, - OwnerAddress = calculatedNewParliamentAddress + OwnerAddress = DefaultSender }; - await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.ChangeConnectorController), + var changeControllerRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub + .ChangeConnectorController), newAuthority); - var controller = await DefaultStub - .GetControllerForManageConnector.CallAsync(new Empty()); - controller.OwnerAddress.ShouldBe(calculatedNewParliamentAddress); + changeControllerRet.Error.ShouldContain("new controller does not exist"); } + } + + [Fact] + public async Task TransferAuthorizationForTokenConvert_Success_Test() + { + var newParliament = new CreateOrganizationInput + { + ProposerAuthorityRequired = false, + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MaximalAbstentionThreshold = 1, + MaximalRejectionThreshold = 1, + MinimalApprovalThreshold = 1, + MinimalVoteThreshold = 1 + }, + ParliamentMemberProposingAllowed = false + }; + var createNewParliament = + (await ParliamentContractStub.CreateOrganization.SendAsync(newParliament)).TransactionResult; + createNewParliament.Status.ShouldBe(TransactionResultStatus.Mined); + var calculatedNewParliamentAddress = + await ParliamentContractStub.CalculateOrganizationAddress.CallAsync(newParliament); + var newAuthority = new AuthorityInfo + { + ContractAddress = ParliamentContractAddress, + OwnerAddress = calculatedNewParliamentAddress + }; + await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.ChangeConnectorController), + newAuthority); + var controller = await DefaultStub + .GetControllerForManageConnector.CallAsync(new Empty()); + controller.OwnerAddress.ShouldBe(calculatedNewParliamentAddress); + } - [Theory] - [InlineData("WRITE", "0.5", "0.5", "resource token symbol has existed")] - [InlineData("", "0.5", "0.5", "resource token symbol should not be empty")] - [InlineData("N89", "0.2", "0.5", "Invalid symbol.")] - [InlineData("MKA", "0", "0.5", "Connector Shares has to be a decimal between 0 and 1.")] - [InlineData("JUN", "0.9", "1", "Connector Shares has to be a decimal between 0 and 1.")] - public async Task AddPairConnector_With_Invalid_Input_Test(string tokenSymbol, string resourceWeight, - string nativeWeight, string errorMessage) + [Theory] + [InlineData("WRITE", "0.5", "0.5", "resource token symbol has existed")] + [InlineData("", "0.5", "0.5", "resource token symbol should not be empty")] + [InlineData("N89", "0.2", "0.5", "Invalid symbol.")] + [InlineData("MKA", "0", "0.5", "Connector Shares has to be a decimal between 0 and 1.")] + [InlineData("JUN", "0.9", "1", "Connector Shares has to be a decimal between 0 and 1.")] + public async Task AddPairConnector_With_Invalid_Input_Test(string tokenSymbol, string resourceWeight, + string nativeWeight, string errorMessage) + { + if (tokenSymbol == "WRITE") { - if (tokenSymbol == "WRITE") - { - var writeConnector = GetLegalPairConnectorParam(tokenSymbol); - await ExecuteProposalForParliamentTransaction( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), - writeConnector); - } - - var pairConnector = GetLegalPairConnectorParam(tokenSymbol); - pairConnector.NativeWeight = nativeWeight; - pairConnector.ResourceWeight = resourceWeight; - var addPairConnectorRet = await ExecuteProposalForParliamentTransactionWithException( + var writeConnector = GetLegalPairConnectorParam(tokenSymbol); + await ExecuteProposalForParliamentTransaction( TokenConverterContractAddress, nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), - pairConnector); - addPairConnectorRet.Error.ShouldContain(errorMessage); + writeConnector); } - [Fact] - public async Task AddPairConnector_Without_Authority_Test() + var pairConnector = GetLegalPairConnectorParam(tokenSymbol); + pairConnector.NativeWeight = nativeWeight; + pairConnector.ResourceWeight = resourceWeight; + var addPairConnectorRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), + pairConnector); + addPairConnectorRet.Error.ShouldContain(errorMessage); + } + + [Fact] + public async Task AddPairConnector_Without_Authority_Test() + { + var tokenSymbol = "NETT"; + var pairConnector = GetLegalPairConnectorParam(tokenSymbol); + var addConnectorWithoutAuthorityRet = + await DefaultStub.AddPairConnector.SendWithExceptionAsync( + pairConnector); + addConnectorWithoutAuthorityRet.TransactionResult.Error.ShouldContain( + "Only manager can perform this action."); + } + + [Fact] + public async Task AddPairConnector_Success_Test() + { + var tokenSymbol = "CWJ"; + var pairConnector = GetLegalPairConnectorParam(tokenSymbol); + await ExecuteProposalForParliamentTransaction( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), + pairConnector); + var getPairConnector = + await DefaultStub.GetPairConnector.CallAsync( + new TokenSymbol + { + Symbol = tokenSymbol + }); + getPairConnector.ResourceConnector.Symbol.ShouldBe(tokenSymbol); + } + + [Fact] + public async Task UpdateConnector_Without_Authority_Test() + { + var tokenSymbol = "CWJ"; + await AddPairConnectorAsync(tokenSymbol); + var updateConnector = new Connector { - string tokenSymbol = "NETT"; - var pairConnector = GetLegalPairConnectorParam(tokenSymbol); - var addConnectorWithoutAuthorityRet = - await DefaultStub.AddPairConnector.SendWithExceptionAsync( - pairConnector); - addConnectorWithoutAuthorityRet.TransactionResult.Error.ShouldContain( - "Only manager can perform this action."); - } + Symbol = tokenSymbol, + Weight = "0.3" + }; + var updateRet = + await DefaultStub.UpdateConnector.SendWithExceptionAsync( + updateConnector); + updateRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); + } - [Fact] - public async Task AddPairConnector_Success_Test() + // if update resource token connector, the virtual balance as a parameter should not equal to the origin one. + [Theory] + [InlineData(true, "", "0.5", 0, "input symbol can not be empty")] + [InlineData(true, "TTA", "0.5", 0, "Can not find target connector.")] + [InlineData(true, "LIO", "0.5a", 0, "Invalid decimal")] + [InlineData(true, "LIO", "1", 0, "Connector Shares has to be a decimal between 0 and 1.")] + [InlineData(true, "LIO", "0.5", 20, "")] + [InlineData(false, "LIO", "0.3", 200, "")] + public async Task UpdateConnector_Test(bool isUpdateResourceToken, string inputTokenSymbol, + string weight, long virtualBalance, string error) + { + var creatConnectorTokenSymbol = "LIO"; + await AddPairConnectorAsync(creatConnectorTokenSymbol); + var pairConnector = + await DefaultStub.GetPairConnector.CallAsync( + new TokenSymbol + { + Symbol = creatConnectorTokenSymbol + }); + var updateConnectorInput = + isUpdateResourceToken ? pairConnector.ResourceConnector : pairConnector.DepositConnector; + if (isUpdateResourceToken) + updateConnectorInput.Symbol = inputTokenSymbol; + updateConnectorInput.Weight = weight; + updateConnectorInput.VirtualBalance = virtualBalance; + + if (!string.IsNullOrEmpty(error)) + { + var updateRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), + updateConnectorInput); + updateRet.Error.ShouldContain(error); + } + else { - var tokenSymbol = "CWJ"; - var pairConnector = GetLegalPairConnectorParam(tokenSymbol); await ExecuteProposalForParliamentTransaction( TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), - pairConnector); - var getPairConnector = + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), + updateConnectorInput); + var afterUpdatePairConnector = await DefaultStub.GetPairConnector.CallAsync( new TokenSymbol { - Symbol = tokenSymbol + Symbol = creatConnectorTokenSymbol }); - getPairConnector.ResourceConnector.Symbol.ShouldBe(tokenSymbol); + var afterUpdateConnector = + isUpdateResourceToken + ? afterUpdatePairConnector.ResourceConnector + : afterUpdatePairConnector.DepositConnector; + updateConnectorInput.Weight.ShouldBe(afterUpdateConnector.Weight); + if (isUpdateResourceToken) + updateConnectorInput.VirtualBalance.ShouldNotBe(afterUpdateConnector.VirtualBalance); + else + updateConnectorInput.VirtualBalance.ShouldBe(afterUpdateConnector.VirtualBalance); } + } - [Fact] - public async Task UpdateConnector_Without_Authority_Test() + [Fact] + public async Task Trade_With_UnPurchasable_Connector_Test() + { + var symbol = "PXY"; + await AddPairConnectorAsync(symbol); + var buyRet = await DefaultStub.Buy.SendWithExceptionAsync(new BuyInput { - var tokenSymbol = "CWJ"; - await AddPairConnectorAsync(tokenSymbol); - var updateConnector = new Connector - { - Symbol = tokenSymbol, - Weight = "0.3" - }; - var updateRet = - await DefaultStub.UpdateConnector.SendWithExceptionAsync( - updateConnector); - updateRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); - } + Symbol = symbol, + Amount = 100 + }); + buyRet.TransactionResult.Error.ShouldContain("can't purchase"); - // if update resource token connector, the virtual balance as a parameter should not equal to the origin one. - [Theory] - [InlineData(true, "", "0.5", 0, "input symbol can not be empty")] - [InlineData(true, "TTA", "0.5", 0, "Can not find target connector.")] - [InlineData(true, "LIO", "0.5a", 0, "Invalid decimal")] - [InlineData(true, "LIO", "1", 0, "Connector Shares has to be a decimal between 0 and 1.")] - [InlineData(true, "LIO", "0.5", 20, "")] - [InlineData(false, "LIO", "0.3", 200, "")] - public async Task UpdateConnector_Test(bool isUpdateResourceToken, string inputTokenSymbol, - string weight, long virtualBalance, string error) - { - var creatConnectorTokenSymbol = "LIO"; - await AddPairConnectorAsync(creatConnectorTokenSymbol); - var pairConnector = - await DefaultStub.GetPairConnector.CallAsync( - new TokenSymbol + var sellRet = await DefaultStub.Buy.SendWithExceptionAsync(new BuyInput + { + Symbol = symbol, + Amount = 100 + }); + sellRet.TransactionResult.Error.ShouldContain("can't purchase"); + } + + [Fact] + public async Task SetFeeRate_Test() + { + //not controller + { + var setFeeRateRet = + await DefaultStub.SetFeeRate.SendWithExceptionAsync( + new StringValue { - Symbol = creatConnectorTokenSymbol + Value = "0.5" }); - var updateConnectorInput = - isUpdateResourceToken ? pairConnector.ResourceConnector : pairConnector.DepositConnector; - if (isUpdateResourceToken) - updateConnectorInput.Symbol = inputTokenSymbol; - updateConnectorInput.Weight = weight; - updateConnectorInput.VirtualBalance = virtualBalance; - - if (!string.IsNullOrEmpty(error)) - { - var updateRet = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), - updateConnectorInput); - updateRet.Error.ShouldContain(error); - } - else - { - await ExecuteProposalForParliamentTransaction( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), - updateConnectorInput); - var afterUpdatePairConnector = - await DefaultStub.GetPairConnector.CallAsync( - new TokenSymbol - { - Symbol = creatConnectorTokenSymbol - }); - var afterUpdateConnector = - isUpdateResourceToken - ? afterUpdatePairConnector.ResourceConnector - : afterUpdatePairConnector.DepositConnector; - updateConnectorInput.Weight.ShouldBe(afterUpdateConnector.Weight); - if (isUpdateResourceToken) - updateConnectorInput.VirtualBalance.ShouldNotBe(afterUpdateConnector.VirtualBalance); - else - updateConnectorInput.VirtualBalance.ShouldBe(afterUpdateConnector.VirtualBalance); - } + setFeeRateRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); } - [Fact] - public async Task Trade_With_UnPurchasable_Connector_Test() + var invalidRate = new StringValue(); + // can not parse { - var symbol = "PXY"; - await AddPairConnectorAsync(symbol); - var buyRet = await DefaultStub.Buy.SendWithExceptionAsync(new BuyInput - { - Symbol = symbol, - Amount = 100 - }); - buyRet.TransactionResult.Error.ShouldContain("can't purchase"); - - var sellRet = await DefaultStub.Buy.SendWithExceptionAsync(new BuyInput - { - Symbol = symbol, - Amount = 100 - }); - sellRet.TransactionResult.Error.ShouldContain("can't purchase"); + invalidRate.Value = "asd"; + var setFeeRateRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), invalidRate); + setFeeRateRet.Error.ShouldContain("Invalid decimal"); } - [Fact] - public async Task SetFeeRate_Test() + // == 1 { - //not controller - { - var setFeeRateRet = - await DefaultStub.SetFeeRate.SendWithExceptionAsync( - new StringValue - { - Value = "0.5" - }); - setFeeRateRet.TransactionResult.Error.ShouldContain("Only manager can perform this action."); - } - - var invalidRate = new StringValue(); - // can not parse - { - invalidRate.Value = "asd"; - var setFeeRateRet = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), invalidRate); - setFeeRateRet.Error.ShouldContain("Invalid decimal"); - } - - // == 1 - { - invalidRate.Value = "1"; - var setFeeRateRet = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), invalidRate); - setFeeRateRet.Error.ShouldContain("Fee rate has to be a decimal between 0 and 1."); - } - - // success - { - var validRate = new StringValue - { - Value = "0.333" - }; - await ExecuteProposalForParliamentTransaction( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), validRate); - var getFeeRate = - await DefaultStub.GetFeeRate.CallAsync(new Empty()); - getFeeRate.Value.ShouldBe(validRate.Value); - } + invalidRate.Value = "1"; + var setFeeRateRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), invalidRate); + setFeeRateRet.Error.ShouldContain("Fee rate has to be a decimal between 0 and 1."); } - [Fact] - public async Task Set_Connector_Test() + // success { - var tokenSymbol = "TRA"; - //with authority user + var validRate = new StringValue { - var createTokenRet = (await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "NET name", - TotalSupply = 100_0000_0000, - Issuer = DefaultSender, - IsBurnable = true - })).TransactionResult; - createTokenRet.Status.ShouldBe(TransactionResultStatus.Mined); - var pairConnector = new PairConnectorParam - { - ResourceConnectorSymbol = tokenSymbol, - ResourceWeight = "0.05", - NativeWeight = "0.05", - NativeVirtualBalance = 1_000_000_00000000, - }; - await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), - pairConnector); - var ramNewInfo = - (await DefaultStub.GetPairConnector.CallAsync( - new TokenSymbol() - { - Symbol = tokenSymbol - })).ResourceConnector; - ramNewInfo.IsPurchaseEnabled.ShouldBeFalse(); - } + Value = "0.333" + }; + await ExecuteProposalForParliamentTransaction( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.SetFeeRate), validRate); + var getFeeRate = + await DefaultStub.GetFeeRate.CallAsync(new Empty()); + getFeeRate.Value.ShouldBe(validRate.Value); } + } - [Fact] - public async Task Update_Connector_Success_Test() + [Fact] + public async Task Set_Connector_Test() + { + var tokenSymbol = "TRA"; + //with authority user { - var token = "NETT"; var createTokenRet = (await TokenContractStub.Create.SendAsync(new CreateInput { - Symbol = token, - TokenName = "NETT name", + Symbol = tokenSymbol, + TokenName = "NET name", TotalSupply = 100_0000_0000, Issuer = DefaultSender, - IsBurnable = true, - LockWhiteList = {TokenConverterContractAddress} + IsBurnable = true })).TransactionResult; createTokenRet.Status.ShouldBe(TransactionResultStatus.Mined); var pairConnector = new PairConnectorParam { - ResourceConnectorSymbol = token, + ResourceConnectorSymbol = tokenSymbol, ResourceWeight = "0.05", NativeWeight = "0.05", - NativeVirtualBalance = 1_0000_0000, + NativeVirtualBalance = 1_000_000_00000000 }; await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), pairConnector); - var updateConnector = new Connector - { - Symbol = token, - VirtualBalance = 1000_000, - IsVirtualBalanceEnabled = false, - IsPurchaseEnabled = true, - Weight = "0.49", - RelatedSymbol = "change" - }; - await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), - updateConnector); - var resourceConnector = + var ramNewInfo = (await DefaultStub.GetPairConnector.CallAsync( - new TokenSymbol {Symbol = token})).ResourceConnector; - resourceConnector.Weight.ShouldBe("0.49"); + new TokenSymbol + { + Symbol = tokenSymbol + })).ResourceConnector; + ramNewInfo.IsPurchaseEnabled.ShouldBeFalse(); } + } - [Fact] - public async Task EnableConnector_With_Invalid_Input_Test() + [Fact] + public async Task Update_Connector_Success_Test() + { + var token = "NETT"; + var createTokenRet = (await TokenContractStub.Create.SendAsync(new CreateInput { - var tokenSymbol = "TEST"; - - // connector does not exist - { - var enableConnectorRet = await DefaultStub.EnableConnector.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = tokenSymbol, - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find from connector."); - } + Symbol = token, + TokenName = "NETT name", + TotalSupply = 100_0000_0000, + Issuer = DefaultSender, + IsBurnable = true, + LockWhiteList = { TokenConverterContractAddress } + })).TransactionResult; + createTokenRet.Status.ShouldBe(TransactionResultStatus.Mined); + var pairConnector = new PairConnectorParam + { + ResourceConnectorSymbol = token, + ResourceWeight = "0.05", + NativeWeight = "0.05", + NativeVirtualBalance = 1_0000_0000 + }; + await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), + pairConnector); + var updateConnector = new Connector + { + Symbol = token, + VirtualBalance = 1000_000, + IsVirtualBalanceEnabled = false, + IsPurchaseEnabled = true, + Weight = "0.49", + RelatedSymbol = "change" + }; + await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), + updateConnector); + var resourceConnector = + (await DefaultStub.GetPairConnector.CallAsync( + new TokenSymbol { Symbol = token })).ResourceConnector; + resourceConnector.Weight.ShouldBe("0.49"); + } - // invalid connector(deposit) - { - await AddPairConnectorAsync(tokenSymbol); - var enableConnectorRet = await DefaultStub.EnableConnector.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find from connector."); - } + [Fact] + public async Task EnableConnector_With_Invalid_Input_Test() + { + var tokenSymbol = "TEST"; + // connector does not exist + { + var enableConnectorRet = await DefaultStub.EnableConnector.SendWithExceptionAsync( + new ToBeConnectedTokenInfo + { + TokenSymbol = tokenSymbol, + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find from connector."); } - [Fact] - public async Task EnableConnector_Success_Test() + // invalid connector(deposit) { - await DefaultStub.Initialize.SendAsync(new InitializeInput - { - FeeRate = "0.005" - }); - string tokenSymbol = "NETT"; - await CreateTokenAsync(tokenSymbol); await AddPairConnectorAsync(tokenSymbol); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Amount = 99_9999_0000, - To = DefaultSender, - Symbol = tokenSymbol - }); - var toBeBuildConnectorInfo = new ToBeConnectedTokenInfo - { - TokenSymbol = tokenSymbol, - AmountToTokenConvert = 99_9999_0000 - }; - var deposit = await DefaultStub.GetNeededDeposit.CallAsync(toBeBuildConnectorInfo); - deposit.NeedAmount.ShouldBe(100); - await DefaultStub.EnableConnector.SendAsync(toBeBuildConnectorInfo); - var tokenInTokenConvert = await GetBalanceAsync(tokenSymbol, TokenConverterContractAddress); - tokenInTokenConvert.ShouldBe(99_9999_0000); - var resourceConnector = - (await DefaultStub.GetPairConnector.CallAsync(new TokenSymbol {Symbol = tokenSymbol})) - .ResourceConnector; - resourceConnector.ShouldNotBeNull(); - resourceConnector.IsPurchaseEnabled.ShouldBe(true); - - // after enable connector buy - { - var beforeTokenBalance = await GetBalanceAsync(tokenSymbol, DefaultSender); - var beforeBaseBalance = await GetBalanceAsync(NativeSymbol, DefaultSender); - var buyRet = (await DefaultStub.Buy.SendAsync(new BuyInput + var enableConnectorRet = await DefaultStub.EnableConnector.SendWithExceptionAsync( + new ToBeConnectedTokenInfo { - Symbol = tokenSymbol, - Amount = 10000 - })).TransactionResult; - buyRet.Status.ShouldBe(TransactionResultStatus.Mined); - var afterTokenBalance = await GetBalanceAsync(tokenSymbol, DefaultSender); - var afterBaseBalance = await GetBalanceAsync(NativeSymbol, DefaultSender); - (afterTokenBalance - beforeTokenBalance).ShouldBe(10000); - (beforeBaseBalance - afterBaseBalance).ShouldBe(100); - } - - // after enable connector update connector - { - var updateRet = await ExecuteProposalForParliamentTransactionWithException( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), - resourceConnector); - updateRet.Error.ShouldContain("onnector can not be updated because it has been activated"); - } + TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find from connector."); } + } - [Fact] - public async Task GetNeededDeposit_With_Invalid_Input_Test() + [Fact] + public async Task EnableConnector_Success_Test() + { + await DefaultStub.Initialize.SendAsync(new InitializeInput { - var tokenSymbol = "TEST"; - - // connector does not exist - { - var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = tokenSymbol, - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); - } - - // invalid connector(deposit) + FeeRate = "0.005" + }); + var tokenSymbol = "NETT"; + await CreateTokenAsync(tokenSymbol); + await AddPairConnectorAsync(tokenSymbol); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = 99_9999_0000, + To = DefaultSender, + Symbol = tokenSymbol + }); + var toBeBuildConnectorInfo = new ToBeConnectedTokenInfo + { + TokenSymbol = tokenSymbol, + AmountToTokenConvert = 99_9999_0000 + }; + var deposit = await DefaultStub.GetNeededDeposit.CallAsync(toBeBuildConnectorInfo); + deposit.NeedAmount.ShouldBe(100); + await DefaultStub.EnableConnector.SendAsync(toBeBuildConnectorInfo); + var tokenInTokenConvert = await GetBalanceAsync(tokenSymbol, TokenConverterContractAddress); + tokenInTokenConvert.ShouldBe(99_9999_0000); + var resourceConnector = + (await DefaultStub.GetPairConnector.CallAsync(new TokenSymbol { Symbol = tokenSymbol })) + .ResourceConnector; + resourceConnector.ShouldNotBeNull(); + resourceConnector.IsPurchaseEnabled.ShouldBe(true); + + // after enable connector buy + { + var beforeTokenBalance = await GetBalanceAsync(tokenSymbol, DefaultSender); + var beforeBaseBalance = await GetBalanceAsync(NativeSymbol, DefaultSender); + var buyRet = (await DefaultStub.Buy.SendAsync(new BuyInput { - await AddPairConnectorAsync(tokenSymbol); - var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); - } + Symbol = tokenSymbol, + Amount = 10000 + })).TransactionResult; + buyRet.Status.ShouldBe(TransactionResultStatus.Mined); + var afterTokenBalance = await GetBalanceAsync(tokenSymbol, DefaultSender); + var afterBaseBalance = await GetBalanceAsync(NativeSymbol, DefaultSender); + (afterTokenBalance - beforeTokenBalance).ShouldBe(10000); + (beforeBaseBalance - afterBaseBalance).ShouldBe(100); } - - [Fact] - public async Task GetNeededDeposit_Success_Test() + // after enable connector update connector { - var tokenSymbol = "TEST"; + var updateRet = await ExecuteProposalForParliamentTransactionWithException( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.UpdateConnector), + resourceConnector); + updateRet.Error.ShouldContain("onnector can not be updated because it has been activated"); + } + } - // connector does not exist - { - var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = tokenSymbol, - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); - } + [Fact] + public async Task GetNeededDeposit_With_Invalid_Input_Test() + { + var tokenSymbol = "TEST"; - // invalid connector(deposit) - { - await AddPairConnectorAsync(tokenSymbol); - var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( - new ToBeConnectedTokenInfo - { - TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol - AmountToTokenConvert = 100, - }); - enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); - } + // connector does not exist + { + var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( + new ToBeConnectedTokenInfo + { + TokenSymbol = tokenSymbol, + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); } - private PairConnectorParam GetLegalPairConnectorParam(string tokenSymbol, long nativeBalance = 1_0000_0000, - string resourceWeight = "0.05", string nativeWeight = "0.05") + // invalid connector(deposit) { - return new PairConnectorParam - { - ResourceConnectorSymbol = tokenSymbol, - ResourceWeight = resourceWeight, - NativeWeight = nativeWeight, - NativeVirtualBalance = nativeBalance - }; + await AddPairConnectorAsync(tokenSymbol); + var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( + new ToBeConnectedTokenInfo + { + TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); } + } - private async Task CreateTokenAsync(string symbol, long totalSupply = 100_0000_0000) + + [Fact] + public async Task GetNeededDeposit_Success_Test() + { + var tokenSymbol = "TEST"; + + // connector does not exist { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - TokenName = symbol + " name", - TotalSupply = totalSupply, - Issuer = DefaultSender, - IsBurnable = true, - LockWhiteList = {TokenConverterContractAddress} - }); + var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( + new ToBeConnectedTokenInfo + { + TokenSymbol = tokenSymbol, + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); } - private async Task AddPairConnectorAsync(string tokenSymbol) + // invalid connector(deposit) { - var pairConnector = GetLegalPairConnectorParam(tokenSymbol); - await ExecuteProposalForParliamentTransaction( - TokenConverterContractAddress, - nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), - pairConnector); + await AddPairConnectorAsync(tokenSymbol); + var enableConnectorRet = await DefaultStub.GetNeededDeposit.SendWithExceptionAsync( + new ToBeConnectedTokenInfo + { + TokenSymbol = "nt" + tokenSymbol, // deposit connector symbol + AmountToTokenConvert = 100 + }); + enableConnectorRet.TransactionResult.Error.ShouldContain("Can't find to connector."); } + } - private async Task ApproveByParliamentMembers(Hash proposalId) + private PairConnectorParam GetLegalPairConnectorParam(string tokenSymbol, long nativeBalance = 1_0000_0000, + string resourceWeight = "0.05", string nativeWeight = "0.05") + { + return new PairConnectorParam { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - await tester.Approve.SendAsync(proposalId); - } - } + ResourceConnectorSymbol = tokenSymbol, + ResourceWeight = resourceWeight, + NativeWeight = nativeWeight, + NativeVirtualBalance = nativeBalance + }; + } - private async Task CreateAndApproveProposalForParliament(Address contract, - string method, IMessage input, Address parliamentOrganization = null) + private async Task CreateTokenAsync(string symbol, long totalSupply = 100_0000_0000) + { + await TokenContractStub.Create.SendAsync(new CreateInput { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = parliamentOrganization, - ContractMethodName = method, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contract - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalHash = createResult.Output; - await ApproveByParliamentMembers(proposalHash); - return proposalHash; - } + Symbol = symbol, + TokenName = symbol + " name", + TotalSupply = totalSupply, + Issuer = DefaultSender, + IsBurnable = true, + LockWhiteList = { TokenConverterContractAddress } + }); + } - private async Task ExecuteProposalForParliamentTransactionWithException( - Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalHash); - return releaseResult.TransactionResult; - } + private async Task AddPairConnectorAsync(string tokenSymbol) + { + var pairConnector = GetLegalPairConnectorParam(tokenSymbol); + await ExecuteProposalForParliamentTransaction( + TokenConverterContractAddress, + nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), + pairConnector); + } - private async Task ExecuteProposalForParliamentTransaction(Address contract, - string method, IMessage input, Address parliamentOrganization = null) + private async Task ApproveByParliamentMembers(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - await ParliamentContractStub.Release.SendAsync(proposalHash); + var tester = GetParliamentContractTester(bp); + await tester.Approve.SendAsync(proposalId); } } + + private async Task CreateAndApproveProposalForParliament(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = parliamentOrganization, + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contract + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalHash = createResult.Output; + await ApproveByParliamentMembers(proposalHash); + return proposalHash; + } + + private async Task ExecuteProposalForParliamentTransactionWithException( + Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalHash); + return releaseResult.TransactionResult; + } + + private async Task ExecuteProposalForParliamentTransaction(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + await ParliamentContractStub.Release.SendAsync(proposalHash); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs index 89a649c147..8d8bd44935 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs @@ -8,414 +8,415 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public partial class TokenConverterContractTests : TokenConverterTestBase { - public partial class TokenConverterContractTests : TokenConverterTestBase - { - private const string NativeSymbol = "ELF"; + private const string NativeSymbol = "ELF"; - private const string WriteSymbol = "WRITE"; + private const string WriteSymbol = "WRITE"; - //init connector - private Connector ELFConnector = new Connector - { - Symbol = NativeSymbol, - VirtualBalance = 100_0000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true - }; + //init connector + private readonly Connector ELFConnector = new() + { + Symbol = NativeSymbol, + VirtualBalance = 100_0000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true + }; + + private readonly Connector NtWriteConnector = new() + { + Symbol = "NT" + WriteSymbol, + VirtualBalance = 100_0000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + RelatedSymbol = WriteSymbol, + IsDepositAccount = true + }; + + private readonly Connector WriteConnector = new() + { + Symbol = WriteSymbol, + VirtualBalance = 0, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false, + RelatedSymbol = "NT" + WriteSymbol, + IsDepositAccount = false + }; + + #region Views Test + + [Fact] + public async Task GetBaseTokenSymbol_Test() + { + await InitializeTokenConverterContract(); + var tokenSymbol = await DefaultStub.GetBaseTokenSymbol.CallAsync(new Empty()); + tokenSymbol.ShouldNotBeNull(); + tokenSymbol.Symbol.ShouldBe("ELF"); + } - private Connector WriteConnector = new Connector - { - Symbol = WriteSymbol, - VirtualBalance = 0, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false, - RelatedSymbol = "NT" + WriteSymbol, - IsDepositAccount = false - }; - - private Connector NtWriteConnector = new Connector + [Fact] + public async Task GetPairConnector_Test() + { + await InitializeTokenConverterContract(); + var ramConnectorInfo = (await DefaultStub.GetPairConnector.CallAsync(new TokenSymbol { - Symbol = "NT" + WriteSymbol, - VirtualBalance = 100_0000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - RelatedSymbol = WriteSymbol, - IsDepositAccount = true - }; + Symbol = WriteConnector.Symbol + })).ResourceConnector; + + ramConnectorInfo.Weight.ShouldBe(WriteConnector.Weight); + ramConnectorInfo.VirtualBalance.ShouldBe(WriteConnector.VirtualBalance); + ramConnectorInfo.IsPurchaseEnabled.ShouldBe(WriteConnector.IsPurchaseEnabled); + ramConnectorInfo.IsVirtualBalanceEnabled.ShouldBe(WriteConnector.IsVirtualBalanceEnabled); + } - #region Views Test + #endregion - [Fact] - public async Task GetBaseTokenSymbol_Test() + #region Action Test + + [Fact] + public async Task Initialize_Failed_Test() + { + //Base token symbol is invalid. { - await InitializeTokenConverterContract(); - var tokenSymbol = await DefaultStub.GetBaseTokenSymbol.CallAsync(new Empty()); - tokenSymbol.ShouldNotBeNull(); - tokenSymbol.Symbol.ShouldBe("ELF"); + var input = GetLegalInitializeInput(); + input.BaseTokenSymbol = "elf1"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Base token symbol is invalid.").ShouldBeTrue(); } - [Fact] - public async Task GetPairConnector_Test() + //invalid fee rate { - await InitializeTokenConverterContract(); - var ramConnectorInfo = (await DefaultStub.GetPairConnector.CallAsync(new TokenSymbol() - { - Symbol = WriteConnector.Symbol - })).ResourceConnector; - - ramConnectorInfo.Weight.ShouldBe(WriteConnector.Weight); - ramConnectorInfo.VirtualBalance.ShouldBe(WriteConnector.VirtualBalance); - ramConnectorInfo.IsPurchaseEnabled.ShouldBe(WriteConnector.IsPurchaseEnabled); - ramConnectorInfo.IsVirtualBalanceEnabled.ShouldBe(WriteConnector.IsVirtualBalanceEnabled); + var input = GetLegalInitializeInput(); + input.FeeRate = "1ass"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Invalid decimal \"1ass\"").ShouldBeTrue(); } - #endregion + //invalid fee rate fee rate should >0 && < 1 + { + var input = GetLegalInitializeInput(); + input.FeeRate = "1"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Fee rate has to be a decimal between 0 and 1.").ShouldBeTrue(); + } - #region Action Test + //Invalid connector symbol + { + var input = GetLegalInitializeInput(); + input.Connectors[0].Symbol = "write"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Invalid symbol.").ShouldBeTrue(); + } - [Fact] - public async Task Initialize_Failed_Test() + //invalid weight rate { - //Base token symbol is invalid. - { - var input = GetLegalInitializeInput(); - input.BaseTokenSymbol = "elf1"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Base token symbol is invalid.").ShouldBeTrue(); - } - - //invalid fee rate - { - var input = GetLegalInitializeInput(); - input.FeeRate = "1ass"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Invalid decimal \"1ass\"").ShouldBeTrue(); - } - - //invalid fee rate fee rate should >0 && < 1 - { - var input = GetLegalInitializeInput(); - input.FeeRate = "1"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Fee rate has to be a decimal between 0 and 1.").ShouldBeTrue(); - } - - //Invalid connector symbol - { - var input = GetLegalInitializeInput(); - input.Connectors[0].Symbol = "write"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Invalid symbol.").ShouldBeTrue(); - } - - //invalid weight rate - { - var input = GetLegalInitializeInput(); - input.Connectors[0].Weight = "1"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Connector Shares has to be a decimal between 0 and 1.").ShouldBeTrue(); - } - - //invalid weight rate - { - var input = GetLegalInitializeInput(); - input.Connectors[0].Weight = "weight1ass"; - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Invalid decimal \"weight1ass\"").ShouldBeTrue(); - } - - //Already initialized - { - var input = GetLegalInitializeInput(); - await InitializeTokenConverterContract(); - var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; - result.Status.ShouldBe(TransactionResultStatus.Failed); - result.Error.Contains("Already initialized.").ShouldBeTrue(); - } + var input = GetLegalInitializeInput(); + input.Connectors[0].Weight = "1"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Connector Shares has to be a decimal between 0 and 1.").ShouldBeTrue(); } - - [Fact] - public async Task Initialize_With_Default_Base_Token_Test() + + //invalid weight rate { var input = GetLegalInitializeInput(); - input.BaseTokenSymbol = string.Empty; - await DefaultStub.Initialize.SendAsync(input); - var baseTokenSymbol = await DefaultStub.GetBaseTokenSymbol.CallAsync(new Empty()); - baseTokenSymbol.Symbol.Equals(NativeSymbol).ShouldBeTrue(); + input.Connectors[0].Weight = "weight1ass"; + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Invalid decimal \"weight1ass\"").ShouldBeTrue(); } - [Fact] - public async Task Buy_Success_Test() + //Already initialized { - await CreateRamToken(); - await InitializeTreasuryContractAsync(); + var input = GetLegalInitializeInput(); await InitializeTokenConverterContract(); - await PrepareToBuyAndSell(); + var result = (await DefaultStub.Initialize.SendWithExceptionAsync(input)).TransactionResult; + result.Status.ShouldBe(TransactionResultStatus.Failed); + result.Error.Contains("Already initialized.").ShouldBeTrue(); + } + } - //check the price and fee - var fromConnectorBalance = ELFConnector.VirtualBalance; - var fromConnectorWeight = decimal.Parse(ELFConnector.Weight); - var toConnectorBalance = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); - var toConnectorWeight = decimal.Parse(WriteConnector.Weight); + [Fact] + public async Task Initialize_With_Default_Base_Token_Test() + { + var input = GetLegalInitializeInput(); + input.BaseTokenSymbol = string.Empty; + await DefaultStub.Initialize.SendAsync(input); + var baseTokenSymbol = await DefaultStub.GetBaseTokenSymbol.CallAsync(new Empty()); + baseTokenSymbol.Symbol.Equals(NativeSymbol).ShouldBeTrue(); + } - var amountToPay = BancorHelper.GetAmountToPayFromReturn(fromConnectorBalance, fromConnectorWeight, - toConnectorBalance, toConnectorWeight, 1000L); - var depositAmountBeforeBuy = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue - { - Value = WriteConnector.Symbol - }); - var fee = Convert.ToInt64(amountToPay * 5 / 1000); - - var buyResult = (await DefaultStub.Buy.SendAsync( - new BuyInput - { - Symbol = WriteConnector.Symbol, - Amount = 1000L, - PayLimit = amountToPay + fee + 10L - })).TransactionResult; - buyResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //Verify the outcome of the transaction - var depositAmountAfterBuy = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue - { - Value = WriteConnector.Symbol - }); - depositAmountAfterBuy.Value.Sub(depositAmountBeforeBuy.Value).ShouldBe(amountToPay); - var balanceOfTesterWrite = await GetBalanceAsync(WriteSymbol, DefaultSender); - balanceOfTesterWrite.ShouldBe(1000L); + [Fact] + public async Task Buy_Success_Test() + { + await CreateRamToken(); + await InitializeTreasuryContractAsync(); + await InitializeTokenConverterContract(); + await PrepareToBuyAndSell(); + + //check the price and fee + var fromConnectorBalance = ELFConnector.VirtualBalance; + var fromConnectorWeight = decimal.Parse(ELFConnector.Weight); + var toConnectorBalance = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); + var toConnectorWeight = decimal.Parse(WriteConnector.Weight); + + var amountToPay = BancorHelper.GetAmountToPayFromReturn(fromConnectorBalance, fromConnectorWeight, + toConnectorBalance, toConnectorWeight, 1000L); + var depositAmountBeforeBuy = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + { + Value = WriteConnector.Symbol + }); + var fee = Convert.ToInt64(amountToPay * 5 / 1000); - var ElfBalanceLoggedInTokenConvert = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + var buyResult = (await DefaultStub.Buy.SendAsync( + new BuyInput { - Value = WriteConnector.Symbol - }); - ElfBalanceLoggedInTokenConvert.Value.ShouldBe(ELFConnector.VirtualBalance + amountToPay); - var balanceOfElfToken = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); - balanceOfElfToken.ShouldBe(amountToPay); + Symbol = WriteConnector.Symbol, + Amount = 1000L, + PayLimit = amountToPay + fee + 10L + })).TransactionResult; + buyResult.Status.ShouldBe(TransactionResultStatus.Mined); - var donatedFee = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); - donatedFee.Value[NativeSymbol].ShouldBe(fee.Div(2)); + //Verify the outcome of the transaction + var depositAmountAfterBuy = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + { + Value = WriteConnector.Symbol + }); + depositAmountAfterBuy.Value.Sub(depositAmountBeforeBuy.Value).ShouldBe(amountToPay); + var balanceOfTesterWrite = await GetBalanceAsync(WriteSymbol, DefaultSender); + balanceOfTesterWrite.ShouldBe(1000L); - var balanceOfRamToken = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); - balanceOfRamToken.ShouldBe(100_0000L - 1000L); + var ElfBalanceLoggedInTokenConvert = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + { + Value = WriteConnector.Symbol + }); + ElfBalanceLoggedInTokenConvert.Value.ShouldBe(ELFConnector.VirtualBalance + amountToPay); + var balanceOfElfToken = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); + balanceOfElfToken.ShouldBe(amountToPay); - var balanceOfTesterToken = await GetBalanceAsync(NativeSymbol, DefaultSender); - balanceOfTesterToken.ShouldBe(100_0000L - amountToPay - fee); - } + var donatedFee = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); + donatedFee.Value[NativeSymbol].ShouldBe(fee.Div(2)); - [Fact] - public async Task Buy_With_Invalid_Input_Test() - { - await CreateRamToken(); - await InitializeTokenConverterContract(); - await PrepareToBuyAndSell(); - - var buyResultNotExistConnector = (await DefaultStub.Buy.SendWithExceptionAsync( - new BuyInput - { - Symbol = "READ", - Amount = 1000L, - PayLimit = 1010L - })).TransactionResult; - buyResultNotExistConnector.Status.ShouldBe(TransactionResultStatus.Failed); - buyResultNotExistConnector.Error.Contains("Can't find to connector.").ShouldBeTrue(); - - var buyResultPriceNotGood = (await DefaultStub.Buy.SendWithExceptionAsync( - new BuyInput - { - Symbol = WriteConnector.Symbol, - Amount = 1000L, - PayLimit = 1L - })).TransactionResult; - buyResultPriceNotGood.Status.ShouldBe(TransactionResultStatus.Failed); - buyResultPriceNotGood.Error.Contains("Price not good.").ShouldBeTrue(); - } + var balanceOfRamToken = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); + balanceOfRamToken.ShouldBe(100_0000L - 1000L); - [Fact] - public async Task Sell_Success_Test() - { - await CreateRamToken(); - await InitializeTreasuryContractAsync(); - await InitializeTokenConverterContract(); - await PrepareToBuyAndSell(); - - var buyResult = (await DefaultStub.Buy.SendAsync( - new BuyInput - { - Symbol = WriteConnector.Symbol, - Amount = 1000L, - PayLimit = 1010L - })).TransactionResult; - buyResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //Balance before Sell - var treasuryBeforeSell = (await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty())).Value[NativeSymbol]; - var balanceOfElfToken = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); - var balanceOfTesterToken = await GetBalanceAsync(NativeSymbol, DefaultSender); - - //check the price and fee - var toConnectorBalance = ELFConnector.VirtualBalance + balanceOfElfToken; - var toConnectorWeight = decimal.Parse(ELFConnector.Weight); - var fromConnectorBalance = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); - var fromConnectorWeight = decimal.Parse(WriteConnector.Weight); - - var amountToReceive = BancorHelper.GetReturnFromPaid(fromConnectorBalance, fromConnectorWeight, - toConnectorBalance, toConnectorWeight, 1000L); - var depositAmountBeforeSell = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + var balanceOfTesterToken = await GetBalanceAsync(NativeSymbol, DefaultSender); + balanceOfTesterToken.ShouldBe(100_0000L - amountToPay - fee); + } + + [Fact] + public async Task Buy_With_Invalid_Input_Test() + { + await CreateRamToken(); + await InitializeTokenConverterContract(); + await PrepareToBuyAndSell(); + + var buyResultNotExistConnector = (await DefaultStub.Buy.SendWithExceptionAsync( + new BuyInput { - Value = WriteConnector.Symbol - }); - var fee = Convert.ToInt64(amountToReceive * 5 / 1000); + Symbol = "READ", + Amount = 1000L, + PayLimit = 1010L + })).TransactionResult; + buyResultNotExistConnector.Status.ShouldBe(TransactionResultStatus.Failed); + buyResultNotExistConnector.Error.Contains("Can't find to connector.").ShouldBeTrue(); - var sellResult = (await DefaultStub.Sell.SendAsync(new SellInput + var buyResultPriceNotGood = (await DefaultStub.Buy.SendWithExceptionAsync( + new BuyInput { Symbol = WriteConnector.Symbol, Amount = 1000L, - ReceiveLimit = amountToReceive - fee - 10L + PayLimit = 1L })).TransactionResult; - sellResult.Status.ShouldBe(TransactionResultStatus.Mined); + buyResultPriceNotGood.Status.ShouldBe(TransactionResultStatus.Failed); + buyResultPriceNotGood.Error.Contains("Price not good.").ShouldBeTrue(); + } + + [Fact] + public async Task Sell_Success_Test() + { + await CreateRamToken(); + await InitializeTreasuryContractAsync(); + await InitializeTokenConverterContract(); + await PrepareToBuyAndSell(); - //Verify the outcome of the transaction - var depositAmountAfterSell = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + var buyResult = (await DefaultStub.Buy.SendAsync( + new BuyInput { - Value = WriteConnector.Symbol - }); - depositAmountBeforeSell.Value.Sub(depositAmountAfterSell.Value).ShouldBe(amountToReceive); - var balanceOfTesterRam = await GetBalanceAsync(WriteSymbol, DefaultSender); - balanceOfTesterRam.ShouldBe(0L); + Symbol = WriteConnector.Symbol, + Amount = 1000L, + PayLimit = 1010L + })).TransactionResult; + buyResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //Balance before Sell + var treasuryBeforeSell = + (await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty())).Value[NativeSymbol]; + var balanceOfElfToken = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); + var balanceOfTesterToken = await GetBalanceAsync(NativeSymbol, DefaultSender); + + //check the price and fee + var toConnectorBalance = ELFConnector.VirtualBalance + balanceOfElfToken; + var toConnectorWeight = decimal.Parse(ELFConnector.Weight); + var fromConnectorBalance = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); + var fromConnectorWeight = decimal.Parse(WriteConnector.Weight); + + var amountToReceive = BancorHelper.GetReturnFromPaid(fromConnectorBalance, fromConnectorWeight, + toConnectorBalance, toConnectorWeight, 1000L); + var depositAmountBeforeSell = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + { + Value = WriteConnector.Symbol + }); + var fee = Convert.ToInt64(amountToReceive * 5 / 1000); - var treasuryAfterSell = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); - treasuryAfterSell.Value[NativeSymbol].ShouldBe(fee.Div(2) + treasuryBeforeSell); + var sellResult = (await DefaultStub.Sell.SendAsync(new SellInput + { + Symbol = WriteConnector.Symbol, + Amount = 1000L, + ReceiveLimit = amountToReceive - fee - 10L + })).TransactionResult; + sellResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //Verify the outcome of the transaction + var depositAmountAfterSell = await DefaultStub.GetDepositConnectorBalance.CallAsync(new StringValue + { + Value = WriteConnector.Symbol + }); + depositAmountBeforeSell.Value.Sub(depositAmountAfterSell.Value).ShouldBe(amountToReceive); + var balanceOfTesterRam = await GetBalanceAsync(WriteSymbol, DefaultSender); + balanceOfTesterRam.ShouldBe(0L); - var balanceOfElfTokenAfterSell = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); - balanceOfElfTokenAfterSell.ShouldBe(balanceOfElfToken - amountToReceive); + var treasuryAfterSell = await TreasuryContractStub.GetUndistributedDividends.CallAsync(new Empty()); + treasuryAfterSell.Value[NativeSymbol].ShouldBe(fee.Div(2) + treasuryBeforeSell); - var balanceOfRamToken = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); - balanceOfRamToken.ShouldBe(100_0000L); + var balanceOfElfTokenAfterSell = await GetBalanceAsync(NativeSymbol, TokenConverterContractAddress); + balanceOfElfTokenAfterSell.ShouldBe(balanceOfElfToken - amountToReceive); - var balanceOfTesterTokenAfterSell = await GetBalanceAsync(NativeSymbol, DefaultSender); - balanceOfTesterTokenAfterSell.ShouldBe(balanceOfTesterToken + amountToReceive - fee); - } + var balanceOfRamToken = await GetBalanceAsync(WriteSymbol, TokenConverterContractAddress); + balanceOfRamToken.ShouldBe(100_0000L); - [Fact] - public async Task Sell_With_Invalid_Input_Test() - { - await CreateRamToken(); - await InitializeTreasuryContractAsync(); - await InitializeTokenConverterContract(); - await PrepareToBuyAndSell(); - - var buyResult = (await DefaultStub.Buy.SendAsync( - new BuyInput - { - Symbol = WriteConnector.Symbol, - Amount = 1000L, - PayLimit = 1010L - })).TransactionResult; - buyResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var sellResultNotExistConnector = (await DefaultStub.Sell.SendWithExceptionAsync( - new SellInput() - { - Symbol = "READ", - Amount = 1000L, - ReceiveLimit = 900L - })).TransactionResult; - sellResultNotExistConnector.Status.ShouldBe(TransactionResultStatus.Failed); - sellResultNotExistConnector.Error.Contains("Can't find from connector.").ShouldBeTrue(); - - var sellResultPriceNotGood = (await DefaultStub.Sell.SendWithExceptionAsync( - new SellInput - { - Symbol = WriteConnector.Symbol, - Amount = 1000L, - ReceiveLimit = 2000L - })).TransactionResult; - sellResultPriceNotGood.Status.ShouldBe(TransactionResultStatus.Failed); - sellResultPriceNotGood.Error.Contains("Price not good.").ShouldBeTrue(); - } + var balanceOfTesterTokenAfterSell = await GetBalanceAsync(NativeSymbol, DefaultSender); + balanceOfTesterTokenAfterSell.ShouldBe(balanceOfTesterToken + amountToReceive - fee); + } - #endregion + [Fact] + public async Task Sell_With_Invalid_Input_Test() + { + await CreateRamToken(); + await InitializeTreasuryContractAsync(); + await InitializeTokenConverterContract(); + await PrepareToBuyAndSell(); - #region Private Task - private InitializeInput GetLegalInitializeInput() - { - var writeConnector = Connector.Parser.ParseFrom(WriteConnector.ToByteString()); - return new InitializeInput + var buyResult = (await DefaultStub.Buy.SendAsync( + new BuyInput { - BaseTokenSymbol = NativeSymbol, - FeeRate = "0.005", - Connectors = {writeConnector} - }; - } - - private async Task CreateRamToken() - { - var createResult = (await TokenContractStub.Create.SendAsync( - new CreateInput() - { - Symbol = WriteConnector.Symbol, - Decimals = 2, - IsBurnable = true, - Issuer = DefaultSender, - TokenName = "Write Resource", - TotalSupply = 100_0000L - })).TransactionResult; - createResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var issueResult = (await TokenContractStub.Issue.SendAsync( - new IssueInput - { - Symbol = WriteConnector.Symbol, - Amount = 100_0000L, - Memo = "Issue WRITE token", - To = TokenConverterContractAddress - })).TransactionResult; - issueResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = WriteConnector.Symbol, + Amount = 1000L, + PayLimit = 1010L + })).TransactionResult; + buyResult.Status.ShouldBe(TransactionResultStatus.Mined); - private async Task InitializeTokenConverterContract() - { - //init token converter - var input = new InitializeInput + var sellResultNotExistConnector = (await DefaultStub.Sell.SendWithExceptionAsync( + new SellInput { - BaseTokenSymbol = "ELF", - FeeRate = "0.005", - Connectors = {ELFConnector, WriteConnector, NtWriteConnector} - }; - return (await DefaultStub.Initialize.SendAsync(input)).TransactionResult; - } + Symbol = "READ", + Amount = 1000L, + ReceiveLimit = 900L + })).TransactionResult; + sellResultNotExistConnector.Status.ShouldBe(TransactionResultStatus.Failed); + sellResultNotExistConnector.Error.Contains("Can't find from connector.").ShouldBeTrue(); + + var sellResultPriceNotGood = (await DefaultStub.Sell.SendWithExceptionAsync( + new SellInput + { + Symbol = WriteConnector.Symbol, + Amount = 1000L, + ReceiveLimit = 2000L + })).TransactionResult; + sellResultPriceNotGood.Status.ShouldBe(TransactionResultStatus.Failed); + sellResultPriceNotGood.Error.Contains("Price not good.").ShouldBeTrue(); + } - private async Task PrepareToBuyAndSell() + #endregion + + #region Private Task + + private InitializeInput GetLegalInitializeInput() + { + var writeConnector = Connector.Parser.ParseFrom(WriteConnector.ToByteString()); + return new InitializeInput { - //approve - var approveTokenResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + BaseTokenSymbol = NativeSymbol, + FeeRate = "0.005", + Connectors = { writeConnector } + }; + } + + private async Task CreateRamToken() + { + var createResult = (await TokenContractStub.Create.SendAsync( + new CreateInput { - Spender = TokenConverterContractAddress, - Symbol = "ELF", - Amount = 2000L, + Symbol = WriteConnector.Symbol, + Decimals = 2, + IsBurnable = true, + Issuer = DefaultSender, + TokenName = "Write Resource", + TotalSupply = 100_0000L })).TransactionResult; - approveTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); + createResult.Status.ShouldBe(TransactionResultStatus.Mined); - var approveRamTokenResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + var issueResult = (await TokenContractStub.Issue.SendAsync( + new IssueInput { - Spender = TokenConverterContractAddress, - Symbol = "WRITE", - Amount = 2000L, + Symbol = WriteConnector.Symbol, + Amount = 100_0000L, + Memo = "Issue WRITE token", + To = TokenConverterContractAddress })).TransactionResult; - approveRamTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + issueResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private async Task InitializeTokenConverterContract() + { + //init token converter + var input = new InitializeInput + { + BaseTokenSymbol = "ELF", + FeeRate = "0.005", + Connectors = { ELFConnector, WriteConnector, NtWriteConnector } + }; + return (await DefaultStub.Initialize.SendAsync(input)).TransactionResult; + } - #endregion + private async Task PrepareToBuyAndSell() + { + //approve + var approveTokenResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = TokenConverterContractAddress, + Symbol = "ELF", + Amount = 2000L + })).TransactionResult; + approveTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var approveRamTokenResult = (await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Spender = TokenConverterContractAddress, + Symbol = "WRITE", + Amount = 2000L + })).TransactionResult; + approveRamTokenResult.Status.ShouldBe(TransactionResultStatus.Mined); } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs index 84a0b60375..e453e1b0fd 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs @@ -15,137 +15,133 @@ using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; -namespace AElf.Contracts.TokenConverter +namespace AElf.Contracts.TokenConverter; + +public class TokenConverterTestBase : AEDPoSExtensionTestBase { - public class TokenConverterTestBase : AEDPoSExtensionTestBase + public TokenConverterTestBase() { - #region Contract Address + ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List + { + ProfitSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name, + TokenConverterSmartContractAddressNameProvider.Name, + TreasurySmartContractAddressNameProvider.Name, + ParliamentSmartContractAddressNameProvider.Name, + ConsensusSmartContractAddressNameProvider.Name + })); + + AsyncHelper.RunSync(InitializeTokenAsync); + } - protected Address TokenContractAddress => - ContractAddresses[TokenSmartContractAddressNameProvider.Name]; + protected async Task GetBalanceAsync(string symbol, Address owner) + { + var balanceResult = await TokenContractStub.GetBalance.CallAsync( + new GetBalanceInput + { + Owner = owner, + Symbol = symbol + }); + return balanceResult.Balance; + } - protected Address TreasuryContractAddress => - ContractAddresses[TreasurySmartContractAddressNameProvider.Name]; + private async Task InitializeTokenAsync() + { + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "ELF", + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = 1000_0000_0000L, + Issuer = DefaultSender, + LockWhiteList = { TokenConverterContractAddress } + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = 1000_000L, + To = DefaultSender, + Memo = "Set for token converter." + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "ELF", + Amount = 100_0000_0000L, + To = ManagerAddress, + Memo = "Set for token converter." + }); + } - protected Address TokenConverterContractAddress => - ContractAddresses[TokenConverterSmartContractAddressNameProvider.Name]; + protected async Task InitializeParliamentContractAsync() + { + var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new Parliament.InitializeInput + { + PrivilegedProposer = DefaultSender, + ProposerAuthorityRequired = true + }); + CheckResult(initializeResult.TransactionResult); + } - protected Address ParliamentContractAddress => - ContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; + protected async Task InitializeTreasuryContractAsync() + { + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); + } - #endregion + private void CheckResult(TransactionResult result) + { + if (!string.IsNullOrEmpty(result.Error)) throw new Exception(result.Error); + } - #region Stubs + #region Contract Address - internal TokenContractContainer.TokenContractStub TokenContractStub => - GetTester(TokenContractAddress, DefaultSenderKeyPair); + protected Address TokenContractAddress => + ContractAddresses[TokenSmartContractAddressNameProvider.Name]; - internal TokenConverterContractImplContainer.TokenConverterContractImplStub DefaultStub => - GetTester(TokenConverterContractAddress, - DefaultSenderKeyPair); + protected Address TreasuryContractAddress => + ContractAddresses[TreasurySmartContractAddressNameProvider.Name]; - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => - GetParliamentContractTester(DefaultSenderKeyPair); + protected Address TokenConverterContractAddress => + ContractAddresses[TokenConverterSmartContractAddressNameProvider.Name]; - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + protected Address ParliamentContractAddress => + ContractAddresses[ParliamentSmartContractAddressNameProvider.Name]; - internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => - GetTester(TreasuryContractAddress, - DefaultSenderKeyPair); + #endregion - #endregion + #region Stubs - #region Properties + internal TokenContractContainer.TokenContractStub TokenContractStub => + GetTester(TokenContractAddress, DefaultSenderKeyPair); - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - protected ECKeyPair ManagerKeyPair => Accounts[11].KeyPair; - protected Address ManagerAddress => Address.FromPublicKey(ManagerKeyPair.PublicKey); - protected List InitialCoreDataCenterKeyPairs => Accounts.Take(5).Select(a => a.KeyPair).ToList(); + internal TokenConverterContractImplContainer.TokenConverterContractImplStub DefaultStub => + GetTester(TokenConverterContractAddress, + DefaultSenderKeyPair); - #endregion + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub => + GetParliamentContractTester(DefaultSenderKeyPair); - public TokenConverterTestBase() - { - ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List - { - ProfitSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name, - TokenConverterSmartContractAddressNameProvider.Name, - TreasurySmartContractAddressNameProvider.Name, - ParliamentSmartContractAddressNameProvider.Name, - ConsensusSmartContractAddressNameProvider.Name, - })); - - AsyncHelper.RunSync(InitializeTokenAsync); - } - - protected async Task GetBalanceAsync(string symbol, Address owner) - { - var balanceResult = await TokenContractStub.GetBalance.CallAsync( - new GetBalanceInput() - { - Owner = owner, - Symbol = symbol - }); - return balanceResult.Balance; - } - - private async Task InitializeTokenAsync() - { - await TokenContractStub.Create.SendAsync(new CreateInput() - { - Symbol = "ELF", - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = 1000_0000_0000L, - Issuer = DefaultSender, - LockWhiteList = {TokenConverterContractAddress} - }); - await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = 1000_000L, - To = DefaultSender, - Memo = "Set for token converter." - }); - await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = 100_0000_0000L, - To = ManagerAddress, - Memo = "Set for token converter." - }); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - protected async Task InitializeParliamentContractAsync() - { - var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new Parliament.InitializeInput() - { - PrivilegedProposer = DefaultSender, - ProposerAuthorityRequired = true - }); - CheckResult(initializeResult.TransactionResult); - } + internal TreasuryContractImplContainer.TreasuryContractImplStub TreasuryContractStub => + GetTester(TreasuryContractAddress, + DefaultSenderKeyPair); - protected async Task InitializeTreasuryContractAsync() - { - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync(new Empty()); - } + #endregion - private void CheckResult(TransactionResult result) - { - if (!string.IsNullOrEmpty(result.Error)) - { - throw new Exception(result.Error); - } - } - } + #region Properties + + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + protected ECKeyPair ManagerKeyPair => Accounts[11].KeyPair; + protected Address ManagerAddress => Address.FromPublicKey(ManagerKeyPair.PublicKey); + protected List InitialCoreDataCenterKeyPairs => Accounts.Take(5).Select(a => a.KeyPair).ToList(); + + #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestModule.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestModule.cs index 190c19152c..1c1b9d1eb0 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestModule.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestModule.cs @@ -2,19 +2,18 @@ using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Modularity; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.Modularity; + +namespace AElf.Contracts.TokenConverter; -namespace AElf.Contracts.TokenConverter +[DependsOn(typeof(ContractTestAEDPoSExtensionModule))] +public class TokenConverterTestModule : ContractTestAEDPoSExtensionModule { - [DependsOn(typeof(ContractTestAEDPoSExtensionModule))] - public class TokenConverterTestModule : ContractTestAEDPoSExtensionModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - context.Services.AddAssemblyOf(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); + context.Services.AddAssemblyOf(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/ACS1_ImplementTest.cs b/test/AElf.Contracts.TokenHolder.Tests/ACS1_ImplementTest.cs index cce18b78e6..11d960d2f6 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/ACS1_ImplementTest.cs @@ -1,145 +1,142 @@ using System.Threading.Tasks; +using AElf.Contracts.Parliament; using AElf.Standards.ACS1; using AElf.Standards.ACS3; -using AElf.Contracts.Parliament; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderTests { - public partial class TokenHolderTests + [Fact] + public async Task ChangeMethodFeeController_Test() { - - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(TokenHolderContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(TokenHolderContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } + var methodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await TokenHolderContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo + const string proposalCreationMethodName = nameof(TokenHolderContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(TokenHolderContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, ContractAddress = ParliamentContractAddress }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + var newMethodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task SetMethodFee_Without_Authority_Test() - { - var setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees - { - MethodName = "Test", - Fees = + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - new MethodFee + ProposalReleaseThreshold = new ProposalReleaseThreshold { - BasicFee = 100, - Symbol = "ELF" + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } - } - }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); - } - - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() + }); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await TokenHolderContractStub.ChangeMethodFeeController.SendWithExceptionAsync(new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } + + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + var setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - var methodFees = new MethodFees + MethodName = "Test", + Fees = { - MethodName = "Test", - Fees = + new MethodFee { - new MethodFee - { - BasicFee = 100, - Symbol = "NOTEXIST" - } + BasicFee = 100, + Symbol = "ELF" } - }; - var setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found"); - methodFees.Fees[0].Symbol = "ELF"; - methodFees.Fees[0].BasicFee = -1; - setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount"); - } - - [Fact] - public async Task SetMethodFee_Test() + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + var methodFees = new MethodFees { - var testMethodName = "Test"; - var feeAmount = 100; - var methodFees = new MethodFees + MethodName = "Test", + Fees = { - MethodName = testMethodName, - Fees = + new MethodFee { - new MethodFee - { - BasicFee = feeAmount, - Symbol = "ELF" - } + BasicFee = 100, + Symbol = "NOTEXIST" } - }; - var methodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenHolderContractAddress, - methodFeeController.OwnerAddress, nameof(TokenHolderContractStub.SetMethodFee), methodFees); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - var getMethodFee = await TokenHolderContractStub.GetMethodFee.CallAsync(new StringValue + } + }; + var setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found"); + methodFees.Fees[0].Symbol = "ELF"; + methodFees.Fees[0].BasicFee = -1; + setMethodFeeRet = await TokenHolderContractStub.SetMethodFee.SendWithExceptionAsync(methodFees); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount"); + } + + [Fact] + public async Task SetMethodFee_Test() + { + var testMethodName = "Test"; + var feeAmount = 100; + var methodFees = new MethodFees + { + MethodName = testMethodName, + Fees = { - Value = testMethodName - }); - getMethodFee.Fees[0].BasicFee.ShouldBe(feeAmount); - } - + new MethodFee + { + BasicFee = feeAmount, + Symbol = "ELF" + } + } + }; + var methodFeeController = await TokenHolderContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenHolderContractAddress, + methodFeeController.OwnerAddress, nameof(TokenHolderContractStub.SetMethodFee), methodFees); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var getMethodFee = await TokenHolderContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = testMethodName + }); + getMethodFee.Fees[0].BasicFee.ShouldBe(feeAmount); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj b/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj index 119adb7137..c836859a07 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj +++ b/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj @@ -10,23 +10,23 @@ 0436 - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/test/AElf.Contracts.TokenHolder.Tests/DAppTests.cs b/test/AElf.Contracts.TokenHolder.Tests/DAppTests.cs index 7227544fd7..596a36da2f 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/DAppTests.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/DAppTests.cs @@ -1,149 +1,145 @@ using System.Threading.Tasks; -using AElf.Standards.ACS9; using AElf.Contracts.MultiToken; using AElf.Contracts.Profit; using AElf.Contracts.TestContract.DApp; +using AElf.Standards.ACS9; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; using Record = AElf.Contracts.TestContract.DApp.Record; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +// ReSharper disable HeuristicUnreachableCode +public partial class TokenHolderTests { - // ReSharper disable HeuristicUnreachableCode - public partial class TokenHolderTests + [Fact] + public async Task DAppTest() { - [Fact] - public async Task DAppTest() - { - // Prepare stubs. - var userTokenStub = - GetTester(TokenContractAddress, UserKeyPairs[0]); - var userTokenHolderStub = - GetTester(TokenHolderContractAddress, - UserKeyPairs[0]); + // Prepare stubs. + var userTokenStub = + GetTester(TokenContractAddress, UserKeyPairs[0]); + var userTokenHolderStub = + GetTester(TokenHolderContractAddress, + UserKeyPairs[0]); - await DAppContractStub.SignUp.SendAsync(new Empty()); + await DAppContractStub.SignUp.SendAsync(new Empty()); - // User has 10 APP tokens because of signing up. - (await GetFirstUserBalance("APP")).ShouldBe(10_00000000); + // User has 10 APP tokens because of signing up. + (await GetFirstUserBalance("APP")).ShouldBe(10_00000000); - var elfBalanceBefore = await GetFirstUserBalance("ELF"); + var elfBalanceBefore = await GetFirstUserBalance("ELF"); - // User has to Approve an amount of ELF tokens before deposit to the DApp. - await userTokenStub.Approve.SendAsync(new ApproveInput - { - Amount = 100_00000000, - Spender = DAppContractAddress, - Symbol = "ELF" - }); - await DAppContractStub.Deposit.SendAsync(new DepositInput - { - Amount = 100_00000000 - }); + // User has to Approve an amount of ELF tokens before deposit to the DApp. + await userTokenStub.Approve.SendAsync(new ApproveInput + { + Amount = 100_00000000, + Spender = DAppContractAddress, + Symbol = "ELF" + }); + await DAppContractStub.Deposit.SendAsync(new DepositInput + { + Amount = 100_00000000 + }); - // Check the change of balance of ELF. - var elfBalanceAfter = await GetFirstUserBalance("ELF"); - elfBalanceAfter.ShouldBe(elfBalanceBefore - 100_00000000); + // Check the change of balance of ELF. + var elfBalanceAfter = await GetFirstUserBalance("ELF"); + elfBalanceAfter.ShouldBe(elfBalanceBefore - 100_00000000); - // Now user has 110 APP tokens. - (await GetFirstUserBalance("APP")).ShouldBe(110_00000000); + // Now user has 110 APP tokens. + (await GetFirstUserBalance("APP")).ShouldBe(110_00000000); - // User lock some APP tokens for getting profits. (APP -57) - await userTokenHolderStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput - { - SchemeManager = DAppContractAddress, - Amount = 57_00000000 - }); + // User lock some APP tokens for getting profits. (APP -57) + await userTokenHolderStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + SchemeManager = DAppContractAddress, + Amount = 57_00000000 + }); - // User uses 10 times of this DApp. (APP -3) - for (var i = 0; i < 10; i++) - { - await DAppContractStub.Use.SendAsync(new Record()); - } + // User uses 10 times of this DApp. (APP -3) + for (var i = 0; i < 10; i++) await DAppContractStub.Use.SendAsync(new Record()); - // Now user has 50 APP tokens. - (await GetFirstUserBalance("APP")).ShouldBe(50_00000000); + // Now user has 50 APP tokens. + (await GetFirstUserBalance("APP")).ShouldBe(50_00000000); - const long baseBalance = (long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1); + const long baseBalance = (long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1); + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses[1], Symbol = "ELF" - }); - balance.Balance.ShouldBe(baseBalance); - } - - // Profits receiver claim 10 ELF profits. - await DAppContractStub.TakeContractProfits.SendAsync(new TakeContractProfitsInput - { - Symbol = "ELF", - Amount = 10_0000_0000 + Owner = UserAddresses[1], Symbol = "ELF" }); + balance.Balance.ShouldBe(baseBalance); + } + + // Profits receiver claim 10 ELF profits. + await DAppContractStub.TakeContractProfits.SendAsync(new TakeContractProfitsInput + { + Symbol = "ELF", + Amount = 10_0000_0000 + }); - // Then profits receiver should have 9.9 ELF tokens. + // Then profits receiver should have 9.9 ELF tokens. + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses[1], Symbol = "ELF" - }); - balance.Balance.ShouldBe(baseBalance + 9_9000_0000); - } - - // And Side Chain Dividends Pool should have 0.1 ELF tokens. + Owner = UserAddresses[1], Symbol = "ELF" + }); + balance.Balance.ShouldBe(baseBalance + 9_9000_0000); + } + + // And Side Chain Dividends Pool should have 0.1 ELF tokens. + { + var scheme = await TokenHolderContractStub.GetScheme.CallAsync(ConsensusContractAddress); + var virtualAddress = await ProfitContractStub.GetSchemeAddress.CallAsync(new SchemePeriod { - var scheme = await TokenHolderContractStub.GetScheme.CallAsync(ConsensusContractAddress); - var virtualAddress = await ProfitContractStub.GetSchemeAddress.CallAsync(new SchemePeriod - { - SchemeId = scheme.SchemeId, - Period = 0 - }); - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = virtualAddress, - Symbol = "ELF" - }); - balance.Balance.ShouldBe(1000_0000); - } - - // Help user to claim profits from token holder profit scheme. - await TokenHolderContractStub.ClaimProfits.SendAsync(new ClaimProfitsInput + SchemeId = scheme.SchemeId, + Period = 0 + }); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Beneficiary = UserAddresses[0], - SchemeManager = DAppContractAddress, + Owner = virtualAddress, + Symbol = "ELF" }); + balance.Balance.ShouldBe(1000_0000); + } - // Profits should be 1 ELF. - (await GetFirstUserBalance("ELF")).ShouldBe(elfBalanceAfter + 1_0000_0000); - - //withdraw - var beforeBalance = - await userTokenStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = "APP", - Owner = UserAddresses[0] - }); - var withDrawResult = await userTokenHolderStub.Withdraw.SendAsync(DAppContractAddress); - withDrawResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var resultBalance = await userTokenStub.GetBalance.CallAsync(new GetBalanceInput + // Help user to claim profits from token holder profit scheme. + await TokenHolderContractStub.ClaimProfits.SendAsync(new ClaimProfitsInput + { + Beneficiary = UserAddresses[0], + SchemeManager = DAppContractAddress + }); + + // Profits should be 1 ELF. + (await GetFirstUserBalance("ELF")).ShouldBe(elfBalanceAfter + 1_0000_0000); + + //withdraw + var beforeBalance = + await userTokenStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = "APP", Owner = UserAddresses[0] }); - resultBalance.Balance.ShouldBe(beforeBalance.Balance + 57_00000000); + var withDrawResult = await userTokenHolderStub.Withdraw.SendAsync(DAppContractAddress); + withDrawResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var resultBalance = await userTokenStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = "APP", + Owner = UserAddresses[0] + }); + resultBalance.Balance.ShouldBe(beforeBalance.Balance + 57_00000000); - var finalScheme = await userTokenHolderStub.GetScheme.CallAsync(DAppContractAddress); - } + var finalScheme = await userTokenHolderStub.GetScheme.CallAsync(DAppContractAddress); + } - private async Task GetFirstUserBalance(string symbol) + private async Task GetFirstUserBalance(string symbol) + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses[0], Symbol = symbol - }); - return balance.Balance; - } + Owner = UserAddresses[0], Symbol = symbol + }); + return balance.Balance; } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/DappSmartContractNameProvider.cs b/test/AElf.Contracts.TokenHolder.Tests/DappSmartContractNameProvider.cs index 2203cdf3dd..2cf4bd4812 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/DappSmartContractNameProvider.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/DappSmartContractNameProvider.cs @@ -3,13 +3,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public class DappSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class DappSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.DApp"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.ContractNames.DApp"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/GenesisContractDtoExtensions.cs b/test/AElf.Contracts.TokenHolder.Tests/GenesisContractDtoExtensions.cs index 5c524139ed..6481e5afb2 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/GenesisContractDtoExtensions.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/GenesisContractDtoExtensions.cs @@ -1,18 +1,19 @@ using AElf.Standards.ACS0; using Google.Protobuf; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class GenesisContractDtoExtensions { - public static class GenesisContractDtoExtensions + internal static void Add( + this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, + string methodName, + IMessage input) { - internal static void Add(this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, string methodName, - IMessage input) + systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall() - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/ResetBlockTimeProvider.cs b/test/AElf.Contracts.TokenHolder.Tests/ResetBlockTimeProvider.cs index c3ed1618ce..eb894ee727 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/ResetBlockTimeProvider.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/ResetBlockTimeProvider.cs @@ -1,10 +1,9 @@ using AElf.ContractTestKit; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public class ResetBlockTimeProvider : IResetBlockTimeProvider { - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => false; - public int StepMilliseconds => 0; - } + public bool Enabled => false; + public int StepMilliseconds => 0; } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestAElfModule.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestAElfModule.cs index 503ed49069..c9b59384cc 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestAElfModule.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestAElfModule.cs @@ -6,18 +6,17 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +[DependsOn(typeof(ContractTestModule))] +public class TokenHolderContractTestAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - public class TokenHolderContractTestAElfModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(); - context.Services.RemoveAll(); - context.Services.RemoveAll(); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.AddSingleton(); - } + context.Services.RemoveAll(); + context.Services.RemoveAll(); + context.Services.RemoveAll(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs index 4624baca35..075145cf73 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; @@ -17,295 +16,295 @@ using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; -using AElf.OS.Node.Application; +using AElf.Standards.ACS0; using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Volo.Abp.Threading; -using InitializeInput = AElf.Contracts.Parliament.InitializeInput; +using InitializeInput = AElf.Contracts.TestContract.DApp.InitializeInput; + +namespace AElf.Contracts.TokenHolder; -namespace AElf.Contracts.TokenHolder +public class TokenHolderContractTestBase : ContractTestBase { - public class TokenHolderContractTestBase : ContractTestBase - { - protected ECKeyPair StarterKeyPair => Accounts[0].KeyPair; - protected Address Starter => Accounts[0].Address; + protected ECKeyPair StarterKeyPair => Accounts[0].KeyPair; + protected Address Starter => Accounts[0].Address; - protected ECKeyPair ProfitReceiverKeyPair => Accounts[1].KeyPair; - protected Address Receiver => Accounts[1].Address; + protected ECKeyPair ProfitReceiverKeyPair => Accounts[1].KeyPair; + protected Address Receiver => Accounts[1].Address; - protected List UserKeyPairs => Accounts.Skip(2).Take(3).Select(a => a.KeyPair).ToList(); + protected List UserKeyPairs => Accounts.Skip(2).Take(3).Select(a => a.KeyPair).ToList(); - protected List
UserAddresses => - UserKeyPairs.Select(k => Address.FromPublicKey(k.PublicKey)).ToList(); + protected List
UserAddresses => + UserKeyPairs.Select(k => Address.FromPublicKey(k.PublicKey)).ToList(); - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(TokenHolderContractTestConstants.InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(TokenHolderContractTestConstants.InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); - protected Address TokenContractAddress { get; set; } - protected Address ProfitContractAddress { get; set; } - protected Address ParliamentContractAddress { get; set; } - protected Address TokenHolderContractAddress { get; set; } - protected Address DAppContractAddress { get; set; } - protected Address ConsensusContractAddress { get; set; } + protected Address TokenContractAddress { get; set; } + protected Address ProfitContractAddress { get; set; } + protected Address ParliamentContractAddress { get; set; } + protected Address TokenHolderContractAddress { get; set; } + protected Address DAppContractAddress { get; set; } + protected Address ConsensusContractAddress { get; set; } - internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub { get; set; } - internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStub { get; set; } - internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub { get; set; } + internal ProfitContractImplContainer.ProfitContractImplStub ProfitContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } - internal TokenHolderContractImplContainer.TokenHolderContractImplStub TokenHolderContractStub { get; set; } + internal TokenHolderContractImplContainer.TokenHolderContractImplStub TokenHolderContractStub { get; set; } - internal DAppContainer.DAppStub DAppContractStub { get; set; } + internal DAppContainer.DAppStub DAppContractStub { get; set; } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } - protected void InitializeContracts() - { - BasicContractZeroStub = GetContractZeroTester(StarterKeyPair); - - ProfitContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ProfitContract).Assembly.Location)), - Name = ProfitSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateProfitInitializationCallList() - })).Output; - ProfitContractStub = GetProfitContractTester(StarterKeyPair); - - //deploy token holder contract - TokenHolderContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenHolderContract).Assembly.Location)), - Name = TokenHolderSmartContractAddressNameProvider.Name, - TransactionMethodCallList = - new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList() - })).Output; - TokenHolderContractStub = GetTokenHolderContractTester(StarterKeyPair); - - //deploy token contract - TokenContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), - Name = TokenSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateTokenInitializationCallList() - })).Output; - TokenContractStub = GetTokenContractTester(StarterKeyPair); - - //deploy parliament auth contract - ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), - Name = ParliamentSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateParliamentInitializationCallList() - })).Output; - ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); - - ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), - Name = ConsensusSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateConsensusInitializationCallList() - })).Output; - AEDPoSContractStub = GetConsensusContractTester(StarterKeyPair); - - AsyncHelper.RunSync(AddDAppContractAddressToCreateTokenWhiteListAsync); - - //deploy DApp contract - DAppContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(DAppContract).Assembly.Location)), - Name = DappSmartContractAddressNameProvider.Name, - TransactionMethodCallList = - new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + protected void InitializeContracts() + { + BasicContractZeroStub = GetContractZeroTester(StarterKeyPair); + + ProfitContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ProfitContract).Assembly.Location)), + Name = ProfitSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateProfitInitializationCallList() + })).Output; + ProfitContractStub = GetProfitContractTester(StarterKeyPair); + + //deploy token holder contract + TokenHolderContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenHolderContract).Assembly.Location)), + Name = TokenHolderSmartContractAddressNameProvider.Name, + TransactionMethodCallList = + new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList() + })).Output; + TokenHolderContractStub = GetTokenHolderContractTester(StarterKeyPair); + + //deploy token contract + TokenContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), + Name = TokenSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateTokenInitializationCallList() + })).Output; + TokenContractStub = GetTokenContractTester(StarterKeyPair); + + //deploy parliament auth contract + ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), + Name = ParliamentSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateParliamentInitializationCallList() + })).Output; + ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); + + ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), + Name = ConsensusSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateConsensusInitializationCallList() + })).Output; + AEDPoSContractStub = GetConsensusContractTester(StarterKeyPair); + + AsyncHelper.RunSync(AddDAppContractAddressToCreateTokenWhiteListAsync); + + //deploy DApp contract + DAppContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(DAppContract).Assembly.Location)), + Name = DappSmartContractAddressNameProvider.Name, + TransactionMethodCallList = + new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + { + Value = { - Value = + new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - new SystemContractDeploymentInput.Types.SystemTransactionMethodCall + MethodName = nameof(DAppContractStub.InitializeForUnitTest), + Params = new InitializeInput { - MethodName = nameof(DAppContractStub.InitializeForUnitTest), - Params = new AElf.Contracts.TestContract.DApp.InitializeInput - { - ProfitReceiver = Address.FromPublicKey(UserKeyPairs[1].PublicKey) - }.ToByteString() - } + ProfitReceiver = Address.FromPublicKey(UserKeyPairs[1].PublicKey) + }.ToByteString() } } - })).Output; - DAppContractStub = GetTester(DAppContractAddress, - UserKeyPairs.First()); - } + } + })).Output; + DAppContractStub = GetTester(DAppContractAddress, + UserKeyPairs.First()); + } - private async Task AddDAppContractAddressToCreateTokenWhiteListAsync() - { - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultOrganization, nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), Address.FromBase58("BHN8oN7D8kWZL9YW3aqD3dct4F83zqAd3CgaBTWucUiNSakcp")); - await ApproveWithMinersAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - } + private async Task AddDAppContractAddressToCreateTokenWhiteListAsync() + { + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultOrganization, nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), + Address.FromBase58("BHN8oN7D8kWZL9YW3aqD3dct4F83zqAd3CgaBTWucUiNSakcp")); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + } - internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + internal BasicContractZeroImplContainer.BasicContractZeroImplStub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + internal TokenContractImplContainer.TokenContractImplStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) - { - return GetTester(ProfitContractAddress, keyPair); - } + internal ProfitContractImplContainer.ProfitContractImplStub GetProfitContractTester(ECKeyPair keyPair) + { + return GetTester(ProfitContractAddress, keyPair); + } - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( - ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, - keyPair); - } + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester( + ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } - internal TokenHolderContractImplContainer.TokenHolderContractImplStub GetTokenHolderContractTester( - ECKeyPair keyPair) - { - return GetTester(TokenHolderContractAddress, - keyPair); - } + internal TokenHolderContractImplContainer.TokenHolderContractImplStub GetTokenHolderContractTester( + ECKeyPair keyPair) + { + return GetTester(TokenHolderContractAddress, + keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateProfitInitializationCallList() - { - return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - } + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateProfitInitializationCallList() + { + return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateTokenInitializationCallList() + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateTokenInitializationCallList() + { + var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput { - var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + Symbol = TokenHolderContractTestConstants.NativeTokenSymbol, + Decimals = 8, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = TokenHolderContractTestConstants.NativeTokenTotalSupply, + Issuer = Starter, + LockWhiteList = { - Symbol = TokenHolderContractTestConstants.NativeTokenSymbol, - Decimals = 8, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = TokenHolderContractTestConstants.NativeTokenTotalSupply, - Issuer = Starter, - LockWhiteList = - { - ProfitContractAddress, - TokenHolderContractAddress - } - }); - tokenContractCallList.Add(nameof(TokenContract.SetPrimaryTokenSymbol), - new SetPrimaryTokenSymbolInput {Symbol = "ELF"}); - tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + ProfitContractAddress, + TokenHolderContractAddress + } + }); + tokenContractCallList.Add(nameof(TokenContract.SetPrimaryTokenSymbol), + new SetPrimaryTokenSymbolInput { Symbol = "ELF" }); + tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + { + Symbol = TokenHolderContractTestConstants.NativeTokenSymbol, + Amount = (long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.12), + To = Address.FromPublicKey(StarterKeyPair.PublicKey), + Memo = "Issue token to default user for vote." + }); + + UserKeyPairs.ForEach(creatorKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), + new IssueInput { Symbol = TokenHolderContractTestConstants.NativeTokenSymbol, - Amount = (long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.12), - To = Address.FromPublicKey(StarterKeyPair.PublicKey), - Memo = "Issue token to default user for vote.", - }); + Amount = (long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1), + To = Address.FromPublicKey(creatorKeyPair.PublicKey), + Memo = "set voters few amount for voting." + })); - UserKeyPairs.ForEach(creatorKeyPair => tokenContractCallList.Add(nameof(TokenContract.Issue), - new IssueInput - { - Symbol = TokenHolderContractTestConstants.NativeTokenSymbol, - Amount = (long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1), - To = Address.FromPublicKey(creatorKeyPair.PublicKey), - Memo = "set voters few amount for voting." - })); - - return tokenContractCallList; - } + return tokenContractCallList; + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateParliamentInitializationCallList() + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateParliamentInitializationCallList() + { + var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new Parliament.InitializeInput { - var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - parliamentContractCallList.Add(nameof(ParliamentContractStub.Initialize), new InitializeInput + PrivilegedProposer = Starter, + ProposerAuthorityRequired = true + }); + + return parliamentContractCallList; + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateConsensusInitializationCallList() + { + var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput { - PrivilegedProposer = Starter, - ProposerAuthorityRequired = true + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000, + IsSideChain = true }); - return parliamentContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateConsensusInitializationCallList() + consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList { - var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000, - IsSideChain = true - }); - - consensusContractCallList.Add(nameof(AEDPoSContractStub.FirstRound), new MinerList - { - Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); + Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); - return consensusContractCallList; - } + return consensusContractCallList; + } - protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + protected async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; - } + return proposalId; + } - protected async Task ApproveWithMinersAsync(Hash proposalId) + protected async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestConstants.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestConstants.cs index 1d997d171f..a94c55c64f 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestConstants.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public static class TokenHolderContractTestConstants { - public static class TokenHolderContractTestConstants - { - public const string NativeTokenSymbol = "ELF"; - public const long NativeTokenTotalSupply = 1_000_000_000_00000000; - public const int InitialCoreDataCenterCount = 5; - } + public const string NativeTokenSymbol = "ELF"; + public const long NativeTokenTotalSupply = 1_000_000_000_00000000; + public const int InitialCoreDataCenterCount = 5; } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs index 892168e49f..959bc2cb56 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs @@ -1,531 +1,522 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; -using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.CSharp.Core; -using AElf.CSharp.Core.Extension; -using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.Types; -using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; // ReSharper disable HeuristicUnreachableCode -namespace AElf.Contracts.TokenHolder +namespace AElf.Contracts.TokenHolder; + +public partial class TokenHolderTests : TokenHolderContractTestBase { - public partial class TokenHolderTests : TokenHolderContractTestBase + public TokenHolderTests() + { + InitializeContracts(); + } + + [Fact] + public async Task CheckTokenHolderProfitScheme() + { + var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = DAppContractAddress + }); + schemeIds.SchemeIds.Count.ShouldBePositive(); + var schemeId = schemeIds.SchemeIds.First(); + var scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); + scheme.Manager.ShouldBe(DAppContractAddress); + } + + [Fact] + public async Task CreateTokenHolderProfitSchemeTest() { - public TokenHolderTests() + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput { - InitializeContracts(); + Symbol = "APP" + }); + + { + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + tokenHolderProfitScheme.Period.ShouldBe(0); + tokenHolderProfitScheme.Symbol.ShouldBe("APP"); + tokenHolderProfitScheme.SchemeId.ShouldBeNull(); } - [Fact] - public async Task CheckTokenHolderProfitScheme() + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput { - var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = DAppContractAddress - }); - schemeIds.SchemeIds.Count.ShouldBePositive(); - var schemeId = schemeIds.SchemeIds.First(); - var scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); - scheme.Manager.ShouldBe(DAppContractAddress); + SchemeManager = Starter, + Symbol = "ELF", + Amount = 1 + }); + + { + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + tokenHolderProfitScheme.SchemeId.ShouldNotBeNull(); } + } + + [Fact] + public async Task ContributeProfitsTest() + { + await CreateTokenHolderProfitSchemeTest(); + + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - [Fact] - public async Task CreateTokenHolderProfitSchemeTest() { - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = "APP" - }); + var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); + originScheme.Manager.ShouldBe(Starter); + originScheme.CurrentPeriod.ShouldBe(1); + originScheme.TotalShares.ShouldBe(0); + var generalLedgerBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - tokenHolderProfitScheme.Period.ShouldBe(0); - tokenHolderProfitScheme.Symbol.ShouldBe("APP"); - tokenHolderProfitScheme.SchemeId.ShouldBeNull(); - } + Owner = originScheme.VirtualAddress, + Symbol = "ELF" + })).Balance; + generalLedgerBalance.ShouldBe(1); + } - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Symbol = "ELF", - Amount = 1 - }); + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeManager = Starter, + Symbol = "ELF", + Amount = 9999 + }); + { + var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); + var generalLedgerBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - tokenHolderProfitScheme.SchemeId.ShouldNotBeNull(); - } + Owner = originScheme.VirtualAddress, + Symbol = "ELF" + })).Balance; + generalLedgerBalance.ShouldBe(10000); } + } - [Fact] - public async Task ContributeProfitsTest() - { - await CreateTokenHolderProfitSchemeTest(); + [Fact] + public async Task AddBeneficiaryTest() + { + await ContributeProfitsTest(); - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - { - var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); - originScheme.Manager.ShouldBe(Starter); - originScheme.CurrentPeriod.ShouldBe(1); - originScheme.TotalShares.ShouldBe(0); - - var generalLedgerBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = originScheme.VirtualAddress, - Symbol = "ELF" - })).Balance; - generalLedgerBalance.ShouldBe(1); - } - - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Symbol = "ELF", - Amount = 9999 - }); + await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput + { + Beneficiary = UserAddresses.First(), + Shares = 1 + }); - { - var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); - var generalLedgerBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = originScheme.VirtualAddress, - Symbol = "ELF" - })).Balance; - generalLedgerBalance.ShouldBe(10000); - } + { + var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); + originScheme.TotalShares.ShouldBe(1); } + } - [Fact] - public async Task AddBeneficiaryTest() + [Fact] + public async Task AddBeneficiary_Repeatedly_Test() + { + await AddBeneficiaryTest(); + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + var newShare = 2; + await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput { - await ContributeProfitsTest(); - - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + Beneficiary = UserAddresses.First(), + Shares = newShare + }); - await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput - { - Beneficiary = UserAddresses.First(), - Shares = 1 - }); - - { - var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); - originScheme.TotalShares.ShouldBe(1); - } - } - - [Fact] - public async Task AddBeneficiary_Repeatedly_Test() { - await AddBeneficiaryTest(); - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - var newShare = 2; - await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput - { - Beneficiary = UserAddresses.First(), - Shares = newShare - }); - - { - var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); - originScheme.TotalShares.ShouldBe(newShare); - } + var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); + originScheme.TotalShares.ShouldBe(newShare); } - - [Fact] - public async Task RemoveBeneficiaryTest() + } + + [Fact] + public async Task RemoveBeneficiaryTest() + { + await AddBeneficiaryTest(); + + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + + await TokenHolderContractStub.RemoveBeneficiary.SendAsync(new RemoveTokenHolderBeneficiaryInput { - await AddBeneficiaryTest(); - - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + Beneficiary = UserAddresses.First() + }); - await TokenHolderContractStub.RemoveBeneficiary.SendAsync(new RemoveTokenHolderBeneficiaryInput - { - Beneficiary = UserAddresses.First() - }); - - { - var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); - originScheme.TotalShares.ShouldBe(0); - } - } - - [Fact] - public async Task RemoveBeneficiary_With_Amount_Test() { - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = "ELF" - }); - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Symbol = "ELF", - Amount = 9999 - }); - await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput - { - Beneficiary = Starter, - Shares = 1000 - }); - var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = Starter - }); - var schemeId = schemeIds.SchemeIds[0]; - var beforeRemoveScheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); - var amount = 10; - await TokenHolderContractStub.RemoveBeneficiary.SendAsync(new RemoveTokenHolderBeneficiaryInput - { - Beneficiary = Starter, - Amount = amount - }); - var afterRemoveScheme = await ProfitContractStub.GetScheme.CallAsync(schemeIds.SchemeIds[0]); - afterRemoveScheme.TotalShares.ShouldBe(beforeRemoveScheme.TotalShares - amount); - var profitAmount = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - Beneficiary = Starter, - SchemeId = schemeId - }); - profitAmount.Details.Count.ShouldBe(2); - profitAmount.Details[0].Shares.ShouldBe(beforeRemoveScheme.TotalShares); - profitAmount.Details[0].EndPeriod.ShouldBe(0); - profitAmount.Details[1].Shares.ShouldBe(beforeRemoveScheme.TotalShares - amount); + var originScheme = await ProfitContractStub.GetScheme.CallAsync(tokenHolderProfitScheme.SchemeId); + originScheme.TotalShares.ShouldBe(0); } + } - [Fact] - public async Task DistributeProfits_ClaimWithProfitContract() + [Fact] + public async Task RemoveBeneficiary_With_Amount_Test() + { + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + { + Symbol = "ELF" + }); + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeManager = Starter, + Symbol = "ELF", + Amount = 9999 + }); + await TokenHolderContractStub.AddBeneficiary.SendAsync(new AddTokenHolderBeneficiaryInput + { + Beneficiary = Starter, + Shares = 1000 + }); + var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput { - await AddBeneficiaryTest(); + Manager = Starter + }); + var schemeId = schemeIds.SchemeIds[0]; + var beforeRemoveScheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); + var amount = 10; + await TokenHolderContractStub.RemoveBeneficiary.SendAsync(new RemoveTokenHolderBeneficiaryInput + { + Beneficiary = Starter, + Amount = amount + }); + var afterRemoveScheme = await ProfitContractStub.GetScheme.CallAsync(schemeIds.SchemeIds[0]); + afterRemoveScheme.TotalShares.ShouldBe(beforeRemoveScheme.TotalShares - amount); + var profitAmount = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + Beneficiary = Starter, + SchemeId = schemeId + }); + profitAmount.Details.Count.ShouldBe(2); + profitAmount.Details[0].Shares.ShouldBe(beforeRemoveScheme.TotalShares); + profitAmount.Details[0].EndPeriod.ShouldBe(0); + profitAmount.Details[1].Shares.ShouldBe(beforeRemoveScheme.TotalShares - amount); + } - var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + [Fact] + public async Task DistributeProfits_ClaimWithProfitContract() + { + await AddBeneficiaryTest(); - await TokenHolderContractStub.DistributeProfits.SendAsync(new DistributeProfitsInput - { - SchemeManager = Starter, - AmountsMap = {{"ELF", 0L}} - }); + var tokenHolderProfitScheme = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses.First(), - Symbol = "ELF" - })).Balance; - balance.ShouldBe((long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1)); - } + await TokenHolderContractStub.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeManager = Starter, + AmountsMap = { { "ELF", 0L } } + }); - var userProfitStub = - GetTester(ProfitContractAddress, UserKeyPairs.First()); - await userProfitStub.ClaimProfits.SendAsync(new Profit.ClaimProfitsInput - { - SchemeId = tokenHolderProfitScheme.SchemeId, - }); - + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses.First(), - Symbol = "ELF" - })).Balance; - balance.ShouldBe((long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1) + 10000); - } + Owner = UserAddresses.First(), + Symbol = "ELF" + })).Balance; + balance.ShouldBe((long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1)); } - - [Fact] - public async Task DistributeProfits_ClaimWithTokenHolderContract() + + var userProfitStub = + GetTester(ProfitContractAddress, UserKeyPairs.First()); + await userProfitStub.ClaimProfits.SendAsync(new Profit.ClaimProfitsInput { - await AddBeneficiaryTest(); + SchemeId = tokenHolderProfitScheme.SchemeId + }); - await TokenHolderContractStub.DistributeProfits.SendAsync(new DistributeProfitsInput + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - SchemeManager = Starter, - AmountsMap = {{"ELF", 0L}} - }); + Owner = UserAddresses.First(), + Symbol = "ELF" + })).Balance; + balance.ShouldBe((long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1) + 10000); + } + } - { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses.First(), - Symbol = "ELF" - })).Balance; - balance.ShouldBe((long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1)); - } + [Fact] + public async Task DistributeProfits_ClaimWithTokenHolderContract() + { + await AddBeneficiaryTest(); - var userTokenHolderStub = - GetTester(TokenHolderContractAddress, UserKeyPairs.First()); - await userTokenHolderStub.ClaimProfits.SendAsync(new ClaimProfitsInput - { - SchemeManager = Starter, - }); - + await TokenHolderContractStub.DistributeProfits.SendAsync(new DistributeProfitsInput + { + SchemeManager = Starter, + AmountsMap = { { "ELF", 0L } } + }); + + { + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = UserAddresses.First(), - Symbol = "ELF" - })).Balance; - balance.ShouldBe((long) (TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1) + 10000); - } + Owner = UserAddresses.First(), + Symbol = "ELF" + })).Balance; + balance.ShouldBe((long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1)); } - [Fact] - public async Task AddBeneficiary_With_Invalid_Scheme() + var userTokenHolderStub = + GetTester(TokenHolderContractAddress, + UserKeyPairs.First()); + await userTokenHolderStub.ClaimProfits.SendAsync(new ClaimProfitsInput { - var ret = await TokenHolderContractStub.AddBeneficiary.SendWithExceptionAsync( - new AddTokenHolderBeneficiaryInput - { - Beneficiary = new Address(), - Shares = 100 - }); - ret.TransactionResult.Error.ShouldContain("token holder profit scheme not found"); - } - - [Fact] - public async Task DistributeProfits_Without_Authority_Test() + SchemeManager = Starter + }); + { - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - Symbol = "Test" - }); - var senderWithoutAuthority = - GetTester(TokenHolderContractAddress, - UserKeyPairs.First()); - var distributeRet = await senderWithoutAuthority.DistributeProfits.SendWithExceptionAsync( - new DistributeProfitsInput - { - SchemeManager = Starter - }); - distributeRet.TransactionResult.Error.ShouldContain("No permission to distribute profits"); + Owner = UserAddresses.First(), + Symbol = "ELF" + })).Balance; + balance.ShouldBe((long)(TokenHolderContractTestConstants.NativeTokenTotalSupply * 0.1) + 10000); } + } - [Fact] - public async Task RegisterForProfits_Repeatedly_Test() - { - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + [Fact] + public async Task AddBeneficiary_With_Invalid_Scheme() + { + var ret = await TokenHolderContractStub.AddBeneficiary.SendWithExceptionAsync( + new AddTokenHolderBeneficiaryInput { - Symbol = "ELF", - AutoDistributeThreshold = { {"ELF", 1000}} + Beneficiary = new Address(), + Shares = 100 }); - await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + ret.TransactionResult.Error.ShouldContain("token holder profit scheme not found"); + } + + [Fact] + public async Task DistributeProfits_Without_Authority_Test() + { + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + { + Symbol = "Test" + }); + var senderWithoutAuthority = + GetTester(TokenHolderContractAddress, + UserKeyPairs.First()); + var distributeRet = await senderWithoutAuthority.DistributeProfits.SendWithExceptionAsync( + new DistributeProfitsInput { - Amount = 10, SchemeManager = Starter }); - var repeatRegisterRet = await TokenHolderContractStub.RegisterForProfits.SendWithExceptionAsync( - new RegisterForProfitsInput - { - Amount = 10, - SchemeManager = Starter - }); - repeatRegisterRet.TransactionResult.Error.ShouldContain("Already registered."); - } + distributeRet.TransactionResult.Error.ShouldContain("No permission to distribute profits"); + } - [Fact] - public async Task RegisterForProfits_Without_Auto_Distribute_Test() + [Fact] + public async Task RegisterForProfits_Repeatedly_Test() + { + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput { - var amount = 10; - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = "ELF", - AutoDistributeThreshold = {{"ELF", 1000}} - }); - await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + Symbol = "ELF", + AutoDistributeThreshold = { { "ELF", 1000 } } + }); + await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + Amount = 10, + SchemeManager = Starter + }); + var repeatRegisterRet = await TokenHolderContractStub.RegisterForProfits.SendWithExceptionAsync( + new RegisterForProfitsInput { - Amount = amount, + Amount = 10, SchemeManager = Starter }); - var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = Starter - }); - var schemeId = schemeIds.SchemeIds.First(); + repeatRegisterRet.TransactionResult.Error.ShouldContain("Already registered."); + } - var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput - { - SchemeId = schemeId, - Beneficiary = Starter - }); - profitDetail.Details.Count.ShouldBe(1); - profitDetail.Details[0].Shares.ShouldBe(amount); - var schemeInfo = await ProfitContractStub.GetScheme.CallAsync(schemeId); - schemeInfo.TotalShares.ShouldBe(amount); + [Fact] + public async Task RegisterForProfits_Without_Auto_Distribute_Test() + { + var amount = 10; + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + { + Symbol = "ELF", + AutoDistributeThreshold = { { "ELF", 1000 } } + }); + await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + Amount = amount, + SchemeManager = Starter + }); + var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = Starter + }); + var schemeId = schemeIds.SchemeIds.First(); - } - - [Fact] - public async Task RegisterForProfits_With_Auto_Distribute_Test() - { - var amount = 1000L; - var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; - var tokenA = "JUN"; - await StarterCreateIssueAndApproveTokenAsync(tokenA, 1000000L, 100000L); - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = nativeTokenSymbol, - AutoDistributeThreshold = - { - {nativeTokenSymbol, amount}, - {tokenA, amount} - } - }); - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Amount = amount, - Symbol = nativeTokenSymbol - }); - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Amount = amount, - Symbol = tokenA - }); - var beforeLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = nativeTokenSymbol, - Owner = Starter - })).Balance; - await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput - { - Amount = amount, - SchemeManager = Starter - }); - var afterLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = nativeTokenSymbol, - Owner = Starter - })).Balance; - beforeLockBalance.ShouldBe(afterLockBalance.Add(amount)); - var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput - { - Manager = Starter - }); - var schemeId = schemeIds.SchemeIds.First(); - var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new Profit.ClaimProfitsInput - { - Beneficiary = Starter, - SchemeId = schemeId - }); - profitMap.Value.Count.ShouldBe(2); - profitMap.Value.ContainsKey(nativeTokenSymbol).ShouldBeTrue(); - profitMap.Value[nativeTokenSymbol].ShouldBe(amount); - var schemeInfoInProfit = await ProfitContractStub.GetScheme.CallAsync(schemeId); - var schemeInfoInTokenHolder = await TokenHolderContractStub.GetScheme.CallAsync(Starter); - schemeInfoInProfit.CurrentPeriod.ShouldBe(2); - schemeInfoInTokenHolder.Period.ShouldBe(2); - } + var profitDetail = await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput + { + SchemeId = schemeId, + Beneficiary = Starter + }); + profitDetail.Details.Count.ShouldBe(1); + profitDetail.Details[0].Shares.ShouldBe(amount); + var schemeInfo = await ProfitContractStub.GetScheme.CallAsync(schemeId); + schemeInfo.TotalShares.ShouldBe(amount); + } - [Fact] - public async Task Withdraw_With_Invalid_Lock_Id_Test() + [Fact] + public async Task RegisterForProfits_With_Auto_Distribute_Test() + { + var amount = 1000L; + var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; + var tokenA = "JUN"; + await StarterCreateIssueAndApproveTokenAsync(tokenA, 1000000L, 100000L); + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput { - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + Symbol = nativeTokenSymbol, + AutoDistributeThreshold = { - Symbol = "TEST", - }); + { nativeTokenSymbol, amount }, + { tokenA, amount } + } + }); + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeManager = Starter, + Amount = amount, + Symbol = nativeTokenSymbol + }); + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeManager = Starter, + Amount = amount, + Symbol = tokenA + }); + var beforeLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = nativeTokenSymbol, + Owner = Starter + })).Balance; + await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + Amount = amount, + SchemeManager = Starter + }); + var afterLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = nativeTokenSymbol, + Owner = Starter + })).Balance; + beforeLockBalance.ShouldBe(afterLockBalance.Add(amount)); + var schemeIds = await ProfitContractStub.GetManagingSchemeIds.CallAsync(new GetManagingSchemeIdsInput + { + Manager = Starter + }); + var schemeId = schemeIds.SchemeIds.First(); + var profitMap = await ProfitContractStub.GetProfitsMap.CallAsync(new Profit.ClaimProfitsInput + { + Beneficiary = Starter, + SchemeId = schemeId + }); + profitMap.Value.Count.ShouldBe(2); + profitMap.Value.ContainsKey(nativeTokenSymbol).ShouldBeTrue(); + profitMap.Value[nativeTokenSymbol].ShouldBe(amount); + var schemeInfoInProfit = await ProfitContractStub.GetScheme.CallAsync(schemeId); + var schemeInfoInTokenHolder = await TokenHolderContractStub.GetScheme.CallAsync(Starter); + schemeInfoInProfit.CurrentPeriod.ShouldBe(2); + schemeInfoInTokenHolder.Period.ShouldBe(2); + } - var withDrawRet = await TokenHolderContractStub.Withdraw.SendWithExceptionAsync(Starter); - withDrawRet.TransactionResult.Error.ShouldContain("Sender didn't register for profits."); - } - - [Fact] - public async Task Withdraw_Test() + [Fact] + public async Task Withdraw_With_Invalid_Lock_Id_Test() + { + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput { - var amount = 1000L; - var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = nativeTokenSymbol, - }); - await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput - { - Amount = amount, - SchemeManager = Starter - }); - var beforeUnLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = nativeTokenSymbol, - Owner = Starter - })).Balance; - await TokenHolderContractStub.Withdraw.SendAsync(Starter); - var afterUnLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = nativeTokenSymbol, - Owner = Starter - })).Balance; - afterUnLockBalance.ShouldBe(beforeUnLockBalance.Add(amount)); - } + Symbol = "TEST" + }); - [Fact] - public async Task GetProfitsMap_Test() + var withDrawRet = await TokenHolderContractStub.Withdraw.SendWithExceptionAsync(Starter); + withDrawRet.TransactionResult.Error.ShouldContain("Sender didn't register for profits."); + } + + [Fact] + public async Task Withdraw_Test() + { + var amount = 1000L; + var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput { - var amount = 1000L; - var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; - var tokenA = "AUG"; - await StarterCreateIssueAndApproveTokenAsync(tokenA, 1000000L, 100000L); - await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput - { - Symbol = nativeTokenSymbol, - AutoDistributeThreshold = - { - {nativeTokenSymbol, amount}, - {tokenA, amount} - } - }); - await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput - { - SchemeManager = Starter, - Amount = amount, - Symbol = nativeTokenSymbol - }); - await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput - { - Amount = amount, - SchemeManager = Starter - }); - var profitMap = await TokenHolderContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput + Symbol = nativeTokenSymbol + }); + await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + Amount = amount, + SchemeManager = Starter + }); + var beforeUnLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = nativeTokenSymbol, + Owner = Starter + })).Balance; + await TokenHolderContractStub.Withdraw.SendAsync(Starter); + var afterUnLockBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = nativeTokenSymbol, + Owner = Starter + })).Balance; + afterUnLockBalance.ShouldBe(beforeUnLockBalance.Add(amount)); + } + + [Fact] + public async Task GetProfitsMap_Test() + { + var amount = 1000L; + var nativeTokenSymbol = TokenHolderContractTestConstants.NativeTokenSymbol; + var tokenA = "AUG"; + await StarterCreateIssueAndApproveTokenAsync(tokenA, 1000000L, 100000L); + await TokenHolderContractStub.CreateScheme.SendAsync(new CreateTokenHolderProfitSchemeInput + { + Symbol = nativeTokenSymbol, + AutoDistributeThreshold = { - Beneficiary = Starter, - SchemeManager = Starter - }); - profitMap.Value.Count.ShouldBe(1); - profitMap.Value.ContainsKey(nativeTokenSymbol).ShouldBeTrue(); - profitMap.Value[nativeTokenSymbol].ShouldBe(amount); - } + { nativeTokenSymbol, amount }, + { tokenA, amount } + } + }); + await TokenHolderContractStub.ContributeProfits.SendAsync(new ContributeProfitsInput + { + SchemeManager = Starter, + Amount = amount, + Symbol = nativeTokenSymbol + }); + await TokenHolderContractStub.RegisterForProfits.SendAsync(new RegisterForProfitsInput + { + Amount = amount, + SchemeManager = Starter + }); + var profitMap = await TokenHolderContractStub.GetProfitsMap.CallAsync(new ClaimProfitsInput + { + Beneficiary = Starter, + SchemeManager = Starter + }); + profitMap.Value.Count.ShouldBe(1); + profitMap.Value.ContainsKey(nativeTokenSymbol).ShouldBeTrue(); + profitMap.Value[nativeTokenSymbol].ShouldBe(amount); + } - private async Task StarterCreateIssueAndApproveTokenAsync(string symbol, long totalSupply, long issueAmount) + private async Task StarterCreateIssueAndApproveTokenAsync(string symbol, long totalSupply, long issueAmount) + { + await TokenContractStub.Create.SendAsync(new CreateInput { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - TokenName = symbol + " name", - TotalSupply = totalSupply, - Issuer = Starter, - LockWhiteList = { ProfitContractAddress} - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Amount = issueAmount, - Symbol = symbol, - To = Starter - }); - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Amount = issueAmount, - Symbol = symbol, - Spender = TokenHolderContractAddress, - }); - } + Symbol = symbol, + TokenName = symbol + " name", + TotalSupply = totalSupply, + Issuer = Starter, + LockWhiteList = { ProfitContractAddress } + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = issueAmount, + Symbol = symbol, + To = Starter + }); + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Amount = issueAmount, + Symbol = symbol, + Spender = TokenHolderContractAddress + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenHolder.Tests/Types/MineList.cs b/test/AElf.Contracts.TokenHolder.Tests/Types/MineList.cs index 4db3af4d4e..ed9c3082b5 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/Types/MineList.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/Types/MineList.cs @@ -1,49 +1,44 @@ using System.Linq; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj index 7573f8907c..16ae83d0ea 100644 --- a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj +++ b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/AElf.Contracts.Vote.AEDPoSExtension.Tests.csproj @@ -7,16 +7,16 @@ - - - - - - + + + + + + - - + + diff --git a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestAElfModule.cs b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestAElfModule.cs index 69ec0efbb2..e939df5561 100644 --- a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestAElfModule.cs +++ b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestAElfModule.cs @@ -3,15 +3,14 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Contract.Vote +namespace AElf.Contract.Vote; + +[DependsOn(typeof(ContractTestAEDPoSExtensionModule))] +public class VoteContractTestAElfModule : ContractTestAEDPoSExtensionModule { - [DependsOn(typeof(ContractTestAEDPoSExtensionModule))] - public class VoteContractTestAElfModule : ContractTestAEDPoSExtensionModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAssemblyOf(); - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - } + context.Services.AddAssemblyOf(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestBase.cs b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestBase.cs index cc9e12a9ce..b0b8a5f292 100644 --- a/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestBase.cs +++ b/test/AElf.Contracts.Vote.AEDPoSExtension.Tests/VoteContractTestBase.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; -using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; using AElf.GovernmentSystem; using AElf.Kernel.Consensus; @@ -9,30 +8,28 @@ using AElf.Types; using Volo.Abp.Threading; -namespace AElf.Contract.Vote +namespace AElf.Contract.Vote; + +// ReSharper disable once InconsistentNaming +public class VoteContractTestBase : AEDPoSExtensionTestBase { - // ReSharper disable once InconsistentNaming - public class VoteContractTestBase : AEDPoSExtensionTestBase + public VoteContractTestBase() { - internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => - GetTester( - ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - internal TokenContractContainer.TokenContractStub TokenStub => - GetTester( - ContractAddresses[TokenSmartContractAddressNameProvider.Name], - Accounts[0].KeyPair); - - - public VoteContractTestBase() + ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List { - ContractAddresses = AsyncHelper.RunSync(() => DeploySystemSmartContracts(new List - { - ConsensusSmartContractAddressNameProvider.Name, - VoteSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name - })); - } + ConsensusSmartContractAddressNameProvider.Name, + VoteSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name + })); } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub ConsensusStub => + GetTester( + ContractAddresses[ConsensusSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); + + internal TokenContractContainer.TokenContractStub TokenStub => + GetTester( + ContractAddresses[TokenSmartContractAddressNameProvider.Name], + Accounts[0].KeyPair); } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj b/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj index 28aa86e9a9..760ae8ed2b 100644 --- a/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj +++ b/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj @@ -9,22 +9,22 @@ 0436 - - - - - - + + + + + + - - - - - - - + + + + + + + diff --git a/test/AElf.Contracts.Vote.Tests/BVT/ACS1ImplTest.cs b/test/AElf.Contracts.Vote.Tests/BVT/ACS1ImplTest.cs index cca6eecfb0..0b6f414744 100644 --- a/test/AElf.Contracts.Vote.Tests/BVT/ACS1ImplTest.cs +++ b/test/AElf.Contracts.Vote.Tests/BVT/ACS1ImplTest.cs @@ -1,244 +1,241 @@ using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Parliament; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests { - public partial class VoteTests + [Fact] + public async Task ChangeMethodFeeController_Test() { - [Fact] - public async Task ChangeMethodFeeController_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - - var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); - var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - - const string proposalCreationMethodName = nameof(VoteContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(VoteContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress + ProposalReleaseThreshold = new ProposalReleaseThreshold + { + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 + } }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var newMethodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); - newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); - } - - [Fact] - public async Task ChangeMethodFeeController_WithoutAuth_Test() - { - var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); - const string proposalCreationMethodName = nameof(VoteContractStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(VoteContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo - { - OwnerAddress = DefaultSender, - ContractAddress = ParliamentContractAddress - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input."); - } + var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + methodFeeController.OwnerAddress.ShouldBe(defaultOrganization); - [Fact] - public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() - { - var createOrganizationResult = - await ParliamentContractStub.CreateOrganization.SendAsync( - new CreateOrganizationInput - { - ProposalReleaseThreshold = new ProposalReleaseThreshold - { - MinimalApprovalThreshold = 1000, - MinimalVoteThreshold = 1000 - } - }); - var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); - var result = await VoteContractStub.ChangeMethodFeeController.SendWithExceptionAsync( - new AuthorityInfo - { - OwnerAddress = organizationAddress, - ContractAddress = ParliamentContractAddress - }); + const string proposalCreationMethodName = nameof(VoteContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(VoteContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); - } + var newMethodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); + newMethodFeeController.OwnerAddress.ShouldBe(organizationAddress); + } - [Fact] - public async Task SetMethodFee_With_Invalid_Input_Test() - { - // Invalid amount + [Fact] + public async Task ChangeMethodFeeController_WithoutAuth_Test() + { + var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); + const string proposalCreationMethodName = nameof(VoteContractStub.ChangeMethodFeeController); + var proposalId = await CreateProposalAsync(VoteContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { - var setMethodFeeRet = await VoteContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + OwnerAddress = DefaultSender, + ContractAddress = ParliamentContractAddress + }); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldContain("Invalid authority input."); + } + + [Fact] + public async Task ChangeMethodFeeController_With_Invalid_Organization_Test() + { + var createOrganizationResult = + await ParliamentContractStub.CreateOrganization.SendAsync( + new CreateOrganizationInput { - MethodName = "Test", - Fees = + ProposalReleaseThreshold = new ProposalReleaseThreshold { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = -111 - } + MinimalApprovalThreshold = 1000, + MinimalVoteThreshold = 1000 } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); - } + var organizationAddress = Address.Parser.ParseFrom(createOrganizationResult.TransactionResult.ReturnValue); + var result = await VoteContractStub.ChangeMethodFeeController.SendWithExceptionAsync( + new AuthorityInfo + { + OwnerAddress = organizationAddress, + ContractAddress = ParliamentContractAddress + }); + + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.Contains("Unauthorized behavior.").ShouldBeTrue(); + } - // token does not exist + [Fact] + public async Task SetMethodFee_With_Invalid_Input_Test() + { + // Invalid amount + { + var setMethodFeeRet = await VoteContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - var setMethodFeeRet = await VoteContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees + MethodName = "Test", + Fees = { - MethodName = "Test", - Fees = + new MethodFee { - new MethodFee - { - Symbol = "NOTEXIST", - BasicFee = 111 - } + Symbol = "NOTEXIST", + BasicFee = -111 } - }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); - } + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Invalid amount."); } - [Fact] - public async Task SetMethodFee_Without_Authority_Test() + // token does not exist { - var tokenSymbol = TestTokenSymbol; - var methodName = "Test"; - var basicFee = 111; var setMethodFeeRet = await VoteContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - MethodName = methodName, + MethodName = "Test", Fees = { new MethodFee { - Symbol = tokenSymbol, - BasicFee = basicFee + Symbol = "NOTEXIST", + BasicFee = 111 } } }); - setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Token is not found."); } + } - [Fact] - public async Task SetMethodFee_Success_Test() + [Fact] + public async Task SetMethodFee_Without_Authority_Test() + { + var tokenSymbol = TestTokenSymbol; + var methodName = "Test"; + var basicFee = 111; + var setMethodFeeRet = await VoteContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { - var tokenSymbol = TestTokenSymbol; - var methodName = "Test"; - var basicFee = 111; - var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); - const string proposalCreationMethodName = nameof(VoteContractStub.SetMethodFee); - var proposalId = await CreateProposalAsync(VoteContractAddress, - methodFeeController.OwnerAddress, proposalCreationMethodName, new MethodFees + MethodName = methodName, + Fees = + { + new MethodFee + { + Symbol = tokenSymbol, + BasicFee = basicFee + } + } + }); + setMethodFeeRet.TransactionResult.Error.ShouldContain("Unauthorized to set method fee."); + } + + [Fact] + public async Task SetMethodFee_Success_Test() + { + var tokenSymbol = TestTokenSymbol; + var methodName = "Test"; + var basicFee = 111; + var methodFeeController = await VoteContractStub.GetMethodFeeController.CallAsync(new Empty()); + const string proposalCreationMethodName = nameof(VoteContractStub.SetMethodFee); + var proposalId = await CreateProposalAsync(VoteContractAddress, + methodFeeController.OwnerAddress, proposalCreationMethodName, new MethodFees + { + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = + new MethodFee { - new MethodFee - { - Symbol = tokenSymbol, - BasicFee = basicFee - } + Symbol = tokenSymbol, + BasicFee = basicFee } - }); - await ApproveWithMinersAsync(proposalId); - var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName + } }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); - } + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue + { + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(tokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(basicFee); + } - private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, - string methodName, IMessage input) + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput { - var proposal = new CreateProposalInput - { - OrganizationAddress = organizationAddress, - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contractAddress - }; + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalId = createResult.Output; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; - return proposalId; - } + return proposalId; + } - [Theory] - [InlineData(false, "Register", 10_00000000)] - [InlineData(true, "Vote", 0)] - [InlineData(true, "AddOption", 0)] - public async Task GetMethodFee_Test(bool isDefault, string methodName, long fee) + [Theory] + [InlineData(false, "Register", 10_00000000)] + [InlineData(true, "Vote", 0)] + [InlineData(true, "AddOption", 0)] + public async Task GetMethodFee_Test(bool isDefault, string methodName, long fee) + { + if (!isDefault) { - if (!isDefault) + var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue { - var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName - }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(TestTokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(fee); - } - else + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(TestTokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(fee); + } + else + { + var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue { - var getMethodFee = await VoteContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = methodName - }); - getMethodFee.Fees.Count.ShouldBe(1); - getMethodFee.Fees[0].Symbol.ShouldBe(TestTokenSymbol); - getMethodFee.Fees[0].BasicFee.ShouldBe(VoteContractConstant.DefaultMethodFee); - } - + Value = methodName + }); + getMethodFee.Fees.Count.ShouldBe(1); + getMethodFee.Fees[0].Symbol.ShouldBe(TestTokenSymbol); + getMethodFee.Fees[0].BasicFee.ShouldBe(VoteContractConstant.DefaultMethodFee); } + } - private async Task ApproveWithMinersAsync(Hash proposalId) + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - var approveResult = await tester.Approve.SendAsync(proposalId); - approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); - } + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs index 77e9a18788..a4b112bf30 100644 --- a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs +++ b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs @@ -9,657 +9,656 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests { - public partial class VoteTests + [Fact] + public async Task VoteContract_Register_Test() { - [Fact] - public async Task VoteContract_Register_Test() + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 10); + + // Check voting item according to the input. + (votingItem.EndTimestamp.ToDateTime() - votingItem.StartTimestamp.ToDateTime()).TotalDays.ShouldBe(10); + votingItem.Options.Count.ShouldBe(4); + votingItem.Sponsor.ShouldBe(DefaultSender); + votingItem.TotalSnapshotNumber.ShouldBe(10); + + // Check more about voting item. + votingItem.CurrentSnapshotNumber.ShouldBe(1); + votingItem.CurrentSnapshotStartTimestamp.ShouldBe(votingItem.StartTimestamp); + votingItem.RegisterTimestamp.ShouldBeGreaterThan(votingItem + .StartTimestamp); // RegisterTimestamp should be a bit later. + + // Check voting result of first period initialized. + var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput { - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 10); - - // Check voting item according to the input. - (votingItem.EndTimestamp.ToDateTime() - votingItem.StartTimestamp.ToDateTime()).TotalDays.ShouldBe(10); - votingItem.Options.Count.ShouldBe(4); - votingItem.Sponsor.ShouldBe(DefaultSender); - votingItem.TotalSnapshotNumber.ShouldBe(10); - - // Check more about voting item. - votingItem.CurrentSnapshotNumber.ShouldBe(1); - votingItem.CurrentSnapshotStartTimestamp.ShouldBe(votingItem.StartTimestamp); - votingItem.RegisterTimestamp.ShouldBeGreaterThan(votingItem - .StartTimestamp); // RegisterTimestamp should be a bit later. + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 1 + }); + votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); + votingResult.SnapshotNumber.ShouldBe(1); + votingResult.SnapshotStartTimestamp.ShouldBe(votingItem.StartTimestamp); + votingResult.SnapshotEndTimestamp.ShouldBe(null); + votingResult.Results.Count.ShouldBe(0); + votingResult.VotersCount.ShouldBe(0); + } - // Check voting result of first period initialized. - var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 1 - }); - votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); - votingResult.SnapshotNumber.ShouldBe(1); - votingResult.SnapshotStartTimestamp.ShouldBe(votingItem.StartTimestamp); - votingResult.SnapshotEndTimestamp.ShouldBe(null); - votingResult.Results.Count.ShouldBe(0); - votingResult.VotersCount.ShouldBe(0); - } + [Fact] + public async Task Register_With_Invalid_Timestamp() + { + var endTime = TimestampHelper.GetUtcNow(); + var input = new VotingRegisterInput + { + TotalSnapshotNumber = 0, + EndTimestamp = endTime, + StartTimestamp = endTime.AddDays(1), + Options = { GenerateOptions() }, + AcceptedCurrency = TestTokenSymbol, + IsLockToken = true + }; + var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(input)).TransactionResult; + transactionResult.Error.ShouldContain("Invalid active time."); + } - [Fact] - public async Task Register_With_Invalid_Timestamp() + [Fact] + public async Task Register_With_Zero_Total_Snapshot_Test() + { + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 0); + votingItem.CurrentSnapshotNumber.ShouldBe(1); + var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput { - var endTime = TimestampHelper.GetUtcNow(); - var input = new VotingRegisterInput - { - TotalSnapshotNumber = 0, - EndTimestamp = endTime, - StartTimestamp = endTime.AddDays(1), - Options = {GenerateOptions(1)}, - AcceptedCurrency = TestTokenSymbol, - IsLockToken = true - }; - var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(input)).TransactionResult; - transactionResult.Error.ShouldContain("Invalid active time."); - } + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 1 + }); + votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); + votingResult.SnapshotNumber.ShouldBe(1); + } - [Fact] - public async Task Register_With_Zero_Total_Snapshot_Test() + [Fact] + public async Task VoteContract_Vote_Test() + { + //voting item not exist { - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 0); - votingItem.CurrentSnapshotNumber.ShouldBe(1); - var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 1 - }); - votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); - votingResult.SnapshotNumber.ShouldBe(1); + var transactionResult = + await VoteWithException(DefaultSenderKeyPair, HashHelper.ComputeFrom("hash"), string.Empty, 100); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_Vote_Test() + //voting item have been out of date { - //voting item not exist - { - var transactionResult = - await VoteWithException(DefaultSenderKeyPair, HashHelper.ComputeFrom("hash"), string.Empty, 100); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); - } - - //voting item have been out of date - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - await TakeSnapshot(registerItem.VotingItemId, 1); - - var voter = Accounts[11].KeyPair; - var voteResult = - await VoteWithException(voter, registerItem.VotingItemId, registerItem.Options[0], 100); - voteResult.Status.ShouldBe(TransactionResultStatus.Failed); - voteResult.Error.Contains("Current voting item already ended").ShouldBeTrue(); - } - - //vote without enough token - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voter = Accounts[31].KeyPair; - var voteResult = - await VoteWithException(voter, registerItem.VotingItemId, registerItem.Options[0], 100); - voteResult.Status.ShouldBe(TransactionResultStatus.Failed); - } - - //vote option length is over the limit 1024 - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voter = Accounts[11].KeyPair; - var option = new StringBuilder(); - option.Append('a', VoteContractConstant.OptionLengthLimit + 1); - var voteResult = await VoteWithException(voter, registerItem.VotingItemId, option.ToString(), 100); - voteResult.Status.ShouldBe(TransactionResultStatus.Failed); - voteResult.Error.Contains("Invalid input.").ShouldBeTrue(); - } + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + await TakeSnapshot(registerItem.VotingItemId, 1); - //vote option not exist - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voter = Accounts[11].KeyPair; - var option = Accounts[3].Address.ToBase58(); - var voteResult = await VoteWithException(voter, registerItem.VotingItemId, option, 100); - voteResult.Status.ShouldBe(TransactionResultStatus.Failed); - voteResult.Error.Contains($"Option {option} not found").ShouldBeTrue(); - } + var voter = Accounts[11].KeyPair; + var voteResult = + await VoteWithException(voter, registerItem.VotingItemId, registerItem.Options[0], 100); + voteResult.Status.ShouldBe(TransactionResultStatus.Failed); + voteResult.Error.Contains("Current voting item already ended").ShouldBeTrue(); } - [Fact] - public async Task Vote_Sender_Test() + //vote without enough token { - var votingItem = await RegisterVotingItemAsync(10, 4, false, DefaultSender, 10); - var otherVoter = GetVoteContractTester(Accounts[11].KeyPair); - var voteRet = await otherVoter.Vote.SendWithExceptionAsync(new VoteInput - { - VotingItemId = votingItem.VotingItemId, - Amount = 100, - Option = votingItem.Options[1] - }); - voteRet.TransactionResult.Error.ShouldContain("Sender of delegated voting event must be the Sponsor."); + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voter = Accounts[31].KeyPair; + var voteResult = + await VoteWithException(voter, registerItem.VotingItemId, registerItem.Options[0], 100); + voteResult.Status.ShouldBe(TransactionResultStatus.Failed); } - [Fact] - public async Task Vote_Success() + //vote option length is over the limit 1024 { var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voteItemId = registerItem.VotingItemId; - var voter = Accounts[11]; - var voteAmount = 100; - var beforeVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = TestTokenSymbol, - Owner = voter.Address - }); - var transactionResult = await Vote(voter.KeyPair, voteItemId, registerItem.Options[1], voteAmount); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var voteResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - SnapshotNumber = 1, - VotingItemId = voteItemId - }); - voteResult.Results[registerItem.Options[1]].ShouldBe(voteAmount); - voteResult.VotesAmount.ShouldBe(voteAmount); - voteResult.VotersCount.ShouldBe(1); - var afterVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = TestTokenSymbol, - Owner = voter.Address - }); - beforeVoteBalance.Balance.Sub(afterVoteBalance.Balance).ShouldBe(voteAmount); - var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voter.Address); - voteItems.VotedItemVoteIds.Count.ShouldBe(1); + var voter = Accounts[11].KeyPair; + var option = new StringBuilder(); + option.Append('a', VoteContractConstant.OptionLengthLimit + 1); + var voteResult = await VoteWithException(voter, registerItem.VotingItemId, option.ToString(), 100); + voteResult.Status.ShouldBe(TransactionResultStatus.Failed); + voteResult.Error.Contains("Invalid input.").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_Withdraw_Fail_Test() + //vote option not exist { - //const long txFee = 1_00000000; - //without vote - { - var withdrawResult = - await WithdrawWithException(Accounts[1].KeyPair, HashHelper.ComputeFrom("hash1")); - withdrawResult.Status.ShouldBe(TransactionResultStatus.Failed); - withdrawResult.Error.Contains("Voting record not found").ShouldBeTrue(); - } - - //Within lock token withdraw with other person - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - - var voteUser = Accounts[1].KeyPair; - var voteAddress = Accounts[1].Address; - var withdrawUser = Accounts[2].KeyPair; - - await Vote(voteUser, registerItem.VotingItemId, registerItem.Options[1], 100); - await TakeSnapshot(registerItem.VotingItemId, 1); - - var voteIds = await GetVoteIds(voteUser, registerItem.VotingItemId); - var beforeBalance = GetUserBalance(voteAddress); - - var transactionResult = await WithdrawWithException(withdrawUser, voteIds.ActiveVotes.First()); + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voter = Accounts[11].KeyPair; + var option = Accounts[3].Address.ToBase58(); + var voteResult = await VoteWithException(voter, registerItem.VotingItemId, option, 100); + voteResult.Status.ShouldBe(TransactionResultStatus.Failed); + voteResult.Error.Contains($"Option {option} not found").ShouldBeTrue(); + } + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("No permission to withdraw votes of others"); + [Fact] + public async Task Vote_Sender_Test() + { + var votingItem = await RegisterVotingItemAsync(10, 4, false, DefaultSender, 10); + var otherVoter = GetVoteContractTester(Accounts[11].KeyPair); + var voteRet = await otherVoter.Vote.SendWithExceptionAsync(new VoteInput + { + VotingItemId = votingItem.VotingItemId, + Amount = 100, + Option = votingItem.Options[1] + }); + voteRet.TransactionResult.Error.ShouldContain("Sender of delegated voting event must be the Sponsor."); + } - var afterBalance = GetUserBalance(voteAddress); - beforeBalance.ShouldBe(afterBalance); // Stay same - } + [Fact] + public async Task Vote_Success() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voteItemId = registerItem.VotingItemId; + var voter = Accounts[11]; + var voteAmount = 100; + var beforeVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = TestTokenSymbol, + Owner = voter.Address + }); + var transactionResult = await Vote(voter.KeyPair, voteItemId, registerItem.Options[1], voteAmount); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var voteResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput + { + SnapshotNumber = 1, + VotingItemId = voteItemId + }); + voteResult.Results[registerItem.Options[1]].ShouldBe(voteAmount); + voteResult.VotesAmount.ShouldBe(voteAmount); + voteResult.VotersCount.ShouldBe(1); + var afterVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = TestTokenSymbol, + Owner = voter.Address + }); + beforeVoteBalance.Balance.Sub(afterVoteBalance.Balance).ShouldBe(voteAmount); + var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voter.Address); + voteItems.VotedItemVoteIds.Count.ShouldBe(1); + } - //Without lock token and withdrawn by other person - { - var registerItem = await RegisterVotingItemAsync(100, 3, false, DefaultSender, 1); - var withdrawUser = Accounts[2]; - var voteId = HashHelper.ComputeFrom("hash"); - await VoteContractStub.Vote.SendAsync(new VoteInput - { - VotingItemId = registerItem.VotingItemId, - Voter = withdrawUser.Address, - VoteId = voteId, - Option = registerItem.Options[1], - Amount = 100 - }); - await TakeSnapshot(registerItem.VotingItemId, 1); - var voteIds = await GetVoteIds(withdrawUser.KeyPair, registerItem.VotingItemId); - var transactionResult = await WithdrawWithException(withdrawUser.KeyPair, voteIds.ActiveVotes.First()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("No permission to withdraw votes of others"); - } + [Fact] + public async Task VoteContract_Withdraw_Fail_Test() + { + //const long txFee = 1_00000000; + //without vote + { + var withdrawResult = + await WithdrawWithException(Accounts[1].KeyPair, HashHelper.ComputeFrom("hash1")); + withdrawResult.Status.ShouldBe(TransactionResultStatus.Failed); + withdrawResult.Error.Contains("Voting record not found").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_Withdraw_Success_Test() + //Within lock token withdraw with other person { var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); var voteUser = Accounts[1].KeyPair; var voteAddress = Accounts[1].Address; - var voteItemId = registerItem.VotingItemId; - var voteAmount = 100; - await Vote(voteUser, voteItemId, registerItem.Options[1], voteAmount); - var voteIds = await GetVoteIds(voteUser, voteItemId); - var currentVoteId = voteIds.ActiveVotes.First(); - var voteRecordBeforeWithdraw = await VoteContractStub.GetVotingRecord.CallAsync(currentVoteId); - voteRecordBeforeWithdraw.IsWithdrawn.ShouldBe(false); - var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voteAddress); - voteItems.VotedItemVoteIds[voteItemId.ToHex()].ActiveVotes.Count.ShouldBe(1); - voteItems.VotedItemVoteIds[voteItemId.ToHex()].WithdrawnVotes.Count.ShouldBe(0); - var voteResultBeforeWithdraw = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - SnapshotNumber = 1, - VotingItemId = voteItemId - }); - await TakeSnapshot(voteItemId, 1); + var withdrawUser = Accounts[2].KeyPair; + await Vote(voteUser, registerItem.VotingItemId, registerItem.Options[1], 100); + await TakeSnapshot(registerItem.VotingItemId, 1); + var voteIds = await GetVoteIds(voteUser, registerItem.VotingItemId); var beforeBalance = GetUserBalance(voteAddress); - var transactionResult = await Withdraw(voteUser, currentVoteId); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - voteItems = await VoteContractStub.GetVotedItems.CallAsync(voteAddress); - voteItems.VotedItemVoteIds[voteItemId.ToHex()].ActiveVotes.Count.ShouldBe(0); - voteItems.VotedItemVoteIds[voteItemId.ToHex()].WithdrawnVotes.Count.ShouldBe(1); - var voteRecordAfterWithdraw = await VoteContractStub.GetVotingRecord.CallAsync(currentVoteId); - voteRecordAfterWithdraw.IsWithdrawn.ShouldBe(true); - var voteResultAfterWithdraw = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - SnapshotNumber = 1, - VotingItemId = voteItemId - }); - voteResultBeforeWithdraw.VotesAmount.Sub(voteResultAfterWithdraw.VotesAmount).ShouldBe(voteAmount); - voteResultBeforeWithdraw.Results[registerItem.Options[1]] - .Sub(voteResultAfterWithdraw.Results[registerItem.Options[1]]).ShouldBe(voteAmount); - voteResultBeforeWithdraw.VotersCount.Sub(1).ShouldBe(voteResultAfterWithdraw.VotersCount); + + var transactionResult = await WithdrawWithException(withdrawUser, voteIds.ActiveVotes.First()); + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("No permission to withdraw votes of others"); + var afterBalance = GetUserBalance(voteAddress); - beforeBalance.ShouldBe(afterBalance - 100); + beforeBalance.ShouldBe(afterBalance); // Stay same } - [Fact] - public async Task VoteContract_AddOption_Fail_Test() + //Without lock token and withdrawn by other person { - //vote item does not exist - { - var voteItemId = HashHelper.ComputeFrom("hash"); - var otherUser = Accounts[10].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).AddOption.SendWithExceptionAsync( - new AddOptionInput - { - Option = Accounts[0].Address.ToBase58(), - VotingItemId = voteItemId - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Voting item not found.").ShouldBeTrue(); - } - //add without permission + var registerItem = await RegisterVotingItemAsync(100, 3, false, DefaultSender, 1); + var withdrawUser = Accounts[2]; + var voteId = HashHelper.ComputeFrom("hash"); + await VoteContractStub.Vote.SendAsync(new VoteInput { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var otherUser = Accounts[10].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).AddOption.SendWithExceptionAsync( - new AddOptionInput - { - Option = Accounts[0].Address.ToBase58(), - VotingItemId = registerItem.VotingItemId - })).TransactionResult; + VotingItemId = registerItem.VotingItemId, + Voter = withdrawUser.Address, + VoteId = voteId, + Option = registerItem.Options[1], + Amount = 100 + }); + await TakeSnapshot(registerItem.VotingItemId, 1); + var voteIds = await GetVoteIds(withdrawUser.KeyPair, registerItem.VotingItemId); + var transactionResult = await WithdrawWithException(withdrawUser.KeyPair, voteIds.ActiveVotes.First()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("No permission to withdraw votes of others"); + } + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); - } + [Fact] + public async Task VoteContract_Withdraw_Success_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + + var voteUser = Accounts[1].KeyPair; + var voteAddress = Accounts[1].Address; + var voteItemId = registerItem.VotingItemId; + var voteAmount = 100; + await Vote(voteUser, voteItemId, registerItem.Options[1], voteAmount); + var voteIds = await GetVoteIds(voteUser, voteItemId); + var currentVoteId = voteIds.ActiveVotes.First(); + var voteRecordBeforeWithdraw = await VoteContractStub.GetVotingRecord.CallAsync(currentVoteId); + voteRecordBeforeWithdraw.IsWithdrawn.ShouldBe(false); + var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voteAddress); + voteItems.VotedItemVoteIds[voteItemId.ToHex()].ActiveVotes.Count.ShouldBe(1); + voteItems.VotedItemVoteIds[voteItemId.ToHex()].WithdrawnVotes.Count.ShouldBe(0); + var voteResultBeforeWithdraw = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput + { + SnapshotNumber = 1, + VotingItemId = voteItemId + }); + await TakeSnapshot(voteItemId, 1); + + + var beforeBalance = GetUserBalance(voteAddress); + var transactionResult = await Withdraw(voteUser, currentVoteId); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + voteItems = await VoteContractStub.GetVotedItems.CallAsync(voteAddress); + voteItems.VotedItemVoteIds[voteItemId.ToHex()].ActiveVotes.Count.ShouldBe(0); + voteItems.VotedItemVoteIds[voteItemId.ToHex()].WithdrawnVotes.Count.ShouldBe(1); + var voteRecordAfterWithdraw = await VoteContractStub.GetVotingRecord.CallAsync(currentVoteId); + voteRecordAfterWithdraw.IsWithdrawn.ShouldBe(true); + var voteResultAfterWithdraw = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput + { + SnapshotNumber = 1, + VotingItemId = voteItemId + }); + voteResultBeforeWithdraw.VotesAmount.Sub(voteResultAfterWithdraw.VotesAmount).ShouldBe(voteAmount); + voteResultBeforeWithdraw.Results[registerItem.Options[1]] + .Sub(voteResultAfterWithdraw.Results[registerItem.Options[1]]).ShouldBe(voteAmount); + voteResultBeforeWithdraw.VotersCount.Sub(1).ShouldBe(voteResultAfterWithdraw.VotersCount); + var afterBalance = GetUserBalance(voteAddress); + beforeBalance.ShouldBe(afterBalance - 100); + } - //add duplicate option - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput + [Fact] + public async Task VoteContract_AddOption_Fail_Test() + { + //vote item does not exist + { + var voteItemId = HashHelper.ComputeFrom("hash"); + var otherUser = Accounts[10].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).AddOption.SendWithExceptionAsync( + new AddOptionInput { - Option = registerItem.Options[0], - VotingItemId = registerItem.VotingItemId + Option = Accounts[0].Address.ToBase58(), + VotingItemId = voteItemId })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Option already exists").ShouldBeTrue(); - } - - // option length exceed 1024 - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var newOption = new StringBuilder().Append('a', VoteContractConstant.OptionLengthLimit + 1); - var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Voting item not found.").ShouldBeTrue(); + } + //add without permission + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var otherUser = Accounts[10].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).AddOption.SendWithExceptionAsync( + new AddOptionInput { - Option = newOption.ToString(), + Option = Accounts[0].Address.ToBase58(), VotingItemId = registerItem.VotingItemId })).TransactionResult; - transactionResult.Error.ShouldContain("Invalid input."); - } - // option count exceed 64 - { - var registerItem = await RegisterVotingItemAsync(100, VoteContractConstant.MaximumOptionsCount, true, - DefaultSender, 1); - var newOption = Accounts[VoteContractConstant.MaximumOptionsCount].Address.ToBase58(); - var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput - { - Option = newOption, - VotingItemId = registerItem.VotingItemId - })).TransactionResult; - transactionResult.Error.ShouldContain( - $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_AddOption_Success_Test() + //add duplicate option { var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var address = Accounts[3].Address.ToBase58(); - var transactionResult = (await VoteContractStub.AddOption.SendAsync(new AddOptionInput + var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput { - Option = address, + Option = registerItem.Options[0], VotingItemId = registerItem.VotingItemId })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var votingItem = await GetVoteItem(registerItem.VotingItemId); - votingItem.Options.Count.ShouldBe(4); - votingItem.Options.Contains(address).ShouldBeTrue(); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Option already exists").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_RemoveOption_Fail_Test() + // option length exceed 1024 { - //voteItem does not exist + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var newOption = new StringBuilder().Append('a', VoteContractConstant.OptionLengthLimit + 1); + var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput { - var voteItemId = HashHelper.ComputeFrom("hash"); - var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( - new RemoveOptionInput - { - Option = Accounts[3].Address.ToBase58(), - VotingItemId = voteItemId - })).TransactionResult; + Option = newOption.ToString(), + VotingItemId = registerItem.VotingItemId + })).TransactionResult; + transactionResult.Error.ShouldContain("Invalid input."); + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Voting item not found."); - } - //remove without permission + // option count exceed 64 + { + var registerItem = await RegisterVotingItemAsync(100, VoteContractConstant.MaximumOptionsCount, true, + DefaultSender, 1); + var newOption = Accounts[VoteContractConstant.MaximumOptionsCount].Address.ToBase58(); + var transactionResult = (await VoteContractStub.AddOption.SendWithExceptionAsync(new AddOptionInput { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var otherUser = Accounts[10].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).RemoveOption.SendWithExceptionAsync( - new RemoveOptionInput - { - Option = registerItem.Options[0], - VotingItemId = registerItem.VotingItemId - })).TransactionResult; + Option = newOption, + VotingItemId = registerItem.VotingItemId + })).TransactionResult; + transactionResult.Error.ShouldContain( + $"The count of options can't greater than {VoteContractConstants.MaximumOptionsCount}"); + } + } - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); - } + [Fact] + public async Task VoteContract_AddOption_Success_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var address = Accounts[3].Address.ToBase58(); + var transactionResult = (await VoteContractStub.AddOption.SendAsync(new AddOptionInput + { + Option = address, + VotingItemId = registerItem.VotingItemId + })).TransactionResult; - //remove not exist one - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( - new RemoveOptionInput - { - Option = Accounts[3].Address.ToBase58(), - VotingItemId = registerItem.VotingItemId - })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Option doesn't exist").ShouldBeTrue(); - } + var votingItem = await GetVoteItem(registerItem.VotingItemId); + votingItem.Options.Count.ShouldBe(4); + votingItem.Options.Contains(address).ShouldBeTrue(); + } - //option length exceed 1024 - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var invalidOption = new StringBuilder().Append('a', VoteContractConstant.OptionLengthLimit + 1); - var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( - new RemoveOptionInput - { - Option = invalidOption.ToString(), - VotingItemId = registerItem.VotingItemId - })).TransactionResult; + [Fact] + public async Task VoteContract_RemoveOption_Fail_Test() + { + //voteItem does not exist + { + var voteItemId = HashHelper.ComputeFrom("hash"); + var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( + new RemoveOptionInput + { + Option = Accounts[3].Address.ToBase58(), + VotingItemId = voteItemId + })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Invalid input.").ShouldBeTrue(); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Voting item not found."); } - - [Fact] - public async Task VoteContract_RemoveOption_Success_Test() + //remove without permission { var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var removeOption = registerItem.Options[0]; - var transactionResult = (await VoteContractStub.RemoveOption.SendAsync(new RemoveOptionInput - { - Option = removeOption, - VotingItemId = registerItem.VotingItemId - })).TransactionResult; + var otherUser = Accounts[10].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).RemoveOption.SendWithExceptionAsync( + new RemoveOptionInput + { + Option = registerItem.Options[0], + VotingItemId = registerItem.VotingItemId + })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); + } - var votingItem = await GetVoteItem(registerItem.VotingItemId); - votingItem.Options.Count.ShouldBe(2); - votingItem.Options.Contains(removeOption).ShouldBeFalse(); + //remove not exist one + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( + new RemoveOptionInput + { + Option = Accounts[3].Address.ToBase58(), + VotingItemId = registerItem.VotingItemId + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Option doesn't exist").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_AddOptions_Test() + //option length exceed 1024 { - //without permission - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var otherUser = Accounts[10].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).AddOptions.SendWithExceptionAsync( - new AddOptionsInput - { - VotingItemId = registerItem.VotingItemId, - Options = - { - Accounts[0].Address.ToBase58(), - Accounts[1].Address.ToBase58() - } - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); - } - //voteItem does not exist - { - var itemId = HashHelper.ComputeFrom("hash"); - var transactionResult = (await VoteContractStub.AddOptions.SendWithExceptionAsync(new AddOptionsInput + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var invalidOption = new StringBuilder().Append('a', VoteContractConstant.OptionLengthLimit + 1); + var transactionResult = (await VoteContractStub.RemoveOption.SendWithExceptionAsync( + new RemoveOptionInput { - VotingItemId = itemId, - Options = - { - Accounts[0].Address.ToBase58(), - } + Option = invalidOption.ToString(), + VotingItemId = registerItem.VotingItemId })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Voting item not found.").ShouldBeTrue(); - } - //success - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var transactionResult = (await VoteContractStub.AddOptions.SendAsync(new AddOptionsInput + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Invalid input.").ShouldBeTrue(); + } + } + + [Fact] + public async Task VoteContract_RemoveOption_Success_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var removeOption = registerItem.Options[0]; + var transactionResult = (await VoteContractStub.RemoveOption.SendAsync(new RemoveOptionInput + { + Option = removeOption, + VotingItemId = registerItem.VotingItemId + })).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var votingItem = await GetVoteItem(registerItem.VotingItemId); + votingItem.Options.Count.ShouldBe(2); + votingItem.Options.Contains(removeOption).ShouldBeFalse(); + } + + [Fact] + public async Task VoteContract_AddOptions_Test() + { + //without permission + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var otherUser = Accounts[10].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).AddOptions.SendWithExceptionAsync( + new AddOptionsInput { VotingItemId = registerItem.VotingItemId, Options = { - Accounts[3].Address.ToBase58(), - Accounts[4].Address.ToBase58() + Accounts[0].Address.ToBase58(), + Accounts[1].Address.ToBase58() } })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var votingItem = await GetVoteItem(registerItem.VotingItemId); - votingItem.Options.Count.ShouldBe(5); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); } - - [Fact] - public async Task VoteContract_RemoveOptions_Fail_Test() + //voteItem does not exist { - //voteItem does not exist + var itemId = HashHelper.ComputeFrom("hash"); + var transactionResult = (await VoteContractStub.AddOptions.SendWithExceptionAsync(new AddOptionsInput { - var voteItemId = HashHelper.ComputeFrom("hash"); - var transactionResult = (await VoteContractStub.RemoveOptions.SendWithExceptionAsync( - new RemoveOptionsInput - { - VotingItemId = voteItemId, - Options = - { - Accounts[0].Address.ToBase58() - } - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Voting item not found."); - } - //without permission - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var otherUser = Accounts[10].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).RemoveOptions.SendWithExceptionAsync( - new RemoveOptionsInput - { - VotingItemId = registerItem.VotingItemId, - Options = - { - registerItem.Options[0], - registerItem.Options[1] - } - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); - } - //with some of not exist - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var transactionResult = (await VoteContractStub.RemoveOptions.SendWithExceptionAsync( - new RemoveOptionsInput - { - VotingItemId = registerItem.VotingItemId, - Options = - { - registerItem.Options[0], - Accounts[0].Address.ToBase58() - } - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Option doesn't exist").ShouldBeTrue(); - } - } + VotingItemId = itemId, + Options = + { + Accounts[0].Address.ToBase58() + } + })).TransactionResult; - [Fact] - public async Task VoteContract_RemoveOptions_Success_Test() + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Voting item not found.").ShouldBeTrue(); + } + //success { var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var transactionResult = (await VoteContractStub.RemoveOptions.SendAsync(new RemoveOptionsInput + var transactionResult = (await VoteContractStub.AddOptions.SendAsync(new AddOptionsInput { VotingItemId = registerItem.VotingItemId, Options = { - registerItem.Options[0], - registerItem.Options[1] + Accounts[3].Address.ToBase58(), + Accounts[4].Address.ToBase58() } })).TransactionResult; transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var votingItem = await GetVoteItem(registerItem.VotingItemId); - votingItem.Options.Count.ShouldBe(1); + votingItem.Options.Count.ShouldBe(5); } + } - [Fact] - public async Task VoteContract_VotesAndGetVotedItems_Test() + [Fact] + public async Task VoteContract_RemoveOptions_Fail_Test() + { + //voteItem does not exist { - var voteUser = Accounts[2].KeyPair; - var votingItem = await RegisterVotingItemAsync(10, 3, true, DefaultSender, 2); + var voteItemId = HashHelper.ComputeFrom("hash"); + var transactionResult = (await VoteContractStub.RemoveOptions.SendWithExceptionAsync( + new RemoveOptionsInput + { + VotingItemId = voteItemId, + Options = + { + Accounts[0].Address.ToBase58() + } + })).TransactionResult; - await Vote(voteUser, votingItem.VotingItemId, votingItem.Options.First(), 1000L); - var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 1 - }); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Voting item not found."); + } + //without permission + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var otherUser = Accounts[10].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).RemoveOptions.SendWithExceptionAsync( + new RemoveOptionsInput + { + VotingItemId = registerItem.VotingItemId, + Options = + { + registerItem.Options[0], + registerItem.Options[1] + } + })).TransactionResult; - votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); - votingResult.VotersCount.ShouldBe(1); - votingResult.Results.Values.First().ShouldBe(1000L); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Only sponsor can update options").ShouldBeTrue(); + } + //with some of not exist + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var transactionResult = (await VoteContractStub.RemoveOptions.SendWithExceptionAsync( + new RemoveOptionsInput + { + VotingItemId = registerItem.VotingItemId, + Options = + { + registerItem.Options[0], + Accounts[0].Address.ToBase58() + } + })).TransactionResult; - await Vote(voteUser, votingItem.VotingItemId, votingItem.Options.Last(), 500L); - var votedResult = await GetVotedItems(Address.FromPublicKey(voteUser.PublicKey)); - votedResult.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].ActiveVotes.Count.ShouldBe(2); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Option doesn't exist").ShouldBeTrue(); } + } - [Fact] - public async Task VoteContract_GetLatestVotingResult_Test() + [Fact] + public async Task VoteContract_RemoveOptions_Success_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var transactionResult = (await VoteContractStub.RemoveOptions.SendAsync(new RemoveOptionsInput { - var voteUser1 = Accounts[2].KeyPair; - var voteUser2 = Accounts[3].KeyPair; - var votingItem = await RegisterVotingItemAsync(10, 3, true, DefaultSender, 2); + VotingItemId = registerItem.VotingItemId, + Options = + { + registerItem.Options[0], + registerItem.Options[1] + } + })).TransactionResult; - await Vote(voteUser1, votingItem.VotingItemId, votingItem.Options.First(), 100L); - await Vote(voteUser1, votingItem.VotingItemId, votingItem.Options.First(), 200L); - var votingResult = await GetLatestVotingResult(votingItem.VotingItemId); - votingResult.VotersCount.ShouldBe(2); - votingResult.VotesAmount.ShouldBe(300L); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await Vote(voteUser2, votingItem.VotingItemId, votingItem.Options.Last(), 100L); - await Vote(voteUser2, votingItem.VotingItemId, votingItem.Options.Last(), 200L); - votingResult = await GetLatestVotingResult(votingItem.VotingItemId); - votingResult.VotersCount.ShouldBe(4); - votingResult.VotesAmount.ShouldBe(600L); - } + var votingItem = await GetVoteItem(registerItem.VotingItemId); + votingItem.Options.Count.ShouldBe(1); + } + + [Fact] + public async Task VoteContract_VotesAndGetVotedItems_Test() + { + var voteUser = Accounts[2].KeyPair; + var votingItem = await RegisterVotingItemAsync(10, 3, true, DefaultSender, 2); - [Fact] - public async Task VoteContract_GetVotedItems_Default_Return_Test() + await Vote(voteUser, votingItem.VotingItemId, votingItem.Options.First(), 1000L); + var votingResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput { - var address = Address.FromPublicKey(Accounts[1].KeyPair.PublicKey); - var votedItem = await GetVotedItems(address); - votedItem.ShouldBe(new VotedItems()); - } + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 1 + }); + + votingResult.VotingItemId.ShouldBe(votingItem.VotingItemId); + votingResult.VotersCount.ShouldBe(1); + votingResult.Results.Values.First().ShouldBe(1000L); + + await Vote(voteUser, votingItem.VotingItemId, votingItem.Options.Last(), 500L); + var votedResult = await GetVotedItems(Address.FromPublicKey(voteUser.PublicKey)); + votedResult.VotedItemVoteIds[votingItem.VotingItemId.ToHex()].ActiveVotes.Count.ShouldBe(2); + } - [Fact] - public async Task VoteContract_GetVotingRecords_Test() + [Fact] + public async Task VoteContract_GetLatestVotingResult_Test() + { + var voteUser1 = Accounts[2].KeyPair; + var voteUser2 = Accounts[3].KeyPair; + var votingItem = await RegisterVotingItemAsync(10, 3, true, DefaultSender, 2); + + await Vote(voteUser1, votingItem.VotingItemId, votingItem.Options.First(), 100L); + await Vote(voteUser1, votingItem.VotingItemId, votingItem.Options.First(), 200L); + var votingResult = await GetLatestVotingResult(votingItem.VotingItemId); + votingResult.VotersCount.ShouldBe(2); + votingResult.VotesAmount.ShouldBe(300L); + + await Vote(voteUser2, votingItem.VotingItemId, votingItem.Options.Last(), 100L); + await Vote(voteUser2, votingItem.VotingItemId, votingItem.Options.Last(), 200L); + votingResult = await GetLatestVotingResult(votingItem.VotingItemId); + votingResult.VotersCount.ShouldBe(4); + votingResult.VotesAmount.ShouldBe(600L); + } + + [Fact] + public async Task VoteContract_GetVotedItems_Default_Return_Test() + { + var address = Address.FromPublicKey(Accounts[1].KeyPair.PublicKey); + var votedItem = await GetVotedItems(address); + votedItem.ShouldBe(new VotedItems()); + } + + [Fact] + public async Task VoteContract_GetVotingRecords_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voteUser = Accounts[1].KeyPair; + var voteItemId = registerItem.VotingItemId; + var voteAmount = 100; + await Vote(voteUser, voteItemId, registerItem.Options[1], voteAmount); + var voteIds = await GetVoteIds(voteUser, voteItemId); + var currentVoteId = voteIds.ActiveVotes.First(); + var voteRecord = await VoteContractStub.GetVotingRecords.CallAsync(new GetVotingRecordsInput { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voteUser = Accounts[1].KeyPair; - var voteItemId = registerItem.VotingItemId; - var voteAmount = 100; - await Vote(voteUser, voteItemId, registerItem.Options[1], voteAmount); - var voteIds = await GetVoteIds(voteUser, voteItemId); - var currentVoteId = voteIds.ActiveVotes.First(); - var voteRecord = await VoteContractStub.GetVotingRecords.CallAsync(new GetVotingRecordsInput - { - Ids = {currentVoteId} - }); - voteRecord.Records.Count.ShouldBe(1); - voteRecord.Records[0].Amount.ShouldBe(voteAmount); - } + Ids = { currentVoteId } + }); + voteRecord.Records.Count.ShouldBe(1); + voteRecord.Records[0].Amount.ShouldBe(voteAmount); + } - [Fact] - public async Task VoteContract_GetVotingIds_Test() + [Fact] + public async Task VoteContract_GetVotingIds_Test() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voteUser = Accounts[1]; + var voteItemId = registerItem.VotingItemId; + var voteAmount = 100; + await Vote(voteUser.KeyPair, voteItemId, registerItem.Options[1], voteAmount); + var voteIds = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); - var voteUser = Accounts[1]; - var voteItemId = registerItem.VotingItemId; - var voteAmount = 100; - await Vote(voteUser.KeyPair, voteItemId, registerItem.Options[1], voteAmount); - var voteIds = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = voteUser.Address, - VotingItemId = registerItem.VotingItemId - }); - voteIds.ActiveVotes.Count.ShouldBe(1); - } + Voter = voteUser.Address, + VotingItemId = registerItem.VotingItemId + }); + voteIds.ActiveVotes.Count.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/BVT/SnapshotTests.cs b/test/AElf.Contracts.Vote.Tests/BVT/SnapshotTests.cs index e5df0a561d..a6e2f5f12b 100644 --- a/test/AElf.Contracts.Vote.Tests/BVT/SnapshotTests.cs +++ b/test/AElf.Contracts.Vote.Tests/BVT/SnapshotTests.cs @@ -3,101 +3,100 @@ using Shouldly; using Xunit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests { - public partial class VoteTests + [Fact] + public async Task VoteContract_TakeSnapshot_WithoutPermission_Test() { - [Fact] - public async Task VoteContract_TakeSnapshot_WithoutPermission_Test() - { - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 1); + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 1); - var otherUser = Accounts[2].KeyPair; - var transactionResult = (await GetVoteContractTester(otherUser).TakeSnapshot.SendWithExceptionAsync( - new TakeSnapshotInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 1 - })).TransactionResult; + var otherUser = Accounts[2].KeyPair; + var transactionResult = (await GetVoteContractTester(otherUser).TakeSnapshot.SendWithExceptionAsync( + new TakeSnapshotInput + { + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 1 + })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Only sponsor can take snapshot."); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Only sponsor can take snapshot."); + } - [Fact] - public async Task VoteContract_TakeSnapshot_WithoutVotingItem_Test() - { - var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( - new TakeSnapshotInput - { - VotingItemId = HashHelper.ComputeFrom("hash"), - SnapshotNumber = 1 - })).TransactionResult; + [Fact] + public async Task VoteContract_TakeSnapshot_WithoutVotingItem_Test() + { + var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( + new TakeSnapshotInput + { + VotingItemId = HashHelper.ComputeFrom("hash"), + SnapshotNumber = 1 + })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); - } - - [Fact] - public async Task VoteContract_TakeSnapshot_Exceed_TotalSnapshotNumber_Test() - { - var totalSnapshotNumber = 1; - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, totalSnapshotNumber); - await VoteContractStub.TakeSnapshot.SendAsync( - new TakeSnapshotInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 1 - }); - var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( - new TakeSnapshotInput - { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 2 - })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Current voting item already ended.").ShouldBeTrue(); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); + } + + [Fact] + public async Task VoteContract_TakeSnapshot_Exceed_TotalSnapshotNumber_Test() + { + var totalSnapshotNumber = 1; + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, totalSnapshotNumber); + await VoteContractStub.TakeSnapshot.SendAsync( + new TakeSnapshotInput + { + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 1 + }); + var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( + new TakeSnapshotInput + { + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 2 + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Current voting item already ended.").ShouldBeTrue(); + } + + [Fact] + public async Task VoteContract_TakeSnapshot_WithWrongSnapshotNumber_Test() + { + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 2); + var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( + new TakeSnapshotInput + { + VotingItemId = votingItem.VotingItemId, + SnapshotNumber = 2 + })).TransactionResult; - [Fact] - public async Task VoteContract_TakeSnapshot_WithWrongSnapshotNumber_Test() + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Can only take snapshot of current snapshot number").ShouldBeTrue(); + } + + [Fact] + public async Task VoteContract_TakeSnapshot_Success_Test() + { + var registerItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 3); + for (var i = 0; i < 3; i++) { - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 2); - var transactionResult = (await VoteContractStub.TakeSnapshot.SendWithExceptionAsync( + var transactionResult = (await VoteContractStub.TakeSnapshot.SendAsync( new TakeSnapshotInput { - VotingItemId = votingItem.VotingItemId, - SnapshotNumber = 2 + VotingItemId = registerItem.VotingItemId, + SnapshotNumber = i + 1 })).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Can only take snapshot of current snapshot number").ShouldBeTrue(); - } + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task VoteContract_TakeSnapshot_Success_Test() - { - var registerItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 3); - for (var i = 0; i < 3; i++) + var votingItem = await GetVoteItem(registerItem.VotingItemId); + votingItem.CurrentSnapshotNumber.ShouldBe(i + 2); + var voteResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput { - var transactionResult = (await VoteContractStub.TakeSnapshot.SendAsync( - new TakeSnapshotInput - { - VotingItemId = registerItem.VotingItemId, - SnapshotNumber = i + 1 - })).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var votingItem = await GetVoteItem(registerItem.VotingItemId); - votingItem.CurrentSnapshotNumber.ShouldBe(i + 2); - var voteResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - VotingItemId = registerItem.VotingItemId, - SnapshotNumber = i + 2 - }); - voteResult.SnapshotNumber.ShouldBe(i + 2); - } + VotingItemId = registerItem.VotingItemId, + SnapshotNumber = i + 2 + }); + voteResult.SnapshotNumber.ShouldBe(i + 2); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/Full/VoteForBestLanguageTests.cs b/test/AElf.Contracts.Vote.Tests/Full/VoteForBestLanguageTests.cs index 8010fb329e..589caca0eb 100644 --- a/test/AElf.Contracts.Vote.Tests/Full/VoteForBestLanguageTests.cs +++ b/test/AElf.Contracts.Vote.Tests/Full/VoteForBestLanguageTests.cs @@ -1,132 +1,130 @@ using System.Linq; using System.Threading.Tasks; -using AElf.ContractTestKit; -using AElf.Kernel; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests { - public partial class VoteTests + [Fact] + public async Task MultipleUsers_Vote_Scenario_Test() { - [Fact] - public async Task MultipleUsers_Vote_Scenario_Test() - { - var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 3); + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 3); - var user1 = Accounts[1]; - var user2 = Accounts[2]; - var user3 = Accounts[3]; + var user1 = Accounts[1]; + var user2 = Accounts[2]; + var user3 = Accounts[3]; - //phase 1 - { - //user1 vote 100 - var transactionResult1 = await Vote(user1.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 100); - transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); - - //user2 vote 150 - var transactionResult2 = await Vote(user2.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 150); - transactionResult2.Status.ShouldBe(TransactionResultStatus.Mined); - - //user3 vote 200 - var transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, registerItem.Options[1], 200); - transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); - - var votingResult = await GetVotingResult(registerItem.VotingItemId, 1); - votingResult.VotersCount.ShouldBe(3); - votingResult.Results.Count.ShouldBe(2); - votingResult.Results[registerItem.Options[0]].ShouldBe(250); - votingResult.Results[registerItem.Options[1]].ShouldBe(200); - - //take snapshot - var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 1); - snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //query vote ids - var voteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); - //query result - var voteRecord = await GetVotingRecord(voteIds.ActiveVotes.First()); - voteRecord.Option.ShouldBe(registerItem.Options[0]); - voteRecord.Amount.ShouldBe(100); - - //withdraw - var beforeBalance = GetUserBalance(user1.Address); - await Withdraw(user1.KeyPair, voteIds.ActiveVotes.First()); - var afterBalance = GetUserBalance(user1.Address); - - beforeBalance.ShouldBe(afterBalance - 100); - - voteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); - voteIds.ActiveVotes.Count.ShouldBe(0); - voteIds.WithdrawnVotes.Count.ShouldBe(1); - } - - //phase 2 + //phase 1 + { + //user1 vote 100 + var transactionResult1 = await Vote(user1.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 100); + transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); + + //user2 vote 150 + var transactionResult2 = await Vote(user2.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 150); + transactionResult2.Status.ShouldBe(TransactionResultStatus.Mined); + + //user3 vote 200 + var transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, registerItem.Options[1], 200); + transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); + + var votingResult = await GetVotingResult(registerItem.VotingItemId, 1); + votingResult.VotersCount.ShouldBe(3); + votingResult.Results.Count.ShouldBe(2); + votingResult.Results[registerItem.Options[0]].ShouldBe(250); + votingResult.Results[registerItem.Options[1]].ShouldBe(200); + + //take snapshot + var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 1); + snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //query vote ids + var voteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); + //query result + var voteRecord = await GetVotingRecord(voteIds.ActiveVotes.First()); + voteRecord.Option.ShouldBe(registerItem.Options[0]); + voteRecord.Amount.ShouldBe(100); + + //withdraw + var beforeBalance = GetUserBalance(user1.Address); + await Withdraw(user1.KeyPair, voteIds.ActiveVotes.First()); + var afterBalance = GetUserBalance(user1.Address); + + beforeBalance.ShouldBe(afterBalance - 100); + + voteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); + voteIds.ActiveVotes.Count.ShouldBe(0); + voteIds.WithdrawnVotes.Count.ShouldBe(1); + } + + //phase 2 + { + //add some more option + var options = new[] { - //add some more option - var options = new[] - { - Accounts[3].Address.ToBase58(), - Accounts[4].Address.ToBase58(), - Accounts[5].Address.ToBase58() - }; - var optionResult = (await VoteContractStub.AddOptions.SendAsync(new AddOptionsInput - { - VotingItemId = registerItem.VotingItemId, - Options = {options} - })).TransactionResult; - optionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //user1 vote new option 1 - var transactionResult1 = await Vote(user1.KeyPair, registerItem.VotingItemId, options[0], 100); - transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); - - //user2 vote new option 2 - var transactionResult2 = await Vote(user2.KeyPair, registerItem.VotingItemId, options[1], 100); - transactionResult2.Status.ShouldBe(TransactionResultStatus.Mined); - - //user3 vote new option 3 twice - var transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, options[2], 100); - transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); - transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, options[2], 100); - transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); - - var votingResult = await GetVotingResult(registerItem.VotingItemId, 2); - votingResult.VotersCount.ShouldBe(7); - votingResult.Results.Count.ShouldBe(3); - votingResult.Results[options[0]].ShouldBe(100); - votingResult.Results[options[1]].ShouldBe(100); - votingResult.Results[options[2]].ShouldBe(200); - - //take snapshot - var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 2); - snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); - - //query vote ids - var user1VoteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); - user1VoteIds.ActiveVotes.Count.ShouldBe(1); - user1VoteIds.WithdrawnVotes.Count.ShouldBe(1); - - var user2VoteIds = await GetVoteIds(user2.KeyPair, registerItem.VotingItemId); - user2VoteIds.ActiveVotes.Count.ShouldBe(2); - user2VoteIds.WithdrawnVotes.Count.ShouldBe(0); - - var user3VoteIds = await GetVoteIds(user3.KeyPair, registerItem.VotingItemId); - user3VoteIds.ActiveVotes.Count.ShouldBe(3); - user3VoteIds.WithdrawnVotes.Count.ShouldBe(0); - } - - //phase 3 + Accounts[3].Address.ToBase58(), + Accounts[4].Address.ToBase58(), + Accounts[5].Address.ToBase58() + }; + var optionResult = (await VoteContractStub.AddOptions.SendAsync(new AddOptionsInput { - //take snapshot - var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 3); - snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transactionResult = await VoteWithException(user2.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 100); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Current voting item already ended").ShouldBeTrue(); - } + VotingItemId = registerItem.VotingItemId, + Options = { options } + })).TransactionResult; + optionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //user1 vote new option 1 + var transactionResult1 = await Vote(user1.KeyPair, registerItem.VotingItemId, options[0], 100); + transactionResult1.Status.ShouldBe(TransactionResultStatus.Mined); + + //user2 vote new option 2 + var transactionResult2 = await Vote(user2.KeyPair, registerItem.VotingItemId, options[1], 100); + transactionResult2.Status.ShouldBe(TransactionResultStatus.Mined); + + //user3 vote new option 3 twice + var transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, options[2], 100); + transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); + transactionResult3 = await Vote(user3.KeyPair, registerItem.VotingItemId, options[2], 100); + transactionResult3.Status.ShouldBe(TransactionResultStatus.Mined); + + var votingResult = await GetVotingResult(registerItem.VotingItemId, 2); + votingResult.VotersCount.ShouldBe(7); + votingResult.Results.Count.ShouldBe(3); + votingResult.Results[options[0]].ShouldBe(100); + votingResult.Results[options[1]].ShouldBe(100); + votingResult.Results[options[2]].ShouldBe(200); + + //take snapshot + var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 2); + snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); + + //query vote ids + var user1VoteIds = await GetVoteIds(user1.KeyPair, registerItem.VotingItemId); + user1VoteIds.ActiveVotes.Count.ShouldBe(1); + user1VoteIds.WithdrawnVotes.Count.ShouldBe(1); + + var user2VoteIds = await GetVoteIds(user2.KeyPair, registerItem.VotingItemId); + user2VoteIds.ActiveVotes.Count.ShouldBe(2); + user2VoteIds.WithdrawnVotes.Count.ShouldBe(0); + + var user3VoteIds = await GetVoteIds(user3.KeyPair, registerItem.VotingItemId); + user3VoteIds.ActiveVotes.Count.ShouldBe(3); + user3VoteIds.WithdrawnVotes.Count.ShouldBe(0); + } + + //phase 3 + { + //take snapshot + var snapshotResult = await TakeSnapshot(registerItem.VotingItemId, 3); + snapshotResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transactionResult = + await VoteWithException(user2.KeyPair, registerItem.VotingItemId, registerItem.Options[0], 100); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Current voting item already ended").ShouldBeTrue(); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/GQL/BasicTests.cs b/test/AElf.Contracts.Vote.Tests/GQL/BasicTests.cs index 49a2d307d9..95cc948009 100644 --- a/test/AElf.Contracts.Vote.Tests/GQL/BasicTests.cs +++ b/test/AElf.Contracts.Vote.Tests/GQL/BasicTests.cs @@ -1,109 +1,106 @@ using System.Linq; using System.Threading.Tasks; -using AElf.ContractTestKit; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests { - public partial class VoteTests + [Fact] + public async Task VoteContract_Register_Again_Test() + { + var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 10); + var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(new VotingRegisterInput + { + // Basically same as previous one. + TotalSnapshotNumber = votingItem.TotalSnapshotNumber, + StartTimestamp = votingItem.StartTimestamp, + EndTimestamp = votingItem.EndTimestamp, + Options = { votingItem.Options }, + AcceptedCurrency = votingItem.AcceptedCurrency, + IsLockToken = votingItem.IsLockToken + })).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Voting item already exists"); + } + + [Fact] + public async Task VoteContract_Register_CurrencyNotSupportVoting_Test() + { + var startTime = TimestampHelper.GetUtcNow(); + var input = new VotingRegisterInput + { + TotalSnapshotNumber = 5, + EndTimestamp = startTime.AddDays(100), + StartTimestamp = startTime, + Options = + { + GenerateOptions(3) + }, + AcceptedCurrency = "USDT", + IsLockToken = true + }; + var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(input)).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.Contains("Claimed accepted token is not available for voting").ShouldBeTrue(); + } + + [Fact] + public async Task VoteContract_Vote_NotSuccess_Test() { - [Fact] - public async Task VoteContract_Register_Again_Test() + //did not find related vote event { - var votingItem = await RegisterVotingItemAsync(10, 4, true, DefaultSender, 10); - var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(new VotingRegisterInput + var input = new VoteInput { - // Basically same as previous one. - TotalSnapshotNumber = votingItem.TotalSnapshotNumber, - StartTimestamp = votingItem.StartTimestamp, - EndTimestamp = votingItem.EndTimestamp, - Options = {votingItem.Options}, - AcceptedCurrency = votingItem.AcceptedCurrency, - IsLockToken = votingItem.IsLockToken - })).TransactionResult; + VotingItemId = HashHelper.ComputeFrom("hash") + }; + + var transactionResult = (await VoteContractStub.Vote.SendWithExceptionAsync(input)).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Voting item already exists"); + transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); } - [Fact] - public async Task VoteContract_Register_CurrencyNotSupportVoting_Test() + //without such option { - var startTime = TimestampHelper.GetUtcNow(); - var input = new VotingRegisterInput + var votingItem = await RegisterVotingItemAsync(100, 4, true, DefaultSender, 2); + + var input = new VoteInput { - TotalSnapshotNumber = 5, - EndTimestamp = startTime.AddDays(100), - StartTimestamp = startTime, - Options = - { - GenerateOptions(3) - }, - AcceptedCurrency = "USDT", - IsLockToken = true + VotingItemId = votingItem.VotingItemId, + Option = "Somebody" }; - var transactionResult = (await VoteContractStub.Register.SendWithExceptionAsync(input)).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Claimed accepted token is not available for voting").ShouldBeTrue(); + var otherKeyPair = Accounts[1].KeyPair; + var otherVoteStub = GetVoteContractTester(otherKeyPair); + + var transactionResult = (await otherVoteStub.Vote.SendWithExceptionAsync(input)).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain($"Option {input.Option} not found"); } - [Fact] - public async Task VoteContract_Vote_NotSuccess_Test() + //not enough token { - //did not find related vote event - { - var input = new VoteInput - { - VotingItemId = HashHelper.ComputeFrom("hash") - }; + var votingItemId = await RegisterVotingItemAsync(100, 4, true, DefaultSender, 2); - var transactionResult = (await VoteContractStub.Vote.SendWithExceptionAsync(input)).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.Contains("Voting item not found").ShouldBeTrue(); - } - - //without such option - { - var votingItem = await RegisterVotingItemAsync(100, 4, true, DefaultSender, 2); - - var input = new VoteInput - { - VotingItemId = votingItem.VotingItemId, - Option = "Somebody" - }; - var otherKeyPair = Accounts[1].KeyPair; - var otherVoteStub = GetVoteContractTester(otherKeyPair); - - var transactionResult = (await otherVoteStub.Vote.SendWithExceptionAsync(input)).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain($"Option {input.Option} not found"); - } - - //not enough token + var input = new VoteInput { - var votingItemId = await RegisterVotingItemAsync(100, 4, true, DefaultSender, 2); - - var input = new VoteInput - { - VotingItemId = votingItemId.VotingItemId, - Option = votingItemId.Options.First(), - Amount = 2000_000_000_00000000L - }; - var otherKeyPair = Accounts[1].KeyPair; - var otherVoteStub = GetVoteContractTester(otherKeyPair); - - var transactionResult = (await otherVoteStub.Vote.SendWithExceptionAsync(input)).TransactionResult; - - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Insufficient balance"); - } + VotingItemId = votingItemId.VotingItemId, + Option = votingItemId.Options.First(), + Amount = 2000_000_000_00000000L + }; + var otherKeyPair = Accounts[1].KeyPair; + var otherVoteStub = GetVoteContractTester(otherKeyPair); + + var transactionResult = (await otherVoteStub.Vote.SendWithExceptionAsync(input)).TransactionResult; + + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Insufficient balance"); } } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/GenesisContractDtoExtensions.cs b/test/AElf.Contracts.Vote.Tests/GenesisContractDtoExtensions.cs index 5c524139ed..6481e5afb2 100644 --- a/test/AElf.Contracts.Vote.Tests/GenesisContractDtoExtensions.cs +++ b/test/AElf.Contracts.Vote.Tests/GenesisContractDtoExtensions.cs @@ -1,18 +1,19 @@ using AElf.Standards.ACS0; using Google.Protobuf; -namespace AElf.ContractTestKit +namespace AElf.ContractTestKit; + +public static class GenesisContractDtoExtensions { - public static class GenesisContractDtoExtensions + internal static void Add( + this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, + string methodName, + IMessage input) { - internal static void Add(this SystemContractDeploymentInput.Types.SystemTransactionMethodCallList systemTransactionMethodCallList, string methodName, - IMessage input) + systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall { - systemTransactionMethodCallList.Value.Add(new SystemContractDeploymentInput.Types.SystemTransactionMethodCall() - { - MethodName = methodName, - Params = input?.ToByteString() ?? ByteString.Empty - }); - } + MethodName = methodName, + Params = input?.ToByteString() ?? ByteString.Empty + }); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/ResetBlockTimeProvider.cs b/test/AElf.Contracts.Vote.Tests/ResetBlockTimeProvider.cs index 8a81c9323a..1af9bba826 100644 --- a/test/AElf.Contracts.Vote.Tests/ResetBlockTimeProvider.cs +++ b/test/AElf.Contracts.Vote.Tests/ResetBlockTimeProvider.cs @@ -1,10 +1,9 @@ using AElf.ContractTestKit; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public class ResetBlockTimeProvider : IResetBlockTimeProvider { - public class ResetBlockTimeProvider : IResetBlockTimeProvider - { - public bool Enabled => false; - public int StepMilliseconds => 0; - } + public bool Enabled => false; + public int StepMilliseconds => 0; } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/Types/MineList.cs b/test/AElf.Contracts.Vote.Tests/Types/MineList.cs index 4db3af4d4e..ed9c3082b5 100644 --- a/test/AElf.Contracts.Vote.Tests/Types/MineList.cs +++ b/test/AElf.Contracts.Vote.Tests/Types/MineList.cs @@ -1,49 +1,44 @@ using System.Linq; using AElf.CSharp.Core.Extension; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Consensus.AEDPoS.Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractConstant.cs b/test/AElf.Contracts.Vote.Tests/VoteContractConstant.cs index f3ca9b04e0..57d959d68a 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractConstant.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractConstant.cs @@ -1,9 +1,8 @@ -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public class VoteContractConstant { - public class VoteContractConstant - { - public const int MaximumOptionsCount = 64; - public const int OptionLengthLimit = 1024; - public const long DefaultMethodFee = 1_0000_0000; - } + public const int MaximumOptionsCount = 64; + public const int OptionLengthLimit = 1024; + public const long DefaultMethodFee = 1_0000_0000; } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractTestAElfModule.cs b/test/AElf.Contracts.Vote.Tests/VoteContractTestAElfModule.cs index 55721cb17a..dc1e61df7d 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractTestAElfModule.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractTestAElfModule.cs @@ -5,16 +5,15 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +[DependsOn(typeof(ContractTestModule))] +public class VoteContractTestAElfModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule))] - public class VoteContractTestAElfModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(); - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.AddSingleton(); - } + context.Services.RemoveAll(); + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs index 7677f2577d..779aaa37b1 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using AElf.Standards.ACS0; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.ContractTestKit; @@ -13,198 +11,195 @@ using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; -using AElf.OS.Node.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Volo.Abp.Threading; -using InitializeInput = AElf.Contracts.Parliament.InitializeInput; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public class VoteContractTestBase : ContractTestBase { - public class VoteContractTestBase : ContractTestBase + protected const string TestTokenSymbol = "ELF"; + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultSender => Accounts[0].Address; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(5).Select(a => a.KeyPair).ToList(); + + protected Address TokenContractAddress { get; set; } + protected Address VoteContractAddress { get; set; } + protected Address ParliamentContractAddress { get; set; } + protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); + protected Address ConsensusContractAddress { get; set; } + internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal VoteContractImplContainer.VoteContractImplStub VoteContractStub { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + + protected void InitializeContracts() { - protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected Address DefaultSender => Accounts[0].Address; - - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(5).Select(a=>a.KeyPair).ToList(); - - protected Address TokenContractAddress { get; set; } - protected Address VoteContractAddress { get; set; } - protected Address ParliamentContractAddress { get; set; } - protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); - protected Address ConsensusContractAddress { get; set; } - internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal VoteContractImplContainer.VoteContractImplStub VoteContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } - - protected const string TestTokenSymbol = "ELF"; - - protected void InitializeContracts() - { - BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - - //deploy vote contract - VoteContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(VoteContract).Assembly.Location)), - Name = VoteSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateVoteInitializationCallList() - })).Output; - VoteContractStub = GetVoteContractTester(DefaultSenderKeyPair); - - //deploy token contract - TokenContractAddress = AsyncHelper.RunSync(() => - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), - Name = TokenSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateTokenInitializationCallList() - })).Output; - TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - - //deploy parliament auth contract - ParliamentContractAddress = AsyncHelper.RunSync(()=> - BasicContractZeroStub.DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), - Name = ParliamentSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateParliamentInitializationCallList() - })).Output; - ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); - - ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(DefaultSenderKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), - Name = ConsensusSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateConsensusInitializationCallList() - })).Output; - AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); - } - - internal ACS0Container.ACS0Stub GetContractZeroTester(ECKeyPair keyPair) - { - return GetTester(ContractZeroAddress, keyPair); - } + BasicContractZeroStub = GetContractZeroTester(DefaultSenderKeyPair); - internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) - { - return GetTester(TokenContractAddress, keyPair); - } + //deploy vote contract + VoteContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(VoteContract).Assembly.Location)), + Name = VoteSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateVoteInitializationCallList() + })).Output; + VoteContractStub = GetVoteContractTester(DefaultSenderKeyPair); + + //deploy token contract + TokenContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(TokenContract).Assembly.Location)), + Name = TokenSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateTokenInitializationCallList() + })).Output; + TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); + + //deploy parliament auth contract + ParliamentContractAddress = AsyncHelper.RunSync(() => + BasicContractZeroStub.DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), + Name = ParliamentSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateParliamentInitializationCallList() + })).Output; + ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + + ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(DefaultSenderKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(AEDPoSContract).Assembly.Location)), + Name = ConsensusSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateConsensusInitializationCallList() + })).Output; + AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + } - internal VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) - { - return GetTester(VoteContractAddress, keyPair); - } - - internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) - { - return GetTester(ParliamentContractAddress, keyPair); - } + internal ACS0Container.ACS0Stub GetContractZeroTester(ECKeyPair keyPair) + { + return GetTester(ContractZeroAddress, keyPair); + } - internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) - { - return GetTester(ConsensusContractAddress, keyPair); - } + internal TokenContractContainer.TokenContractStub GetTokenContractTester(ECKeyPair keyPair) + { + return GetTester(TokenContractAddress, keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList GenerateVoteInitializationCallList() - { - return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - } + internal VoteContractImplContainer.VoteContractImplStub GetVoteContractTester(ECKeyPair keyPair) + { + return GetTester(VoteContractAddress, keyPair); + } + + internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamentContractTester(ECKeyPair keyPair) + { + return GetTester(ParliamentContractAddress, + keyPair); + } + + internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContractTester(ECKeyPair keyPair) + { + return GetTester(ConsensusContractAddress, keyPair); + } - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList GenerateTokenInitializationCallList() + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList GenerateVoteInitializationCallList() + { + return new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList GenerateTokenInitializationCallList() + { + const long totalSupply = 1_000_000_000_0000_0000; + + var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput { - const long totalSupply = 1_000_000_000_0000_0000; - - var tokenContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + Symbol = TestTokenSymbol, + Decimals = 2, + IsBurnable = true, + TokenName = "elf token for testing", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { - Symbol = TestTokenSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token for testing", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = - { - VoteContractAddress - } - }); + VoteContractAddress + } + }); - //issue default user + //issue default user + tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput + { + Symbol = TestTokenSymbol, + Amount = totalSupply - 20 * 100_000_0000_0000L, + To = DefaultSender, + Memo = "Issue token to default user for vote." + }); + + //issue some amount to voter + for (var i = 1; i < 20; i++) tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput { Symbol = TestTokenSymbol, - Amount = totalSupply - 20 * 100_000_0000_0000L, - To = DefaultSender, - Memo = "Issue token to default user for vote.", + Amount = 100_000_0000_0000L, + To = Accounts[i].Address, + Memo = "set voters few amount for voting." }); - - //issue some amount to voter - for (int i = 1; i < 20; i++) - { - tokenContractCallList.Add(nameof(TokenContract.Issue), new IssueInput - { - Symbol = TestTokenSymbol, - Amount = 100_000_0000_0000L, - To = Accounts[i].Address, - Memo = "set voters few amount for voting." - }); - } - return tokenContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList GenerateParliamentInitializationCallList() + return tokenContractCallList; + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateParliamentInitializationCallList() + { + var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + parliamentContractCallList.Add(nameof(ParliamentContract.Initialize), new InitializeInput { - var parliamentContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - parliamentContractCallList.Add(nameof(ParliamentContract.Initialize), new InitializeInput + PrivilegedProposer = DefaultSender, + ProposerAuthorityRequired = true + }); + + return parliamentContractCallList; + } + + private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList + GenerateConsensusInitializationCallList() + { + var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); + consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), + new InitialAElfConsensusContractInput { - PrivilegedProposer = DefaultSender, - ProposerAuthorityRequired = true + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000 }); - return parliamentContractCallList; - } - - private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList - GenerateConsensusInitializationCallList() + consensusContractCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), new MinerList { - var consensusContractCallList = new SystemContractDeploymentInput.Types.SystemTransactionMethodCallList(); - consensusContractCallList.Add(nameof(AEDPoSContractStub.InitialAElfConsensusContract), - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000 - }); + Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } + }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); - consensusContractCallList.Add(nameof(AEDPoSContractContainer.AEDPoSContractStub.FirstRound), new MinerList - { - Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))} - }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow())); + return consensusContractCallList; + } - return consensusContractCallList; - } - - protected long GetUserBalance(Address owner) + protected long GetUserBalance(Address owner) + { + return TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - return TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = owner, - Symbol = TestTokenSymbol - }).Result.Balance; - } + Owner = owner, + Symbol = TestTokenSymbol + }).Result.Balance; } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractTestHelper.cs b/test/AElf.Contracts.Vote.Tests/VoteContractTestHelper.cs index 74318aae76..48897898ad 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractTestHelper.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractTestHelper.cs @@ -1,166 +1,162 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.Types; -using Google.Protobuf.WellKnownTypes; using Shouldly; -namespace AElf.Contracts.Vote +namespace AElf.Contracts.Vote; + +public partial class VoteTests : VoteContractTestBase { - public partial class VoteTests : VoteContractTestBase + public VoteTests() + { + InitializeContracts(); + } + + /// + /// Register a voting item. + /// + /// + /// + /// + /// + /// + /// + private async Task RegisterVotingItemAsync(int lastingDays, int optionsCount, bool isLockToken, + Address sender, + int totalSnapshotNumber = int.MaxValue) { - public VoteTests() + var startTime = TimestampHelper.GetUtcNow(); + var input = new VotingRegisterInput { - InitializeContracts(); - } - - /// - /// Register a voting item. - /// - /// - /// - /// - /// - /// - /// - private async Task RegisterVotingItemAsync(int lastingDays, int optionsCount, bool isLockToken, Address sender, - int totalSnapshotNumber = int.MaxValue) + TotalSnapshotNumber = totalSnapshotNumber, + EndTimestamp = startTime.AddDays(lastingDays), + StartTimestamp = startTime, + Options = { GenerateOptions(optionsCount) }, + AcceptedCurrency = TestTokenSymbol, + IsLockToken = isLockToken + }; + var transactionResult = (await VoteContractStub.Register.SendAsync(input)).TransactionResult; + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + input.Options.Clear(); + var votingItemId = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sender)); + return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - var startTime = TimestampHelper.GetUtcNow(); - var input = new VotingRegisterInput - { - TotalSnapshotNumber = totalSnapshotNumber, - EndTimestamp = startTime.AddDays(lastingDays), - StartTimestamp = startTime, - Options = {GenerateOptions(optionsCount)}, - AcceptedCurrency = TestTokenSymbol, - IsLockToken = isLockToken - }; - var transactionResult = (await VoteContractStub.Register.SendAsync(input)).TransactionResult; - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - input.Options.Clear(); - var votingItemId = HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(input), HashHelper.ComputeFrom(sender)); - return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = votingItemId - }); - } - - private async Task TakeSnapshot(Hash votingItemId, long snapshotNumber) + VotingItemId = votingItemId + }); + } + + private async Task TakeSnapshot(Hash votingItemId, long snapshotNumber) + { + var input = new TakeSnapshotInput { - var input = new TakeSnapshotInput - { - VotingItemId = votingItemId, - SnapshotNumber = snapshotNumber - }; - var transactionResult = (await VoteContractStub.TakeSnapshot.SendAsync(input)).TransactionResult; + VotingItemId = votingItemId, + SnapshotNumber = snapshotNumber + }; + var transactionResult = (await VoteContractStub.TakeSnapshot.SendAsync(input)).TransactionResult; - return transactionResult; - } + return transactionResult; + } - private async Task Withdraw(ECKeyPair owner, Hash voteId) - { - var voterStub = GetVoteContractTester(owner); - var input = new WithdrawInput - { - VoteId = voteId - }; - - var withdrawResult = (await voterStub.Withdraw.SendAsync(input)).TransactionResult; - - return withdrawResult; - } - - private async Task WithdrawWithException(ECKeyPair owner, Hash voteId) - { - var voterStub = GetVoteContractTester(owner); - var input = new WithdrawInput - { - VoteId = voteId - }; - - var withdrawResult = (await voterStub.Withdraw.SendWithExceptionAsync(input)).TransactionResult; - - return withdrawResult; - } - - private async Task Vote(ECKeyPair voterKeyPair, Hash votingItemId, string option, - long amount) - { - return (await GetVoteContractTester(voterKeyPair).Vote.SendAsync(new VoteInput - { - VotingItemId = votingItemId, - Option = option, - Amount = amount - })).TransactionResult; - } - - private async Task VoteWithException(ECKeyPair voterKeyPair, Hash votingItemId, string option, - long amount) - { - return (await GetVoteContractTester(voterKeyPair).Vote.SendWithExceptionAsync(new VoteInput - { - VotingItemId = votingItemId, - Option = option, - Amount = amount - })).TransactionResult; - } - - private async Task GetVotingRecord(Hash voteHash) + private async Task Withdraw(ECKeyPair owner, Hash voteId) + { + var voterStub = GetVoteContractTester(owner); + var input = new WithdrawInput { - return await VoteContractStub.GetVotingRecord.CallAsync(voteHash); - } + VoteId = voteId + }; + + var withdrawResult = (await voterStub.Withdraw.SendAsync(input)).TransactionResult; + + return withdrawResult; + } - private async Task GetVotingResult(Hash votingItemId, long snapshotNumber) + private async Task WithdrawWithException(ECKeyPair owner, Hash voteId) + { + var voterStub = GetVoteContractTester(owner); + var input = new WithdrawInput { - return await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput - { - VotingItemId = votingItemId, - SnapshotNumber = snapshotNumber - }); - } - - - private async Task GetVoteItem(Hash votingItemId) + VoteId = voteId + }; + + var withdrawResult = (await voterStub.Withdraw.SendWithExceptionAsync(input)).TransactionResult; + + return withdrawResult; + } + + private async Task Vote(ECKeyPair voterKeyPair, Hash votingItemId, string option, + long amount) + { + return (await GetVoteContractTester(voterKeyPair).Vote.SendAsync(new VoteInput { - return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput - { - VotingItemId = votingItemId - }); - } + VotingItemId = votingItemId, + Option = option, + Amount = amount + })).TransactionResult; + } - private async Task GetVotedItems(Address address) + private async Task VoteWithException(ECKeyPair voterKeyPair, Hash votingItemId, string option, + long amount) + { + return (await GetVoteContractTester(voterKeyPair).Vote.SendWithExceptionAsync(new VoteInput { - return await VoteContractStub.GetVotedItems.CallAsync(address); - } + VotingItemId = votingItemId, + Option = option, + Amount = amount + })).TransactionResult; + } + + private async Task GetVotingRecord(Hash voteHash) + { + return await VoteContractStub.GetVotingRecord.CallAsync(voteHash); + } - private async Task GetLatestVotingResult(Hash hash) + private async Task GetVotingResult(Hash votingItemId, long snapshotNumber) + { + return await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput { - return await VoteContractStub.GetLatestVotingResult.CallAsync(hash); - } - - private async Task GetVoteIds(ECKeyPair voterKeyPair, Hash votingItemId) + VotingItemId = votingItemId, + SnapshotNumber = snapshotNumber + }); + } + + + private async Task GetVoteItem(Hash votingItemId) + { + return await VoteContractStub.GetVotingItem.CallAsync(new GetVotingItemInput { - var voterStub = GetVoteContractTester(voterKeyPair); - - var votingIds = await voterStub.GetVotingIds.CallAsync(new GetVotingIdsInput - { - Voter = Address.FromPublicKey(voterKeyPair.PublicKey), - VotingItemId = votingItemId - }); - - return votingIds; - } - - private List GenerateOptions(int count = 1) + VotingItemId = votingItemId + }); + } + + private async Task GetVotedItems(Address address) + { + return await VoteContractStub.GetVotedItems.CallAsync(address); + } + + private async Task GetLatestVotingResult(Hash hash) + { + return await VoteContractStub.GetLatestVotingResult.CallAsync(hash); + } + + private async Task GetVoteIds(ECKeyPair voterKeyPair, Hash votingItemId) + { + var voterStub = GetVoteContractTester(voterKeyPair); + + var votingIds = await voterStub.GetVotingIds.CallAsync(new GetVotingIdsInput { - return Enumerable.Range(0, count).Select(i => Accounts[i].Address.ToBase58()).ToList(); - } + Voter = Address.FromPublicKey(voterKeyPair.PublicKey), + VotingItemId = votingItemId + }); + + return votingIds; + } + + private List GenerateOptions(int count = 1) + { + return Enumerable.Range(0, count).Select(i => Accounts[i].Address.ToBase58()).ToList(); } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/AElf.Core.Tests.csproj b/test/AElf.Core.Tests/AElf.Core.Tests.csproj index fa0ce92cc1..70dc103cfe 100644 --- a/test/AElf.Core.Tests/AElf.Core.Tests.csproj +++ b/test/AElf.Core.Tests/AElf.Core.Tests.csproj @@ -7,16 +7,16 @@ - + - - - - - - + + + + + + diff --git a/test/AElf.Core.Tests/CoreAElfTestBase.cs b/test/AElf.Core.Tests/CoreAElfTestBase.cs index 423f5d9170..fdd9d9d064 100644 --- a/test/AElf.Core.Tests/CoreAElfTestBase.cs +++ b/test/AElf.Core.Tests/CoreAElfTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf +namespace AElf; + +public class CoreAElfTestBase : AElfIntegratedTest { - public class CoreAElfTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/CoreAElfTestModule.cs b/test/AElf.Core.Tests/CoreAElfTestModule.cs index a5c6db2bd7..b98f59f880 100644 --- a/test/AElf.Core.Tests/CoreAElfTestModule.cs +++ b/test/AElf.Core.Tests/CoreAElfTestModule.cs @@ -4,28 +4,27 @@ using AElf.Providers; using Volo.Abp.Modularity; -namespace AElf +namespace AElf; + +[DependsOn( + typeof(CoreAElfModule))] +public class CoreAElfTestModule : AElfModule { - [DependsOn( - typeof(CoreAElfModule))] - public class CoreAElfTestModule: AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } - - [DependsOn( - typeof(CoreAElfModule))] - public class CoreWithServiceContainerFactoryOptionsAElfTestModule: AElfModule +} + +[DependsOn( + typeof(CoreAElfModule))] +public class CoreWithServiceContainerFactoryOptionsAElfTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure>(options => { - Configure>(options => - { - options.Types = new List - {typeof(ATestProvider), typeof(CTestProvider), typeof(BTestProvider)}; - }); - } + options.Types = new List + { typeof(ATestProvider), typeof(CTestProvider), typeof(BTestProvider) }; + }); } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/Providers/ATestProvider.cs b/test/AElf.Core.Tests/Providers/ATestProvider.cs index cf0acb4b4c..6df7985f55 100644 --- a/test/AElf.Core.Tests/Providers/ATestProvider.cs +++ b/test/AElf.Core.Tests/Providers/ATestProvider.cs @@ -1,9 +1,8 @@ using Volo.Abp.DependencyInjection; -namespace AElf.Providers +namespace AElf.Providers; + +public class ATestProvider : ITestProvider, ISingletonDependency { - public class ATestProvider : ITestProvider, ISingletonDependency - { - public string Name => nameof(ATestProvider); - } + public string Name => nameof(ATestProvider); } \ No newline at end of file diff --git a/test/AElf.Core.Tests/Providers/BTestProvider.cs b/test/AElf.Core.Tests/Providers/BTestProvider.cs index 070b775653..7bc5eacd02 100644 --- a/test/AElf.Core.Tests/Providers/BTestProvider.cs +++ b/test/AElf.Core.Tests/Providers/BTestProvider.cs @@ -1,9 +1,8 @@ using Volo.Abp.DependencyInjection; -namespace AElf.Providers +namespace AElf.Providers; + +public class BTestProvider : ITestProvider, ISingletonDependency { - public class BTestProvider : ITestProvider, ISingletonDependency - { - public string Name => nameof(BTestProvider); - } + public string Name => nameof(BTestProvider); } \ No newline at end of file diff --git a/test/AElf.Core.Tests/Providers/CTestProvider.cs b/test/AElf.Core.Tests/Providers/CTestProvider.cs index c81aa6cf9e..c8912bc5dc 100644 --- a/test/AElf.Core.Tests/Providers/CTestProvider.cs +++ b/test/AElf.Core.Tests/Providers/CTestProvider.cs @@ -1,9 +1,8 @@ using Volo.Abp.DependencyInjection; -namespace AElf.Providers +namespace AElf.Providers; + +public class CTestProvider : ITestProvider, ISingletonDependency { - public class CTestProvider : ITestProvider, ISingletonDependency - { - public string Name => nameof(CTestProvider); - } + public string Name => nameof(CTestProvider); } \ No newline at end of file diff --git a/test/AElf.Core.Tests/Providers/ITestProvider.cs b/test/AElf.Core.Tests/Providers/ITestProvider.cs index 0f9693d015..ecea677f2f 100644 --- a/test/AElf.Core.Tests/Providers/ITestProvider.cs +++ b/test/AElf.Core.Tests/Providers/ITestProvider.cs @@ -1,7 +1,6 @@ -namespace AElf.Providers +namespace AElf.Providers; + +public interface ITestProvider { - public interface ITestProvider - { - string Name { get; } - } + string Name { get; } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/RegistrationTests.cs b/test/AElf.Core.Tests/RegistrationTests.cs index 10b6ece63d..3d56ce8fa7 100644 --- a/test/AElf.Core.Tests/RegistrationTests.cs +++ b/test/AElf.Core.Tests/RegistrationTests.cs @@ -1,31 +1,29 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.Providers; using Shouldly; using Xunit; -namespace AElf +namespace AElf; + +public sealed class RegistrationTests : CoreAElfTestBase { - public sealed class RegistrationTests : CoreAElfTestBase - { - private readonly IEnumerable _testProviders; - private readonly IServiceContainer _testProviderList; + private readonly IServiceContainer _testProviderList; + private readonly IEnumerable _testProviders; - public RegistrationTests() - { - _testProviders = GetRequiredService>(); - _testProviderList = GetRequiredService>(); - } + public RegistrationTests() + { + _testProviders = GetRequiredService>(); + _testProviderList = GetRequiredService>(); + } - [Fact] - public void IocRegistration_Test() - { - var count = _testProviders.Count(); - count.ShouldBeGreaterThan(0); - count.ShouldBe(_testProviders.Select(provider => provider.Name).Distinct().Count()); - _testProviderList.Count().ShouldBe(count); - ServiceProvider.GetServices(new[] {typeof(ATestProvider)}).Count().ShouldBe(1); - } + [Fact] + public void IocRegistration_Test() + { + var count = _testProviders.Count(); + count.ShouldBeGreaterThan(0); + count.ShouldBe(_testProviders.Select(provider => provider.Name).Distinct().Count()); + _testProviderList.Count().ShouldBe(count); + ServiceProvider.GetServices(new[] { typeof(ATestProvider) }).Count().ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/ServiceContainerTests.cs b/test/AElf.Core.Tests/ServiceContainerTests.cs index ad4425bf3d..62c899cf3d 100644 --- a/test/AElf.Core.Tests/ServiceContainerTests.cs +++ b/test/AElf.Core.Tests/ServiceContainerTests.cs @@ -4,24 +4,23 @@ using Shouldly; using Xunit; -namespace AElf +namespace AElf; + +public sealed class ServiceContainerTests : AElfIntegratedTest { - public sealed class ServiceContainerTests:AElfIntegratedTest - { - private readonly IServiceContainer _testProviders; + private readonly IServiceContainer _testProviders; - public ServiceContainerTests() - { - _testProviders = GetRequiredService>(); - } + public ServiceContainerTests() + { + _testProviders = GetRequiredService>(); + } - [Fact] - public void ServiceContainerTest() - { - var types = _testProviders.Select(p => p.GetType()).ToList(); - types[0].ShouldBe(typeof(ATestProvider)); - types[1].ShouldBe(typeof(CTestProvider)); - types[2].ShouldBe(typeof(BTestProvider)); - } + [Fact] + public void ServiceContainerTest() + { + var types = _testProviders.Select(p => p.GetType()).ToList(); + types[0].ShouldBe(typeof(ATestProvider)); + types[1].ShouldBe(typeof(CTestProvider)); + types[2].ShouldBe(typeof(BTestProvider)); } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/TaskQueueManagerTests.cs b/test/AElf.Core.Tests/TaskQueueManagerTests.cs index efa240feb9..eba5556db6 100644 --- a/test/AElf.Core.Tests/TaskQueueManagerTests.cs +++ b/test/AElf.Core.Tests/TaskQueueManagerTests.cs @@ -4,147 +4,162 @@ using Shouldly; using Xunit; -namespace AElf +namespace AElf; + +public class TaskQueueManagerTests : CoreAElfTestBase { - public class TaskQueueManagerTests : CoreAElfTestBase + private readonly ITaskQueueManager _taskQueueManager; + + public TaskQueueManagerTests() { - private readonly ITaskQueueManager _taskQueueManager; + _taskQueueManager = GetRequiredService(); + } - public TaskQueueManagerTests() - { - _taskQueueManager = GetRequiredService(); - } + [Fact] + public void Test_StartAsync_Test() + { + var testQueue = _taskQueueManager.CreateQueue("TestQueue"); - [Fact] - public void Test_StartAsync_Test() - { - var testQueue = _taskQueueManager.CreateQueue("TestQueue"); + Should.Throw(() => _taskQueueManager.CreateQueue("TestQueue")); - Should.Throw(()=> _taskQueueManager.CreateQueue("TestQueue")); - - Should.Throw(()=>testQueue.Start()); + Should.Throw(() => testQueue.Start()); - testQueue.Dispose(); - Should.Throw(() => testQueue.Enqueue(() => Task.CompletedTask)); - } + testQueue.Dispose(); + Should.Throw(() => testQueue.Enqueue(() => Task.CompletedTask)); + } - [Fact] - public void Test_Enqueue_Test() + [Fact] + public void Test_Enqueue_Test() + { + var result = 1; + var testQueue = _taskQueueManager.CreateQueue("TestQueue"); + Parallel.For(0, 100, i => { - var result = 1; - var testQueue = _taskQueueManager.CreateQueue("TestQueue"); - Parallel.For(0, 100, i => + testQueue.Enqueue(() => { - testQueue.Enqueue(() => - { - var value = result; - result = value + 1; - return Task.CompletedTask; - }); + var value = result; + result = value + 1; + return Task.CompletedTask; }); + }); + + testQueue.Dispose(); - testQueue.Dispose(); + result.ShouldBe(101); + } - result.ShouldBe(101); - } + [Fact] + public void Test_Many_Enqueue_Test() + { + var testData = new int[3]; + var testQueueA = _taskQueueManager.CreateQueue("TestQueueA"); + var testQueueB = _taskQueueManager.CreateQueue("TestQueueB"); + var testQueueC = _taskQueueManager.CreateQueue("TestQueueC"); - [Fact] - public void Test_Many_Enqueue_Test() + Parallel.For(0, 100, i => { - var testData = new int[3]; - var testQueueA = _taskQueueManager.CreateQueue("TestQueueA"); - var testQueueB = _taskQueueManager.CreateQueue("TestQueueB"); - var testQueueC = _taskQueueManager.CreateQueue("TestQueueC"); - - Parallel.For(0, 100, i => + testQueueA.Enqueue(() => + { + testData[0]++; + return Task.CompletedTask; + }); + testQueueB.Enqueue(() => { - testQueueA.Enqueue(() => { testData[0]++; return Task.CompletedTask;}); - testQueueB.Enqueue(() => { testData[1]++; return Task.CompletedTask;}); - testQueueC.Enqueue(() => { testData[2]++; return Task.CompletedTask;}); + testData[1]++; + return Task.CompletedTask; }); + testQueueC.Enqueue(() => + { + testData[2]++; + return Task.CompletedTask; + }); + }); - testQueueA.Dispose(); - testQueueB.Dispose(); - testQueueC.Dispose(); + testQueueA.Dispose(); + testQueueB.Dispose(); + testQueueC.Dispose(); - testData[0].ShouldBe(100); - testData[1].ShouldBe(100); - testData[2].ShouldBe(100); - } + testData[0].ShouldBe(100); + testData[1].ShouldBe(100); + testData[2].ShouldBe(100); + } - [Fact] - public void Test_Dispose_Test() - { - var result = 1; + [Fact] + public void Test_Dispose_Test() + { + var result = 1; - var testQueue = _taskQueueManager.CreateQueue("TestQueue"); + var testQueue = _taskQueueManager.CreateQueue("TestQueue"); - Parallel.For(0, 3, i => + Parallel.For(0, 3, i => + { + testQueue.Enqueue(async () => { - testQueue.Enqueue(async () => - { - var value = result; - await Task.Delay(100); - result = value + 1; - }); + var value = result; + await Task.Delay(100); + result = value + 1; }); - testQueue.Dispose(); - - result.ShouldBe(4); + }); + testQueue.Dispose(); - Should.Throw(() => testQueue.Enqueue(() => { result++; return Task.CompletedTask;})); - } + result.ShouldBe(4); - [Fact] - public void Test_GetQueue_Test() - { - var defaultQueueA = _taskQueueManager.GetQueue(); - var defaultQueueB = _taskQueueManager.GetQueue(); - defaultQueueA.ShouldBe(defaultQueueB); - - var testQueueA1 = _taskQueueManager.CreateQueue("TestQueueA"); - var testQueueA2 = _taskQueueManager.GetQueue("TestQueueA"); - testQueueA1.ShouldBe(testQueueA2); - testQueueA1.ShouldNotBe(defaultQueueA); - - var testQueueB1 = _taskQueueManager.CreateQueue("TestQueueB"); - var testQueueB2 = _taskQueueManager.GetQueue("TestQueueB"); - testQueueB1.ShouldBe(testQueueB2); - testQueueB1.ShouldNotBe(defaultQueueA); - testQueueB1.ShouldNotBe(testQueueA1); - - _taskQueueManager.Dispose(); - } - - [Fact] - public void Test_TaskQueue_StopAsync_Test() - { - var testQueue = _taskQueueManager.CreateQueue("TestQueue"); - testQueue.Dispose(); - - var result = 1; - Should.Throw(() => - testQueue.Enqueue(() => - { - var value = result; - result = value + 1; - return Task.CompletedTask; - }) - ); - } - - [Fact] - public void GetQueueStatus_Test() + Should.Throw(() => testQueue.Enqueue(() => { - _taskQueueManager.CreateQueue("TestQueueA"); - _taskQueueManager.CreateQueue("TestQueueB"); - - var queueInfos = _taskQueueManager.GetQueueStatus(); - queueInfos.Count.ShouldBe(2); - queueInfos.Select(o=>o.Name).ShouldContain("TestQueueA"); - queueInfos.Select(o=>o.Name).ShouldContain("TestQueueB"); - - _taskQueueManager.Dispose(); - } + result++; + return Task.CompletedTask; + })); + } + + [Fact] + public void Test_GetQueue_Test() + { + var defaultQueueA = _taskQueueManager.GetQueue(); + var defaultQueueB = _taskQueueManager.GetQueue(); + defaultQueueA.ShouldBe(defaultQueueB); + + var testQueueA1 = _taskQueueManager.CreateQueue("TestQueueA"); + var testQueueA2 = _taskQueueManager.GetQueue("TestQueueA"); + testQueueA1.ShouldBe(testQueueA2); + testQueueA1.ShouldNotBe(defaultQueueA); + + var testQueueB1 = _taskQueueManager.CreateQueue("TestQueueB"); + var testQueueB2 = _taskQueueManager.GetQueue("TestQueueB"); + testQueueB1.ShouldBe(testQueueB2); + testQueueB1.ShouldNotBe(defaultQueueA); + testQueueB1.ShouldNotBe(testQueueA1); + + _taskQueueManager.Dispose(); + } + + [Fact] + public void Test_TaskQueue_StopAsync_Test() + { + var testQueue = _taskQueueManager.CreateQueue("TestQueue"); + testQueue.Dispose(); + + var result = 1; + Should.Throw(() => + testQueue.Enqueue(() => + { + var value = result; + result = value + 1; + return Task.CompletedTask; + }) + ); + } + + [Fact] + public void GetQueueStatus_Test() + { + _taskQueueManager.CreateQueue("TestQueueA"); + _taskQueueManager.CreateQueue("TestQueueB"); + + var queueInfos = _taskQueueManager.GetQueueStatus(); + queueInfos.Count.ShouldBe(2); + queueInfos.Select(o => o.Name).ShouldContain("TestQueueA"); + queueInfos.Select(o => o.Name).ShouldContain("TestQueueB"); + + _taskQueueManager.Dispose(); } } \ No newline at end of file diff --git a/test/AElf.Core.Tests/TaskQueueTests.cs b/test/AElf.Core.Tests/TaskQueueTests.cs index baee50de64..361d326405 100644 --- a/test/AElf.Core.Tests/TaskQueueTests.cs +++ b/test/AElf.Core.Tests/TaskQueueTests.cs @@ -1,65 +1,63 @@ using System; -using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using Shouldly; using Xunit; -namespace AElf +namespace AElf; + +public class TaskQueueTests { - public class TaskQueueTests + private readonly TaskQueue _taskQueue; + private int _counter; + + public TaskQueueTests() + { + _taskQueue = new TaskQueue(); + _counter = 0; + } + + [Fact] + public void StartQueueTest_Twice_Test() + { + _taskQueue.Start(); + Should.Throw(() => _taskQueue.Start()); + } + + [Fact] + public void Enqueue_Test() { - private readonly TaskQueue _taskQueue; - private int _counter; - public TaskQueueTests() - { - _taskQueue = new TaskQueue(); - _counter = 0; - } + _taskQueue.Start(); + _taskQueue.Enqueue(ProcessTask); - [Fact] - public void StartQueueTest_Twice_Test() - { - _taskQueue.Start(); - Should.Throw(() => _taskQueue.Start()); - } + _taskQueue.Dispose(); + _counter.ShouldBe(1); - [Fact] - public void Enqueue_Test() - { - _taskQueue.Start(); + _taskQueue.Dispose(); + Should.Throw(() => _taskQueue.Enqueue(ProcessTask)); + } + + [Fact] + public void Enqueue_MultipleTimes_Test() + { + _taskQueue.Start(); + for (var i = 0; i < 10; i++) _taskQueue.Enqueue(ProcessTask); - - _taskQueue.Dispose(); - _counter.ShouldBe(1); - - _taskQueue.Dispose(); - Should.Throw(() => _taskQueue.Enqueue(ProcessTask)); - } + _taskQueue.Dispose(); - [Fact] - public void Enqueue_MultipleTimes_Test() - { - _taskQueue.Start(); - for (var i = 0; i < 10; i++) - _taskQueue.Enqueue(ProcessTask); - _taskQueue.Dispose(); - - _counter.ShouldBe(10); - } + _counter.ShouldBe(10); + } - [Fact] - public void Dispose_Queue_Test() - { - _taskQueue.Start(); - _taskQueue.Dispose(); + [Fact] + public void Dispose_Queue_Test() + { + _taskQueue.Start(); + _taskQueue.Dispose(); - Should.Throw(() => _taskQueue.Enqueue(ProcessTask)); - } + Should.Throw(() => _taskQueue.Enqueue(ProcessTask)); + } - private async Task ProcessTask() - { - await Task.Run(() => _counter++); - } + private async Task ProcessTask() + { + await Task.Run(() => _counter++); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/AElf.CrossChain.Core.Tests.csproj b/test/AElf.CrossChain.Core.Tests/AElf.CrossChain.Core.Tests.csproj index 4511df9cda..c1b7888509 100644 --- a/test/AElf.CrossChain.Core.Tests/AElf.CrossChain.Core.Tests.csproj +++ b/test/AElf.CrossChain.Core.Tests/AElf.CrossChain.Core.Tests.csproj @@ -5,17 +5,17 @@ false - - - - - - + + + + + + - - - + + + @@ -26,7 +26,7 @@ Protobuf\Proto\authority_info.proto - + Protobuf\Proto\cross_chain_contract.proto @@ -35,5 +35,5 @@ Protobuf\Proto\cross_chain_contract_impl.proto - + diff --git a/test/AElf.CrossChain.Core.Tests/Application/CrossChainRequestServiceTests.cs b/test/AElf.CrossChain.Core.Tests/Application/CrossChainRequestServiceTests.cs index cb5923990b..1febd1d0ef 100644 --- a/test/AElf.CrossChain.Core.Tests/Application/CrossChainRequestServiceTests.cs +++ b/test/AElf.CrossChain.Core.Tests/Application/CrossChainRequestServiceTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Threading.Tasks; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Communication.Application; @@ -7,42 +6,43 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public class CrossChainRequestServiceTests : AElfIntegratedTest { - public class CrossChainRequestServiceTests : AElfIntegratedTest + private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + private readonly ICrossChainClientService _crossChainClientService; + private readonly ICrossChainRequestService _crossChainRequestService; + + public CrossChainRequestServiceTests() { - private readonly ICrossChainRequestService _crossChainRequestService; - private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; - private readonly ICrossChainClientService _crossChainClientService; - - public CrossChainRequestServiceTests() - { - _crossChainRequestService = GetRequiredService(); - _crossChainCacheEntityService = GetRequiredService(); - _crossChainClientService = GetRequiredService(); - } + _crossChainRequestService = GetRequiredService(); + _crossChainCacheEntityService = GetRequiredService(); + _crossChainClientService = GetRequiredService(); + } - [Fact] - public async Task RequestCrossChainDataTest() + [Fact] + public async Task RequestCrossChainDataTest() + { + var crossChainClientCreationContext = new CrossChainClientCreationContext { - var crossChainClientCreationContext = new CrossChainClientCreationContext - { - LocalChainId = 0, - RemoteChainId = 1, - IsClientToParentChain = false, - RemoteServerHost = "localhost", - RemoteServerPort = 5000 - }; - var communicationHelper = GetRequiredService(); - communicationHelper.SetClientConnected(crossChainClientCreationContext.RemoteChainId, true); - await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); - _crossChainCacheEntityService.RegisterNewChain(crossChainClientCreationContext.RemoteChainId, 10); - communicationHelper.CheckClientConnected(-1).ShouldBeFalse(); - await _crossChainRequestService.RequestCrossChainDataFromOtherChainsAsync(); - communicationHelper.CheckClientConnected(-1).ShouldBeTrue(); - - var chainInitializationData = await _crossChainRequestService.RequestChainInitializationDataAsync(crossChainClientCreationContext.RemoteChainId); - chainInitializationData.CreationHeightOnParentChain.ShouldBe(1); - } + LocalChainId = 0, + RemoteChainId = 1, + IsClientToParentChain = false, + RemoteServerHost = "localhost", + RemoteServerPort = 5000 + }; + var communicationHelper = GetRequiredService(); + communicationHelper.SetClientConnected(crossChainClientCreationContext.RemoteChainId, true); + await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); + _crossChainCacheEntityService.RegisterNewChain(crossChainClientCreationContext.RemoteChainId, 10); + communicationHelper.CheckClientConnected(-1).ShouldBeFalse(); + await _crossChainRequestService.RequestCrossChainDataFromOtherChainsAsync(); + communicationHelper.CheckClientConnected(-1).ShouldBeTrue(); + + var chainInitializationData = + await _crossChainRequestService.RequestChainInitializationDataAsync(crossChainClientCreationContext + .RemoteChainId); + chainInitializationData.CreationHeightOnParentChain.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Application/CrossChainResponseServiceTest.cs b/test/AElf.CrossChain.Core.Tests/Application/CrossChainResponseServiceTest.cs index 2ea566ad44..99284a0cf9 100644 --- a/test/AElf.CrossChain.Core.Tests/Application/CrossChainResponseServiceTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Application/CrossChainResponseServiceTest.cs @@ -2,59 +2,58 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Application +namespace AElf.CrossChain.Application; + +public class CrossChainResponseServiceTest : CrossChainCommunicationTestBase { - public class CrossChainResponseServiceTest : CrossChainCommunicationTestBase + private readonly ICrossChainResponseService _chainResponseService; + private readonly CrossChainCommunicationTestHelper _crossChainCommunicationTestHelper; + + public CrossChainResponseServiceTest() + { + _chainResponseService = GetRequiredService(); + _crossChainCommunicationTestHelper = GetRequiredService(); + } + + [Fact] + public async Task ResponseSideChainBlockData_Test() + { + var res = await _chainResponseService.ResponseSideChainBlockDataAsync(2); + Assert.True(res.Height == 2); + } + + [Fact] + public async Task ResponseParentChainBlockData_WithoutBlock_Test() + { + var chainId = ChainHelper.GetChainId(1); + var height = 5; + var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); + Assert.Null(res); + } + + [Fact] + public async Task ResponseParentChainBlockData_WithMerklePath_Test() + { + var chainId = 123; + var height = 3; + var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); + res.ShouldNotBeNull(); + + var indexedSideChainBlockData = _crossChainCommunicationTestHelper.IndexedSideChainBlockData; + + var computedRoot = res.IndexedMerklePath[indexedSideChainBlockData.SideChainBlockDataList[0].Height] + .ComputeRootWithLeafNode(indexedSideChainBlockData.SideChainBlockDataList[0] + .TransactionStatusMerkleTreeRoot); + + computedRoot.ShouldBe(res.CrossChainExtraData.TransactionStatusMerkleTreeRoot); + } + + [Fact] + public async Task ResponseParentChainBlockData_Test() { - private readonly ICrossChainResponseService _chainResponseService; - private readonly CrossChainCommunicationTestHelper _crossChainCommunicationTestHelper; - - public CrossChainResponseServiceTest() - { - _chainResponseService = GetRequiredService(); - _crossChainCommunicationTestHelper = GetRequiredService(); - } - - [Fact] - public async Task ResponseSideChainBlockData_Test() - { - var res = await _chainResponseService.ResponseSideChainBlockDataAsync(2); - Assert.True(res.Height == 2); - } - - [Fact] - public async Task ResponseParentChainBlockData_WithoutBlock_Test() - { - var chainId = ChainHelper.GetChainId(1); - var height = 5; - var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); - Assert.Null(res); - } - - [Fact] - public async Task ResponseParentChainBlockData_WithMerklePath_Test() - { - var chainId = 123; - var height = 3; - var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); - res.ShouldNotBeNull(); - - var indexedSideChainBlockData = _crossChainCommunicationTestHelper.IndexedSideChainBlockData; - - var computedRoot = res.IndexedMerklePath[indexedSideChainBlockData.SideChainBlockDataList[0].Height] - .ComputeRootWithLeafNode(indexedSideChainBlockData.SideChainBlockDataList[0] - .TransactionStatusMerkleTreeRoot); - - computedRoot.ShouldBe(res.CrossChainExtraData.TransactionStatusMerkleTreeRoot); - } - - [Fact] - public async Task ResponseParentChainBlockData_Test() - { - var chainId = ChainHelper.GetChainId(1); - var height = 3; - var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); - Assert.True(res.Height == 3); - } + var chainId = ChainHelper.GetChainId(1); + var height = 3; + var res = await _chainResponseService.ResponseParentChainBlockDataAsync(height, chainId); + Assert.True(res.Height == 3); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Cache/ChainCacheEntityProviderTest.cs b/test/AElf.CrossChain.Core.Tests/Cache/ChainCacheEntityProviderTest.cs index bfead5d1f7..26edcfac77 100644 --- a/test/AElf.CrossChain.Core.Tests/Cache/ChainCacheEntityProviderTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Cache/ChainCacheEntityProviderTest.cs @@ -1,56 +1,55 @@ using AElf.CrossChain.Cache.Infrastructure; using Xunit; -namespace AElf.CrossChain.Cache +namespace AElf.CrossChain.Cache; + +public class ChainCacheEntityProviderTest : CrossChainTestBase { - public class ChainCacheEntityProviderTest : CrossChainTestBase + private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; + + public ChainCacheEntityProviderTest() + { + _crossChainCacheEntityProvider = GetRequiredService(); + } + + [Fact] + public void TryAdd_New() + { + var chainId = 123; + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); + Assert.True(_crossChainCacheEntityProvider.Size == 1); + } + + [Fact] + public void TryGet_Null() + { + var chainId = 123; + + _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); + Assert.Null(actualBlockInfoCache); + } + + [Fact] + public void TryGet() { - private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; - - public ChainCacheEntityProviderTest() - { - _crossChainCacheEntityProvider = GetRequiredService(); - } - - [Fact] - public void TryAdd_New() - { - int chainId = 123; - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); - Assert.True(_crossChainCacheEntityProvider.Size == 1); - } - - [Fact] - public void TryGet_Null() - { - int chainId = 123; - - _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); - Assert.Null(actualBlockInfoCache); - } - - [Fact] - public void TryGet() - { - int chainId = 123; - - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); - - _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); - Assert.Equal(1, actualBlockInfoCache.TargetChainHeight()); - } - - [Fact] - public void TryAdd_Twice_With_SameChainId_NotSameValue() - { - int chainId = 123; - - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 2); + var chainId = 123; + + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); + + _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); + Assert.Equal(1, actualBlockInfoCache.TargetChainHeight()); + } + + [Fact] + public void TryAdd_Twice_With_SameChainId_NotSameValue() + { + var chainId = 123; + + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 2); // var blockInfoCache2 = new BlockCacheEntityProvider(2); - Assert.True(_crossChainCacheEntityProvider.Size == 1); - _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); - Assert.Equal(1, actualBlockInfoCache.TargetChainHeight()); - } + Assert.True(_crossChainCacheEntityProvider.Size == 1); + _crossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var actualBlockInfoCache); + Assert.Equal(1, actualBlockInfoCache.TargetChainHeight()); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainCacheEntityServiceTest.cs b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainCacheEntityServiceTest.cs index 4295630a0d..f367d968cf 100644 --- a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainCacheEntityServiceTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainCacheEntityServiceTest.cs @@ -1,47 +1,46 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Application; +using AElf.Standards.ACS7; using Shouldly; using Xunit; -namespace AElf.CrossChain.Cache +namespace AElf.CrossChain.Cache; + +public class CrossChainCacheEntityServiceTest : CrossChainTestBase { - public class CrossChainCacheEntityServiceTest : CrossChainTestBase + private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + + public CrossChainCacheEntityServiceTest() { - private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + _crossChainCacheEntityService = GetService(); + } - public CrossChainCacheEntityServiceTest() - { - _crossChainCacheEntityService = GetService(); - } + [Fact] + public void RegisterNewChainTest() + { + var chainId = 1; + _crossChainCacheEntityService.RegisterNewChain(chainId, 1); + var cachedChainIdList = _crossChainCacheEntityService.GetCachedChainIds(); + cachedChainIdList.ShouldContain(chainId); - [Fact] - public void RegisterNewChainTest() - { - var chainId = 1; - _crossChainCacheEntityService.RegisterNewChain(chainId, 1); - var cachedChainIdList = _crossChainCacheEntityService.GetCachedChainIds(); - cachedChainIdList.ShouldContain(chainId); + _crossChainCacheEntityService.GetCachedChainIds(); + var targetHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); + targetHeight.ShouldBe(2); + } - _crossChainCacheEntityService.GetCachedChainIds(); - var targetHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); - targetHeight.ShouldBe(2); - } + [Fact] + public async Task UpdateCrossChainCacheAsyncTest() + { + var chainId = 1; + _crossChainCacheEntityService.RegisterNewChain(chainId, 10); + var cachedChainIdList = _crossChainCacheEntityService.GetCachedChainIds(); + cachedChainIdList.ShouldContain(chainId); - [Fact] - public async Task UpdateCrossChainCacheAsyncTest() + await _crossChainCacheEntityService.UpdateCrossChainCacheAsync(null, 0, new ChainIdAndHeightDict { - var chainId = 1; - _crossChainCacheEntityService.RegisterNewChain(chainId, 10); - var cachedChainIdList = _crossChainCacheEntityService.GetCachedChainIds(); - cachedChainIdList.ShouldContain(chainId); - - await _crossChainCacheEntityService.UpdateCrossChainCacheAsync(null, 0, new ChainIdAndHeightDict - { - IdHeightDict = {{chainId, 12}} - }); - var targetHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); - targetHeight.ShouldBe(13); - } + IdHeightDict = { { chainId, 12 } } + }); + var targetHeight = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); + targetHeight.ShouldBe(13); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataConsumerTest.cs b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataConsumerTest.cs index e218d24dfc..cf541239b9 100644 --- a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataConsumerTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataConsumerTest.cs @@ -1,95 +1,93 @@ using System.Collections.Generic; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Cache.Infrastructure; -using AElf.Types; +using AElf.Standards.ACS7; using Xunit; -namespace AElf.CrossChain.Cache +namespace AElf.CrossChain.Cache; + +public class CrossChainDataConsumerTest : CrossChainTestBase { - public class CrossChainDataConsumerTest : CrossChainTestBase + private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; + private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; + + public CrossChainDataConsumerTest() { - private readonly IBlockCacheEntityConsumer _blockCacheEntityConsumer; - private readonly ICrossChainCacheEntityProvider _crossChainCacheEntityProvider; + _blockCacheEntityConsumer = GetRequiredService(); + _crossChainCacheEntityProvider = GetRequiredService(); + } - public CrossChainDataConsumerTest() - { - _blockCacheEntityConsumer = GetRequiredService(); - _crossChainCacheEntityProvider = GetRequiredService(); - } - - [Fact] - public void TryTake_EmptyCache() - { - int chainId = 123; - var blockInfo = _blockCacheEntityConsumer.Take(chainId, 1, false); - Assert.Null(blockInfo); - } + [Fact] + public void TryTake_EmptyCache() + { + var chainId = 123; + var blockInfo = _blockCacheEntityConsumer.Take(chainId, 1, false); + Assert.Null(blockInfo); + } - [Fact] - public void TryTake_NotExistChain() + [Fact] + public void TryTake_NotExistChain() + { + var chainId = 123; + var dict = new Dictionary { - int chainId = 123; - var dict = new Dictionary - { - {chainId, new ChainCacheEntity(chainId, 1)} - }; - CreateFakeCache(dict); - int chainIdB = 124; - var blockInfo = _blockCacheEntityConsumer.Take(chainIdB, 1, false); - Assert.Null(blockInfo); - } + { chainId, new ChainCacheEntity(chainId, 1) } + }; + CreateFakeCache(dict); + var chainIdB = 124; + var blockInfo = _blockCacheEntityConsumer.Take(chainIdB, 1, false); + Assert.Null(blockInfo); + } - [Fact] - public void TryTake_WrongIndex() + [Fact] + public void TryTake_WrongIndex() + { + var chainId = 123; + var blockInfoCache = new ChainCacheEntity(chainId, 1); + var sideChainBlockData = CreateSideChainBlockData(chainId, 1); + blockInfoCache.TryAdd(sideChainBlockData); + var dict = new Dictionary { - int chainId = 123; - var blockInfoCache = new ChainCacheEntity(chainId, 1); - var sideChainBlockData = CreateSideChainBlockData(chainId, 1); - blockInfoCache.TryAdd(sideChainBlockData); - var dict = new Dictionary - { - {chainId, blockInfoCache} - }; - CreateFakeCache(dict); - var blockInfo = _blockCacheEntityConsumer.Take(chainId, 2, false); - Assert.Null(blockInfo); - } + { chainId, blockInfoCache } + }; + CreateFakeCache(dict); + var blockInfo = _blockCacheEntityConsumer.Take(chainId, 2, false); + Assert.Null(blockInfo); + } - [Fact] - public void TryTake_After_RegisterNewChain() - { - int chainId = 123; - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); - CrossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var blockInfoCache); - Assert.NotNull(blockInfoCache); - var expectedBlockInfo = CreateSideChainBlockData(chainId, 1); - blockInfoCache.TryAdd(expectedBlockInfo); - var actualBlockInfo = _blockCacheEntityConsumer.Take(chainId, 1, false); - Assert.Equal(expectedBlockInfo, actualBlockInfo); - } - - [Fact] - public void TryTake_WrongIndex_After_RegisterNewChain() - { - int chainId = 123; - _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); - CrossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var blockInfoCache); - Assert.NotNull(blockInfoCache); - var expectedBlockInfo = CreateSideChainBlockData(chainId, 1); - blockInfoCache.TryAdd(expectedBlockInfo); - var blockInfo = _blockCacheEntityConsumer.Take(chainId, 2, false); - Assert.Null(blockInfo); - } + [Fact] + public void TryTake_After_RegisterNewChain() + { + var chainId = 123; + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); + CrossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var blockInfoCache); + Assert.NotNull(blockInfoCache); + var expectedBlockInfo = CreateSideChainBlockData(chainId, 1); + blockInfoCache.TryAdd(expectedBlockInfo); + var actualBlockInfo = _blockCacheEntityConsumer.Take(chainId, 1, false); + Assert.Equal(expectedBlockInfo, actualBlockInfo); + } - private SideChainBlockData CreateSideChainBlockData(int chainId, long height) + [Fact] + public void TryTake_WrongIndex_After_RegisterNewChain() + { + var chainId = 123; + _crossChainCacheEntityProvider.AddChainCacheEntity(chainId, 1); + CrossChainCacheEntityProvider.TryGetChainCacheEntity(chainId, out var blockInfoCache); + Assert.NotNull(blockInfoCache); + var expectedBlockInfo = CreateSideChainBlockData(chainId, 1); + blockInfoCache.TryAdd(expectedBlockInfo); + var blockInfo = _blockCacheEntityConsumer.Take(chainId, 2, false); + Assert.Null(blockInfo); + } + + private SideChainBlockData CreateSideChainBlockData(int chainId, long height) + { + return new SideChainBlockData { - return new SideChainBlockData - { - ChainId = chainId, - Height = height, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) - }; - } + ChainId = chainId, + Height = height, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) + }; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataProducerTest.cs b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataProducerTest.cs index 44d6a288bb..5f94700a8d 100644 --- a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataProducerTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainDataProducerTest.cs @@ -1,76 +1,74 @@ using System; using System.Collections.Generic; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Cache.Infrastructure; -using AElf.Types; +using AElf.Standards.ACS7; using Xunit; -namespace AElf.CrossChain.Cache +namespace AElf.CrossChain.Cache; + +public class CrossChainDataProducerTest : CrossChainTestBase { - public class CrossChainDataProducerTest : CrossChainTestBase + private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + + public CrossChainDataProducerTest() + { + _blockCacheEntityProducer = GetRequiredService(); + } + + [Fact] + public void TryAdd_Null() { - private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + Assert.Throws(() => _blockCacheEntityProducer.TryAddBlockCacheEntity(null)); + } - public CrossChainDataProducerTest() - { - _blockCacheEntityProducer = GetRequiredService(); - } - - [Fact] - public void TryAdd_Null() + [Fact] + public void TryAdd_NotExistChain() + { + var chainId = 123; + var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData { - Assert.Throws(() => _blockCacheEntityProducer.TryAddBlockCacheEntity(null)); - } + ChainId = chainId + }); + Assert.False(res); + } - [Fact] - public void TryAdd_NotExistChain() + [Fact] + public void TryAdd_ExistChain_WrongIndex() + { + var chainId = 123; + var dict = new Dictionary { - int chainId = 123; - var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData { - ChainId = chainId - }); - Assert.False(res); - } - - [Fact] - public void TryAdd_ExistChain_WrongIndex() + chainId, new ChainCacheEntity(chainId, 1) + } + }; + CreateFakeCache(dict); + var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData { - int chainId = 123; - var dict = new Dictionary - { - { - chainId, new ChainCacheEntity(chainId, 1) - } - }; - CreateFakeCache(dict); - var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData - { - ChainId = chainId, - Height = 2 - }); - Assert.False(res); - } - - [Fact] - public void TryAdd_ExistChain_CorrectIndex() + ChainId = chainId, + Height = 2 + }); + Assert.False(res); + } + + [Fact] + public void TryAdd_ExistChain_CorrectIndex() + { + var chainId = 123; + var dict = new Dictionary { - int chainId = 123; - var dict = new Dictionary { - { - chainId, new ChainCacheEntity(chainId, 1) - } - }; - CreateFakeCache(dict); - var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData - { - ChainId = chainId, - Height = 1, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") - }); - Assert.True(res); - } + chainId, new ChainCacheEntity(chainId, 1) + } + }; + CreateFakeCache(dict); + var res = _blockCacheEntityProducer.TryAddBlockCacheEntity(new SideChainBlockData + { + ChainId = chainId, + Height = 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") + }); + Assert.True(res); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainMemoryCacheTest.cs b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainMemoryCacheTest.cs index 857b102550..903a7a5c7e 100644 --- a/test/AElf.CrossChain.Core.Tests/Cache/CrossChainMemoryCacheTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Cache/CrossChainMemoryCacheTest.cs @@ -1,364 +1,348 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Infrastructure; -using AElf.Types; +using AElf.Standards.ACS7; using Xunit; -namespace AElf.CrossChain.Cache +namespace AElf.CrossChain.Cache; + +public class CrossChainMemoryCacheTest : CrossChainTestBase { - public class CrossChainMemoryCacheTest : CrossChainTestBase + [Fact] + public void TryAdd_SingleThread_Success() { - [Fact] - public void TryAdd_SingleThread_Success() + var chainId = 123; + var height = 1; + var blockInfoCache = new ChainCacheEntity(chainId, 1); + var res = blockInfoCache.TryAdd(new SideChainBlockData { - var chainId = 123; - var height = 1; - var blockInfoCache = new ChainCacheEntity(chainId, 1); - var res = blockInfoCache.TryAdd(new SideChainBlockData - { - Height = height, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) - }); - Assert.True(res); - Assert.True(blockInfoCache.TargetChainHeight() == height + 1); - } + Height = height, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) + }); + Assert.True(res); + Assert.True(blockInfoCache.TargetChainHeight() == height + 1); + } - [Fact] - public void TryAdd_SingleThread_Fail() + [Fact] + public void TryAdd_SingleThread_Fail() + { + var height = 2; + var initTarget = 1; + var chainId = 123; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var res = blockInfoCache.TryAdd(new SideChainBlockData { - var height = 2; - var initTarget = 1; - var chainId = 123; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - var res = blockInfoCache.TryAdd(new SideChainBlockData - { - Height = height - }); - Assert.False(res); - Assert.True(blockInfoCache.TargetChainHeight() == initTarget); - } + Height = height + }); + Assert.False(res); + Assert.True(blockInfoCache.TargetChainHeight() == initTarget); + } - [Fact] - public void TryAdd_Twice_SingleThread_Success() + [Fact] + public void TryAdd_Twice_SingleThread_Success() + { + var chainId = 123; + var height = 1; + var blockInfoCache = new ChainCacheEntity(chainId, 1); + blockInfoCache.TryAdd(new SideChainBlockData { - var chainId = 123; - var height = 1; - var blockInfoCache = new ChainCacheEntity(chainId, 1); - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = height, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height++.ToString()) - }); - var res = blockInfoCache.TryAdd(new SideChainBlockData + Height = height, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height++.ToString()) + }); + var res = blockInfoCache.TryAdd(new SideChainBlockData + { + Height = height, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) + }); + Assert.True(res); + Assert.True(blockInfoCache.TargetChainHeight() == height + 1); + } + + [Fact] + public void TryAdd_MultiThreads_WithDifferentData() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + var taskList = new List(); + while (i < 5) + { + var j = i; + var t = Task.Run(() => blockInfoCache.TryAdd(new SideChainBlockData { - Height = height, + Height = 2 * j + 1, ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(height.ToString()) - }); - Assert.True(res); - Assert.True(blockInfoCache.TargetChainHeight() == height + 1); + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((2 * j + 1).ToString()) + })); + taskList.Add(t); + i++; } - [Fact] - public void TryAdd_MultiThreads_WithDifferentData() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - var i = 0; - var taskList = new List(); - while (i < 5) + Task.WaitAll(taskList.ToArray()); + Assert.True(blockInfoCache.TargetChainHeight() == initTarget + 1); + } + + [Fact] + public void TryAdd_DataContinuous() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i < 5) + blockInfoCache.TryAdd(new SideChainBlockData { - var j = i; - var t = Task.Run(() => blockInfoCache.TryAdd(new SideChainBlockData - { - Height = 2 * j + 1, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((2 * j + 1).ToString()) - })); - taskList.Add(t); - i++; - } + Height = i, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i++.ToString()) + }); - Task.WaitAll(taskList.ToArray()); - Assert.True(blockInfoCache.TargetChainHeight() == initTarget + 1); - } + Assert.True(blockInfoCache.TargetChainHeight() == 5); + } - [Fact] - public void TryAdd_DataContinuous() + [Fact] + public void TryAdd_DataNotContinuous() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + blockInfoCache.TryAdd(new SideChainBlockData { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - var i = 0; - while (i < 5) - { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i++.ToString()) - }); - } + Height = 1, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") + }); + blockInfoCache.TryAdd(new SideChainBlockData + { + Height = 2, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("2") + }); - Assert.True(blockInfoCache.TargetChainHeight() == 5); - } + // 3 is absent. + blockInfoCache.TryAdd(new SideChainBlockData + { + Height = 4, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("4") + }); + Assert.True(blockInfoCache.TargetChainHeight() == 3); + } - [Fact] - public void TryAdd_DataNotContinuous() + [Fact] + public void TryAdd_MultiThreads_WithSameData() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + var taskList = new List(); + while (i++ < 5) { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - blockInfoCache.TryAdd(new SideChainBlockData + var t = Task.Run(() => blockInfoCache.TryAdd(new SideChainBlockData { - Height = 1, + Height = initTarget, ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") - }); + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(initTarget.ToString()) + })); + taskList.Add(t); + } + + Task.WaitAll(taskList.ToArray()); + Assert.True(blockInfoCache.TargetChainHeight() == initTarget + 1); + } + + [Fact] + public void TryTake_WithoutCache() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var res = blockInfoCache.TryTake(initTarget, out _, false); + Assert.False(res); + } + + [Fact] + public void TryTake_WithoutEnoughCache() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ < CrossChainConstants.DefaultBlockCacheEntityCount) blockInfoCache.TryAdd(new SideChainBlockData { - Height = 2, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("2") + Height = i }); - // 3 is absent. + var res = blockInfoCache.TryTake(initTarget, out _, true); + Assert.False(res); + } + + [Fact] + public void TryTake_WithSizeLimit() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ <= CrossChainConstants.DefaultBlockCacheEntityCount) blockInfoCache.TryAdd(new SideChainBlockData { - Height = 4, + Height = i, ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("4") + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) }); - Assert.True(blockInfoCache.TargetChainHeight() == 3); - } - - [Fact] - public void TryAdd_MultiThreads_WithSameData() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - var i = 0; - var taskList = new List(); - while (i++ < 5) - { - var t = Task.Run(() => blockInfoCache.TryAdd(new SideChainBlockData - { - Height = initTarget, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(initTarget.ToString()) - })); - taskList.Add(t); - } - Task.WaitAll(taskList.ToArray()); - Assert.True(blockInfoCache.TargetChainHeight() == initTarget + 1); - } + var res = blockInfoCache.TryTake(initTarget, out var blockInfo, true); + Assert.True(res); + Assert.True(blockInfo.Height == initTarget); + } - [Fact] - public void TryTake_WithoutCache() + [Fact] + public void TryTake_WithoutSizeLimit() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + blockInfoCache.TryAdd(new SideChainBlockData { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - var res = blockInfoCache.TryTake(initTarget, out _, false); - Assert.False(res); - } + Height = 1, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") + }); + var res = blockInfoCache.TryTake(initTarget, out var blockInfo, false); + Assert.True(res); + Assert.True(blockInfo.Height == initTarget); + } - [Fact] - public void TryTake_WithoutEnoughCache() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ < CrossChainConstants.DefaultBlockCacheEntityCount) + [Fact] + public void TryTake_WithClearCacheNeeded() + { + var chainId = 123; + var initTarget = 2; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) + blockInfoCache.TryAdd(new SideChainBlockData { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i - }); - } + ChainId = chainId, + Height = i, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - var res = blockInfoCache.TryTake(initTarget, out _, true); - Assert.False(res); - } + var res = blockInfoCache.TryTake(initTarget, out var blockInfo, true); + Assert.True(res); + Assert.True(blockInfo.Height == initTarget); + } - [Fact] - public void TryTake_WithSizeLimit() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ <= CrossChainConstants.DefaultBlockCacheEntityCount) + [Fact] + public void TryTake_Twice() + { + var chainId = 123; + var initTarget = 2; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) + blockInfoCache.TryAdd(new SideChainBlockData { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + Height = i, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - var res = blockInfoCache.TryTake(initTarget, out var blockInfo, true); - Assert.True(res); - Assert.True(blockInfo.Height == initTarget); - } + var res = blockInfoCache.TryTake(initTarget, out var b1, true); + Assert.True(res); + res = blockInfoCache.TryTake(initTarget, out var b2, true); + Assert.True(res); + Assert.Equal(b1, b2); + } - [Fact] - public void TryTake_WithoutSizeLimit() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + [Fact] + public void TryTake_OutDatedData() + { + var chainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) blockInfoCache.TryAdd(new SideChainBlockData { - Height = 1, + Height = i, ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) }); - var res = blockInfoCache.TryTake(initTarget, out var blockInfo, false); - Assert.True(res); - Assert.True(blockInfo.Height == initTarget); - } - - [Fact] - public void TryTake_WithClearCacheNeeded() - { - var chainId = 123; - var initTarget = 2; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) - { - blockInfoCache.TryAdd(new SideChainBlockData - { - ChainId = chainId, - Height = i, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } - var res = blockInfoCache.TryTake(initTarget, out var blockInfo, true); - Assert.True(res); - Assert.True(blockInfo.Height == initTarget); - } + blockInfoCache.TryTake(2, out _, true); + var res = blockInfoCache.TryTake(1, out var b2, true); + Assert.True(res); + Assert.True(b2.Height == 1); + } - [Fact] - public void TryTake_Twice() + [Fact] + public void TargetHeight_WithEmptyQueue() + { + var sideChainId = 123; + var initTarget = 1; + var blockInfoCache = new ChainCacheEntity(sideChainId, initTarget); + blockInfoCache.TryAdd(new SideChainBlockData { - var chainId = 123; - var initTarget = 2; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) - { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + Height = 1, + ChainId = sideChainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") + }); + blockInfoCache.TryAdd(new SideChainBlockData + { + Height = 2, + ChainId = sideChainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("2") + }); + blockInfoCache.TryTake(1, out _, false); + blockInfoCache.TryTake(2, out _, false); - var res = blockInfoCache.TryTake(initTarget, out var b1, true); - Assert.True(res); - res = blockInfoCache.TryTake(initTarget, out var b2, true); - Assert.True(res); - Assert.Equal(b1, b2); - } + Assert.Equal(3, blockInfoCache.TargetChainHeight()); + } - [Fact] - public void TryTake_OutDatedData() - { - var chainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) + [Fact] + public void ClearByHeight() + { + var chainId = 123; + var initTarget = 2; + var blockInfoCache = new ChainCacheEntity(chainId, initTarget); + var i = 0; + while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) + blockInfoCache.TryAdd(new SideChainBlockData { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + Height = i, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - blockInfoCache.TryTake(2, out _, true); - var res = blockInfoCache.TryTake(1, out var b2, true); + { + blockInfoCache.ClearOutOfDateCacheByHeight(initTarget - 1); + var res = blockInfoCache.TryTake(initTarget, out _, false); Assert.True(res); - Assert.True(b2.Height == 1); } - [Fact] - public void TargetHeight_WithEmptyQueue() { - var sideChainId = 123; - var initTarget = 1; - var blockInfoCache = new ChainCacheEntity(sideChainId, initTarget); - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = 1, - ChainId = sideChainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") - }); - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = 2, - ChainId = sideChainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("2") - }); - blockInfoCache.TryTake(1, out _, false); - blockInfoCache.TryTake(2, out _, false); - - Assert.Equal(3, blockInfoCache.TargetChainHeight()); + blockInfoCache.ClearOutOfDateCacheByHeight(initTarget); + var res = blockInfoCache.TryTake(initTarget, out _, false); + Assert.False(res); } - [Fact] - public void ClearByHeight() { - var chainId = 123; - var initTarget = 2; - var blockInfoCache = new ChainCacheEntity(chainId, initTarget); - int i = 0; - while (i++ < initTarget + CrossChainConstants.DefaultBlockCacheEntityCount) - { - blockInfoCache.TryAdd(new SideChainBlockData - { - Height = i, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } - - { - blockInfoCache.ClearOutOfDateCacheByHeight(initTarget - 1); - var res = blockInfoCache.TryTake(initTarget, out _, false); - Assert.True(res); - } - + var targetHeight = blockInfoCache.TargetChainHeight(); + blockInfoCache.ClearOutOfDateCacheByHeight(targetHeight); + Assert.True(targetHeight + 1 == blockInfoCache.TargetChainHeight()); + for (var j = 0; j < targetHeight; j++) { - blockInfoCache.ClearOutOfDateCacheByHeight(initTarget); - var res = blockInfoCache.TryTake(initTarget, out _, false); + var res = blockInfoCache.TryTake(j, out _, false); Assert.False(res); } - - { - var targetHeight = blockInfoCache.TargetChainHeight(); - blockInfoCache.ClearOutOfDateCacheByHeight(targetHeight); - Assert.True(targetHeight + 1 == blockInfoCache.TargetChainHeight()); - for (int j = 0; j < targetHeight; j++) - { - var res = blockInfoCache.TryTake(j, out _, false); - Assert.False(res); - } - } } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Communication/CrossChainClientServiceTests.cs b/test/AElf.CrossChain.Core.Tests/Communication/CrossChainClientServiceTests.cs index e671b7ce80..0d9c6a4fa5 100644 --- a/test/AElf.CrossChain.Core.Tests/Communication/CrossChainClientServiceTests.cs +++ b/test/AElf.CrossChain.Core.Tests/Communication/CrossChainClientServiceTests.cs @@ -4,80 +4,79 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Communication +namespace AElf.CrossChain.Communication; + +public class CrossChainClientServiceTests : CrossChainCommunicationTestBase { - public class CrossChainClientServiceTests : CrossChainCommunicationTestBase + private readonly ICrossChainClientService _crossChainClientService; + private readonly CrossChainCommunicationTestHelper _crossChainCommunicationTestHelper; + + public CrossChainClientServiceTests() { - private readonly ICrossChainClientService _crossChainClientService; - private readonly CrossChainCommunicationTestHelper _crossChainCommunicationTestHelper; + _crossChainClientService = GetRequiredService(); + _crossChainCommunicationTestHelper = GetRequiredService(); + } - public CrossChainClientServiceTests() + [Fact] + public async Task AddClientTest() + { + var remoteChainId = ChainHelper.GetChainId(1); + var localChainId = ChainHelper.ConvertBase58ToChainId("AELF"); + var crossChainClientCreationContext = new CrossChainClientCreationContext { - _crossChainClientService = GetRequiredService(); - _crossChainCommunicationTestHelper = GetRequiredService(); - } + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = "localhost", + RemoteServerPort = 5000 + }; + _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId, true); + var client = await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); + client.IsConnected.ShouldBeTrue(); + client.RemoteChainId.ShouldBe(remoteChainId); + } - [Fact] - public async Task AddClientTest() + [Fact] + public async Task GetClientTest() + { + var remoteChainId1 = ChainHelper.GetChainId(1); + var remoteChainId2 = ChainHelper.GetChainId(2); + var remoteChainId3 = ChainHelper.GetChainId(3); + var localChainId = ChainHelper.ConvertBase58ToChainId("AELF"); { - int remoteChainId = ChainHelper.GetChainId(1); - var localChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - var crossChainClientCreationContext = new CrossChainClientCreationContext + var crossChainClientCreationContext1 = new CrossChainClientCreationContext { LocalChainId = localChainId, - RemoteChainId = remoteChainId, + RemoteChainId = remoteChainId1, IsClientToParentChain = false, RemoteServerHost = "localhost", RemoteServerPort = 5000 }; - _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId, true); - var client = await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext); - client.IsConnected.ShouldBeTrue(); - client.RemoteChainId.ShouldBe(remoteChainId); + _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId1, true); + await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext1); + var client1 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId1); + client1.IsConnected.ShouldBeTrue(); + client1.RemoteChainId.ShouldBe(remoteChainId1); } - - [Fact] - public async Task GetClientTest() - { - int remoteChainId1 = ChainHelper.GetChainId(1); - int remoteChainId2 = ChainHelper.GetChainId(2); - int remoteChainId3 = ChainHelper.GetChainId(3); - var localChainId = ChainHelper.ConvertBase58ToChainId("AELF"); - { - var crossChainClientCreationContext1 = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId1, - IsClientToParentChain = false, - RemoteServerHost = "localhost", - RemoteServerPort = 5000 - }; - _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId1, true); - await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext1); - var client1 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId1); - client1.IsConnected.ShouldBeTrue(); - client1.RemoteChainId.ShouldBe(remoteChainId1); - } + { + var crossChainClientCreationContext2 = new CrossChainClientCreationContext { - var crossChainClientCreationContext2 = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId2, - IsClientToParentChain = false, - RemoteServerHost = "localhost", - RemoteServerPort = 5000 - }; - _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId2, false); - await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext2); - var client2 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId2); - client2.ShouldBeNull(); - } + LocalChainId = localChainId, + RemoteChainId = remoteChainId2, + IsClientToParentChain = false, + RemoteServerHost = "localhost", + RemoteServerPort = 5000 + }; + _crossChainCommunicationTestHelper.SetClientConnected(remoteChainId2, false); + await _crossChainClientService.CreateClientAsync(crossChainClientCreationContext2); + var client2 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId2); + client2.ShouldBeNull(); + } - { - var client3 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId3); - client3.ShouldBeNull(); - } + { + var client3 = await _crossChainClientService.GetConnectedCrossChainClientAsync(remoteChainId3); + client3.ShouldBeNull(); } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestBase.cs b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestBase.cs index 2835930bec..25c3436d43 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestBase.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainCommunicationTestBase : AElfIntegratedTest { - public class CrossChainCommunicationTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestHelper.cs b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestHelper.cs index 3d68e0c160..86a4290058 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestHelper.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestHelper.cs @@ -1,82 +1,80 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS7; using AElf.CrossChain.Communication.Infrastructure; +using AElf.Standards.ACS7; using AElf.Types; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainCommunicationTestHelper { - public class CrossChainCommunicationTestHelper - { - private readonly Dictionary _crossChainClientCreationContexts = - new Dictionary(); - - private readonly Dictionary _clientConnected = new Dictionary(); + private readonly Dictionary _clientConnected = new(); + + private readonly Dictionary _crossChainClientCreationContexts = new(); - public IndexedSideChainBlockData IndexedSideChainBlockData { get; set; } = new IndexedSideChainBlockData + public IndexedSideChainBlockData IndexedSideChainBlockData { get; set; } = new() + { + SideChainBlockDataList = { - SideChainBlockDataList = + new SideChainBlockData { - new SideChainBlockData - { - ChainId = 123, Height = 1, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("fakeTransactionMerkleTree") - } + ChainId = 123, Height = 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("fakeTransactionMerkleTree") } - }; - - public void AddNewCrossChainClient(CrossChainClientCreationContext crossChainClientCreationContext) - { - _crossChainClientCreationContexts[crossChainClientCreationContext.RemoteChainId] = - crossChainClientCreationContext; } + }; - public bool TryGetCrossChainClientCreationContext(int chainId, - out CrossChainClientCreationContext crossChainClientCreationContext) - { - return _crossChainClientCreationContexts.TryGetValue(chainId, out crossChainClientCreationContext); - } - - - public bool CheckClientConnected(int chainId) - { - return _clientConnected.TryGetValue(chainId, out var res) && res; - } + public void AddNewCrossChainClient(CrossChainClientCreationContext crossChainClientCreationContext) + { + _crossChainClientCreationContexts[crossChainClientCreationContext.RemoteChainId] = + crossChainClientCreationContext; + } - public void SetClientConnected(int chainId, bool isConnected) - { - _clientConnected[chainId] = isConnected; - } + public bool TryGetCrossChainClientCreationContext(int chainId, + out CrossChainClientCreationContext crossChainClientCreationContext) + { + return _crossChainClientCreationContexts.TryGetValue(chainId, out crossChainClientCreationContext); + } - public Hash GetBlockHashByHeight(long height) - { - var dict = CreateDict(); - return dict.TryGetValue(height, out var hash) ? hash : null; - } - public bool TryGetHeightByHash(Hash hash, out long height) - { - height = 0; - var dict = CreateDict(); - if (dict.All(kv => kv.Value != hash)) return false; - height = dict.First(kv => kv.Value == hash).Key; - return true; - } - - private Dictionary CreateDict() + public bool CheckClientConnected(int chainId) + { + return _clientConnected.TryGetValue(chainId, out var res) && res; + } + + public void SetClientConnected(int chainId, bool isConnected) + { + _clientConnected[chainId] = isConnected; + } + + public Hash GetBlockHashByHeight(long height) + { + var dict = CreateDict(); + return dict.TryGetValue(height, out var hash) ? hash : null; + } + + public bool TryGetHeightByHash(Hash hash, out long height) + { + height = 0; + var dict = CreateDict(); + if (dict.All(kv => kv.Value != hash)) return false; + height = dict.First(kv => kv.Value == hash).Key; + return true; + } + + private Dictionary CreateDict() + { + return new Dictionary { - return new Dictionary + { 1, HashHelper.ComputeFrom("1") }, + { 2, HashHelper.ComputeFrom("2") }, { - {1, HashHelper.ComputeFrom("1")}, - {2, HashHelper.ComputeFrom("2")}, - { - 3, - BinaryMerkleTree - .FromLeafNodes( - IndexedSideChainBlockData.SideChainBlockDataList.Select(scb => - scb.TransactionStatusMerkleTreeRoot)).Root - } - }; - } + 3, + BinaryMerkleTree + .FromLeafNodes( + IndexedSideChainBlockData.SideChainBlockDataList.Select(scb => + scb.TransactionStatusMerkleTreeRoot)).Root + } + }; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestModule.cs b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestModule.cs index 4427ce8e9b..fecca48fee 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestModule.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainCommunicationTestModule.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Communication.Infrastructure; using AElf.CrossChain.Indexing.Application; using AElf.CrossChain.Indexing.Infrastructure; @@ -11,195 +9,198 @@ using AElf.Kernel.Consensus.Application; using AElf.Kernel.SmartContract; using AElf.Modularity; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +[DependsOn(typeof(CrossChainCoreModule), + typeof(SmartContractAElfModule), + typeof(KernelCoreTestAElfModule))] +public class CrossChainCommunicationTestModule : AElfModule { - [DependsOn(typeof(CrossChainCoreModule), - typeof(SmartContractAElfModule), - typeof(KernelCoreTestAElfModule))] - public class CrossChainCommunicationTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + base.ConfigureServices(context); + context.Services.AddSingleton(); + + Configure(option => { - base.ConfigureServices(context); - context.Services.AddSingleton(); + option.ParentChainId = ChainHelper.ConvertChainIdToBase58(ChainHelper.GetChainId(1)); + }); - Configure(option => + context.Services.AddTransient(provider => + { + var kernelTestHelper = context.Services.GetRequiredServiceLazy(); + var crossChainCommunicationTestHelper = + context.Services.GetRequiredServiceLazy().Value; + var mockBlockChainService = new Mock(); + mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => { - option.ParentChainId = ChainHelper.ConvertChainIdToBase58(ChainHelper.GetChainId(1)); + var chain = new Chain { LastIrreversibleBlockHeight = 10 }; + return Task.FromResult(chain); }); - - context.Services.AddTransient(provider => + mockBlockChainService.Setup(m => + m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((chain, height, hash) => + Task.FromResult(crossChainCommunicationTestHelper.GetBlockHashByHeight(height))); + mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => { - var kernelTestHelper = context.Services.GetRequiredServiceLazy(); - var crossChainCommunicationTestHelper = - context.Services.GetRequiredServiceLazy().Value; - var mockBlockChainService = new Mock(); - mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => - { - var chain = new Chain {LastIrreversibleBlockHeight = 10}; - return Task.FromResult(chain); - }); - mockBlockChainService.Setup(m => - m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns((chain, height, hash) => - Task.FromResult(crossChainCommunicationTestHelper.GetBlockHashByHeight(height))); - mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => - { - if (!crossChainCommunicationTestHelper.TryGetHeightByHash(hash, out var height)) - return Task.FromResult(null); - var block = kernelTestHelper.Value.GenerateBlock(height - 1, - crossChainCommunicationTestHelper.GetBlockHashByHeight(height - 1)); - return Task.FromResult(block); - }); - return mockBlockChainService.Object; + if (!crossChainCommunicationTestHelper.TryGetHeightByHash(hash, out var height)) + return Task.FromResult(null); + var block = kernelTestHelper.Value.GenerateBlock(height - 1, + crossChainCommunicationTestHelper.GetBlockHashByHeight(height - 1)); + return Task.FromResult(block); }); + return mockBlockChainService.Object; + }); - context.Services.AddTransient(provider => - { - var crossChainCommunicationTestHelper = - context.Services.GetRequiredServiceLazy().Value; - var mockBlockExtraDataService = new Mock(); - mockBlockExtraDataService - .Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny(), It.IsAny())).Returns( - () => + context.Services.AddTransient(provider => + { + var crossChainCommunicationTestHelper = + context.Services.GetRequiredServiceLazy().Value; + var mockBlockExtraDataService = new Mock(); + mockBlockExtraDataService + .Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny(), It.IsAny())).Returns( + () => + { + var crossExtraData = new CrossChainExtraData { - var crossExtraData = new CrossChainExtraData - { - TransactionStatusMerkleTreeRoot = BinaryMerkleTree - .FromLeafNodes( - crossChainCommunicationTestHelper.IndexedSideChainBlockData - .SideChainBlockDataList.Select(scb => scb.TransactionStatusMerkleTreeRoot)) - .Root, - }; - return ByteString.CopyFrom(crossExtraData.ToByteArray()); - }); - return mockBlockExtraDataService.Object; - }); + TransactionStatusMerkleTreeRoot = BinaryMerkleTree + .FromLeafNodes( + crossChainCommunicationTestHelper.IndexedSideChainBlockData + .SideChainBlockDataList.Select(scb => scb.TransactionStatusMerkleTreeRoot)) + .Root + }; + return ByteString.CopyFrom(crossExtraData.ToByteArray()); + }); + return mockBlockExtraDataService.Object; + }); + + context.Services.AddTransient(provider => + { + var crossChainCommunicationTestHelper = + context.Services.GetRequiredServiceLazy().Value; - context.Services.AddTransient(provider => - { - var crossChainCommunicationTestHelper = - context.Services.GetRequiredServiceLazy().Value; + var mockCrossChainIndexingDataService = new Mock(); + var irreversibleBlockStateProvider = + context.Services.GetRequiredServiceLazy(); - var mockCrossChainIndexingDataService = new Mock(); - var irreversibleBlockStateProvider = - context.Services.GetRequiredServiceLazy(); + mockCrossChainIndexingDataService.Setup(service => service.GetNonIndexedBlockAsync(It.IsAny())) + .Returns(async height => await irreversibleBlockStateProvider.Value + .GetNotIndexedIrreversibleBlockByHeightAsync(height)); - mockCrossChainIndexingDataService.Setup(service => service.GetNonIndexedBlockAsync(It.IsAny())) - .Returns(async height => await irreversibleBlockStateProvider.Value - .GetNotIndexedIrreversibleBlockByHeightAsync(height)); + mockCrossChainIndexingDataService + .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny(), It.IsAny())).Returns( + () => + { + var indexedSideChainBlockData = crossChainCommunicationTestHelper.IndexedSideChainBlockData; + return Task.FromResult(indexedSideChainBlockData); + }); + return mockCrossChainIndexingDataService.Object; + }); - mockCrossChainIndexingDataService - .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny(), It.IsAny())).Returns( - () => + context.Services.AddTransient(provider => + { + var crossChainCommunicationTestHelper = + context.Services.GetRequiredServiceLazy().Value; + var mockCrossChainClientProvider = new Mock(); + ICrossChainClient client; + mockCrossChainClientProvider + .Setup(m => m.TryGetClient(It.IsAny(), out client)) + .Callback(new TryGetClientCallback((int chainId, out ICrossChainClient crossChainClient) => + { + if (!crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _)) + { + crossChainClient = null; + return; + } + + var isConnected = crossChainCommunicationTestHelper.CheckClientConnected(chainId); + crossChainClient = MockCrossChainClient(chainId, isConnected, + entity => { - var indexedSideChainBlockData = crossChainCommunicationTestHelper.IndexedSideChainBlockData; - return Task.FromResult(indexedSideChainBlockData); + crossChainCommunicationTestHelper.SetClientConnected(-1, true); + return true; }); - return mockCrossChainIndexingDataService.Object; - }); + })) + .Returns((chainId, client) => + crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _)); + + mockCrossChainClientProvider + .Setup(c => c.AddOrUpdateClient(It.IsAny())) + .Returns( + crossChainClientCreationContext => CreateAndAddClient(crossChainCommunicationTestHelper, + crossChainClientCreationContext)); + + mockCrossChainClientProvider.Setup(c => + c.CreateChainInitializationDataClient(It.IsAny())) + .Returns( + crossChainClientCreationContext => + CreateAndAddClient(crossChainCommunicationTestHelper, crossChainClientCreationContext)); + return mockCrossChainClientProvider.Object; + }); + + context.Services.AddSingleton(); + } - context.Services.AddTransient(provider => + private ICrossChainClient MockCrossChainClient(int remoteChainId, bool isConnected, + Func func) + { + var mockCrossChainClient = new Mock(); + mockCrossChainClient.Setup(c => c.RemoteChainId) + .Returns(() => remoteChainId); + mockCrossChainClient.Setup(c => c.IsConnected) + .Returns(() => isConnected); + mockCrossChainClient.Setup(m => m.RequestChainInitializationDataAsync(It.IsAny())).Returns( + () => { - var crossChainCommunicationTestHelper = - context.Services.GetRequiredServiceLazy().Value; - var mockCrossChainClientProvider = new Mock(); - ICrossChainClient client; - mockCrossChainClientProvider - .Setup(m => m.TryGetClient(It.IsAny(), out client)) - .Callback(new TryGetClientCallback((int chainId, out ICrossChainClient crossChainClient) => - { - if (!crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _)) - { - crossChainClient = null; - return; - } - - bool isConnected = crossChainCommunicationTestHelper.CheckClientConnected(chainId); - crossChainClient = MockCrossChainClient(chainId, isConnected, - entity => - { - crossChainCommunicationTestHelper.SetClientConnected(-1, true); - return true; - }); - })) - .Returns((chainId, client) => - crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _)); - - mockCrossChainClientProvider - .Setup(c => c.AddOrUpdateClient(It.IsAny())) - .Returns( - crossChainClientCreationContext => CreateAndAddClient(crossChainCommunicationTestHelper, crossChainClientCreationContext)); - - mockCrossChainClientProvider.Setup(c => - c.CreateChainInitializationDataClient(It.IsAny())).Returns( - crossChainClientCreationContext => CreateAndAddClient(crossChainCommunicationTestHelper, crossChainClientCreationContext)); - return mockCrossChainClientProvider.Object; + var chainInitialization = new ChainInitializationData + { + CreationHeightOnParentChain = 1 + }; + return Task.FromResult(chainInitialization); }); + mockCrossChainClient.Setup(m => + m.RequestCrossChainDataAsync(It.IsAny(), + It.IsAny>())) + .Returns(() => + { + func(new ParentChainBlockData()); + return Task.CompletedTask; + }); + mockCrossChainClient.Setup(c => c.ConnectAsync()).Returns(() => Task.CompletedTask); + return mockCrossChainClient.Object; + } - context.Services.AddSingleton(); - } - - delegate void TryGetClientCallback(int chainId, out ICrossChainClient crossChainClient); - - public class MockConsensusExtraDataProvider : IConsensusExtraDataProvider - { - public Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) + private ICrossChainClient CreateAndAddClient(CrossChainCommunicationTestHelper crossChainCommunicationTestHelper, + CrossChainClientCreationContext crossChainClientCreationContext) + { + crossChainCommunicationTestHelper.AddNewCrossChainClient(crossChainClientCreationContext); + var isConnected = + crossChainCommunicationTestHelper.CheckClientConnected(crossChainClientCreationContext + .RemoteChainId); + return MockCrossChainClient(crossChainClientCreationContext.RemoteChainId, isConnected, + entity => { - throw new NotImplementedException(); - } + crossChainCommunicationTestHelper.SetClientConnected(-1, true); + return true; + }); + } - public string BlockHeaderExtraDataKey => "Consensus"; - } + private delegate void TryGetClientCallback(int chainId, out ICrossChainClient crossChainClient); - private ICrossChainClient MockCrossChainClient(int remoteChainId, bool isConnected, - Func func) + public class MockConsensusExtraDataProvider : IConsensusExtraDataProvider + { + public Task GetBlockHeaderExtraDataAsync(BlockHeader blockHeader) { - var mockCrossChainClient = new Mock(); - mockCrossChainClient.Setup(c => c.RemoteChainId) - .Returns(() => remoteChainId); - mockCrossChainClient.Setup(c => c.IsConnected) - .Returns(() => isConnected); - mockCrossChainClient.Setup(m => m.RequestChainInitializationDataAsync(It.IsAny())).Returns( - () => - { - var chainInitialization = new ChainInitializationData - { - CreationHeightOnParentChain = 1, - }; - return Task.FromResult(chainInitialization); - }); - mockCrossChainClient.Setup(m => - m.RequestCrossChainDataAsync(It.IsAny(), - It.IsAny>())) - .Returns(() => - { - func(new ParentChainBlockData()); - return Task.CompletedTask; - }); - mockCrossChainClient.Setup(c => c.ConnectAsync()).Returns(() => Task.CompletedTask); - return mockCrossChainClient.Object; + throw new NotImplementedException(); } - private ICrossChainClient CreateAndAddClient(CrossChainCommunicationTestHelper crossChainCommunicationTestHelper, - CrossChainClientCreationContext crossChainClientCreationContext) - { - crossChainCommunicationTestHelper.AddNewCrossChainClient(crossChainClientCreationContext); - bool isConnected = - crossChainCommunicationTestHelper.CheckClientConnected(crossChainClientCreationContext - .RemoteChainId); - return MockCrossChainClient(crossChainClientCreationContext.RemoteChainId, isConnected, - entity => - { - crossChainCommunicationTestHelper.SetClientConnected(-1, true); - return true; - }); - } + public string BlockHeaderExtraDataKey => "Consensus"; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainIndexingDataValidationServiceTests.cs b/test/AElf.CrossChain.Core.Tests/CrossChainIndexingDataValidationServiceTests.cs index 0ad7232719..c39cd4f34a 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainIndexingDataValidationServiceTests.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainIndexingDataValidationServiceTests.cs @@ -1,440 +1,423 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Indexing.Application; +using AElf.Standards.ACS7; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainIndexingDataValidationServiceTests : CrossChainTestBase { - public class CrossChainIndexingDataValidationServiceTests : CrossChainTestBase + private readonly ICrossChainIndexingDataValidationService _crossChainIndexingDataValidationService; + private readonly CrossChainTestHelper _crossChainTestHelper; + + public CrossChainIndexingDataValidationServiceTests() + { + _crossChainTestHelper = GetRequiredService(); + _crossChainIndexingDataValidationService = GetRequiredService(); + } + + [Fact] + public async Task Validate_WithoutEmptyInput_Test() { - private readonly CrossChainTestHelper _crossChainTestHelper; - private readonly ICrossChainIndexingDataValidationService _crossChainIndexingDataValidationService; + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + for (var i = 0; i <= CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new SideChainBlockData + { + Height = 1 + i, + ChainId = chainId + }); + + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + + var crossChainBlockData = new CrossChainBlockData(); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.True(res); + } + - public CrossChainIndexingDataValidationServiceTests() + [Fact] + public async Task ValidateSideChainBlock_WithCaching_Test() + { + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List { - _crossChainTestHelper = GetRequiredService(); - _crossChainIndexingDataValidationService = GetRequiredService(); - } + new SideChainBlockData + { ChainId = chainId, Height = 1, TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") } + }; + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); + + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); - [Fact] - public async Task Validate_WithoutEmptyInput_Test() + + var crossChainBlockData = FakeCrossChainBlockData(new[] { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - for (int i = 0; i <= CrossChainConstants.DefaultBlockCacheEntityCount; i++) + new SideChainBlockData { - blockInfoCache.Add(new SideChainBlockData - { - Height = 1 + i, - ChainId = chainId - }); + ChainId = chainId, + Height = 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") } + }, new ParentChainBlockData[0]); - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - - var crossChainBlockData = new CrossChainBlockData(); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); - Assert.True(res); - } + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.True(res); + } + [Fact] + public async Task ValidateSideChainBlock_WithoutCaching_Test() + { + var chainId = _chainOptions.ChainId; - [Fact] - public async Task ValidateSideChainBlock_WithCaching_Test() + var list = new List { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List + new() { - new SideChainBlockData - {ChainId = chainId, Height = 1, TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1")} - }; - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); + ChainId = chainId, + Height = 1 + } + }; + var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); + [Fact] + public async Task ValidateSideChainBlock_WithWrongBlockIndex_Test() + { + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List + { + new SideChainBlockData { ChainId = chainId, Height = 1 } + }; - var crossChainBlockData = FakeCrossChainBlockData(new[] + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); + var list = new List + { + new() { - new SideChainBlockData - { - ChainId = chainId, - Height = 1, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("1") - } - }, new ParentChainBlockData[0]); + ChainId = chainId, + Height = 2 + } + }; + var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); - Assert.True(res); - } - [Fact] - public async Task ValidateSideChainBlock_WithoutCaching_Test() - { - int chainId = _chainOptions.ChainId; + [Fact] + public async Task ValidateSideChainBlock__NotEnoughCaching_Test() + { + var chainId = _chainOptions.ChainId; + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); - var list = new List + var list = new List + { + new() { - new SideChainBlockData - { - ChainId = chainId, - Height = 1 - } - }; - var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); - Assert.False(res); - } + ChainId = chainId, + Height = 1 + } + }; + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { list } + }; + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } - [Fact] - public async Task ValidateSideChainBlock_WithWrongBlockIndex_Test() + [Fact] + public async Task ValidateSideChainBlock__NotExpected_Test() + { + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List + new SideChainBlockData { - new SideChainBlockData {ChainId = chainId, Height = 1} - }; + ChainId = chainId, + Height = 1, + BlockHeaderHash = HashHelper.ComputeFrom("blockHash") + } + }; + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); - var list = new List + var list = new List + { + new() { - new SideChainBlockData - { - ChainId = chainId, - Height = 2 - } - }; - var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); - Assert.False(res); - } - + ChainId = chainId, + Height = 1, + BlockHeaderHash = HashHelper.ComputeFrom("Block") + } + }; + var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } - [Fact] - public async Task ValidateSideChainBlock__NotEnoughCaching_Test() - { - int chainId = _chainOptions.ChainId; - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 1); + [Fact] + public async Task TryTwice_ValidateSideChainBlock_Test() + { + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); - var list = new List - { - new SideChainBlockData - { - ChainId = chainId, - Height = 1 - } - }; - var crossChainBlockData = new CrossChainBlockData + var cachingCount = CrossChainConstants.DefaultBlockCacheEntityCount * 2; + for (var i = 0; i <= cachingCount; i++) + blockInfoCache.Add(new SideChainBlockData { - SideChainBlockDataList = {list} - }; - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); - Assert.False(res); - } + ChainId = chainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) + }); - - [Fact] - public async Task ValidateSideChainBlock__NotExpected_Test() + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List - { - new SideChainBlockData + var list = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + list.Add(new SideChainBlockData { ChainId = chainId, - Height = 1, - BlockHeaderHash = HashHelper.ComputeFrom("blockHash") - } - }; - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - - var list = new List - { - new SideChainBlockData - { - ChainId = chainId, - Height = 1, - BlockHeaderHash = HashHelper.ComputeFrom("Block") - } - }; + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) + }); + var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, Hash.Empty, 1); - Assert.False(res); + Assert.True(res); } - - [Fact] - public async Task TryTwice_ValidateSideChainBlock_Test() { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); - - var cachingCount = CrossChainConstants.DefaultBlockCacheEntityCount * 2; - for (int i = 0; i <= cachingCount; i++) - { - blockInfoCache.Add(new SideChainBlockData() + var list = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + list.Add(new SideChainBlockData { ChainId = chainId, - Height = (i + 1), + Height = i + 1, TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) }); - } - - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - { - var list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - list.Add(new SideChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) - }); - } - - var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 1); - Assert.True(res); - } - { - var list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - list.Add(new SideChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) - }); - } - - var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 2); - Assert.True(res); - } - } - - [Fact] - public async Task ValidateParentChainBlock_WithoutProvidedData_Test() - { - int chainId = _chainOptions.ChainId; - _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); - var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], new ParentChainBlockData[0]); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, - Hash.Empty, 1); + var crossChainBlockData = FakeCrossChainBlockData(list, new ParentChainBlockData[0]); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 2); Assert.True(res); } + } - [Fact] - public async Task ValidateParentChainBlock_WithCaching_Test() - { - int chainId = _chainOptions.ChainId; - _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); - - var blockInfoCache = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - blockInfoCache.Add(new ParentChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i + 1) - }); - } + [Fact] + public async Task ValidateParentChainBlock_WithoutProvidedData_Test() + { + var chainId = _chainOptions.ChainId; + _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); + + var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], new ParentChainBlockData[0]); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.True(res); + } - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); + [Fact] + public async Task ValidateParentChainBlock_WithCaching_Test() + { + var chainId = _chainOptions.ChainId; + _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); + var blockInfoCache = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new ParentChainBlockData { - var list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - list.Add(new ParentChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i) - }); - } - - var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 1); - res.ShouldBeFalse(); - } - - { - var list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - list.Add(new ParentChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i + 1) - }); - } - - var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 1); - Assert.True(res); - } - } + ChainId = chainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i + 1) + }); - [Fact] - public async Task ValidateParentChainBlock_WithoutCaching_Test() - { - int parentChainId = _chainOptions.ChainId; - _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + { var list = new List(); - for (int i = 0; i <= CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) list.Add(new ParentChainBlockData { - ChainId = parentChainId, - Height = (i + 1) + ChainId = chainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i) }); - } var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, Hash.Empty, 1); - Assert.False(res); + res.ShouldBeFalse(); } - [Fact] - public async Task ValidateParentChainBlock_WithWrongIndex_Test() { - int chainId = _chainOptions.ChainId; - _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); - var blockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount; i++) - { - blockInfoCache.Add(new ParentChainBlockData + var list = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + list.Add(new ParentChainBlockData { ChainId = chainId, - Height = (i + 1) + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i + 1) }); - } - - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - var list = new List - { - new ParentChainBlockData - {ChainId = chainId, Height = 2} - }; var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync(crossChainBlockData, + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, Hash.Empty, 1); - Assert.False(res); + Assert.True(res); } + } - [Fact] - public async Task TryTwice_ValidateParentChainBlock_Test() - { - int chainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); + [Fact] + public async Task ValidateParentChainBlock_WithoutCaching_Test() + { + var parentChainId = _chainOptions.ChainId; + _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); - var cachingCount = CrossChainConstants.DefaultBlockCacheEntityCount * 2; - for (int i = 0; i <= cachingCount; i++) + var list = new List(); + for (var i = 0; i <= CrossChainConstants.DefaultBlockCacheEntityCount; i++) + list.Add(new ParentChainBlockData { - blockInfoCache.Add(new ParentChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) - }); - } + ChainId = parentChainId, + Height = i + 1 + }); + + var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } - var list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task ValidateParentChainBlock_WithWrongIndex_Test() + { + var chainId = _chainOptions.ChainId; + _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); + var blockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount; i++) + blockInfoCache.Add(new ParentChainBlockData { + ChainId = chainId, + Height = i + 1 + }); + + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + + var list = new List + { + new() { ChainId = chainId, Height = 2 } + }; + var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + Assert.False(res); + } + + [Fact] + public async Task TryTwice_ValidateParentChainBlock_Test() + { + var chainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + _crossChainTestHelper.AddFakeParentChainIdHeight(chainId, 0); + + var cachingCount = CrossChainConstants.DefaultBlockCacheEntityCount * 2; + for (var i = 0; i <= cachingCount; i++) + blockInfoCache.Add(new ParentChainBlockData + { + ChainId = chainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) + }); + + var list = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) + list.Add(new ParentChainBlockData + { + ChainId = chainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) + }); + + var fakeCache = new Dictionary> { { chainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + { + var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 1); + list = new List(); + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) list.Add(new ParentChainBlockData { ChainId = chainId, - Height = (i + 1), + Height = i + 1, TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) }); - } - var fakeCache = new Dictionary> {{chainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - { - var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 1); - list = new List(); - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - list.Add(new ParentChainBlockData - { - ChainId = chainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((i + 1).ToString()) - }); - } - - Assert.True(res); - } - { - var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); - var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( - crossChainBlockData, - Hash.Empty, 2); - Assert.True(res); - } + Assert.True(res); } - - [Fact] - public void CrossChainRequestExceptionTest() { - var message = "message"; - Should.Throw(() => throw new CrossChainRequestException(message)); - Should.Throw(() => - throw new CrossChainRequestException(message, new Exception())); + var crossChainBlockData = FakeCrossChainBlockData(new SideChainBlockData[0], list); + var res = await _crossChainIndexingDataValidationService.ValidateCrossChainIndexingDataAsync( + crossChainBlockData, + Hash.Empty, 2); + Assert.True(res); } + } + + [Fact] + public void CrossChainRequestExceptionTest() + { + var message = "message"; + Should.Throw(() => throw new CrossChainRequestException(message)); + Should.Throw(() => + throw new CrossChainRequestException(message, new Exception())); + } - private CrossChainBlockData FakeCrossChainBlockData(IEnumerable sideChainBlockDataList, - IEnumerable parentChainBlockDataList) + private CrossChainBlockData FakeCrossChainBlockData(IEnumerable sideChainBlockDataList, + IEnumerable parentChainBlockDataList) + { + return new CrossChainBlockData { - return new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockDataList}, - ParentChainBlockDataList = {parentChainBlockDataList} - }; - } + SideChainBlockDataList = { sideChainBlockDataList }, + ParentChainBlockDataList = { parentChainBlockDataList } + }; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainTestBase.cs b/test/AElf.CrossChain.Core.Tests/CrossChainTestBase.cs index a42e3a1bb6..215f7dda67 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainTestBase.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainTestBase.cs @@ -6,42 +6,36 @@ using AElf.TestBase; using Microsoft.Extensions.Options; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainTestBase : AElfIntegratedTest { - public class CrossChainTestBase : AElfIntegratedTest - { - protected ICrossChainCacheEntityProvider CrossChainCacheEntityProvider; - protected IBlockCacheEntityProducer BlockCacheEntityProducer; - protected CrossChainConfigOptions _configOptions; - protected ChainOptions _chainOptions; + protected ChainOptions _chainOptions; + protected CrossChainConfigOptions _configOptions; + protected IBlockCacheEntityProducer BlockCacheEntityProducer; + protected ICrossChainCacheEntityProvider CrossChainCacheEntityProvider; - public CrossChainTestBase() - { - CrossChainCacheEntityProvider = GetRequiredService(); - BlockCacheEntityProducer = GetRequiredService(); - _configOptions = GetRequiredService>().CurrentValue; - _chainOptions = GetRequiredService>().Value; - _configOptions.CrossChainDataValidationIgnored = false; - } + public CrossChainTestBase() + { + CrossChainCacheEntityProvider = GetRequiredService(); + BlockCacheEntityProducer = GetRequiredService(); + _configOptions = GetRequiredService>().CurrentValue; + _chainOptions = GetRequiredService>().Value; + _configOptions.CrossChainDataValidationIgnored = false; + } - protected void CreateFakeCache(Dictionary cachingData) - { - foreach (var (key, value) in cachingData) - { - CrossChainCacheEntityProvider.AddChainCacheEntity(key, value.TargetChainHeight()); - } - } + protected void CreateFakeCache(Dictionary cachingData) + { + foreach (var (key, value) in cachingData) + CrossChainCacheEntityProvider.AddChainCacheEntity(key, value.TargetChainHeight()); + } - protected void AddFakeCacheData(Dictionary> fakeCache) + protected void AddFakeCacheData(Dictionary> fakeCache) + { + foreach (var (crossChainId, blockInfos) in fakeCache) { - foreach (var (crossChainId, blockInfos) in fakeCache) - { - CrossChainCacheEntityProvider.AddChainCacheEntity(crossChainId, blockInfos.First().Height); - foreach (var blockInfo in blockInfos) - { - BlockCacheEntityProducer.TryAddBlockCacheEntity(blockInfo); - } - } + CrossChainCacheEntityProvider.AddChainCacheEntity(crossChainId, blockInfos.First().Height); + foreach (var blockInfo in blockInfos) BlockCacheEntityProducer.TryAddBlockCacheEntity(blockInfo); } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainTestHelper.cs b/test/AElf.CrossChain.Core.Tests/CrossChainTestHelper.cs index 9dfd126ec7..3071ee547e 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainTestHelper.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainTestHelper.cs @@ -1,151 +1,145 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS7; using AElf.Contracts.CrossChain; using AElf.Kernel; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Shouldly; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainTestHelper { - public class CrossChainTestHelper + private readonly Dictionary _indexedCrossChainBlockData = new(); + private readonly Dictionary _parentChainIdHeight = new(); + private readonly Dictionary _sideChainIdHeights = new(); + + private readonly GetIndexingProposalStatusOutput _pendingCrossChainIndexingProposalOutput = new(); + + public long FakeLibHeight { get; private set; } + + public void AddFakeSideChainIdHeight(int sideChainId, long height) + { + _sideChainIdHeights.Add(sideChainId, height); + } + + public void AddFakeParentChainIdHeight(int parentChainId, long height) { - private readonly Dictionary _sideChainIdHeights = new Dictionary(); - private readonly Dictionary _parentChainIdHeight = new Dictionary(); - - private GetIndexingProposalStatusOutput _pendingCrossChainIndexingProposalOutput = - new GetIndexingProposalStatusOutput(); - - public long FakeLibHeight { get; private set;} - private readonly Dictionary _indexedCrossChainBlockData = new Dictionary(); - - public void AddFakeSideChainIdHeight(int sideChainId, long height) + _parentChainIdHeight.Add(parentChainId, height); + } + + internal void AddFakeIndexedCrossChainBlockData(long height, CrossChainBlockData crossChainBlockData) + { + _indexedCrossChainBlockData.Add(height, crossChainBlockData); + } + + internal void AddFakePendingCrossChainIndexingProposal(int chainId, + PendingChainIndexingProposalStatus pendingCrossChainIndexingProposalOutput) + { + _pendingCrossChainIndexingProposalOutput.ChainIndexingProposalStatus[chainId] = + pendingCrossChainIndexingProposalOutput; + } + + public TransactionTrace CreateFakeTransactionTrace(Transaction transaction) + { + var methodName = transaction.MethodName; + + var trace = new TransactionTrace { - _sideChainIdHeights.Add(sideChainId, height); - } + TransactionId = transaction.GetHash(), + ExecutionStatus = ExecutionStatus.Executed + }; + var returnValue = CreateFakeReturnValue(trace, transaction, methodName); + if (returnValue == null) + trace.ExecutionStatus = ExecutionStatus.ContractError; + else + trace.ReturnValue = ByteString.CopyFrom(returnValue); - public void AddFakeParentChainIdHeight(int parentChainId, long height) + return trace; + } + + private byte[] CreateFakeReturnValue(TransactionTrace trace, Transaction transaction, string methodName) + { + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetParentChainId)) { - _parentChainIdHeight.Add(parentChainId, height); + var parentChainId = _parentChainIdHeight.Keys.FirstOrDefault(); + if (parentChainId != 0) + return new Int32Value { Value = parentChainId }.ToByteArray(); + trace.ExecutionStatus = ExecutionStatus.ContractError; + return null; } - internal void AddFakeIndexedCrossChainBlockData(long height, CrossChainBlockData crossChainBlockData) + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetParentChainHeight)) + return _parentChainIdHeight.Count == 0 + ? null + : new Int64Value { Value = _parentChainIdHeight.Values.First() }.ToByteArray(); + + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetSideChainHeight)) { - _indexedCrossChainBlockData.Add(height, crossChainBlockData); + var sideChainId = Int32Value.Parser.ParseFrom(transaction.Params).Value; + var exist = _sideChainIdHeights.TryGetValue(sideChainId, out var sideChainHeight); + if (exist) + return new Int64Value { Value = sideChainHeight }.ToByteArray(); + trace.ExecutionStatus = ExecutionStatus.ContractError; + return new Int64Value().ToByteArray(); } - internal void AddFakePendingCrossChainIndexingProposal(int chainId, PendingChainIndexingProposalStatus pendingCrossChainIndexingProposalOutput) + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetAllChainsIdAndHeight)) { - _pendingCrossChainIndexingProposalOutput.ChainIndexingProposalStatus[chainId] = - pendingCrossChainIndexingProposalOutput; + var dict = new ChainIdAndHeightDict(); + dict.IdHeightDict.Add(_sideChainIdHeights); + dict.IdHeightDict.Add(_parentChainIdHeight); + return dict.ToByteArray(); } - public TransactionTrace CreateFakeTransactionTrace(Transaction transaction) + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetSideChainIdAndHeight)) { - string methodName = transaction.MethodName; - - var trace = new TransactionTrace - { - TransactionId = transaction.GetHash(), - ExecutionStatus = ExecutionStatus.Executed, - }; - var returnValue = CreateFakeReturnValue(trace, transaction, methodName); - if (returnValue == null) - trace.ExecutionStatus = ExecutionStatus.ContractError; - else - trace.ReturnValue = ByteString.CopyFrom(returnValue); - - return trace; + var dict = new ChainIdAndHeightDict(); + dict.IdHeightDict.Add(_sideChainIdHeights); + return dict.ToByteArray(); } - private byte[] CreateFakeReturnValue(TransactionTrace trace, Transaction transaction, string methodName) + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub + .GetIndexedSideChainBlockDataByHeight)) { - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetParentChainId)) + var height = Int64Value.Parser.ParseFrom(transaction.Params).Value; + if (_indexedCrossChainBlockData.TryGetValue(height, out var crossChainBlockData)) { - var parentChainId = _parentChainIdHeight.Keys.FirstOrDefault(); - if (parentChainId != 0) - return new Int32Value {Value = parentChainId}.ToByteArray(); - trace.ExecutionStatus = ExecutionStatus.ContractError; - return null; - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetParentChainHeight)) - { - return _parentChainIdHeight.Count == 0 - ? null - : new Int64Value {Value = _parentChainIdHeight.Values.First()}.ToByteArray(); - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetSideChainHeight)) - { - int sideChainId = Int32Value.Parser.ParseFrom(transaction.Params).Value; - var exist = _sideChainIdHeights.TryGetValue(sideChainId, out var sideChainHeight); - if (exist) - return new Int64Value{Value = sideChainHeight}.ToByteArray(); - trace.ExecutionStatus = ExecutionStatus.ContractError; - return new Int64Value().ToByteArray(); - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetAllChainsIdAndHeight)) - { - var dict = new ChainIdAndHeightDict(); - dict.IdHeightDict.Add(_sideChainIdHeights); - dict.IdHeightDict.Add(_parentChainIdHeight); - return dict.ToByteArray(); - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetSideChainIdAndHeight)) - { - var dict = new ChainIdAndHeightDict(); - dict.IdHeightDict.Add(_sideChainIdHeights); - return dict.ToByteArray(); - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetIndexedSideChainBlockDataByHeight)) - { - long height = Int64Value.Parser.ParseFrom(transaction.Params).Value; - if (_indexedCrossChainBlockData.TryGetValue(height, out var crossChainBlockData)) - { - var indexedSideChainBlockData = new IndexedSideChainBlockData - { - SideChainBlockDataList = {crossChainBlockData.SideChainBlockDataList} - }; - return indexedSideChainBlockData.ToByteArray(); - } - - trace.ExecutionStatus = ExecutionStatus.ContractError; - return new IndexedSideChainBlockData().ToByteArray(); - } - - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub.GetSideChainIndexingInformationList)) - { - var sideChainIndexingInformationList = new SideChainIndexingInformationList(); - foreach (var kv in _sideChainIdHeights) + var indexedSideChainBlockData = new IndexedSideChainBlockData { - sideChainIndexingInformationList.IndexingInformationList.Add(new SideChainIndexingInformation - { - ChainId = kv.Key, - IndexedHeight = kv.Value - }); - } - - return sideChainIndexingInformationList.ToByteArray(); + SideChainBlockDataList = { crossChainBlockData.SideChainBlockDataList } + }; + return indexedSideChainBlockData.ToByteArray(); } - if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub - .GetIndexingProposalStatus)) - { - return _pendingCrossChainIndexingProposalOutput?.ToByteArray(); - } - - return new byte[0]; + trace.ExecutionStatus = ExecutionStatus.ContractError; + return new IndexedSideChainBlockData().ToByteArray(); } - - public void SetFakeLibHeight(long height) + + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub + .GetSideChainIndexingInformationList)) { - FakeLibHeight = height; + var sideChainIndexingInformationList = new SideChainIndexingInformationList(); + foreach (var kv in _sideChainIdHeights) + sideChainIndexingInformationList.IndexingInformationList.Add(new SideChainIndexingInformation + { + ChainId = kv.Key, + IndexedHeight = kv.Value + }); + + return sideChainIndexingInformationList.ToByteArray(); } + + if (methodName == nameof(CrossChainContractImplContainer.CrossChainContractImplStub + .GetIndexingProposalStatus)) + return _pendingCrossChainIndexingProposalOutput?.ToByteArray(); + + return new byte[0]; + } + + public void SetFakeLibHeight(long height) + { + FakeLibHeight = height; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/CrossChainTestModule.cs b/test/AElf.CrossChain.Core.Tests/CrossChainTestModule.cs index 9783705be7..b6831bee0b 100644 --- a/test/AElf.CrossChain.Core.Tests/CrossChainTestModule.cs +++ b/test/AElf.CrossChain.Core.Tests/CrossChainTestModule.cs @@ -4,119 +4,118 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Modularity; -using Google.Protobuf.WellKnownTypes; using AElf.Types; +using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +[DependsOn( + typeof(CoreKernelAElfModule), + typeof(CrossChainCoreModule), + typeof(KernelAElfModule), + typeof(KernelCoreTestAElfModule) +)] +public class CrossChainTestModule : AElfModule { - [DependsOn( - typeof(CoreKernelAElfModule), - typeof(CrossChainCoreModule), - typeof(KernelAElfModule), - typeof(KernelCoreTestAElfModule) - )] - public class CrossChainTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var dictionary = new Dictionary { - var dictionary = new Dictionary - { - {1, HashHelper.ComputeFrom("1")}, - {2, HashHelper.ComputeFrom("2")}, - {3, HashHelper.ComputeFrom("3")} - }; - - Configure(option => { option.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); + { 1, HashHelper.ComputeFrom("1") }, + { 2, HashHelper.ComputeFrom("2") }, + { 3, HashHelper.ComputeFrom("3") } + }; - //context.Services.AddTransient(); - context.Services.AddSingleton(); - context.Services.AddTransient(provider => - { - var mockTransactionReadOnlyExecutionService = new Mock(); - mockTransactionReadOnlyExecutionService - .Setup(m => m.ExecuteAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((chainContext, transaction, dateTime) => - { - var crossChainTestHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(crossChainTestHelper.CreateFakeTransactionTrace(transaction)); - }); - return mockTransactionReadOnlyExecutionService.Object; - }); - context.Services.AddTransient(provider => + Configure(option => { option.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); + + //context.Services.AddTransient(); + context.Services.AddSingleton(); + context.Services.AddTransient(provider => + { + var mockTransactionReadOnlyExecutionService = new Mock(); + mockTransactionReadOnlyExecutionService + .Setup(m => m.ExecuteAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((chainContext, transaction, dateTime) => + { + var crossChainTestHelper = + context.Services.GetRequiredServiceLazy().Value; + return Task.FromResult(crossChainTestHelper.CreateFakeTransactionTrace(transaction)); + }); + return mockTransactionReadOnlyExecutionService.Object; + }); + context.Services.AddTransient(provider => + { + var mockSmartContractAddressService = new Mock(); + mockSmartContractAddressService.Setup(m => + m.GetAddressByContractNameAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(SampleAddress.AddressList[0])); + return mockSmartContractAddressService.Object; + }); + context.Services.AddTransient(provider => + { + var mockBlockChainService = new Mock(); + mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => { - var mockSmartContractAddressService = new Mock(); - mockSmartContractAddressService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(),It.IsAny())) - .Returns(Task.FromResult(SampleAddress.AddressList[0])); - return mockSmartContractAddressService.Object; + var chain = new Chain(); + var crossChainTestHelper = context.Services.GetRequiredServiceLazy().Value; + chain.LastIrreversibleBlockHeight = crossChainTestHelper.FakeLibHeight; + return Task.FromResult(chain); }); - context.Services.AddTransient(provider => - { - var mockBlockChainService = new Mock(); - mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => + mockBlockChainService.Setup(m => + m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((chain, height, hash) => { - var chain = new Chain(); - var crossChainTestHelper = context.Services.GetRequiredServiceLazy().Value; - chain.LastIrreversibleBlockHeight = crossChainTestHelper.FakeLibHeight; - return Task.FromResult(chain); + if (height > 0 && height <= 3) + return Task.FromResult(dictionary[height]); + return Task.FromResult(null); }); - mockBlockChainService.Setup(m => - m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns((chain, height, hash) => - { - if (height > 0 && height <= 3) - return Task.FromResult(dictionary[height]); - return Task.FromResult(null); - }); - mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => - { - foreach (var kv in dictionary) - { - if (kv.Value.Equals(hash)) - return Task.FromResult(new Block {Header = new BlockHeader {Height = kv.Key}}); - } + mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => + { + foreach (var kv in dictionary) + if (kv.Value.Equals(hash)) + return Task.FromResult(new Block { Header = new BlockHeader { Height = kv.Key } }); - return Task.FromResult(null); - }); - return mockBlockChainService.Object; + return Task.FromResult(null); }); - } + return mockBlockChainService.Object; + }); } +} - [DependsOn( - typeof(CrossChainCoreModule), - typeof(KernelCoreWithChainTestAElfModule) - )] - public class CrossChainWithChainTestModule : AElfModule +[DependsOn( + typeof(CrossChainCoreModule), + typeof(KernelCoreWithChainTestAElfModule) +)] +public class CrossChainWithChainTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(); + context.Services.AddTransient(provider => { - context.Services.AddSingleton(); - context.Services.AddTransient(provider => - { - var mockSmartContractAddressService = new Mock(); - mockSmartContractAddressService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(),It.IsAny())) - .Returns(Task.FromResult(SampleAddress.AddressList[0])); - return mockSmartContractAddressService.Object; - }); - context.Services.AddTransient(provider => - { - var mockTransactionReadOnlyExecutionService = new Mock(); - mockTransactionReadOnlyExecutionService - .Setup(m => m.ExecuteAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((chainContext, transaction, dateTime) => - { - var crossChainTestHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(crossChainTestHelper.CreateFakeTransactionTrace(transaction)); - }); - return mockTransactionReadOnlyExecutionService.Object; - }); - } + var mockSmartContractAddressService = new Mock(); + mockSmartContractAddressService.Setup(m => + m.GetAddressByContractNameAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(SampleAddress.AddressList[0])); + return mockSmartContractAddressService.Object; + }); + context.Services.AddTransient(provider => + { + var mockTransactionReadOnlyExecutionService = new Mock(); + mockTransactionReadOnlyExecutionService + .Setup(m => m.ExecuteAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((chainContext, transaction, dateTime) => + { + var crossChainTestHelper = + context.Services.GetRequiredServiceLazy().Value; + return Task.FromResult(crossChainTestHelper.CreateFakeTransactionTrace(transaction)); + }); + return mockTransactionReadOnlyExecutionService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Indexing/CrossChainIndexingDataServiceTests.cs b/test/AElf.CrossChain.Core.Tests/Indexing/CrossChainIndexingDataServiceTests.cs index a5bf640f66..9685016732 100644 --- a/test/AElf.CrossChain.Core.Tests/Indexing/CrossChainIndexingDataServiceTests.cs +++ b/test/AElf.CrossChain.Core.Tests/Indexing/CrossChainIndexingDataServiceTests.cs @@ -1,768 +1,745 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.CrossChain; using AElf.CrossChain.Indexing.Application; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.CrossChain.Indexing +namespace AElf.CrossChain.Indexing; + +public class CrossChainIndexingDataServiceTests : CrossChainTestBase { - public class CrossChainIndexingDataServiceTests : CrossChainTestBase + private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; + private readonly CrossChainTestHelper _crossChainTestHelper; + + public CrossChainIndexingDataServiceTests() { - private readonly ICrossChainIndexingDataService _crossChainIndexingDataService; - private readonly CrossChainTestHelper _crossChainTestHelper; + _crossChainIndexingDataService = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + } - public CrossChainIndexingDataServiceTests() + private PendingChainIndexingProposalStatus CreatePendingChainIndexingProposalStatus(Address proposer, + Hash proposalId, CrossChainBlockData proposedCrossChainBlockData, bool toBeReleased = true, + Timestamp expiredTimeStamp = null) + { + return new PendingChainIndexingProposalStatus { - _crossChainIndexingDataService = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); - } + Proposer = proposer, + ProposalId = proposalId, + ProposedCrossChainBlockData = proposedCrossChainBlockData, + ToBeReleased = toBeReleased, + ExpiredTime = expiredTimeStamp ?? TimestampHelper.GetUtcNow().AddSeconds(10) + }; + } - #region Side chain + #region Side chain - [Fact] - public async Task GetIndexedSideChainBlockData_WithIndex_Test() + [Fact] + public async Task GetIndexedSideChainBlockData_WithIndex_Test() + { + var chainId = _chainOptions.ChainId; + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var fakeSideChainBlockData = new SideChainBlockData { - var chainId = _chainOptions.ChainId; - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - var fakeSideChainBlockData = new SideChainBlockData - { - Height = 1, - ChainId = chainId, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1 - }; + Height = 1, + ChainId = chainId, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1 + }; - var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); - fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] {fakeSideChainBlockData}); + var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); + fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] { fakeSideChainBlockData }); - _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(fakeSideChainBlockData.Height, - fakeIndexedCrossChainBlockData); - _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); + _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(fakeSideChainBlockData.Height, + fakeIndexedCrossChainBlockData); + _crossChainTestHelper.AddFakeSideChainIdHeight(chainId, 0); - AddFakeCacheData(new Dictionary> + AddFakeCacheData(new Dictionary> + { { + chainId, + new List { - chainId, - new List - { - fakeSideChainBlockData - } + fakeSideChainBlockData } - }); + } + }); - var res = await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync( - fakeSideChainBlockData.BlockHeaderHash, 1); - Assert.True(res.SideChainBlockDataList[0].Height == fakeSideChainBlockData.Height); - Assert.True(res.SideChainBlockDataList[0].ChainId == chainId); - } + var res = await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync( + fakeSideChainBlockData.BlockHeaderHash, 1); + Assert.True(res.SideChainBlockDataList[0].Height == fakeSideChainBlockData.Height); + Assert.True(res.SideChainBlockDataList[0].ChainId == chainId); + } - [Fact] - public async Task GetIndexedSideChainBlockData_WithoutIndex_Test() + [Fact] + public async Task GetIndexedSideChainBlockData_WithoutIndex_Test() + { + var chainId = _chainOptions.ChainId; + var fakeSideChainBlockData = new SideChainBlockData { - var chainId = _chainOptions.ChainId; - var fakeSideChainBlockData = new SideChainBlockData - { - Height = 1, - ChainId = chainId - }; + Height = 1, + ChainId = chainId + }; - var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); - fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] {fakeSideChainBlockData}); + var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); + fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] { fakeSideChainBlockData }); - var res = await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync( - fakeSideChainBlockData.BlockHeaderHash, 1); - Assert.True(res == null); - } + var res = await _crossChainIndexingDataService.GetIndexedSideChainBlockDataAsync( + fakeSideChainBlockData.BlockHeaderHash, 1); + Assert.True(res == null); + } - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_NoProposal_FirstTimeIndexing_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_NoProposal_FirstTimeIndexing_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); - var fakeCache = new Dictionary> {{sideChainId, sideChainBlockInfoCache}}; - AddFakeCacheData(fakeCache); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - Assert.Single(crossChainBlockData.SideChainBlockDataList); - Assert.Equal(sideChainBlockInfoCache.First().ToByteString(), - crossChainBlockData.SideChainBlockDataList.First().ToByteString()); - } + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); + var fakeCache = new Dictionary> { { sideChainId, sideChainBlockInfoCache } }; + AddFakeCacheData(fakeCache); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + Assert.Single(crossChainBlockData.SideChainBlockDataList); + Assert.Equal(sideChainBlockInfoCache.First().ToByteString(), + crossChainBlockData.SideChainBlockDataList.First().ToByteString()); + } - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_NoProposal_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_NoProposal_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } - - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - var fakeCache = new Dictionary> {{sideChainId, sideChainBlockInfoCache}}; - AddFakeCacheData(fakeCache); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - crossChainTransactionInput.MethodName.ShouldBe(nameof(CrossChainContractImplContainer.CrossChainContractImplStub - .ProposeCrossChainIndexing)); - Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, - crossChainBlockData.SideChainBlockDataList.Count); - } - - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_NoProposal_NoCache_Test() - { - var sideChainId = 123; - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - res.ShouldBeEmpty(); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - crossChainTransactionInput.ShouldBeNull(); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); - [Fact] - public async Task CheckExtraDataIsNeeded_ToBeReleased_Test() - { - var sideChainId = 123; - var utcNow = TimestampHelper.GetUtcNow(); - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), - new CrossChainBlockData(), true, utcNow.AddSeconds(1))); - var res = await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(Hash.Empty, 1, utcNow); - res.ShouldBe(true); - } - - [Fact] - public async Task CheckExtraDataIsNeeded_NotToBeReleased_Test() - { - var sideChainId = 123; - - var utcNow = TimestampHelper.GetUtcNow(); - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), - new CrossChainBlockData(), false)); - var res = await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(Hash.Empty, 1, utcNow); - res.ShouldBe(false); - } - - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_NotApproved_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - sideChainBlockInfoCache.Add(new SideChainBlockData - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + var fakeCache = new Dictionary> { { sideChainId, sideChainBlockInfoCache } }; + AddFakeCacheData(fakeCache); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + crossChainTransactionInput.MethodName.ShouldBe(nameof(CrossChainContractImplContainer.CrossChainContractImplStub + .ProposeCrossChainIndexing)); + Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, + crossChainBlockData.SideChainBlockDataList.Count); + } - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), - new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockInfoCache} - }, - false) - ); - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - crossChainTransactionInput.ShouldBeNull(); - } - - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_NoProposal_NoCache_Test() + { + var sideChainId = 123; + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + res.ShouldBeEmpty(); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + crossChainTransactionInput.ShouldBeNull(); + } - var crossChainBlockData = new CrossChainBlockData - { - SideChainBlockDataList = {sideChainBlockInfoCache} - }; - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), crossChainBlockData) - ); + [Fact] + public async Task CheckExtraDataIsNeeded_ToBeReleased_Test() + { + var sideChainId = 123; + var utcNow = TimestampHelper.GetUtcNow(); + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), + new CrossChainBlockData(), true, utcNow.AddSeconds(1))); + var res = await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(Hash.Empty, 1, utcNow); + res.ShouldBe(true); + } - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - var crossChainExtraData = CrossChainExtraData.Parser.ParseFrom(res); - var expectedMerkleTreeRoot = BinaryMerkleTree - .FromLeafNodes(sideChainBlockInfoCache.Select(s => s.TransactionStatusMerkleTreeRoot)).Root; - Assert.Equal(expectedMerkleTreeRoot, crossChainExtraData.TransactionStatusMerkleTreeRoot); - Assert.Equal(res, crossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData()); - } + [Fact] + public async Task CheckExtraDataIsNeeded_NotToBeReleased_Test() + { + var sideChainId = 123; + + var utcNow = TimestampHelper.GetUtcNow(); + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), + new CrossChainBlockData(), false)); + var res = await _crossChainIndexingDataService.CheckExtraDataIsNeededAsync(Hash.Empty, 1, utcNow); + res.ShouldBe(false); + } - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_Expired_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_NotApproved_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - var fakeCache = new Dictionary> - {{sideChainId, sideChainBlockInfoCache.ToList()}}; - AddFakeCacheData(fakeCache); + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), + new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockInfoCache } + }, + false) + ); + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + crossChainTransactionInput.ShouldBeNull(); + } - var crossChainBlockData = new CrossChainBlockData + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - SideChainBlockDataList = {sideChainBlockInfoCache} - }; - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, true, - TimestampHelper.GetUtcNow().AddSeconds(-1))); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockDataFromInput = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - - Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, - crossChainBlockDataFromInput.SideChainBlockDataList.Count); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_AlmostExpired_Test() + var crossChainBlockData = new CrossChainBlockData { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } - - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - var fakeCache = new Dictionary> - {{sideChainId, sideChainBlockInfoCache.ToList()}}; - AddFakeCacheData(fakeCache); + SideChainBlockDataList = { sideChainBlockInfoCache } + }; + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), crossChainBlockData) + ); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + var crossChainExtraData = CrossChainExtraData.Parser.ParseFrom(res); + var expectedMerkleTreeRoot = BinaryMerkleTree + .FromLeafNodes(sideChainBlockInfoCache.Select(s => s.TransactionStatusMerkleTreeRoot)).Root; + Assert.Equal(expectedMerkleTreeRoot, crossChainExtraData.TransactionStatusMerkleTreeRoot); + Assert.Equal(res, crossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData()); + } - var crossChainBlockData = new CrossChainBlockData + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_Expired_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - SideChainBlockDataList = {sideChainBlockInfoCache} - }; - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, true, - TimestampHelper.GetUtcNow().AddMilliseconds(500))); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - var crossChainExtraData = CrossChainExtraData.Parser.ParseFrom(res); - var expectedMerkleTreeRoot = BinaryMerkleTree - .FromLeafNodes(sideChainBlockInfoCache.Select(s => s.TransactionStatusMerkleTreeRoot)).Root; - Assert.Equal(expectedMerkleTreeRoot, crossChainExtraData.TransactionStatusMerkleTreeRoot); - Assert.Equal(res, crossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData()); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); - [Fact] - public async Task PrepareExtraDataForNextMiningAsync_AlmostExpired_NotApproved_Test() + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + var fakeCache = new Dictionary> + { { sideChainId, sideChainBlockInfoCache.ToList() } }; + AddFakeCacheData(fakeCache); + + var crossChainBlockData = new CrossChainBlockData { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + SideChainBlockDataList = { sideChainBlockInfoCache } + }; + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, true, + TimestampHelper.GetUtcNow().AddSeconds(-1))); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockDataFromInput = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + + Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, + crossChainBlockDataFromInput.SideChainBlockDataList.Count); + } + + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_AlmostExpired_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - sideChainBlockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); + + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + var fakeCache = new Dictionary> + { { sideChainId, sideChainBlockInfoCache.ToList() } }; + AddFakeCacheData(fakeCache); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - var fakeCache = new Dictionary> - {{sideChainId, sideChainBlockInfoCache.ToList()}}; - AddFakeCacheData(fakeCache); + var crossChainBlockData = new CrossChainBlockData + { + SideChainBlockDataList = { sideChainBlockInfoCache } + }; + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, true, + TimestampHelper.GetUtcNow().AddMilliseconds(500))); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + var crossChainExtraData = CrossChainExtraData.Parser.ParseFrom(res); + var expectedMerkleTreeRoot = BinaryMerkleTree + .FromLeafNodes(sideChainBlockInfoCache.Select(s => s.TransactionStatusMerkleTreeRoot)).Root; + Assert.Equal(expectedMerkleTreeRoot, crossChainExtraData.TransactionStatusMerkleTreeRoot); + Assert.Equal(res, crossChainBlockData.ExtractCrossChainExtraDataFromCrossChainBlockData()); + } - var crossChainBlockData = new CrossChainBlockData + [Fact] + public async Task PrepareExtraDataForNextMiningAsync_AlmostExpired_NotApproved_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + sideChainBlockInfoCache.Add(new SideChainBlockData { - SideChainBlockDataList = {sideChainBlockInfoCache} - }; - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, false, - TimestampHelper.GetUtcNow().AddMilliseconds(500) - )); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }); + + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + var fakeCache = new Dictionary> + { { sideChainId, sideChainBlockInfoCache.ToList() } }; + AddFakeCacheData(fakeCache); - [Fact] - public async Task GetCrossChainBlockDataForNextMining_WithoutCachingParentBlock_Test() + var crossChainBlockData = new CrossChainBlockData { - var sideChainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + SideChainBlockDataList = { sideChainBlockInfoCache } + }; + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), crossChainBlockData, false, + TimestampHelper.GetUtcNow().AddMilliseconds(500) + )); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + } + + [Fact] + public async Task GetCrossChainBlockDataForNextMining_WithoutCachingParentBlock_Test() + { + var sideChainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new SideChainBlockData { - blockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - var fakeCache = new Dictionary> {{sideChainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, - crossChainBlockData.SideChainBlockDataList.Count); - Assert.Empty(crossChainBlockData.ParentChainBlockDataList); - } + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + var fakeCache = new Dictionary> { { sideChainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, + crossChainBlockData.SideChainBlockDataList.Count); + Assert.Empty(crossChainBlockData.ParentChainBlockDataList); + } - [Fact] - public async Task GetCrossChainBlockDataForNextMining_WithoutCachingSideBlock_Test() - { - var parentChainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task GetCrossChainBlockDataForNextMining_WithoutCachingSideBlock_Test() + { + var parentChainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new ParentChainBlockData { - blockInfoCache.Add(new ParentChainBlockData() - { - ChainId = parentChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + ChainId = parentChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - _crossChainTestHelper.SetFakeLibHeight(2); - _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); - var fakeCache = new Dictionary> {{parentChainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, - crossChainBlockData.ParentChainBlockDataList.Count); - Assert.Empty(crossChainBlockData.SideChainBlockDataList); - } + _crossChainTestHelper.SetFakeLibHeight(2); + _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); + var fakeCache = new Dictionary> { { parentChainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + Assert.Equal(CrossChainConstants.DefaultBlockCacheEntityCount, + crossChainBlockData.ParentChainBlockDataList.Count); + Assert.Empty(crossChainBlockData.SideChainBlockDataList); + } - [Fact] - public async Task GetCrossChainBlockDataForNextMining_FromGenesisBlock_Test() - { - var sideChainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task GetCrossChainBlockDataForNextMining_FromGenesisBlock_Test() + { + var sideChainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new SideChainBlockData { - blockInfoCache.Add(new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) - }); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom(i.ToString()) + }); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); - var fakeCache = new Dictionary> {{sideChainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); - - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.NotNull(crossChainTransactionInput); - var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); - Assert.True(1 == crossChainBlockData.SideChainBlockDataList.Count); - Assert.Empty(crossChainBlockData.ParentChainBlockDataList); - } + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); + var fakeCache = new Dictionary> { { sideChainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); + + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.NotNull(crossChainTransactionInput); + var crossChainBlockData = CrossChainBlockData.Parser.ParseFrom(crossChainTransactionInput.Value); + Assert.True(1 == crossChainBlockData.SideChainBlockDataList.Count); + Assert.Empty(crossChainBlockData.ParentChainBlockDataList); + } - [Fact] - public async Task GetCrossChainBlockDataForNextMining_WithoutLIB_Test() - { - var parentChainId = _chainOptions.ChainId; - var blockInfoCache = new List(); - var cachingCount = 5; - for (int i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + [Fact] + public async Task GetCrossChainBlockDataForNextMining_WithoutLIB_Test() + { + var parentChainId = _chainOptions.ChainId; + var blockInfoCache = new List(); + var cachingCount = 5; + for (var i = 0; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + blockInfoCache.Add(new ParentChainBlockData { - blockInfoCache.Add(new ParentChainBlockData() - { - ChainId = parentChainId, - Height = (i + 1), - }); - } + ChainId = parentChainId, + Height = i + 1 + }); - _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); - var fakeCache = new Dictionary> {{parentChainId, blockInfoCache}}; - AddFakeCacheData(fakeCache); + _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); + var fakeCache = new Dictionary> { { parentChainId, blockInfoCache } }; + AddFakeCacheData(fakeCache); - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); - Assert.Null(crossChainTransactionInput); - } + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(Hash.Empty, 1); + Assert.Empty(res); + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(Hash.Empty, 1); + Assert.Null(crossChainTransactionInput); + } - [Fact] - public async Task GetNonIndexedBlock_Test() - { - _crossChainTestHelper.SetFakeLibHeight(2); - var res = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(1); - Assert.True(res.Height.Equals(1)); - } + [Fact] + public async Task GetNonIndexedBlock_Test() + { + _crossChainTestHelper.SetFakeLibHeight(2); + var res = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(1); + Assert.True(res.Height.Equals(1)); + } - [Fact] - public async Task GetNonIndexedBlock_NoBlock_Test() - { - _crossChainTestHelper.SetFakeLibHeight(1); - var res = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(2); - Assert.Null(res); - } + [Fact] + public async Task GetNonIndexedBlock_NoBlock_Test() + { + _crossChainTestHelper.SetFakeLibHeight(1); + var res = await _crossChainIndexingDataService.GetNonIndexedBlockAsync(2); + Assert.Null(res); + } - [Fact] - public async Task GenerateTransactionInput_PendingProposal_Test() - { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); - var previousBlockHeight = 1; + [Fact] + public async Task GenerateTransactionInput_PendingProposal_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); + var previousBlockHeight = 1; - var cachingCount = 5; - for (int i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + var cachingCount = 5; + for (var i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + { + var sideChainBlockData = new SideChainBlockData { - var sideChainBlockData = new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }; - sideChainBlockInfoCache.Add(sideChainBlockData); - } + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }; + sideChainBlockInfoCache.Add(sideChainBlockData); + } + + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + new PendingChainIndexingProposalStatus()); + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + AddFakeCacheData(new Dictionary> + { { sideChainId, sideChainBlockInfoCache } }); - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - new PendingChainIndexingProposalStatus()); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - AddFakeCacheData(new Dictionary> - {{sideChainId, sideChainBlockInfoCache}}); + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData())); - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData())); + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(previousBlockHash, + previousBlockHeight); + Assert.Empty(res); - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(previousBlockHash, + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, previousBlockHeight); - Assert.Empty(res); - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, - previousBlockHeight); + Assert.Equal( + nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ReleaseCrossChainIndexingProposal), + crossChainTransactionInput.MethodName); - Assert.Equal(nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ReleaseCrossChainIndexingProposal), - crossChainTransactionInput.MethodName); + var sideChainIdListInParam = ReleaseCrossChainIndexingProposalInput.Parser + .ParseFrom(crossChainTransactionInput.Value).ChainIdList; + sideChainIdListInParam.ShouldContain(sideChainId); + } - var sideChainIdListInParam = ReleaseCrossChainIndexingProposalInput.Parser.ParseFrom(crossChainTransactionInput.Value).ChainIdList; - sideChainIdListInParam.ShouldContain(sideChainId); - } + [Fact] + public async Task GenerateTransaction_PendingProposal_NotApproved_Test() + { + var sideChainId = 123; + var sideChainBlockInfoCache = new List(); + var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); + var previousBlockHeight = 1; - [Fact] - public async Task GenerateTransaction_PendingProposal_NotApproved_Test() + var cachingCount = 5; + for (var i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) { - var sideChainId = 123; - var sideChainBlockInfoCache = new List(); - var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); - var previousBlockHeight = 1; - - var cachingCount = 5; - for (int i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) + var sideChainBlockData = new SideChainBlockData { - var sideChainBlockData = new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }; - sideChainBlockInfoCache.Add(sideChainBlockData); - } - - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - new PendingChainIndexingProposalStatus()); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); - AddFakeCacheData(new Dictionary> - {{sideChainId, sideChainBlockInfoCache}}); + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) + }; + sideChainBlockInfoCache.Add(sideChainBlockData); + } - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData(), false)); - var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(previousBlockHash, + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + new PendingChainIndexingProposalStatus()); + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 1); + AddFakeCacheData(new Dictionary> + { { sideChainId, sideChainBlockInfoCache } }); + + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(sideChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData(), false)); + var res = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(previousBlockHash, + previousBlockHeight); + Assert.Empty(res); + + var crossChainTransactionInput = + await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, previousBlockHeight); - Assert.Empty(res); + Assert.Null(crossChainTransactionInput); + } - var crossChainTransactionInput = - await _crossChainIndexingDataService.GetCrossChainTransactionInputForNextMiningAsync(previousBlockHash, - previousBlockHeight); - Assert.Null(crossChainTransactionInput); - } + [Fact] + public async Task FillExtraData_WithoutSideChainBlockData_Test() + { + var parentChainId = _chainOptions.ChainId; + var parentChainBlockDataList = new List(); + + for (var i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount + 1; i++) + parentChainBlockDataList.Add(new ParentChainBlockData + { + Height = i + 1, + ChainId = parentChainId + } + ); - [Fact] - public async Task FillExtraData_WithoutSideChainBlockData_Test() + var header = new BlockHeader { - int parentChainId = _chainOptions.ChainId; - var parentChainBlockDataList = new List(); + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 2 + }; + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(parentChainId, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData + { + ParentChainBlockDataList = { parentChainBlockDataList } + } + )); + var bytes = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(header.PreviousBlockHash, + header.Height - 1); + Assert.Empty(bytes); + } - for (int i = 0; i < CrossChainConstants.DefaultBlockCacheEntityCount + 1; i++) + [Fact] + public async Task FillExtraData_Test() + { + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var fakeMerkleTreeRoot2 = HashHelper.ComputeFrom("fakeMerkleTreeRoot2"); + var fakeMerkleTreeRoot3 = HashHelper.ComputeFrom("fakeMerkleTreeRoot3"); + + var chainId1 = ChainHelper.ConvertBase58ToChainId("2112"); + var chainId2 = ChainHelper.ConvertBase58ToChainId("2113"); + var chainId3 = ChainHelper.ConvertBase58ToChainId("2114"); + var fakeSideChainBlockDataList = new List + { + new() { - parentChainBlockDataList.Add(new ParentChainBlockData - { - Height = i + 1, - ChainId = parentChainId - } - ); - } - - var header = new BlockHeader + Height = 1, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, + ChainId = chainId1 + }, + new() { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 2 - }; - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(parentChainId, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData - { - ParentChainBlockDataList = {parentChainBlockDataList} - } - )); - var bytes = await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(header.PreviousBlockHash, - header.Height - 1); - Assert.Empty(bytes); - } - - [Fact] - public async Task FillExtraData_Test() - { - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - var fakeMerkleTreeRoot2 = HashHelper.ComputeFrom("fakeMerkleTreeRoot2"); - var fakeMerkleTreeRoot3 = HashHelper.ComputeFrom("fakeMerkleTreeRoot3"); - - int chainId1 = ChainHelper.ConvertBase58ToChainId("2112"); - int chainId2 = ChainHelper.ConvertBase58ToChainId("2113"); - int chainId3 = ChainHelper.ConvertBase58ToChainId("2114"); - var fakeSideChainBlockDataList = new List + Height = 1, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2, + ChainId = chainId2 + }, + new() { - new SideChainBlockData - { - Height = 1, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, - ChainId = chainId1 - }, - new SideChainBlockData - { - Height = 1, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2, - ChainId = chainId2 - }, - new SideChainBlockData - { - Height = 1, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3, - ChainId = chainId3 - } - }; + Height = 1, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3, + ChainId = chainId3 + } + }; - var list1 = new List(); - var list2 = new List(); - var list3 = new List(); + var list1 = new List(); + var list2 = new List(); + var list3 = new List(); - list1.Add(fakeSideChainBlockDataList[0]); - list2.Add(fakeSideChainBlockDataList[1]); - list3.Add(fakeSideChainBlockDataList[2]); + list1.Add(fakeSideChainBlockDataList[0]); + list2.Add(fakeSideChainBlockDataList[1]); + list3.Add(fakeSideChainBlockDataList[2]); - for (int i = 2; i < CrossChainConstants.DefaultBlockCacheEntityCount + 2; i++) + for (var i = 2; i < CrossChainConstants.DefaultBlockCacheEntityCount + 2; i++) + { + list1.Add(new SideChainBlockData { - list1.Add(new SideChainBlockData + Height = i, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, + ChainId = chainId1 + }); + list2.Add(new SideChainBlockData + { + Height = i, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2, + ChainId = chainId2 + }); + list3.Add(new SideChainBlockData + { + Height = i, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3, + ChainId = chainId3 + }); + } + + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId1, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData { - Height = i, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, - ChainId = chainId1 - }); - list2.Add(new SideChainBlockData + SideChainBlockDataList = { list1 } + })); + + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId2, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData { - Height = i, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2, - ChainId = chainId2 - }); - list3.Add(new SideChainBlockData + SideChainBlockDataList = { list2 } + })); + + _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId3, + CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], + HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData { - Height = i, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3, - ChainId = chainId3 - }); - } + SideChainBlockDataList = { list3 } + }) + ); - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId1, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData - { - SideChainBlockDataList = {list1} - })); - - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId2, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData - { - SideChainBlockDataList = {list2} - })); - - _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId3, - CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0], - HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData - { - SideChainBlockDataList = {list3} - }) - ); + _crossChainTestHelper.SetFakeLibHeight(1); + var header = new BlockHeader + { + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 2 + }; - _crossChainTestHelper.SetFakeLibHeight(1); - var header = new BlockHeader - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 2 - }; + var sideChainTxMerkleTreeRoot = + await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(header.PreviousBlockHash, + header.Height - 1); + var merkleTreeRoot = BinaryMerkleTree + .FromLeafNodes(list1.Concat(list2).Concat(list3).Select(sideChainBlockData => + sideChainBlockData.TransactionStatusMerkleTreeRoot)).Root; + var expected = new CrossChainExtraData { TransactionStatusMerkleTreeRoot = merkleTreeRoot }.ToByteString(); + Assert.Equal(expected, sideChainTxMerkleTreeRoot); + } - var sideChainTxMerkleTreeRoot = - await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(header.PreviousBlockHash, - header.Height - 1); - var merkleTreeRoot = BinaryMerkleTree - .FromLeafNodes(list1.Concat(list2).Concat(list3).Select(sideChainBlockData => - sideChainBlockData.TransactionStatusMerkleTreeRoot)).Root; - var expected = new CrossChainExtraData {TransactionStatusMerkleTreeRoot = merkleTreeRoot}.ToByteString(); - Assert.Equal(expected, sideChainTxMerkleTreeRoot); + [Fact] + public async Task GetAllChainIdHeightPairsAtLibAsync_Test() + { + { + var allChainIdAndHeightResult = + await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); + allChainIdAndHeightResult.ShouldBe(new ChainIdAndHeightDict()); } - [Fact] - public async Task GetAllChainIdHeightPairsAtLibAsync_Test() + _crossChainTestHelper.SetFakeLibHeight(2); + { - { - var allChainIdAndHeightResult = - await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); - allChainIdAndHeightResult.ShouldBe(new ChainIdAndHeightDict()); - } - - _crossChainTestHelper.SetFakeLibHeight(2); - - { - var allChainIdAndHeightResult = - await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); - allChainIdAndHeightResult.ShouldBe(new ChainIdAndHeightDict()); - } - - var parentChainId = ChainHelper.GetChainId(10); - _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); - - var sideChainId = ChainHelper.GetChainId(100); - _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); - - { - var allChainIdAndHeightResult = - await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); - allChainIdAndHeightResult.IdHeightDict[parentChainId].ShouldBe(1); - allChainIdAndHeightResult.IdHeightDict[sideChainId].ShouldBe(0); - } + var allChainIdAndHeightResult = + await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); + allChainIdAndHeightResult.ShouldBe(new ChainIdAndHeightDict()); } - #endregion + var parentChainId = ChainHelper.GetChainId(10); + _crossChainTestHelper.AddFakeParentChainIdHeight(parentChainId, 1); + + var sideChainId = ChainHelper.GetChainId(100); + _crossChainTestHelper.AddFakeSideChainIdHeight(sideChainId, 0); - private PendingChainIndexingProposalStatus CreatePendingChainIndexingProposalStatus(Address proposer, - Hash proposalId, CrossChainBlockData proposedCrossChainBlockData, bool toBeReleased = true, - Timestamp expiredTimeStamp = null) { - return new PendingChainIndexingProposalStatus - { - Proposer = proposer, - ProposalId = proposalId, - ProposedCrossChainBlockData = proposedCrossChainBlockData, - ToBeReleased = toBeReleased, - ExpiredTime = expiredTimeStamp ?? TimestampHelper.GetUtcNow().AddSeconds(10) - }; + var allChainIdAndHeightResult = + await _crossChainIndexingDataService.GetAllChainIdHeightPairsAtLibAsync(); + allChainIdAndHeightResult.IdHeightDict[parentChainId].ShouldBe(1); + allChainIdAndHeightResult.IdHeightDict[sideChainId].ShouldBe(0); } } + + #endregion } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Indexing/IrreversibleBlockStateProviderTest.cs b/test/AElf.CrossChain.Core.Tests/Indexing/IrreversibleBlockStateProviderTest.cs index e683dbc232..d0e4bf4da7 100644 --- a/test/AElf.CrossChain.Core.Tests/Indexing/IrreversibleBlockStateProviderTest.cs +++ b/test/AElf.CrossChain.Core.Tests/Indexing/IrreversibleBlockStateProviderTest.cs @@ -3,38 +3,37 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Indexing +namespace AElf.CrossChain.Indexing; + +public class IrreversibleBlockStateProviderTest : CrossChainTestBase { - public class IrreversibleBlockStateProviderTest : CrossChainTestBase + private readonly CrossChainTestHelper _crossChainTestHelper; + private readonly IIrreversibleBlockStateProvider _irreversibleBlockStateProvider; + + public IrreversibleBlockStateProviderTest() { - private readonly IIrreversibleBlockStateProvider _irreversibleBlockStateProvider; - private readonly CrossChainTestHelper _crossChainTestHelper; + _irreversibleBlockStateProvider = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + } + + [Fact] + public async Task ValidateIrreversibleBlockExistingAsync_Test() + { + { + var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); + libExists.ShouldBeFalse(); + } - public IrreversibleBlockStateProviderTest() + _crossChainTestHelper.SetFakeLibHeight(1); { - _irreversibleBlockStateProvider = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); + var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); + libExists.ShouldBeFalse(); } - [Fact] - public async Task ValidateIrreversibleBlockExistingAsync_Test() + _crossChainTestHelper.SetFakeLibHeight(2); { - { - var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); - libExists.ShouldBeFalse(); - } - - _crossChainTestHelper.SetFakeLibHeight(1); - { - var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); - libExists.ShouldBeFalse(); - } - - _crossChainTestHelper.SetFakeLibHeight(2); - { - var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); - libExists.ShouldBeTrue(); - } + var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync(); + libExists.ShouldBeTrue(); } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Core.Tests/Indexing/TransactionInputForBlockMiningDataProviderTests.cs b/test/AElf.CrossChain.Core.Tests/Indexing/TransactionInputForBlockMiningDataProviderTests.cs index 62278cfb2c..96650a7696 100644 --- a/test/AElf.CrossChain.Core.Tests/Indexing/TransactionInputForBlockMiningDataProviderTests.cs +++ b/test/AElf.CrossChain.Core.Tests/Indexing/TransactionInputForBlockMiningDataProviderTests.cs @@ -2,39 +2,38 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Indexing +namespace AElf.CrossChain.Indexing; + +public class TransactionInputForBlockMiningDataProviderTests : CrossChainTestBase { - public class TransactionInputForBlockMiningDataProviderTests : CrossChainTestBase + private readonly ITransactionInputForBlockMiningDataProvider _transactionInputForBlockMiningDataProvider; + + public TransactionInputForBlockMiningDataProviderTests() + { + _transactionInputForBlockMiningDataProvider = + GetRequiredService(); + } + + [Fact] + public void TransactionInputForBlockMiningDataProvider_AddAndGet_Tests() { - private readonly ITransactionInputForBlockMiningDataProvider _transactionInputForBlockMiningDataProvider; + var blockHash = HashHelper.ComputeFrom("Random"); + var crossChainTransactionInput = new CrossChainTransactionInput + { + PreviousBlockHeight = 10 + }; + _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, + crossChainTransactionInput); - public TransactionInputForBlockMiningDataProviderTests() { - _transactionInputForBlockMiningDataProvider = - GetRequiredService(); + var actual = _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); + actual.ShouldBe(crossChainTransactionInput); } - [Fact] - public void TransactionInputForBlockMiningDataProvider_AddAndGet_Tests() { - var blockHash = HashHelper.ComputeFrom("Random"); - var crossChainTransactionInput = new CrossChainTransactionInput - { - PreviousBlockHeight = 10 - }; - _transactionInputForBlockMiningDataProvider.AddTransactionInputForBlockMining(blockHash, - crossChainTransactionInput); - - { - var actual = _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); - actual.ShouldBe(crossChainTransactionInput); - } - - { - _transactionInputForBlockMiningDataProvider.ClearExpiredTransactionInput(11); - var actual = _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); - actual.ShouldBeNull(); - } + _transactionInputForBlockMiningDataProvider.ClearExpiredTransactionInput(11); + var actual = _transactionInputForBlockMiningDataProvider.GetTransactionInputForBlockMining(blockHash); + actual.ShouldBeNull(); } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/AElf.CrossChain.Grpc.Tests.csproj b/test/AElf.CrossChain.Grpc.Tests/AElf.CrossChain.Grpc.Tests.csproj index 3c6dcc048c..49fec3f3d0 100644 --- a/test/AElf.CrossChain.Grpc.Tests/AElf.CrossChain.Grpc.Tests.csproj +++ b/test/AElf.CrossChain.Grpc.Tests/AElf.CrossChain.Grpc.Tests.csproj @@ -5,16 +5,16 @@ false - - - - - - - + + + + + + + - - + + diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcClientTests.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcClientTests.cs index d44ed52ed5..d57b4e58a7 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcClientTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcClientTests.cs @@ -1,95 +1,93 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Cache.Application; -using AElf.CrossChain.Grpc.Client; +using AElf.Standards.ACS7; using Grpc.Core; using Xunit; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcClientTests : GrpcCrossChainClientTestBase { - public class GrpcClientTests : GrpcCrossChainClientTestBase + private const string Host = "127.0.0.1"; + private const int ListenPort = 2200; + private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + private BasicCrossChainRpc.BasicCrossChainRpcClient _basicClient; + private readonly GrpcCrossChainCommunicationTestHelper _grpcCrossChainCommunicationTestHelper; + + public GrpcClientTests() { - private const string Host = "127.0.0.1"; - private const int ListenPort = 2200; - private BasicCrossChainRpc.BasicCrossChainRpcClient _basicClient; - private GrpcCrossChainCommunicationTestHelper _grpcCrossChainCommunicationTestHelper; - private readonly IBlockCacheEntityProducer _blockCacheEntityProducer; + _grpcCrossChainCommunicationTestHelper = GetRequiredService(); + _blockCacheEntityProducer = GetRequiredService(); + } - public GrpcClientTests() + [Fact] + public async Task BasicCrossChainClient_TryHandShake_Test() + { + await InitServerAndClientAsync(5000); + var result = await _basicClient.CrossChainHandShakeAsync(new HandShake { - _grpcCrossChainCommunicationTestHelper = GetRequiredService(); - _blockCacheEntityProducer = GetRequiredService(); - } + ListeningPort = ListenPort, + ChainId = 0 + }); + Assert.True(result.Status == HandShakeReply.Types.HandShakeStatus.Success); + Dispose(); + } - [Fact] - public async Task BasicCrossChainClient_TryHandShake_Test() - { - await InitServerAndClientAsync(5000); - var result = await _basicClient.CrossChainHandShakeAsync(new HandShake - { - ListeningPort = ListenPort, - ChainId = 0 - }); - Assert.True(result.Status == HandShakeReply.Types.HandShakeStatus.Success); - Dispose(); - } + [Fact] + public async Task RequestChainInitializationData_ParentClient_Test() + { + var chainId = ChainHelper.GetChainId(ChainHelper.ConvertBase58ToChainId("AELF") + 1); + await Server.StartAsync(5000); - [Fact] - public async Task RequestChainInitializationData_ParentClient_Test() + var grpcClientInitializationContext = new GrpcClientInitializationContext { - var chainId = ChainHelper.GetChainId(ChainHelper.ConvertBase58ToChainId("AELF") + 1); - await Server.StartAsync(5000); + LocalChainId = chainId, + RemoteChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + DialTimeout = 1000, + UriStr = string.Concat(Host, ":", "5000") + }; + var client = new ClientForParentChain(grpcClientInitializationContext); + var res = await client.RequestChainInitializationDataAsync(chainId); + Assert.Equal(1, res.CreationHeightOnParentChain); + Dispose(); + } - var grpcClientInitializationContext = new GrpcClientInitializationContext - { - LocalChainId = chainId, - RemoteChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - DialTimeout = 1000, - UriStr = string.Concat(Host, ":", "5000") - }; - var client = new ClientForParentChain(grpcClientInitializationContext); - var res = await client.RequestChainInitializationDataAsync(chainId); - Assert.Equal(1, res.CreationHeightOnParentChain); - Dispose(); - } + [Fact] + public async Task RequestCrossChainData_Test() + { + var chainId = ChainHelper.GetChainId(ChainHelper.ConvertBase58ToChainId("AELF") + 1); + var remoteChainId = ChainOptions.ChainId; + var height = 2; + var port = 5000; + await Server.StartAsync(port); - [Fact] - public async Task RequestCrossChainData_Test() + var grpcClientInitializationContext = new GrpcClientInitializationContext { - var chainId = ChainHelper.GetChainId(ChainHelper.ConvertBase58ToChainId("AELF") + 1); - var remoteChainId = ChainOptions.ChainId; - var height = 2; - var port = 5000; - await Server.StartAsync(port); - - var grpcClientInitializationContext = new GrpcClientInitializationContext - { - RemoteChainId = chainId, - LocalChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - DialTimeout = 1000, - UriStr = string.Concat(Host, ":", port) - }; - var client = new ClientForSideChain(grpcClientInitializationContext); - _grpcCrossChainCommunicationTestHelper.GrpcCrossChainClients.TryAdd(remoteChainId, client); - _grpcCrossChainCommunicationTestHelper.FakeSideChainBlockDataEntityCacheOnServerSide(height); - await client.RequestCrossChainDataAsync(height, b => _blockCacheEntityProducer.TryAddBlockCacheEntity(b)); - - var clientBlockDataEntityCache = GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache; - var sideChainBlockData = new SideChainBlockData {Height = height}; - Assert.Contains(sideChainBlockData, clientBlockDataEntityCache); - Dispose(); - } + RemoteChainId = chainId, + LocalChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + DialTimeout = 1000, + UriStr = string.Concat(Host, ":", port) + }; + var client = new ClientForSideChain(grpcClientInitializationContext); + _grpcCrossChainCommunicationTestHelper.GrpcCrossChainClients.TryAdd(remoteChainId, client); + _grpcCrossChainCommunicationTestHelper.FakeSideChainBlockDataEntityCacheOnServerSide(height); + await client.RequestCrossChainDataAsync(height, b => _blockCacheEntityProducer.TryAddBlockCacheEntity(b)); - private async Task InitServerAndClientAsync(int port) - { - await Server.StartAsync(port); - _basicClient = - new BasicCrossChainRpc.BasicCrossChainRpcClient(new Channel(Host, port, ChannelCredentials.Insecure)); - } + var clientBlockDataEntityCache = GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache; + var sideChainBlockData = new SideChainBlockData { Height = height }; + Assert.Contains(sideChainBlockData, clientBlockDataEntityCache); + Dispose(); + } - public override void Dispose() - { - Server?.Dispose(); - } + private async Task InitServerAndClientAsync(int port) + { + await Server.StartAsync(port); + _basicClient = + new BasicCrossChainRpc.BasicCrossChainRpcClient(new Channel(Host, port, ChannelCredentials.Insecure)); + } + + public override void Dispose() + { + Server?.Dispose(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientNodePluginTests.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientNodePluginTests.cs index 212bca7b14..d52d3fcbc8 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientNodePluginTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientNodePluginTests.cs @@ -3,52 +3,52 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Grpc.Client -{ - public sealed class GrpcCrossChainClientNodePluginTests : GrpcCrossChainClientTestBase - { - private readonly IGrpcClientPlugin _grpcCrossChainClientNodePlugin; - private readonly ICrossChainClientProvider _crossChainClientProvider; +namespace AElf.CrossChain.Grpc.Client; - public GrpcCrossChainClientNodePluginTests() - { - _grpcCrossChainClientNodePlugin = GetRequiredService(); - _crossChainClientProvider = GetRequiredService(); - } +public sealed class GrpcCrossChainClientNodePluginTests : GrpcCrossChainClientTestBase +{ + private readonly ICrossChainClientProvider _crossChainClientProvider; + private readonly IGrpcClientPlugin _grpcCrossChainClientNodePlugin; - [Fact] - public async Task ClientStart_Test() - { - var chainId = ChainHelper.GetChainId(1); - var remoteChainId = ChainOptions.ChainId; - await Server.StartAsync(5000); - await _grpcCrossChainClientNodePlugin.StartAsync(chainId); - var clients = _crossChainClientProvider.GetAllClients(); - clients[0].RemoteChainId.ShouldBe(remoteChainId); - Server.Dispose(); - } + public GrpcCrossChainClientNodePluginTests() + { + _grpcCrossChainClientNodePlugin = GetRequiredService(); + _crossChainClientProvider = GetRequiredService(); } - - public sealed class GrpcCrossChainClientNodePluginWithoutParentChainTests : GrpcCrossChainClientWithoutParentChainTestBase + + [Fact] + public async Task ClientStart_Test() { - private readonly IGrpcClientPlugin _grpcCrossChainClientNodePlugin; - private readonly ICrossChainClientProvider _crossChainClientProvider; + var chainId = ChainHelper.GetChainId(1); + var remoteChainId = ChainOptions.ChainId; + await Server.StartAsync(5000); + await _grpcCrossChainClientNodePlugin.StartAsync(chainId); + var clients = _crossChainClientProvider.GetAllClients(); + clients[0].RemoteChainId.ShouldBe(remoteChainId); + Server.Dispose(); + } +} - public GrpcCrossChainClientNodePluginWithoutParentChainTests() - { - _grpcCrossChainClientNodePlugin = GetRequiredService(); - _crossChainClientProvider = GetRequiredService(); - } +public sealed class + GrpcCrossChainClientNodePluginWithoutParentChainTests : GrpcCrossChainClientWithoutParentChainTestBase +{ + private readonly ICrossChainClientProvider _crossChainClientProvider; + private readonly IGrpcClientPlugin _grpcCrossChainClientNodePlugin; - [Fact] - public async Task ClientWithoutParentChainStart_Test() - { - var chainId = ChainHelper.GetChainId(1); - await Server.StartAsync(5000); - await _grpcCrossChainClientNodePlugin.StartAsync(chainId); - var clients = _crossChainClientProvider.GetAllClients(); - clients.ShouldBeEmpty(); - Server.Dispose(); - } + public GrpcCrossChainClientNodePluginWithoutParentChainTests() + { + _grpcCrossChainClientNodePlugin = GetRequiredService(); + _crossChainClientProvider = GetRequiredService(); + } + + [Fact] + public async Task ClientWithoutParentChainStart_Test() + { + var chainId = ChainHelper.GetChainId(1); + await Server.StartAsync(5000); + await _grpcCrossChainClientNodePlugin.StartAsync(chainId); + var clients = _crossChainClientProvider.GetAllClients(); + clients.ShouldBeEmpty(); + Server.Dispose(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientProviderTests.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientProviderTests.cs index d5ae6d3067..485f6fa655 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientProviderTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientProviderTests.cs @@ -2,123 +2,122 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainClientProviderTests : GrpcCrossChainClientTestBase { - public class GrpcCrossChainClientProviderTests : GrpcCrossChainClientTestBase + private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; + + public GrpcCrossChainClientProviderTests() { - private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; + _grpcCrossChainClientProvider = GetRequiredService(); + } - public GrpcCrossChainClientProviderTests() - { - _grpcCrossChainClientProvider = GetRequiredService(); - } + [Fact] + public void AddOrUpdateClient_Test() + { + var remoteChainId = ChainOptions.ChainId; + var localChainId = ChainHelper.GetChainId(1); - [Fact] - public void AddOrUpdateClient_Test() + var host = "127.0.0.1"; + var port = 5000; + var crossChainClientDto = new CrossChainClientCreationContext { - var remoteChainId = ChainOptions.ChainId; - var localChainId = ChainHelper.GetChainId(1); - - var host = "127.0.0.1"; - var port = 5000; - var crossChainClientDto = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = false, - RemoteServerHost = host, - RemoteServerPort = port - }; - - var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); - - Assert.True(client.RemoteChainId == remoteChainId); - Assert.False(client.IsConnected); - Assert.Equal(remoteChainId, client.RemoteChainId); - - var expectedUriStr = string.Concat(host, ":", "5000"); - Assert.Equal(expectedUriStr, client.TargetUriString); - - var sameClient = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); - sameClient.ShouldBe(client); - } - - - [Fact] - public void TryGetClient_Test() + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = host, + RemoteServerPort = port + }; + + var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); + + Assert.True(client.RemoteChainId == remoteChainId); + Assert.False(client.IsConnected); + Assert.Equal(remoteChainId, client.RemoteChainId); + + var expectedUriStr = string.Concat(host, ":", "5000"); + Assert.Equal(expectedUriStr, client.TargetUriString); + + var sameClient = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); + sameClient.ShouldBe(client); + } + + + [Fact] + public void TryGetClient_Test() + { + var remoteChainId = ChainOptions.ChainId; + var localChainId = ChainHelper.GetChainId(1); + + var host = "127.0.0.1"; + var port = 5000; + var crossChainClientDto = new CrossChainClientCreationContext { - var remoteChainId = ChainOptions.ChainId; - var localChainId = ChainHelper.GetChainId(1); - - var host = "127.0.0.1"; - var port = 5000; - var crossChainClientDto = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = false, - RemoteServerHost = host, - RemoteServerPort = port - }; - - var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); - var isClientCached = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out var clientInCache); - Assert.True(isClientCached); - Assert.Equal(client, clientInCache); - } - - [Fact] - public void GetAllClients_Test() + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = host, + RemoteServerPort = port + }; + + var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); + var isClientCached = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out var clientInCache); + Assert.True(isClientCached); + Assert.Equal(client, clientInCache); + } + + [Fact] + public void GetAllClients_Test() + { + var remoteChainId = ChainOptions.ChainId; + var localChainId = ChainHelper.GetChainId(1); + + var host = "127.0.0.1"; + var port = 5000; + var crossChainClientDto = new CrossChainClientCreationContext { - var remoteChainId = ChainOptions.ChainId; - var localChainId = ChainHelper.GetChainId(1); - - var host = "127.0.0.1"; - var port = 5000; - var crossChainClientDto = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = false, - RemoteServerHost = host, - RemoteServerPort = port - }; - - var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); - - var clients = _grpcCrossChainClientProvider.GetAllClients(); - Assert.Single(clients); - Assert.Equal(client, clients[0]); - } - - - [Fact] - public void CreateCrossChainClient_Test() + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = host, + RemoteServerPort = port + }; + + var client = _grpcCrossChainClientProvider.AddOrUpdateClient(crossChainClientDto); + + var clients = _grpcCrossChainClientProvider.GetAllClients(); + Assert.Single(clients); + Assert.Equal(client, clients[0]); + } + + + [Fact] + public void CreateCrossChainClient_Test() + { + var remoteChainId = ChainOptions.ChainId; + var localChainId = ChainHelper.GetChainId(1); + + var host = "127.0.0.1"; + var port = 5000; + var crossChainClientDto = new CrossChainClientCreationContext { - var remoteChainId = ChainOptions.ChainId; - var localChainId = ChainHelper.GetChainId(1); - - var host = "127.0.0.1"; - var port = 5000; - var crossChainClientDto = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = false, - RemoteServerHost = host, - RemoteServerPort = port - }; - - var client = _grpcCrossChainClientProvider.CreateChainInitializationDataClient(crossChainClientDto); - var isClientCached = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out _); - Assert.False(isClientCached); - - Assert.True(client.RemoteChainId == remoteChainId); - Assert.False(client.IsConnected); - Assert.Equal(remoteChainId, client.RemoteChainId); - - var expectedUriStr = string.Concat(host, ":", "5000"); - Assert.Equal(expectedUriStr, client.TargetUriString); - } + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = host, + RemoteServerPort = port + }; + + var client = _grpcCrossChainClientProvider.CreateChainInitializationDataClient(crossChainClientDto); + var isClientCached = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out _); + Assert.False(isClientCached); + + Assert.True(client.RemoteChainId == remoteChainId); + Assert.False(client.IsConnected); + Assert.Equal(remoteChainId, client.RemoteChainId); + + var expectedUriStr = string.Concat(host, ":", "5000"); + Assert.Equal(expectedUriStr, client.TargetUriString); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientServiceTests.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientServiceTests.cs index 837f0aee59..44a6fd17f2 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientServiceTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientServiceTests.cs @@ -3,47 +3,46 @@ using AElf.CrossChain.Communication.Infrastructure; using Xunit; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainClientServiceTests : GrpcCrossChainClientTestBase { - public class GrpcCrossChainClientServiceTests : GrpcCrossChainClientTestBase + private readonly ICrossChainClientService _crossChainClientService; + private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; + + public GrpcCrossChainClientServiceTests() { - private readonly ICrossChainClientService _crossChainClientService; - private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; + _crossChainClientService = GetRequiredService(); + _grpcCrossChainClientProvider = GetRequiredService(); + } - public GrpcCrossChainClientServiceTests() - { - _crossChainClientService = GetRequiredService(); - _grpcCrossChainClientProvider = GetRequiredService(); - } - - [Fact] - public async Task CreateClient_Test() + [Fact] + public async Task CreateClient_Test() + { + var remoteChainId = ChainOptions.ChainId; + var localChainId = ChainHelper.GetChainId(1); + + var host = "127.0.0.1"; + var port = 5100; + await Server.StartAsync(port); + + var fakeCrossChainClient = new CrossChainClientCreationContext { - var remoteChainId = ChainOptions.ChainId; - var localChainId = ChainHelper.GetChainId(1); - - var host = "127.0.0.1"; - var port = 5100; - await Server.StartAsync(port); - - var fakeCrossChainClient = new CrossChainClientCreationContext - { - LocalChainId = localChainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = false, - RemoteServerHost = host, - RemoteServerPort = port - }; - - await _crossChainClientService.CreateClientAsync(fakeCrossChainClient); - var res = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out var client); - Assert.True(res); - - await client.ConnectAsync(); - Assert.True(client.IsConnected); - - await client.CloseAsync(); - Assert.False(client.IsConnected); - } + LocalChainId = localChainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = false, + RemoteServerHost = host, + RemoteServerPort = port + }; + + await _crossChainClientService.CreateClientAsync(fakeCrossChainClient); + var res = _grpcCrossChainClientProvider.TryGetClient(remoteChainId, out var client); + Assert.True(res); + + await client.ConnectAsync(); + Assert.True(client.IsConnected); + + await client.CloseAsync(); + Assert.False(client.IsConnected); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestBase.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestBase.cs index 7ee014c662..e9ec62e883 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestBase.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestBase.cs @@ -3,29 +3,30 @@ using AElf.TestBase; using Microsoft.Extensions.Options; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +public class GrpcCrossChainClientTestBase : AElfIntegratedTest { - public class GrpcCrossChainClientTestBase : AElfIntegratedTest + protected ChainOptions ChainOptions; + protected IGrpcCrossChainServer Server; + + public GrpcCrossChainClientTestBase() { - protected ChainOptions ChainOptions; - protected IGrpcCrossChainServer Server; - - public GrpcCrossChainClientTestBase() - { - ChainOptions = GetRequiredService>().Value; - Server = GetRequiredService(); - } + ChainOptions = GetRequiredService>().Value; + Server = GetRequiredService(); } - - public class GrpcCrossChainClientWithoutParentChainTestBase : AElfIntegratedTest +} + +public class + GrpcCrossChainClientWithoutParentChainTestBase : AElfIntegratedTest< + GrpcCrossChainClientWithoutParentChainTestModule> +{ + protected ChainOptions ChainOptions; + protected IGrpcCrossChainServer Server; + + public GrpcCrossChainClientWithoutParentChainTestBase() { - protected ChainOptions ChainOptions; - protected IGrpcCrossChainServer Server; - - public GrpcCrossChainClientWithoutParentChainTestBase() - { - ChainOptions = GetRequiredService>().Value; - Server = GetRequiredService(); - } + ChainOptions = GetRequiredService>().Value; + Server = GetRequiredService(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestModule.cs b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestModule.cs index e9424d6fa2..18ffdc9caa 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestModule.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Client/GrpcCrossChainClientTestModule.cs @@ -1,97 +1,97 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Grpc.Server; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Modularity; +using AElf.Standards.ACS7; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.CrossChain.Grpc.Client +namespace AElf.CrossChain.Grpc.Client; + +[DependsOn(typeof(GrpcCrossChainTestModule))] +public class GrpcCrossChainClientTestModule : AElfModule { - [DependsOn(typeof(GrpcCrossChainTestModule))] - public class GrpcCrossChainClientTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - services.AddSingleton(); - Configure(option => { option.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); + var services = context.Services; + services.AddSingleton(); + services.AddSingleton(); + Configure(option => { option.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); - services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetChainAsync()) - .Returns(Task.FromResult(new Chain - { - LastIrreversibleBlockHeight = 1 - })); - return mockService.Object; - }); + services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetChainAsync()) + .Returns(Task.FromResult(new Chain + { + LastIrreversibleBlockHeight = 1 + })); + return mockService.Object; + }); - services.AddTransient(o => - { - var mockService = new Mock(); - return mockService.Object; - }); + services.AddTransient(o => + { + var mockService = new Mock(); + return mockService.Object; + }); - services.AddTransient(o => - { - var mockBlockCacheEntityProvider = new Mock(); - mockBlockCacheEntityProvider.Setup(m => m.TryAddBlockCacheEntity(It.IsAny())) - .Returns( - blockCacheEntity => - { - if (!GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache.Contains( + services.AddTransient(o => + { + var mockBlockCacheEntityProvider = new Mock(); + mockBlockCacheEntityProvider.Setup(m => m.TryAddBlockCacheEntity(It.IsAny())) + .Returns( + blockCacheEntity => + { + if (!GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache.Contains( blockCacheEntity)) - { - GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache.Add(blockCacheEntity); - return true; - } - - return false; - }); - return mockBlockCacheEntityProvider.Object; - }); - - services.AddTransient(o => - { - var mockCrossChainResponseService = new Mock(); - int i = 0; - mockCrossChainResponseService.Setup(b => b.ResponseSideChainBlockDataAsync(It.IsAny())) - .Returns( - async () => { - if (i >= GrpcCrossChainCommunicationTestHelper.ServerBlockDataEntityCache.Count) - return null; - return await Task.FromResult(GrpcCrossChainCommunicationTestHelper.ServerBlockDataEntityCache[i++]); - }); + GrpcCrossChainCommunicationTestHelper.ClientBlockDataEntityCache.Add(blockCacheEntity); + return true; + } - mockCrossChainResponseService - .Setup(m => m.ResponseChainInitializationDataFromParentChainAsync(It.IsAny())).Returns(async () => + return false; + }); + return mockBlockCacheEntityProvider.Object; + }); + + services.AddTransient(o => + { + var mockCrossChainResponseService = new Mock(); + var i = 0; + mockCrossChainResponseService.Setup(b => b.ResponseSideChainBlockDataAsync(It.IsAny())) + .Returns( + async () => { - var chainInitializationData = new ChainInitializationData - { - CreationHeightOnParentChain = 1 - }; - return await Task.FromResult(chainInitializationData); + if (i >= GrpcCrossChainCommunicationTestHelper.ServerBlockDataEntityCache.Count) + return null; + return await Task.FromResult( + GrpcCrossChainCommunicationTestHelper.ServerBlockDataEntityCache[i++]); }); - return mockCrossChainResponseService.Object; - }); - } + + mockCrossChainResponseService + .Setup(m => m.ResponseChainInitializationDataFromParentChainAsync(It.IsAny())).Returns(async () => + { + var chainInitializationData = new ChainInitializationData + { + CreationHeightOnParentChain = 1 + }; + return await Task.FromResult(chainInitializationData); + }); + return mockCrossChainResponseService.Object; + }); } +} - [DependsOn(typeof(GrpcCrossChainClientTestModule))] - public class GrpcCrossChainClientWithoutParentChainTestModule : AElfModule +[DependsOn(typeof(GrpcCrossChainClientTestModule))] +public class GrpcCrossChainClientWithoutParentChainTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(option => { option.ParentChainId = string.Empty; }); - } + Configure(option => { option.ParentChainId = string.Empty; }); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainCommunicationTestHelper.cs b/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainCommunicationTestHelper.cs index bc6ef41e8e..dae126c49e 100644 --- a/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainCommunicationTestHelper.cs +++ b/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainCommunicationTestHelper.cs @@ -1,26 +1,21 @@ using System.Collections.Concurrent; using System.Collections.Generic; -using AElf.Standards.ACS7; -using AElf.CrossChain.Cache; using AElf.CrossChain.Communication.Infrastructure; +using AElf.Standards.ACS7; + +namespace AElf.CrossChain.Grpc; -namespace AElf.CrossChain.Grpc +public class GrpcCrossChainCommunicationTestHelper { - public class GrpcCrossChainCommunicationTestHelper - { - public static List ServerBlockDataEntityCache = - new List(); + public static List ServerBlockDataEntityCache = new(); - public static List ClientBlockDataEntityCache = - new List(); + public static List ClientBlockDataEntityCache = new(); - public readonly ConcurrentDictionary GrpcCrossChainClients = - new ConcurrentDictionary(); + public readonly ConcurrentDictionary GrpcCrossChainClients = new(); - public void FakeSideChainBlockDataEntityCacheOnServerSide(int height) - { - var blockInfoCache = new SideChainBlockData {Height = height}; - ServerBlockDataEntityCache.Add(blockInfoCache); - } + public void FakeSideChainBlockDataEntityCacheOnServerSide(int height) + { + var blockInfoCache = new SideChainBlockData { Height = height }; + ServerBlockDataEntityCache.Add(blockInfoCache); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainTestModule.cs b/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainTestModule.cs index 31e9ad9d3e..757644cf9b 100644 --- a/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainTestModule.cs +++ b/test/AElf.CrossChain.Grpc.Tests/GrpcCrossChainTestModule.cs @@ -1,33 +1,30 @@ using AElf.CrossChain.Grpc.Client; using AElf.Kernel; using AElf.Kernel.SmartContract; -using AElf.Kernel.SmartContract.Application; using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; -using Moq; using Volo.Abp.Modularity; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +[DependsOn( + typeof(GrpcCrossChainAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(SmartContractAElfModule) +)] +public class GrpcCrossChainTestModule : AElfModule { - [DependsOn( - typeof(GrpcCrossChainAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(SmartContractAElfModule) - )] - public class GrpcCrossChainTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + Configure(option => { - var services = context.Services; - Configure(option => - { - option.ListeningPort = 5001; - option.ParentChainServerIp = "127.0.0.1"; - option.ParentChainServerPort = 5000; - }); + option.ListeningPort = 5001; + option.ParentChainServerIp = "127.0.0.1"; + option.ParentChainServerPort = 5000; + }); - Configure(option => { option.ParentChainId = "AELF"; }); - services.AddSingleton(); - } + Configure(option => { option.ParentChainId = "AELF"; }); + services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/LocalLibExtensionTest.cs b/test/AElf.CrossChain.Grpc.Tests/LocalLibExtensionTest.cs index 05f49b41a1..bd511b68ee 100644 --- a/test/AElf.CrossChain.Grpc.Tests/LocalLibExtensionTest.cs +++ b/test/AElf.CrossChain.Grpc.Tests/LocalLibExtensionTest.cs @@ -13,83 +13,81 @@ using Volo.Abp.Modularity; using Xunit; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public class CrossChainLibExtensionModule : AElfModule { - public class CrossChainLibExtensionModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var dictionary = new Dictionary { - var dictionary = new Dictionary - { - {1, HashHelper.ComputeFrom("1")}, - {2, HashHelper.ComputeFrom("2")}, - {3, HashHelper.ComputeFrom("3")} - }; - context.Services.AddTransient(provider => + { 1, HashHelper.ComputeFrom("1") }, + { 2, HashHelper.ComputeFrom("2") }, + { 3, HashHelper.ComputeFrom("3") } + }; + context.Services.AddTransient(provider => + { + var mockBlockChainService = new Mock(); + mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(Task.FromResult(new Chain { - var mockBlockChainService = new Mock(); - mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(Task.FromResult(new Chain + LastIrreversibleBlockHeight = CrossChainConstants.LibHeightOffsetForCrossChainIndex + 1 + })); + mockBlockChainService.Setup(m => + m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((chain, height, hash) => { - LastIrreversibleBlockHeight = CrossChainConstants.LibHeightOffsetForCrossChainIndex + 1 - })); - mockBlockChainService.Setup(m => m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns((chain, height, hash) => - { - if (height > 0 && height <= 3) - return Task.FromResult(dictionary[height]); - return Task.FromResult(null); - }); - mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => - { - foreach (var kv in dictionary) - { - if (kv.Value.Equals(hash)) - return Task.FromResult(new Block {Header = new BlockHeader {Height = kv.Key}}); - } - - return Task.FromResult(null); + if (height > 0 && height <= 3) + return Task.FromResult(dictionary[height]); + return Task.FromResult(null); }); - return mockBlockChainService.Object; + mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(hash => + { + foreach (var kv in dictionary) + if (kv.Value.Equals(hash)) + return Task.FromResult(new Block { Header = new BlockHeader { Height = kv.Key } }); + + return Task.FromResult(null); }); - } + return mockBlockChainService.Object; + }); } - - public sealed class LocalLibExtensionTest : AElfIntegratedTest +} + +public sealed class LocalLibExtensionTest : AElfIntegratedTest +{ + private readonly IBlockchainService _blockchainService; + + public LocalLibExtensionTest() { - private readonly IBlockchainService _blockchainService; - - public LocalLibExtensionTest() - { - _blockchainService = GetService(); - } - - [Fact] - public async Task GetLibHeight_Test() - { - var lastIrreversibleBlockDto = await _blockchainService.GetLibHashAndHeightAsync(); - lastIrreversibleBlockDto.BlockHeight.ShouldBe(CrossChainConstants.LibHeightOffsetForCrossChainIndex + 1); - } + _blockchainService = GetService(); + } - [Fact] - public async Task GetIrreversibleBlockByHeight_Test() - { - var height = 2; - var irreversibleBlock = await _blockchainService.GetIrreversibleBlockByHeightAsync(height); - irreversibleBlock.ShouldBeNull(); + [Fact] + public async Task GetLibHeight_Test() + { + var lastIrreversibleBlockDto = await _blockchainService.GetLibHashAndHeightAsync(); + lastIrreversibleBlockDto.BlockHeight.ShouldBe(CrossChainConstants.LibHeightOffsetForCrossChainIndex + 1); + } - height = 1; - irreversibleBlock = await _blockchainService.GetIrreversibleBlockByHeightAsync(height); - var expectedBlock = new Block {Header = new BlockHeader {Height = height}}; - irreversibleBlock.Equals(expectedBlock).ShouldBeTrue(); - } + [Fact] + public async Task GetIrreversibleBlockByHeight_Test() + { + var height = 2; + var irreversibleBlock = await _blockchainService.GetIrreversibleBlockByHeightAsync(height); + irreversibleBlock.ShouldBeNull(); - [Fact] - public void GrpcCrossChainRequestExceptionTest() - { - var message = "message"; - Should.Throw(() => throw new GrpcCrossChainRequestException(message)); - Should.Throw(() => - throw new GrpcCrossChainRequestException(message, new Exception())); - } + height = 1; + irreversibleBlock = await _blockchainService.GetIrreversibleBlockByHeightAsync(height); + var expectedBlock = new Block { Header = new BlockHeader { Height = height } }; + irreversibleBlock.Equals(expectedBlock).ShouldBeTrue(); + } + + [Fact] + public void GrpcCrossChainRequestExceptionTest() + { + var message = "message"; + Should.Throw(() => throw new GrpcCrossChainRequestException(message)); + Should.Throw(() => + throw new GrpcCrossChainRequestException(message, new Exception())); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerNodePluginTests.cs b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerNodePluginTests.cs index e44d64eccf..ce5f9576ed 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerNodePluginTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerNodePluginTests.cs @@ -2,27 +2,26 @@ using AElf.CrossChain.Communication; using Xunit; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public sealed class GrpcCrossChainServerNodePluginTests : GrpcCrossChainServerTestBase { - public sealed class GrpcCrossChainServerNodePluginTests : GrpcCrossChainServerTestBase - { - private readonly ICrossChainCommunicationPlugin _grpcCrossChainServerNodePlugin; - private readonly IGrpcCrossChainServer _grpcCrossChainServer; + private readonly IGrpcCrossChainServer _grpcCrossChainServer; + private readonly ICrossChainCommunicationPlugin _grpcCrossChainServerNodePlugin; - public GrpcCrossChainServerNodePluginTests() - { - _grpcCrossChainServer = GetRequiredService(); - _grpcCrossChainServerNodePlugin = GetRequiredService(); - } + public GrpcCrossChainServerNodePluginTests() + { + _grpcCrossChainServer = GetRequiredService(); + _grpcCrossChainServerNodePlugin = GetRequiredService(); + } - [Fact] - public async Task CrossChainServerStart_Test() - { - var localChainId = ChainHelper.GetChainId(1); - await _grpcCrossChainServerNodePlugin.StartAsync(localChainId); - Assert.True(_grpcCrossChainServer.IsStarted); - await _grpcCrossChainServerNodePlugin.ShutdownAsync(); - Assert.False(_grpcCrossChainServer.IsStarted); - } + [Fact] + public async Task CrossChainServerStart_Test() + { + var localChainId = ChainHelper.GetChainId(1); + await _grpcCrossChainServerNodePlugin.StartAsync(localChainId); + Assert.True(_grpcCrossChainServer.IsStarted); + await _grpcCrossChainServerNodePlugin.ShutdownAsync(); + Assert.False(_grpcCrossChainServer.IsStarted); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestBase.cs b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestBase.cs index c9eb301a16..1e5b49ca44 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestBase.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestBase.cs @@ -4,28 +4,27 @@ [assembly: CollectionBehavior(DisableTestParallelization = true)] -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcCrossChainServerTestBase : AElfIntegratedTest { - public class GrpcCrossChainServerTestBase : AElfIntegratedTest - { - private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; + private readonly ICrossChainClientProvider _grpcCrossChainClientProvider; - public GrpcCrossChainServerTestBase() - { - _grpcCrossChainClientProvider = GetRequiredService(); - } + public GrpcCrossChainServerTestBase() + { + _grpcCrossChainClientProvider = GetRequiredService(); + } - public void CreateAndCacheClient(int chainId, bool toParenChain, int port, int remoteChainId = 0) + public void CreateAndCacheClient(int chainId, bool toParenChain, int port, int remoteChainId = 0) + { + var fakeCrossChainClient = new CrossChainClientCreationContext { - var fakeCrossChainClient = new CrossChainClientCreationContext - { - LocalChainId = chainId, - RemoteChainId = remoteChainId, - IsClientToParentChain = toParenChain, - RemoteServerHost = "localhost", - RemoteServerPort = port - }; - _grpcCrossChainClientProvider.AddOrUpdateClient(fakeCrossChainClient); - } + LocalChainId = chainId, + RemoteChainId = remoteChainId, + IsClientToParentChain = toParenChain, + RemoteServerHost = "localhost", + RemoteServerPort = port + }; + _grpcCrossChainClientProvider.AddOrUpdateClient(fakeCrossChainClient); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestModule.cs b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestModule.cs index 03562a46be..74fa1928c7 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestModule.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcCrossChainServerTestModule.cs @@ -1,97 +1,96 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; using AElf.CrossChain.Cache.Application; using AElf.CrossChain.Communication; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Modularity; +using AElf.Standards.ACS7; using AElf.Types; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +[DependsOn(typeof(GrpcCrossChainTestModule))] +public class GrpcCrossChainServerTestModule : AElfModule { - [DependsOn(typeof(GrpcCrossChainTestModule))] - public class GrpcCrossChainServerTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + base.ConfigureServices(context); + + var services = context.Services; + services.AddSingleton(); + services.AddTransient(o => { - base.ConfigureServices(context); + var kernelTestHelper = context.Services.GetRequiredServiceLazy(); + var mockService = new Mock(); + mockService.Setup(m => m.GetChainAsync()) + .Returns(Task.FromResult(new Chain + { + LastIrreversibleBlockHeight = 10 + })); + mockService.Setup(m => + m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(HashHelper.ComputeFrom("hash"))); + mockService.Setup(m => m.GetBlockByHashAsync(It.IsAny())) + .Returns(() => + { + var previousBlockHash = HashHelper.ComputeFrom("previousBlockHash"); + return Task.FromResult(kernelTestHelper.Value.GenerateBlock(9, previousBlockHash)); + }); + return mockService.Object; + }); - var services = context.Services; - services.AddSingleton(); - services.AddTransient(o => - { - var kernelTestHelper = context.Services.GetRequiredServiceLazy(); - var mockService = new Mock(); - mockService.Setup(m => m.GetChainAsync()) - .Returns(Task.FromResult(new Chain - { - LastIrreversibleBlockHeight = 10 - })); - mockService.Setup(m => - m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(HashHelper.ComputeFrom("hash"))); - mockService.Setup(m => m.GetBlockByHashAsync(It.IsAny())) - .Returns(() => + services.AddTransient(o => + { + var mockCrossChainResponseService = new Mock(); + mockCrossChainResponseService + .Setup(c => c.ResponseParentChainBlockDataAsync(It.IsAny(), It.IsAny())).Returns( + (height, chainId) => { - var previousBlockHash = HashHelper.ComputeFrom("previousBlockHash"); - return Task.FromResult(kernelTestHelper.Value.GenerateBlock(9, previousBlockHash)); - }); - return mockService.Object; - }); + if (height > 100) + return Task.FromResult(null); - services.AddTransient(o => - { - var mockCrossChainResponseService = new Mock(); - mockCrossChainResponseService - .Setup(c => c.ResponseParentChainBlockDataAsync(It.IsAny(), It.IsAny())).Returns( - (height, chainId) => + var parentChanBlockData = new ParentChainBlockData { - if (height > 100) - return Task.FromResult(null); - - var parentChanBlockData = new ParentChainBlockData - { - ChainId = chainId, - Height = height, - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot") - }; - return Task.FromResult(parentChanBlockData); - }); - mockCrossChainResponseService - .Setup(c => c.ResponseSideChainBlockDataAsync(It.IsAny())).Returns( - (height) => + ChainId = chainId, + Height = height, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom("TransactionStatusMerkleRoot") + }; + return Task.FromResult(parentChanBlockData); + }); + mockCrossChainResponseService + .Setup(c => c.ResponseSideChainBlockDataAsync(It.IsAny())).Returns( + height => + { + if (height > 100) + return Task.FromResult(null); + var sideChanBlockData = new SideChainBlockData { - if (height > 100) - return Task.FromResult(null); - var sideChanBlockData = new SideChainBlockData() - { - ChainId = ChainHelper.GetChainId(1), - Height = height, - }; - return Task.FromResult(sideChanBlockData); - }); - mockCrossChainResponseService - .Setup(c => c.ResponseChainInitializationDataFromParentChainAsync(It.IsAny())).Returns( - () => + ChainId = ChainHelper.GetChainId(1), + Height = height + }; + return Task.FromResult(sideChanBlockData); + }); + mockCrossChainResponseService + .Setup(c => c.ResponseChainInitializationDataFromParentChainAsync(It.IsAny())).Returns( + () => + { + var chainInitializationData = new ChainInitializationData { - var chainInitializationData = new ChainInitializationData() - { - CreationHeightOnParentChain = 1 - }; - return Task.FromResult(chainInitializationData); - }); - return mockCrossChainResponseService.Object; - }); + CreationHeightOnParentChain = 1 + }; + return Task.FromResult(chainInitializationData); + }); + return mockCrossChainResponseService.Object; + }); - services.AddTransient(o => - { - var mockService = new Mock(); - return mockService.Object; - }); - } + services.AddTransient(o => + { + var mockService = new Mock(); + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcServerTests.cs b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcServerTests.cs index 8ffb4b937c..7ecf637d47 100644 --- a/test/AElf.CrossChain.Grpc.Tests/Server/GrpcServerTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/Server/GrpcServerTests.cs @@ -2,10 +2,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS7; using Grpc.Core; using Grpc.Core.Testing; using Grpc.Core.Utils; @@ -13,165 +13,163 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Grpc.Server +namespace AElf.CrossChain.Grpc.Server; + +public class GrpcServerTests : GrpcCrossChainServerTestBase { - public class GrpcServerTests : GrpcCrossChainServerTestBase - { - private ParentChainRpc.ParentChainRpcBase ParentChainGrpcServerBase; - private SideChainRpc.SideChainRpcBase SideChainGrpcServerBase; - private BasicCrossChainRpc.BasicCrossChainRpcBase BasicCrossChainRpcBase; + private ISmartContractAddressService _smartContractAddressService; + private BasicCrossChainRpc.BasicCrossChainRpcBase BasicCrossChainRpcBase; + private ParentChainRpc.ParentChainRpcBase ParentChainGrpcServerBase; + private SideChainRpc.SideChainRpcBase SideChainGrpcServerBase; - private ISmartContractAddressService _smartContractAddressService; + public GrpcServerTests() + { + ParentChainGrpcServerBase = GetRequiredService(); + SideChainGrpcServerBase = GetRequiredService(); + BasicCrossChainRpcBase = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + // _smartContractAddressService.SetAddress(CrossChainSmartContractAddressNameProvider.Name, + // SampleAddress.AddressList[0]); + } - public GrpcServerTests() + [Fact] + public async Task RequestIndexingParentChain_MaximalResponse_Test() + { + var requestData = new CrossChainRequest { - ParentChainGrpcServerBase = GetRequiredService(); - SideChainGrpcServerBase = GetRequiredService(); - BasicCrossChainRpcBase = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - // _smartContractAddressService.SetAddress(CrossChainSmartContractAddressNameProvider.Name, - // SampleAddress.AddressList[0]); - } + ChainId = ChainHelper.GetChainId(1), + NextHeight = 10 + }; + + var responseResults = new List(); + var responseStream = MockServerStreamWriter(responseResults); + var context = BuildServerCallContext(); + await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); + Assert.Equal(GrpcCrossChainConstants.MaximalIndexingCount, responseResults.Count); + Assert.Equal(10, responseResults[0].Height); + } - [Fact] - public async Task RequestIndexingParentChain_MaximalResponse_Test() + [Fact] + public async Task RequestIndexingParentChain_EmptyResponse_Test() + { + var requestData = new CrossChainRequest { - var requestData = new CrossChainRequest - { - ChainId = ChainHelper.GetChainId(1), - NextHeight = 10 - }; - - var responseResults = new List(); - IServerStreamWriter responseStream = MockServerStreamWriter(responseResults); - var context = BuildServerCallContext(); - await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); - Assert.Equal(GrpcCrossChainConstants.MaximalIndexingCount, responseResults.Count); - Assert.Equal(10, responseResults[0].Height); - } + ChainId = ChainHelper.GetChainId(1), + NextHeight = 101 + }; + + var responseResults = new List(); + var responseStream = MockServerStreamWriter(responseResults); + var context = BuildServerCallContext(); + await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); + Assert.Empty(responseResults); + } - [Fact] - public async Task RequestIndexingParentChain_EmptyResponse_Test() - { - var requestData = new CrossChainRequest - { - ChainId = ChainHelper.GetChainId(1), - NextHeight = 101 - }; - - var responseResults = new List(); - IServerStreamWriter responseStream = MockServerStreamWriter(responseResults); - var context = BuildServerCallContext(); - await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); - Assert.Empty(responseResults); - } - - [Fact] - public async Task RequestIndexingParentChain_SpecificResponse_Test() + [Fact] + public async Task RequestIndexingParentChain_SpecificResponse_Test() + { + var requestData = new CrossChainRequest { - var requestData = new CrossChainRequest - { - ChainId = ChainHelper.GetChainId(1), - NextHeight = 81 - }; - - var responseResults = new List(); - IServerStreamWriter responseStream = MockServerStreamWriter(responseResults); - var context = BuildServerCallContext(); - await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); - Assert.Equal(20, responseResults.Count); - Assert.Equal(81, responseResults.First().Height); - Assert.Equal(100, responseResults.Last().Height); - } + ChainId = ChainHelper.GetChainId(1), + NextHeight = 81 + }; + + var responseResults = new List(); + var responseStream = MockServerStreamWriter(responseResults); + var context = BuildServerCallContext(); + await ParentChainGrpcServerBase.RequestIndexingFromParentChain(requestData, responseStream, context); + Assert.Equal(20, responseResults.Count); + Assert.Equal(81, responseResults.First().Height); + Assert.Equal(100, responseResults.Last().Height); + } - [Fact] - public async Task RequestIndexingSideChain_MaximalResponse_Test() + [Fact] + public async Task RequestIndexingSideChain_MaximalResponse_Test() + { + var requestData = new CrossChainRequest { - var requestData = new CrossChainRequest - { - ChainId = ChainHelper.GetChainId(1), - NextHeight = 10 - }; - - var responseResults = new List(); - IServerStreamWriter responseStream = MockServerStreamWriter(responseResults); - var context = BuildServerCallContext(); - await SideChainGrpcServerBase.RequestIndexingFromSideChain(requestData, responseStream, context); - Assert.Equal(GrpcCrossChainConstants.MaximalIndexingCount, responseResults.Count); - Assert.Equal(10, responseResults[0].Height); - } - - [Fact] - public async Task RequestIndexingSideChain_EmptyResponse_Test() + ChainId = ChainHelper.GetChainId(1), + NextHeight = 10 + }; + + var responseResults = new List(); + var responseStream = MockServerStreamWriter(responseResults); + var context = BuildServerCallContext(); + await SideChainGrpcServerBase.RequestIndexingFromSideChain(requestData, responseStream, context); + Assert.Equal(GrpcCrossChainConstants.MaximalIndexingCount, responseResults.Count); + Assert.Equal(10, responseResults[0].Height); + } + + [Fact] + public async Task RequestIndexingSideChain_EmptyResponse_Test() + { + var requestData = new CrossChainRequest { - var requestData = new CrossChainRequest - { - ChainId = ChainHelper.GetChainId(1), - NextHeight = 101 - }; - - var responseResults = new List(); - IServerStreamWriter responseStream = MockServerStreamWriter(responseResults); - var context = BuildServerCallContext(); - await SideChainGrpcServerBase.RequestIndexingFromSideChain(requestData, responseStream, context); - Assert.Empty(responseResults); - } + ChainId = ChainHelper.GetChainId(1), + NextHeight = 101 + }; + + var responseResults = new List(); + var responseStream = MockServerStreamWriter(responseResults); + var context = BuildServerCallContext(); + await SideChainGrpcServerBase.RequestIndexingFromSideChain(requestData, responseStream, context); + Assert.Empty(responseResults); + } - [Fact] - public async Task CrossChainIndexingShake_Test() + [Fact] + public async Task CrossChainIndexingShake_Test() + { + var request = new HandShake { - var request = new HandShake - { - ListeningPort = 2100, - ChainId = ChainHelper.GetChainId(1) - }; - { - // invalid peer format - var context = BuildServerCallContext(null, "127.0.0.1"); - var indexingHandShakeReply = await BasicCrossChainRpcBase.CrossChainHandShake(request, context); - indexingHandShakeReply.Status.ShouldBe(HandShakeReply.Types.HandShakeStatus.InvalidHandshakeRequest); - } - - { - var context = BuildServerCallContext(); - var indexingHandShakeReply = await BasicCrossChainRpcBase.CrossChainHandShake(request, context); - - Assert.NotNull(indexingHandShakeReply); - Assert.True(indexingHandShakeReply.Status == HandShakeReply.Types.HandShakeStatus.Success); - } + ListeningPort = 2100, + ChainId = ChainHelper.GetChainId(1) + }; + { + // invalid peer format + var context = BuildServerCallContext(null, "127.0.0.1"); + var indexingHandShakeReply = await BasicCrossChainRpcBase.CrossChainHandShake(request, context); + indexingHandShakeReply.Status.ShouldBe(HandShakeReply.Types.HandShakeStatus.InvalidHandshakeRequest); } - [Fact] - public async Task RequestChainInitializationDataFromParentChain_Test() { - var requestData = new SideChainInitializationRequest - { - ChainId = ChainHelper.GetChainId(1), - }; var context = BuildServerCallContext(); - var sideChainInitializationResponse = - await ParentChainGrpcServerBase.RequestChainInitializationDataFromParentChain(requestData, context); - Assert.Equal(1, sideChainInitializationResponse.CreationHeightOnParentChain); + var indexingHandShakeReply = await BasicCrossChainRpcBase.CrossChainHandShake(request, context); + + Assert.NotNull(indexingHandShakeReply); + Assert.True(indexingHandShakeReply.Status == HandShakeReply.Types.HandShakeStatus.Success); } + } - private ServerCallContext BuildServerCallContext(Metadata metadata = null, string peer = null) + [Fact] + public async Task RequestChainInitializationDataFromParentChain_Test() + { + var requestData = new SideChainInitializationRequest { - var meta = metadata ?? new Metadata(); - return TestServerCallContext.Create("mock", "127.0.0.1", - TimestampHelper.GetUtcNow().AddHours(1).ToDateTime(), meta, CancellationToken.None, - peer ?? "ipv4:127.0.0.1:2100", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), - writeOptions => { }); - } + ChainId = ChainHelper.GetChainId(1) + }; + var context = BuildServerCallContext(); + var sideChainInitializationResponse = + await ParentChainGrpcServerBase.RequestChainInitializationDataFromParentChain(requestData, context); + Assert.Equal(1, sideChainInitializationResponse.CreationHeightOnParentChain); + } - private IServerStreamWriter MockServerStreamWriter(IList list) + private ServerCallContext BuildServerCallContext(Metadata metadata = null, string peer = null) + { + var meta = metadata ?? new Metadata(); + return TestServerCallContext.Create("mock", "127.0.0.1", + TimestampHelper.GetUtcNow().AddHours(1).ToDateTime(), meta, CancellationToken.None, + peer ?? "ipv4:127.0.0.1:2100", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), + writeOptions => { }); + } + + private IServerStreamWriter MockServerStreamWriter(IList list) + { + var mockServerStreamWriter = new Mock>(); + mockServerStreamWriter.Setup(w => w.WriteAsync(It.IsAny())).Returns(o => { - var mockServerStreamWriter = new Mock>(); - mockServerStreamWriter.Setup(w => w.WriteAsync(It.IsAny())).Returns(o => - { - list.Add(o); - return Task.CompletedTask; - }); - return mockServerStreamWriter.Object; - } + list.Add(o); + return Task.CompletedTask; + }); + return mockServerStreamWriter.Object; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Grpc.Tests/UriHelperTests.cs b/test/AElf.CrossChain.Grpc.Tests/UriHelperTests.cs index a639d85778..cf854800ee 100644 --- a/test/AElf.CrossChain.Grpc.Tests/UriHelperTests.cs +++ b/test/AElf.CrossChain.Grpc.Tests/UriHelperTests.cs @@ -1,31 +1,30 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain.Grpc +namespace AElf.CrossChain.Grpc; + +public class UriHelperTests { - public class UriHelperTests + [Fact] + public void GrpcUrl_ParseTest() { - [Fact] - public void GrpcUrl_ParseTest() + //wrong format + { + var address = "127.0.0.1:8000"; + var parsed = GrpcUriHelper.TryParsePrefixedEndpoint(address, out var endpoint); + + parsed.ShouldBeFalse(); + endpoint.ShouldBeNull(); + } + + //correct format { - //wrong format - { - string address = "127.0.0.1:8000"; - var parsed = GrpcUriHelper.TryParsePrefixedEndpoint(address, out var endpoint); + var address = "ipv4:127.0.0.1:8000"; + var parsed = GrpcUriHelper.TryParsePrefixedEndpoint(address, out var endpoint); - parsed.ShouldBeFalse(); - endpoint.ShouldBeNull(); - } - - //correct format - { - string address = "ipv4:127.0.0.1:8000"; - var parsed = GrpcUriHelper.TryParsePrefixedEndpoint(address, out var endpoint); - - parsed.ShouldBeTrue(); - endpoint.ToString().ShouldBe("127.0.0.1:8000"); - endpoint.Port.ShouldBe(8000); - } + parsed.ShouldBeTrue(); + endpoint.ToString().ShouldBe("127.0.0.1:8000"); + endpoint.Port.ShouldBe(8000); } } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/AElf.CrossChain.Tests.csproj b/test/AElf.CrossChain.Tests/AElf.CrossChain.Tests.csproj index fdd1a28bdd..6b88e05a92 100644 --- a/test/AElf.CrossChain.Tests/AElf.CrossChain.Tests.csproj +++ b/test/AElf.CrossChain.Tests/AElf.CrossChain.Tests.csproj @@ -6,19 +6,19 @@ - - - - - - - + + + + + + + - - - + + + diff --git a/test/AElf.CrossChain.Tests/CrossChainBlockExtraDataProviderTests.cs b/test/AElf.CrossChain.Tests/CrossChainBlockExtraDataProviderTests.cs index ffafb6b855..87cea1b2ac 100644 --- a/test/AElf.CrossChain.Tests/CrossChainBlockExtraDataProviderTests.cs +++ b/test/AElf.CrossChain.Tests/CrossChainBlockExtraDataProviderTests.cs @@ -1,85 +1,82 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Txn.Application; -using AElf.Types; +using AElf.Standards.ACS7; using Google.Protobuf; -using Microsoft.Extensions.Options; using Xunit; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainBlockExtraDataProviderTest : CrossChainTestBase { - public class CrossChainBlockExtraDataProviderTest : CrossChainTestBase + private readonly IBlockExtraDataProvider _crossChainBlockExtraDataProvider; + private readonly CrossChainTestHelper _crossChainTestHelper; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + + public CrossChainBlockExtraDataProviderTest() { - private readonly IBlockExtraDataProvider _crossChainBlockExtraDataProvider; - private readonly CrossChainTestHelper _crossChainTestHelper; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - - public CrossChainBlockExtraDataProviderTest() - { - _crossChainBlockExtraDataProvider = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); - _transactionPackingOptionProvider = GetRequiredService(); - } - - [Fact] - public async Task FillExtraData_GenesisHeight_Test() + _crossChainBlockExtraDataProvider = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + _transactionPackingOptionProvider = GetRequiredService(); + } + + [Fact] + public async Task FillExtraData_GenesisHeight_Test() + { + var header = new BlockHeader { - var header = new BlockHeader - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 1 - }; - var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); - Assert.Empty(bytes); - } - - [Fact] - public async Task FillExtraData__NoPendingProposal_Test() + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 1 + }; + var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); + Assert.Empty(bytes); + } + + [Fact] + public async Task FillExtraData__NoPendingProposal_Test() + { + var header = new BlockHeader { - var header = new BlockHeader - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 2 - }; - var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); - Assert.Empty(bytes); - } + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 2 + }; + var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); + Assert.Empty(bytes); + } - [Fact] - public async Task FIllExtraData_TransactionPackingDisabled() + [Fact] + public async Task FIllExtraData_TransactionPackingDisabled() + { + var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot"); + var expected = new CrossChainExtraData { TransactionStatusMerkleTreeRoot = merkleTreeRoot }; + var header = new BlockHeader + { + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 2 + }; + _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected); + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex { - var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot"); - var expected = new CrossChainExtraData {TransactionStatusMerkleTreeRoot = merkleTreeRoot}; - var header = new BlockHeader - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 2 - }; - _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected); - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex - { - BlockHash = header.PreviousBlockHash, - BlockHeight = header.Height - 1 - }, false); - var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); - Assert.Empty(bytes); - } + BlockHash = header.PreviousBlockHash, + BlockHeight = header.Height - 1 + }, false); + var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); + Assert.Empty(bytes); + } - [Fact] - public async Task FillExtraData_Test() + [Fact] + public async Task FillExtraData_Test() + { + var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot"); + var expected = new CrossChainExtraData { TransactionStatusMerkleTreeRoot = merkleTreeRoot }; + var header = new BlockHeader { - var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot"); - var expected = new CrossChainExtraData {TransactionStatusMerkleTreeRoot = merkleTreeRoot}; - var header = new BlockHeader - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), - Height = 2 - }; - _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected); - var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); - Assert.Equal(expected.ToByteString(), bytes); - } + PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"), + Height = 2 + }; + _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected); + var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header); + Assert.Equal(expected.ToByteString(), bytes); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainIndexingTransactionGeneratorTests.cs b/test/AElf.CrossChain.Tests/CrossChainIndexingTransactionGeneratorTests.cs index f8c98fe9af..775f284b4e 100644 --- a/test/AElf.CrossChain.Tests/CrossChainIndexingTransactionGeneratorTests.cs +++ b/test/AElf.CrossChain.Tests/CrossChainIndexingTransactionGeneratorTests.cs @@ -1,105 +1,100 @@ -using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.Contracts.CrossChain; using AElf.CrossChain.Indexing.Infrastructure; using AElf.Kernel; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Domain; -using AElf.Types; +using AElf.Standards.ACS7; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public sealed class CrossChainIndexingTransactionGeneratorTest : CrossChainTestBase { - public sealed class CrossChainIndexingTransactionGeneratorTest : CrossChainTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ISystemTransactionGenerator _crossChainIndexingTransactionGenerator; + private readonly CrossChainTestHelper _crossChainTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + + public CrossChainIndexingTransactionGeneratorTest() { - private readonly ISystemTransactionGenerator _crossChainIndexingTransactionGenerator; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly CrossChainTestHelper _crossChainTestHelper; - private readonly IBlockStateSetManger _blockStateSetManger; + _crossChainIndexingTransactionGenerator = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } - public CrossChainIndexingTransactionGeneratorTest() - { - _crossChainIndexingTransactionGenerator = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } + [Fact] + public async Task GenerateTransactions_Test() + { + var sideChainId = 123; + var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); + var previousBlockHeight = 1; + var crossChainBlockData = new CrossChainBlockData(); - [Fact] - public async Task GenerateTransactions_Test() + var cachingCount = 5; + for (var i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) { - var sideChainId = 123; - var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); - var previousBlockHeight = 1; - var crossChainBlockData = new CrossChainBlockData + var sideChainBlockData = new SideChainBlockData { + ChainId = sideChainId, + Height = i + 1, + TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) }; - - var cachingCount = 5; - for (int i = 1; i < cachingCount + CrossChainConstants.DefaultBlockCacheEntityCount; i++) - { - var sideChainBlockData = new SideChainBlockData() - { - ChainId = sideChainId, - Height = (i + 1), - TransactionStatusMerkleTreeRoot = HashHelper.ComputeFrom((sideChainId + 1).ToString()) - }; - if (i <= CrossChainConstants.DefaultBlockCacheEntityCount) - crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); - } + if (i <= CrossChainConstants.DefaultBlockCacheEntityCount) + crossChainBlockData.SideChainBlockDataList.Add(sideChainBlockData); + } - var crossChainTransactionInput = new CrossChainTransactionInput - { - Value = crossChainBlockData.ToByteString(), - MethodName = nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing), - PreviousBlockHeight = previousBlockHeight - }; - _crossChainTestHelper.AddFakeCrossChainTransactionInput(previousBlockHash, crossChainTransactionInput); - // AddFakeCacheData(new Dictionary> {{sideChainId, sideChainBlockInfoCache}}); + var crossChainTransactionInput = new CrossChainTransactionInput + { + Value = crossChainBlockData.ToByteString(), + MethodName = nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing), + PreviousBlockHeight = previousBlockHeight + }; + _crossChainTestHelper.AddFakeCrossChainTransactionInput(previousBlockHash, crossChainTransactionInput); + // AddFakeCacheData(new Dictionary> {{sideChainId, sideChainBlockInfoCache}}); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = previousBlockHash, - BlockHeight = previousBlockHeight - }); + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = previousBlockHash, + BlockHeight = previousBlockHeight + }); - var transactions = - await _crossChainIndexingTransactionGenerator.GenerateTransactionsAsync(SampleAddress.AddressList[0], - previousBlockHeight, previousBlockHash); + var transactions = + await _crossChainIndexingTransactionGenerator.GenerateTransactionsAsync(SampleAddress.AddressList[0], + previousBlockHeight, previousBlockHash); - transactions.Count.ShouldBe(1); - transactions[0].From.ShouldBe(SampleAddress.AddressList[0]); - transactions[0].To.ShouldBeNull(); - transactions[0].RefBlockNumber.ShouldBe(previousBlockHeight); - - transactions[0].RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(previousBlockHash)); - transactions[0].MethodName - .ShouldBe(nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing)); + transactions.Count.ShouldBe(1); + transactions[0].From.ShouldBe(SampleAddress.AddressList[0]); + transactions[0].To.ShouldBeNull(); + transactions[0].RefBlockNumber.ShouldBe(previousBlockHeight); - var crossChainBlockDataInParam = CrossChainBlockData.Parser.ParseFrom(transactions[0].Params); - Assert.Equal(crossChainBlockData, crossChainBlockDataInParam); - } - - [Fact] - public async Task GenerateTransaction_NoTransaction_Test() + transactions[0].RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(previousBlockHash)); + transactions[0].MethodName + .ShouldBe(nameof(CrossChainContractImplContainer.CrossChainContractImplStub.ProposeCrossChainIndexing)); + + var crossChainBlockDataInParam = CrossChainBlockData.Parser.ParseFrom(transactions[0].Params); + Assert.Equal(crossChainBlockData, crossChainBlockDataInParam); + } + + [Fact] + public async Task GenerateTransaction_NoTransaction_Test() + { + var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); + var previousBlockHeight = 1; + var smartContractAddress = SampleAddress.AddressList[0]; + await _smartContractAddressService.SetSmartContractAddressAsync(new BlockIndex { - var previousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"); - var previousBlockHeight = 1; - var smartContractAddress = SampleAddress.AddressList[0]; - await _smartContractAddressService.SetSmartContractAddressAsync(new BlockIndex - { - BlockHash = previousBlockHash, - BlockHeight = previousBlockHeight - }, CrossChainSmartContractAddressNameProvider.StringName, smartContractAddress); - var transactions = - await _crossChainIndexingTransactionGenerator.GenerateTransactionsAsync(SampleAddress.AddressList[0], - previousBlockHeight, previousBlockHash); - - Assert.Empty(transactions); - } + BlockHash = previousBlockHash, + BlockHeight = previousBlockHeight + }, CrossChainSmartContractAddressNameProvider.StringName, smartContractAddress); + var transactions = + await _crossChainIndexingTransactionGenerator.GenerateTransactionsAsync(SampleAddress.AddressList[0], + previousBlockHeight, previousBlockHash); + + Assert.Empty(transactions); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainServiceTests.cs b/test/AElf.CrossChain.Tests/CrossChainServiceTests.cs index 0b3622b932..50496c660c 100644 --- a/test/AElf.CrossChain.Tests/CrossChainServiceTests.cs +++ b/test/AElf.CrossChain.Tests/CrossChainServiceTests.cs @@ -6,39 +6,38 @@ using Shouldly; using Xunit; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainServiceTest : CrossChainTestBase { - public class CrossChainServiceTest : CrossChainTestBase + private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; + private readonly CrossChainConfigOptions _crossChainConfigOptions; + private readonly ICrossChainService _crossChainService; + private readonly CrossChainTestHelper _crossChainTestHelper; + + public CrossChainServiceTest() { - private readonly ICrossChainService _crossChainService; - private readonly CrossChainTestHelper _crossChainTestHelper; - private readonly ICrossChainCacheEntityService _crossChainCacheEntityService; - private readonly CrossChainConfigOptions _crossChainConfigOptions; - - public CrossChainServiceTest() - { - _crossChainService = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); - _crossChainCacheEntityService = GetRequiredService(); - _crossChainConfigOptions = GetRequiredService>().Value; - } - - [Fact] - public async Task FinishInitialSync_Test() + _crossChainService = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + _crossChainCacheEntityService = GetRequiredService(); + _crossChainConfigOptions = GetRequiredService>().Value; + } + + [Fact] + public async Task FinishInitialSync_Test() + { + var chainId = ChainHelper.ConvertBase58ToChainId("AELF"); + long libHeight = 10; + _crossChainTestHelper.AddFakeChainIdHeight(chainId, libHeight); + _crossChainConfigOptions.CrossChainDataValidationIgnored.ShouldBeTrue(); + await _crossChainService.FinishInitialSyncAsync(); + _crossChainConfigOptions.CrossChainDataValidationIgnored.ShouldBeFalse(); + + var height = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); { - int chainId = ChainHelper.ConvertBase58ToChainId("AELF"); - long libHeight = 10; - _crossChainTestHelper.AddFakeChainIdHeight(chainId, libHeight); - _crossChainConfigOptions.CrossChainDataValidationIgnored.ShouldBeTrue(); - await _crossChainService.FinishInitialSyncAsync(); - _crossChainConfigOptions.CrossChainDataValidationIgnored.ShouldBeFalse(); - - var height = _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId); - { - Should.Throw(() => - _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId - 1)); - } - Assert.Equal(libHeight + 1, height); + Should.Throw(() => + _crossChainCacheEntityService.GetTargetHeightForChainCacheEntity(chainId - 1)); } + Assert.Equal(libHeight + 1, height); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainTestBase.cs b/test/AElf.CrossChain.Tests/CrossChainTestBase.cs index c72811f845..324fae3b1a 100644 --- a/test/AElf.CrossChain.Tests/CrossChainTestBase.cs +++ b/test/AElf.CrossChain.Tests/CrossChainTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainTestBase : AElfIntegratedTest { - public class CrossChainTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainTestHelper.cs b/test/AElf.CrossChain.Tests/CrossChainTestHelper.cs index ac7bac36dd..29dfefc526 100644 --- a/test/AElf.CrossChain.Tests/CrossChainTestHelper.cs +++ b/test/AElf.CrossChain.Tests/CrossChainTestHelper.cs @@ -1,72 +1,68 @@ using System.Collections.Generic; -using AElf.Standards.ACS7; using AElf.CrossChain.Indexing.Infrastructure; +using AElf.Standards.ACS7; using AElf.Types; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class CrossChainTestHelper { - public class CrossChainTestHelper - { - private readonly Dictionary _fakeCrossChainBlockData = - new Dictionary(); + private readonly Dictionary _chainIdHeight = new(); - private readonly Dictionary _fakeCrossChainExtraData = - new Dictionary(); + private readonly Dictionary _fakeCrossChainBlockData = new(); - private readonly Dictionary _fakeIndexedCrossChainBlockData = - new Dictionary(); + private readonly Dictionary _fakeCrossChainExtraData = new(); - private readonly Dictionary _chainIdHeight = new Dictionary(); + private readonly Dictionary _fakeIndexedCrossChainBlockData = new(); - public void AddFakeCrossChainTransactionInput(Hash previousHash, - CrossChainTransactionInput crossChainTransactionInput) - { - _fakeCrossChainBlockData.Add(previousHash, crossChainTransactionInput); - } + public void AddFakeCrossChainTransactionInput(Hash previousHash, + CrossChainTransactionInput crossChainTransactionInput) + { + _fakeCrossChainBlockData.Add(previousHash, crossChainTransactionInput); + } - public CrossChainTransactionInput GetCrossChainBlockData(Hash previousHash) - { - return _fakeCrossChainBlockData.TryGetValue(previousHash, out var chainTransactionInput) - ? chainTransactionInput - : null; - } + public CrossChainTransactionInput GetCrossChainBlockData(Hash previousHash) + { + return _fakeCrossChainBlockData.TryGetValue(previousHash, out var chainTransactionInput) + ? chainTransactionInput + : null; + } - public void AddFakeExtraData(Hash previousHash, CrossChainExtraData crossChainExtraData) - { - _fakeCrossChainExtraData.Add(previousHash, crossChainExtraData); - } + public void AddFakeExtraData(Hash previousHash, CrossChainExtraData crossChainExtraData) + { + _fakeCrossChainExtraData.Add(previousHash, crossChainExtraData); + } - public CrossChainExtraData GetCrossChainExtraData(Hash previousHash) - { - return _fakeCrossChainExtraData.TryGetValue(previousHash, out var crossChainExtraData) - ? crossChainExtraData - : null; - } + public CrossChainExtraData GetCrossChainExtraData(Hash previousHash) + { + return _fakeCrossChainExtraData.TryGetValue(previousHash, out var crossChainExtraData) + ? crossChainExtraData + : null; + } - public void AddFakeIndexedCrossChainBlockData(long height, CrossChainBlockData crossChainBlockData) - { - _fakeIndexedCrossChainBlockData.Add(height, crossChainBlockData); - } + public void AddFakeIndexedCrossChainBlockData(long height, CrossChainBlockData crossChainBlockData) + { + _fakeIndexedCrossChainBlockData.Add(height, crossChainBlockData); + } - public CrossChainBlockData GetIndexedCrossChainExtraData(long height) - { - return _fakeIndexedCrossChainBlockData.TryGetValue(height, out var crossChainBlockData) - ? crossChainBlockData - : null; - } + public CrossChainBlockData GetIndexedCrossChainExtraData(long height) + { + return _fakeIndexedCrossChainBlockData.TryGetValue(height, out var crossChainBlockData) + ? crossChainBlockData + : null; + } - public void AddFakeChainIdHeight(int chainId, long libHeight) - { - _chainIdHeight.Add(chainId, libHeight); - } + public void AddFakeChainIdHeight(int chainId, long libHeight) + { + _chainIdHeight.Add(chainId, libHeight); + } - public ChainIdAndHeightDict GetAllIndexedCrossChainExtraData() + public ChainIdAndHeightDict GetAllIndexedCrossChainExtraData() + { + var sideChainIdAndHeightDict = new ChainIdAndHeightDict { - var sideChainIdAndHeightDict = new ChainIdAndHeightDict - { - IdHeightDict = {_chainIdHeight} - }; - return sideChainIdAndHeightDict; - } + IdHeightDict = { _chainIdHeight } + }; + return sideChainIdAndHeightDict; } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainTestModule.cs b/test/AElf.CrossChain.Tests/CrossChainTestModule.cs index e29b5019c3..5179d7d7d5 100644 --- a/test/AElf.CrossChain.Tests/CrossChainTestModule.cs +++ b/test/AElf.CrossChain.Tests/CrossChainTestModule.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using AElf.Standards.ACS7; using AElf.CrossChain.Application; using AElf.CrossChain.Indexing.Application; using AElf.Kernel; @@ -7,103 +6,102 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Txn.Application; using AElf.Modularity; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Moq; -using NSubstitute; using Volo.Abp.Modularity; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +[DependsOn( + typeof(CrossChainAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(SmartContractAElfModule) +)] +public class CrossChainTestModule : AElfModule { - [DependsOn( - typeof(CrossChainAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(SmartContractAElfModule) - )] - public class CrossChainTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(); + context.Services.AddTransient(provider => { - context.Services.AddSingleton(); - context.Services.AddTransient(provider => - { - var mockCrossChainRequestService = new Mock(); - mockCrossChainRequestService.Setup(mock => mock.RequestCrossChainDataFromOtherChainsAsync()) - .Returns(Task.CompletedTask); - return mockCrossChainRequestService.Object; - }); + var mockCrossChainRequestService = new Mock(); + mockCrossChainRequestService.Setup(mock => mock.RequestCrossChainDataFromOtherChainsAsync()) + .Returns(Task.CompletedTask); + return mockCrossChainRequestService.Object; + }); - context.Services.AddTransient(provider => - { - var mockCrossChainIndexingDataService = new Mock(); - mockCrossChainIndexingDataService - .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny(), It.IsAny())) - .Returns((blockHash, blockHeight) => + context.Services.AddTransient(provider => + { + var mockCrossChainIndexingDataService = new Mock(); + mockCrossChainIndexingDataService + .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny(), It.IsAny())) + .Returns((blockHash, blockHeight) => + { + var crossChainTestHelper = + context.Services.GetRequiredServiceLazy().Value; + var crossChainBlockData = crossChainTestHelper.GetIndexedCrossChainExtraData(blockHeight); + var indexedSideChainBlockData = new IndexedSideChainBlockData + { + SideChainBlockDataList = { crossChainBlockData.SideChainBlockDataList } + }; + return Task.FromResult(indexedSideChainBlockData); + }); + + mockCrossChainIndexingDataService.Setup(m => + m.GetCrossChainTransactionInputForNextMiningAsync(It.IsAny(), It.IsAny())) + .Returns( + (previousHash, height) => { var crossChainTestHelper = context.Services.GetRequiredServiceLazy().Value; - var crossChainBlockData = crossChainTestHelper.GetIndexedCrossChainExtraData(blockHeight); - var indexedSideChainBlockData = new IndexedSideChainBlockData - { - SideChainBlockDataList = {crossChainBlockData.SideChainBlockDataList}, - }; - return Task.FromResult(indexedSideChainBlockData); + return Task.FromResult(crossChainTestHelper.GetCrossChainBlockData(previousHash)); }); - mockCrossChainIndexingDataService.Setup(m => - m.GetCrossChainTransactionInputForNextMiningAsync(It.IsAny(), It.IsAny())) - .Returns( - (previousHash, height) => - { - var crossChainTestHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(crossChainTestHelper.GetCrossChainBlockData(previousHash)); - }); - - mockCrossChainIndexingDataService.Setup(m => - m.PrepareExtraDataForNextMiningAsync(It.IsAny(), It.IsAny())) - .Returns( - (previousHash, height) => - { - var crossChainTestHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult( - crossChainTestHelper.GetCrossChainExtraData(previousHash)?.ToByteString() ?? - ByteString.Empty); - }); - - mockCrossChainIndexingDataService.Setup(m => - m.GetAllChainIdHeightPairsAtLibAsync()).Returns(() => - { - var crossChainTestHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(crossChainTestHelper.GetAllIndexedCrossChainExtraData()); - }); - - mockCrossChainIndexingDataService - .Setup( - m => m.CheckExtraDataIsNeededAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns((blockHash, height, timeStamp) => + mockCrossChainIndexingDataService.Setup(m => + m.PrepareExtraDataForNextMiningAsync(It.IsAny(), It.IsAny())) + .Returns( + (previousHash, height) => { var crossChainTestHelper = context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(crossChainTestHelper.GetCrossChainExtraData(blockHash) != null); + return Task.FromResult( + crossChainTestHelper.GetCrossChainExtraData(previousHash)?.ToByteString() ?? + ByteString.Empty); }); - return mockCrossChainIndexingDataService.Object; - }); - context.Services.AddTransient(provider => + mockCrossChainIndexingDataService.Setup(m => + m.GetAllChainIdHeightPairsAtLibAsync()).Returns(() => { - var mockService = new Mock(); - mockService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(), - It.IsAny())) - .Returns(Task.FromResult(default(Address))); - return mockService.Object; + var crossChainTestHelper = + context.Services.GetRequiredServiceLazy().Value; + return Task.FromResult(crossChainTestHelper.GetAllIndexedCrossChainExtraData()); }); - context.Services.AddSingleton(); - } + mockCrossChainIndexingDataService + .Setup( + m => m.CheckExtraDataIsNeededAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((blockHash, height, timeStamp) => + { + var crossChainTestHelper = + context.Services.GetRequiredServiceLazy().Value; + return Task.FromResult(crossChainTestHelper.GetCrossChainExtraData(blockHash) != null); + }); + return mockCrossChainIndexingDataService.Object; + }); + + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(), + It.IsAny())) + .Returns(Task.FromResult(default(Address))); + return mockService.Object; + }); + + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/CrossChainValidationProviderTests.cs b/test/AElf.CrossChain.Tests/CrossChainValidationProviderTests.cs index 9950129add..7f48795ddb 100644 --- a/test/AElf.CrossChain.Tests/CrossChainValidationProviderTests.cs +++ b/test/AElf.CrossChain.Tests/CrossChainValidationProviderTests.cs @@ -1,193 +1,192 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS7; +using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS7; using AElf.Types; using Google.Protobuf; using Xunit; -using AElf.CSharp.Core.Extension; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public sealed class CrossChainValidationProviderTest : CrossChainTestBase { - public sealed class CrossChainValidationProviderTest : CrossChainTestBase - { - private readonly IBlockValidationProvider _crossChainBlockValidationProvider; - private readonly CrossChainTestHelper _crossChainTestHelper; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IBlockValidationProvider _crossChainBlockValidationProvider; + private readonly CrossChainTestHelper _crossChainTestHelper; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; - public CrossChainValidationProviderTest() - { - _crossChainBlockValidationProvider = GetRequiredService(); - _crossChainTestHelper = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - } + public CrossChainValidationProviderTest() + { + _crossChainBlockValidationProvider = GetRequiredService(); + _crossChainTestHelper = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + } - [Fact] - public async Task Validate_GenesisHeight_Test() + [Fact] + public async Task Validate_GenesisHeight_Test() + { + var block = new Block { - var block = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - Height = 1 - } - }; - var validationRes = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); - Assert.True(validationRes); - } + Height = 1 + } + }; + var validationRes = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + Assert.True(validationRes); + } + + [Fact] + public async Task Validate_EmptyHeader_NoIndexedData_Test() + { + var block = _kernelTestHelper.GenerateBlock(10, Hash.Empty); + block.Header.Bloom = ByteString.CopyFrom(new byte[256]); + var validationRes = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + Assert.True(validationRes); + } + + [Fact] + public async Task Validate_EmptyHeader_WithIndexedData_Test() + { + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); + var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); - [Fact] - public async Task Validate_EmptyHeader_NoIndexedData_Test() + CreateFakeStateData(fakeSideChainId, fakeSideChainBlockData, 2); + var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); + var bloom = new Bloom(); + bloom.Combine(new[] { - var block = _kernelTestHelper.GenerateBlock(10, Hash.Empty); - block.Header.Bloom = ByteString.CopyFrom(new byte[256]); - var validationRes = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); - Assert.True(validationRes); - } + GetSideChainBlockDataIndexedEventBloom() + }); + block.Header.Bloom = ByteString.CopyFrom(bloom.Data); - [Fact] - public async Task Validate_EmptyHeader_WithIndexedData_Test() + var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + Assert.False(res); + } + + [Fact] + public async Task Validate_Test() + { + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var chainId = ChainHelper.ConvertBase58ToChainId("2112"); + var sideChainBlockData = new SideChainBlockData { - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); - var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); + Height = 1, + TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, + ChainId = chainId + }; + var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] { sideChainBlockData }); + var block = CreateFilledBlock(sideChainTxMerkleTreeRoot); + block.Header.Bloom = ByteString.CopyFrom(GetSideChainBlockDataIndexedEventBloom().Data); - CreateFakeStateData(fakeSideChainId, fakeSideChainBlockData, 2); - var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); - var bloom = new Bloom(); - bloom.Combine(new[] - { - GetSideChainBlockDataIndexedEventBloom() - }); - block.Header.Bloom = ByteString.CopyFrom(bloom.Data); + var fakeIndexedCrossChainData = new CrossChainBlockData(); + fakeIndexedCrossChainData.SideChainBlockDataList.Add(sideChainBlockData); + _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(2, fakeIndexedCrossChainData); + + var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + Assert.True(res); + } + + [Fact] + public async Task Validate_IncompatibleExtraData_Test() + { + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); + var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); + CreateFakeStateData(fakeSideChainId, fakeSideChainBlockData, 2); - var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + // mock data in cache + var fakeTxnMerkleTreeRoot = HashHelper.ComputeFrom("fakeMerkleTreeRoot2"); + + var block = CreateFilledBlock(fakeTxnMerkleTreeRoot); + block.Header.Bloom = ByteString.CopyFrom(GetSideChainBlockDataIndexedEventBloom().Data); + + var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + Assert.False(res); + } + + [Fact] + public async Task ValidateBlockBeforeExecute_Test() + { + var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); + var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); + var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); + var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] { fakeSideChainBlockData }); + var block = CreateFilledBlock(sideChainTxMerkleTreeRoot); + { + var res = await _crossChainBlockValidationProvider.ValidateBlockBeforeExecuteAsync(block); Assert.False(res); } - [Fact] - public async Task Validate_Test() { - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - int chainId = ChainHelper.ConvertBase58ToChainId("2112"); - var sideChainBlockData = new SideChainBlockData - { - Height = 1, - TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1, - ChainId = chainId - }; - var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] {sideChainBlockData}); - var block = CreateFilledBlock(sideChainTxMerkleTreeRoot); - block.Header.Bloom = ByteString.CopyFrom(GetSideChainBlockDataIndexedEventBloom().Data); - - var fakeIndexedCrossChainData = new CrossChainBlockData(); - fakeIndexedCrossChainData.SideChainBlockDataList.Add(sideChainBlockData); - _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(2, fakeIndexedCrossChainData); - - var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); + _crossChainTestHelper.AddFakeExtraData(block.Header.PreviousBlockHash, + new CrossChainExtraData { TransactionStatusMerkleTreeRoot = sideChainTxMerkleTreeRoot }); + + var res = await _crossChainBlockValidationProvider.ValidateBlockBeforeExecuteAsync(block); Assert.True(res); } - - [Fact] - public async Task Validate_IncompatibleExtraData_Test() - { - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); - var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); - CreateFakeStateData(fakeSideChainId, fakeSideChainBlockData, 2); - - // mock data in cache - var fakeTxnMerkleTreeRoot = HashHelper.ComputeFrom("fakeMerkleTreeRoot2"); - - var block = CreateFilledBlock(fakeTxnMerkleTreeRoot); - block.Header.Bloom = ByteString.CopyFrom(GetSideChainBlockDataIndexedEventBloom().Data); - - var res = await _crossChainBlockValidationProvider.ValidateBlockAfterExecuteAsync(block); - Assert.False(res); - } + } - [Fact] - public async Task ValidateBlockBeforeExecute_Test() + [Fact] + public async Task ValidateBlockBeforeAttach_Test() + { { var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); - var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] {fakeSideChainBlockData}); + var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] { fakeSideChainBlockData }); var block = CreateFilledBlock(sideChainTxMerkleTreeRoot); - { - var res = await _crossChainBlockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - Assert.False(res); - } - - { - _crossChainTestHelper.AddFakeExtraData(block.Header.PreviousBlockHash, - new CrossChainExtraData {TransactionStatusMerkleTreeRoot = sideChainTxMerkleTreeRoot}); - - var res = await _crossChainBlockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - Assert.True(res); - } - } - - [Fact] - public async Task ValidateBlockBeforeAttach_Test() - { - { - var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1"); - var fakeSideChainId = ChainHelper.ConvertBase58ToChainId("2112"); - var fakeSideChainBlockData = CreateSideChainBlockData(fakeSideChainId, 1, fakeMerkleTreeRoot1); - var sideChainTxMerkleTreeRoot = ComputeRootHash(new[] {fakeSideChainBlockData}); - var block = CreateFilledBlock(sideChainTxMerkleTreeRoot); - var res = await _crossChainBlockValidationProvider.ValidateBeforeAttachAsync(block); - Assert.True(res); - } - } - - private IBlock CreateFilledBlock(Hash merkleTreeRoot) - { - var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); - block.Header.ExtraData.Clear(); - block.Header.ExtraData.Add(CrossChainConstants.CrossChainExtraDataKey, - new CrossChainExtraData {TransactionStatusMerkleTreeRoot = merkleTreeRoot}.ToByteString()); - return block; - } - - - private Hash ComputeRootHash(IEnumerable blockInfo) - { - var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(blockInfo.Select(sideChainBlockData => - sideChainBlockData.TransactionStatusMerkleTreeRoot)); - return binaryMerkleTree.Root; + var res = await _crossChainBlockValidationProvider.ValidateBeforeAttachAsync(block); + Assert.True(res); } - - private void CreateFakeStateData(int fakeSideChainId, SideChainBlockData fakeSideChainBlockData, - long height = 1) - { - var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); - fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] {fakeSideChainBlockData}); + } - // mock data in state - _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(height, fakeIndexedCrossChainBlockData); - } + private IBlock CreateFilledBlock(Hash merkleTreeRoot) + { + var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); + block.Header.ExtraData.Clear(); + block.Header.ExtraData.Add(CrossChainConstants.CrossChainExtraDataKey, + new CrossChainExtraData { TransactionStatusMerkleTreeRoot = merkleTreeRoot }.ToByteString()); + return block; + } - private SideChainBlockData CreateSideChainBlockData(int chainId, long height, Hash transactionMerkleTreeRoot) - { - return new SideChainBlockData - { - Height = height, - TransactionStatusMerkleTreeRoot = transactionMerkleTreeRoot, - ChainId = chainId - }; - } - private Bloom GetSideChainBlockDataIndexedEventBloom() + private Hash ComputeRootHash(IEnumerable blockInfo) + { + var binaryMerkleTree = BinaryMerkleTree.FromLeafNodes(blockInfo.Select(sideChainBlockData => + sideChainBlockData.TransactionStatusMerkleTreeRoot)); + return binaryMerkleTree.Root; + } + + private void CreateFakeStateData(int fakeSideChainId, SideChainBlockData fakeSideChainBlockData, + long height = 1) + { + var fakeIndexedCrossChainBlockData = new CrossChainBlockData(); + fakeIndexedCrossChainBlockData.SideChainBlockDataList.AddRange(new[] { fakeSideChainBlockData }); + + // mock data in state + _crossChainTestHelper.AddFakeIndexedCrossChainBlockData(height, fakeIndexedCrossChainBlockData); + } + + private SideChainBlockData CreateSideChainBlockData(int chainId, long height, Hash transactionMerkleTreeRoot) + { + return new SideChainBlockData { - var logEvent = new SideChainBlockDataIndexed().ToLogEvent(); - return logEvent.GetBloom(); - } + Height = height, + TransactionStatusMerkleTreeRoot = transactionMerkleTreeRoot, + ChainId = chainId + }; + } + + private Bloom GetSideChainBlockDataIndexedEventBloom() + { + var logEvent = new SideChainBlockDataIndexed().ToLogEvent(); + return logEvent.GetBloom(); } } \ No newline at end of file diff --git a/test/AElf.CrossChain.Tests/MockTransactionPackingOptionProvider.cs b/test/AElf.CrossChain.Tests/MockTransactionPackingOptionProvider.cs index 9f880c8fb6..b2b2bffe0c 100644 --- a/test/AElf.CrossChain.Tests/MockTransactionPackingOptionProvider.cs +++ b/test/AElf.CrossChain.Tests/MockTransactionPackingOptionProvider.cs @@ -2,21 +2,20 @@ using AElf.Kernel; using AElf.Kernel.Txn.Application; -namespace AElf.CrossChain +namespace AElf.CrossChain; + +public class MockTransactionPackingOptionProvider : ITransactionPackingOptionProvider { - public class MockTransactionPackingOptionProvider : ITransactionPackingOptionProvider - { - private bool _isTransactionPackable = true; + private bool _isTransactionPackable = true; - public Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) - { - _isTransactionPackable = isTransactionPackable; - return Task.CompletedTask; - } + public Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) + { + _isTransactionPackable = isTransactionPackable; + return Task.CompletedTask; + } - public bool IsTransactionPackable(IChainContext chainContext) - { - return _isTransactionPackable; - } + public bool IsTransactionPackable(IChainContext chainContext) + { + return _isTransactionPackable; } } \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj b/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj index bcf6ae3f82..549098a847 100644 --- a/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj +++ b/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj @@ -4,14 +4,14 @@ false - - - - - - + + + + + + - + \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs index cdbef3d037..0a5578c15f 100644 --- a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs +++ b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs @@ -1,137 +1,135 @@ using System; using System.Text; using AElf.Cryptography.Exceptions; -using AElf.Types; -using Xunit; using Shouldly; using Virgil.Crypto; +using Xunit; + +namespace AElf.Cryptography.Tests; -namespace AElf.Cryptography.Tests +public class CryptoHelperTests { - public class CryptoHelperTests + [Fact] + public void Generate_Key_Test() + { + var keyPair = CryptoHelper.GenerateKeyPair(); + keyPair.ShouldNotBeNull(); + keyPair.PrivateKey.Length.ShouldBe(32); + keyPair.PublicKey.Length.ShouldBe(65); + + //invalid key length + var bytes = new byte[30]; + new Random().NextBytes(bytes); + Assert.Throws(() => CryptoHelper.FromPrivateKey(bytes)); + } + + [Fact] + public void Generate_KeyPair_Not_Same_Test() + { + var keyPair1 = CryptoHelper.GenerateKeyPair(); + var keyPair2 = CryptoHelper.GenerateKeyPair(); + keyPair1.ShouldNotBe(keyPair2); + } + + [Fact] + public void Recover_Public_Key_Test() + { + var keyPair = CryptoHelper.GenerateKeyPair(); + + var messageBytes1 = Encoding.UTF8.GetBytes("Hello world."); + var messageHash1 = messageBytes1.ComputeHash(); + + var messageBytes2 = Encoding.UTF8.GetBytes("Hello aelf."); + var messageHash2 = messageBytes2.ComputeHash(); + + var signature1 = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, messageHash1); + + var recoverResult1 = CryptoHelper.RecoverPublicKey(signature1, messageHash1, out var publicKey1); + + Assert.True(recoverResult1); + Assert.True(publicKey1.BytesEqual(keyPair.PublicKey)); + + var recoverResult2 = CryptoHelper.RecoverPublicKey(signature1, messageHash2, out var publicKey2); + + Assert.True(recoverResult2); + Assert.False(publicKey2.BytesEqual(keyPair.PublicKey)); + + var invalidSignature = ByteArrayHelper.HexStringToByteArray( + "1c9469cbd4b9f722056d3eafd9823b14be9d2759192a7980aafba9d767576834ce25cb570e63dede117ff5c831e33ac47d0450b6b4cea0d04d66a435f2275ef3ec"); + var recoverResult3 = CryptoHelper.RecoverPublicKey(invalidSignature, messageHash2, out var publicKey3); + Assert.False(recoverResult3); + + var invalidSignature2 = new byte[10]; + var recoverResult4 = CryptoHelper.RecoverPublicKey(invalidSignature2, messageHash2, out var publicKey4); + Assert.False(recoverResult4); + } + + [Fact] + public void VerifySignature_BadSignature() + { + var keyPair = CryptoHelper.GenerateKeyPair(); + var messageBytes = Encoding.UTF8.GetBytes("Hello world."); + var messageHash = messageBytes.ComputeHash(); + var signature = new byte[65]; + + var verifyResult = CryptoHelper.VerifySignature(signature, messageHash, keyPair.PublicKey); + verifyResult.ShouldBeFalse(); + } + + [Fact] + public void FromPrivateKey_BadPrivateKey_ShouldThrowException() + { + Should.Throw(() => CryptoHelper.FromPrivateKey(new byte[32])); + Should.Throw(() => CryptoHelper.FromPrivateKey(null)); + Should.Throw(() => CryptoHelper.FromPrivateKey(new byte[0])); + } + + [Fact] + public void Decrypt_Message_Test() + { + var alice = CryptoHelper.GenerateKeyPair(); + var bob = CryptoHelper.GenerateKeyPair(); + var sam = CryptoHelper.GenerateKeyPair(); + + // Alice want to transmit plain text "aelf" to Bob. + + var plainText = Encoding.UTF8.GetBytes(HashHelper.ComputeFrom("hash").ToHex()); + var cipherText = CryptoHelper.EncryptMessage(alice.PrivateKey, bob.PublicKey, plainText); + + // Bob decrypt the message. + var decrypt = CryptoHelper.DecryptMessage(alice.PublicKey, bob.PrivateKey, cipherText); + Assert.True(decrypt.BytesEqual(plainText)); + + // Sam can't decrypt this message. + var func = new Func(() => CryptoHelper.DecryptMessage(alice.PublicKey, sam.PrivateKey, + cipherText)); + Assert.Throws(func); + } + + [Fact] + public void Ecdh_Test() + { + var alice = CryptoHelper.GenerateKeyPair(); + var bob = CryptoHelper.GenerateKeyPair(); + + var ecdhKey1 = CryptoHelper.Ecdh(alice.PrivateKey, bob.PublicKey); + var ecdhKey2 = CryptoHelper.Ecdh(bob.PrivateKey, alice.PublicKey); + + Assert.Equal(ecdhKey1.ToHex(), ecdhKey2.ToHex()); + } + + [Fact] + public void Ecdh_BadArgument_ShouldThrowException() + { + Assert.Throws(() => CryptoHelper.Ecdh(new byte[32], new byte[33])); + } + + [Fact] + public void ExceptionTest() { - [Fact] - public void Generate_Key_Test() - { - var keyPair = CryptoHelper.GenerateKeyPair(); - keyPair.ShouldNotBeNull(); - keyPair.PrivateKey.Length.ShouldBe(32); - keyPair.PublicKey.Length.ShouldBe(65); - - //invalid key length - var bytes = new byte[30]; - new Random().NextBytes(bytes); - Assert.Throws(() => CryptoHelper.FromPrivateKey(bytes)); - } - - [Fact] - public void Generate_KeyPair_Not_Same_Test() - { - var keyPair1 = CryptoHelper.GenerateKeyPair(); - var keyPair2 = CryptoHelper.GenerateKeyPair(); - keyPair1.ShouldNotBe(keyPair2); - } - - [Fact] - public void Recover_Public_Key_Test() - { - var keyPair = CryptoHelper.GenerateKeyPair(); - - var messageBytes1 = Encoding.UTF8.GetBytes("Hello world."); - var messageHash1 = messageBytes1.ComputeHash(); - - var messageBytes2 = Encoding.UTF8.GetBytes("Hello aelf."); - var messageHash2 = messageBytes2.ComputeHash(); - - var signature1 = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, messageHash1); - - var recoverResult1 = CryptoHelper.RecoverPublicKey(signature1, messageHash1, out var publicKey1); - - Assert.True(recoverResult1); - Assert.True(publicKey1.BytesEqual(keyPair.PublicKey)); - - var recoverResult2 = CryptoHelper.RecoverPublicKey(signature1, messageHash2, out var publicKey2); - - Assert.True(recoverResult2); - Assert.False(publicKey2.BytesEqual(keyPair.PublicKey)); - - var invalidSignature = ByteArrayHelper.HexStringToByteArray( - "1c9469cbd4b9f722056d3eafd9823b14be9d2759192a7980aafba9d767576834ce25cb570e63dede117ff5c831e33ac47d0450b6b4cea0d04d66a435f2275ef3ec"); - var recoverResult3 = CryptoHelper.RecoverPublicKey(invalidSignature, messageHash2, out var publicKey3); - Assert.False(recoverResult3); - - var invalidSignature2 = new byte[10]; - var recoverResult4 = CryptoHelper.RecoverPublicKey(invalidSignature2, messageHash2, out var publicKey4); - Assert.False(recoverResult4); - } - - [Fact] - public void VerifySignature_BadSignature() - { - var keyPair = CryptoHelper.GenerateKeyPair(); - var messageBytes = Encoding.UTF8.GetBytes("Hello world."); - var messageHash = messageBytes.ComputeHash(); - var signature = new byte[65]; - - var verifyResult = CryptoHelper.VerifySignature(signature, messageHash, keyPair.PublicKey); - verifyResult.ShouldBeFalse(); - } - - [Fact] - public void FromPrivateKey_BadPrivateKey_ShouldThrowException() - { - Should.Throw(() => CryptoHelper.FromPrivateKey(new byte[32])); - Should.Throw(() => CryptoHelper.FromPrivateKey(null)); - Should.Throw(() => CryptoHelper.FromPrivateKey(new byte[0])); - } - - [Fact] - public void Decrypt_Message_Test() - { - var alice = CryptoHelper.GenerateKeyPair(); - var bob = CryptoHelper.GenerateKeyPair(); - var sam = CryptoHelper.GenerateKeyPair(); - - // Alice want to transmit plain text "aelf" to Bob. - - var plainText = Encoding.UTF8.GetBytes(HashHelper.ComputeFrom("hash").ToHex()); - var cipherText = CryptoHelper.EncryptMessage(alice.PrivateKey, bob.PublicKey, plainText); - - // Bob decrypt the message. - var decrypt = CryptoHelper.DecryptMessage(alice.PublicKey, bob.PrivateKey, cipherText); - Assert.True(decrypt.BytesEqual(plainText)); - - // Sam can't decrypt this message. - var func = new Func(() => CryptoHelper.DecryptMessage(alice.PublicKey, sam.PrivateKey, - cipherText)); - Assert.Throws(func); - } - - [Fact] - public void Ecdh_Test() - { - var alice = CryptoHelper.GenerateKeyPair(); - var bob = CryptoHelper.GenerateKeyPair(); - - var ecdhKey1 = CryptoHelper.Ecdh(alice.PrivateKey, bob.PublicKey); - var ecdhKey2 = CryptoHelper.Ecdh(bob.PrivateKey, alice.PublicKey); - - Assert.Equal(ecdhKey1.ToHex(), ecdhKey2.ToHex()); - } - - [Fact] - public void Ecdh_BadArgument_ShouldThrowException() - { - Assert.Throws(() => CryptoHelper.Ecdh(new byte[32], new byte[33])); - } - - [Fact] - public void ExceptionTest() - { - var message = "message"; - Should.Throw(() => throw new EcdhOperationException(message)); - Should.Throw(() => throw new SignatureOperationException(message)); - Should.Throw(() => throw new InvalidKeyPairException(message, new Exception())); - } + var message = "message"; + Should.Throw(() => throw new EcdhOperationException(message)); + Should.Throw(() => throw new SignatureOperationException(message)); + Should.Throw(() => throw new InvalidKeyPairException(message, new Exception())); } } \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/ECDSA/BlockSignatureTest.cs b/test/AElf.Cryptography.Tests/ECDSA/BlockSignatureTest.cs index e6a0b6dc55..12d87b49ce 100644 --- a/test/AElf.Cryptography.Tests/ECDSA/BlockSignatureTest.cs +++ b/test/AElf.Cryptography.Tests/ECDSA/BlockSignatureTest.cs @@ -1,35 +1,33 @@ -using AElf.Cryptography.ECDSA; -using AElf.Kernel; +using AElf.Kernel; using AElf.Types; -using Xunit; using Google.Protobuf; +using Xunit; -namespace AElf.Cryptography.Tests.ECDSA +namespace AElf.Cryptography.Tests.ECDSA; + +public class BlockSignatureTest { - public class BlockSignatureTest + [Fact] + public void SignAndVerifyTransaction_Test() { - [Fact] - public void SignAndVerifyTransaction_Test() - { - ECKeyPair keyPair1 = CryptoHelper.GenerateKeyPair(); - Transaction tx = new Transaction(); - tx.From = Address.FromPublicKey(keyPair1.PublicKey); - - ECKeyPair keyPair2 = CryptoHelper.GenerateKeyPair(); - tx.To = Address.FromPublicKey(keyPair2.PublicKey); - tx.Params = ByteString.CopyFrom(new byte[0]); - tx.MethodName = "TestMethod"; - tx.Params = ByteString.Empty; - tx.RefBlockNumber = 1; - tx.RefBlockPrefix = ByteString.Empty; + var keyPair1 = CryptoHelper.GenerateKeyPair(); + var tx = new Transaction(); + tx.From = Address.FromPublicKey(keyPair1.PublicKey); + + var keyPair2 = CryptoHelper.GenerateKeyPair(); + tx.To = Address.FromPublicKey(keyPair2.PublicKey); + tx.Params = ByteString.CopyFrom(); + tx.MethodName = "TestMethod"; + tx.Params = ByteString.Empty; + tx.RefBlockNumber = 1; + tx.RefBlockPrefix = ByteString.Empty; - // Serialize and hash the transaction - Hash hash = tx.GetHash(); + // Serialize and hash the transaction + var hash = tx.GetHash(); - // Sign the hash - var signature = CryptoHelper.SignWithPrivateKey(keyPair1.PrivateKey, hash.ToByteArray()); - tx.Signature = ByteString.CopyFrom(signature); - Assert.True(tx.VerifySignature()); - } + // Sign the hash + var signature = CryptoHelper.SignWithPrivateKey(keyPair1.PrivateKey, hash.ToByteArray()); + tx.Signature = ByteString.CopyFrom(signature); + Assert.True(tx.VerifySignature()); } } \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/SecretSharingTest.cs b/test/AElf.Cryptography.Tests/SecretSharingTest.cs index f887756c6f..423063e3ed 100644 --- a/test/AElf.Cryptography.Tests/SecretSharingTest.cs +++ b/test/AElf.Cryptography.Tests/SecretSharingTest.cs @@ -5,84 +5,77 @@ using Shouldly; using Xunit; -namespace AElf.Cryptography.Tests +namespace AElf.Cryptography.Tests; + +public class SecretSharingTest { - public class SecretSharingTest + [Theory] + [InlineData(new byte[] { 0x1, 0xff }, new byte[] { 0xff })] + [InlineData(new byte[] { 0x1, 0x2, 0x3, 0x4 }, new byte[] { 0x4, 0x3, 0x2 })] + public void BigIntegerToBytesArrayTest(byte[] dataArray, byte[] expectedArray) + { + var number = new BigInteger(dataArray); + var numberByteArray = number.ToBytesArray(); + numberByteArray.Length.ShouldBe(expectedArray.Length); + for (var i = 0; i < expectedArray.Length; i++) expectedArray[i].ShouldBe(numberByteArray[i]); + } + + [Theory] + [InlineData(new byte[] { 0xff }, new byte[] { 0x00, 0xff })] + [InlineData(new byte[] { 0xff, 0x14, 0x54 }, new byte[] { 0x00, 0x54, 0x14, 0xff })] + public void BytesArrayToBigIntegerTest(byte[] dataArray, byte[] expectedArray) { - [Theory] - [InlineData(new byte[]{0x1, 0xff}, new byte[]{0xff})] - [InlineData(new byte[]{0x1, 0x2, 0x3, 0x4}, new byte[]{0x4, 0x3, 0x2})] - public void BigIntegerToBytesArrayTest(byte[] dataArray, byte[] expectedArray) - { - var number = new BigInteger(dataArray); - var numberByteArray = number.ToBytesArray(); - numberByteArray.Length.ShouldBe(expectedArray.Length); - for (var i = 0; i < expectedArray.Length; i++) - { - expectedArray[i].ShouldBe(numberByteArray[i]); - } - } - - [Theory] - [InlineData(new byte[]{0xff}, new byte[]{0x00, 0xff})] - [InlineData(new byte[]{0xff, 0x14, 0x54}, new byte[]{0x00, 0x54, 0x14, 0xff})] - public void BytesArrayToBigIntegerTest(byte[] dataArray, byte[] expectedArray) - { - var byteArrayToNumber = dataArray.ToBigInteger(); - var newDataArray = byteArrayToNumber.ToByteArray(); - newDataArray.Length.ShouldBe(expectedArray.Length); - for (var i = 0; i < expectedArray.Length; i++) - { - expectedArray[i].ShouldBe(newDataArray[i]); - } - } - - [Fact] - public void BigIntegerAbsTest() - { - var dataArray = new byte[] {0xff, 0xff}; - var rawData = new BigInteger(dataArray); - rawData.ShouldBe(-1); - var absData = rawData.Abs(); - absData.ShouldBe(SecretSharingConsts.FieldPrime - 1); - } - - [Fact] - public void BigIntegerToStringTest() - { - var bigInteger = - BigInteger.Parse("68117399500852794112165623985513434038399476516881142682654290358811497358689"); - var str = bigInteger.ConvertToString(); - Assert.Equal("aelf", str); - } + var byteArrayToNumber = dataArray.ToBigInteger(); + var newDataArray = byteArrayToNumber.ToByteArray(); + newDataArray.Length.ShouldBe(expectedArray.Length); + for (var i = 0; i < expectedArray.Length; i++) expectedArray[i].ShouldBe(newDataArray[i]); + } - [Theory] - [InlineData("gggaelf", 3, 9)] - [InlineData("bbbaelf", 12, 17)] - [InlineData("kkkkaelf", 5, 20)] - public void SharingTest(string str, int threshold, int totalParts) - { - var bytes = Encoding.UTF8.GetBytes(str); - var parts = SecretSharingHelper.EncodeSecret(bytes, threshold, totalParts); - Assert.Equal(totalParts, parts.Count); + [Fact] + public void BigIntegerAbsTest() + { + var dataArray = new byte[] { 0xff, 0xff }; + var rawData = new BigInteger(dataArray); + rawData.ShouldBe(-1); + var absData = rawData.Abs(); + absData.ShouldBe(SecretSharingConsts.FieldPrime - 1); + } - var result = SecretSharingHelper.DecodeSecret(parts.Take(threshold).ToList(), - Enumerable.Range(1, threshold).ToList(), threshold); - Assert.Equal(bytes, result); - } - - [Theory] - [InlineData(3, 9)] - [InlineData(12, 17)] - [InlineData(5, 20)] - public void HashSharingTest(int threshold, int totalParts) - { - var hash = HashHelper.ComputeFrom("hash"); - var hashBytes = hash.ToByteArray(); - var parts = SecretSharingHelper.EncodeSecret(hashBytes, threshold, totalParts); - var result = SecretSharingHelper.DecodeSecret(parts.Take(threshold).ToList(), - Enumerable.Range(1, threshold).ToList(), threshold); - Assert.Equal(hashBytes, result); - } + [Fact] + public void BigIntegerToStringTest() + { + var bigInteger = + BigInteger.Parse("68117399500852794112165623985513434038399476516881142682654290358811497358689"); + var str = bigInteger.ConvertToString(); + Assert.Equal("aelf", str); + } + + [Theory] + [InlineData("gggaelf", 3, 9)] + [InlineData("bbbaelf", 12, 17)] + [InlineData("kkkkaelf", 5, 20)] + public void SharingTest(string str, int threshold, int totalParts) + { + var bytes = Encoding.UTF8.GetBytes(str); + var parts = SecretSharingHelper.EncodeSecret(bytes, threshold, totalParts); + Assert.Equal(totalParts, parts.Count); + + var result = SecretSharingHelper.DecodeSecret(parts.Take(threshold).ToList(), + Enumerable.Range(1, threshold).ToList(), threshold); + Assert.Equal(bytes, result); + } + + [Theory] + [InlineData(3, 9)] + [InlineData(12, 17)] + [InlineData(5, 20)] + public void HashSharingTest(int threshold, int totalParts) + { + var hash = HashHelper.ComputeFrom("hash"); + var hashBytes = hash.ToByteArray(); + var parts = SecretSharingHelper.EncodeSecret(hashBytes, threshold, totalParts); + var result = SecretSharingHelper.DecodeSecret(parts.Take(threshold).ToList(), + Enumerable.Range(1, threshold).ToList(), threshold); + Assert.Equal(hashBytes, result); } } \ No newline at end of file diff --git a/test/AElf.Database.Tests/AElf.Database.Tests.csproj b/test/AElf.Database.Tests/AElf.Database.Tests.csproj index 7a58894cf8..273937591c 100644 --- a/test/AElf.Database.Tests/AElf.Database.Tests.csproj +++ b/test/AElf.Database.Tests/AElf.Database.Tests.csproj @@ -4,15 +4,15 @@ false - - - - - - + + + + + + - - + + \ No newline at end of file diff --git a/test/AElf.Database.Tests/DatabaseTestBase.cs b/test/AElf.Database.Tests/DatabaseTestBase.cs index 3c682a4a84..521242ab07 100644 --- a/test/AElf.Database.Tests/DatabaseTestBase.cs +++ b/test/AElf.Database.Tests/DatabaseTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.Database.Tests +namespace AElf.Database.Tests; + +public abstract class DatabaseTestBase : AElfIntegratedTest { - public abstract class DatabaseTestBase : AElfIntegratedTest - { - } -} +} \ No newline at end of file diff --git a/test/AElf.Database.Tests/InMemoryDbContextTests.cs b/test/AElf.Database.Tests/InMemoryDbContextTests.cs index 38e85b6943..2b6db68d8e 100644 --- a/test/AElf.Database.Tests/InMemoryDbContextTests.cs +++ b/test/AElf.Database.Tests/InMemoryDbContextTests.cs @@ -1,6 +1,5 @@ -namespace AElf.Database.Tests +namespace AElf.Database.Tests; + +public class InMemoryDbContextTests : KeyValueDbContextTestBase { - public class InMemoryDbContextTests: KeyValueDbContextTestBase - { - } } \ No newline at end of file diff --git a/test/AElf.Database.Tests/KeyValueDbContextTestBase.cs b/test/AElf.Database.Tests/KeyValueDbContextTestBase.cs index b19f623d18..e0667932d3 100644 --- a/test/AElf.Database.Tests/KeyValueDbContextTestBase.cs +++ b/test/AElf.Database.Tests/KeyValueDbContextTestBase.cs @@ -5,144 +5,140 @@ using AElf.Database.RedisProtocol; using Xunit; -namespace AElf.Database.Tests +namespace AElf.Database.Tests; + +public abstract class KeyValueDbContextTestBase : DatabaseTestBase + where TKeyValueDbContext : KeyValueDbContext { - public abstract class KeyValueDbContextTestBase : DatabaseTestBase - where TKeyValueDbContext : KeyValueDbContext - { - protected TKeyValueDbContext _context; + protected TKeyValueDbContext _context; - protected IKeyValueDatabase _database; + protected IKeyValueDatabase _database; - protected KeyValueDbContextTestBase() - { - // ReSharper disable once VirtualMemberCallInConstructor - _context = GetRequiredService(); - _database = _context.Database; - } + protected KeyValueDbContextTestBase() + { + // ReSharper disable once VirtualMemberCallInConstructor + _context = GetRequiredService(); + _database = _context.Database; + } - [Fact] - public void IsConnected_Test() - { - var result = _database.IsConnected(); - Assert.True(result); - } + [Fact] + public void IsConnected_Test() + { + var result = _database.IsConnected(); + Assert.True(result); + } - [Fact] - public async Task Set_Test() - { - var key = "settest"; - var value = Guid.NewGuid().ToString(); + [Fact] + public async Task Set_Test() + { + var key = "settest"; + var value = Guid.NewGuid().ToString(); - await _database.SetAsync(key, value.ToUtf8Bytes()); - } + await _database.SetAsync(key, value.ToUtf8Bytes()); + } - [Fact] - public async Task Get_Test() - { - var key = "gettest"; - var value = Guid.NewGuid().ToString(); + [Fact] + public async Task Get_Test() + { + var key = "gettest"; + var value = Guid.NewGuid().ToString(); - await _database.SetAsync(key, value.ToUtf8Bytes()); - var getResult = await _database.GetAsync(key); + await _database.SetAsync(key, value.ToUtf8Bytes()); + var getResult = await _database.GetAsync(key); - Assert.Equal(value, getResult.FromUtf8Bytes()); - } + Assert.Equal(value, getResult.FromUtf8Bytes()); + } - [Fact] - public async Task Remove_Test() - { - var key = "removetest"; - var value = Guid.NewGuid().ToString(); + [Fact] + public async Task Remove_Test() + { + var key = "removetest"; + var value = Guid.NewGuid().ToString(); - await _database.SetAsync(key, Encoding.UTF8.GetBytes(value)); - var exists = await _database.IsExistsAsync(key); - Assert.True(exists); + await _database.SetAsync(key, Encoding.UTF8.GetBytes(value)); + var exists = await _database.IsExistsAsync(key); + Assert.True(exists); - await _database.RemoveAsync(key); + await _database.RemoveAsync(key); - exists = await _database.IsExistsAsync(key); - Assert.False(exists); - } + exists = await _database.IsExistsAsync(key); + Assert.False(exists); + } - [Fact] - public async Task GetAllAsync_With_Invalid_Key_Test() - { - var invalidKey1 = ""; - Assert.Throws(() => - { - _database.GetAllAsync(new List {invalidKey1}); - }); - } + [Fact] + public async Task GetAllAsync_With_Invalid_Key_Test() + { + var invalidKey1 = ""; + Assert.Throws(() => { _database.GetAllAsync(new List { invalidKey1 }); }); + } - [Fact] - public async Task SetAllAsync_With_Invalid_Key_Test() + [Fact] + public async Task SetAllAsync_With_Invalid_Key_Test() + { + var key1 = ""; + var value1 = Guid.NewGuid().ToString(); + Assert.Throws(() => { - var key1 = ""; - var value1 = Guid.NewGuid().ToString(); - Assert.Throws(() => + _database.SetAllAsync(new Dictionary { - _database.SetAllAsync(new Dictionary - { - {key1, Encoding.UTF8.GetBytes(value1)}, - }); + { key1, Encoding.UTF8.GetBytes(value1) } }); - } - - [Fact] - public async Task RemoveAllAsync_With_Invalid_Key_Test() - { - Assert.Throws(() => { _database.RemoveAllAsync(new List {null}); }); - } - - [Fact] - public async Task Multiple_Test() - { - var key1 = "setalltest1"; - var value1 = Guid.NewGuid().ToString(); - var key2 = "setalltest2"; - var value2 = Guid.NewGuid().ToString(); - var key3 = "setalltest3"; + }); + } - await _database.SetAllAsync(new Dictionary - { - {key1,Encoding.UTF8.GetBytes(value1)}, - {key2,Encoding.UTF8.GetBytes(value2)} - }); + [Fact] + public async Task RemoveAllAsync_With_Invalid_Key_Test() + { + Assert.Throws(() => { _database.RemoveAllAsync(new List { null }); }); + } - var getResult = await _database.GetAllAsync(new List {key1, key2, key3}); - Assert.Equal(value1,Encoding.UTF8.GetString(getResult[0])); - Assert.Equal(value2,Encoding.UTF8.GetString(getResult[1])); - - await _database.RemoveAllAsync(new List {key1, key2, key3}); - - var exists = await _database.IsExistsAsync(key1); - Assert.False(exists); - - exists = await _database.IsExistsAsync(key2); - Assert.False(exists); - } - - [Fact] - public void Get_Exception_Test() - { - var key = string.Empty; - Assert.Throws(() => { _database.GetAsync(key); }); - } + [Fact] + public async Task Multiple_Test() + { + var key1 = "setalltest1"; + var value1 = Guid.NewGuid().ToString(); + var key2 = "setalltest2"; + var value2 = Guid.NewGuid().ToString(); + var key3 = "setalltest3"; - [Fact] - public void Set_Exception_Test() + await _database.SetAllAsync(new Dictionary { - var key = string.Empty; - var value = Guid.NewGuid().ToString(); - Assert.Throws(() => { _database.SetAsync(key, value.ToUtf8Bytes()); }); - } + { key1, Encoding.UTF8.GetBytes(value1) }, + { key2, Encoding.UTF8.GetBytes(value2) } + }); - [Fact] - public void Remove_Exception_Test() - { - var key = string.Empty; - Assert.Throws(() => { _database.RemoveAsync(key); }); - } + var getResult = await _database.GetAllAsync(new List { key1, key2, key3 }); + Assert.Equal(value1, Encoding.UTF8.GetString(getResult[0])); + Assert.Equal(value2, Encoding.UTF8.GetString(getResult[1])); + + await _database.RemoveAllAsync(new List { key1, key2, key3 }); + + var exists = await _database.IsExistsAsync(key1); + Assert.False(exists); + + exists = await _database.IsExistsAsync(key2); + Assert.False(exists); + } + + [Fact] + public void Get_Exception_Test() + { + var key = string.Empty; + Assert.Throws(() => { _database.GetAsync(key); }); + } + + [Fact] + public void Set_Exception_Test() + { + var key = string.Empty; + var value = Guid.NewGuid().ToString(); + Assert.Throws(() => { _database.SetAsync(key, value.ToUtf8Bytes()); }); + } + + [Fact] + public void Remove_Exception_Test() + { + var key = string.Empty; + Assert.Throws(() => { _database.RemoveAsync(key); }); } } \ No newline at end of file diff --git a/test/AElf.Database.Tests/MyDbContextTests.cs b/test/AElf.Database.Tests/MyDbContextTests.cs index ab26c24d4e..21d65d1de8 100644 --- a/test/AElf.Database.Tests/MyDbContextTests.cs +++ b/test/AElf.Database.Tests/MyDbContextTests.cs @@ -1,19 +1,18 @@ using Shouldly; using Xunit; -namespace AElf.Database.Tests +namespace AElf.Database.Tests; + +public class MyDbContextTests : KeyValueDbContextTestBase { - public class MyDbContextTests: KeyValueDbContextTestBase + [Fact] + public void CheckDbType_Test() { - [Fact] - public void CheckDbType_Test() - { - var type = _context.Database.GetType().GetGenericTypeDefinition(); - typeof(InMemoryDatabase<>).IsAssignableFrom(type).ShouldBe(true); + var type = _context.Database.GetType().GetGenericTypeDefinition(); + typeof(InMemoryDatabase<>).IsAssignableFrom(type).ShouldBe(true); + + var connection = GetRequiredService>().ConnectionString; - var connection = GetRequiredService>().ConnectionString; - - connection.ShouldBe( "127.0.0.1"); - } + connection.ShouldBe("127.0.0.1"); } } \ No newline at end of file diff --git a/test/AElf.Database.Tests/TestsDatabaseAElfModule.cs b/test/AElf.Database.Tests/TestsDatabaseAElfModule.cs index 9c675f343f..64ee3d7e79 100644 --- a/test/AElf.Database.Tests/TestsDatabaseAElfModule.cs +++ b/test/AElf.Database.Tests/TestsDatabaseAElfModule.cs @@ -5,42 +5,37 @@ using Volo.Abp.Data; using Volo.Abp.Modularity; -namespace AElf.Database.Tests +namespace AElf.Database.Tests; + +[DependsOn(typeof(DatabaseAElfModule), typeof(TestBaseAElfModule))] +public class TestsDatabaseAElfModule : AElfModule { - [DependsOn(typeof(DatabaseAElfModule), typeof(TestBaseAElfModule))] - public class TestsDatabaseAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(o => Mock.Of( - c => c.Resolve("Default") == "127.0.0.1" && - c.Resolve("AElf.Database.Tests.MyContext2") == "10.1.1.1" - )); - - services.AddKeyValueDbContext(builder => builder.UseRedisDatabase()); - - services.AddKeyValueDbContext(builder => builder.UseInMemoryDatabase()); - - services.AddKeyValueDbContext(builder => builder.UseSsdbDatabase()); - services.AddKeyValueDbContext(builder => builder.UseInMemoryDatabase()); - - } - } + var services = context.Services; + services.AddSingleton(o => Mock.Of( + c => c.Resolve("Default") == "127.0.0.1" && + c.Resolve("AElf.Database.Tests.MyContext2") == "10.1.1.1" + )); + services.AddKeyValueDbContext(builder => builder.UseRedisDatabase()); - [ConnectionStringName("Default")] - public class MyContext : KeyValueDbContext - { + services.AddKeyValueDbContext(builder => builder.UseInMemoryDatabase()); + + services.AddKeyValueDbContext(builder => builder.UseSsdbDatabase()); + services.AddKeyValueDbContext(builder => builder.UseInMemoryDatabase()); } +} +[ConnectionStringName("Default")] +public class MyContext : KeyValueDbContext +{ +} - public class MyContext2 : KeyValueDbContext - { - } +public class MyContext2 : KeyValueDbContext +{ +} - public class InMemoryDbContext : KeyValueDbContext - { - - } +public class InMemoryDbContext : KeyValueDbContext +{ } \ No newline at end of file diff --git a/test/AElf.EconomicSystem.Tests/AElf.EconomicSystem.Tests.csproj b/test/AElf.EconomicSystem.Tests/AElf.EconomicSystem.Tests.csproj index 792843525a..1b1d29fe44 100644 --- a/test/AElf.EconomicSystem.Tests/AElf.EconomicSystem.Tests.csproj +++ b/test/AElf.EconomicSystem.Tests/AElf.EconomicSystem.Tests.csproj @@ -5,16 +5,16 @@ - - - - - - + + + + + + - - + + diff --git a/test/AElf.EconomicSystem.Tests/EconomicSystemTestBase.cs b/test/AElf.EconomicSystem.Tests/EconomicSystemTestBase.cs index 052458db9b..2e4c570023 100644 --- a/test/AElf.EconomicSystem.Tests/EconomicSystemTestBase.cs +++ b/test/AElf.EconomicSystem.Tests/EconomicSystemTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.EconomicSystem.Tests +namespace AElf.EconomicSystem.Tests; + +public class EconomicSystemTestBase : AElfIntegratedTest { - public class EconomicSystemTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.EconomicSystem.Tests/EconomicSystemTestModule.cs b/test/AElf.EconomicSystem.Tests/EconomicSystemTestModule.cs index 7bc0cc2692..c881df3da0 100644 --- a/test/AElf.EconomicSystem.Tests/EconomicSystemTestModule.cs +++ b/test/AElf.EconomicSystem.Tests/EconomicSystemTestModule.cs @@ -3,20 +3,20 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.EconomicSystem.Tests +namespace AElf.EconomicSystem.Tests; + +[DependsOn( + typeof(EconomicSystemAElfModule) +)] +public class EconomicSystemTestModule : AElfModule { - [DependsOn( - typeof(EconomicSystemAElfModule) - )] - public class EconomicSystemTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => { - Configure(options => - { - options.MiningInterval = 4000; - options.InitialMinerList = new List{"5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f"}; - }); - } + options.MiningInterval = 4000; + options.InitialMinerList = new List + { "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f" }; + }); } } \ No newline at end of file diff --git a/test/AElf.EconomicSystem.Tests/ProviderTest.cs b/test/AElf.EconomicSystem.Tests/ProviderTest.cs index 124f655a66..e7e29fff0d 100644 --- a/test/AElf.EconomicSystem.Tests/ProviderTest.cs +++ b/test/AElf.EconomicSystem.Tests/ProviderTest.cs @@ -4,68 +4,67 @@ using Shouldly; using Xunit; -namespace AElf.EconomicSystem.Tests +namespace AElf.EconomicSystem.Tests; + +public class ProviderTest : EconomicSystemTestBase { - public class ProviderTest : EconomicSystemTestBase - { - #region EconomicContractInitializationProvider Test + #region EconomicContractInitializationProvider Test - [Fact] - public void EconomicContractInitializationProvider_Test() - { - var contractInitializationProvider = - GetContractInitializationProvider(); - var methodList = contractInitializationProvider.GetInitializeMethodList(null); - methodList.Count.ShouldBe(2); - } + [Fact] + public void EconomicContractInitializationProvider_Test() + { + var contractInitializationProvider = + GetContractInitializationProvider(); + var methodList = contractInitializationProvider.GetInitializeMethodList(null); + methodList.Count.ShouldBe(2); + } - #endregion + #endregion - #region EconomicSmartContractAddressNameProvider Test + #region EconomicSmartContractAddressNameProvider Test - [Fact] - public void EconomicSmartContractAddressNameProvider_Test() - { - var economicSmartContractAddressNameProvider = new EconomicSmartContractAddressNameProvider(); - var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); - economicSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); - } + [Fact] + public void EconomicSmartContractAddressNameProvider_Test() + { + var economicSmartContractAddressNameProvider = new EconomicSmartContractAddressNameProvider(); + var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Economic"); + economicSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); + } - #endregion + #endregion - #region TokenHolderContractInitializationProvider Test + #region TokenHolderContractInitializationProvider Test - [Fact] - public void TokenHolderContractInitializationProvider_Test() - { - var contractInitializationProvider = - GetContractInitializationProvider(); - contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); - } + [Fact] + public void TokenHolderContractInitializationProvider_Test() + { + var contractInitializationProvider = + GetContractInitializationProvider(); + contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); + } - #endregion + #endregion - #region TokenHolderSmartContractAddressNameProvider Test + #region TokenHolderSmartContractAddressNameProvider Test - [Fact] - public void TokenHolderSmartContractAddressNameProvider_Test() - { - var tokenHolderSmartContractAddressNameProvider = new TokenHolderSmartContractAddressNameProvider(); - var targetName = HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); - tokenHolderSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); - } + [Fact] + public void TokenHolderSmartContractAddressNameProvider_Test() + { + var tokenHolderSmartContractAddressNameProvider = new TokenHolderSmartContractAddressNameProvider(); + var targetName = HashHelper.ComputeFrom("AElf.ContractNames.TokenHolder"); + tokenHolderSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); + } - #endregion + #endregion - private IContractInitializationProvider GetContractInitializationProvider() - where T : IContractInitializationProvider - { - var contractInitializationProviders = GetRequiredService>(); - var contractInitializationProvider = - contractInitializationProviders.SingleOrDefault(x => - x.GetType() == typeof(T)); - contractInitializationProvider.ShouldNotBeNull(); - return contractInitializationProvider; - } + private IContractInitializationProvider GetContractInitializationProvider() + where T : IContractInitializationProvider + { + var contractInitializationProviders = GetRequiredService>(); + var contractInitializationProvider = + contractInitializationProviders.SingleOrDefault(x => + x.GetType() == typeof(T)); + contractInitializationProvider.ShouldNotBeNull(); + return contractInitializationProvider; } } \ No newline at end of file diff --git a/test/AElf.GovernmentSystem.Tests/AElf.GovernmentSystem.Tests.csproj b/test/AElf.GovernmentSystem.Tests/AElf.GovernmentSystem.Tests.csproj index cbfb5df5e4..fde85873bf 100644 --- a/test/AElf.GovernmentSystem.Tests/AElf.GovernmentSystem.Tests.csproj +++ b/test/AElf.GovernmentSystem.Tests/AElf.GovernmentSystem.Tests.csproj @@ -5,17 +5,17 @@ - - - - - - + + + + + + - - + + diff --git a/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestBase.cs b/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestBase.cs index 1fe3e615ea..e68ded1470 100644 --- a/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestBase.cs +++ b/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.GovernmentSystem.Tests +namespace AElf.GovernmentSystem.Tests; + +public class GovernmentSystemTestBase : AElfIntegratedTest { - public class GovernmentSystemTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestModule.cs b/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestModule.cs index 973572c256..c0063b4a95 100644 --- a/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestModule.cs +++ b/test/AElf.GovernmentSystem.Tests/GovernmentSystemTestModule.cs @@ -5,27 +5,29 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.GovernmentSystem.Tests +namespace AElf.GovernmentSystem.Tests; + +[DependsOn( + typeof(GovernmentSystemAElfModule) +)] +public class GovernmentSystemTestModule : AElfModule { - [DependsOn( - typeof(GovernmentSystemAElfModule) - )] - public class GovernmentSystemTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(options => + { + options.PeriodSeconds = 1200; + options.MiningInterval = 4000; + options.InitialMinerList = new List + { "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f" }; + }); + Configure(options => { - Configure(options => - { - options.PeriodSeconds = 1200; - options.MiningInterval = 4000; - options.InitialMinerList = new List{"5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f"}; - }); - Configure(options => - { - options.MaximumLockTime = 120; - options.MinimumLockTime = 10; - }); - context.Services.AddSingleton(); - } + options.MaximumLockTime = 120; + options.MinimumLockTime = 10; + }); + context.Services + .AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.GovernmentSystem.Tests/ParliamentContractInitializationDataProvider.cs b/test/AElf.GovernmentSystem.Tests/ParliamentContractInitializationDataProvider.cs index c591263b1b..fc9ac53f98 100644 --- a/test/AElf.GovernmentSystem.Tests/ParliamentContractInitializationDataProvider.cs +++ b/test/AElf.GovernmentSystem.Tests/ParliamentContractInitializationDataProvider.cs @@ -1,10 +1,9 @@ -namespace AElf.GovernmentSystem.Tests +namespace AElf.GovernmentSystem.Tests; + +public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider { - public class ParliamentContractInitializationDataProvider : IParliamentContractInitializationDataProvider + public ParliamentContractInitializationData GetContractInitializationData() { - public ParliamentContractInitializationData GetContractInitializationData() - { - return new ParliamentContractInitializationData(); - } + return new ParliamentContractInitializationData(); } } \ No newline at end of file diff --git a/test/AElf.GovernmentSystem.Tests/ProviderTest.cs b/test/AElf.GovernmentSystem.Tests/ProviderTest.cs index f34f77495e..0487c3448f 100644 --- a/test/AElf.GovernmentSystem.Tests/ProviderTest.cs +++ b/test/AElf.GovernmentSystem.Tests/ProviderTest.cs @@ -4,68 +4,67 @@ using Shouldly; using Xunit; -namespace AElf.GovernmentSystem.Tests +namespace AElf.GovernmentSystem.Tests; + +public class ProviderTest : GovernmentSystemTestBase { - public class ProviderTest : GovernmentSystemTestBase - { - #region ElectionContractInitializationProvider Test + #region ElectionContractInitializationProvider Test - [Fact] - public void ElectionContractInitializationProvider_Test() - { - var contractInitializationProvider = - GetContractInitializationProvider(); - var initializeMethodList = contractInitializationProvider.GetInitializeMethodList(null); - initializeMethodList.Count.ShouldBe(1); - } + [Fact] + public void ElectionContractInitializationProvider_Test() + { + var contractInitializationProvider = + GetContractInitializationProvider(); + var initializeMethodList = contractInitializationProvider.GetInitializeMethodList(null); + initializeMethodList.Count.ShouldBe(1); + } - #endregion + #endregion - #region ElectionSmartContractAddressNameProvider Test + #region ElectionSmartContractAddressNameProvider Test - [Fact] - public void ElectionSmartContractAddressNameProvider_Test() - { - var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Election"); - var electionSmartContractAddressNameProvider = new ElectionSmartContractAddressNameProvider(); - electionSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); - } + [Fact] + public void ElectionSmartContractAddressNameProvider_Test() + { + var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Election"); + var electionSmartContractAddressNameProvider = new ElectionSmartContractAddressNameProvider(); + electionSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); + } - #endregion + #endregion - #region VoteContractInitializationProvider Test + #region VoteContractInitializationProvider Test - [Fact] - public void VoteContractInitializationProvider_Test() - { - var contractInitializationProvider = - GetContractInitializationProvider(); - contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); - } + [Fact] + public void VoteContractInitializationProvider_Test() + { + var contractInitializationProvider = + GetContractInitializationProvider(); + contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); + } - #endregion + #endregion - #region VoteSmartContractAddressNameProvider Test + #region VoteSmartContractAddressNameProvider Test - [Fact] - public void VoteSmartContractAddressNameProvider_Test() - { - var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); - var voteSmartContractAddressNameProvider = new VoteSmartContractAddressNameProvider(); - voteSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); - } + [Fact] + public void VoteSmartContractAddressNameProvider_Test() + { + var targetName = HashHelper.ComputeFrom("AElf.ContractNames.Vote"); + var voteSmartContractAddressNameProvider = new VoteSmartContractAddressNameProvider(); + voteSmartContractAddressNameProvider.ContractName.ShouldBe(targetName); + } - #endregion + #endregion - private IContractInitializationProvider GetContractInitializationProvider() - where T : IContractInitializationProvider - { - var contractInitializationProviders = GetRequiredService>(); - var contractInitializationProvider = - contractInitializationProviders.SingleOrDefault(x => - x.GetType() == typeof(T)); - contractInitializationProvider.ShouldNotBeNull(); - return contractInitializationProvider; - } + private IContractInitializationProvider GetContractInitializationProvider() + where T : IContractInitializationProvider + { + var contractInitializationProviders = GetRequiredService>(); + var contractInitializationProvider = + contractInitializationProviders.SingleOrDefault(x => + x.GetType() == typeof(T)); + contractInitializationProvider.ShouldNotBeNull(); + return contractInitializationProvider; } } \ No newline at end of file diff --git a/test/AElf.Kernel.ChainController.Tests/AElf.Kernel.ChainController.Tests.csproj b/test/AElf.Kernel.ChainController.Tests/AElf.Kernel.ChainController.Tests.csproj index 4b103758bb..d20c85d793 100644 --- a/test/AElf.Kernel.ChainController.Tests/AElf.Kernel.ChainController.Tests.csproj +++ b/test/AElf.Kernel.ChainController.Tests/AElf.Kernel.ChainController.Tests.csproj @@ -5,15 +5,15 @@ false - - - - - - + + + + + + - - + + diff --git a/test/AElf.Kernel.ChainController.Tests/Application/ChainCreationServiceTests.cs b/test/AElf.Kernel.ChainController.Tests/Application/ChainCreationServiceTests.cs index 131b327a5c..d633ef0df7 100644 --- a/test/AElf.Kernel.ChainController.Tests/Application/ChainCreationServiceTests.cs +++ b/test/AElf.Kernel.ChainController.Tests/Application/ChainCreationServiceTests.cs @@ -6,49 +6,49 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.ChainController.Application +namespace AElf.Kernel.ChainController.Application; + +public class ChainCreationServiceTests : ChainControllerTestBase { - public class ChainCreationServiceTests : ChainControllerTestBase + private readonly IBlockchainService _blockchainService; + private readonly ChainCreationService _chainCreationService; + + public ChainCreationServiceTests() { - private readonly ChainCreationService _chainCreationService; - private readonly IBlockchainService _blockchainService; + _chainCreationService = GetRequiredService(); + _blockchainService = GetRequiredService(); + } - public ChainCreationServiceTests() - { - _chainCreationService = GetRequiredService(); - _blockchainService = GetRequiredService(); - } + [Fact] + public async Task Create_NewChain_Success_Test() + { + var chain = await _blockchainService.GetChainAsync(); + chain.ShouldBeNull(); - [Fact] - public async Task Create_NewChain_Success_Test() - { - var chain = await _blockchainService.GetChainAsync(); - chain.ShouldBeNull(); + await _chainCreationService.CreateNewChainAsync(new List()); + chain = await _blockchainService.GetChainAsync(); + chain.ShouldNotBeNull(); - await _chainCreationService.CreateNewChainAsync(new List()); - chain = await _blockchainService.GetChainAsync(); - chain.ShouldNotBeNull(); + var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); + block.Header.Height.ShouldBe(AElfConstants.GenesisBlockHeight); + block.Header.PreviousBlockHash.ShouldBe(Hash.Empty); + block.Header.ChainId.ShouldBe(chain.Id); + } - var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); - block.Header.Height.ShouldBe(AElfConstants.GenesisBlockHeight); - block.Header.PreviousBlockHash.ShouldBe(Hash.Empty); - block.Header.ChainId.ShouldBe(chain.Id); + [Fact] + public async Task Create_NewChain_Failed_Test() + { + var chain = await _blockchainService.GetChainAsync(); + chain.ShouldBeNull(); + var transactions = new List(); + transactions.Add(new Transaction()); + try + { + await _chainCreationService.CreateNewChainAsync(transactions); } - [Fact] - public async Task Create_NewChain_Failed_Test() + catch (Exception e) { - var chain = await _blockchainService.GetChainAsync(); - chain.ShouldBeNull(); - var transactions= new List(); - transactions.Add(new Transaction()); - try - { - await _chainCreationService.CreateNewChainAsync(transactions); - } - catch (Exception e) - { - e.Message.ShouldBe("Invalid transaction: { }"); - } + e.Message.ShouldBe("Invalid transaction: { }"); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.ChainController.Tests/ChainControllerTestAElfModule.cs b/test/AElf.Kernel.ChainController.Tests/ChainControllerTestAElfModule.cs index 8ebabe59dd..a07bc7d480 100644 --- a/test/AElf.Kernel.ChainController.Tests/ChainControllerTestAElfModule.cs +++ b/test/AElf.Kernel.ChainController.Tests/ChainControllerTestAElfModule.cs @@ -6,23 +6,21 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Kernel.ChainController +namespace AElf.Kernel.ChainController; + +[DependsOn( + typeof(ChainControllerAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(TokenKernelAElfModule) +)] +public class ChainControllerTestAElfModule : AElfModule { - [DependsOn( - typeof(ChainControllerAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(TokenKernelAElfModule) - )] - public class ChainControllerTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - - services.AddTransient(); - context.Services.Replace(ServiceDescriptor - .Singleton()); - } + var services = context.Services; + services.AddTransient(); + context.Services.Replace(ServiceDescriptor + .Singleton()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.ChainController.Tests/ChainControllerTestBase.cs b/test/AElf.Kernel.ChainController.Tests/ChainControllerTestBase.cs index c2fab8d626..c21c2dbde6 100644 --- a/test/AElf.Kernel.ChainController.Tests/ChainControllerTestBase.cs +++ b/test/AElf.Kernel.ChainController.Tests/ChainControllerTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.Kernel.ChainController +namespace AElf.Kernel.ChainController; + +public class ChainControllerTestBase : AElfIntegratedTest { - public class ChainControllerTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/AElf.Kernel.CodeCheck.Tests.csproj b/test/AElf.Kernel.CodeCheck.Tests/AElf.Kernel.CodeCheck.Tests.csproj index d367551896..85137d7617 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/AElf.Kernel.CodeCheck.Tests.csproj +++ b/test/AElf.Kernel.CodeCheck.Tests/AElf.Kernel.CodeCheck.Tests.csproj @@ -3,21 +3,21 @@ net6.0 - + - - + + - + - - - + + + Protobuf\Proto\acs3.proto - + diff --git a/test/AElf.Kernel.CodeCheck.Tests/Application/CodeCheckServiceTest.cs b/test/AElf.Kernel.CodeCheck.Tests/Application/CodeCheckServiceTest.cs index 438ff63ab4..c3fb3eb266 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/Application/CodeCheckServiceTest.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/Application/CodeCheckServiceTest.cs @@ -1,57 +1,55 @@ using System.Threading.Tasks; using AElf.Kernel.CodeCheck.Application; using AElf.Kernel.CodeCheck.Infrastructure; -using AElf.Kernel.SmartContract.Application; using Microsoft.Extensions.Options; using Shouldly; using Xunit; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +public partial class CodeCheckTest : CodeCheckTestBase { - public partial class CodeCheckTest : CodeCheckTestBase + private readonly CodeCheckOptions _codeCheckOptions; + private readonly ICodeCheckService _codeCheckService; + private readonly IContractAuditorContainer _contractAuditorContainer; + private readonly IRequiredAcsProvider _requiredAcsProvider; + + + public CodeCheckTest() + { + _codeCheckService = GetRequiredService(); + _codeCheckOptions = GetRequiredService>().CurrentValue; + _contractAuditorContainer = GetRequiredService(); + _requiredAcsProvider = GetRequiredService(); + } + + [Fact] + public async Task PerformCodeCheckAsync_Without_CodeCheckEnable_Test() + { + _codeCheckOptions.CodeCheckEnabled = false; + var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, 0, false); + result.ShouldBeTrue(); + } + + [Fact] + public async Task PerformCodeCheckAsync_With_Invalid_Category_Test() + { + var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, -1, false); + result.ShouldBeFalse(); + } + + [Fact] + public async Task PerformCodeCheckAsync_With_Audit_Fail_Test() + { + var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, CodeCheckConstant.FailAudit, false); + result.ShouldBeFalse(); + } + + [Fact] + public async Task PerformCodeCheckAsync_Success_Test() { - private readonly ICodeCheckService _codeCheckService; - private readonly CodeCheckOptions _codeCheckOptions; - private readonly IContractAuditorContainer _contractAuditorContainer; - private readonly IRequiredAcsProvider _requiredAcsProvider; - - - public CodeCheckTest() - { - _codeCheckService = GetRequiredService(); - _codeCheckOptions = GetRequiredService>().CurrentValue; - _contractAuditorContainer = GetRequiredService(); - _requiredAcsProvider = GetRequiredService(); - } - - [Fact] - public async Task PerformCodeCheckAsync_Without_CodeCheckEnable_Test() - { - _codeCheckOptions.CodeCheckEnabled = false; - var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, 0, false); - result.ShouldBeTrue(); - } - - [Fact] - public async Task PerformCodeCheckAsync_With_Invalid_Category_Test() - { - var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, -1, false); - result.ShouldBeFalse(); - } - - [Fact] - public async Task PerformCodeCheckAsync_With_Audit_Fail_Test() - { - var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, CodeCheckConstant.FailAudit, false); - result.ShouldBeFalse(); - } - - [Fact] - public async Task PerformCodeCheckAsync_Success_Test() - { - var result = await _codeCheckService.PerformCodeCheckAsync(null, null, 0, CodeCheckConstant.SuccessAudit, false); - result.ShouldBeTrue(); - } - + var result = + await _codeCheckService.PerformCodeCheckAsync(null, null, 0, CodeCheckConstant.SuccessAudit, false); + result.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckConstant.cs b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckConstant.cs index 45ca761d4a..37de7d70af 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckConstant.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckConstant.cs @@ -1,13 +1,12 @@ -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +public static class CodeCheckConstant { - public static class CodeCheckConstant - { - public const int SuccessAudit = 1000; - public const int FailAudit = 1001; - public const int DefaultAudit = 0; - public const string RequiredAcsInContractsConfigurationName = "RequiredAcsInContracts"; - public const string Acs1 = "acs1"; - public const string Acs2 = "acs1"; - public const bool IsRequireAllAcs = true; - } + public const int SuccessAudit = 1000; + public const int FailAudit = 1001; + public const int DefaultAudit = 0; + public const string RequiredAcsInContractsConfigurationName = "RequiredAcsInContracts"; + public const string Acs1 = "acs1"; + public const string Acs2 = "acs1"; + public const bool IsRequireAllAcs = true; } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckRequiredLogEventProcessorTest.cs b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckRequiredLogEventProcessorTest.cs index 9764dfe3d6..551a79d001 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckRequiredLogEventProcessorTest.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckRequiredLogEventProcessorTest.cs @@ -1,54 +1,56 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Kernel.Proposal.Infrastructure; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +public class LogEventProcessorTest : CodeCheckTestBase { - public class LogEventProcessorTest : CodeCheckTestBase + private readonly ILogEventProcessor _logEventProcessor; + private readonly IProposalProvider _proposalProvider; + + public LogEventProcessorTest() { - private readonly ILogEventProcessor _logEventProcessor; - private readonly IProposalProvider _proposalProvider; + _logEventProcessor = GetRequiredService(); + _proposalProvider = GetRequiredService(); + } - public LogEventProcessorTest() - { - _logEventProcessor = GetRequiredService(); - _proposalProvider = GetRequiredService(); - } - - [Fact] - public async Task GetInterestedEventAsync_Test() + [Fact] + public async Task GetInterestedEventAsync_Test() + { + var interestedEvent = await _logEventProcessor.GetInterestedEventAsync(new ChainContext()); + interestedEvent.ShouldNotBeNull(); + interestedEvent.LogEvent.Name.ShouldContain("CodeCheckRequired"); + } + + [Fact] + public async Task ProcessAsync_Test() + { + var proposalCreated = new ProposalCreated { - var interestedEvent = await _logEventProcessor.GetInterestedEventAsync(new ChainContext()); - interestedEvent.ShouldNotBeNull(); - interestedEvent.LogEvent.Name.ShouldContain("CodeCheckRequired"); - } - - [Fact] - public async Task ProcessAsync_Test() + ProposalId = HashHelper.ComputeFrom("Test") + }; + var transactionResult = new TransactionResult { - var proposalCreated = new ProposalCreated - { - ProposalId = HashHelper.ComputeFrom("Test") - }; - var transactionResult = new TransactionResult + Logs = { - Logs = { new LogEvent + new LogEvent { Name = "ProposalCreated", NonIndexed = proposalCreated.ToByteString() - }} - }; - var logEventsMap = new Dictionary>(); - - // use default auditor - logEventsMap[transactionResult] = new List{new LogEvent()}; - await _logEventProcessor.ProcessAsync(new Block(), logEventsMap); - } + } + } + }; + var logEventsMap = new Dictionary>(); + + // use default auditor + logEventsMap[transactionResult] = new List { new() }; + await _logEventProcessor.ProcessAsync(new Block(), logEventsMap); } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestAElfModule.cs b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestAElfModule.cs index 91c61f120d..c4747f485d 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestAElfModule.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestAElfModule.cs @@ -9,41 +9,37 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +[DependsOn( + typeof(KernelTestAElfModule), + typeof(CodeCheckAElfModule))] +public class CodeCheckTestAElfModule : AElfModule { - [DependsOn( - typeof(KernelTestAElfModule), - typeof(CodeCheckAElfModule))] - public class CodeCheckTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + //IProposalProvider is used to check code check ProcessAsync + context.Services.RemoveAll(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + Configure(options => { options.CodeCheckEnabled = true; }); + context.Services.AddTransient(provider => { - //IProposalProvider is used to check code check ProcessAsync - context.Services.RemoveAll(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - Configure(options => { options.CodeCheckEnabled = true; }); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => - m.GetConfigurationDataAsync(It.IsAny(), - It.IsAny())) - .Returns((configurationName, chainContext) => - { - if (configurationName == CodeCheckConstant.RequiredAcsInContractsConfigurationName) + var mockService = new Mock(); + mockService.Setup(m => + m.GetConfigurationDataAsync(It.IsAny(), + It.IsAny())) + .Returns((configurationName, chainContext) => + { + if (configurationName == CodeCheckConstant.RequiredAcsInContractsConfigurationName) + return Task.FromResult(new RequiredAcsInContracts { - return Task.FromResult(new RequiredAcsInContracts - { - AcsList = {CodeCheckConstant.Acs1, CodeCheckConstant.Acs2}, - RequireAll = CodeCheckConstant.IsRequireAllAcs - }.ToByteString()); - } - return null; - }); - return mockService.Object; - }); - - } + AcsList = { CodeCheckConstant.Acs1, CodeCheckConstant.Acs2 }, + RequireAll = CodeCheckConstant.IsRequireAllAcs + }.ToByteString()); + return null; + }); + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestBase.cs b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestBase.cs index 4b77ff9d2e..ae06bc6f21 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestBase.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/CodeCheckTestBase.cs @@ -1,9 +1,7 @@ using AElf.TestBase; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +public class CodeCheckTestBase : AElfIntegratedTest { - public class CodeCheckTestBase : AElfIntegratedTest - { - - } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/CustomizeContractAuditor.cs b/test/AElf.Kernel.CodeCheck.Tests/CustomizeContractAuditor.cs index a2785fc7e9..9f2ed51c66 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/CustomizeContractAuditor.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/CustomizeContractAuditor.cs @@ -2,31 +2,33 @@ using AElf.Kernel.SmartContract; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +// this auditor is used in log event processor +public class DefaultContractAuditor : IContractAuditor, ISingletonDependency { - // this auditor is used in log event processor - public class DefaultContractAuditor : IContractAuditor, ISingletonDependency + public int Category { get; } = CodeCheckConstant.DefaultAudit; + + public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) { - public int Category { get; } = CodeCheckConstant.DefaultAudit; - public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) - { - } } - - public class CustomizeAlwaysSuccessContractAuditor : IContractAuditor, ISingletonDependency +} + +public class CustomizeAlwaysSuccessContractAuditor : IContractAuditor, ISingletonDependency +{ + public int Category { get; } = CodeCheckConstant.SuccessAudit; + + public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) { - public int Category { get; } = CodeCheckConstant.SuccessAudit; - public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) - { - } } - - public class CustomizeAlwaysFailContractAuditor : IContractAuditor, ISingletonDependency +} + +public class CustomizeAlwaysFailContractAuditor : IContractAuditor, ISingletonDependency +{ + public int Category { get; } = CodeCheckConstant.FailAudit; + + public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) { - public int Category { get; } = CodeCheckConstant.FailAudit; - public void Audit(byte[] code, RequiredAcs requiredAcs, bool isSystemContract) - { - throw new InvalidCodeException("failed"); - } + throw new InvalidCodeException("failed"); } } \ No newline at end of file diff --git a/test/AElf.Kernel.CodeCheck.Tests/Infrastructure/ContractAuditorContainerTest.cs b/test/AElf.Kernel.CodeCheck.Tests/Infrastructure/ContractAuditorContainerTest.cs index 8d00a42c8f..aec65ca24a 100644 --- a/test/AElf.Kernel.CodeCheck.Tests/Infrastructure/ContractAuditorContainerTest.cs +++ b/test/AElf.Kernel.CodeCheck.Tests/Infrastructure/ContractAuditorContainerTest.cs @@ -5,37 +5,36 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.CodeCheck.Tests +namespace AElf.Kernel.CodeCheck.Tests; + +public partial class CodeCheckTest { - public partial class CodeCheckTest + [Fact] + public void TryGetContractAuditor_Test() + { + _contractAuditorContainer.TryGetContractAuditor(CodeCheckConstant.SuccessAudit, out var successAuditor); + successAuditor.GetType().GetTypeInfo().Name.ShouldBe(nameof(CustomizeAlwaysSuccessContractAuditor)); + + _contractAuditorContainer.TryGetContractAuditor(CodeCheckConstant.FailAudit, out var failAuditor); + failAuditor.GetType().GetTypeInfo().Name.ShouldBe(nameof(CustomizeAlwaysFailContractAuditor)); + } + + [Fact] + public void ContractAuditorContainer_Test() + { + var auditor = new CustomizeAlwaysFailContractAuditor(); + var auditors = new List { auditor }; + var contractAuditorContainer = new ContractAuditorContainer(auditors); + contractAuditorContainer.TryGetContractAuditor(auditor.Category, out _).ShouldBeTrue(); + } + + [Fact] + public async Task GetRequiredAcsInContractsAsync_Test() { - [Fact] - public void TryGetContractAuditor_Test() - { - _contractAuditorContainer.TryGetContractAuditor(CodeCheckConstant.SuccessAudit, out var successAuditor); - successAuditor.GetType().GetTypeInfo().Name.ShouldBe(nameof(CustomizeAlwaysSuccessContractAuditor)); - - _contractAuditorContainer.TryGetContractAuditor(CodeCheckConstant.FailAudit, out var failAuditor); - failAuditor.GetType().GetTypeInfo().Name.ShouldBe(nameof(CustomizeAlwaysFailContractAuditor)); - } - - [Fact] - public void ContractAuditorContainer_Test() - { - var auditor = new CustomizeAlwaysFailContractAuditor(); - var auditors = new List{auditor}; - var contractAuditorContainer = new ContractAuditorContainer(auditors); - contractAuditorContainer.TryGetContractAuditor(auditor.Category, out _).ShouldBeTrue(); - } - - [Fact] - public async Task GetRequiredAcsInContractsAsync_Test() - { - var requireAcsConfiguration = await _requiredAcsProvider.GetRequiredAcsInContractsAsync(null, 0); - requireAcsConfiguration.RequireAll.ShouldBe(CodeCheckConstant.IsRequireAllAcs); - requireAcsConfiguration.AcsList.Count.ShouldBe(2); - requireAcsConfiguration.AcsList.Contains(CodeCheckConstant.Acs1).ShouldBeTrue(); - requireAcsConfiguration.AcsList.Contains(CodeCheckConstant.Acs2).ShouldBeTrue(); - } + var requireAcsConfiguration = await _requiredAcsProvider.GetRequiredAcsInContractsAsync(null, 0); + requireAcsConfiguration.RequireAll.ShouldBe(CodeCheckConstant.IsRequireAllAcs); + requireAcsConfiguration.AcsList.Count.ShouldBe(2); + requireAcsConfiguration.AcsList.Contains(CodeCheckConstant.Acs1).ShouldBeTrue(); + requireAcsConfiguration.AcsList.Contains(CodeCheckConstant.Acs2).ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/AElf.Kernel.Configuration.Tests.csproj b/test/AElf.Kernel.Configuration.Tests/AElf.Kernel.Configuration.Tests.csproj index 88c6faf0e4..5c2071b4e6 100644 --- a/test/AElf.Kernel.Configuration.Tests/AElf.Kernel.Configuration.Tests.csproj +++ b/test/AElf.Kernel.Configuration.Tests/AElf.Kernel.Configuration.Tests.csproj @@ -6,12 +6,12 @@ - - - - - - + + + + + + @@ -32,11 +32,11 @@ PreserveNewest - False + False Contract PreserveNewest - + diff --git a/test/AElf.Kernel.Configuration.Tests/ConfigurationServiceTest.cs b/test/AElf.Kernel.Configuration.Tests/ConfigurationServiceTest.cs index 24539e22cf..e47c890391 100644 --- a/test/AElf.Kernel.Configuration.Tests/ConfigurationServiceTest.cs +++ b/test/AElf.Kernel.Configuration.Tests/ConfigurationServiceTest.cs @@ -1,89 +1,88 @@ using System.Threading.Tasks; -using AElf.Standards.ACS3; using AElf.Contracts.Configuration; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner; +using AElf.Standards.ACS3; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.Configuration.Tests +namespace AElf.Kernel.Configuration.Tests; + +public sealed partial class ConfigurationServiceTest : KernelConfigurationTestBase { - public sealed partial class ConfigurationServiceTest : KernelConfigurationTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly IConfigurationService _configurationService; + + public ConfigurationServiceTest() { - private readonly IConfigurationService _configurationService; - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly IBlockchainService _blockchainService; + _blockchainService = GetRequiredService(); + _configurationService = GetRequiredService(); + _blockTransactionLimitProvider = GetRequiredService(); + } - public ConfigurationServiceTest() - { - _blockchainService = GetRequiredService(); - _configurationService = GetRequiredService(); - _blockTransactionLimitProvider = GetRequiredService(); - } + private async Task InitializeContractsAndSetLib() + { + await DeployContractsAsync(); + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); + } - private async Task InitializeContractsAndSetLib() + [Theory] + [InlineData(55, true)] + [InlineData(-50, false)] + public async Task ProcessConfigurationAsync_Test(int targetLimit, bool isSuccessful) + { + var blockTransactionLimitConfigurationProcessor = GetRequiredService(); + var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; + var targetValue = new Int32Value { - await DeployContractsAsync(); - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); - } - - [Theory] - [InlineData(55,true)] - [InlineData(-50,false)] - public async Task ProcessConfigurationAsync_Test(int targetLimit,bool isSuccessful) + Value = targetLimit + }.ToByteString(); + var chain = await _blockchainService.GetChainAsync(); + var blockIndex = new BlockIndex { - var blockTransactionLimitConfigurationProcessor = GetRequiredService(); - var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; - var targetValue = new Int32Value - { - Value = targetLimit - }.ToByteString(); - var chain = await _blockchainService.GetChainAsync(); - var blockIndex = new BlockIndex - { - BlockHeight = chain.BestChainHeight, - BlockHash = chain.BestChainHash - }; - await _configurationService.ProcessConfigurationAsync(configurationName, targetValue, blockIndex); - await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); - var getValue = await _blockTransactionLimitProvider.GetLimitAsync(blockIndex); - getValue.ShouldBe(isSuccessful ? targetLimit : int.MaxValue); - } + BlockHeight = chain.BestChainHeight, + BlockHash = chain.BestChainHash + }; + await _configurationService.ProcessConfigurationAsync(configurationName, targetValue, blockIndex); + await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); + var getValue = await _blockTransactionLimitProvider.GetLimitAsync(blockIndex); + getValue.ShouldBe(isSuccessful ? targetLimit : int.MaxValue); + } - [Fact] - public async Task GetConfigurationDataAsync_Test() + [Fact] + public async Task GetConfigurationDataAsync_Test() + { + var blockTransactionLimitConfigurationProcessor = GetRequiredService(); + var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; + var setValue = 100; + await InitializeContractsAndSetLib(); + var proposalId = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput { - var blockTransactionLimitConfigurationProcessor = GetRequiredService(); - var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; - var setValue = 100; - await InitializeContractsAndSetLib(); - var proposalId = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput - { - ContractMethodName = nameof(ConfigurationStub.SetConfiguration), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = new SetConfigurationInput - { - Key = configurationName, - Value = new Int32Value {Value = setValue}.ToByteString() - }.ToByteString(), - ToAddress = ConfigurationContractAddress, - OrganizationAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()) - })).Output; - await ParliamentContractStub.Approve.SendAsync(proposalId); - await ParliamentContractStub.Release.SendAsync(proposalId); - var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext + ContractMethodName = nameof(ConfigurationStub.SetConfiguration), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = new SetConfigurationInput { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var getValueByteString = await _configurationService.GetConfigurationDataAsync(configurationName, chainContext); - var getValue = Int32Value.Parser.ParseFrom(getValueByteString); - getValue.Value.ShouldBe(setValue); - } + Key = configurationName, + Value = new Int32Value { Value = setValue }.ToByteString() + }.ToByteString(), + ToAddress = ConfigurationContractAddress, + OrganizationAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()) + })).Output; + await ParliamentContractStub.Approve.SendAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var chain = await _blockchainService.GetChainAsync(); + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var getValueByteString = await _configurationService.GetConfigurationDataAsync(configurationName, chainContext); + var getValue = Int32Value.Parser.ParseFrom(getValueByteString); + getValue.Value.ShouldBe(setValue); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/ConfigurationSetLogEventProcessorTest.cs b/test/AElf.Kernel.Configuration.Tests/ConfigurationSetLogEventProcessorTest.cs index 5544d8e97d..cf258dd6fc 100644 --- a/test/AElf.Kernel.Configuration.Tests/ConfigurationSetLogEventProcessorTest.cs +++ b/test/AElf.Kernel.Configuration.Tests/ConfigurationSetLogEventProcessorTest.cs @@ -10,88 +10,87 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Configuration.Tests +namespace AElf.Kernel.Configuration.Tests; + +public partial class ConfigurationServiceTest { - public partial class ConfigurationServiceTest + [Fact] + public async Task GetInterestedEventAsync_Without_DeployContract_Test() { - [Fact] - public async Task GetInterestedEventAsync_Without_DeployContract_Test() + var chain = await _blockchainService.GetChainAsync(); + var chainContext = new ChainContext { - var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var configurationSetLogEventProcessor = GetRequiredService(); - var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); - eventData.ShouldBeNull(); - } - - [Fact] - public async Task GetInterestedEventAsync_Repeat_Get_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var configurationSetLogEventProcessor = GetRequiredService(); + var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); + eventData.ShouldBeNull(); + } + + [Fact] + public async Task GetInterestedEventAsync_Repeat_Get_Test() + { + await InitializeContractsAndSetLib(); + var chain = await _blockchainService.GetChainAsync(); + var chainContext = new ChainContext { - await InitializeContractsAndSetLib(); - var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var configurationSetLogEventProcessor = GetRequiredService(); - await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); - var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(null); - eventData.ShouldNotBeNull(); - } - - [Fact] - public async Task GetInterestedEventAsync_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var configurationSetLogEventProcessor = GetRequiredService(); + await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); + var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(null); + eventData.ShouldNotBeNull(); + } + + [Fact] + public async Task GetInterestedEventAsync_Test() + { + await InitializeContractsAndSetLib(); + var chain = await _blockchainService.GetChainAsync(); + var chainContext = new ChainContext { - await InitializeContractsAndSetLib(); - var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var configurationSetLogEventProcessor = GetRequiredService(); - var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); - eventData.LogEvent.Address.ShouldBe(ConfigurationContractAddress); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var configurationSetLogEventProcessor = GetRequiredService(); + var eventData = await configurationSetLogEventProcessor.GetInterestedEventAsync(chainContext); + eventData.LogEvent.Address.ShouldBe(ConfigurationContractAddress); + } - [Fact] - public async Task ProcessLogEventAsync_Test() + [Fact] + public async Task ProcessLogEventAsync_Test() + { + var blockTransactionLimitConfigurationProcessor = GetRequiredService(); + var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; + var key = configurationName; + var value = new Int32Value + { + Value = 100 + }; + var setting = new ConfigurationSet + { + Key = key, + Value = value.ToByteString() + }; + var logEvent = setting.ToLogEvent(); + var chain = await _blockchainService.GetChainAsync(); + var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(chain.BestChainHeight); + var configurationSetLogEventProcessor = GetRequiredService(); + var logEventDic = new Dictionary>(); + var transactionRet = new TransactionResult + { + BlockHash = block.GetHash() + }; + logEventDic[transactionRet] = new List { logEvent }; + await configurationSetLogEventProcessor.ProcessAsync(block, logEventDic); + await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); + var getValue = await _blockTransactionLimitProvider.GetLimitAsync(new BlockIndex { - var blockTransactionLimitConfigurationProcessor = GetRequiredService(); - var configurationName = blockTransactionLimitConfigurationProcessor.ConfigurationName; - var key = configurationName; - var value = new Int32Value - { - Value = 100 - }; - var setting = new ConfigurationSet - { - Key = key, - Value = value.ToByteString() - }; - var logEvent = setting.ToLogEvent(); - var chain = await _blockchainService.GetChainAsync(); - var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(chain.BestChainHeight); - var configurationSetLogEventProcessor = GetRequiredService(); - var logEventDic = new Dictionary>(); - var transactionRet = new TransactionResult - { - BlockHash = block.GetHash() - }; - logEventDic[transactionRet] = new List{logEvent}; - await configurationSetLogEventProcessor.ProcessAsync(block, logEventDic); - await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); - var getValue = await _blockTransactionLimitProvider.GetLimitAsync(new BlockIndex - { - BlockHeight = chain.BestChainHeight, - BlockHash = chain.BestChainHash - }); - getValue.ShouldBe(value.Value); - } + BlockHeight = chain.BestChainHeight, + BlockHash = chain.BestChainHash + }); + getValue.ShouldBe(value.Value); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/ConfigurationTestModule.cs b/test/AElf.Kernel.Configuration.Tests/ConfigurationTestModule.cs index 4b3ac7d173..1863e5d712 100644 --- a/test/AElf.Kernel.Configuration.Tests/ConfigurationTestModule.cs +++ b/test/AElf.Kernel.Configuration.Tests/ConfigurationTestModule.cs @@ -5,21 +5,20 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Modularity; -namespace AElf.Kernel.Configuration.Tests +namespace AElf.Kernel.Configuration.Tests; + +[DependsOn(typeof(ContractTestModule), + typeof(ConfigurationAElfModule), + typeof(KernelAElfModule))] +public class ConfigurationTestModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule), - typeof(ConfigurationAElfModule), - typeof(KernelAElfModule))] - public class ConfigurationTestModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(typeof(LogEventProcessingService<>)); - context.Services - .Replace(ServiceDescriptor - .Singleton, - OptionalLogEventProcessingService>()); - Configure(o => o.ContractDeploymentAuthorityRequired = false); - } + context.Services.AddSingleton(typeof(LogEventProcessingService<>)); + context.Services + .Replace(ServiceDescriptor + .Singleton, + OptionalLogEventProcessingService>()); + Configure(o => o.ContractDeploymentAuthorityRequired = false); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/KernelConfigurationTestBase.cs b/test/AElf.Kernel.Configuration.Tests/KernelConfigurationTestBase.cs index 2e1862ca49..4fb7260fb1 100644 --- a/test/AElf.Kernel.Configuration.Tests/KernelConfigurationTestBase.cs +++ b/test/AElf.Kernel.Configuration.Tests/KernelConfigurationTestBase.cs @@ -11,50 +11,50 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.Configuration.Tests +namespace AElf.Kernel.Configuration.Tests; + +public class KernelConfigurationTestBase : ContractTestBase { - public class KernelConfigurationTestBase : ContractTestBase + internal ConfigurationContainer.ConfigurationStub ConfigurationStub; + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; + protected Address ConfigurationContractAddress { get; set; } + private ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + + protected async Task DeployContractsAsync() { - protected Address ConfigurationContractAddress { get; set; } - internal ConfigurationContainer.ConfigurationStub ConfigurationStub; - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; - private ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - - protected async Task DeployContractsAsync() - { - var category = KernelConstants.CodeCoverageRunnerCategory; - var code = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Configuration")).Value; - OptionalLogEventProcessingService.Enabled = true; - ConfigurationContractAddress = await DeploySystemSmartContract(category, code, - ConfigurationSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - ConfigurationStub = - GetTester(ConfigurationContractAddress, - DefaultSenderKeyPair); - - var consensusContractCode = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Consensus.AEDPoS")).Value; - var consensusContractAddress = await DeploySystemSmartContract(category, consensusContractCode, - ConsensusSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - var consensusStub = GetTester(consensusContractAddress, + var category = KernelConstants.CodeCoverageRunnerCategory; + var code = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Configuration")).Value; + OptionalLogEventProcessingService.Enabled = true; + ConfigurationContractAddress = await DeploySystemSmartContract(category, code, + ConfigurationSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ConfigurationStub = + GetTester(ConfigurationContractAddress, DefaultSenderKeyPair); - await consensusStub.FirstRound.SendAsync( - new MinerList - { - Pubkeys = {ByteString.CopyFrom(DefaultSenderKeyPair.PublicKey)} - }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow()) - ); - - var parliamentContractCode = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Parliament")).Value; - var parliamentContractAddress = await DeploySystemSmartContract(category, parliamentContractCode, - ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - ParliamentContractStub = GetTester(parliamentContractAddress, - DefaultSenderKeyPair); - - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + var consensusContractCode = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Consensus.AEDPoS")).Value; + var consensusContractAddress = await DeploySystemSmartContract(category, consensusContractCode, + ConsensusSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + var consensusStub = GetTester(consensusContractAddress, + DefaultSenderKeyPair); + + await consensusStub.FirstRound.SendAsync( + new MinerList { - ProposerAuthorityRequired = true, - PrivilegedProposer = Address.FromPublicKey(DefaultSenderKeyPair.PublicKey) - }); - } + Pubkeys = { ByteString.CopyFrom(DefaultSenderKeyPair.PublicKey) } + }.GenerateFirstRoundOfNewTerm(4000, TimestampHelper.GetUtcNow()) + ); + + var parliamentContractCode = Codes.Single(kv => kv.Key.Split(",").First().EndsWith("Parliament")).Value; + var parliamentContractAddress = await DeploySystemSmartContract(category, parliamentContractCode, + ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ParliamentContractStub = GetTester( + parliamentContractAddress, + DefaultSenderKeyPair); + + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = true, + PrivilegedProposer = Address.FromPublicKey(DefaultSenderKeyPair.PublicKey) + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/MinerList.cs b/test/AElf.Kernel.Configuration.Tests/MinerList.cs index 96a1ddef1e..0ef019af8c 100644 --- a/test/AElf.Kernel.Configuration.Tests/MinerList.cs +++ b/test/AElf.Kernel.Configuration.Tests/MinerList.cs @@ -4,51 +4,47 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; - } + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - public Hash GetMinersHash() + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var orderedMiners = Pubkeys.OrderBy(p => p); - return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; + } + + public Hash GetMinersHash() + { + var orderedMiners = Pubkeys.OrderBy(p => p); + return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Configuration.Tests/OptionalLogEventProcessingService.cs b/test/AElf.Kernel.Configuration.Tests/OptionalLogEventProcessingService.cs index 1732e514bc..2889452efa 100644 --- a/test/AElf.Kernel.Configuration.Tests/OptionalLogEventProcessingService.cs +++ b/test/AElf.Kernel.Configuration.Tests/OptionalLogEventProcessingService.cs @@ -3,25 +3,21 @@ using AElf.Kernel.Blockchain; using AElf.Kernel.SmartContract.Application; -namespace AElf.Kernel.Configuration.Tests +namespace AElf.Kernel.Configuration.Tests; + +public class OptionalLogEventProcessingService : ILogEventProcessingService where T : ILogEventProcessor { - public class OptionalLogEventProcessingService : ILogEventProcessingService where T : ILogEventProcessor - { - private LogEventProcessingService _inner; + private readonly LogEventProcessingService _inner; - public OptionalLogEventProcessingService(LogEventProcessingService inner) - { - _inner = inner; - } + public OptionalLogEventProcessingService(LogEventProcessingService inner) + { + _inner = inner; + } - public static bool Enabled { get; set; } + public static bool Enabled { get; set; } - public async Task ProcessAsync(List blockExecutedSets) - { - if (Enabled) - { - await _inner.ProcessAsync(blockExecutedSets); - } - } + public async Task ProcessAsync(List blockExecutedSets) + { + if (Enabled) await _inner.ProcessAsync(blockExecutedSets); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs index c6281fae45..685b78a9ab 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs @@ -1,11 +1,13 @@ -using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Kernel.Blockchain.Application; using AElf.Contracts.Consensus.AEDPoS; +using AElf.CSharp.Core.Extension; +using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Kernel.Consensus.Application; +using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; +using AElf.Kernel.Txn.Application; using AElf.Modularity; using AElf.Types; using Google.Protobuf; @@ -13,167 +15,166 @@ using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -using AElf.CSharp.Core.Extension; -using AElf.Kernel.SmartContract; -using AElf.Kernel.Txn.Application; -namespace AElf.Kernel.Consensus.DPoS.Tests +namespace AElf.Kernel.Consensus.DPoS.Tests; + +[DependsOn( + typeof(KernelTestAElfModule), + typeof(SmartContractAElfModule), + typeof(AEDPoSAElfModule))] +// ReSharper disable once InconsistentNaming +public class AEDPoSTestAElfModule : AElfModule { - [DependsOn( - typeof(KernelTestAElfModule), - typeof(SmartContractAElfModule), - typeof(AEDPoSAElfModule))] - // ReSharper disable once InconsistentNaming - public class AEDPoSTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var interestedEvent = new IrreversibleBlockFound(); - var logEvent = interestedEvent.ToLogEvent(SampleAddress.AddressList[0]); + var interestedEvent = new IrreversibleBlockFound(); + var logEvent = interestedEvent.ToLogEvent(SampleAddress.AddressList[0]); - context.Services.AddTransient(provider => + context.Services.AddTransient(provider => + { + var mockBlockChainService = new Mock(); + mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => { - var mockBlockChainService = new Mock(); - mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() => + var chain = new Chain { - var chain = new Chain - { - LastIrreversibleBlockHeight = 10, - LastIrreversibleBlockHash = HashHelper.ComputeFrom("LastIrreversibleBlockHash") - }; + LastIrreversibleBlockHeight = 10, + LastIrreversibleBlockHash = HashHelper.ComputeFrom("LastIrreversibleBlockHash") + }; - return Task.FromResult(chain); - }); + return Task.FromResult(chain); + }); - mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(Task.FromResult( - new Block + mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny())).Returns(Task.FromResult( + new Block + { + Header = new BlockHeader { - Header = new BlockHeader - { - Bloom = ByteString.CopyFrom(logEvent.GetBloom().Data), - Height = 15 - }, - Body = new BlockBody + Bloom = ByteString.CopyFrom(logEvent.GetBloom().Data), + Height = 15 + }, + Body = new BlockBody + { + TransactionIds = { - TransactionIds = - { - HashHelper.ComputeFrom("not exist"), - HashHelper.ComputeFrom("failed case"), - HashHelper.ComputeFrom("mined case") - } + HashHelper.ComputeFrom("not exist"), + HashHelper.ComputeFrom("failed case"), + HashHelper.ComputeFrom("mined case") } } - )); + } + )); - mockBlockChainService.Setup(m => - m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new Hash())); - return mockBlockChainService.Object; - }); + mockBlockChainService.Setup(m => + m.GetBlockHashByHeightAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(new Hash())); + return mockBlockChainService.Object; + }); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("not exist")))) - .Returns(Task.FromResult(null)); - mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("failed case")))) - .Returns(Task.FromResult(new TransactionResult - { - Error = "failed due to some reason", - Status = TransactionResultStatus.Failed - })); - mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("mined case")))) - .Returns(Task.FromResult(new TransactionResult + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("not exist")))) + .Returns(Task.FromResult(null)); + mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("failed case")))) + .Returns(Task.FromResult(new TransactionResult + { + Error = "failed due to some reason", + Status = TransactionResultStatus.Failed + })); + mockService.Setup(m => m.GetTransactionResultAsync(It.IsIn(HashHelper.ComputeFrom("mined case")))) + .Returns(Task.FromResult(new TransactionResult + { + Status = TransactionResultStatus.Mined, + Bloom = ByteString.CopyFrom(logEvent.GetBloom().Data), + Logs = { - Status = TransactionResultStatus.Mined, - Bloom = ByteString.CopyFrom(logEvent.GetBloom().Data), - Logs = + new LogEvent { - new LogEvent - { - Address = SampleAddress.AddressList[0], - Name = logEvent.Name - } + Address = SampleAddress.AddressList[0], + Name = logEvent.Name } - })); - - return mockService.Object; - }); + } + })); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - var consensusHash = ConsensusSmartContractAddressNameProvider.StringName; - mockService.Setup(o => o.GetAddressByContractNameAsync(It.IsAny(), It.Is(hash => hash != consensusHash))) - .Returns(Task.FromResult(SampleAddress.AddressList[0])); - mockService.Setup(o => - o.GetAddressByContractNameAsync(It.IsAny(), It.Is(hash => hash == consensusHash))) - .Returns(Task.FromResult(SampleAddress.AddressList[1])); - - return mockService.Object; - }); + return mockService.Object; + }); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetExtraDataFromBlockHeader("Consensus", - It.Is(o => o != null))) - .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation - { - Behaviour = AElfConsensusBehaviour.UpdateValue, - SenderPubkey = ByteString.CopyFromUtf8("real-pubkey"), - Round = new Round() - }.ToByteArray())); - mockService.Setup(m => m.GetExtraDataFromBlockHeader("Consensus", - It.Is(o => o == null))) - .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation - { - Behaviour = AElfConsensusBehaviour.Nothing, - SenderPubkey = ByteString.CopyFromUtf8("real-pubkey"), - Round = new Round() - }.ToByteArray())); + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + var consensusHash = ConsensusSmartContractAddressNameProvider.StringName; + mockService.Setup(o => + o.GetAddressByContractNameAsync(It.IsAny(), + It.Is(hash => hash != consensusHash))) + .Returns(Task.FromResult(SampleAddress.AddressList[0])); + mockService.Setup(o => + o.GetAddressByContractNameAsync(It.IsAny(), + It.Is(hash => hash == consensusHash))) + .Returns(Task.FromResult(SampleAddress.AddressList[1])); + + return mockService.Object; + }); + + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetExtraDataFromBlockHeader("Consensus", + It.Is(o => o != null))) + .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation + { + Behaviour = AElfConsensusBehaviour.UpdateValue, + SenderPubkey = ByteString.CopyFromUtf8("real-pubkey"), + Round = new Round() + }.ToByteArray())); + mockService.Setup(m => m.GetExtraDataFromBlockHeader("Consensus", + It.Is(o => o == null))) + .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation + { + Behaviour = AElfConsensusBehaviour.Nothing, + SenderPubkey = ByteString.CopyFromUtf8("real-pubkey"), + Round = new Round() + }.ToByteArray())); - return mockService.Object; - }); + return mockService.Object; + }); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetConsensusExtraDataAsync(It.IsAny())).Returns( - Task.FromResult(ByteString.CopyFromUtf8("test").ToByteArray())); + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetConsensusExtraDataAsync(It.IsAny())).Returns( + Task.FromResult(ByteString.CopyFromUtf8("test").ToByteArray())); - mockService.Setup(m => m.TriggerConsensusAsync(It.IsAny())).Returns(Task.CompletedTask); + mockService.Setup(m => m.TriggerConsensusAsync(It.IsAny())).Returns(Task.CompletedTask); - return mockService.Object; - }); + return mockService.Object; + }); - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => - tx.MethodName == "GetCurrentMinerList"), - It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + context.Services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => + tx.MethodName == "GetCurrentMinerList"), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new MinerList { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new MinerList + Pubkeys = { - Pubkeys = - { - ByteString.CopyFromUtf8("bp1"), - ByteString.CopyFromUtf8("bp2"), - ByteString.CopyFromUtf8("bp3") - } - }.ToByteArray()) - })); - - return mockService.Object; - }); + ByteString.CopyFromUtf8("bp1"), + ByteString.CopyFromUtf8("bp2"), + ByteString.CopyFromUtf8("bp3") + } + }.ToByteArray()) + })); + + return mockService.Object; + }); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestBase.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestBase.cs index 6cf895f86c..38e045bfbd 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestBase.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestBase.cs @@ -1,9 +1,8 @@ using AElf.TestBase; -namespace AElf.Kernel.Consensus.DPoS.Tests +namespace AElf.Kernel.Consensus.DPoS.Tests; + +// ReSharper disable once InconsistentNaming +public class AEDPoSTestBase : AElfIntegratedTest { - // ReSharper disable once InconsistentNaming - public class AEDPoSTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AElf.Kernel.Consensus.AEDPoS.Tests.csproj b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AElf.Kernel.Consensus.AEDPoS.Tests.csproj index 7ece11fce0..b34762b039 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AElf.Kernel.Consensus.AEDPoS.Tests.csproj +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AElf.Kernel.Consensus.AEDPoS.Tests.csproj @@ -7,17 +7,17 @@ 0436 - - - - - - + + + + + + - - - + + + diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSExtraDataExtractorTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSExtraDataExtractorTests.cs index ce2e71f0bb..f8a0940ac6 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSExtraDataExtractorTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSExtraDataExtractorTests.cs @@ -5,46 +5,45 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Consensus.DPoS.Tests.Application +namespace AElf.Kernel.Consensus.DPoS.Tests.Application; + +public class AEDPoSExtraDataExtractorTests : AEDPoSTestBase { - public class AEDPoSExtraDataExtractorTests : AEDPoSTestBase + private readonly IBlockchainService _blockchainService; + private readonly IConsensusExtraDataExtractor _consensusExtraDataExtractor; + + public AEDPoSExtraDataExtractorTests() { - private readonly IConsensusExtraDataExtractor _consensusExtraDataExtractor; - private readonly IBlockchainService _blockchainService; + _consensusExtraDataExtractor = GetRequiredService(); + _blockchainService = GetRequiredService(); + } - public AEDPoSExtraDataExtractorTests() - { - _consensusExtraDataExtractor = GetRequiredService(); - _blockchainService = GetRequiredService(); - } + [Fact] + public async Task ExtractConsensusExtraData_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var height = chain.BestChainHeight; + var hash = chain.BestChainHash; - [Fact] - public async Task ExtractConsensusExtraData_Test() + var header = new BlockHeader { - var chain = await _blockchainService.GetChainAsync(); - var height = chain.BestChainHeight; - var hash = chain.BestChainHash; + PreviousBlockHash = hash, + Height = height, + SignerPubkey = ByteString.CopyFromUtf8("fake-pubkey") + }; + var result = _consensusExtraDataExtractor.ExtractConsensusExtraData(header); + result.ShouldBeNull(); - var header = new BlockHeader - { - PreviousBlockHash = hash, - Height = height, - SignerPubkey = ByteString.CopyFromUtf8("fake-pubkey") - }; - var result = _consensusExtraDataExtractor.ExtractConsensusExtraData(header); - result.ShouldBeNull(); - - header.SignerPubkey = ByteString.CopyFromUtf8("real-pubkey"); - result = _consensusExtraDataExtractor.ExtractConsensusExtraData(header); - result.ShouldNotBeNull(); - } + header.SignerPubkey = ByteString.CopyFromUtf8("real-pubkey"); + result = _consensusExtraDataExtractor.ExtractConsensusExtraData(header); + result.ShouldNotBeNull(); + } - [Fact] - public void ExtractConsensusExtraData_Test_Null() - { - var extraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(new BlockHeader - {Height = AElfConstants.GenesisBlockHeight}); - extraData.ShouldBeNull(); - } + [Fact] + public void ExtractConsensusExtraData_Test_Null() + { + var extraData = _consensusExtraDataExtractor.ExtractConsensusExtraData(new BlockHeader + { Height = AElfConstants.GenesisBlockHeight }); + extraData.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs index 5245fe8441..e17515599c 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs @@ -1,68 +1,67 @@ using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS4; using AElf.Contracts.Consensus.AEDPoS; using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Kernel.Consensus.Application; +using AElf.Standards.ACS4; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.Consensus.DPoS.Tests.Application +namespace AElf.Kernel.Consensus.DPoS.Tests.Application; + +public class AEDPoSTriggerInformationProviderTests : AEDPoSTestBase { - public class AEDPoSTriggerInformationProviderTests : AEDPoSTestBase - { - private ITriggerInformationProvider _triggerInformationProvider; - private IAEDPoSInformationProvider _aedpoSInformationProvider; + private readonly IAEDPoSInformationProvider _aedpoSInformationProvider; + private readonly ITriggerInformationProvider _triggerInformationProvider; - public AEDPoSTriggerInformationProviderTests() - { - _triggerInformationProvider = GetRequiredService(); - _aedpoSInformationProvider = GetRequiredService(); - } + public AEDPoSTriggerInformationProviderTests() + { + _triggerInformationProvider = GetRequiredService(); + _aedpoSInformationProvider = GetRequiredService(); + } - [Fact] - public Task GetTriggerInformationForBlockHeaderExtraData_ConsensusCommand_Test() - { - var result = - _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( - new BytesValue()); - var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); - triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); + [Fact] + public Task GetTriggerInformationForBlockHeaderExtraData_ConsensusCommand_Test() + { + var result = + _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( + new BytesValue()); + var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); + triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); - result = _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( - new ConsensusCommand - {Hint = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.Nothing}.ToByteString()} - .ToBytesValue()); - triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); - triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.Nothing); - return Task.CompletedTask; - } + result = _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData( + new ConsensusCommand + { Hint = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.Nothing }.ToByteString() } + .ToBytesValue()); + triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); + triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.Nothing); + return Task.CompletedTask; + } - [Fact] - public async Task GetCurrentMinerList_Test() - { - var result = await _aedpoSInformationProvider.GetCurrentMinerList(new ChainContext()); - result.Count().ShouldBe(3); - } + [Fact] + public async Task GetCurrentMinerList_Test() + { + var result = await _aedpoSInformationProvider.GetCurrentMinerList(new ChainContext()); + result.Count().ShouldBe(3); + } - [Fact] - public void GetTriggerInformationForBlockHeaderExtraData_CommandIsNull_Test() - { - var result = - _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData(null); - var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); - triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); - } + [Fact] + public void GetTriggerInformationForBlockHeaderExtraData_CommandIsNull_Test() + { + var result = + _triggerInformationProvider.GetTriggerInformationForBlockHeaderExtraData(null); + var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); + triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); + } - [Fact] - public void GetTriggerInformationForConsensusTransactions_CommandIsNull_Test() - { - var result = - _triggerInformationProvider.GetTriggerInformationForConsensusTransactions(null); - var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); - triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); - } + [Fact] + public void GetTriggerInformationForConsensusTransactions_CommandIsNull_Test() + { + var result = + _triggerInformationProvider.GetTriggerInformationForConsensusTransactions(null); + var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); + triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusExtraDataProviderTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusExtraDataProviderTests.cs index f3e20d5b68..6103de4fd3 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusExtraDataProviderTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusExtraDataProviderTests.cs @@ -1,44 +1,42 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.Consensus.DPoS.Tests.Application +namespace AElf.Kernel.Consensus.DPoS.Tests.Application; + +public class ConsensusExtraDataProviderTests : AEDPoSTestBase { - public class ConsensusExtraDataProviderTests : AEDPoSTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockExtraDataProvider _blockExtraDataProvider; + + public ConsensusExtraDataProviderTests() { - private readonly IBlockExtraDataProvider _blockExtraDataProvider; - private readonly IBlockchainService _blockchainService; + _blockExtraDataProvider = GetRequiredService(); + _blockchainService = GetRequiredService(); + } - public ConsensusExtraDataProviderTests() + [Fact] + public async Task GetExtraDataForFillingBlockHeaderAsync_Test() + { + //null situation + var blockHeader = new BlockHeader { - _blockExtraDataProvider = GetRequiredService(); - _blockchainService = GetRequiredService(); - } + Height = 1 + }; + var result = await _blockExtraDataProvider.GetBlockHeaderExtraDataAsync(blockHeader); + result.ShouldBeNull(); - [Fact] - public async Task GetExtraDataForFillingBlockHeaderAsync_Test() - { - //null situation - var blockHeader = new BlockHeader - { - Height = 1 - }; - var result = await _blockExtraDataProvider.GetBlockHeaderExtraDataAsync(blockHeader); - result.ShouldBeNull(); - - //with data - var chain = await _blockchainService.GetChainAsync(); - var height = chain.BestChainHeight; - var hash = chain.BestChainHash; + //with data + var chain = await _blockchainService.GetChainAsync(); + var height = chain.BestChainHeight; + var hash = chain.BestChainHash; - var result1 = await _blockExtraDataProvider.GetBlockHeaderExtraDataAsync(new BlockHeader - { - PreviousBlockHash = hash, - Height = height - }); - result1.ShouldNotBeNull(); - } + var result1 = await _blockExtraDataProvider.GetBlockHeaderExtraDataAsync(new BlockHeader + { + PreviousBlockHash = hash, + Height = height + }); + result1.ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusValidationFailedEventHandlerTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusValidationFailedEventHandlerTests.cs index a567b992ae..91b188e757 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusValidationFailedEventHandlerTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/ConsensusValidationFailedEventHandlerTests.cs @@ -2,28 +2,27 @@ using AElf.Kernel.Consensus.AEDPoS.Application; using Xunit; -namespace AElf.Kernel.Consensus.DPoS.Tests.Application +namespace AElf.Kernel.Consensus.DPoS.Tests.Application; + +public class ConsensusValidationFailedEventHandlerTests : AEDPoSTestBase { - public class ConsensusValidationFailedEventHandlerTests : AEDPoSTestBase - { - private readonly ConsensusValidationFailedEventHandler _consensusValidationFailedEventHandler; + private readonly ConsensusValidationFailedEventHandler _consensusValidationFailedEventHandler; - public ConsensusValidationFailedEventHandlerTests() - { - _consensusValidationFailedEventHandler = GetRequiredService(); - } + public ConsensusValidationFailedEventHandlerTests() + { + _consensusValidationFailedEventHandler = GetRequiredService(); + } - [Fact] - public async Task HandleEventAsync_Test() + [Fact] + public async Task HandleEventAsync_Test() + { + var eventData = new ConsensusValidationFailedEventData { - var eventData = new ConsensusValidationFailedEventData() - { - ValidationResultMessage = "Time slot already passed before execution." - }; - await _consensusValidationFailedEventHandler.HandleEventAsync(eventData); + ValidationResultMessage = "Time slot already passed before execution." + }; + await _consensusValidationFailedEventHandler.HandleEventAsync(eventData); - eventData.ValidationResultMessage = "other message"; - await _consensusValidationFailedEventHandler.HandleEventAsync(eventData); - } + eventData.ValidationResultMessage = "other message"; + await _consensusValidationFailedEventHandler.HandleEventAsync(eventData); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/InValueCacheTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/InValueCacheTests.cs index 394ae0bed8..4b19326a33 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/InValueCacheTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/InValueCacheTests.cs @@ -1,35 +1,38 @@ -using System; using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Kernel.Consensus.DPoS.Tests.Application +namespace AElf.Kernel.Consensus.DPoS.Tests.Application; + +public class InValueCacheTests : AEDPoSTestBase { - public class InValueCacheTests : AEDPoSTestBase + private readonly IInValueCache _inValueCache; + + public InValueCacheTests() { - private IInValueCache _inValueCache; + _inValueCache = GetRequiredService(); + } - public InValueCacheTests() + [Fact] + public void InValueCacheBasicFunctionTest() + { + const long startRoundId = 1000000L; + + Hash GenerateInValue(long i) { - _inValueCache = GetRequiredService(); + return HashHelper.ComputeFrom($"InValue{i.ToString()}"); } - [Fact] - public void InValueCacheBasicFunctionTest() + for (var i = 0; i < 13; i++) { - const long startRoundId = 1000000L; - Hash GenerateInValue(long i) => HashHelper.ComputeFrom($"InValue{i.ToString()}"); - for (var i = 0; i < 13; i++) - { - var roundId = startRoundId + i * 100; - var inValue = GenerateInValue(roundId); - _inValueCache.AddInValue(roundId, inValue); - } - - _inValueCache.GetInValue(startRoundId + 500).ShouldBe(GenerateInValue(startRoundId + 500)); - // Already cleared. - _inValueCache.GetInValue(startRoundId).ShouldBe(Hash.Empty); + var roundId = startRoundId + i * 100; + var inValue = GenerateInValue(roundId); + _inValueCache.AddInValue(roundId, inValue); } + + _inValueCache.GetInValue(startRoundId + 500).ShouldBe(GenerateInValue(startRoundId + 500)); + // Already cleared. + _inValueCache.GetInValue(startRoundId).ShouldBe(Hash.Empty); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/MockTransactionPackingOptionProvider.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/MockTransactionPackingOptionProvider.cs index a57c79ea15..f1be355179 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/MockTransactionPackingOptionProvider.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/MockTransactionPackingOptionProvider.cs @@ -1,21 +1,20 @@ using System.Threading.Tasks; using AElf.Kernel.Txn.Application; -namespace AElf.Kernel.Consensus.DPoS.Tests +namespace AElf.Kernel.Consensus.DPoS.Tests; + +public class MockTransactionPackingOptionProvider : ITransactionPackingOptionProvider { - public class MockTransactionPackingOptionProvider : ITransactionPackingOptionProvider - { - private bool _isTransactionPackable = true; + private bool _isTransactionPackable = true; - public Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) - { - _isTransactionPackable = isTransactionPackable; - return Task.CompletedTask; - } + public Task SetTransactionPackingOptionAsync(IBlockIndex blockIndex, bool isTransactionPackable) + { + _isTransactionPackable = isTransactionPackable; + return Task.CompletedTask; + } - public bool IsTransactionPackable(IChainContext chainContext) - { - return _isTransactionPackable; - } + public bool IsTransactionPackable(IChainContext chainContext) + { + return _isTransactionPackable; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/AElf.Kernel.Consensus.Tests.csproj b/test/AElf.Kernel.Consensus.Tests/AElf.Kernel.Consensus.Tests.csproj index 73b995f18d..dd8be58621 100644 --- a/test/AElf.Kernel.Consensus.Tests/AElf.Kernel.Consensus.Tests.csproj +++ b/test/AElf.Kernel.Consensus.Tests/AElf.Kernel.Consensus.Tests.csproj @@ -6,20 +6,20 @@ false - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/test/AElf.Kernel.Consensus.Tests/Application/ConsensusServiceTests.cs b/test/AElf.Kernel.Consensus.Tests/Application/ConsensusServiceTests.cs index 9728a644e5..19f8900102 100644 --- a/test/AElf.Kernel.Consensus.Tests/Application/ConsensusServiceTests.cs +++ b/test/AElf.Kernel.Consensus.Tests/Application/ConsensusServiceTests.cs @@ -5,91 +5,90 @@ using Volo.Abp.Threading; using Xunit; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public sealed class ConsensusServiceTests : ConsensusTestBase { - public sealed class ConsensusServiceTests : ConsensusTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockTimeProvider _blockTimeProvider; + private readonly IConsensusService _consensusService; + + public ConsensusServiceTests() { - private readonly IConsensusService _consensusService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockTimeProvider _blockTimeProvider; + _blockchainService = GetRequiredService(); + _consensusService = GetRequiredService(); + _blockTimeProvider = GetRequiredService(); + } - private ChainContext ChainContext => AsyncHelper.RunSync(GetDefaultChainContextAsync); + private ChainContext ChainContext => AsyncHelper.RunSync(GetDefaultChainContextAsync); - public ConsensusServiceTests() - { - _blockchainService = GetRequiredService(); - _consensusService = GetRequiredService(); - _blockTimeProvider = GetRequiredService(); - } + [Fact] + public async Task TriggerConsensusAsync_Test() + { + await _consensusService.TriggerConsensusAsync(ChainContext); - [Fact] - public async Task TriggerConsensusAsync_Test() - { - await _consensusService.TriggerConsensusAsync(ChainContext); + // Check BlockTimeProvider. + var blockTime = _blockTimeProvider.GetBlockTime(Hash.Empty); + blockTime.ShouldNotBeNull(); - // Check BlockTimeProvider. - var blockTime = _blockTimeProvider.GetBlockTime(Hash.Empty); - blockTime.ShouldNotBeNull(); + // Check whether consensus scheduler is filled. + var consensusTestHelper = GetRequiredService(); + consensusTestHelper.IsConsensusSchedulerFilled.ShouldBeTrue(); + } - // Check whether consensus scheduler is filled. - var consensusTestHelper = GetRequiredService(); - consensusTestHelper.IsConsensusSchedulerFilled.ShouldBeTrue(); - } + [Fact] + public async Task ValidateConsensusBeforeExecutionAsync_Test() + { + var chainContext = ChainContext; - [Fact] - public async Task ValidateConsensusBeforeExecutionAsync_Test() - { - var chainContext = ChainContext; + (await _consensusService.ValidateConsensusBeforeExecutionAsync(chainContext, new byte[] { })) + .ShouldBeFalse(); + (await _consensusService.ValidateConsensusBeforeExecutionAsync(chainContext, new byte[] { 0, 1 })) + .ShouldBeTrue(); + } - (await _consensusService.ValidateConsensusBeforeExecutionAsync(chainContext, new byte[] { })) - .ShouldBeFalse(); - (await _consensusService.ValidateConsensusBeforeExecutionAsync(chainContext, new byte[] {0, 1})) - .ShouldBeTrue(); - } + [Fact] + public async Task ValidateConsensusAfterExecutionAsync_Test() + { + var chainContext = ChainContext; - [Fact] - public async Task ValidateConsensusAfterExecutionAsync_Test() - { - var chainContext = ChainContext; + (await _consensusService.ValidateConsensusAfterExecutionAsync(chainContext, new byte[] { })) + .ShouldBeFalse(); + (await _consensusService.ValidateConsensusAfterExecutionAsync(chainContext, new byte[] { 0, 1 })) + .ShouldBeTrue(); + } - (await _consensusService.ValidateConsensusAfterExecutionAsync(chainContext, new byte[] { })) - .ShouldBeFalse(); - (await _consensusService.ValidateConsensusAfterExecutionAsync(chainContext, new byte[] {0, 1})) - .ShouldBeTrue(); - } + [Fact] + public async Task GetConsensusExtraDataAsyncAsync_Test() + { + await TriggerConsensusAsync(); + var result = await _consensusService.GetConsensusExtraDataAsync(ChainContext); + result.ShouldNotBeNull(); + } - [Fact] - public async Task GetConsensusExtraDataAsyncAsync_Test() - { - await TriggerConsensusAsync(); - var result = await _consensusService.GetConsensusExtraDataAsync(ChainContext); - result.ShouldNotBeNull(); - } + [Fact] + public async Task GenerateConsensusTransactionsAsync_Test() + { + await TriggerConsensusAsync(); + var result = await _consensusService.GenerateConsensusTransactionsAsync(ChainContext); + result.Count.ShouldBe(1); + } - [Fact] - public async Task GenerateConsensusTransactionsAsync_Test() - { - await TriggerConsensusAsync(); - var result = await _consensusService.GenerateConsensusTransactionsAsync(ChainContext); - result.Count.ShouldBe(1); - } + private async Task TriggerConsensusAsync() + { + var chainContext = await GetDefaultChainContextAsync(); + await _consensusService.TriggerConsensusAsync(chainContext); + } - private async Task TriggerConsensusAsync() + private async Task GetDefaultChainContextAsync() + { + var chain = await _blockchainService.GetChainAsync(); + var chainContext = new ChainContext { - var chainContext = await GetDefaultChainContextAsync(); - await _consensusService.TriggerConsensusAsync(chainContext); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; - private async Task GetDefaultChainContextAsync() - { - var chain = await _blockchainService.GetChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - - return chainContext; - } + return chainContext; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/Application/ConsensusValidationProviderTests.cs b/test/AElf.Kernel.Consensus.Tests/Application/ConsensusValidationProviderTests.cs index 62b0530c14..9991d5353c 100644 --- a/test/AElf.Kernel.Consensus.Tests/Application/ConsensusValidationProviderTests.cs +++ b/test/AElf.Kernel.Consensus.Tests/Application/ConsensusValidationProviderTests.cs @@ -1,98 +1,93 @@ using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.Consensus.Application +namespace AElf.Kernel.Consensus.Application; + +public class ConsensusValidationProviderTests : ConsensusTestBase { - public class ConsensusValidationProviderTests : ConsensusTestBase - { - private readonly IBlockValidationProvider _blockValidationProvider; - private readonly KernelTestHelper _kernelTestHelper; + private readonly IBlockValidationProvider _blockValidationProvider; + private readonly KernelTestHelper _kernelTestHelper; - public ConsensusValidationProviderTests() - { - _blockValidationProvider = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + public ConsensusValidationProviderTests() + { + _blockValidationProvider = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - [Fact] - public async Task ValidateBeforeAttachAsync_Test() + [Fact] + public async Task ValidateBeforeAttachAsync_Test() + { + var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test")); + block.Header = new BlockHeader { - var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test")); - block.Header = new BlockHeader - { - Height = 1, - ExtraData = { } - }; - var result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - result.ShouldBeTrue(); + Height = 1 + }; + var result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + result.ShouldBeTrue(); - block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); - result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - result.ShouldBeFalse(); + block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); + result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + result.ShouldBeFalse(); - block.Header = new BlockHeader - { - Height = 10, - ExtraData = {{ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("test")}}, - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash") - }; - result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - result.ShouldBeTrue(); - } + block.Header = new BlockHeader + { + Height = 10, + ExtraData = { { ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("test") } }, + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash") + }; + result = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + result.ShouldBeTrue(); + } - [Fact] - public async Task ValidateBlockBeforeExecuteAsync_Test() + [Fact] + public async Task ValidateBlockBeforeExecuteAsync_Test() + { + var block = new Block { - var block = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - Height = 1, - ExtraData = { } - } - }; - var result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - result.ShouldBeTrue(); + Height = 1 + } + }; + var result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + result.ShouldBeTrue(); - block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); - result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - result.ShouldBeFalse(); + block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); + result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + result.ShouldBeFalse(); - block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test"), null, - new Dictionary - {{ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("extra data")}}); - result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - result.ShouldBeTrue(); - } + block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test"), null, + new Dictionary + { { ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("extra data") } }); + result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + result.ShouldBeTrue(); + } - [Fact] - public async Task ValidateBlockAfterExecuteAsync_Test() + [Fact] + public async Task ValidateBlockAfterExecuteAsync_Test() + { + var block = new Block { - var block = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - Height = 1, - ExtraData = { } - } - }; - var result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - result.ShouldBeTrue(); + Height = 1 + } + }; + var result = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + result.ShouldBeTrue(); - block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); - result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(block); - result.ShouldBeFalse(); + block = _kernelTestHelper.GenerateBlock(8, HashHelper.ComputeFrom("test")); + result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(block); + result.ShouldBeFalse(); - block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test"), null, - new Dictionary - {{ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("extra data")}}); - result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(block); - result.ShouldBeTrue(); - } + block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("test"), null, + new Dictionary + { { ConsensusConstants.ConsensusExtraDataKey, ByteString.CopyFromUtf8("extra data") } }); + result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(block); + result.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs b/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs index 6e2679d955..b31b834a82 100644 --- a/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs +++ b/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs @@ -1,11 +1,11 @@ using System.Threading.Tasks; -using AElf.Standards.ACS4; using AElf.Contracts.Consensus.AEDPoS; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus.Application; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; using AElf.Modularity; +using AElf.Standards.ACS4; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -13,144 +13,143 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +[DependsOn( + typeof(CoreConsensusAElfModule), + typeof(SmartContractAElfModule), + typeof(KernelCoreWithChainTestAElfModule) +)] +public class ConsensusTestAElfModule : AElfModule { - [DependsOn( - typeof(CoreConsensusAElfModule), - typeof(SmartContractAElfModule), - typeof(KernelCoreWithChainTestAElfModule) - )] - public class ConsensusTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + + services.AddSingleton(); + + services.AddSingleton(); + services.AddSingleton(); + + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetTriggerInformationForConsensusCommand(It.IsAny())) + .Returns(new BytesValue()); + mockService.Setup(m => m.GetTriggerInformationForBlockHeaderExtraData(It.IsAny())) + .Returns(new BytesValue()); + mockService.Setup(m => m.GetTriggerInformationForConsensusTransactions(It.IsAny())) + .Returns(new BytesValue()); + + return mockService.Object; + }); + + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(SampleAddress.AddressList[0])); + + return mockService.Object; + }); + + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.ExtractConsensusExtraData(It.Is(o => o.Height == 9))) + .Returns(ByteString.Empty); + mockService.Setup(m => m.ExtractConsensusExtraData(It.Is(o => o.Height != 9))) + .Returns(ByteString.CopyFromUtf8("test")); + return mockService.Object; + }); + + //mock consensus service transaction execution result + services.AddTransient(provider => { - var services = context.Services; - - services.AddSingleton(); - - services.AddSingleton(); - services.AddSingleton(); - - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetTriggerInformationForConsensusCommand(It.IsAny())) - .Returns(new BytesValue()); - mockService.Setup(m => m.GetTriggerInformationForBlockHeaderExtraData(It.IsAny())) - .Returns(new BytesValue()); - mockService.Setup(m => m.GetTriggerInformationForConsensusTransactions(It.IsAny())) - .Returns(new BytesValue()); - - return mockService.Object; - }); - - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetAddressByContractNameAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(SampleAddress.AddressList[0])); - - return mockService.Object; - }); - - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.ExtractConsensusExtraData(It.Is(o => o.Height == 9))) - .Returns(ByteString.Empty); - mockService.Setup(m => m.ExtractConsensusExtraData(It.Is(o => o.Height != 9))) - .Returns(ByteString.CopyFromUtf8("test")); - return mockService.Object; - }); - - //mock consensus service transaction execution result - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => tx.MethodName == "GetConsensusCommand"), It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => tx.MethodName == "GetConsensusCommand"), It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new ConsensusCommand { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new ConsensusCommand - { - ArrangedMiningTime = TimestampHelper.GetUtcNow(), - Hint = new AElfConsensusHint {Behaviour = AElfConsensusBehaviour.Nothing}.ToByteString(), - LimitMillisecondsOfMiningBlock = 400 - }.ToByteArray()) - })); - - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => - tx.MethodName.Contains("ValidateConsensus") && tx.Params == ByteString.Empty), - It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + ArrangedMiningTime = TimestampHelper.GetUtcNow(), + Hint = new AElfConsensusHint { Behaviour = AElfConsensusBehaviour.Nothing }.ToByteString(), + LimitMillisecondsOfMiningBlock = 400 + }.ToByteArray()) + })); + + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => + tx.MethodName.Contains("ValidateConsensus") && tx.Params == ByteString.Empty), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new ValidationResult { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new ValidationResult - { - Success = false, - Message = "Parameter is not valid" - }.ToByteArray()) - })); - - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => - tx.MethodName.Contains("ValidateConsensus") && tx.Params != ByteString.Empty), - It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + Success = false, + Message = "Parameter is not valid" + }.ToByteArray()) + })); + + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => + tx.MethodName.Contains("ValidateConsensus") && tx.Params != ByteString.Empty), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new ValidationResult { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new ValidationResult - { - Success = true, - Message = "Validate success" - }.ToByteArray()) - })); - - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => tx.MethodName == "GetConsensusExtraData"), - It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + Success = true, + Message = "Validate success" + }.ToByteArray()) + })); + + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => tx.MethodName == "GetConsensusExtraData"), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new AElfConsensusHeaderInformation { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new AElfConsensusHeaderInformation - { - Behaviour = AElfConsensusBehaviour.Nothing, - Round = new Round() - }.ToBytesValue().ToByteArray()) - })); - - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.Is(tx => tx.MethodName == "GenerateConsensusTransactions"), - It.IsAny())) - .Returns(Task.FromResult(new TransactionTrace + Behaviour = AElfConsensusBehaviour.Nothing, + Round = new Round() + }.ToBytesValue().ToByteArray()) + })); + + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => tx.MethodName == "GenerateConsensusTransactions"), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = ByteString.CopyFrom(new TransactionList { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = ByteString.CopyFrom(new TransactionList + Transactions = { - Transactions = + new Transaction { - new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[1], - MethodName = "NextTerm", - Params = ByteString.Empty - } + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[1], + MethodName = "NextTerm", + Params = ByteString.Empty } - }.ToByteArray()) - })); + } + }.ToByteArray()) + })); - return mockService.Object; - }); + return mockService.Object; + }); - services.AddTransient(); - } + services.AddTransient(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/ConsensusTestBase.cs b/test/AElf.Kernel.Consensus.Tests/ConsensusTestBase.cs index 95a655799b..3b0513d6bb 100644 --- a/test/AElf.Kernel.Consensus.Tests/ConsensusTestBase.cs +++ b/test/AElf.Kernel.Consensus.Tests/ConsensusTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public class ConsensusTestBase : AElfIntegratedTest { - public class ConsensusTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/ConsensusTestHelper.cs b/test/AElf.Kernel.Consensus.Tests/ConsensusTestHelper.cs index 0758d6477d..f8279d4f6b 100644 --- a/test/AElf.Kernel.Consensus.Tests/ConsensusTestHelper.cs +++ b/test/AElf.Kernel.Consensus.Tests/ConsensusTestHelper.cs @@ -1,12 +1,11 @@ -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +public class ConsensusTestHelper : IConsensusTestHelper { - public class ConsensusTestHelper : IConsensusTestHelper - { - public bool IsConsensusSchedulerFilled { get; set; } - } + public bool IsConsensusSchedulerFilled { get; set; } +} - public interface IConsensusTestHelper - { - bool IsConsensusSchedulerFilled { get; set; } - } +public interface IConsensusTestHelper +{ + bool IsConsensusSchedulerFilled { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Consensus.Tests/MockConsensusScheduler.cs b/test/AElf.Kernel.Consensus.Tests/MockConsensusScheduler.cs index e9282f1878..34625ec85e 100644 --- a/test/AElf.Kernel.Consensus.Tests/MockConsensusScheduler.cs +++ b/test/AElf.Kernel.Consensus.Tests/MockConsensusScheduler.cs @@ -1,27 +1,26 @@ using AElf.Kernel.Consensus.Application; -namespace AElf.Kernel.Consensus +namespace AElf.Kernel.Consensus; + +/// +/// Mock this for testing method TriggerConsensusAsync in ConsensusService. +/// +public class MockConsensusScheduler : IConsensusScheduler { - /// - /// Mock this for testing method TriggerConsensusAsync in ConsensusService. - /// - public class MockConsensusScheduler : IConsensusScheduler - { - private readonly IConsensusTestHelper _consensusTestHelper; + private readonly IConsensusTestHelper _consensusTestHelper; - public MockConsensusScheduler(IConsensusTestHelper consensusTestHelper) - { - _consensusTestHelper = consensusTestHelper; - } + public MockConsensusScheduler(IConsensusTestHelper consensusTestHelper) + { + _consensusTestHelper = consensusTestHelper; + } - public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) - { - _consensusTestHelper.IsConsensusSchedulerFilled = true; - } + public void NewEvent(long countingMilliseconds, ConsensusRequestMiningEventData consensusRequestMiningEventData) + { + _consensusTestHelper.IsConsensusSchedulerFilled = true; + } - public void CancelCurrentEvent() - { - _consensusTestHelper.IsConsensusSchedulerFilled = false; - } + public void CancelCurrentEvent() + { + _consensusTestHelper.IsConsensusSchedulerFilled = false; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/AElf.Kernel.Core.Tests.csproj b/test/AElf.Kernel.Core.Tests/AElf.Kernel.Core.Tests.csproj index cca48ecec8..fd580402ab 100644 --- a/test/AElf.Kernel.Core.Tests/AElf.Kernel.Core.Tests.csproj +++ b/test/AElf.Kernel.Core.Tests/AElf.Kernel.Core.Tests.csproj @@ -6,15 +6,15 @@ false - - - - - - + + + + + + - - + + diff --git a/test/AElf.Kernel.Core.Tests/AElfKernelTestBase.cs b/test/AElf.Kernel.Core.Tests/AElfKernelTestBase.cs index 0c74a07f49..ef7c54c508 100644 --- a/test/AElf.Kernel.Core.Tests/AElfKernelTestBase.cs +++ b/test/AElf.Kernel.Core.Tests/AElfKernelTestBase.cs @@ -1,29 +1,31 @@ using System.Collections.Generic; -using AElf.Kernel.SmartContract; using AElf.TestBase; -using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class AElfKernelTestBase : AElfIntegratedTest { - public class AElfKernelTestBase : AElfIntegratedTest - { - protected string GetBlockExecutedDataKey(IMessage key = null) - { - var list = new List {KernelConstants.BlockExecutedDataKey, typeof(T).Name}; - if (key != null) list.Add(key.ToString()); - return string.Join("/", list); - } - } - - public class AElfKernelWithChainTestBase : AElfIntegratedTest - { - } - - public class AElfMinerTestBase : AElfIntegratedTest - { - } - - public class AccountTestBase : AElfIntegratedTest + protected const string AElfBlockchainModule = nameof(AElfBlockchainModule); + + protected static string GetBlockExecutedDataKey(IMessage key = null) { + var list = new List { KernelConstants.BlockExecutedDataKey, typeof(T).Name }; + if (key != null) list.Add(key.ToString()); + return string.Join("/", list); } +} + +public class AElfKernelWithChainTestBase : AElfIntegratedTest +{ + protected const string AElfBlockchainModule = nameof(AElfBlockchainModule); +} + +public class AElfMinerTestBase : AElfIntegratedTest +{ + protected const string AElfMinerModule = nameof(AElfMinerModule); +} + +public class AccountTestBase : AElfIntegratedTest +{ + protected const string AElfAccountModule = nameof(AElfAccountModule); } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs index a4725736ca..204efef405 100644 --- a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs @@ -1,69 +1,62 @@ -using System.Threading.Tasks; using AElf.Cryptography; using AElf.Cryptography.ECDSA; using AElf.Kernel.Account.Infrastructure; -using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Account.Application +namespace AElf.Kernel.Account.Application; + +[Trait("Category", AElfAccountModule)] +public sealed class AccountServiceTests : AccountTestBase { - public class AccountServiceTests : AccountTestBase + private readonly IAccountService _accountService; + private readonly ECKeyPair _ecKeyPair; + + public AccountServiceTests() { - private readonly IAccountService _accountService; - private readonly IAElfAsymmetricCipherKeyPairProvider _aelfAsymmetricCipherKeyPairProvider; - private readonly ECKeyPair _ecKeyPair; + _accountService = GetRequiredService(); + _ecKeyPair = CryptoHelper.GenerateKeyPair(); + var aelfAsymmetricCipherKeyPairProvider = GetRequiredService(); + aelfAsymmetricCipherKeyPairProvider.SetKeyPair(_ecKeyPair); + } - public AccountServiceTests() - { - _accountService = GetRequiredService(); - _aelfAsymmetricCipherKeyPairProvider = GetRequiredService(); - _ecKeyPair = CryptoHelper.GenerateKeyPair(); - _aelfAsymmetricCipherKeyPairProvider.SetKeyPair(_ecKeyPair); - } - - [Fact] - public async Task GetPublicKey_Test() - { - var publicKey = await _accountService.GetPublicKeyAsync(); - Assert.Equal(publicKey,_ecKeyPair.PublicKey); - } + [Fact] + public async Task GetPublicKey_Test() + { + var publicKey = await _accountService.GetPublicKeyAsync(); + publicKey.ShouldBe(_ecKeyPair.PrivateKey); + } - [Fact] - public async Task GetAccount_Test() - { - var account = await _accountService.GetAccountAsync(); - account.ShouldBe(Address.FromPublicKey(_ecKeyPair.PublicKey)); - } + [Fact] + public async Task GetAccount_Test() + { + var address = await _accountService.GetAccountAsync(); + address.ShouldBe(Address.FromPublicKey(_ecKeyPair.PublicKey)); + } - [Fact] - public async Task Sign_Test() - { - var data = HashHelper.ComputeFrom("test").ToByteArray(); - var signature = await _accountService.SignAsync(data); + [Fact] + public async Task Sign_Test() + { + var data = HashHelper.ComputeFrom("test").ToByteArray(); + var signature = await _accountService.SignAsync(data); - var recoverResult = CryptoHelper.RecoverPublicKey(signature, data, out var recoverPublicKey); - var verifyResult = recoverResult && _ecKeyPair.PublicKey.BytesEqual(recoverPublicKey); - verifyResult.ShouldBeTrue(); - } + var recoverResult = CryptoHelper.RecoverPublicKey(signature, data, out var recoverPublicKey); + var verifyResult = recoverResult && _ecKeyPair.PublicKey.BytesEqual(recoverPublicKey); + verifyResult.ShouldBeTrue(); + } - [Fact] - public async Task EncryptAndDecryptMessage_Test() + [Fact] + public async Task EncryptAndDecryptMessage_Test() + { + var stringValue = new StringValue { - var stringValue = new StringValue - { - Value = "EncryptAndDecryptMessage" - }; - var pubicKey = await _accountService.GetPublicKeyAsync(); - var plainMessage = stringValue.ToByteArray(); - - var encryptMessage = await _accountService.EncryptMessageAsync(pubicKey, plainMessage); - var decryptMessage = await _accountService.DecryptMessageAsync(pubicKey, encryptMessage); + Value = "EncryptAndDecryptMessage" + }; + var pubicKey = await _accountService.GetPublicKeyAsync(); + var plainMessage = stringValue.ToByteArray(); - decryptMessage.ShouldBe(plainMessage); - } + var encryptMessage = await _accountService.EncryptMessageAsync(pubicKey, plainMessage); + var decryptMessage = await _accountService.DecryptMessageAsync(pubicKey, encryptMessage); + decryptMessage.ShouldBe(plainMessage); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/AccountTestAElfModule.cs b/test/AElf.Kernel.Core.Tests/AccountTestAElfModule.cs new file mode 100644 index 0000000000..63a0a0bb07 --- /dev/null +++ b/test/AElf.Kernel.Core.Tests/AccountTestAElfModule.cs @@ -0,0 +1,17 @@ +using AElf.Kernel.Account.Application; +using AElf.Modularity; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace AElf.Kernel; + +[DependsOn( + typeof(KernelCoreTestAElfModule))] +public class AccountTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var services = context.Services; + services.AddSingleton(); + } +} \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockExtraDataServiceTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockExtraDataServiceTests.cs index 7c5a5d6b3a..63e451ca36 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockExtraDataServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockExtraDataServiceTests.cs @@ -1,53 +1,49 @@ using System.Linq; -using System.Threading.Tasks; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfMinerModule)] +public sealed class BlockExtraDataServiceTests : AElfMinerTestBase { - public class BlockExtraDataServiceTests: AElfMinerTestBase + private readonly IBlockExtraDataService _blockExtraDataService; + + public BlockExtraDataServiceTests() { - private readonly IBlockExtraDataService _blockExtraDataService; + _blockExtraDataService = GetRequiredService(); + } - public BlockExtraDataServiceTests() + [Fact] + public void GetBlockExtraData_Test() + { + var blockHeader = new BlockHeader { - _blockExtraDataService = GetRequiredService(); - } + Height = 1, // no extra data in genesis block + ExtraData = { { "ExtraDataKey", ByteString.CopyFromUtf8("test1") } } + }; - [Fact] - public void GetBlockExtraData_Test() - { - var blockHeader = new BlockHeader() - { - Height = 1, // no extra data in genesis block - ExtraData = { {"ExtraDataKey", ByteString.CopyFromUtf8("test1")} } - }; - - var queryResult = _blockExtraDataService.GetExtraDataFromBlockHeader("ExtraDataKey", blockHeader); - queryResult.ShouldBeNull(); - - blockHeader.Height = 2; - queryResult = _blockExtraDataService.GetExtraDataFromBlockHeader("ExtraDataKey", blockHeader); - queryResult.ShouldBe(blockHeader.ExtraData.First().Value); - - var queryResult1 = _blockExtraDataService.GetExtraDataFromBlockHeader("NotExistExtraDataKey", blockHeader); - queryResult1.ShouldBeNull(); - } - - [Fact] - public async Task FillBlockExtraData_Test() + var queryResult = _blockExtraDataService.GetExtraDataFromBlockHeader("ExtraDataKey", blockHeader); + queryResult.ShouldBeNull(); + + blockHeader.Height = 2; + queryResult = _blockExtraDataService.GetExtraDataFromBlockHeader("ExtraDataKey", blockHeader); + queryResult.ShouldBe(blockHeader.ExtraData.First().Value); + + var queryResult1 = _blockExtraDataService.GetExtraDataFromBlockHeader("NotExistExtraDataKey", blockHeader); + queryResult1.ShouldBeNull(); + } + + [Fact] + public async Task FillBlockExtraData_Test() + { + var blockHeader = new BlockHeader { - var blockHeader = new BlockHeader() - { - Height = 100, - }; - await _blockExtraDataService.FillBlockExtraDataAsync(blockHeader); - blockHeader.ExtraData.Count.ShouldBe(0); - - blockHeader.Height = 1; - await _blockExtraDataService.FillBlockExtraDataAsync(blockHeader); - blockHeader.ExtraData.Count.ShouldBe(1); - } + Height = 100 + }; + await _blockExtraDataService.FillBlockExtraDataAsync(blockHeader); + blockHeader.ExtraData.Count.ShouldBe(0); + + blockHeader.Height = 1; + await _blockExtraDataService.FillBlockExtraDataAsync(blockHeader); + blockHeader.ExtraData.Count.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockGenerationServiceTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockGenerationServiceTests.cs index 69eadd04b1..29b505a30f 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockGenerationServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockGenerationServiceTests.cs @@ -1,43 +1,36 @@ -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; -using AElf.Types; -using Google.Protobuf.WellKnownTypes; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfMinerModule)] +public sealed class BlockGenerationServiceTests : AElfMinerTestBase { - public class BlockGenerationServiceTests : AElfMinerTestBase - { - private readonly BlockGenerationService _blockGenerationService; + private readonly BlockGenerationService _blockGenerationService; - private readonly IBlockchainService _blockchainService; - private readonly IStaticChainInformationProvider _staticChainInformationProvider; + private readonly IStaticChainInformationProvider _staticChainInformationProvider; - public BlockGenerationServiceTests() - { - _blockchainService = GetRequiredService(); - _blockGenerationService = GetRequiredService(); - _staticChainInformationProvider = GetRequiredService(); - } + public BlockGenerationServiceTests() + { + _blockGenerationService = GetRequiredService(); + _staticChainInformationProvider = GetRequiredService(); + } - [Fact] - public async Task Generate_Block_Success() + [Fact] + public async Task Generate_Block_Success() + { + var generateBlockDto = new GenerateBlockDto { - var generateBlockDto = new GenerateBlockDto - { - PreviousBlockHash = Hash.Empty, - PreviousBlockHeight = 1 - }; - - var block = await _blockGenerationService.GenerateBlockBeforeExecutionAsync(generateBlockDto); - - block.Header.ChainId.ShouldBe(_staticChainInformationProvider.ChainId); - block.Header.Height.ShouldBe(generateBlockDto.PreviousBlockHeight + 1); - block.Header.PreviousBlockHash.ShouldBe(generateBlockDto.PreviousBlockHash); - block.Header.Time.ShouldBe(generateBlockDto.BlockTime); - block.Header.ExtraData.Count.ShouldBe(1); - } + PreviousBlockHash = Hash.Empty, + PreviousBlockHeight = 1 + }; + + var block = await _blockGenerationService.GenerateBlockBeforeExecutionAsync(generateBlockDto); + + block.Header.ChainId.ShouldBe(_staticChainInformationProvider.ChainId); + block.Header.Height.ShouldBe(generateBlockDto.PreviousBlockHeight + 1); + block.Header.PreviousBlockHash.ShouldBe(generateBlockDto.PreviousBlockHash); + block.Header.Time.ShouldBe(generateBlockDto.BlockTime); + block.Header.ExtraData.Count.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockValidationProviderTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockValidationProviderTests.cs index 3ecba2fd73..8e4d5b0218 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockValidationProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/BlockValidationProviderTests.cs @@ -1,229 +1,222 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Cryptography; using AElf.Kernel.Miner.Application; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockValidationProviderTests : AElfKernelWithChainTestBase { - public sealed class BlockValidationProviderTests : AElfKernelWithChainTestBase + private readonly BlockValidationProvider _blockValidationProvider; + private readonly IBlockValidationService _blockValidationService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + + public BlockValidationProviderTests() { - private readonly BlockValidationProvider _blockValidationProvider; - private readonly IBlockValidationService _blockValidationService; - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + _blockValidationService = GetRequiredService(); + _blockValidationProvider = GetRequiredService(); + _transactionBlockIndexService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _systemTransactionExtraDataProvider = GetRequiredService(); + } - public BlockValidationProviderTests() - { - _blockValidationService = GetRequiredService(); - _blockValidationProvider = GetRequiredService(); - _transactionBlockIndexService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _systemTransactionExtraDataProvider = GetRequiredService(); - } - - [Fact] - public async Task Test_Validate_Block_Before_Execute() - { - Block block = null; - bool validateResult; + [Fact] + public async Task Test_Validate_Block_Before_Execute() + { + var validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(null); + validateResult.ShouldBeFalse(); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeFalse(); + var block = new Block(); + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeFalse(); - block = new Block(); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeFalse(); + block.Header = new BlockHeader(); + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeFalse(); - block.Header = new BlockHeader(); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeFalse(); + block.Body = new BlockBody(); + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeFalse(); - block.Body = new BlockBody(); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeFalse(); + block.Body.TransactionIds.Add(Hash.Empty); + block.Header = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")).Header; - block.Body.TransactionIds.Add(Hash.Empty); - block.Header = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")).Header; + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeTrue(); + } - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeTrue(); - } + [Fact] + public async Task Test_Validate_Block_After_Execute() + { + var validateResult = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(null); + validateResult.ShouldBeTrue(); + } - [Fact] - public async Task Test_Validate_Block_After_Execute() - { - var validateResult = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(null); - validateResult.ShouldBeTrue(); - } + [Fact] + public async Task Test_Validate_Before_Attach() + { + var validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(null); + validateResult.ShouldBeFalse(); + + var block = new Block(); + + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header = new BlockHeader(); + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Body = new BlockBody(); + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Body.TransactionIds.Add(Hash.Empty); + block.Header.ChainId = 1234; + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header.ChainId = 0; + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header.Height = AElfConstants.GenesisBlockHeight; + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")).Header; + block.Header.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + block.GetHash().ToByteArray())); + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); + block.Header.Time = TimestampHelper.GetUtcNow() + TimestampHelper.DurationFromMinutes(30); + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Header.Time = TimestampHelper.GetUtcNow(); + validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeTrue(); + } - [Fact] - public async Task Test_Validate_Before_Attach() - { - Block block = null; - bool validateResult; - - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block = new Block(); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header = new BlockHeader(); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Body = new BlockBody(); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Body.TransactionIds.Add(Hash.Empty); - block.Header.ChainId = 1234; - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header.ChainId = 0; - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header.Height = AElfConstants.GenesisBlockHeight; - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")).Header; - block.Header.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - block.GetHash().ToByteArray())); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); - block.Header.Time = TimestampHelper.GetUtcNow() + TimestampHelper.DurationFromMinutes(30); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Header.Time = TimestampHelper.GetUtcNow(); - validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeTrue(); - } - - [Fact] - public async Task ValidateBlockBeforeAttachAsync_Test() - { - var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")); - var validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - block.Body.TransactionIds.Add(Hash.Empty); - block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); - block.Header.ChainId = 0; - - block.Header.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - block.GetHash().ToByteArray())); - - validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - - _systemTransactionExtraDataProvider.SetSystemTransactionCount(1,block.Header); - block.Header.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - block.GetHash().ToByteArray())); - validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); - validateResult.ShouldBeTrue(); - - } - - [Fact] - public async Task ValidateBeforeAttach_DuplicatesTransactions_ReturnFalse() - { - var transaction = _kernelTestHelper.GenerateTransaction(); - var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash"), - new List {transaction, transaction}); + [Fact] + public async Task ValidateBlockBeforeAttachAsync_Test() + { + var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")); + var validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + block.Body.TransactionIds.Add(Hash.Empty); + block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); + block.Header.ChainId = 0; + + block.Header.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + block.GetHash().ToByteArray())); + + validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + + _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, block.Header); + block.Header.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + block.GetHash().ToByteArray())); + validateResult = await _blockValidationService.ValidateBlockBeforeAttachAsync(block); + validateResult.ShouldBeTrue(); + } - block.Header.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - block.GetHash().ToByteArray())); + [Fact] + public async Task ValidateBeforeAttach_DuplicatesTransactions_ReturnFalse() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + var block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash"), + new List { transaction, transaction }); - var validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - } + block.Header.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + block.GetHash().ToByteArray())); - [Fact] - public async Task ValidateBlockBeforeExecute_Repackaged_ReturnFalse() + var validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + } + + [Fact] + public async Task ValidateBlockBeforeExecute_Repackaged_ReturnFalse() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + var block = await _kernelTestHelper.AttachBlockToBestChain(new List { - var transaction = _kernelTestHelper.GenerateTransaction(); - var block = await _kernelTestHelper.AttachBlockToBestChain(new List + transaction + }); + await _transactionBlockIndexService.AddBlockIndexAsync(new List { transaction.GetHash() }, + new BlockIndex { - transaction + BlockHash = block.GetHash(), + BlockHeight = block.Height }); - await _transactionBlockIndexService.AddBlockIndexAsync(new List {transaction.GetHash()}, - new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - var validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeTrue(); + var validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeTrue(); - var repackagedBlock = await _kernelTestHelper.AttachBlockToBestChain(new List - { - transaction - }); + var repackagedBlock = await _kernelTestHelper.AttachBlockToBestChain(new List + { + transaction + }); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(repackagedBlock); - validateResult.ShouldBeFalse(); - } + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(repackagedBlock); + validateResult.ShouldBeFalse(); + } - [Fact] - public async Task ValidateBlockBeforeExecute_RepackagedInDifferentBranch_ReturnTrue() - { - var transaction = _kernelTestHelper.GenerateTransaction(); - var forkBranchBlock = _kernelTestHelper.ForkBranchBlockList.Last(); - var block = await _kernelTestHelper.AttachBlock(forkBranchBlock.Height, forkBranchBlock.GetHash(), - new List - { - transaction - }); - await _transactionBlockIndexService.AddBlockIndexAsync(new List {transaction.GetHash()}, - new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - - var validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeTrue(); - - var repackagedBlock = await _kernelTestHelper.AttachBlockToBestChain(new List + [Fact] + public async Task ValidateBlockBeforeExecute_RepackagedInDifferentBranch_ReturnTrue() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + var forkBranchBlock = _kernelTestHelper.ForkBranchBlockList.Last(); + var block = await _kernelTestHelper.AttachBlock(forkBranchBlock.Height, forkBranchBlock.GetHash(), + new List { transaction }); + await _transactionBlockIndexService.AddBlockIndexAsync(new List { transaction.GetHash() }, + new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); - validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(repackagedBlock); - validateResult.ShouldBeTrue(); - } + var validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeTrue(); - [Fact] - public void ExceptionTest() + var repackagedBlock = await _kernelTestHelper.AttachBlockToBestChain(new List { - var message = "message"; - var exception = new Exception(); - Should.Throw(() => throw new BlockValidationException()); - Should.Throw(() => throw new BlockValidationException(message)); - Should.Throw(() => throw new BlockValidationException(message, exception)); - Should.Throw(() => throw new ValidateNextTimeBlockValidationException()); - Should.Throw(() => throw new ValidateNextTimeBlockValidationException(message)); - Should.Throw(() => throw new ValidateNextTimeBlockValidationException(message, exception)); - Should.Throw(() => throw new ValidateNextTimeBlockValidationException(Hash.Empty)); - } + transaction + }); + + validateResult = await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(repackagedBlock); + validateResult.ShouldBeTrue(); + } + + [Fact] + public void ExceptionTest() + { + const string message = "message"; + var exception = new Exception(); + Should.Throw(() => throw new BlockValidationException()); + Should.Throw(() => throw new BlockValidationException(message)); + Should.Throw(() => throw new BlockValidationException(message, exception)); + Should.Throw(() => + throw new ValidateNextTimeBlockValidationException()); + Should.Throw(() => + throw new ValidateNextTimeBlockValidationException(message)); + Should.Throw(() => + throw new ValidateNextTimeBlockValidationException(message, exception)); + Should.Throw(() => + throw new ValidateNextTimeBlockValidationException(Hash.Empty)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceCreateChainTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceCreateChainTests.cs index 76ca0777c3..b61a47e39c 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceCreateChainTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceCreateChainTests.cs @@ -1,54 +1,49 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; -using AElf.Types; -using Google.Protobuf.WellKnownTypes; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class FullBlockchainServiceCreateChainTests : AElfKernelTestBase { - public class FullBlockchainServiceCreateChainTests: AElfKernelTestBase + private readonly FullBlockchainService _fullBlockchainService; + private readonly KernelTestHelper _kernelTestHelper; + + public FullBlockchainServiceCreateChainTests() { - private readonly FullBlockchainService _fullBlockchainService; - private readonly KernelTestHelper _kernelTestHelper; + _fullBlockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public FullBlockchainServiceCreateChainTests() - { - _fullBlockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } - - [Fact] - public async Task Create_Chain_Success() + [Fact] + public async Task Create_Chain_Success() + { + var transactions = new List { - var transactions = new List - { - _kernelTestHelper.GenerateTransaction(), - _kernelTestHelper.GenerateTransaction() - }; - - var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); - - var chain = await _fullBlockchainService.GetChainAsync(); - chain.ShouldBeNull(); - - var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); - existBlock.ShouldBeNull(); - - var createChainResult = await _fullBlockchainService.CreateChainAsync(block, transactions); - - chain = await _fullBlockchainService.GetChainAsync(); - chain.ShouldNotBeNull(); - chain.ShouldBe(createChainResult); - - existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); - existBlock.GetHash().ShouldBe(block.GetHash()); - - var existTransactions = await _fullBlockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash())); - existTransactions.ShouldContain(transactions[0]); - existTransactions.ShouldContain(transactions[1]); - } + _kernelTestHelper.GenerateTransaction(), + _kernelTestHelper.GenerateTransaction() + }; + + var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); + + var chain = await _fullBlockchainService.GetChainAsync(); + chain.ShouldBeNull(); + + var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); + existBlock.ShouldBeNull(); + + var createChainResult = await _fullBlockchainService.CreateChainAsync(block, transactions); + + chain = await _fullBlockchainService.GetChainAsync(); + chain.ShouldNotBeNull(); + chain.ShouldBe(createChainResult); + + existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); + existBlock.GetHash().ShouldBe(block.GetHash()); + + var existTransactions = + await _fullBlockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash())); + existTransactions.ShouldContain(transactions[0]); + existTransactions.ShouldContain(transactions[1]); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceTests.cs index 241fadc54f..2a6f37970f 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/FullBlockchainServiceTests.cs @@ -1,800 +1,790 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Shouldly; -using Shouldly.ShouldlyExtensionMethods; using Volo.Abp.EventBus.Local; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfBlockchainModule)] +public class FullBlockchainServiceTests : AElfKernelWithChainTestBase { - public class FullBlockchainServiceTests : AElfKernelWithChainTestBase + private readonly IChainManager _chainManager; + private readonly ILocalEventBus _eventBus; + private readonly FullBlockchainService _fullBlockchainService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionManager _transactionManager; + + public FullBlockchainServiceTests() { - private readonly FullBlockchainService _fullBlockchainService; - private readonly ITransactionManager _transactionManager; - private readonly IChainManager _chainManager; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ILocalEventBus _eventBus; + _fullBlockchainService = GetRequiredService(); + _transactionManager = GetRequiredService(); + _chainManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _eventBus = GetRequiredService(); + } - public FullBlockchainServiceTests() + [Fact] + public async Task Add_Block_Success() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) { - _fullBlockchainService = GetRequiredService(); - _transactionManager = GetRequiredService(); - _chainManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _eventBus = GetRequiredService(); + var transaction = _kernelTestHelper.GenerateTransaction(); + transactions.Add(transaction); } - [Fact] - public async Task Add_Block_Success() - { - var transactions = new List(); - for (var i = 0; i < 3; i++) - { - var transaction = _kernelTestHelper.GenerateTransaction(); - transactions.Add(transaction); - } + var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); - var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); + var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); + existBlock.ShouldBeNull(); - var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); - existBlock.ShouldBeNull(); + await _fullBlockchainService.AddBlockAsync(block); - await _fullBlockchainService.AddBlockAsync(block); + existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); + existBlock.ShouldBe(block); - existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); - existBlock.ShouldBe(block); + var blockHeader = await _fullBlockchainService.GetBlockHeaderByHashAsync(block.GetHash()); + blockHeader.ShouldBe(block.Header); + } - var blockHeader = await _fullBlockchainService.GetBlockHeaderByHashAsync(block.GetHash()); - blockHeader.ShouldBe(block.Header); - } + [Fact] + public async Task Has_Block_ReturnTrue() + { + var result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.BestBranchBlockList[1].GetHash()); + result.ShouldBeTrue(); - [Fact] - public async Task Has_Block_ReturnTrue() - { - var result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.BestBranchBlockList[1].GetHash()); - result.ShouldBeTrue(); + result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); + result.ShouldBeTrue(); - result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); - result.ShouldBeTrue(); + result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.ForkBranchBlockList[1].GetHash()); + result.ShouldBeTrue(); - result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.ForkBranchBlockList[1].GetHash()); - result.ShouldBeTrue(); + result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.NotLinkedBlockList[1].GetHash()); + result.ShouldBeTrue(); + } - result = await _fullBlockchainService.HasBlockAsync(_kernelTestHelper.NotLinkedBlockList[1].GetHash()); - result.ShouldBeTrue(); - } + [Fact] + public async Task Has_Block_ReturnFalse() + { + var result = await _fullBlockchainService.HasBlockAsync(HashHelper.ComputeFrom("Not Exist Block")); + result.ShouldBeFalse(); + } - [Fact] - public async Task Has_Block_ReturnFalse() - { - var result = await _fullBlockchainService.HasBlockAsync(HashHelper.ComputeFrom("Not Exist Block")); - result.ShouldBeFalse(); - } + [Fact] + public async Task Get_BlockHash_ByHeight_ReturnNull() + { + var chain = await _fullBlockchainService.GetChainAsync(); - [Fact] - public async Task Get_BlockHash_ByHeight_ReturnNull() - { - var chain = await _fullBlockchainService.GetChainAsync(); - - var result = - await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 14, chain.BestChainHash); - result.ShouldBeNull(); - - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 20, chain.LongestChainHash); - result.ShouldBeNull(); - - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 14, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); - result.ShouldBeNull(); - - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 15, - _kernelTestHelper.NotLinkedBlockList.Last().GetHash()); - result.ShouldBeNull(); - - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 8, - _kernelTestHelper.NotLinkedBlockList.Last().GetHash()); - result.ShouldBeNull(); - } + var result = + await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 14, chain.BestChainHash); + result.ShouldBeNull(); - [Fact] - public async Task Get_BlockHash_ByHeight_ReturnHash() - { - var chain = await _fullBlockchainService.GetChainAsync(); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 20, chain.LongestChainHash); + result.ShouldBeNull(); - var result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, - _kernelTestHelper.BestBranchBlockList[8].Height, chain.BestChainHash); - result.ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 14, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); + result.ShouldBeNull(); - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, - _kernelTestHelper.LongestBranchBlockList[3].Height, chain.LongestChainHash); - result.ShouldBe(_kernelTestHelper.LongestBranchBlockList[3].GetHash()); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 15, + _kernelTestHelper.NotLinkedBlockList.Last().GetHash()); + result.ShouldBeNull(); - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, - _kernelTestHelper.ForkBranchBlockList[3].Height, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); - result.ShouldBe(_kernelTestHelper.ForkBranchBlockList[3].GetHash()); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, 8, + _kernelTestHelper.NotLinkedBlockList.Last().GetHash()); + result.ShouldBeNull(); + } - // search irreversible section of the chain - result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, - chain.LastIrreversibleBlockHeight - 1, chain.BestChainHash); - result.ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); - } + [Fact] + public async Task Get_BlockHash_ByHeight_ReturnHash() + { + var chain = await _fullBlockchainService.GetChainAsync(); - [Fact] - public async Task Set_BestChain_Success() - { - BestChainFoundEventData eventData = null; - _eventBus.Subscribe(d => - { - eventData = d; - return Task.CompletedTask; - }); - - var chain = await _fullBlockchainService.GetChainAsync(); + var result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, + _kernelTestHelper.BestBranchBlockList[8].Height, chain.BestChainHash); + result.ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); - chain.BestChainHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().Height); - chain.BestChainHash.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().GetHash()); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, + _kernelTestHelper.LongestBranchBlockList[3].Height, chain.LongestChainHash); + result.ShouldBe(_kernelTestHelper.LongestBranchBlockList[3].GetHash()); - await _fullBlockchainService.SetBestChainAsync(chain, chain.LongestChainHeight, chain.LongestChainHash); + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, + _kernelTestHelper.ForkBranchBlockList[3].Height, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); + result.ShouldBe(_kernelTestHelper.ForkBranchBlockList[3].GetHash()); - chain = await _fullBlockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().Height); - chain.BestChainHash.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().GetHash()); - - eventData.ShouldNotBeNull(); - eventData.BlockHash.ShouldBe(chain.BestChainHash); - eventData.BlockHeight.ShouldBe(chain.BestChainHeight); - } + // search irreversible section of the chain + result = await _fullBlockchainService.GetBlockHashByHeightAsync(chain, + chain.LastIrreversibleBlockHeight - 1, chain.BestChainHash); + result.ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); + } - [Fact] - public async Task Get_GetReservedBlockHashes_ReturnNull() + [Fact] + public async Task Set_BestChain_Success() + { + BestChainFoundEventData eventData = null; + _eventBus.Subscribe(d => { - var chain = await _fullBlockchainService.GetChainAsync(); + eventData = d; + return Task.CompletedTask; + }); - var result = await _fullBlockchainService.GetReversedBlockIndexes(HashHelper.ComputeFrom("not exist"), 1); - result.Count.ShouldBe(0); + var chain = await _fullBlockchainService.GetChainAsync(); - result = await _fullBlockchainService.GetReversedBlockIndexes(chain.GenesisBlockHash, 1); - result.Count.ShouldBe(0); - } + chain.BestChainHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().Height); + chain.BestChainHash.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().GetHash()); - [Fact] - public async Task Get_ReversedBlockHashes_ReturnEmpty() - { - var result = - await _fullBlockchainService.GetReversedBlockIndexes(_kernelTestHelper.BestBranchBlockList[2].GetHash(), - 0); - result.Count.ShouldBe(0); - } + await _fullBlockchainService.SetBestChainAsync(chain, chain.LongestChainHeight, chain.LongestChainHash); - [Fact] - public async Task Get_GetReservedBlockHashes_ReturnHashes() - { - var chain = await _fullBlockchainService.GetChainAsync(); - - var result = - await _fullBlockchainService.GetReversedBlockIndexes(_kernelTestHelper.BestBranchBlockList[5].GetHash(), - 3); - result.Count.ShouldBe(3); - result[0].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); - result[1].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); - result[2].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); - - result = await _fullBlockchainService.GetReversedBlockIndexes( - _kernelTestHelper.BestBranchBlockList[3].GetHash(), 4); - result.Count.ShouldBe(3); - result[0].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); - result[1].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[1].GetHash()); - result[2].BlockHash.ShouldBe(chain.GenesisBlockHash); - } + chain = await _fullBlockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().Height); + chain.BestChainHash.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().GetHash()); - [Fact] - public async Task Get_Blocks_ReturnEmpty() - { - var result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync(HashHelper.ComputeFrom("not exist"), 3); - result.Count.ShouldBe(0); - } + eventData.ShouldNotBeNull(); + eventData.BlockHash.ShouldBe(chain.BestChainHash); + eventData.BlockHeight.ShouldBe(chain.BestChainHeight); + } - [Fact] - public async Task Get_Blocks_ReturnBlocks() - { - var chain = await _fullBlockchainService.GetChainAsync(); - - var result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync(chain.BestChainHash, 3); - result.Count.ShouldBe(0); - - result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( - _kernelTestHelper.BestBranchBlockList[3].GetHash(), 3); - result.Count.ShouldBe(3); - result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); - result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[5].GetHash()); - result[2].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); - - result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( - _kernelTestHelper.BestBranchBlockList[8].GetHash(), 3); - result.Count.ShouldBe(2); - result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); - result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); - - _fullBlockchainService.GetBlocksInBestChainBranchAsync( - _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 3) - .ShouldThrow("wrong branch", typeof(Exception)); - } + [Fact] + public async Task Get_GetReservedBlockHashes_ReturnNull() + { + var chain = await _fullBlockchainService.GetChainAsync(); - [Fact] - public async Task Get_GetBlockHashes_ReturnEmpty() - { - var chain = await _fullBlockchainService.GetChainAsync(); - var notExistHash = HashHelper.ComputeFrom("not exist"); + var result = await _fullBlockchainService.GetReversedBlockIndexes(HashHelper.ComputeFrom("not exist"), 1); + result.Count.ShouldBe(0); - var result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, chain.BestChainHash); - result.Count.ShouldBe(0); + result = await _fullBlockchainService.GetReversedBlockIndexes(chain.GenesisBlockHash, 1); + result.Count.ShouldBe(0); + } - result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, chain.LongestChainHash); - result.Count.ShouldBe(0); + [Fact] + public async Task Get_ReversedBlockHashes_ReturnEmpty() + { + var result = + await _fullBlockchainService.GetReversedBlockIndexes(_kernelTestHelper.BestBranchBlockList[2].GetHash(), + 0); + result.Count.ShouldBe(0); + } - result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); - result.Count.ShouldBe(0); + [Fact] + public async Task Get_GetReservedBlockHashes_ReturnHashes() + { + var chain = await _fullBlockchainService.GetChainAsync(); + + var result = + await _fullBlockchainService.GetReversedBlockIndexes(_kernelTestHelper.BestBranchBlockList[5].GetHash(), + 3); + result.Count.ShouldBe(3); + result[0].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); + result[1].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); + result[2].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); + + result = await _fullBlockchainService.GetReversedBlockIndexes( + _kernelTestHelper.BestBranchBlockList[3].GetHash(), 4); + result.Count.ShouldBe(3); + result[0].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); + result[1].BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[1].GetHash()); + result[2].BlockHash.ShouldBe(chain.GenesisBlockHash); + } - await _fullBlockchainService.GetBlockHashesAsync(chain, chain.BestChainHash, 10, chain.BestChainHash) - .ContinueWith(p => p.Result.Count.ShouldBe(0)); + [Fact] + public async Task Get_Blocks_ReturnEmpty() + { + var result = + await _fullBlockchainService.GetBlocksInBestChainBranchAsync(HashHelper.ComputeFrom("not exist"), 3); + result.Count.ShouldBe(0); + } - await _fullBlockchainService.GetBlockHashesAsync(chain, chain.LongestChainHash, 10, chain.LongestChainHash) - .ContinueWith(p => p.Result.Count.ShouldBe(0)); + [Fact] + public async Task Get_Blocks_ReturnBlocks() + { + var chain = await _fullBlockchainService.GetChainAsync(); + + var result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync(chain.BestChainHash, 3); + result.Count.ShouldBe(0); + + result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( + _kernelTestHelper.BestBranchBlockList[3].GetHash(), 3); + result.Count.ShouldBe(3); + result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); + result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[5].GetHash()); + result[2].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); + + result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( + _kernelTestHelper.BestBranchBlockList[8].GetHash(), 3); + result.Count.ShouldBe(2); + result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); + result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); + + _fullBlockchainService.GetBlocksInBestChainBranchAsync( + _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 3) + .ShouldThrow("wrong branch", typeof(Exception)); + } - await _fullBlockchainService.GetBlockHashesAsync(chain, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash(), 10, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash()) - .ContinueWith(p => p.Result.Count.ShouldBe(0)); - } + [Fact] + public async Task Get_GetBlockHashes_ReturnEmpty() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var notExistHash = HashHelper.ComputeFrom("not exist"); - [Fact] - public async Task Get_GetBlockHashes_ThrowInvalidOperationException() - { - var chain = await _fullBlockchainService.GetChainAsync(); + var result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, chain.BestChainHash); + result.Count.ShouldBe(0); - await _fullBlockchainService - .GetBlockHashesAsync(chain, _kernelTestHelper.BestBranchBlockList[5].GetHash(), 2, - _kernelTestHelper.NotLinkedBlockList.Last().GetHash()) - .ShouldThrowAsync(); - } - - [Fact] - public async Task GetBlockHashes_WrongBranch_ThrowException() - { - var chain = await _fullBlockchainService.GetChainAsync(); + result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, chain.LongestChainHash); + result.Count.ShouldBe(0); - await _fullBlockchainService - .GetBlockHashesAsync(chain, _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2, - _kernelTestHelper.BestBranchBlockList.Last().GetHash()) - .ShouldThrowAsync(); - } + result = await _fullBlockchainService.GetBlockHashesAsync(chain, notExistHash, 1, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash()); + result.Count.ShouldBe(0); - [Fact] - public async Task Get_GetBlockHashes_ReturnHashes() - { - var chain = await _fullBlockchainService.GetChainAsync(); - - var result = await _fullBlockchainService.GetBlockHashesAsync(chain, - _kernelTestHelper.BestBranchBlockList[1].GetHash(), 3, - _kernelTestHelper.BestBranchBlockList[6].GetHash()); - result.Count.ShouldBe(3); - result[0].ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); - result[1].ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); - result[2].ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); - - result = await _fullBlockchainService.GetBlockHashesAsync(chain, - _kernelTestHelper.BestBranchBlockList[7].GetHash(), 10, - _kernelTestHelper.BestBranchBlockList[9].GetHash()); - result.Count.ShouldBe(2); - result[0].ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); - result[1].ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); - - result = await _fullBlockchainService.GetBlockHashesAsync(chain, - _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2, - _kernelTestHelper.LongestBranchBlockList[3].GetHash()); - result.Count.ShouldBe(2); - result[0].ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); - result[1].ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); - - result = await _fullBlockchainService.GetBlockHashesAsync(chain, - _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 10, - _kernelTestHelper.LongestBranchBlockList[3].GetHash()); - result.Count.ShouldBe(3); - result[0].ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); - result[1].ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); - result[2].ShouldBe(_kernelTestHelper.LongestBranchBlockList[3].GetHash()); - } + await _fullBlockchainService.GetBlockHashesAsync(chain, chain.BestChainHash, 10, chain.BestChainHash) + .ContinueWith(p => p.Result.Count.ShouldBe(0)); - [Fact] - public async Task Get_Block_ByHeight_ReturnBlock() - { - var result = - await _fullBlockchainService.GetBlockByHeightInBestChainBranchAsync( - _kernelTestHelper.BestBranchBlockList[3].Height); - result.ShouldNotBeNull(); - result.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); - } + await _fullBlockchainService.GetBlockHashesAsync(chain, chain.LongestChainHash, 10, chain.LongestChainHash) + .ContinueWith(p => p.Result.Count.ShouldBe(0)); - [Fact] - public async Task Get_Block_ByHeight_ReturnNull() - { - var result = await _fullBlockchainService.GetBlockByHeightInBestChainBranchAsync(15); - result.ShouldBeNull(); - } + await _fullBlockchainService.GetBlockHashesAsync(chain, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash(), 10, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash()) + .ContinueWith(p => p.Result.Count.ShouldBe(0)); + } - [Fact] - public async Task Get_Block_ByHash_ReturnBlock() - { - var transactions = new List(); - for (var i = 0; i < 3; i++) - { - transactions.Add(_kernelTestHelper.GenerateTransaction()); - } + [Fact] + public async Task Get_GetBlockHashes_ThrowInvalidOperationException() + { + var chain = await _fullBlockchainService.GetChainAsync(); - var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); + await _fullBlockchainService + .GetBlockHashesAsync(chain, _kernelTestHelper.BestBranchBlockList[5].GetHash(), 2, + _kernelTestHelper.NotLinkedBlockList.Last().GetHash()) + .ShouldThrowAsync(); + } - await _fullBlockchainService.AddBlockAsync(block); - var result = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); - result.GetHash().ShouldBe(block.GetHash()); - result.Body.TransactionIds[0].ShouldBe(block.Body.TransactionIds[0]); - result.Body.TransactionIds[1].ShouldBe(block.Body.TransactionIds[1]); - result.Body.TransactionIds[2].ShouldBe(block.Body.TransactionIds[2]); - } + [Fact] + public async Task GetBlockHashes_WrongBranch_ThrowException() + { + var chain = await _fullBlockchainService.GetChainAsync(); - [Fact] - public async Task Get_Block_ByHash_ReturnNull() - { - var result = await _fullBlockchainService.GetBlockByHashAsync(HashHelper.ComputeFrom("Not Exist Block")); - result.ShouldBeNull(); - } + await _fullBlockchainService + .GetBlockHashesAsync(chain, _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2, + _kernelTestHelper.BestBranchBlockList.Last().GetHash()) + .ShouldThrowAsync(); + } - [Fact] - public async Task Get_BlockHeaderByHash_ReturnHeader() - { - var blockHeader = - await _fullBlockchainService.GetBlockHeaderByHeightAsync( - _kernelTestHelper.BestBranchBlockList[2].Height); - blockHeader.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); - } + [Fact] + public async Task Get_GetBlockHashes_ReturnHashes() + { + var chain = await _fullBlockchainService.GetChainAsync(); + + var result = await _fullBlockchainService.GetBlockHashesAsync(chain, + _kernelTestHelper.BestBranchBlockList[1].GetHash(), 3, + _kernelTestHelper.BestBranchBlockList[6].GetHash()); + result.Count.ShouldBe(3); + result[0].ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); + result[1].ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); + result[2].ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); + + result = await _fullBlockchainService.GetBlockHashesAsync(chain, + _kernelTestHelper.BestBranchBlockList[7].GetHash(), 10, + _kernelTestHelper.BestBranchBlockList[9].GetHash()); + result.Count.ShouldBe(2); + result[0].ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); + result[1].ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); + + result = await _fullBlockchainService.GetBlockHashesAsync(chain, + _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2, + _kernelTestHelper.LongestBranchBlockList[3].GetHash()); + result.Count.ShouldBe(2); + result[0].ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); + result[1].ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); + + result = await _fullBlockchainService.GetBlockHashesAsync(chain, + _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 10, + _kernelTestHelper.LongestBranchBlockList[3].GetHash()); + result.Count.ShouldBe(3); + result[0].ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); + result[1].ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); + result[2].ShouldBe(_kernelTestHelper.LongestBranchBlockList[3].GetHash()); + } - [Fact] - public async Task Get_Chain_ReturnChain() - { - var chain = await _fullBlockchainService.GetChainAsync(); - chain.ShouldNotBeNull(); - } + [Fact] + public async Task Get_Block_ByHeight_ReturnBlock() + { + var result = + await _fullBlockchainService.GetBlockByHeightInBestChainBranchAsync( + _kernelTestHelper.BestBranchBlockList[3].Height); + result.ShouldNotBeNull(); + result.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[3].GetHash()); + } - [Fact] - public async Task Get_BestChain_ReturnBlockHeader() - { - var chain = await _fullBlockchainService.GetChainAsync(); + [Fact] + public async Task Get_Block_ByHeight_ReturnNull() + { + var result = await _fullBlockchainService.GetBlockByHeightInBestChainBranchAsync(15); + result.ShouldBeNull(); + } - var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, HashHelper.ComputeFrom("New Branch")); + [Fact] + public async Task Get_Block_ByHash_ReturnBlock() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(_kernelTestHelper.GenerateTransaction()); - await _fullBlockchainService.AddBlockAsync(newBlock); - chain = await _fullBlockchainService.GetChainAsync(); - await _fullBlockchainService.AttachBlockToChainAsync(chain, newBlock); + var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); - var result = await _fullBlockchainService.GetBestChainLastBlockHeaderAsync(); - result.Height.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().Height); - result.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().GetHash()); - } + await _fullBlockchainService.AddBlockAsync(block); + var result = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash()); + result.GetHash().ShouldBe(block.GetHash()); + result.Body.TransactionIds[0].ShouldBe(block.Body.TransactionIds[0]); + result.Body.TransactionIds[1].ShouldBe(block.Body.TransactionIds[1]); + result.Body.TransactionIds[2].ShouldBe(block.Body.TransactionIds[2]); + } + + [Fact] + public async Task Get_Block_ByHash_ReturnNull() + { + var result = await _fullBlockchainService.GetBlockByHashAsync(HashHelper.ComputeFrom("Not Exist Block")); + result.ShouldBeNull(); + } - [Fact] - public async Task Get_BlocksInBestChainBranch_ReturnHashes() + [Fact] + public async Task Get_BlockHeaderByHash_ReturnHeader() + { + var blockHeader = + await _fullBlockchainService.GetBlockHeaderByHeightAsync( + _kernelTestHelper.BestBranchBlockList[2].Height); + blockHeader.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); + } + + [Fact] + public async Task Get_Chain_ReturnChain() + { + var chain = await _fullBlockchainService.GetChainAsync(); + chain.ShouldNotBeNull(); + } + + [Fact] + public async Task Get_BestChain_ReturnBlockHeader() + { + var chain = await _fullBlockchainService.GetChainAsync(); + + var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, HashHelper.ComputeFrom("New Branch")); + + await _fullBlockchainService.AddBlockAsync(newBlock); + chain = await _fullBlockchainService.GetChainAsync(); + await _fullBlockchainService.AttachBlockToChainAsync(chain, newBlock); + + var result = await _fullBlockchainService.GetBestChainLastBlockHeaderAsync(); + result.Height.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().Height); + result.GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().GetHash()); + } + + [Fact] + public async Task Get_BlocksInBestChainBranch_ReturnHashes() + { + var result = + await _fullBlockchainService.GetBlocksInBestChainBranchAsync( + _kernelTestHelper.BestBranchBlockList[0].GetHash(), + 2); + result.Count.ShouldBe(2); + result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[1].GetHash()); + result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); + + result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( + _kernelTestHelper.BestBranchBlockList[7].GetHash(), 10); + result.Count.ShouldBe(3); + result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); + result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); + result[2].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); + } + + [Fact] + public async Task Get_BlocksInLongestChainBranchAsync_ReturnHashes() + { + var result = + await _fullBlockchainService.GetBlocksInLongestChainBranchAsync( + _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2); + result.Count.ShouldBe(2); + result[0].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); + result[1].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); + + result = await _fullBlockchainService.GetBlocksInLongestChainBranchAsync( + _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 20); + var count = 10; + result.Count.ShouldBe(count); + for (var i = 0; i < count; i++) + result[i].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[i + 1].GetHash()); + } + + [Fact] + public async Task Set_IrreversibleBlock_Test() + { + NewIrreversibleBlockFoundEvent eventData = null; + _eventBus.Subscribe(d => { - var result = - await _fullBlockchainService.GetBlocksInBestChainBranchAsync( - _kernelTestHelper.BestBranchBlockList[0].GetHash(), - 2); - result.Count.ShouldBe(2); - result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[1].GetHash()); - result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[2].GetHash()); - - result = await _fullBlockchainService.GetBlocksInBestChainBranchAsync( - _kernelTestHelper.BestBranchBlockList[7].GetHash(), 10); - result.Count.ShouldBe(3); - result[0].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[8].GetHash()); - result[1].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[9].GetHash()); - result[2].GetHash().ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); - } + eventData = d; + return Task.CompletedTask; + }); - [Fact] - public async Task Get_BlocksInLongestChainBranchAsync_ReturnHashes() + var chain = await _fullBlockchainService.GetChainAsync(); { - var result = - await _fullBlockchainService.GetBlocksInLongestChainBranchAsync( - _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 2); - result.Count.ShouldBe(2); - result[0].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[1].GetHash()); - result[1].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[2].GetHash()); - - result = await _fullBlockchainService.GetBlocksInLongestChainBranchAsync( - _kernelTestHelper.LongestBranchBlockList[0].GetHash(), 20); - int count = 10; - result.Count.ShouldBe(count); - for (int i = 0; i < count; i++) + // LIB height: 7 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (h)-> l -> m -> n -> o -> p + // Fork Branch: (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v -> w -> x -> y -> z + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[6] + .Height, _kernelTestHelper.BestBranchBlockList[6].GetHash()); + + chain = await _fullBlockchainService.GetChainAsync(); + chain.LastIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); + chain.LastIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); + + eventData.ShouldNotBeNull(); + eventData.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); + eventData.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); + eventData.PreviousIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); + eventData.PreviousIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].Height); + + var blockLink = + await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.BestBranchBlockList[6].GetHash()); + while (blockLink != null) { - result[i].GetHash().ShouldBe(_kernelTestHelper.LongestBranchBlockList[i + 1].GetHash()); + blockLink.IsIrreversibleBlock.ShouldBeTrue(); + var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(blockLink.Height); + chainBlockIndex.BlockHash.ShouldBe(blockLink.BlockHash); + + blockLink = await _chainManager.GetChainBlockLinkAsync(blockLink.PreviousBlockHash); } } - [Fact] - public async Task Set_IrreversibleBlock_Test() { - NewIrreversibleBlockFoundEvent eventData = null; - _eventBus.Subscribe(d => - { - eventData = d; - return Task.CompletedTask; - }); - - var chain = await _fullBlockchainService.GetChainAsync(); - { - // LIB height: 7 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (h)-> l -> m -> n -> o -> p - // Fork Branch: (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v -> w -> x -> y -> z - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[6] - .Height, _kernelTestHelper.BestBranchBlockList[6].GetHash()); - - chain = await _fullBlockchainService.GetChainAsync(); - chain.LastIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); - chain.LastIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); - - eventData.ShouldNotBeNull(); - eventData.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); - eventData.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); - eventData.PreviousIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); - eventData.PreviousIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].Height); - - var blockLink = - await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.BestBranchBlockList[6].GetHash()); - while (blockLink != null) - { - blockLink.IsIrreversibleBlock.ShouldBeTrue(); - var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(blockLink.Height); - chainBlockIndex.BlockHash.ShouldBe(blockLink.BlockHash); - - blockLink = await _chainManager.GetChainBlockLinkAsync(blockLink.PreviousBlockHash); - } - } + // LIB height: 11 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (-) (h)-> l -> m -> n -> o -> p + // Fork Branch: (-) (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v(-) -> w -> x -> y -> z + eventData = null; + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[10] + .Height, _kernelTestHelper.BestBranchBlockList[10].GetHash()); - { - // LIB height: 11 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (-) (h)-> l -> m -> n -> o -> p - // Fork Branch: (-) (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v(-) -> w -> x -> y -> z - eventData = null; - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[10] - .Height, _kernelTestHelper.BestBranchBlockList[10].GetHash()); - - chain = await _fullBlockchainService.GetChainAsync(); - chain.LastIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); - chain.LastIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].Height); - - eventData.ShouldNotBeNull(); - eventData.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); - eventData.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].Height); - eventData.PreviousIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); - eventData.PreviousIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); - - var blockLink = - await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.BestBranchBlockList[10].GetHash()); - while (blockLink != null) - { - blockLink.IsIrreversibleBlock.ShouldBeTrue(); - var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(blockLink.Height); - chainBlockIndex.BlockHash.ShouldBe(blockLink.BlockHash); - - blockLink = await _chainManager.GetChainBlockLinkAsync(blockLink.PreviousBlockHash); - } - } + chain = await _fullBlockchainService.GetChainAsync(); + chain.LastIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); + chain.LastIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].Height); + eventData.ShouldNotBeNull(); + eventData.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].GetHash()); + eventData.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[10].Height); + eventData.PreviousIrreversibleBlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].GetHash()); + eventData.PreviousIrreversibleBlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[6].Height); + + var blockLink = + await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.BestBranchBlockList[10].GetHash()); + while (blockLink != null) { - // Set lib failed - eventData = null; - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[9] - .Height, _kernelTestHelper.BestBranchBlockList[9].GetHash()); - - eventData.ShouldBeNull(); + blockLink.IsIrreversibleBlock.ShouldBeTrue(); + var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(blockLink.Height); + chainBlockIndex.BlockHash.ShouldBe(blockLink.BlockHash); + + blockLink = await _chainManager.GetChainBlockLinkAsync(blockLink.PreviousBlockHash); } } - [Fact] - public async Task Attach_New_Block_To_Chain_Test() { - var chain = await _fullBlockchainService.GetChainAsync(); - var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash, - new List {_kernelTestHelper.GenerateTransaction()}); - await _fullBlockchainService.AddBlockAsync(newBlock); - var status = await _fullBlockchainService.AttachBlockToChainAsync(chain, newBlock); - status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); + // Set lib failed + eventData = null; + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[9] + .Height, _kernelTestHelper.BestBranchBlockList[9].GetHash()); + + eventData.ShouldBeNull(); } - - [Fact] - public async Task Attach_Exist_Block_To_Chain_Test() - { - var chain = await _fullBlockchainService.GetChainAsync(); - var block = _kernelTestHelper.BestBranchBlockList.Last(); - await _fullBlockchainService.AddBlockAsync(block); - var status = await _fullBlockchainService.AttachBlockToChainAsync(chain, block); - status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + } - chain = await _fullBlockchainService.GetChainAsync(); - block = _kernelTestHelper.LongestBranchBlockList.Last(); - await _fullBlockchainService.AddBlockAsync(block); - status = await _fullBlockchainService.AttachBlockToChainAsync(chain, block); - status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); - chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); + [Fact] + public async Task Attach_New_Block_To_Chain_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash, + new List { _kernelTestHelper.GenerateTransaction() }); + await _fullBlockchainService.AddBlockAsync(newBlock); + var status = await _fullBlockchainService.AttachBlockToChainAsync(chain, newBlock); + status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); + } + + [Fact] + public async Task Attach_Exist_Block_To_Chain_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var block = _kernelTestHelper.BestBranchBlockList.Last(); + await _fullBlockchainService.AddBlockAsync(block); + var status = await _fullBlockchainService.AttachBlockToChainAsync(chain, block); + status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + + chain = await _fullBlockchainService.GetChainAsync(); + block = _kernelTestHelper.LongestBranchBlockList.Last(); + await _fullBlockchainService.AddBlockAsync(block); + status = await _fullBlockchainService.AttachBlockToChainAsync(chain, block); + status.ShouldBe(BlockAttachOperationStatus.NewBlockLinked); + chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); + } + + [Fact] + public async Task Get_DiscardedBranch_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + { + // LIB height: 5 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (h)-> l -> m -> n -> o -> p + // Fork Branch: (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v -> w -> x -> y -> z + var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); + + discardedBranch.BranchKeys.Count.ShouldBe(0); + discardedBranch.NotLinkedKeys.Count.ShouldBe(0); } - [Fact] - public async Task Get_DiscardedBranch_Test() { - var chain = await _fullBlockchainService.GetChainAsync(); - { - // LIB height: 5 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (h)-> l -> m -> n -> o -> p - // Fork Branch: (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v -> w -> x -> y -> z - var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - - discardedBranch.BranchKeys.Count.ShouldBe(0); - discardedBranch.NotLinkedKeys.Count.ShouldBe(0); - } - - { - // LIB height: 7 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (h)-> l -> m -> n -> o -> p - // Fork Branch: (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v -> w -> x -> y -> z - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[6] - .Height, _kernelTestHelper.BestBranchBlockList[6].GetHash()); - chain = await _fullBlockchainService.GetChainAsync(); - - var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - - discardedBranch.BranchKeys.Count.ShouldBe(1); - discardedBranch.BranchKeys[0] - .ShouldBe(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); - - discardedBranch.NotLinkedKeys.Count.ShouldBe(0); - } + // LIB height: 7 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (h)-> l -> m -> n -> o -> p + // Fork Branch: (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v -> w -> x -> y -> z + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[6] + .Height, _kernelTestHelper.BestBranchBlockList[6].GetHash()); + chain = await _fullBlockchainService.GetChainAsync(); - { - // LIB height: 9 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (h)-> l -> m -> n -> o -> p - // Fork Branch: (-) (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v -> w -> x -> y -> z - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[8] - .Height, _kernelTestHelper.BestBranchBlockList[8].GetHash()); - chain = await _fullBlockchainService.GetChainAsync(); - - var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - - discardedBranch.BranchKeys.Count.ShouldBe(2); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); - - discardedBranch.NotLinkedKeys.Count.ShouldBe(0); - } + var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - { - // LIB height: 10 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (-) (h)-> l -> m -> n -> o -> p - // Fork Branch: (-) (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v -> w -> x -> y -> z - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[9] - .Height, _kernelTestHelper.BestBranchBlockList[9].GetHash()); - chain = await _fullBlockchainService.GetChainAsync(); - - var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - - discardedBranch.BranchKeys.Count.ShouldBe(2); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); - - discardedBranch.NotLinkedKeys.Count.ShouldBe(1); - discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[0].Header - .PreviousBlockHash.ToStorageKey()); - } + discardedBranch.BranchKeys.Count.ShouldBe(1); + discardedBranch.BranchKeys[0] + .ShouldBe(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); - { - // LIB height: 11 - // - // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - // Longest Branch: (-) (h)-> l -> m -> n -> o -> p - // Fork Branch: (-) (e)-> q -> r -> s -> t -> u - // Unlinked Branch: v(-) -> w -> x -> y -> z - await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[10] - .Height, _kernelTestHelper.BestBranchBlockList[10].GetHash()); - chain = await _fullBlockchainService.GetChainAsync(); - - var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - - discardedBranch.BranchKeys.Count.ShouldBe(2); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); - discardedBranch.BranchKeys - .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); - - discardedBranch.NotLinkedKeys.Count.ShouldBe(2); - discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[0].Header - .PreviousBlockHash.ToStorageKey()); - discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[1].Header - .PreviousBlockHash.ToStorageKey()); - } + discardedBranch.NotLinkedKeys.Count.ShouldBe(0); } - [Fact] - public async Task Get_DiscardedBranch_InvalidBranchTest() { - var chain = await _fullBlockchainService.GetChainAsync(); - var branchCount = chain.Branches.Count; - await _fullBlockchainService.AttachBlockToChainAsync(chain, _kernelTestHelper.BestBranchBlockList[3]); - + // LIB height: 9 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (h)-> l -> m -> n -> o -> p + // Fork Branch: (-) (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v -> w -> x -> y -> z + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[8] + .Height, _kernelTestHelper.BestBranchBlockList[8].GetHash()); chain = await _fullBlockchainService.GetChainAsync(); - chain.Branches.Count.ShouldBe(branchCount + 1); var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - discardedBranch.BranchKeys.Count.ShouldBe(1); - discardedBranch.BranchKeys.ShouldContain(_kernelTestHelper.BestBranchBlockList[3].GetHash().ToStorageKey()); + discardedBranch.BranchKeys.Count.ShouldBe(2); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); + discardedBranch.NotLinkedKeys.Count.ShouldBe(0); } - [Fact] - public async Task Clean_ChainBranch_Test() { - var chain = await _fullBlockchainService.GetChainAsync(); - var bestChainKey = chain.BestChainHash.ToStorageKey(); - var longestChainKey = chain.LongestChainHash.ToStorageKey(); + // LIB height: 10 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (-) (h)-> l -> m -> n -> o -> p + // Fork Branch: (-) (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v -> w -> x -> y -> z + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[9] + .Height, _kernelTestHelper.BestBranchBlockList[9].GetHash()); + chain = await _fullBlockchainService.GetChainAsync(); - var discardedBranch = new DiscardedBranch - { - BranchKeys = new List - { - bestChainKey, - longestChainKey, - _kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey(), - "Not Exist Branch" - }, - NotLinkedKeys = new List - { - _kernelTestHelper.NotLinkedBlockList[0].Header.PreviousBlockHash.ToStorageKey(), - _kernelTestHelper.NotLinkedBlockList[1].Header.PreviousBlockHash.ToStorageKey(), - "Not Exist Block" - } - }; - await _fullBlockchainService.CleanChainBranchAsync(discardedBranch); - - var currentChain = await _fullBlockchainService.GetChainAsync(); - - currentChain.LongestChainHash.ShouldBe(currentChain.BestChainHash); - - currentChain.Branches.Count.ShouldBe(chain.Branches.Count - 2); - currentChain.Branches.ShouldNotContainKey(longestChainKey); - currentChain.Branches.ShouldNotContainKey(_kernelTestHelper.ForkBranchBlockList.Last().GetHash() - .ToStorageKey()); - - currentChain.NotLinkedBlocks.Count.ShouldBe(3); - currentChain.NotLinkedBlocks.ShouldNotContainKey(discardedBranch.NotLinkedKeys[0]); - currentChain.NotLinkedBlocks.ShouldNotContainKey(discardedBranch.NotLinkedKeys[1]); + var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); + + discardedBranch.BranchKeys.Count.ShouldBe(2); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); + + discardedBranch.NotLinkedKeys.Count.ShouldBe(1); + discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[0].Header + .PreviousBlockHash.ToStorageKey()); } - [Fact] - public async Task ResetChainToLib_Test() { - var chain = await _fullBlockchainService.GetChainAsync(); - chain = await _fullBlockchainService.ResetChainToLibAsync(chain); + // LIB height: 11 + // + // Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + // Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + // Longest Branch: (-) (h)-> l -> m -> n -> o -> p + // Fork Branch: (-) (e)-> q -> r -> s -> t -> u + // Unlinked Branch: v(-) -> w -> x -> y -> z + await _fullBlockchainService.SetIrreversibleBlockAsync(chain, _kernelTestHelper.BestBranchBlockList[10] + .Height, _kernelTestHelper.BestBranchBlockList[10].GetHash()); + chain = await _fullBlockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(chain.LastIrreversibleBlockHash); - chain.BestChainHeight.ShouldBe(chain.LastIrreversibleBlockHeight); - chain.LongestChainHash.ShouldBe(chain.LastIrreversibleBlockHash); - chain.LongestChainHeight.ShouldBe(chain.LastIrreversibleBlockHeight); + var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); - chain.Branches.Count.ShouldBe(1); - chain.Branches[chain.LastIrreversibleBlockHash.ToStorageKey()].ShouldBe(chain.LastIrreversibleBlockHeight); + discardedBranch.BranchKeys.Count.ShouldBe(2); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey()); + discardedBranch.BranchKeys + .ShouldContain(_kernelTestHelper.LongestBranchBlockList.Last().GetHash().ToStorageKey()); - chain.NotLinkedBlocks.ShouldBeEmpty(); + discardedBranch.NotLinkedKeys.Count.ShouldBe(2); + discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[0].Header + .PreviousBlockHash.ToStorageKey()); + discardedBranch.NotLinkedKeys.ShouldContain(_kernelTestHelper.NotLinkedBlockList[1].Header + .PreviousBlockHash.ToStorageKey()); + } + } - foreach (var block in _kernelTestHelper.LongestBranchBlockList) - { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.IsLinked.ShouldBeFalse(); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); - } + [Fact] + public async Task Get_DiscardedBranch_InvalidBranchTest() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var branchCount = chain.Branches.Count; + await _fullBlockchainService.AttachBlockToChainAsync(chain, _kernelTestHelper.BestBranchBlockList[3]); - foreach (var block in _kernelTestHelper.ForkBranchBlockList) - { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.IsLinked.ShouldBeFalse(); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); - } + chain = await _fullBlockchainService.GetChainAsync(); + chain.Branches.Count.ShouldBe(branchCount + 1); + + var discardedBranch = await _fullBlockchainService.GetDiscardedBranchAsync(chain); + + discardedBranch.BranchKeys.Count.ShouldBe(1); + discardedBranch.BranchKeys.ShouldContain(_kernelTestHelper.BestBranchBlockList[3].GetHash().ToStorageKey()); + discardedBranch.NotLinkedKeys.Count.ShouldBe(0); + } + + [Fact] + public async Task Clean_ChainBranch_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var bestChainKey = chain.BestChainHash.ToStorageKey(); + var longestChainKey = chain.LongestChainHash.ToStorageKey(); - foreach (var block in _kernelTestHelper.ForkBranchBlockList.TakeWhile(block => - block.Height != chain.LastIrreversibleBlockHeight)) + var discardedBranch = new DiscardedBranch + { + BranchKeys = new List + { + bestChainKey, + longestChainKey, + _kernelTestHelper.ForkBranchBlockList.Last().GetHash().ToStorageKey(), + "Not Exist Branch" + }, + NotLinkedKeys = new List { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.IsLinked.ShouldBeFalse(); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); + _kernelTestHelper.NotLinkedBlockList[0].Header.PreviousBlockHash.ToStorageKey(), + _kernelTestHelper.NotLinkedBlockList[1].Header.PreviousBlockHash.ToStorageKey(), + "Not Exist Block" } - } + }; + await _fullBlockchainService.CleanChainBranchAsync(discardedBranch); - [Fact] - public async Task Transaction_Test() - { - var transaction1 = _kernelTestHelper.GenerateTransaction(); - var transaction2 = _kernelTestHelper.GenerateTransaction(); + var currentChain = await _fullBlockchainService.GetChainAsync(); + + currentChain.LongestChainHash.ShouldBe(currentChain.BestChainHash); + + currentChain.Branches.Count.ShouldBe(chain.Branches.Count - 2); + currentChain.Branches.ShouldNotContainKey(longestChainKey); + currentChain.Branches.ShouldNotContainKey(_kernelTestHelper.ForkBranchBlockList.Last().GetHash() + .ToStorageKey()); - var hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction1.GetHash()); - hasTransaction.ShouldBeFalse(); - hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction2.GetHash()); - hasTransaction.ShouldBeFalse(); + currentChain.NotLinkedBlocks.Count.ShouldBe(3); + currentChain.NotLinkedBlocks.ShouldNotContainKey(discardedBranch.NotLinkedKeys[0]); + currentChain.NotLinkedBlocks.ShouldNotContainKey(discardedBranch.NotLinkedKeys[1]); + } + + [Fact] + public async Task ResetChainToLib_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + chain = await _fullBlockchainService.ResetChainToLibAsync(chain); - await _fullBlockchainService.AddTransactionsAsync(new List {transaction1, transaction2}); + chain.BestChainHash.ShouldBe(chain.LastIrreversibleBlockHash); + chain.BestChainHeight.ShouldBe(chain.LastIrreversibleBlockHeight); + chain.LongestChainHash.ShouldBe(chain.LastIrreversibleBlockHash); + chain.LongestChainHeight.ShouldBe(chain.LastIrreversibleBlockHeight); - var transactions = await _fullBlockchainService.GetTransactionsAsync(new List - {transaction1.GetHash(), transaction2.GetHash()}); + chain.Branches.Count.ShouldBe(1); + chain.Branches[chain.LastIrreversibleBlockHash.ToStorageKey()].ShouldBe(chain.LastIrreversibleBlockHeight); - transactions[0].ShouldBe(transaction1); - transactions[1].ShouldBe(transaction2); + chain.NotLinkedBlocks.ShouldBeEmpty(); - hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction1.GetHash()); - hasTransaction.ShouldBeTrue(); - hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction2.GetHash()); - hasTransaction.ShouldBeTrue(); + foreach (var block in _kernelTestHelper.LongestBranchBlockList) + { + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.IsLinked.ShouldBeFalse(); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); } - - [Fact] - public async Task RemoveLongestBranch_Test() + + foreach (var block in _kernelTestHelper.ForkBranchBlockList) { - var chain = await _fullBlockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - chain.LongestChainHash.ShouldNotBe(bestChainHash); - chain.LongestChainHeight.ShouldNotBe(bestChainHeight); - - await _fullBlockchainService.RemoveLongestBranchAsync(chain); - - chain.LongestChainHash.ShouldBe(bestChainHash); - chain.LongestChainHeight.ShouldBe(bestChainHeight); + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.IsLinked.ShouldBeFalse(); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); + } + + foreach (var block in _kernelTestHelper.ForkBranchBlockList.TakeWhile(block => + block.Height != chain.LastIrreversibleBlockHeight)) + { + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.IsLinked.ShouldBeFalse(); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); } + } + + [Fact] + public async Task Transaction_Test() + { + var transaction1 = _kernelTestHelper.GenerateTransaction(); + var transaction2 = _kernelTestHelper.GenerateTransaction(); + + var hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction1.GetHash()); + hasTransaction.ShouldBeFalse(); + hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction2.GetHash()); + hasTransaction.ShouldBeFalse(); + + await _fullBlockchainService.AddTransactionsAsync(new List { transaction1, transaction2 }); + + var transactions = await _fullBlockchainService.GetTransactionsAsync(new List + { transaction1.GetHash(), transaction2.GetHash() }); + + transactions[0].ShouldBe(transaction1); + transactions[1].ShouldBe(transaction2); + + hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction1.GetHash()); + hasTransaction.ShouldBeTrue(); + hasTransaction = await _fullBlockchainService.HasTransactionAsync(transaction2.GetHash()); + hasTransaction.ShouldBeTrue(); + } + + [Fact] + public async Task RemoveLongestBranch_Test() + { + var chain = await _fullBlockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + chain.LongestChainHash.ShouldNotBe(bestChainHash); + chain.LongestChainHeight.ShouldNotBe(bestChainHeight); + + await _fullBlockchainService.RemoveLongestBranchAsync(chain); + chain.LongestChainHash.ShouldBe(bestChainHash); + chain.LongestChainHeight.ShouldBe(bestChainHeight); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionBlockIndexServiceTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionBlockIndexServiceTests.cs index 2ef483673a..f726c7d48b 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionBlockIndexServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionBlockIndexServiceTests.cs @@ -1,476 +1,477 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Blockchain.Infrastructure; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Application +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfBlockchainModule)] +public class TransactionBlockIndexServiceTests : AElfKernelWithChainTestBase { - public class TransactionBlockIndexServiceTests : AElfKernelWithChainTestBase + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionBlockIndexManager _transactionBlockIndexManager; + private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + + public TransactionBlockIndexServiceTests() { - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionBlockIndexManager _transactionBlockIndexManager; - private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; + _transactionBlockIndexService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockchainService = GetRequiredService(); + _transactionBlockIndexManager = GetRequiredService(); + _transactionBlockIndexProvider = GetRequiredService(); + } - public TransactionBlockIndexServiceTests() - { - _transactionBlockIndexService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockchainService = GetRequiredService(); - _transactionBlockIndexManager = GetRequiredService(); - _transactionBlockIndexProvider = GetRequiredService(); - } + [Fact] + public async Task UpdateOneBlockIndexWithoutBestChain() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash")); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block); - [Fact] - public async Task UpdateOneBlockIndexWithoutBestChain() + var txId = HashHelper.ComputeFrom("Transaction"); + var blockIndex = new BlockIndex { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash")); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block); - - var txId = HashHelper.ComputeFrom("Transaction"); - var blockIndex = new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex); + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex); - var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Null(actual); + var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Null(actual); - var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Null(cacheInBestBranch); + var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Null(cacheInBestBranch); - var cacheInForkBranch = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block.GetHash()); - Assert.True(cacheInForkBranch); - } + var cacheInForkBranch = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block.GetHash()); + Assert.True(cacheInForkBranch); + } - [Fact] - public async Task UpdateOneBlockIndexWithBestChain() + [Fact] + public async Task UpdateOneBlockIndexWithBestChain() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash")); + var txId = HashHelper.ComputeFrom("Transaction"); + var blockIndex = new BlockIndex { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash")); - var txId = HashHelper.ComputeFrom("Transaction"); - var blockIndex = new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block); - await SetBestChain(chain, block); - - var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex, actual); - - var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex, cacheInBestBranch); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block); + await SetBestChain(chain, block); + + var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex, actual); + + var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex, cacheInBestBranch); + } - [Fact] - public async Task UpdateTwoBlockIndexesWithoutBestChain() - { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block1 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); + [Fact] + public async Task UpdateTwoBlockIndexesWithoutBestChain() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block1 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block1); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block1); - var txId = HashHelper.ComputeFrom("Transaction"); - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); + var txId = HashHelper.ComputeFrom("Transaction"); + var blockIndex1 = new BlockIndex + { + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block2); + chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block2); - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); + var blockIndex2 = new BlockIndex + { + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); + + var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Null(actual); + + var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Null(cacheInBestBranch); + + var cacheBlockIndex1 = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block1.GetHash()); + Assert.True(cacheBlockIndex1); + + var cacheBlockIndex2 = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block2.GetHash()); + Assert.True(cacheBlockIndex2); + } - var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Null(actual); + [Fact] + public async Task UpdateTwoBlockIndexesWithFirstBestChain() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block1 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); - var cacheInBestBranch = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Null(cacheInBestBranch); + var txId = HashHelper.ComputeFrom("Transaction"); - var cacheBlockIndex1 = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block1.GetHash()); - Assert.True(cacheBlockIndex1); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block1); + await SetBestChain(chain, block1); - var cacheBlockIndex2 = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block2.GetHash()); - Assert.True(cacheBlockIndex2); - } + var blockIndex1 = new BlockIndex + { + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - [Fact] - public async Task UpdateTwoBlockIndexesWithFirstBestChain() + var blockIndex2 = new BlockIndex { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block1 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); + + chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block2); + + var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex1, actual); + + var cacheBlockIndex1 = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + chain.BestChainHash); + Assert.True(cacheBlockIndex1); + + var cacheBlockIndex2 = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block2.GetHash()); + Assert.True(cacheBlockIndex2); + } - var txId = HashHelper.ComputeFrom("Transaction"); + [Fact] + public async Task UpdateTwoBlockIndexesWithSecondBestChain() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block1 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block1); - await SetBestChain(chain, block1); + var txId = HashHelper.ComputeFrom("Transaction"); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block1); - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); + var blockIndex1 = new BlockIndex + { + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); + var blockIndex2 = new BlockIndex + { + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); + + chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block2); + await SetBestChain(chain, block2); + + var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex2, actual); + + var cacheBlockIndex1InBestChain = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + chain.BestChainHash); + Assert.True(cacheBlockIndex1InBestChain); + + var cacheBlockIndex1 = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block1.GetHash()); + Assert.True(cacheBlockIndex1); + } - chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block2); + [Fact] + public async Task GetTransactionBlockIndexBelowLibTest() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block1 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, previousBlockHeader.PreviousBlockHash); - var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex1, actual); + var txId = HashHelper.ComputeFrom("Transaction"); + var chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block1); - var cacheBlockIndex1 = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - chain.BestChainHash); - Assert.True(cacheBlockIndex1); + var blockIndex = + await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + blockIndex.ShouldBeNull(); - var cacheBlockIndex2 = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block2.GetHash()); - Assert.True(cacheBlockIndex2); - } + var blockIndex1 = new BlockIndex + { + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - [Fact] - public async Task UpdateTwoBlockIndexesWithSecondBestChain() + var blockIndex2 = new BlockIndex { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block1 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash2")); + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); - var txId = HashHelper.ComputeFrom("Transaction"); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block1); + chain = await _blockchainService.GetChainAsync(); + await AddBlockAsync(chain, block2); + await SetBestChain(chain, block2); - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); + { + var existsOnForkBranch = + await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, + block1.GetHash()); + Assert.True(existsOnForkBranch); - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); + var actualBlockIndexOnBestChain = + await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex2, actualBlockIndexOnBestChain); - chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block2); - await SetBestChain(chain, block2); + var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); + transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); + transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(1); + transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHash.ShouldBe(blockIndex1.BlockHash); + transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHeight.ShouldBe(blockIndex1.BlockHeight); + + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndexCache) + .ShouldBeTrue(); + transactionBlockIndexCache.ShouldBe(transactionBlockIndex); + } - var actual = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex2, actual); + var i = 0; + var currentBlock = block2; + while (i++ < KernelConstants.ReferenceBlockValidPeriod) + { + var block = await _kernelTestHelper.AttachBlock(currentBlock.Height, currentBlock.GetHash()); + // await AddBlockAsync(chain, block); + currentBlock = block; + } - var cacheBlockIndex1InBestChain = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - chain.BestChainHash); - Assert.True(cacheBlockIndex1InBestChain); + await SetBestChain(chain, currentBlock); + await _blockchainService.SetIrreversibleBlockAsync(chain, currentBlock.Height, currentBlock.GetHash()); + await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(currentBlock.Height); + { + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out _).ShouldBeFalse(); - var cacheBlockIndex1 = + var existsOnForkBranch = await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, block1.GetHash()); - Assert.True(cacheBlockIndex1); + Assert.False(existsOnForkBranch); + var actualBlockIndexOnBestChain = + await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.Equal(blockIndex2, actualBlockIndexOnBestChain); + + var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); + transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); + transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(0); } + } - [Fact] - public async Task GetTransactionBlockIndexBelowLibTest() - { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block1 = - _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = - _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, previousBlockHeader.PreviousBlockHash); + [Fact] + public async Task AddBlockIndex_Repeated_Test() + { + var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; + var block1 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = + _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, previousBlockHeader.PreviousBlockHash); - var txId = HashHelper.ComputeFrom("Transaction"); - var chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block1); + var txId = HashHelper.ComputeFrom("Transaction"); - var blockIndex = - await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - blockIndex.ShouldBeNull(); + var blockIndex1 = new BlockIndex + { + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); + var blockIndex2 = new BlockIndex + { + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); + var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - chain = await _blockchainService.GetChainAsync(); - await AddBlockAsync(chain, block2); - await SetBestChain(chain, block2); + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); + var txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + txBlockIndex.ShouldBe(transactionBlockIndex); - { - var existsOnForkBranch = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block1.GetHash()); - Assert.True(existsOnForkBranch); - - var actualBlockIndexOnBestChain = - await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex2, actualBlockIndexOnBestChain); - - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); - transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); - transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(1); - transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHash.ShouldBe(blockIndex1.BlockHash); - transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHeight.ShouldBe(blockIndex1.BlockHeight); - - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndexCache) - .ShouldBeTrue(); - transactionBlockIndexCache.ShouldBe(transactionBlockIndex); - } + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); + txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + txBlockIndex.ShouldBe(transactionBlockIndex); + } - var i = 0; - var currentBlock = block2; - while (i++ < KernelConstants.ReferenceBlockValidPeriod) - { - var block = await _kernelTestHelper.AttachBlock(currentBlock.Height, currentBlock.GetHash()); - // await AddBlockAsync(chain, block); - currentBlock = block; - } + [Fact] + public async Task AddBlockIndex_Replace_Test() + { + var block1 = _kernelTestHelper.GenerateBlock(11, HashHelper.ComputeFrom("PreBlockHash1")); + var block2 = _kernelTestHelper.GenerateBlock(12, HashHelper.ComputeFrom("PreBlockHash2")); + var block3 = _kernelTestHelper.GenerateBlock(13, HashHelper.ComputeFrom("PreBlockHash3")); - await SetBestChain(chain, currentBlock); - await _blockchainService.SetIrreversibleBlockAsync(chain, currentBlock.Height, currentBlock.GetHash()); - await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(currentBlock.Height); - { - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out _).ShouldBeFalse(); - - var existsOnForkBranch = - await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId, - block1.GetHash()); - Assert.False(existsOnForkBranch); - var actualBlockIndexOnBestChain = - await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.Equal(blockIndex2, actualBlockIndexOnBestChain); - - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); - transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); - transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(0); - } - } + var txId = HashHelper.ComputeFrom("Transaction"); - [Fact] - public async Task AddBlockIndex_Repeated_Test() + var blockIndex1 = new BlockIndex { - var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header; - var block1 = _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = - _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, previousBlockHeader.PreviousBlockHash); + BlockHash = block1.GetHash(), + BlockHeight = block1.Height + }; - var txId = HashHelper.ComputeFrom("Transaction"); + var blockIndex2 = new BlockIndex + { + BlockHash = block2.GetHash(), + BlockHeight = block2.Height + }; - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); + var blockIndex3 = new BlockIndex + { + BlockHash = block3.GetHash(), + BlockHeight = block3.Height + }; + + { + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex2); - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); - var txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - txBlockIndex.ShouldBe(transactionBlockIndex); - - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); - txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - txBlockIndex.ShouldBe(transactionBlockIndex); + transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); + transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); + transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(0); } - [Fact] - public async Task AddBlockIndex_Replace_Test() { - var block1 = _kernelTestHelper.GenerateBlock(11, HashHelper.ComputeFrom("PreBlockHash1")); - var block2 = _kernelTestHelper.GenerateBlock(12, HashHelper.ComputeFrom("PreBlockHash2")); - var block3 = _kernelTestHelper.GenerateBlock(13, HashHelper.ComputeFrom("PreBlockHash3")); - - var txId = HashHelper.ComputeFrom("Transaction"); - - var blockIndex1 = new BlockIndex - { - BlockHash = block1.GetHash(), - BlockHeight = block1.Height - }; - - var blockIndex2 = new BlockIndex - { - BlockHash = block2.GetHash(), - BlockHeight = block2.Height - }; - - var blockIndex3 = new BlockIndex - { - BlockHash = block3.GetHash(), - BlockHeight = block3.Height - }; - - { - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex2); + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex1); - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); - transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); - transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(0); - } - - { - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex1); - - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); - transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); - transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(1); - transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHash.ShouldBe(blockIndex1.BlockHash); - transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHeight.ShouldBe(blockIndex1.BlockHeight); - } - - { - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex3); - var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); - transactionBlockIndex.BlockHash.ShouldBe(blockIndex3.BlockHash); - transactionBlockIndex.BlockHeight.ShouldBe(blockIndex3.BlockHeight); - transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(2); - transactionBlockIndex.PreviousExecutionBlockIndexList.ShouldContain(blockIndex1); - transactionBlockIndex.PreviousExecutionBlockIndexList.ShouldContain(blockIndex2); - } + var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash); + transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight); + transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(1); + transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHash.ShouldBe(blockIndex1.BlockHash); + transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHeight.ShouldBe(blockIndex1.BlockHeight); } - [Fact] - public async Task InitializeTransactionBlockIndexCache_Success() { - var chain = await _blockchainService.GetChainAsync(); + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex3); + var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId); + transactionBlockIndex.BlockHash.ShouldBe(blockIndex3.BlockHash); + transactionBlockIndex.BlockHeight.ShouldBe(blockIndex3.BlockHeight); + transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(2); + transactionBlockIndex.PreviousExecutionBlockIndexList.ShouldContain(blockIndex1); + transactionBlockIndex.PreviousExecutionBlockIndexList.ShouldContain(blockIndex2); + } + } - var blockHash = chain.LastIrreversibleBlockHash; - var blockHeight = chain.LastIrreversibleBlockHeight; - while (true) - { - var block = await _blockchainService.GetBlockByHashAsync(blockHash); - foreach (var txId in block.TransactionIds) - { - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, - new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - } - - if (blockHeight == AElfConstants.GenesisBlockHeight) - break; - - blockHash = block.Header.PreviousBlockHash; - blockHeight--; - } + [Fact] + public async Task InitializeTransactionBlockIndexCache_Success() + { + var chain = await _blockchainService.GetChainAsync(); - await _transactionBlockIndexService.LoadTransactionBlockIndexAsync(); + var blockHash = chain.LastIrreversibleBlockHash; + var blockHeight = chain.LastIrreversibleBlockHeight; + while (true) + { + var block = await _blockchainService.GetBlockByHashAsync(blockHash); + foreach (var txId in block.TransactionIds) + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, + new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); + + if (blockHeight == AElfConstants.GenesisBlockHeight) + break; + + blockHash = block.Header.PreviousBlockHash; + blockHeight--; + } + + await _transactionBlockIndexService.LoadTransactionBlockIndexAsync(); - blockHeight = chain.LastIrreversibleBlockHeight; - blockHash = chain.LastIrreversibleBlockHash; - while (true) + blockHeight = chain.LastIrreversibleBlockHeight; + blockHash = chain.LastIrreversibleBlockHash; + while (true) + { + var block = await _blockchainService.GetBlockByHashAsync(blockHash); + foreach (var txId in block.TransactionIds) { - var block = await _blockchainService.GetBlockByHashAsync(blockHash); - foreach (var txId in block.TransactionIds) - { - var blockIndex = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); - Assert.NotNull(blockIndex); - } - - if (blockHeight == AElfConstants.GenesisBlockHeight || blockHeight <= - chain.LastIrreversibleBlockHeight - KernelConstants.ReferenceBlockValidPeriod) - break; - - blockHash = block.Header.PreviousBlockHash; - blockHeight--; + var blockIndex = await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId); + Assert.NotNull(blockIndex); } - } - [Fact] - public async Task UpdateTransactionBlockIndicesByLibHeight_Test() - { - var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + if (blockHeight == AElfConstants.GenesisBlockHeight || blockHeight <= + chain.LastIrreversibleBlockHeight - KernelConstants.ReferenceBlockValidPeriod) + break; - var txId = HashHelper.ComputeFrom("Transaction"); - var blockIndex = new BlockIndex - { - BlockHash = blockHeader.GetHash(), - BlockHeight = blockHeader.Height - }; - await _transactionBlockIndexService.AddBlockIndexAsync(new List {txId}, blockIndex); - - await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(blockHeader.Height); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex); - transactionBlockIndex.BlockHash.ShouldBe(blockHeader.GetHash()); - transactionBlockIndex.BlockHeight.ShouldBe(blockHeader.Height); - - await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync( - blockHeader.Height + KernelConstants.ReferenceBlockValidPeriod); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out transactionBlockIndex); - transactionBlockIndex.ShouldBeNull(); + blockHash = block.Header.PreviousBlockHash; + blockHeight--; } + } - private async Task AddBlockAsync(Chain chain, Block block) - { - await _blockchainService.AddBlockAsync(block); - await _blockchainService.AttachBlockToChainAsync(chain, block); - } + [Fact] + public async Task UpdateTransactionBlockIndicesByLibHeight_Test() + { + var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - private async Task SetBestChain(Chain chain, Block block) + var txId = HashHelper.ComputeFrom("Transaction"); + var blockIndex = new BlockIndex { - await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); - } + BlockHash = blockHeader.GetHash(), + BlockHeight = blockHeader.Height + }; + await _transactionBlockIndexService.AddBlockIndexAsync(new List { txId }, blockIndex); + + await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(blockHeader.Height); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndex); + transactionBlockIndex.BlockHash.ShouldBe(blockHeader.GetHash()); + transactionBlockIndex.BlockHeight.ShouldBe(blockHeader.Height); + + await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync( + blockHeader.Height + KernelConstants.ReferenceBlockValidPeriod); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out transactionBlockIndex); + transactionBlockIndex.ShouldBeNull(); + } + + private async Task AddBlockAsync(Chain chain, Block block) + { + await _blockchainService.AddBlockAsync(block); + await _blockchainService.AttachBlockToChainAsync(chain, block); + } + + private async Task SetBestChain(Chain chain, Block block) + { + await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionResultServiceTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionResultServiceTests.cs index ed5a26a8a3..17beaa318c 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionResultServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Application/TransactionResultServiceTests.cs @@ -1,238 +1,226 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.Blockchain.Events; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Volo.Abp.EventBus.Local; -using Xunit; - -namespace AElf.Kernel.Blockchain.Application + +namespace AElf.Kernel.Blockchain.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class TransactionResultServiceTests : AElfKernelWithChainTestBase { - public class TransactionResultServiceTests : AElfKernelWithChainTestBase + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionBlockIndexManager _transacionBlockIndexManager; + private readonly ITransactionBlockIndexService _transactionBlockIndexService; + private readonly ITransactionResultManager _transactionResultManager; + private readonly ITransactionResultService _transactionResultService; + + public TransactionResultServiceTests() { - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionResultService _transactionResultService; - private readonly ITransactionResultManager _transactionResultManager; - private readonly ITransactionBlockIndexManager _transacionBlockIndexManager; - private readonly ILocalEventBus _localEventBus; - private readonly ITransactionBlockIndexService _transactionBlockIndexService; - - public TransactionResultServiceTests() - { - _transactionBlockIndexService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockchainService = GetRequiredService(); - _transactionResultService = GetRequiredService(); - _transactionResultManager = GetRequiredService(); - _transacionBlockIndexManager = GetRequiredService(); - _localEventBus = GetRequiredService(); - } + _transactionBlockIndexService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockchainService = GetRequiredService(); + _transactionResultService = GetRequiredService(); + _transactionResultManager = GetRequiredService(); + _transacionBlockIndexManager = GetRequiredService(); + } - private async Task AddTransactionResultsWithPostMiningAsync(Block block, IEnumerable results) - { - // Add block to chain - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.AddBlockAsync(block); - await _blockchainService.AttachBlockToChainAsync(chain, block); + private async Task AddTransactionResultsWithPostMiningAsync(Block block, IEnumerable results) + { + // Add block to chain + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.AddBlockAsync(block); + await _blockchainService.AttachBlockToChainAsync(chain, block); - // TransactionResults are added during execution - // Add TransactionResult before completing and adding block - await _transactionResultService.AddTransactionResultsAsync(results.ToList(), block.Header); + // TransactionResults are added during execution + // Add TransactionResult before completing and adding block + await _transactionResultService.AddTransactionResultsAsync(results.ToList(), block.Header); - // Set best chain after execution - await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); + // Set best chain after execution + await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); - var blockIndex = new BlockIndex - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; + var blockIndex = new BlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; - await _transactionBlockIndexService.AddBlockIndexAsync(block.Body.TransactionIds, blockIndex); - } + await _transactionBlockIndexService.AddBlockIndexAsync(block.Body.TransactionIds, blockIndex); + } - private (Block, List) GetNextBlockWithTransactionAndResults(BlockHeader previous, - IEnumerable transactions, ByteString uniqueData = null) - { - var block = _kernelTestHelper.GenerateBlock(previous.Height, previous.GetHash()); - if (uniqueData != null) - { - // piggy back on Bloom to make block unique - block.Header.Bloom = uniqueData; - } + private (Block, List) GetNextBlockWithTransactionAndResults(BlockHeader previous, + IEnumerable transactions, ByteString uniqueData = null) + { + var block = _kernelTestHelper.GenerateBlock(previous.Height, previous.GetHash()); + if (uniqueData != null) + // piggy back on Bloom to make block unique + block.Header.Bloom = uniqueData; - var results = new List(); - foreach (var transaction in transactions) + var results = new List(); + foreach (var transaction in transactions) + { + block.Body.TransactionIds.Add(transaction.GetHash()); + results.Add(new TransactionResult { - block.Body.TransactionIds.Add(transaction.GetHash()); - results.Add(new TransactionResult() - { - TransactionId = transaction.GetHash(), - ReturnValue = ByteString.CopyFromUtf8(block.GetHash().ToHex()) - }); - } - - return (block, results); + TransactionId = transaction.GetHash(), + ReturnValue = ByteString.CopyFromUtf8(block.GetHash().ToHex()) + }); } - [Fact] - public async Task Add_TransactionResult_With_BlockHash() - { - var tx = _kernelTestHelper.GenerateTransaction(); - var (block, results) = GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last() - .Header, new[] {tx}); + return (block, results); + } - var result = results.First(); - - (await _transactionResultService.GetTransactionResultAsync(tx.GetHash())).ShouldBeNull(); - // Complete block - await AddTransactionResultsWithPostMiningAsync(block, new[] {result}); + [Fact] + public async Task Add_TransactionResult_With_BlockHash() + { + var tx = _kernelTestHelper.GenerateTransaction(); + var (block, results) = GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last() + .Header, new[] { tx }); - var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); - queried.ShouldBe(result); + var result = results.First(); - var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash()); - queried2.ShouldBe(result); - } + (await _transactionResultService.GetTransactionResultAsync(tx.GetHash())).ShouldBeNull(); + // Complete block + await AddTransactionResultsWithPostMiningAsync(block, new[] { result }); - [Fact] - public async Task Query_TransactionResult_On_BestChain() - { - var tx = _kernelTestHelper.GenerateTransaction(); - var (block11, results11) = - GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] {tx}, - ByteString.CopyFromUtf8("branch_1")); - var (block21, results21) = - GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] {tx}, - ByteString.CopyFromUtf8("branch_2")); + var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); + queried.ShouldBe(result); - // Add branch 1 - await AddTransactionResultsWithPostMiningAsync(block11, new[] {results11.First()}); + var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash()); + queried2.ShouldBe(result); + } - // Add branch 2 - await AddTransactionResultsWithPostMiningAsync(block21, new[] {results21.First()}); + [Fact] + public async Task Query_TransactionResult_On_BestChain() + { + var tx = _kernelTestHelper.GenerateTransaction(); + var (block11, results11) = + GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] { tx }, + ByteString.CopyFromUtf8("branch_1")); + var (block21, results21) = + GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] { tx }, + ByteString.CopyFromUtf8("branch_2")); - Assert.NotEqual(results11.First(), results21.First()); + // Add branch 1 + await AddTransactionResultsWithPostMiningAsync(block11, new[] { results11.First() }); - var chain = await _blockchainService.GetChainAsync(); + // Add branch 2 + await AddTransactionResultsWithPostMiningAsync(block21, new[] { results21.First() }); - // Set BestChain to branch 1 - await _blockchainService.SetBestChainAsync(chain, block11.Height, block11.Header.GetHash()); - var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); - queried.ShouldBe(results11.First()); + Assert.NotEqual(results11.First(), results21.First()); - var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block11.GetHash()); - queried2.ShouldBe(results11.First()); + var chain = await _blockchainService.GetChainAsync(); - // Set BestChain to branch 2 - await _blockchainService.SetBestChainAsync(chain, block21.Height, block21.Header.GetHash()); - queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); - queried.ShouldBe(results21.First()); + // Set BestChain to branch 1 + await _blockchainService.SetBestChainAsync(chain, block11.Height, block11.Header.GetHash()); + var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); + queried.ShouldBe(results11.First()); - queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block21.GetHash()); - queried2.ShouldBe(results21.First()); - } + var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block11.GetHash()); + queried2.ShouldBe(results11.First()); - [Fact] - public async Task Query_TransactionResult_After_Execution() - { - var tx1 = _kernelTestHelper.GenerateTransaction(); - var (block11, results11) = - GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] {tx1}); + // Set BestChain to branch 2 + await _blockchainService.SetBestChainAsync(chain, block21.Height, block21.Header.GetHash()); + queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); + queried.ShouldBe(results21.First()); + + queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block21.GetHash()); + queried2.ShouldBe(results21.First()); + } - var tx2 = _kernelTestHelper.GenerateTransaction(); - var (block12, results12) = - GetNextBlockWithTransactionAndResults(block11.Header, new[] {tx2}); + [Fact] + public async Task Query_TransactionResult_After_Execution() + { + var tx1 = _kernelTestHelper.GenerateTransaction(); + var (block11, results11) = + GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] { tx1 }); - // Add block 1 - await AddTransactionResultsWithPostMiningAsync(block11, new[] {results11.First()}); + var tx2 = _kernelTestHelper.GenerateTransaction(); + var (block12, results12) = + GetNextBlockWithTransactionAndResults(block11.Header, new[] { tx2 }); - // Add block 2 - await AddTransactionResultsWithPostMiningAsync(block12, new[] {results12.First()}); + // Add block 1 + await AddTransactionResultsWithPostMiningAsync(block11, new[] { results11.First() }); + // Add block 2 + await AddTransactionResultsWithPostMiningAsync(block12, new[] { results12.First() }); - #region Before LIB - // Before LIB, transaction result is saved with PreMiningHash but not with PostMiningHash (normal BlockHash) - { - var queried = await _transactionResultService.GetTransactionResultAsync(tx2.GetHash()); - queried.ShouldBe(results12.First()); - - var queried2 = - await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); - queried2.ShouldBe(results12.First()); - - var queried3 = - await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); - queried3.ShouldBe(results12.First()); - // PreMiningHash - // var resultWithPreMiningHash = - // await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), - // block11.Header.GetDisambiguatingHash()); - // resultWithPreMiningHash.ShouldBe(results11.First()); - - // PostMiningHash - var resultWithPostMiningHash = - await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), - block11.Header.GetHash()); - //resultWithPostMiningHash.ShouldBeNull(); - } - - await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block11.Header, - block11.Body.TransactionIds.ToList()); - - // After LIB, transaction result is re-saved with PostMiningHash (normal BlockHash) - { - var queried = await _transactionResultService.GetTransactionResultAsync(tx2.GetHash()); - queried.ShouldBe(results12.First()); - - var queried2 = - await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); - queried2.ShouldBe(results12.First()); - // PreMiningHash - // var resultWithPreMiningHash = - // await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), - // block11.Header.GetDisambiguatingHash()); - // resultWithPreMiningHash.ShouldBeNull(); - - // PostMiningHash - var resultWithPostMiningHash = - await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), - block11.Header.GetHash()); - resultWithPostMiningHash.ShouldBe(results11.First()); - } - - #endregion + #region Before LIB + + // Before LIB, transaction result is saved with PreMiningHash but not with PostMiningHash (normal BlockHash) + { + var queried = await _transactionResultService.GetTransactionResultAsync(tx2.GetHash()); + queried.ShouldBe(results12.First()); + + var queried2 = + await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); + queried2.ShouldBe(results12.First()); + + var queried3 = + await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); + queried3.ShouldBe(results12.First()); + // PreMiningHash + // var resultWithPreMiningHash = + // await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), + // block11.Header.GetDisambiguatingHash()); + // resultWithPreMiningHash.ShouldBe(results11.First()); + + // PostMiningHash + var resultWithPostMiningHash = + await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), + block11.Header.GetHash()); + //resultWithPostMiningHash.ShouldBeNull(); } - [Fact] - public async Task Query_TransactionResult_With_Index() + await _transactionResultService.ProcessTransactionResultAfterExecutionAsync(block11.Header, + block11.Body.TransactionIds.ToList()); + + // After LIB, transaction result is re-saved with PostMiningHash (normal BlockHash) { - var tx = _kernelTestHelper.GenerateTransaction(); - var (block, results) = - GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] {tx}); + var queried = await _transactionResultService.GetTransactionResultAsync(tx2.GetHash()); + queried.ShouldBe(results12.First()); + + var queried2 = + await _transactionResultService.GetTransactionResultAsync(tx2.GetHash(), block12.GetHash()); + queried2.ShouldBe(results12.First()); + // PreMiningHash + // var resultWithPreMiningHash = + // await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), + // block11.Header.GetDisambiguatingHash()); + // resultWithPreMiningHash.ShouldBeNull(); + + // PostMiningHash + var resultWithPostMiningHash = + await _transactionResultManager.GetTransactionResultAsync(tx1.GetHash(), + block11.Header.GetHash()); + resultWithPostMiningHash.ShouldBe(results11.First()); + } - var result = results.First(); - // Complete block - await AddTransactionResultsWithPostMiningAsync(block, new[] {result}); + #endregion + } - var transactionBlockIndex = new TransactionBlockIndex() - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - await _transacionBlockIndexManager.SetTransactionBlockIndexAsync(tx.GetHash(), transactionBlockIndex); + [Fact] + public async Task Query_TransactionResult_With_Index() + { + var tx = _kernelTestHelper.GenerateTransaction(); + var (block, results) = + GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] { tx }); - var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); - queried.ShouldBe(result); + var result = results.First(); + // Complete block + await AddTransactionResultsWithPostMiningAsync(block, new[] { result }); - var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash()); - queried2.ShouldBe(result); - } + var transactionBlockIndex = new TransactionBlockIndex + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + await _transacionBlockIndexManager.SetTransactionBlockIndexAsync(tx.GetHash(), transactionBlockIndex); + + var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash()); + queried.ShouldBe(result); + + var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash()); + queried2.ShouldBe(result); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/BlockManagerTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/BlockManagerTests.cs index e96e56cee2..4bf0da80a9 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/BlockManagerTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/BlockManagerTests.cs @@ -1,49 +1,43 @@ -using System.Threading.Tasks; -using AElf.Types; -using Shouldly; -using Xunit; +namespace AElf.Kernel.Blockchain.Domain; -namespace AElf.Kernel.Blockchain.Domain +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockManagerTests : AElfKernelTestBase { - public sealed class BlockManagerTests:AElfKernelTestBase + private readonly IBlockManager _blockManager; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockManagerTests() + { + _blockManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public async Task GetBlock_Header_And_Body_Test() { - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockManager _blockManager; - private const int _chainId = 1234; - - public BlockManagerTests() - { - _blockManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } - - [Fact] - public async Task GetBlock_Header_And_Body_Test() - { - var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty); - var blockHash = block.GetHash(); - await _blockManager.AddBlockHeaderAsync(block.Header); - var blockHeader = await _blockManager.GetBlockHeaderAsync(blockHash); - Assert.Equal(blockHeader, block.Header); - - var storedBlock = await _blockManager.GetBlockAsync(blockHash); - storedBlock.ShouldBeNull(); - - await _blockManager.AddBlockBodyAsync(blockHash, block.Body); - - storedBlock = await _blockManager.GetBlockAsync(blockHash); - Assert.Equal(storedBlock.Header, block.Header); - Assert.Equal(storedBlock.Body, block.Body); - - (await _blockManager.HasBlockAsync(blockHash)).ShouldBeTrue(); - - await _blockManager.RemoveBlockAsync(blockHash); - await _blockManager.AddBlockBodyAsync(blockHash, block.Body); - - storedBlock = await _blockManager.GetBlockAsync(blockHash); - storedBlock.ShouldBeNull(); - - (await _blockManager.HasBlockAsync(blockHash)).ShouldBeFalse(); - } + var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty); + var blockHash = block.GetHash(); + await _blockManager.AddBlockHeaderAsync(block.Header); + var blockHeader = await _blockManager.GetBlockHeaderAsync(blockHash); + Assert.Equal(blockHeader, block.Header); + + var storedBlock = await _blockManager.GetBlockAsync(blockHash); + storedBlock.ShouldBeNull(); + + await _blockManager.AddBlockBodyAsync(blockHash, block.Body); + + storedBlock = await _blockManager.GetBlockAsync(blockHash); + Assert.Equal(storedBlock.Header, block.Header); + Assert.Equal(storedBlock.Body, block.Body); + + (await _blockManager.HasBlockAsync(blockHash)).ShouldBeTrue(); + + await _blockManager.RemoveBlockAsync(blockHash); + await _blockManager.AddBlockBodyAsync(blockHash, block.Body); + + storedBlock = await _blockManager.GetBlockAsync(blockHash); + storedBlock.ShouldBeNull(); + + (await _blockManager.HasBlockAsync(blockHash)).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/ChainManagerTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/ChainManagerTests.cs index 4e63067257..1fe4a8eeb5 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/ChainManagerTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/ChainManagerTests.cs @@ -1,1138 +1,1133 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Infrastructure; -using AElf.Types; -using Shouldly; using Shouldly.ShouldlyExtensionMethods; -using Xunit; -namespace AElf.Kernel.Blockchain.Domain +namespace AElf.Kernel.Blockchain.Domain; + +public static class BlockNumberExtensions { - public static class BlockNumberExtensions + public static long BlockHeight(this int index) { - public static long BlockHeight(this int index) - { - return AElfConstants.GenesisBlockHeight + index; - } + return AElfConstants.GenesisBlockHeight + index; + } +} + +[Trait("Category", AElfBlockchainModule)] +public sealed class ChainManagerTests : AElfKernelTestBase +{ + private readonly Hash[] _blocks = Enumerable.Range(1, 101).Select(IntToHash).ToArray(); + private readonly IChainBlockLinkCacheProvider _chainBlockLinkCacheProvider; + private readonly ChainManager _chainManager; + private readonly Hash _genesis; + + public ChainManagerTests() + { + _chainManager = GetRequiredService(); + _chainBlockLinkCacheProvider = GetRequiredService(); + _genesis = _blocks[0]; } - public class ChainManagerTests : AElfKernelTestBase + private static Hash IntToHash(int n) { - private readonly ChainManager _chainManager; - private readonly Hash _genesis; - private readonly Hash[] _blocks = Enumerable.Range(1, 101).Select(IntToHash).ToArray(); - private readonly IChainBlockLinkCacheProvider _chainBlockLinkCacheProvider; + var bytes = BitConverter.GetBytes(n); + var arr = new byte[32]; + Array.Copy(bytes, arr, bytes.Length); + return Hash.LoadFromByteArray(arr); + } + + [Fact] + public async Task Create_Chain_Success() + { + var chain = await _chainManager.GetAsync(); + chain.ShouldBeNull(); + + var createChainResult = await _chainManager.CreateAsync(_genesis); + chain = await _chainManager.GetAsync(); + chain.ShouldBe(createChainResult); + chain.LongestChainHeight.ShouldBe(AElfConstants.GenesisBlockHeight); + chain.LongestChainHash.ShouldBe(_genesis); + chain.BestChainHash.ShouldBe(_genesis); + chain.BestChainHeight.ShouldBe(AElfConstants.GenesisBlockHeight); + chain.GenesisBlockHash.ShouldBe(_genesis); + chain.LastIrreversibleBlockHash.ShouldBe(_genesis); + chain.LastIrreversibleBlockHeight.ShouldBe(AElfConstants.GenesisBlockHeight); + chain.Branches.Count.ShouldBe(1); + chain.Branches[_genesis.ToStorageKey()].ShouldBe(AElfConstants.GenesisBlockHeight); + + var blockLink = await _chainManager.GetChainBlockLinkAsync(_genesis); + blockLink.BlockHash.ShouldBe(_genesis); + blockLink.Height.ShouldBe(AElfConstants.GenesisBlockHeight); + blockLink.PreviousBlockHash.ShouldBe(Hash.Empty); + blockLink.IsLinked.ShouldBeTrue(); + blockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); + + var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(AElfConstants.GenesisBlockHeight); + chainBlockIndex.BlockHash.ShouldBe(_genesis); + } + + [Fact] + public async Task Create_Chain_ThrowInvalidOperationException() + { + //basic verify for code coverage + var chain = new Chain(0, _genesis); + chain.ShouldNotBeNull(); + chain.Id.ShouldBe(0); + chain.GenesisBlockHash.ShouldBe(_genesis); + + await _chainManager.CreateAsync(_genesis); - private static Hash IntToHash(int n) + await _chainManager.CreateAsync(_genesis).ShouldThrowAsync(); + await _chainManager.CreateAsync(_blocks[1]).ShouldThrowAsync(); + } + + [Fact] + public async Task LIB_Blocks_Test() + { + //0 -> 1 linked + //0 -> 1 -> 5 equals to 0[0] -> 1[1] -> 5[2] + //not linked: (2) -> 3[5] means a block hash 3 at height 5, has a hash 2 previous block, + // but hash 2 block was not in the chain + //*10, *11[12] means just added to the chain + + + var chain = await _chainManager.CreateAsync(_genesis); + + //0 -> *1, no branch { - var bytes = BitConverter.GetBytes(n); - var arr = new byte[32]; - Array.Copy(bytes, arr, bytes.Length); - return Hash.LoadFromByteArray(arr); + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1], + PreviousBlockHash = _genesis + }); + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(1.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[1]); } - public ChainManagerTests() + //0 -> 1 -> *2, no branch + { - _chainManager = GetRequiredService(); - _chainBlockLinkCacheProvider = GetRequiredService(); - _genesis = _blocks[0]; + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2], + PreviousBlockHash = _blocks[1] + }); + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); } - [Fact] - public async Task Create_Chain_Success() + { - var chain = await _chainManager.GetAsync(); - chain.ShouldBeNull(); - - var createChainResult = await _chainManager.CreateAsync(_genesis); - chain = await _chainManager.GetAsync(); - chain.ShouldBe(createChainResult); - chain.LongestChainHeight.ShouldBe(AElfConstants.GenesisBlockHeight); - chain.LongestChainHash.ShouldBe(_genesis); - chain.BestChainHash.ShouldBe(_genesis); - chain.BestChainHeight.ShouldBe(AElfConstants.GenesisBlockHeight); - chain.GenesisBlockHash.ShouldBe(_genesis); - chain.LastIrreversibleBlockHash.ShouldBe(_genesis); - chain.LastIrreversibleBlockHeight.ShouldBe(AElfConstants.GenesisBlockHeight); - chain.Branches.Count.ShouldBe(1); - chain.Branches[_genesis.ToStorageKey()].ShouldBe(AElfConstants.GenesisBlockHeight); - - var blockLink = await _chainManager.GetChainBlockLinkAsync(_genesis); - blockLink.BlockHash.ShouldBe(_genesis); - blockLink.Height.ShouldBe(AElfConstants.GenesisBlockHeight); - blockLink.PreviousBlockHash.ShouldBe(Hash.Empty); - blockLink.IsLinked.ShouldBeTrue(); - blockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionNone); - - var chainBlockIndex = await _chainManager.GetChainBlockIndexAsync(AElfConstants.GenesisBlockHeight); - chainBlockIndex.BlockHash.ShouldBe(_genesis); + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[1])).ShouldBeTrue(); + //test repeat set + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[1])).ShouldBeFalse(); + (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( + _blocks[0]); + (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( + _blocks[1]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); + chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); } - [Fact] - public async Task Create_Chain_ThrowInvalidOperationException() + //0 -> 1 -> 2, no branch + //not linked: *4 + { - //basic verify for code coverage - var chain = new Chain(0, _genesis); - chain.ShouldNotBeNull(); - chain.Id.ShouldBe(0); - chain.GenesisBlockHash.ShouldBe(_genesis); - - await _chainManager.CreateAsync(_genesis); - - await _chainManager.CreateAsync(_genesis).ShouldThrowAsync(); - await _chainManager.CreateAsync(_blocks[1]).ShouldThrowAsync(); + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 4.BlockHeight(), + BlockHash = _blocks[4], + PreviousBlockHash = _blocks[3] + }); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); } - [Fact] - public async Task LIB_Blocks_Test() { - //0 -> 1 linked - //0 -> 1 -> 5 equals to 0[0] -> 1[1] -> 5[2] - //not linked: (2) -> 3[5] means a block hash 3 at height 5, has a hash 2 previous block, - // but hash 2 block was not in the chain - //*10, *11[12] means just added to the chain - + await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[4]) + .ShouldThrowAsync(); + (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( + _blocks[0]); + (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( + _blocks[1]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); + chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); + } - var chain = await _chainManager.CreateAsync(_genesis); + //0 -> 1 -> 2, no branch + //not linked: 4, *5 - //0 -> *1, no branch + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 1.BlockHeight(), - BlockHash = _blocks[1], - PreviousBlockHash = _genesis - }); + Height = 5.BlockHeight(), + BlockHash = _blocks[5], + PreviousBlockHash = _blocks[4] + }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - chain.LongestChainHeight.ShouldBe(1.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[1]); - } + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); + } - //0 -> 1 -> *2, no branch + //0 -> 1 -> 2 -> *3 -> 4 -> 5 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 2.BlockHeight(), - BlockHash = _blocks[2], - PreviousBlockHash = _blocks[1] - }); + Height = 3.BlockHeight(), + BlockHash = _blocks[3], + PreviousBlockHash = _blocks[2] + }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + } + { + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); + chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); + + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[4])).ShouldBeTrue(); + (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( + _blocks[0]); + (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( + _blocks[1]); + (await _chainManager.GetChainBlockIndexAsync(2.BlockHeight())).BlockHash.ShouldBe( + _blocks[2]); + (await _chainManager.GetChainBlockIndexAsync(3.BlockHeight())).BlockHash.ShouldBe( + _blocks[3]); + (await _chainManager.GetChainBlockIndexAsync(4.BlockHeight())).BlockHash.ShouldBe( + _blocks[4]); + + + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[4]); + chain.LastIrreversibleBlockHeight.ShouldBe(4.BlockHeight()); + } + //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches + // 4 -> *6 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[1])).ShouldBeTrue(); - //test repeat set - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[1])).ShouldBeFalse(); - (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( - _blocks[0]); - (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( - _blocks[1]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); - chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); - } - - //0 -> 1 -> 2, no branch - //not linked: *4 + Height = 5.BlockHeight(), + BlockHash = _blocks[6], + PreviousBlockHash = _blocks[4] + }); - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 4.BlockHeight(), - BlockHash = _blocks[4], - PreviousBlockHash = _blocks[3] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - { - await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[4]) - .ShouldThrowAsync(); - (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( - _blocks[0]); - (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( - _blocks[1]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); - chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); - } - - //0 -> 1 -> 2, no branch - //not linked: 4, *5 + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + } + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> *8 , 2 branches + // 4 -> 6 -> 7 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[5], - PreviousBlockHash = _blocks[4] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + Height = 6.BlockHeight(), + BlockHash = _blocks[8], + PreviousBlockHash = _blocks[5] + }); - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - //0 -> 1 -> 2 -> *3 -> 4 -> 5 + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[8]); + } + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches + // 5 -> *7 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 3.BlockHeight(), - BlockHash = _blocks[3], - PreviousBlockHash = _blocks[2] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - } + Height = 6.BlockHeight(), + BlockHash = _blocks[7], + PreviousBlockHash = _blocks[5] + }); - { - - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[1]); - chain.LastIrreversibleBlockHeight.ShouldBe(1.BlockHeight()); - - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[4])).ShouldBeTrue(); - (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( - _blocks[0]); - (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( - _blocks[1]); - (await _chainManager.GetChainBlockIndexAsync(2.BlockHeight())).BlockHash.ShouldBe( - _blocks[2]); - (await _chainManager.GetChainBlockIndexAsync(3.BlockHeight())).BlockHash.ShouldBe( - _blocks[3]); - (await _chainManager.GetChainBlockIndexAsync(4.BlockHeight())).BlockHash.ShouldBe( - _blocks[4]); - - - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[4]); - chain.LastIrreversibleBlockHeight.ShouldBe(4.BlockHeight()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches - // 4 -> *6 - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[6], - PreviousBlockHash = _blocks[4] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> *8 , 2 branches - // 4 -> 6 -> 7 - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 6.BlockHeight(), - BlockHash = _blocks[8], - PreviousBlockHash = _blocks[5] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[8]); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches - // 5 -> *7 - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 6.BlockHeight(), - BlockHash = _blocks[7], - PreviousBlockHash = _blocks[5] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[8]); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches - // 5 -> 7[6] - //not linked: (9) -> *10[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[10], - PreviousBlockHash = _blocks[9] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[8]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches - // 4 -> 6 -> 7[6] -> *11[7] - //not linked: (9) -> 10[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 7.BlockHeight(), - BlockHash = _blocks[11], - PreviousBlockHash = _blocks[7] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[8]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches - // 4 -> 6 -> 7 -> 10 - //not linked: (9) -> 8[5] , (12) -> *13[8] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 8.BlockHeight(), - BlockHash = _blocks[13], - PreviousBlockHash = _blocks[12] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[8]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); - chain.NotLinkedBlocks[_blocks[12].ToStorageKey()].ShouldBe(_blocks[13].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8[6] -> *12[7] -> 13[8] , 2 branches - // 4 -> 6 -> 7[6] - //not linked: (9) -> 8[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 7.BlockHeight(), - BlockHash = _blocks[12], - PreviousBlockHash = _blocks[8] - }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[8]); + } - chain.LongestChainHeight.ShouldBe(8.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[13]); + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches + // 5 -> 7[6] + //not linked: (9) -> *10[5] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 5.BlockHeight(), + BlockHash = _blocks[10], + PreviousBlockHash = _blocks[9] + }); - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); - chain.NotLinkedBlocks.ContainsKey(_blocks[11].ToStorageKey()).ShouldBeFalse(); - } + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - { - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[5])).ShouldBeTrue(); - (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( - _blocks[0]); - (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( - _blocks[1]); - (await _chainManager.GetChainBlockIndexAsync(2.BlockHeight())).BlockHash.ShouldBe( - _blocks[2]); - (await _chainManager.GetChainBlockIndexAsync(3.BlockHeight())).BlockHash.ShouldBe( - _blocks[3]); - (await _chainManager.GetChainBlockIndexAsync(4.BlockHeight())).BlockHash.ShouldBe( - _blocks[4]); - (await _chainManager.GetChainBlockIndexAsync(5.BlockHeight())).BlockHash.ShouldBe( - _blocks[5]); - - - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - } - - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8[6] -> 12[7] -> 13[8] , 2 branches - // 5 -> 7[6] -> 11[7] - //not linked: (9) -> 8[5] - // (14) -> 15[9] -> 16[10] -> 17[11] -> 18[12] -> 19[13] -> 20[14] -> 21[15] -> 22[16] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 9.BlockHeight(), - BlockHash = _blocks[15], - PreviousBlockHash = _blocks[14] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 10.BlockHeight(), - BlockHash = _blocks[16], - PreviousBlockHash = _blocks[15] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 11.BlockHeight(), - BlockHash = _blocks[17], - PreviousBlockHash = _blocks[16] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 12.BlockHeight(), - BlockHash = _blocks[18], - PreviousBlockHash = _blocks[17] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 13.BlockHeight(), - BlockHash = _blocks[19], - PreviousBlockHash = _blocks[18] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink - { - Height = 14.BlockHeight(), - BlockHash = _blocks[20], - PreviousBlockHash = _blocks[19] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink - { - Height = 15.BlockHeight(), - BlockHash = _blocks[21], - PreviousBlockHash = _blocks[20] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink - { - Height = 16.BlockHeight(), - BlockHash = _blocks[22], - PreviousBlockHash = _blocks[21] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] -> 12[7] -> 13[8] , 2 branches - // 5 -> 7[6] -> 11[7] -> 14[8] -> 15[9] -> 16[10] -> 17[11] -> 18[12] -> 19[13] -> 20[14] -> 21[15] -> 22[16] - //not linked: (9) -> 8[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink - { - Height = 8.BlockHeight(), - BlockHash = _blocks[14], - PreviousBlockHash = _blocks[11] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHash.ShouldBe(_blocks[22]); - chain.LongestChainHeight.ShouldBe(16.BlockHeight()); - - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); - chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); - - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[11])).ShouldBeTrue(); - chain.LastIrreversibleBlockHash.ShouldBe(_blocks[11]); - chain.LastIrreversibleBlockHeight.ShouldBe(7.BlockHeight()); - (await _chainManager.GetChainBlockIndexAsync(6.BlockHeight())).BlockHash.ShouldBe( - _blocks[7]); - (await _chainManager.GetChainBlockIndexAsync(7.BlockHeight())).BlockHash.ShouldBe( - _blocks[11]); - - (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[13])).ShouldBeFalse(); - - await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[25]) - .ShouldThrowAsync(); - } + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[8]); + + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); } - [Fact] - public async Task Should_Attach_Blocks_To_A_Chain() + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches + // 4 -> 6 -> 7[6] -> *11[7] + //not linked: (9) -> 10[5] { - //0 -> 1 linked - //0 -> 1 -> 5 equals to 0[0] -> 1[1] -> 5[2] - //not linked: (2) -> 3[5] means a block hash 3 at height 5, has a hash 2 previous block, - // but hash 2 block was not in the chain - //*10, *11[12] means just added to the chain + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 7.BlockHeight(), + BlockHash = _blocks[11], + PreviousBlockHash = _blocks[7] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - var chain = await _chainManager.CreateAsync(_genesis); + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[8]); + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); + } - //0 -> *1, no branch + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8 , 2 branches + // 4 -> 6 -> 7 -> 10 + //not linked: (9) -> 8[5] , (12) -> *13[8] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 1.BlockHeight(), - BlockHash = _blocks[1], - PreviousBlockHash = _genesis - }); + Height = 8.BlockHeight(), + BlockHash = _blocks[13], + PreviousBlockHash = _blocks[12] + }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - chain.LongestChainHeight.ShouldBe(1.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[1]); - } + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[8]); - //0 -> 1 -> *2, no branch + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); + chain.NotLinkedBlocks[_blocks[12].ToStorageKey()].ShouldBe(_blocks[13].ToStorageKey()); + } + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8[6] -> *12[7] -> 13[8] , 2 branches + // 4 -> 6 -> 7[6] + //not linked: (9) -> 8[5] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 2.BlockHeight(), - BlockHash = _blocks[2], - PreviousBlockHash = _blocks[1] - }); + Height = 7.BlockHeight(), + BlockHash = _blocks[12], + PreviousBlockHash = _blocks[8] + }); + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + chain.LongestChainHeight.ShouldBe(8.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[13]); - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[10].ToStorageKey()); + chain.NotLinkedBlocks.ContainsKey(_blocks[11].ToStorageKey()).ShouldBeFalse(); + } - //0 -> 1 -> 2, no branch - //not linked: *4 + { + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[5])).ShouldBeTrue(); + (await _chainManager.GetChainBlockIndexAsync(0.BlockHeight())).BlockHash.ShouldBe( + _blocks[0]); + (await _chainManager.GetChainBlockIndexAsync(1.BlockHeight())).BlockHash.ShouldBe( + _blocks[1]); + (await _chainManager.GetChainBlockIndexAsync(2.BlockHeight())).BlockHash.ShouldBe( + _blocks[2]); + (await _chainManager.GetChainBlockIndexAsync(3.BlockHeight())).BlockHash.ShouldBe( + _blocks[3]); + (await _chainManager.GetChainBlockIndexAsync(4.BlockHeight())).BlockHash.ShouldBe( + _blocks[4]); + (await _chainManager.GetChainBlockIndexAsync(5.BlockHeight())).BlockHash.ShouldBe( + _blocks[5]); + + + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + } - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 4.BlockHeight(), - BlockHash = _blocks[4], - PreviousBlockHash = _blocks[3] - }); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 8[6] -> 12[7] -> 13[8] , 2 branches + // 5 -> 7[6] -> 11[7] + //not linked: (9) -> 8[5] + // (14) -> 15[9] -> 16[10] -> 17[11] -> 18[12] -> 19[13] -> 20[14] -> 21[15] -> 22[16] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 9.BlockHeight(), + BlockHash = _blocks[15], + PreviousBlockHash = _blocks[14] + }); - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - //0 -> 1 -> 2, no branch - //not linked: 4, *5 + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[5], - PreviousBlockHash = _blocks[4] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + Height = 10.BlockHeight(), + BlockHash = _blocks[16], + PreviousBlockHash = _blocks[15] + }); - chain.LongestChainHeight.ShouldBe(2.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[2]); - } + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - //0 -> 1 -> 2 -> *3 -> 4 -> 5 + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 3.BlockHeight(), - BlockHash = _blocks[3], - PreviousBlockHash = _blocks[2] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches - // 4 -> *6 - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[6], - PreviousBlockHash = _blocks[4] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches - // 4 -> 6 -> *7 - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 6.BlockHeight(), - BlockHash = _blocks[7], - PreviousBlockHash = _blocks[6] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - } - - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches - // 4 -> 6 -> 7[6] - //not linked: (9) -> *8[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 5.BlockHeight(), - BlockHash = _blocks[8], - PreviousBlockHash = _blocks[9] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(5.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[5]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> *10[6] , 2 branches - // 4 -> 6 -> 7[6] - //not linked: (9) -> 8[5] - { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 6.BlockHeight(), - BlockHash = _blocks[10], - PreviousBlockHash = _blocks[5] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[10]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] , 2 branches - // 4 -> 6 -> 7[6] - //not linked: (9) -> 8[5] , (11) -> *12[8] + Height = 11.BlockHeight(), + BlockHash = _blocks[17], + PreviousBlockHash = _blocks[16] + }); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 8.BlockHeight(), - BlockHash = _blocks[12], - PreviousBlockHash = _blocks[11] - }); - - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(6.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[10]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); - chain.NotLinkedBlocks[_blocks[11].ToStorageKey()].ShouldBe(_blocks[12].ToStorageKey()); - } - - //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] -> *11[7] -> 12[8] , 2 branches - // 4 -> 6 -> 7[6] - //not linked: (9) -> 8[5] + Height = 12.BlockHeight(), + BlockHash = _blocks[18], + PreviousBlockHash = _blocks[17] + }); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 7.BlockHeight(), - BlockHash = _blocks[11], - PreviousBlockHash = _blocks[10] - }); - - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - - chain.LongestChainHeight.ShouldBe(8.BlockHeight()); - chain.LongestChainHash.ShouldBe(_blocks[12]); - - chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); - chain.NotLinkedBlocks.ContainsKey(_blocks[11].ToStorageKey()).ShouldBeFalse(); - } - - // Attach linked block + Height = 13.BlockHeight(), + BlockHash = _blocks[19], + PreviousBlockHash = _blocks[18] + }); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 7.BlockHeight(), - BlockHash = _blocks[11], - PreviousBlockHash = _blocks[10], - IsLinked = true - }).ShouldThrowAsync(); - } - } + Height = 14.BlockHeight(), + BlockHash = _blocks[20], + PreviousBlockHash = _blocks[19] + }); - [Fact] - public async Task Test_Set_Block_Executed() - { - var firstBlockLink = new ChainBlockLink + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 1.BlockHeight(), - BlockHash = _blocks[1], - ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone - }; + Height = 15.BlockHeight(), + BlockHash = _blocks[21], + PreviousBlockHash = _blocks[20] + }); - await _chainManager.SetChainBlockLinkExecutionStatusAsync(firstBlockLink, - ChainBlockLinkExecutionStatus.ExecutionSuccess); - var currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[1]); - currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ExecutionStatus - .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - var secondBlockLink = new ChainBlockLink + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 2.BlockHeight(), - BlockHash = _blocks[2], - ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionSuccess - }; - - _chainManager - .SetChainBlockLinkExecutionStatusAsync(firstBlockLink, ChainBlockLinkExecutionStatus.ExecutionNone) - .ShouldThrow(); - - _chainManager - .SetChainBlockLinkExecutionStatusAsync(secondBlockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess) - .ShouldThrow(); + Height = 16.BlockHeight(), + BlockHash = _blocks[22], + PreviousBlockHash = _blocks[21] + }); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[13]); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); } - - [Fact] - public async Task SetChainBlockLinkExecutionStatuses_Test() + + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] -> 12[7] -> 13[8] , 2 branches + // 5 -> 7[6] -> 11[7] -> 14[8] -> 15[9] -> 16[10] -> 17[11] -> 18[12] -> 19[13] -> 20[14] -> 21[15] -> 22[16] + //not linked: (9) -> 8[5] { - var blockLink1 = new ChainBlockLink + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 1.BlockHeight(), - BlockHash = _blocks[1], - ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone - }; - - var blockLink2 = new ChainBlockLink - { - Height = 2.BlockHeight(), - BlockHash = _blocks[2], - ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone - }; - - await _chainManager - .SetChainBlockLinkExecutionStatusesAsync(new List {blockLink1, blockLink2}, - ChainBlockLinkExecutionStatus.ExecutionNone).ShouldThrowAsync(); - - blockLink1.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; - blockLink2.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionFailed; - await _chainManager - .SetChainBlockLinkExecutionStatusesAsync(new List {blockLink1, blockLink2}, - ChainBlockLinkExecutionStatus.ExecutionSuccess).ShouldThrowAsync(); - - blockLink1.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; - blockLink2.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; - await _chainManager - .SetChainBlockLinkExecutionStatusesAsync(new List {blockLink1, blockLink2}, - ChainBlockLinkExecutionStatus.ExecutionSuccess); - - var currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[1]); - currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ExecutionStatus - .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - - currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[2]); - currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[2]).ExecutionStatus - .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - } + Height = 8.BlockHeight(), + BlockHash = _blocks[14], + PreviousBlockHash = _blocks[11] + }); - [Fact] - public async Task Set_Best_Chain_Test() - { - var chain = await _chainManager.CreateAsync(_genesis); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHash.ShouldBe(_blocks[22]); + chain.LongestChainHeight.ShouldBe(16.BlockHeight()); + + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[5]); + chain.LastIrreversibleBlockHeight.ShouldBe(5.BlockHeight()); + + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[11])).ShouldBeTrue(); + chain.LastIrreversibleBlockHash.ShouldBe(_blocks[11]); + chain.LastIrreversibleBlockHeight.ShouldBe(7.BlockHeight()); + (await _chainManager.GetChainBlockIndexAsync(6.BlockHeight())).BlockHash.ShouldBe( + _blocks[7]); + (await _chainManager.GetChainBlockIndexAsync(7.BlockHeight())).BlockHash.ShouldBe( + _blocks[11]); - await _chainManager.SetBestChainAsync(chain, 1.BlockHeight(), _blocks[1]); - var currentChain = await _chainManager.GetAsync(); - currentChain.BestChainHeight.ShouldBe(1.BlockHeight()); - currentChain.BestChainHash.ShouldBe(_blocks[1]); + (await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[13])).ShouldBeFalse(); - _chainManager.SetBestChainAsync(chain, 0.BlockHeight(), _blocks[1]) - .ShouldThrow(); + await _chainManager.SetIrreversibleBlockAsync(chain, _blocks[25]) + .ShouldThrowAsync(); } + } + + [Fact] + public async Task Should_Attach_Blocks_To_A_Chain() + { + //0 -> 1 linked + //0 -> 1 -> 5 equals to 0[0] -> 1[1] -> 5[2] + //not linked: (2) -> 3[5] means a block hash 3 at height 5, has a hash 2 previous block, + // but hash 2 block was not in the chain + //*10, *11[12] means just added to the chain - [Fact] - public async Task Get_Not_ExecutedBlocks_Test() + + var chain = await _chainManager.CreateAsync(_genesis); + + + //0 -> *1, no branch { - // execution success blocks - var chain = await _chainManager.CreateAsync(_genesis); - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 1.BlockHeight(), BlockHash = _blocks[1], PreviousBlockHash = _genesis }); - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(1.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[1]); + } + + //0 -> 1 -> *2, no branch + + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 2.BlockHeight(), BlockHash = _blocks[2], PreviousBlockHash = _blocks[1] }); - var chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[2]); - chainBlockLinks.Count.ShouldBe(3); - chainBlockLinks[0].BlockHash.ShouldBe(_blocks[0]); - chainBlockLinks[1].BlockHash.ShouldBe(_blocks[1]); - chainBlockLinks[2].BlockHash.ShouldBe(_blocks[2]); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - // execution failed block - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 3.BlockHeight(), - BlockHash = _blocks[3], - PreviousBlockHash = _blocks[2], - }); + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); + } + + //0 -> 1 -> 2, no branch + //not linked: *4 - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 4.BlockHeight(), BlockHash = _blocks[4], - PreviousBlockHash = _blocks[3], - ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionFailed + PreviousBlockHash = _blocks[3] }); - await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); + } + + //0 -> 1 -> 2, no branch + //not linked: 4, *5 + + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 5.BlockHeight(), BlockHash = _blocks[5], PreviousBlockHash = _blocks[4] }); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - //when block 3 is the last one, all blocks status is execution none - chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[3]); - chainBlockLinks.Count.ShouldBe(4); - chainBlockLinks[0].BlockHash.ShouldBe(_blocks[0]); - chainBlockLinks[1].BlockHash.ShouldBe(_blocks[1]); - chainBlockLinks[2].BlockHash.ShouldBe(_blocks[2]); - - - //when block 5 is the last one, as block 4 is executed failed, mean all block 4's previous blocks have been - //executed, and as block 4 is failed, so all block after block 4 is failed. so Count = 0 - chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[5]); - chainBlockLinks.Count.ShouldBe(0); + chain.LongestChainHeight.ShouldBe(2.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[2]); } - [Fact] - public async Task Attach_Forked_Blocks_Test() - { - // execution success blocks - var chain = await _chainManager.CreateAsync(_genesis); + //0 -> 1 -> 2 -> *3 -> 4 -> 5 - // *4[4] - var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 4.BlockHeight(), - BlockHash = _blocks[4], - PreviousBlockHash = _blocks[3] + Height = 3.BlockHeight(), + BlockHash = _blocks[3], + PreviousBlockHash = _blocks[2] }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - // *1[1] ... 4[4] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 1.BlockHeight(), - BlockHash = _blocks[1], - PreviousBlockHash = _genesis - }); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - // 1[1] ... 4[4] -> *5[5] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + } + + //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches + // 4 -> *6 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 5.BlockHeight(), - BlockHash = _blocks[5], + BlockHash = _blocks[6], PreviousBlockHash = _blocks[4] }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + } - // 1[1] -> *2[2] .... 4[4] -> 5[5] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches + // 4 -> 6 -> *7 + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 2.BlockHeight(), - BlockHash = _blocks[2], - PreviousBlockHash = _blocks[1] + Height = 6.BlockHeight(), + BlockHash = _blocks[7], + PreviousBlockHash = _blocks[6] }); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - // 1[1] -> 2[2] -> *3[3] -> 4[4] -> 5[5] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 3.BlockHeight(), - BlockHash = _blocks[3], - PreviousBlockHash = _blocks[2] - }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); - status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); - status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + } - // Attach 4 again - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() - { - Height = 4.BlockHeight(), - BlockHash = _blocks[4], - PreviousBlockHash = _blocks[3] - }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); - // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] - // | -> *10[5] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + //0 -> 1 -> 2 -> 3 -> 4 -> 5 , 2 branches + // 4 -> 6 -> 7[6] + //not linked: (9) -> *8[5] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 5.BlockHeight(), - BlockHash = _blocks[10], - PreviousBlockHash = _blocks[4] + BlockHash = _blocks[8], + PreviousBlockHash = _blocks[9] }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> *6[6] - // | -> 10[5] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + chain.LongestChainHeight.ShouldBe(5.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[5]); + + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); + } + + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> *10[6] , 2 branches + // 4 -> 6 -> 7[6] + //not linked: (9) -> 8[5] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 6.BlockHeight(), - BlockHash = _blocks[6], + BlockHash = _blocks[10], PreviousBlockHash = _blocks[5] }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); - // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> 6[6] - // | -> 10[5] -> *11[6] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[10]); + + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); + } + + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] , 2 branches + // 4 -> 6 -> 7[6] + //not linked: (9) -> 8[5] , (11) -> *12[8] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 6.BlockHeight(), - BlockHash = _blocks[11], - PreviousBlockHash = _blocks[10] + Height = 8.BlockHeight(), + BlockHash = _blocks[12], + PreviousBlockHash = _blocks[11] }); - status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(6.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[10]); - // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> 6[6] -> *7[7] - // | -> 10[5] -> 11[6] - status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink() + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); + chain.NotLinkedBlocks[_blocks[11].ToStorageKey()].ShouldBe(_blocks[12].ToStorageKey()); + } + + //0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 10[6] -> *11[7] -> 12[8] , 2 branches + // 4 -> 6 -> 7[6] + //not linked: (9) -> 8[5] + { + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { Height = 7.BlockHeight(), - BlockHash = _blocks[7], - PreviousBlockHash = _blocks[6] + BlockHash = _blocks[11], + PreviousBlockHash = _blocks[10] }); + + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + chain.LongestChainHeight.ShouldBe(8.BlockHeight()); + chain.LongestChainHash.ShouldBe(_blocks[12]); + + chain.NotLinkedBlocks[_blocks[9].ToStorageKey()].ShouldBe(_blocks[8].ToStorageKey()); + chain.NotLinkedBlocks.ContainsKey(_blocks[11].ToStorageKey()).ShouldBeFalse(); } - [Fact] - public async Task ChainBlockLinkCache_Test() + // Attach linked block { - var chainBlockLink = new ChainBlockLink - { - Height = 1.BlockHeight(), - BlockHash = _blocks[1] - }; - - (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBeNull(); - _chainManager.GetCachedChainBlockLinks().ShouldBeEmpty(); - _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ShouldBeNull(); - - await _chainManager.SetChainBlockLinkAsync(chainBlockLink); - - (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBe(chainBlockLink); - _chainManager.GetCachedChainBlockLinks().Count.ShouldBe(1); - _chainManager.GetCachedChainBlockLinks().ShouldContain(chainBlockLink); - _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ShouldBe(chainBlockLink); - - await _chainManager.SetChainBlockLinkAsync(new ChainBlockLink + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink { - Height = 2.BlockHeight(), - BlockHash = _blocks[2] - }); - - _chainManager.GetCachedChainBlockLinks().Count.ShouldBe(2); - _chainManager.CleanCachedChainBlockLinks(2.BlockHeight()); - _chainManager.GetCachedChainBlockLinks().ShouldBeEmpty(); - - (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBe(chainBlockLink); + Height = 7.BlockHeight(), + BlockHash = _blocks[11], + PreviousBlockHash = _blocks[10], + IsLinked = true + }).ShouldThrowAsync(); } } + + [Fact] + public async Task Test_Set_Block_Executed() + { + var firstBlockLink = new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1], + ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone + }; + + await _chainManager.SetChainBlockLinkExecutionStatusAsync(firstBlockLink, + ChainBlockLinkExecutionStatus.ExecutionSuccess); + var currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[1]); + currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ExecutionStatus + .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + + var secondBlockLink = new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2], + ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionSuccess + }; + + _chainManager + .SetChainBlockLinkExecutionStatusAsync(firstBlockLink, ChainBlockLinkExecutionStatus.ExecutionNone) + .ShouldThrow(); + + _chainManager + .SetChainBlockLinkExecutionStatusAsync(secondBlockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess) + .ShouldThrow(); + } + + [Fact] + public async Task SetChainBlockLinkExecutionStatuses_Test() + { + var blockLink1 = new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1], + ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone + }; + + var blockLink2 = new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2], + ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone + }; + + await _chainManager + .SetChainBlockLinkExecutionStatusesAsync(new List { blockLink1, blockLink2 }, + ChainBlockLinkExecutionStatus.ExecutionNone).ShouldThrowAsync(); + + blockLink1.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; + blockLink2.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionFailed; + await _chainManager + .SetChainBlockLinkExecutionStatusesAsync(new List { blockLink1, blockLink2 }, + ChainBlockLinkExecutionStatus.ExecutionSuccess).ShouldThrowAsync(); + + blockLink1.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; + blockLink2.ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionNone; + await _chainManager + .SetChainBlockLinkExecutionStatusesAsync(new List { blockLink1, blockLink2 }, + ChainBlockLinkExecutionStatus.ExecutionSuccess); + + var currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[1]); + currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ExecutionStatus + .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + + currentBlockLink = await _chainManager.GetChainBlockLinkAsync(_blocks[2]); + currentBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[2]).ExecutionStatus + .ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + } + + [Fact] + public async Task Set_Best_Chain_Test() + { + var chain = await _chainManager.CreateAsync(_genesis); + + await _chainManager.SetBestChainAsync(chain, 1.BlockHeight(), _blocks[1]); + var currentChain = await _chainManager.GetAsync(); + currentChain.BestChainHeight.ShouldBe(1.BlockHeight()); + currentChain.BestChainHash.ShouldBe(_blocks[1]); + + _chainManager.SetBestChainAsync(chain, 0.BlockHeight(), _blocks[1]) + .ShouldThrow(); + } + + [Fact] + public async Task Get_Not_ExecutedBlocks_Test() + { + // execution success blocks + var chain = await _chainManager.CreateAsync(_genesis); + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1], + PreviousBlockHash = _genesis + }); + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2], + PreviousBlockHash = _blocks[1] + }); + + var chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[2]); + chainBlockLinks.Count.ShouldBe(3); + chainBlockLinks[0].BlockHash.ShouldBe(_blocks[0]); + chainBlockLinks[1].BlockHash.ShouldBe(_blocks[1]); + chainBlockLinks[2].BlockHash.ShouldBe(_blocks[2]); + + // execution failed block + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 3.BlockHeight(), + BlockHash = _blocks[3], + PreviousBlockHash = _blocks[2] + }); + + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 4.BlockHeight(), + BlockHash = _blocks[4], + PreviousBlockHash = _blocks[3], + ExecutionStatus = ChainBlockLinkExecutionStatus.ExecutionFailed + }); + + await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 5.BlockHeight(), + BlockHash = _blocks[5], + PreviousBlockHash = _blocks[4] + }); + + + //when block 3 is the last one, all blocks status is execution none + chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[3]); + chainBlockLinks.Count.ShouldBe(4); + chainBlockLinks[0].BlockHash.ShouldBe(_blocks[0]); + chainBlockLinks[1].BlockHash.ShouldBe(_blocks[1]); + chainBlockLinks[2].BlockHash.ShouldBe(_blocks[2]); + + + //when block 5 is the last one, as block 4 is executed failed, mean all block 4's previous blocks have been + //executed, and as block 4 is failed, so all block after block 4 is failed. so Count = 0 + chainBlockLinks = await _chainManager.GetNotExecutedBlocks(_blocks[5]); + chainBlockLinks.Count.ShouldBe(0); + } + + [Fact] + public async Task Attach_Forked_Blocks_Test() + { + // execution success blocks + var chain = await _chainManager.CreateAsync(_genesis); + + // *4[4] + var status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 4.BlockHeight(), + BlockHash = _blocks[4], + PreviousBlockHash = _blocks[3] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + + // *1[1] ... 4[4] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1], + PreviousBlockHash = _genesis + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + // 1[1] ... 4[4] -> *5[5] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 5.BlockHeight(), + BlockHash = _blocks[5], + PreviousBlockHash = _blocks[4] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + + // 1[1] -> *2[2] .... 4[4] -> 5[5] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2], + PreviousBlockHash = _blocks[1] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + // 1[1] -> 2[2] -> *3[3] -> 4[4] -> 5[5] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 3.BlockHeight(), + BlockHash = _blocks[3], + PreviousBlockHash = _blocks[2] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlocksLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + // Attach 4 again + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 4.BlockHeight(), + BlockHash = _blocks[4], + PreviousBlockHash = _blocks[3] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + + // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] + // | -> *10[5] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 5.BlockHeight(), + BlockHash = _blocks[10], + PreviousBlockHash = _blocks[4] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + + // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> *6[6] + // | -> 10[5] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 6.BlockHeight(), + BlockHash = _blocks[6], + PreviousBlockHash = _blocks[5] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + + // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> 6[6] + // | -> 10[5] -> *11[6] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 6.BlockHeight(), + BlockHash = _blocks[11], + PreviousBlockHash = _blocks[10] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.NewBlockLinked); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.LongestChainFound); + + // 1[1] -> 2[2] -> 3[3] -> 4[4] -> 5[5] -> 6[6] -> *7[7] + // | -> 10[5] -> 11[6] + status = await _chainManager.AttachBlockToChainAsync(chain, new ChainBlockLink + { + Height = 7.BlockHeight(), + BlockHash = _blocks[7], + PreviousBlockHash = _blocks[6] + }); + status.ShouldHaveFlag(BlockAttachOperationStatus.LongestChainFound); + status.ShouldNotHaveFlag(BlockAttachOperationStatus.NewBlockNotLinked); + } + + [Fact] + public async Task ChainBlockLinkCache_Test() + { + var chainBlockLink = new ChainBlockLink + { + Height = 1.BlockHeight(), + BlockHash = _blocks[1] + }; + + (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBeNull(); + _chainManager.GetCachedChainBlockLinks().ShouldBeEmpty(); + _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ShouldBeNull(); + + await _chainManager.SetChainBlockLinkAsync(chainBlockLink); + + (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBe(chainBlockLink); + _chainManager.GetCachedChainBlockLinks().Count.ShouldBe(1); + _chainManager.GetCachedChainBlockLinks().ShouldContain(chainBlockLink); + _chainBlockLinkCacheProvider.GetChainBlockLink(_blocks[1]).ShouldBe(chainBlockLink); + + await _chainManager.SetChainBlockLinkAsync(new ChainBlockLink + { + Height = 2.BlockHeight(), + BlockHash = _blocks[2] + }); + + _chainManager.GetCachedChainBlockLinks().Count.ShouldBe(2); + _chainManager.CleanCachedChainBlockLinks(2.BlockHeight()); + _chainManager.GetCachedChainBlockLinks().ShouldBeEmpty(); + + (await _chainManager.GetChainBlockLinkAsync(_blocks[1])).ShouldBe(chainBlockLink); + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/TransactionManagerTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/TransactionManagerTests.cs index 8004ee2d59..9d4f3a1ded 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Domain/TransactionManagerTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Domain/TransactionManagerTests.cs @@ -1,55 +1,49 @@ -using System.Security.Cryptography; -using System.Threading.Tasks; -using AElf.Types; -using Xunit; -using Shouldly; +namespace AElf.Kernel.Blockchain.Domain; -namespace AElf.Kernel.Blockchain.Domain +[Trait("Category", AElfBlockchainModule)] +public sealed class TransactionManagerTests : AElfKernelTestBase { - public sealed class TransactionManagerTests : AElfKernelTestBase + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionManager _transactionManager; + + public TransactionManagerTests() + { + _transactionManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public async Task Insert_Transaction_Test() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + var hash = await _transactionManager.AddTransactionAsync(transaction); + hash.ShouldNotBeNull(); + } + + [Fact] + public async Task Insert_MultipleTx_Test() { - private ITransactionManager _transactionManager; - private KernelTestHelper _kernelTestHelper; - - public TransactionManagerTests() - { - _transactionManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } - - [Fact] - public async Task Insert_Transaction_Test() - { - var transaction = _kernelTestHelper.GenerateTransaction(); - var hash = await _transactionManager.AddTransactionAsync(transaction); - hash.ShouldNotBeNull(); - } - - [Fact] - public async Task Insert_MultipleTx_Test() - { - var t1 = _kernelTestHelper.GenerateTransaction(1, HashHelper.ComputeFrom("tx1")); - var t2 = _kernelTestHelper.GenerateTransaction(2, HashHelper.ComputeFrom("tx2")); - var key1 = await _transactionManager.AddTransactionAsync(t1); - var key2 = await _transactionManager.AddTransactionAsync(t2); - Assert.NotEqual(key1, key2); - } - - [Fact] - public async Task Remove_Transaction_Test() - { - var t1 = _kernelTestHelper.GenerateTransaction(1, HashHelper.ComputeFrom("tx1")); - var t2 = _kernelTestHelper.GenerateTransaction(2, HashHelper.ComputeFrom("tx2")); - - var key1 = await _transactionManager.AddTransactionAsync(t1); - var key2 = await _transactionManager.AddTransactionAsync(t2); - - var td1 = await _transactionManager.GetTransactionAsync(key1); - Assert.Equal(t1, td1); - - await _transactionManager.RemoveTransactionAsync(key2); - var td2 = await _transactionManager.GetTransactionAsync(key2); - Assert.Null(td2); - } + var t1 = _kernelTestHelper.GenerateTransaction(1, HashHelper.ComputeFrom("tx1")); + var t2 = _kernelTestHelper.GenerateTransaction(2, HashHelper.ComputeFrom("tx2")); + var key1 = await _transactionManager.AddTransactionAsync(t1); + var key2 = await _transactionManager.AddTransactionAsync(t2); + Assert.NotEqual(key1, key2); + } + + [Fact] + public async Task Remove_Transaction_Test() + { + var t1 = _kernelTestHelper.GenerateTransaction(1, HashHelper.ComputeFrom("tx1")); + var t2 = _kernelTestHelper.GenerateTransaction(2, HashHelper.ComputeFrom("tx2")); + + var key1 = await _transactionManager.AddTransactionAsync(t1); + var key2 = await _transactionManager.AddTransactionAsync(t2); + + var td1 = await _transactionManager.GetTransactionAsync(key1); + Assert.Equal(t1, td1); + + await _transactionManager.RemoveTransactionAsync(key2); + var td2 = await _transactionManager.GetTransactionAsync(key2); + Assert.Null(td2); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/StorageKeyExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/StorageKeyExtensionsTests.cs index 7668f562fe..6cbe9d6244 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/StorageKeyExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/StorageKeyExtensionsTests.cs @@ -1,28 +1,25 @@ using AElf.Kernel.Infrastructure; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Blockchain.Infrastructure +namespace AElf.Kernel.Blockchain.Infrastructure; + +[Trait("Category", AElfBlockchainModule)] +public class StorageKeyExtensionsTests : AElfKernelTestBase { - public class StorageKeyExtensionsTests + [Fact] + public void ToStorageKeyTest() { - [Fact] - public void ToStorageKeyTest() - { - var intNum = 1; - long longNum = intNum; - ulong ulongNum = 1; - var numString = "1"; - longNum.ToStorageKey().ShouldBe(numString); - intNum.ToStorageKey().ShouldBe(numString); - ulongNum.ToStorageKey().ShouldBe(numString); - var numToHash = HashHelper.ComputeFrom(intNum); - numToHash.ToStorageKey().ShouldBe(numToHash.Value.ToBase64()); - var byteString = numToHash.ToByteString(); - byteString.ToStorageKey().ShouldBe(byteString.ToBase64()); - var address = SampleAddress.AddressList[0]; - address.ToStorageKey().ShouldBe(address.ToBase58()); - } + const int intNum = 1; + const long longNum = intNum; + const ulong ulongNum = 1; + const string numString = "1"; + longNum.ToStorageKey().ShouldBe(numString); + intNum.ToStorageKey().ShouldBe(numString); + ulongNum.ToStorageKey().ShouldBe(numString); + var numToHash = HashHelper.ComputeFrom(intNum); + numToHash.ToStorageKey().ShouldBe(numToHash.Value.ToBase64()); + var byteString = numToHash.ToByteString(); + byteString.ToStorageKey().ShouldBe(byteString.ToBase64()); + var address = SampleAddress.AddressList[0]; + address.ToStorageKey().ShouldBe(address.ToBase58()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/TransactionBlockIndexCacheProviderTests.cs b/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/TransactionBlockIndexCacheProviderTests.cs index 00c8b6c0f0..7790086eb2 100644 --- a/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/TransactionBlockIndexCacheProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/Blockchain/Infrastructure/TransactionBlockIndexCacheProviderTests.cs @@ -1,130 +1,127 @@ -using AElf.Types; -using Shouldly; -using Xunit; +namespace AElf.Kernel.Blockchain.Infrastructure; -namespace AElf.Kernel.Blockchain.Infrastructure +[Trait("Category", AElfBlockchainModule)] +public class TransactionBlockIndexCacheProviderTests : AElfKernelTestBase { - public class TransactionBlockIndexCacheProviderTests : AElfKernelTestBase - { - private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; + private readonly ITransactionBlockIndexProvider _transactionBlockIndexProvider; - public TransactionBlockIndexCacheProviderTests() - { - _transactionBlockIndexProvider = GetRequiredService(); - } + public TransactionBlockIndexCacheProviderTests() + { + _transactionBlockIndexProvider = GetRequiredService(); + } - [Fact] - public void TransactionBlockIndexCacheTest() + [Fact] + public void TransactionBlockIndexCacheTest() + { + var txId1 = HashHelper.ComputeFrom("TxId1"); + var transactionBlockIndex1 = new TransactionBlockIndex { - var txId1 = HashHelper.ComputeFrom("TxId1"); - var transactionBlockIndex1 = new TransactionBlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 100 - }; - - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId1, transactionBlockIndex1); - var getResult = _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cachedTransactionBlockIndex); - getResult.ShouldBeTrue(); - cachedTransactionBlockIndex.ShouldBe(transactionBlockIndex1); - - var txId2 = HashHelper.ComputeFrom("TxId2"); - var transactionBlockIndex2 = new TransactionBlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash2"), - BlockHeight = 101, - PreviousExecutionBlockIndexList = - { - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), BlockHeight = 100} - } - }; - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId2, transactionBlockIndex2); + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 100 + }; - var txId3 = HashHelper.ComputeFrom("TxId3"); - var transactionBlockIndex3 = new TransactionBlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash3"), - BlockHeight = 101, - PreviousExecutionBlockIndexList = - { - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash2"), BlockHeight = 102}, - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash3"), BlockHeight = 103} - } - }; - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId3, transactionBlockIndex3); - - var transactionBlockIndex4 = new TransactionBlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash4"), - BlockHeight = 104, - PreviousExecutionBlockIndexList = - { - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash1"), BlockHeight = 101}, - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash2"), BlockHeight = 102}, - new BlockIndex {BlockHash = HashHelper.ComputeFrom("PreviousBlockHash3"), BlockHeight = 103} - } - }; - _transactionBlockIndexProvider.AddTransactionBlockIndex(txId3, transactionBlockIndex4); + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId1, transactionBlockIndex1); + var getResult = + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cachedTransactionBlockIndex); + getResult.ShouldBeTrue(); + cachedTransactionBlockIndex.ShouldBe(transactionBlockIndex1); + var txId2 = HashHelper.ComputeFrom("TxId2"); + var transactionBlockIndex2 = new TransactionBlockIndex + { + BlockHash = HashHelper.ComputeFrom("BlockHash2"), + BlockHeight = 101, + PreviousExecutionBlockIndexList = { - _transactionBlockIndexProvider.CleanByHeight(99); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBe(transactionBlockIndex1); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBe(transactionBlockIndex2); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), BlockHeight = 100 } } + }; + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId2, transactionBlockIndex2); + var txId3 = HashHelper.ComputeFrom("TxId3"); + var transactionBlockIndex3 = new TransactionBlockIndex + { + BlockHash = HashHelper.ComputeFrom("BlockHash3"), + BlockHeight = 101, + PreviousExecutionBlockIndexList = { - _transactionBlockIndexProvider.CleanByHeight(100); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBe(transactionBlockIndex2); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash2"), BlockHeight = 102 }, + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash3"), BlockHeight = 103 } } + }; + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId3, transactionBlockIndex3); + var transactionBlockIndex4 = new TransactionBlockIndex + { + BlockHash = HashHelper.ComputeFrom("BlockHash4"), + BlockHeight = 104, + PreviousExecutionBlockIndexList = { - _transactionBlockIndexProvider.CleanByHeight(101); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash1"), BlockHeight = 101 }, + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash2"), BlockHeight = 102 }, + new BlockIndex { BlockHash = HashHelper.ComputeFrom("PreviousBlockHash3"), BlockHeight = 103 } } + }; + _transactionBlockIndexProvider.AddTransactionBlockIndex(txId3, transactionBlockIndex4); - { - _transactionBlockIndexProvider.CleanByHeight(102); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldBe(transactionBlockIndex4); - } + { + _transactionBlockIndexProvider.CleanByHeight(99); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBe(transactionBlockIndex1); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBe(transactionBlockIndex2); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + } - { - _transactionBlockIndexProvider.CleanByHeight(103); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldNotBeNull(); - } - - { - _transactionBlockIndexProvider.CleanByHeight(104); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); - cacheBlockIndex1.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); - cacheBlockIndex2.ShouldBeNull(); - _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); - cacheBlockIndex3.ShouldBeNull(); - } + { + _transactionBlockIndexProvider.CleanByHeight(100); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBe(transactionBlockIndex2); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + } + + { + _transactionBlockIndexProvider.CleanByHeight(101); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + } + + { + _transactionBlockIndexProvider.CleanByHeight(102); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldBe(transactionBlockIndex4); + } + + { + _transactionBlockIndexProvider.CleanByHeight(103); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldNotBeNull(); + } + + { + _transactionBlockIndexProvider.CleanByHeight(104); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId1, out var cacheBlockIndex1); + cacheBlockIndex1.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId2, out var cacheBlockIndex2); + cacheBlockIndex2.ShouldBeNull(); + _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId3, out var cacheBlockIndex3); + cacheBlockIndex3.ShouldBeNull(); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/BlockBodyExtensionsTest.cs b/test/AElf.Kernel.Core.Tests/Extensions/BlockBodyExtensionsTest.cs index c15e7cf783..883d50dab8 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/BlockBodyExtensionsTest.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/BlockBodyExtensionsTest.cs @@ -1,38 +1,34 @@ -using AElf.Types; -using Shouldly; -using Xunit; +namespace AElf.Kernel; -namespace AElf.Kernel +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockBodyExtensionsTest : AElfKernelTestBase { - public class BlockBodyExtensionsTest : AElfKernelTestBase + private readonly KernelTestHelper _kernelTestHelper; + + public BlockBodyExtensionsTest() { - private readonly KernelTestHelper _kernelTestHelper; + _kernelTestHelper = GetRequiredService(); + } - public BlockBodyExtensionsTest() - { - _kernelTestHelper = GetRequiredService(); - } + [Fact] + public void BlockBody_Test() + { + var blockBody = new BlockBody(); + blockBody.CalculateMerkleTreeRoot().ShouldBe(Hash.Empty); - [Fact] - public void BlockBody_Test() - { - var blockBody = new BlockBody(); - blockBody.CalculateMerkleTreeRoot().ShouldBe(Hash.Empty); + var transaction1 = _kernelTestHelper.GenerateTransaction(); + var transaction2 = _kernelTestHelper.GenerateTransaction(); + var transaction3 = _kernelTestHelper.GenerateTransaction(); - var transaction1 = _kernelTestHelper.GenerateTransaction(); - var transaction2 = _kernelTestHelper.GenerateTransaction(); - var transaction3 = _kernelTestHelper.GenerateTransaction(); + blockBody.AddTransaction(transaction1); + blockBody.TransactionIds.Count.ShouldBe(1); + blockBody.TransactionIds.ShouldContain(transaction1.GetHash()); - blockBody.AddTransaction(transaction1); - blockBody.TransactionIds.Count.ShouldBe(1); - blockBody.TransactionIds.ShouldContain(transaction1.GetHash()); + blockBody.AddTransactions(new[] { transaction2.GetHash(), transaction3.GetHash() }); + blockBody.TransactionIds.Count.ShouldBe(3); + blockBody.TransactionIds.ShouldContain(transaction2.GetHash()); + blockBody.TransactionIds.ShouldContain(transaction3.GetHash()); - blockBody.AddTransactions(new[] {transaction2.GetHash(), transaction3.GetHash()}); - blockBody.TransactionIds.Count.ShouldBe(3); - blockBody.TransactionIds.ShouldContain(transaction2.GetHash()); - blockBody.TransactionIds.ShouldContain(transaction3.GetHash()); - - blockBody.CalculateMerkleTreeRoot().ShouldBe(BinaryMerkleTree.FromLeafNodes(blockBody.TransactionIds).Root); - } + blockBody.CalculateMerkleTreeRoot().ShouldBe(BinaryMerkleTree.FromLeafNodes(blockBody.TransactionIds).Root); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/BlockExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Extensions/BlockExtensionsTests.cs index b778cdb050..6f9e450268 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/BlockExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/BlockExtensionsTests.cs @@ -1,72 +1,67 @@ using System.Collections.Generic; using AElf.Cryptography; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Virgil.Crypto; -using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockExtensionsTests : AElfKernelTestBase { - public class BlockExtensionsTests : AElfKernelTestBase + private readonly KernelTestHelper _kernelTestHelper; + + public BlockExtensionsTests() + { + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public void VerifySignature_Test() { - private readonly KernelTestHelper _kernelTestHelper; - - public BlockExtensionsTests() { - _kernelTestHelper = GetRequiredService(); + var block = GenerateBlock(); + block.Header.Height = -1; + block.VerifySignature().ShouldBeFalse(); + } + + { + var block = GenerateBlock(); + block.Body.TransactionIds.Clear(); + block.VerifySignature().ShouldBeFalse(); + } + + { + var block = GenerateBlock(); + block.Header.Signature = ByteString.Empty; + block.VerifySignature().ShouldBeFalse(); } - - [Fact] - public void VerifySignature_Test() + + { + var block = GenerateBlock(); + block.Header.Signature = ByteString.CopyFromUtf8("Signature"); + block.VerifySignature().ShouldBeFalse(); + } + { - { - var block = GenerateBlock(); - block.Header.Height = -1; - block.VerifySignature().ShouldBeFalse(); - } - - { - var block = GenerateBlock(); - block.Body.TransactionIds.Clear(); - block.VerifySignature().ShouldBeFalse(); - } - - { - var block = GenerateBlock(); - block.Header.Signature = ByteString.Empty; - block.VerifySignature().ShouldBeFalse(); - } - - { - var block = GenerateBlock(); - block.Header.Signature = ByteString.CopyFromUtf8("Signature"); - block.VerifySignature().ShouldBeFalse(); - } - - { - var block = GenerateBlock(); - block.Header.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); - block.VerifySignature().ShouldBeFalse(); - } - - { - var block = GenerateBlock(); - block.VerifySignature().ShouldBeTrue(); - } + var block = GenerateBlock(); + block.Header.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); + block.VerifySignature().ShouldBeFalse(); } - private Block GenerateBlock() { - var transaction = _kernelTestHelper.GenerateTransaction(); - var block = _kernelTestHelper.GenerateBlock(10, HashHelper.ComputeFrom("PreviousBlockHash"), - new List {transaction}); - - block.Header.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - block.GetHash().ToByteArray())); - - return block; + var block = GenerateBlock(); + block.VerifySignature().ShouldBeTrue(); } } + + private Block GenerateBlock() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + var block = _kernelTestHelper.GenerateBlock(10, HashHelper.ComputeFrom("PreviousBlockHash"), + new List { transaction }); + + block.Header.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + block.GetHash().ToByteArray())); + + return block; + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/BlockHeaderExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Extensions/BlockHeaderExtensionsTests.cs index 7f05306021..cb2bd9fe4c 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/BlockHeaderExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/BlockHeaderExtensionsTests.cs @@ -1,28 +1,25 @@ using System; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockHeaderExtensionsTests : AElfKernelTestBase { - public class BlockHeaderExtensionsTests : AElfKernelTestBase + private readonly KernelTestHelper _kernelTestHelper; + + public BlockHeaderExtensionsTests() + { + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public void BlockHeader_Test() { - private readonly KernelTestHelper _kernelTestHelper; - - public BlockHeaderExtensionsTests() - { - _kernelTestHelper = GetRequiredService(); - } + var blockHeader = _kernelTestHelper.GenerateBlock(1, Hash.Empty).Header; - [Fact] - public void BlockHeader_Test() - { - var blockHeader = _kernelTestHelper.GenerateBlock(1, Hash.Empty).Header; - - blockHeader.GetDisambiguatingHash().ShouldBe(blockHeader.GetHash()); + blockHeader.GetDisambiguatingHash().ShouldBe(blockHeader.GetHash()); - blockHeader.MerkleTreeRootOfTransactions = null; - Assert.Throws(blockHeader.GetDisambiguatingHash); - } + blockHeader.MerkleTreeRootOfTransactions = null; + Assert.Throws(blockHeader.GetDisambiguatingHash); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/BlockStateSetExtensionTest.cs b/test/AElf.Kernel.Core.Tests/Extensions/BlockStateSetExtensionTest.cs index 40a04aefba..9dd87f0507 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/BlockStateSetExtensionTest.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/BlockStateSetExtensionTest.cs @@ -1,40 +1,36 @@ -using Google.Protobuf; -using Shouldly; -using Xunit; +namespace AElf.Kernel; -namespace AElf.Kernel +[Trait("Category", AElfBlockchainModule)] +public class BlockStateSetExtensionTest : AElfKernelTestBase { - public class BlockStateSetExtensionTest : AElfKernelTestBase + [Fact] + public void TryGetState_Test() { - [Fact] - public void TryGetState_Test() - { - var blockStateSet = new BlockStateSet(); - - blockStateSet.TryGetState("key1", out var value).ShouldBeFalse(); - - blockStateSet.Deletes.Add("key1"); - blockStateSet.TryGetState("key1", out value).ShouldBeTrue(); - value.ShouldBeNull(); + var blockStateSet = new BlockStateSet(); - blockStateSet.Changes.Add("key1", ByteString.CopyFromUtf8("key1")); - blockStateSet.TryGetState("key1", out value).ShouldBeTrue(); - value.ShouldBeNull(); - - blockStateSet.Changes.Add("key2", ByteString.CopyFromUtf8("key2")); - blockStateSet.TryGetState("key2", out value).ShouldBeTrue(); - value.ShouldBe(ByteString.CopyFromUtf8("key2")); - } + blockStateSet.TryGetState("key1", out var value).ShouldBeFalse(); - [Fact] - public void TryGetExecutedCache_Test() - { - var blockStateSet = new BlockStateSet(); - blockStateSet.TryGetExecutedCache("key1", out var value).ShouldBeFalse(); - - blockStateSet.BlockExecutedData.Add("key1",ByteString.CopyFromUtf8("key1")); - blockStateSet.TryGetExecutedCache("key1", out value).ShouldBeTrue(); - value.ShouldBe(ByteString.CopyFromUtf8("key1")); - } + blockStateSet.Deletes.Add("key1"); + blockStateSet.TryGetState("key1", out value).ShouldBeTrue(); + value.ShouldBeNull(); + + blockStateSet.Changes.Add("key1", ByteString.CopyFromUtf8("key1")); + blockStateSet.TryGetState("key1", out value).ShouldBeTrue(); + value.ShouldBeNull(); + + blockStateSet.Changes.Add("key2", ByteString.CopyFromUtf8("key2")); + blockStateSet.TryGetState("key2", out value).ShouldBeTrue(); + value.ShouldBe(ByteString.CopyFromUtf8("key2")); + } + + [Fact] + public void TryGetExecutedCache_Test() + { + var blockStateSet = new BlockStateSet(); + blockStateSet.TryGetExecutedCache("key1", out var value).ShouldBeFalse(); + + blockStateSet.BlockExecutedData.Add("key1", ByteString.CopyFromUtf8("key1")); + blockStateSet.TryGetExecutedCache("key1", out value).ShouldBeTrue(); + value.ShouldBe(ByteString.CopyFromUtf8("key1")); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/LogEventExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Extensions/LogEventExtensionsTests.cs index 6fbdae967c..a211015cc1 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/LogEventExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/LogEventExtensionsTests.cs @@ -1,40 +1,35 @@ -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Xunit; +namespace AElf.Kernel; -namespace AElf.Kernel.Extensions +[Trait("Category", AElfBlockchainModule)] +public class LogEventExtensionsTests : AElfKernelTestBase { - public class LogEventExtensionsTests + [Fact] + public void LogEvent_GetBloomAndCompare() { - [Fact] - public void LogEvent_GetBloomAndCompare() + var address = SampleAddress.AddressList[0]; + var logEvent = new LogEvent { - var address = SampleAddress.AddressList[0]; - var logEvent = new LogEvent() + Address = address, + Indexed = { - Address = address, - Indexed = - { - ByteString.CopyFromUtf8("event1") - } - }; - var bloom = logEvent.GetBloom(); - bloom.Data.ShouldNotBeNull(); - - var logEvent1 = new LogEvent() + ByteString.CopyFromUtf8("event1") + } + }; + var bloom = logEvent.GetBloom(); + bloom.Data.ShouldNotBeNull(); + + var logEvent1 = new LogEvent + { + Address = address, + Indexed = { - Address = address, - Indexed = - { - ByteString.CopyFromUtf8("event1"), - ByteString.CopyFromUtf8("event2"), - } - }; - var bloom1 = logEvent1.GetBloom(); - bloom1.Data.ShouldNotBeNull(); + ByteString.CopyFromUtf8("event1"), + ByteString.CopyFromUtf8("event2") + } + }; + var bloom1 = logEvent1.GetBloom(); + bloom1.Data.ShouldNotBeNull(); - bloom.IsIn(bloom1).ShouldBeTrue(); - } + bloom.IsIn(bloom1).ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/TransactionExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Extensions/TransactionExtensionsTests.cs index 632623af6a..daa6331365 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/TransactionExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/TransactionExtensionsTests.cs @@ -1,53 +1,49 @@ -using System; using System.Linq; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +[Trait("Category", AElfBlockchainModule)] +public sealed class TransactionExtensionsTests : AElfKernelTestBase { - public class TransactionExtensionsTests : AElfKernelTestBase + private readonly KernelTestHelper _kernelTestHelper; + + public TransactionExtensionsTests() + { + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public void Size_Test() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + transaction.Size().ShouldBe(transaction.CalculateSize()); + } + + [Fact] + public void VerifySignature_Test() + { + var transaction = _kernelTestHelper.GenerateTransaction(); + transaction.MethodName = string.Empty; + transaction.VerifySignature().ShouldBeFalse(); + + transaction = _kernelTestHelper.GenerateTransaction(); + transaction.Signature = ByteString.Empty; + transaction.VerifySignature().ShouldBeFalse(); + + transaction = _kernelTestHelper.GenerateTransaction(); + transaction.From = SampleAddress.AddressList.Last(); + transaction.VerifySignature().ShouldBeFalse(); + + transaction = _kernelTestHelper.GenerateTransaction(); + transaction.VerifySignature().ShouldBeTrue(); + } + + [Fact] + public void VerifyExpiration_Test() { - private readonly KernelTestHelper _kernelTestHelper; - - public TransactionExtensionsTests() - { - _kernelTestHelper = GetRequiredService(); - } - - [Fact] - public void Size_Test() - { - var transaction = _kernelTestHelper.GenerateTransaction(); - transaction.Size().ShouldBe(transaction.CalculateSize()); - } - - [Fact] - public void VerifySignature_Test() - { - var transaction = _kernelTestHelper.GenerateTransaction(); - transaction.MethodName = string.Empty; - transaction.VerifySignature().ShouldBeFalse(); - - transaction = _kernelTestHelper.GenerateTransaction(); - transaction.Signature = ByteString.Empty; - transaction.VerifySignature().ShouldBeFalse(); - - transaction = _kernelTestHelper.GenerateTransaction(); - transaction.From = SampleAddress.AddressList.Last(); - transaction.VerifySignature().ShouldBeFalse(); - - transaction = _kernelTestHelper.GenerateTransaction(); - transaction.VerifySignature().ShouldBeTrue(); - } - - [Fact] - public void VerifyExpiration_Test() - { - var transaction = _kernelTestHelper.GenerateTransaction(100); - transaction.VerifyExpiration(99).ShouldBeFalse(); - transaction.VerifyExpiration(100).ShouldBeTrue(); - transaction.VerifyExpiration(612).ShouldBeFalse(); - } + var transaction = _kernelTestHelper.GenerateTransaction(100); + transaction.VerifyExpiration(99).ShouldBeFalse(); + transaction.VerifyExpiration(100).ShouldBeTrue(); + transaction.VerifyExpiration(612).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/TransactionResultExtensionsTest.cs b/test/AElf.Kernel.Core.Tests/Extensions/TransactionResultExtensionsTest.cs index 24b2bf1dd2..cfc8641b2e 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/TransactionResultExtensionsTest.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/TransactionResultExtensionsTest.cs @@ -1,36 +1,32 @@ using System.Collections.Generic; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +[Trait("Category", AElfBlockchainModule)] +public class TransactionResultExtensionsTest : AElfKernelTestBase { - public class TransactionResultExtensionsTest : AElfKernelTestBase + [Fact] + public void UpdateBloom_Test() { - [Fact] - public void UpdateBloom_Test() + var transactionResult = new TransactionResult(); + + transactionResult.UpdateBloom(); + transactionResult.Bloom.ShouldBe(ByteString.Empty); + + var logEvent1 = new LogEvent + { + Address = SampleAddress.AddressList[0], + Name = "LogEvent1" + }; + var logEvent2 = new LogEvent { - var transactionResult = new TransactionResult(); - - transactionResult.UpdateBloom(); - transactionResult.Bloom.ShouldBe(ByteString.Empty); - - var logEvent1 = new LogEvent - { - Address = SampleAddress.AddressList[0], - Name = "LogEvent1" - }; - var logEvent2 = new LogEvent - { - Address = SampleAddress.AddressList[1], - Name = "LogEvent2" - }; - transactionResult.Logs.Add(new[] {logEvent1, logEvent2}); - transactionResult.UpdateBloom(); - var bloom = new Bloom(); - bloom.Combine(new List {logEvent1.GetBloom(), logEvent2.GetBloom()}); - transactionResult.Bloom.ShouldBe(ByteString.CopyFrom(bloom.Data)); - } + Address = SampleAddress.AddressList[1], + Name = "LogEvent2" + }; + transactionResult.Logs.Add(new[] { logEvent1, logEvent2 }); + transactionResult.UpdateBloom(); + var bloom = new Bloom(); + bloom.Combine(new List { logEvent1.GetBloom(), logEvent2.GetBloom() }); + transactionResult.Bloom.ShouldBe(ByteString.CopyFrom(bloom.Data)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Extensions/TransactionTraceExtensionsTests.cs b/test/AElf.Kernel.Core.Tests/Extensions/TransactionTraceExtensionsTests.cs index e0e7d9edde..2664f7c5fe 100644 --- a/test/AElf.Kernel.Core.Tests/Extensions/TransactionTraceExtensionsTests.cs +++ b/test/AElf.Kernel.Core.Tests/Extensions/TransactionTraceExtensionsTests.cs @@ -1,229 +1,223 @@ using System.Collections.Generic; using System.Linq; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Extensions +namespace AElf.Kernel; + +[Trait("Category", AElfBlockchainModule)] +public class TransactionTraceExtensionsTests : AElfKernelTestBase { - public class TransactionTraceExtensionsTests : AElfKernelTestBase + [Theory] + [InlineData(ExecutionStatus.Executed, true)] + [InlineData(ExecutionStatus.Canceled, false)] + [InlineData(ExecutionStatus.Postfailed, false)] + [InlineData(ExecutionStatus.Prefailed, false)] + [InlineData(ExecutionStatus.Undefined, false)] + [InlineData(ExecutionStatus.ContractError, false)] + [InlineData(ExecutionStatus.SystemError, false)] + [InlineData(ExecutionStatus.ExceededMaxCallDepth, false)] + public void IsSuccessful_Test(ExecutionStatus executionStatus, bool isSuccess) { - [Theory] - [InlineData(ExecutionStatus.Executed, true)] - [InlineData(ExecutionStatus.Canceled, false)] - [InlineData(ExecutionStatus.Postfailed, false)] - [InlineData(ExecutionStatus.Prefailed, false)] - [InlineData(ExecutionStatus.Undefined, false)] - [InlineData(ExecutionStatus.ContractError, false)] - [InlineData(ExecutionStatus.SystemError, false)] - [InlineData(ExecutionStatus.ExceededMaxCallDepth, false)] - public void IsSuccessful_Test(ExecutionStatus executionStatus, bool isSuccess) { + var transactionTrace = new TransactionTrace { - var transactionTrace = new TransactionTrace - { - ExecutionStatus = executionStatus - }; - transactionTrace.IsSuccessful().ShouldBe(isSuccess); - } - - { - var transactionTrace = new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed, - PreTraces = - { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed - }, - new TransactionTrace - { - ExecutionStatus = executionStatus - } - } - }; - transactionTrace.IsSuccessful().ShouldBe(isSuccess); - } - - { - var transactionTrace = new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed, - InlineTraces = - { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed - }, - new TransactionTrace - { - ExecutionStatus = executionStatus - } - } - }; - transactionTrace.IsSuccessful().ShouldBe(isSuccess); - } - - { - var transactionTrace = new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed, - PostTraces = - { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed - }, - new TransactionTrace - { - ExecutionStatus = executionStatus - } - } - }; - transactionTrace.IsSuccessful().ShouldBe(isSuccess); - } + ExecutionStatus = executionStatus + }; + transactionTrace.IsSuccessful().ShouldBe(isSuccess); } - [Fact] - public void GetPluginLogs_Test() { - var logEvents = new List(); - for (int i = 0; i < 5; i++) - { - logEvents.Add(new LogEvent {Name = "LogEvent" + i}); - } - var transactionTrace = new TransactionTrace { + ExecutionStatus = ExecutionStatus.Executed, PreTraces = { new TransactionTrace { - ExecutionStatus = ExecutionStatus.Executed, - Logs = {logEvents[0]} + ExecutionStatus = ExecutionStatus.Executed }, new TransactionTrace { - ExecutionStatus = ExecutionStatus.Canceled, - Logs = {logEvents[1]} + ExecutionStatus = executionStatus } - }, + } + }; + transactionTrace.IsSuccessful().ShouldBe(isSuccess); + } + + { + var transactionTrace = new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, InlineTraces = { new TransactionTrace { - ExecutionStatus = ExecutionStatus.Executed, - Logs = {logEvents[2]} - } - }, - PostTraces = - { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed, - Logs = {logEvents[3]} + ExecutionStatus = ExecutionStatus.Executed }, new TransactionTrace { - ExecutionStatus = ExecutionStatus.Canceled, - Logs = {logEvents[4]} + ExecutionStatus = executionStatus } } }; - - var logs = transactionTrace.GetPluginLogs().ToList(); - logs.Count.ShouldBe(2); - logs.ShouldContain(logEvents[0]); - logs.ShouldContain(logEvents[3]); + transactionTrace.IsSuccessful().ShouldBe(isSuccess); } - [Fact] - public void SurfaceUpError_Test() { var transactionTrace = new TransactionTrace { ExecutionStatus = ExecutionStatus.Executed, - InlineTraces = + PostTraces = { new TransactionTrace { ExecutionStatus = ExecutionStatus.Executed + }, + new TransactionTrace + { + ExecutionStatus = executionStatus } } }; - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldBeEmpty(); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + transactionTrace.IsSuccessful().ShouldBe(isSuccess); + } + } - transactionTrace.ExecutionStatus = ExecutionStatus.Canceled; - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldBeEmpty(); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Canceled); - - transactionTrace = new TransactionTrace + [Fact] + public void GetPluginLogs_Test() + { + var logEvents = new List(); + for (var i = 0; i < 5; i++) logEvents.Add(new LogEvent { Name = "LogEvent" + i }); + + var transactionTrace = new TransactionTrace + { + PreTraces = { - ExecutionStatus = ExecutionStatus.Executed, - InlineTraces = + new TransactionTrace { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.ExceededMaxCallDepth, - Error = "ExceededMaxCallDepth" - } + ExecutionStatus = ExecutionStatus.Executed, + Logs = { logEvents[0] } + }, + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Canceled, + Logs = { logEvents[1] } } - }; - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldContain("ExceededMaxCallDepth"); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.ExceededMaxCallDepth); - - transactionTrace = new TransactionTrace + }, + InlineTraces = { - ExecutionStatus = ExecutionStatus.Prefailed, - PreTraces = + new TransactionTrace { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed - } + ExecutionStatus = ExecutionStatus.Executed, + Logs = { logEvents[2] } } - }; - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldBeEmpty(); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Prefailed); - - transactionTrace.PreTraces.Add(new TransactionTrace + }, + PostTraces = { - ExecutionStatus = ExecutionStatus.Canceled, - Error = "Canceled" - }); - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldContain("Canceled"); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Prefailed); - - transactionTrace = new TransactionTrace + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + Logs = { logEvents[3] } + }, + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Canceled, + Logs = { logEvents[4] } + } + } + }; + + var logs = transactionTrace.GetPluginLogs().ToList(); + logs.Count.ShouldBe(2); + logs.ShouldContain(logEvents[0]); + logs.ShouldContain(logEvents[3]); + } + + [Fact] + public void SurfaceUpError_Test() + { + var transactionTrace = new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + InlineTraces = { - ExecutionStatus = ExecutionStatus.Postfailed, - PostTraces = + new TransactionTrace { - new TransactionTrace - { - ExecutionStatus = ExecutionStatus.Executed - } + ExecutionStatus = ExecutionStatus.Executed } - }; - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldBeEmpty(); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Postfailed); - - transactionTrace.PostTraces.Add(new TransactionTrace + } + }; + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldBeEmpty(); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + + transactionTrace.ExecutionStatus = ExecutionStatus.Canceled; + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldBeEmpty(); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Canceled); + + transactionTrace = new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + InlineTraces = { - ExecutionStatus = ExecutionStatus.Canceled, - Error = "Canceled" - }); - transactionTrace.SurfaceUpError(); - transactionTrace.Error.ShouldContain("Canceled"); - transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Postfailed); - } + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.ExceededMaxCallDepth, + Error = "ExceededMaxCallDepth" + } + } + }; + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldContain("ExceededMaxCallDepth"); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.ExceededMaxCallDepth); + + transactionTrace = new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Prefailed, + PreTraces = + { + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed + } + } + }; + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldBeEmpty(); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Prefailed); + + transactionTrace.PreTraces.Add(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Canceled, + Error = "Canceled" + }); + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldContain("Canceled"); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Prefailed); + + transactionTrace = new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Postfailed, + PostTraces = + { + new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed + } + } + }; + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldBeEmpty(); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Postfailed); + + transactionTrace.PostTraces.Add(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Canceled, + Error = "Canceled" + }); + transactionTrace.SurfaceUpError(); + transactionTrace.Error.ShouldContain("Canceled"); + transactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Postfailed); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/GlobalUsings.cs b/test/AElf.Kernel.Core.Tests/GlobalUsings.cs new file mode 100644 index 0000000000..f6ba93045a --- /dev/null +++ b/test/AElf.Kernel.Core.Tests/GlobalUsings.cs @@ -0,0 +1,5 @@ +global using Xunit; +global using Google.Protobuf; +global using Shouldly; +global using AElf.Types; +global using System.Threading.Tasks; \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/KernelCoreTestAElfModule.cs b/test/AElf.Kernel.Core.Tests/KernelCoreTestAElfModule.cs index b5353a8a0d..5b0fa6d96e 100644 --- a/test/AElf.Kernel.Core.Tests/KernelCoreTestAElfModule.cs +++ b/test/AElf.Kernel.Core.Tests/KernelCoreTestAElfModule.cs @@ -1,89 +1,81 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner.Application; using AElf.Modularity; -using AElf.Types; -using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Moq; using Volo.Abp; using Volo.Abp.EventBus; using Volo.Abp.Modularity; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(AbpEventBusModule), + typeof(TestBaseKernelAElfModule))] +public class KernelCoreTestAElfModule : AElfModule { - [DependsOn( - typeof(AbpEventBusModule), - typeof(TestBaseKernelAElfModule))] - public class KernelCoreTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddTransient(); - services.AddTransient(); - services.AddSingleton(p => Mock.Of()); - } + var services = context.Services; + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(p => Mock.Of()); } - - [DependsOn( - typeof(KernelCoreTestAElfModule))] - public class KernelMinerTestAElfModule : AElfModule +} + +[DependsOn( + typeof(KernelCoreTestAElfModule))] +public class KernelMinerTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - delegate Task> MockGenerateTransactions(Address @from, long preBlockHeight, Hash previousBlockHash); - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + + //For system transaction generator testing + services.AddTransient(provider => { - var services = context.Services; - - //For system transaction generator testing - services.AddTransient(provider => + var transactionList = new List { - var transactionList = new List + new() { - new Transaction() {From = SampleAddress.AddressList[0], To = SampleAddress.AddressList[2], MethodName = "InValue"}, - new Transaction() {From = SampleAddress.AddressList[1], To = SampleAddress.AddressList[3], MethodName = "OutValue"}, - }; - var consensusTransactionGenerator = new Mock(); - consensusTransactionGenerator - .Setup(m => m.GenerateTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(transactionList)); - - return consensusTransactionGenerator.Object; - }); - - //For BlockExtraDataService testing. - services.AddTransient( - builder => + From = SampleAddress.AddressList[0], To = SampleAddress.AddressList[2], MethodName = "InValue" + }, + new() { - var dataProvider = new Mock(); - dataProvider.Setup( m=>m.GetBlockHeaderExtraDataAsync(It.Is(o=>o.Height != 100))) - .Returns(Task.FromResult(ByteString.CopyFromUtf8("not null"))); + From = SampleAddress.AddressList[1], To = SampleAddress.AddressList[3], MethodName = "OutValue" + } + }; + var consensusTransactionGenerator = new Mock(); + consensusTransactionGenerator + .Setup(m => m.GenerateTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(transactionList)); - ByteString bs = null; - dataProvider.Setup( m=>m.GetBlockHeaderExtraDataAsync(It.Is(o => o.Height == 100))) - .Returns(Task.FromResult(bs)); - - dataProvider.Setup(m => m.BlockHeaderExtraDataKey).Returns(nameof(IBlockExtraDataProvider)); - return dataProvider.Object; - }); - } + return consensusTransactionGenerator.Object; + }); - public override void OnPreApplicationInitialization(ApplicationInitializationContext context) - { - } + //For BlockExtraDataService testing. + services.AddTransient( + builder => + { + var dataProvider = new Mock(); + dataProvider.Setup(m => m.GetBlockHeaderExtraDataAsync(It.Is(o => o.Height != 100))) + .Returns(Task.FromResult(ByteString.CopyFromUtf8("not null"))); + + ByteString bs = null; + dataProvider.Setup(m => m.GetBlockHeaderExtraDataAsync(It.Is(o => o.Height == 100))) + .Returns(Task.FromResult(bs)); + + dataProvider.Setup(m => m.BlockHeaderExtraDataKey).Returns(nameof(IBlockExtraDataProvider)); + return dataProvider.Object; + }); } - [DependsOn( - typeof(KernelCoreTestAElfModule))] - public class AccountTestAElfModule : AElfModule + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - } } + + private delegate Task> MockGenerateTransactions(Address from, long preBlockHeight, + Hash previousBlockHash); } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/KernelCoreWithChainTestAElfModule.cs b/test/AElf.Kernel.Core.Tests/KernelCoreWithChainTestAElfModule.cs index dd89f0e914..49d00e29ab 100644 --- a/test/AElf.Kernel.Core.Tests/KernelCoreWithChainTestAElfModule.cs +++ b/test/AElf.Kernel.Core.Tests/KernelCoreWithChainTestAElfModule.cs @@ -4,20 +4,19 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(KernelCoreTestAElfModule))] +public class KernelCoreWithChainTestAElfModule : AElfModule { - [DependsOn( - typeof(KernelCoreTestAElfModule))] - public class KernelCoreWithChainTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var kernelTestHelper = context.ServiceProvider.GetService(); - AsyncHelper.RunSync(() => kernelTestHelper.MockChainAsync()); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var kernelTestHelper = context.ServiceProvider.GetService(); + AsyncHelper.RunSync(() => kernelTestHelper!.MockChainAsync()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionExtraDataProviderTests.cs b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionExtraDataProviderTests.cs index 7c06976dea..d08816f3a8 100644 --- a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionExtraDataProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionExtraDataProviderTests.cs @@ -1,30 +1,30 @@ using AElf.Kernel.Miner.Application; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +[Trait("Category", AElfMinerModule)] +public sealed class SystemTransactionExtraDataProviderTests : AElfMinerTestBase { - public sealed class SystemTransactionExtraDataProviderTests : AElfKernelTestBase + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + + public SystemTransactionExtraDataProviderTests() { - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + _systemTransactionExtraDataProvider = GetRequiredService(); + } - public SystemTransactionExtraDataProviderTests() - { - _systemTransactionExtraDataProvider = GetRequiredService(); - } - - [Fact] - public void SetAndGetSystemTransactionCountTest() - { - var blockHeader = new BlockHeader(); - _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader,out var systemTransactionCount).ShouldBeFalse(); - systemTransactionCount.ShouldBe(0); + [Fact] + public void SetAndGetSystemTransactionCountTest() + { + var blockHeader = new BlockHeader(); + _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader, out var systemTransactionCount) + .ShouldBeFalse(); + systemTransactionCount.ShouldBe(0); - var count = 10; - _systemTransactionExtraDataProvider.SetSystemTransactionCount(count, blockHeader); + var count = 10; + _systemTransactionExtraDataProvider.SetSystemTransactionCount(count, blockHeader); - _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader, out systemTransactionCount).ShouldBeTrue(); - systemTransactionCount.ShouldBe(count); - } + _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockHeader, out systemTransactionCount) + .ShouldBeTrue(); + systemTransactionCount.ShouldBe(count); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionGenerationServiceTests.cs b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionGenerationServiceTests.cs index 50917aecb3..2547a806cf 100644 --- a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionGenerationServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionGenerationServiceTests.cs @@ -1,27 +1,23 @@ -using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Miner.Application; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +[Trait("Category", AElfMinerModule)] +public sealed class SystemTransactionGenerationServiceTests : AElfMinerTestBase { - public class SystemTransactionGenerationServiceTests: AElfMinerTestBase + private readonly ISystemTransactionGenerationService _systemTransactionGenerationService; + + public SystemTransactionGenerationServiceTests() { - private readonly ISystemTransactionGenerationService _systemTransactionGenerationService; - public SystemTransactionGenerationServiceTests() - { - _systemTransactionGenerationService = GetRequiredService(); - } + _systemTransactionGenerationService = GetRequiredService(); + } - [Fact] - public async Task Generate_SystemTransactions_Test() - { - var transactionList = await _systemTransactionGenerationService.GenerateSystemTransactionsAsync( - SampleAddress.AddressList[0], 1L, HashHelper.ComputeFrom("hash")); - transactionList.ShouldNotBeNull(); - transactionList.Count.ShouldBe(2); - } + [Fact] + public async Task Generate_SystemTransactions_Test() + { + var transactionList = await _systemTransactionGenerationService.GenerateSystemTransactionsAsync( + SampleAddress.AddressList[0], 1L, HashHelper.ComputeFrom("hash")); + transactionList.ShouldNotBeNull(); + transactionList.Count.ShouldBe(2); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionValidationProviderTests.cs b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionValidationProviderTests.cs index 46627fed51..6af7538b0c 100644 --- a/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionValidationProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/Miner/SystemTransactionValidationProviderTests.cs @@ -1,78 +1,75 @@ -using System.Threading.Tasks; using AElf.Kernel.Miner.Application; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +[Trait("Category", AElfBlockchainModule)] +public sealed class SystemTransactionValidationProviderTests : AElfKernelWithChainTestBase { - public sealed class SystemTransactionValidationProviderTests : AElfKernelWithChainTestBase + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly SystemTransactionValidationProvider _systemTransactionValidationProvider; + + public SystemTransactionValidationProviderTests() { - private readonly SystemTransactionValidationProvider _systemTransactionValidationProvider; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + _systemTransactionValidationProvider = GetRequiredService(); + _systemTransactionExtraDataProvider = GetRequiredService(); + } - public SystemTransactionValidationProviderTests() - { - _systemTransactionValidationProvider = GetRequiredService(); - _systemTransactionExtraDataProvider = GetRequiredService(); - } - - [Fact] - public async Task ValidateBeforeAttach_WithoutExtraData_Test() + [Fact] + public async Task ValidateBeforeAttach_WithoutExtraData_Test() + { + var block = new Block { - var block = new Block - { - Header = new BlockHeader() - }; - var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateBeforeAttach_WithExtraData_False_Test() + Header = new BlockHeader() + }; + var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + } + + [Fact] + public async Task ValidateBeforeAttach_WithExtraData_False_Test() + { + var block = new Block { - var block = new Block - { - Header = new BlockHeader() - }; - - _systemTransactionExtraDataProvider.SetSystemTransactionCount(0, block.Header); - var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateBeforeAttach_WithExtraData_True_Test() + Header = new BlockHeader() + }; + + _systemTransactionExtraDataProvider.SetSystemTransactionCount(0, block.Header); + var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeFalse(); + } + + [Fact] + public async Task ValidateBeforeAttach_WithExtraData_True_Test() + { + var block = new Block { - var block = new Block - { - Header = new BlockHeader() - }; - - _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, block.Header); - var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); - validateResult.ShouldBeTrue(); - } + Header = new BlockHeader() + }; + + _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, block.Header); + var validateResult = await _systemTransactionValidationProvider.ValidateBeforeAttachAsync(block); + validateResult.ShouldBeTrue(); + } - [Fact] - public async Task ValidateBlockBeforeExecute_Test() + [Fact] + public async Task ValidateBlockBeforeExecute_Test() + { + var block = new Block { - var block = new Block - { - Header = new BlockHeader() - }; - var validateResult = await _systemTransactionValidationProvider.ValidateBlockBeforeExecuteAsync(block); - validateResult.ShouldBeTrue(); - } + Header = new BlockHeader() + }; + var validateResult = await _systemTransactionValidationProvider.ValidateBlockBeforeExecuteAsync(block); + validateResult.ShouldBeTrue(); + } - [Fact] - public async Task ValidateBlockAfterExecuteTest() + [Fact] + public async Task ValidateBlockAfterExecuteTest() + { + var block = new Block { - var block = new Block - { - Header = new BlockHeader() - }; - var validateResult = await _systemTransactionValidationProvider.ValidateBlockAfterExecuteAsync(block); - validateResult.ShouldBeTrue(); - } + Header = new BlockHeader() + }; + var validateResult = await _systemTransactionValidationProvider.ValidateBlockAfterExecuteAsync(block); + validateResult.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/SmartContract/Application/BlockchainStateServiceTests.cs b/test/AElf.Kernel.Core.Tests/SmartContract/Application/BlockchainStateServiceTests.cs index 66e4aa78e4..5e0b6f4657 100644 --- a/test/AElf.Kernel.Core.Tests/SmartContract/Application/BlockchainStateServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/SmartContract/Application/BlockchainStateServiceTests.cs @@ -1,165 +1,159 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockchainStateServiceTests : AElfKernelWithChainTestBase { - public sealed class BlockchainStateServiceTests : AElfKernelWithChainTestBase + private readonly IBlockchainExecutedDataService _blockchainExecutedDataService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockchainStateServiceTests() { - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockchainExecutedDataService _blockchainExecutedDataService; - private readonly KernelTestHelper _kernelTestHelper; + _blockStateSetManger = GetRequiredService(); + _blockchainStateService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockchainExecutedDataService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public BlockchainStateServiceTests() - { - _blockStateSetManger = GetRequiredService(); - _blockchainStateService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockchainExecutedDataService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + [Fact] + public async Task BlockState_NoNeed_To_Merge_Test() + { + var lastIrreversibleBlockHeight = -2; + var lastIrreversibleBlockHash = HashHelper.ComputeFrom("hash"); - [Fact] - public async Task BlockState_NoNeed_To_Merge_Test() - { - var lastIrreversibleBlockHeight = -2; - var lastIrreversibleBlockHash = HashHelper.ComputeFrom("hash"); + await _blockchainStateService.MergeBlockStateAsync(lastIrreversibleBlockHeight, + lastIrreversibleBlockHash); - await _blockchainStateService.MergeBlockStateAsync(lastIrreversibleBlockHeight, - lastIrreversibleBlockHash); + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHeight.ShouldNotBe(lastIrreversibleBlockHeight); + chainStateInfo.MergingBlockHash.ShouldNotBe(lastIrreversibleBlockHash); + } - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHeight.ShouldNotBe(lastIrreversibleBlockHeight); - chainStateInfo.MergingBlockHash.ShouldNotBe(lastIrreversibleBlockHash); - } + [Fact] + public async Task BlockState_Merge_GotException_Test() + { + var lastIrreversibleBlockHeight = 1; + var lastIrreversibleBlockHash = HashHelper.ComputeFrom("hash"); + + await Should.ThrowAsync(() => _blockchainStateService.MergeBlockStateAsync( + lastIrreversibleBlockHeight, + lastIrreversibleBlockHash)); + + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHeight.ShouldNotBe(lastIrreversibleBlockHeight); + chainStateInfo.MergingBlockHash.ShouldNotBe(lastIrreversibleBlockHash); + } + + [Fact] + public async Task BlockState_MergeBlock_Test() + { + for (var i = 0; i < 5; i++) await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[i]); - [Fact] - public async Task BlockState_Merge_GotException_Test() { - var lastIrreversibleBlockHeight = 1; - var lastIrreversibleBlockHash = HashHelper.ComputeFrom("hash"); + await _blockchainStateService.MergeBlockStateAsync(_kernelTestHelper.BestBranchBlockList[0].Height, + _kernelTestHelper.BestBranchBlockList[0].GetHash()); - await Should.ThrowAsync(()=>_blockchainStateService.MergeBlockStateAsync(lastIrreversibleBlockHeight, - lastIrreversibleBlockHash)); - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHeight.ShouldNotBe(lastIrreversibleBlockHeight); - chainStateInfo.MergingBlockHash.ShouldNotBe(lastIrreversibleBlockHash); + chainStateInfo.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[0].Height); + chainStateInfo.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[0].GetHash()); } - [Fact] - public async Task BlockState_MergeBlock_Test() { - for (var i = 0; i < 5; i++) - { - await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[i]); - } + await _blockchainStateService.MergeBlockStateAsync(_kernelTestHelper.BestBranchBlockList[4].Height, + _kernelTestHelper.BestBranchBlockList[4].GetHash()); - { - await _blockchainStateService.MergeBlockStateAsync(_kernelTestHelper.BestBranchBlockList[0].Height, - _kernelTestHelper.BestBranchBlockList[0].GetHash()); + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].Height); + chainStateInfo.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); + } + } - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[0].Height); - chainStateInfo.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[0].GetHash()); - } + private async Task AddBlockStateSetAsync(Block block) + { + var blockStateSet = new BlockStateSet + { + BlockHeight = block.Height, + BlockHash = block.GetHash(), + PreviousHash = block.Header.PreviousBlockHash + }; - { - await _blockchainStateService.MergeBlockStateAsync(_kernelTestHelper.BestBranchBlockList[4].Height, - _kernelTestHelper.BestBranchBlockList[4].GetHash()); + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + } - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].Height); - chainStateInfo.BlockHash.ShouldBe(_kernelTestHelper.BestBranchBlockList[4].GetHash()); - } - } + [Fact] + public async Task BlockExecutedData_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var blockStateSet = new BlockStateSet + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - private async Task AddBlockStateSetAsync(Block block) + var transactionDic = new Dictionary(); + for (var i = 0; i < 5; i++) { - var blockStateSet = new BlockStateSet() + var transaction = new Transaction { - BlockHeight = block.Height, - BlockHash = block.GetHash(), - PreviousHash = block.Header.PreviousBlockHash + From = SampleAddress.AddressList[i], + To = SampleAddress.AddressList[i + 1], + RefBlockNumber = chain.BestChainHeight - 1, + MethodName = "Test" }; - - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + transactionDic.Add( + string.Join("/", KernelConstants.BlockExecutedDataKey, nameof(Transaction), + transaction.GetHash().ToString()), transaction); } - [Fact] - public async Task BlockExecutedData_Test() + await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, + transactionDic); + var transactionResult = new TransactionResult { - var chain = await _blockchainService.GetChainAsync(); - var blockStateSet = new BlockStateSet - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight, - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - - var transactionDic = new Dictionary(); - for (int i = 0; i < 5; i++) - { - var transaction = new Transaction - { - From = SampleAddress.AddressList[i], - To = SampleAddress.AddressList[i + 1], - RefBlockNumber = chain.BestChainHeight - 1, - MethodName = "Test" - }; - transactionDic.Add( - string.Join("/", KernelConstants.BlockExecutedDataKey, nameof(Transaction), - transaction.GetHash().ToString()), transaction); - } - - await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, - transactionDic); - var transactionResult = new TransactionResult - { - TransactionId = transactionDic.First().Value.GetHash() - }; - var transactionResultKey = string.Join("/", KernelConstants.BlockExecutedDataKey, - nameof(TransactionResult), transactionResult.TransactionId.ToString()); - await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, transactionResultKey, - transactionResult); - var chainKey = string.Join("/", KernelConstants.BlockExecutedDataKey, nameof(Chain)); - await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, chainKey, chain); - - var newBlockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); - newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); - newBlockStateSet.BlockExecutedData.Count.ShouldBe(7); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key=>key.Contains(typeof(Transaction).Name)); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key=>key.Contains(typeof(TransactionResult).Name)); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key=>key.Contains(typeof(Chain).Name)); - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var chainFromBlockExecutedData = - await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, chainKey); - chainFromBlockExecutedData.ShouldBe(chain); - - var transactionResultFromBlockExecutedData = - await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, - transactionResultKey); - transactionResultFromBlockExecutedData.ShouldBe(transactionResult); - foreach (var keyPair in transactionDic) - { - var transaction = - await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, keyPair.Key); - transaction.ShouldBe(keyPair.Value); - } + TransactionId = transactionDic.First().Value.GetHash() + }; + var transactionResultKey = string.Join("/", KernelConstants.BlockExecutedDataKey, + nameof(TransactionResult), transactionResult.TransactionId.ToString()); + await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, transactionResultKey, + transactionResult); + var chainKey = string.Join("/", KernelConstants.BlockExecutedDataKey, nameof(Chain)); + await _blockchainExecutedDataService.AddBlockExecutedDataAsync(chain.BestChainHash, chainKey, chain); + + var newBlockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); + newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); + newBlockStateSet.BlockExecutedData.Count.ShouldBe(7); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Transaction).Name)); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(TransactionResult).Name)); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Chain).Name)); + + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var chainFromBlockExecutedData = + await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, chainKey); + chainFromBlockExecutedData.ShouldBe(chain); + + var transactionResultFromBlockExecutedData = + await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, + transactionResultKey); + transactionResultFromBlockExecutedData.ShouldBe(transactionResult); + foreach (var keyPair in transactionDic) + { + var transaction = + await _blockchainExecutedDataService.GetBlockExecutedDataAsync(chainContext, keyPair.Key); + transaction.ShouldBe(keyPair.Value); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/SmartContract/Application/CachedBlockchainExecutedDataServiceTests.cs b/test/AElf.Kernel.Core.Tests/SmartContract/Application/CachedBlockchainExecutedDataServiceTests.cs index b7f9a4aadc..2e7129680c 100644 --- a/test/AElf.Kernel.Core.Tests/SmartContract/Application/CachedBlockchainExecutedDataServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/SmartContract/Application/CachedBlockchainExecutedDataServiceTests.cs @@ -1,260 +1,257 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class CachedBlockchainExecutedDataServiceTests : AElfKernelTestBase { - public sealed class CachedBlockchainExecutedDataServiceTests : AElfKernelTestBase - { - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockchainService _blockchainService; - private readonly ICachedBlockchainExecutedDataService _chainBlockchainExecutedDataService; - private readonly ICachedBlockchainExecutedDataService _transactionBlockchainExecutedDataService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockchainExecutedDataCacheProvider _chainBlockchainExecutedDataCacheProvider; + private readonly ICachedBlockchainExecutedDataService _chainBlockchainExecutedDataService; + + private readonly KernelTestHelper _kernelTestHelper; - private readonly ICachedBlockchainExecutedDataService - _transactionResultBlockchainExecutedDataService; + private readonly IBlockchainExecutedDataCacheProvider + _transactionBlockchainExecutedDataCacheProvider; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockchainExecutedDataCacheProvider _chainBlockchainExecutedDataCacheProvider; + private readonly ICachedBlockchainExecutedDataService _transactionBlockchainExecutedDataService; - private readonly IBlockchainExecutedDataCacheProvider - _transactionBlockchainExecutedDataCacheProvider; + private readonly IBlockchainExecutedDataCacheProvider + _transactionResultBlockchainExecutedDataCacheProvider; - private readonly IBlockchainExecutedDataCacheProvider - _transactionResultBlockchainExecutedDataCacheProvider; + private readonly ICachedBlockchainExecutedDataService + _transactionResultBlockchainExecutedDataService; - public CachedBlockchainExecutedDataServiceTests() + public CachedBlockchainExecutedDataServiceTests() + { + _blockStateSetManger = GetRequiredService(); + _blockchainStateService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _chainBlockchainExecutedDataService = GetRequiredService>(); + _transactionBlockchainExecutedDataService = + GetRequiredService>(); + _transactionResultBlockchainExecutedDataService = + GetRequiredService>(); + _kernelTestHelper = GetRequiredService(); + _chainBlockchainExecutedDataCacheProvider = + GetRequiredService>(); + _transactionBlockchainExecutedDataCacheProvider = + GetRequiredService>(); + _transactionResultBlockchainExecutedDataCacheProvider = + GetRequiredService>(); + } + + [Fact] + public async Task BlockExecutedData_Test() + { + var genesisBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); + var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); + var blockStateSet = new BlockStateSet { - _blockStateSetManger = GetRequiredService(); - _blockchainStateService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _chainBlockchainExecutedDataService = GetRequiredService>(); - _transactionBlockchainExecutedDataService = - GetRequiredService>(); - _transactionResultBlockchainExecutedDataService = - GetRequiredService>(); - _kernelTestHelper = GetRequiredService(); - _chainBlockchainExecutedDataCacheProvider = - GetRequiredService>(); - _transactionBlockchainExecutedDataCacheProvider = - GetRequiredService>(); - _transactionResultBlockchainExecutedDataCacheProvider = - GetRequiredService>(); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - [Fact] - public async Task BlockExecutedData_Test() + var transactionDic = new Dictionary(); + for (var i = 0; i < 5; i++) { - var genesisBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); - var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); - var blockStateSet = new BlockStateSet + var transaction = new Transaction { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight + From = SampleAddress.AddressList[i], + To = SampleAddress.AddressList[i + 1], + RefBlockNumber = chain.BestChainHeight - 1, + MethodName = "Test" }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + transactionDic.Add(GetBlockExecutedDataKey(transaction.GetHash()), transaction); + } - var transactionDic = new Dictionary(); - for (var i = 0; i < 5; i++) - { - var transaction = new Transaction - { - From = SampleAddress.AddressList[i], - To = SampleAddress.AddressList[i + 1], - RefBlockNumber = chain.BestChainHeight - 1, - MethodName = "Test" - }; - transactionDic.Add(GetBlockExecutedDataKey(transaction.GetHash()), transaction); - } - - await _transactionBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, transactionDic); + await _transactionBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, transactionDic); - var transactionResult = new TransactionResult + var transactionResult = new TransactionResult + { + TransactionId = transactionDic.First().Value.GetHash() + }; + var transactionResultKey = GetBlockExecutedDataKey(transactionResult.TransactionId); + await _transactionResultBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex { - TransactionId = transactionDic.First().Value.GetHash() - }; - var transactionResultKey = GetBlockExecutedDataKey(transactionResult.TransactionId); - await _transactionResultBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, - transactionResultKey, - transactionResult); - - var chainKey = GetBlockExecutedDataKey(); - await _chainBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, - chainKey, chain); - - CheckBlockExecutedDataCache(new BlockIndex + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, + transactionResultKey, + transactionResult); + + var chainKey = GetBlockExecutedDataKey(); + await _chainBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex { BlockHash = blockStateSet.BlockHash, BlockHeight = blockStateSet.BlockHeight - }, chain, transactionResult, transactionDic, false, false); + }, + chainKey, chain); - var newBlockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); - newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); - newBlockStateSet.BlockExecutedData.Count.ShouldBe(7); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Transaction).Name)); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(TransactionResult).Name)); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Chain).Name)); + CheckBlockExecutedDataCache(new BlockIndex + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, chain, transactionResult, transactionDic, false, false); + + var newBlockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); + newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); + newBlockStateSet.BlockExecutedData.Count.ShouldBe(7); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Transaction).Name)); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(TransactionResult).Name)); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => key.Contains(typeof(Chain).Name)); + + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + + CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); + CheckBlockExecutedDataCache(new BlockIndex + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, chain, transactionResult, transactionDic, false, false); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); + await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); - CheckBlockExecutedDataCache(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, chain, transactionResult, transactionDic, false, false); + CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); + CheckBlockExecutedDataCache(new BlockIndex + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, chain, transactionResult, transactionDic, false, true); - await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); - CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); - CheckBlockExecutedDataCache(new BlockIndex + chain = await _blockchainService.GetChainAsync(); + await _chainBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, chain, transactionResult, transactionDic, false, true); + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, + chainKey, chain); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - CheckBlockExecutedData(blockStateSet, chain, transactionResult, transactionDic); + _chainBlockchainExecutedDataCacheProvider + .TryGetChangeHeight(GetBlockExecutedDataKey(), out var chainChangeHeight) + .ShouldBeTrue(); + chainChangeHeight.ShouldBe(chain.BestChainHeight); - chain = await _blockchainService.GetChainAsync(); - await _chainBlockchainExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, - chainKey, chain); + _chainBlockchainExecutedDataCacheProvider + .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out var chainExecutedData) + .ShouldBeFalse(); - _chainBlockchainExecutedDataCacheProvider - .TryGetChangeHeight(GetBlockExecutedDataKey(), out var chainChangeHeight) - .ShouldBeTrue(); - chainChangeHeight.ShouldBe(chain.BestChainHeight); + await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + _chainBlockchainExecutedDataService.CleanChangeHeight(chain.BestChainHeight); - _chainBlockchainExecutedDataCacheProvider - .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out var chainExecutedData) - .ShouldBeFalse(); - - await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - _chainBlockchainExecutedDataService.CleanChangeHeight(chain.BestChainHeight); + _chainBlockchainExecutedDataCacheProvider + .TryGetChangeHeight(GetBlockExecutedDataKey(), out chainChangeHeight) + .ShouldBeFalse(); - _chainBlockchainExecutedDataCacheProvider - .TryGetChangeHeight(GetBlockExecutedDataKey(), out chainChangeHeight) - .ShouldBeFalse(); + _chainBlockchainExecutedDataService.GetBlockExecutedData(new ChainContext + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, GetBlockExecutedDataKey()); + + _chainBlockchainExecutedDataCacheProvider + .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out chainExecutedData) + .ShouldBeTrue(); + chainExecutedData.ShouldBe(chain); + } - _chainBlockchainExecutedDataService.GetBlockExecutedData(new ChainContext - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, GetBlockExecutedDataKey()); + private async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) + { + var block = await _kernelTestHelper.AttachBlockToBestChain(); + var blockStateSet = new BlockStateSet + { + BlockHash = block.GetHash(), + BlockHeight = block.Height, + PreviousHash = previousBlockStateSet.BlockHash + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + return blockStateSet; + } - _chainBlockchainExecutedDataCacheProvider - .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out chainExecutedData) - .ShouldBeTrue(); - chainExecutedData.ShouldBe(chain); + private void CheckBlockExecutedData(BlockStateSet blockStateSet, Chain chain, + TransactionResult transactionResult, Dictionary transactionDic) + { + var chainContext = new ChainContext + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }; + var chainFromBlockExecutedData = + _chainBlockchainExecutedDataService.GetBlockExecutedData(chainContext, + GetBlockExecutedDataKey()); + chainFromBlockExecutedData.ShouldBe(chain); + + var transactionResultFromBlockExecutedData = + _transactionResultBlockchainExecutedDataService.GetBlockExecutedData(chainContext, + GetBlockExecutedDataKey(transactionResult.TransactionId)); + transactionResultFromBlockExecutedData.ShouldBe(transactionResult); + foreach (var keyPair in transactionDic) + { + var transaction = + _transactionBlockchainExecutedDataService.GetBlockExecutedData(chainContext, keyPair.Key); + transaction.ShouldBe(keyPair.Value); } + } - private async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) + private void CheckBlockExecutedDataCache(BlockIndex blockIndex, Chain chain, + TransactionResult transactionResult, Dictionary transactionDic, bool existChangeHeight, + bool existExecutedData) + { { - var block = await _kernelTestHelper.AttachBlockToBestChain(); - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height, - PreviousHash = previousBlockStateSet.BlockHash - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - return blockStateSet; + _chainBlockchainExecutedDataCacheProvider + .TryGetChangeHeight(GetBlockExecutedDataKey(), out var chainChangeHeight) + .ShouldBe(existChangeHeight); + if (existChangeHeight) + chainChangeHeight.ShouldBe(blockIndex.BlockHeight); + + _chainBlockchainExecutedDataCacheProvider + .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out var chainExecutedData) + .ShouldBe(existExecutedData); + if (existExecutedData) + chainExecutedData.ShouldBe(chain); } - private void CheckBlockExecutedData(BlockStateSet blockStateSet, Chain chain, - TransactionResult transactionResult, Dictionary transactionDic) { - var chainContext = new ChainContext - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }; - var chainFromBlockExecutedData = - _chainBlockchainExecutedDataService.GetBlockExecutedData(chainContext, - GetBlockExecutedDataKey()); - chainFromBlockExecutedData.ShouldBe(chain); - - var transactionResultFromBlockExecutedData = - _transactionResultBlockchainExecutedDataService.GetBlockExecutedData(chainContext, - GetBlockExecutedDataKey(transactionResult.TransactionId)); - transactionResultFromBlockExecutedData.ShouldBe(transactionResult); - foreach (var keyPair in transactionDic) - { - var transaction = - _transactionBlockchainExecutedDataService.GetBlockExecutedData(chainContext, keyPair.Key); - transaction.ShouldBe(keyPair.Value); - } + _transactionResultBlockchainExecutedDataCacheProvider + .TryGetChangeHeight(GetBlockExecutedDataKey(transactionResult.TransactionId), + out var transactionResultChangeHeight).ShouldBe(existChangeHeight); + if (existChangeHeight) + transactionResultChangeHeight.ShouldBe(blockIndex.BlockHeight); + _transactionResultBlockchainExecutedDataCacheProvider + .TryGetBlockExecutedData( + GetBlockExecutedDataKey(transactionResult.TransactionId), + out var transactionResultExecutedData).ShouldBe(existExecutedData); + if (existExecutedData) + transactionResultExecutedData.ShouldBe(transactionResult); } - private void CheckBlockExecutedDataCache(BlockIndex blockIndex, Chain chain, - TransactionResult transactionResult, Dictionary transactionDic, bool existChangeHeight, - bool existExecutedData) + foreach (var transaction in transactionDic) { - { - _chainBlockchainExecutedDataCacheProvider - .TryGetChangeHeight(GetBlockExecutedDataKey(), out var chainChangeHeight) - .ShouldBe(existChangeHeight); - if (existChangeHeight) - chainChangeHeight.ShouldBe(blockIndex.BlockHeight); - - _chainBlockchainExecutedDataCacheProvider - .TryGetBlockExecutedData(GetBlockExecutedDataKey(), out var chainExecutedData) - .ShouldBe(existExecutedData); - if (existExecutedData) - chainExecutedData.ShouldBe(chain); - } - - { - _transactionResultBlockchainExecutedDataCacheProvider - .TryGetChangeHeight(GetBlockExecutedDataKey(transactionResult.TransactionId), - out var transactionResultChangeHeight).ShouldBe(existChangeHeight); - if (existChangeHeight) - transactionResultChangeHeight.ShouldBe(blockIndex.BlockHeight); - _transactionResultBlockchainExecutedDataCacheProvider - .TryGetBlockExecutedData( - GetBlockExecutedDataKey(transactionResult.TransactionId), - out var transactionResultExecutedData).ShouldBe(existExecutedData); - if (existExecutedData) - transactionResultExecutedData.ShouldBe(transactionResult); - } - - foreach (var transaction in transactionDic) - { - _transactionBlockchainExecutedDataCacheProvider - .TryGetChangeHeight(transaction.Key, out var transactionChangeHeight) - .ShouldBe(existChangeHeight); - if (existChangeHeight) - transactionChangeHeight.ShouldBe(blockIndex.BlockHeight); - _transactionBlockchainExecutedDataCacheProvider - .TryGetBlockExecutedData(transaction.Key, out var transactionExecutedData) - .ShouldBe(existExecutedData); - if (existExecutedData) - transactionExecutedData.ShouldBe(transaction.Value); - } + _transactionBlockchainExecutedDataCacheProvider + .TryGetChangeHeight(transaction.Key, out var transactionChangeHeight) + .ShouldBe(existChangeHeight); + if (existChangeHeight) + transactionChangeHeight.ShouldBe(blockIndex.BlockHeight); + _transactionBlockchainExecutedDataCacheProvider + .TryGetBlockExecutedData(transaction.Key, out var transactionExecutedData) + .ShouldBe(existExecutedData); + if (existExecutedData) + transactionExecutedData.ShouldBe(transaction.Value); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainExecutedDataManagerTests.cs b/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainExecutedDataManagerTests.cs index 3939af4368..65681e02b4 100644 --- a/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainExecutedDataManagerTests.cs +++ b/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainExecutedDataManagerTests.cs @@ -1,88 +1,83 @@ using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockchainExecutedDataManagerTests : AElfKernelTestBase { - public sealed class BlockchainExecutedDataManagerTests : AElfKernelTestBase + private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockchainExecutedDataManagerTests() { - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockchainExecutedDataManager _blockchainExecutedDataManager; - private readonly KernelTestHelper _kernelTestHelper; + _blockStateSetManger = GetRequiredService(); + _blockchainStateService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockchainExecutedDataManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public BlockchainExecutedDataManagerTests() + [Fact] + public async Task BlockExecutedData_Test() + { + var genesisBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); + var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); + var blockStateSet = new BlockStateSet { - _blockStateSetManger = GetRequiredService(); - _blockchainStateService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockchainExecutedDataManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - [Fact] - public async Task BlockExecutedData_Test() + var chainKey = GetBlockExecutedDataKey(); + var dictionary = new Dictionary { - var genesisBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); - var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); - var blockStateSet = new BlockStateSet - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - - var chainKey = GetBlockExecutedDataKey(); - var dictionary = new Dictionary - { - {chainKey, ByteString.CopyFrom(SerializationHelper.Serialize(chain))} - }; - await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockStateSet.BlockHash, dictionary); - var isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); - isInStore.ShouldBeFalse(); - - await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); - isInStore.ShouldBeTrue(); - - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - - isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); - isInStore.ShouldBeTrue(); - - // BlockStateSet is not exist - var notExistHash = HashHelper.ComputeFrom("NotExist"); - await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(notExistHash, dictionary); - var stateSet = await _blockStateSetManger.GetBlockStateSetAsync(notExistHash); - stateSet.ShouldBeNull(); - } + { chainKey, ByteString.CopyFrom(SerializationHelper.Serialize(chain)) } + }; + await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(blockStateSet.BlockHash, dictionary); + var isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); + isInStore.ShouldBeFalse(); - private async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) - { - var block = await _kernelTestHelper.AttachBlockToBestChain(); - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height, - PreviousHash = previousBlockStateSet.BlockHash - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - return blockStateSet; - } + await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); + isInStore.ShouldBeTrue(); + + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + + isInStore = await CheckExecutedDataInStoreAsync(blockStateSet, chainKey, dictionary[chainKey]); + isInStore.ShouldBeTrue(); - private async Task CheckExecutedDataInStoreAsync(BlockStateSet blockStateSet, string key, - ByteString blockExecutedData) + // BlockStateSet is not exist + var notExistHash = HashHelper.ComputeFrom("NotExist"); + await _blockchainExecutedDataManager.AddBlockExecutedCacheAsync(notExistHash, dictionary); + var stateSet = await _blockStateSetManger.GetBlockStateSetAsync(notExistHash); + stateSet.ShouldBeNull(); + } + + private async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) + { + var block = await _kernelTestHelper.AttachBlockToBestChain(); + var blockStateSet = new BlockStateSet { - var stateReturn = await _blockchainExecutedDataManager.GetExecutedCacheAsync(key, blockStateSet.BlockHeight, - blockStateSet.BlockHash); - stateReturn.Value.ShouldBe(blockExecutedData); - return stateReturn.IsInStore; - } + BlockHash = block.GetHash(), + BlockHeight = block.Height, + PreviousHash = previousBlockStateSet.BlockHash + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + return blockStateSet; + } + + private async Task CheckExecutedDataInStoreAsync(BlockStateSet blockStateSet, string key, + ByteString blockExecutedData) + { + var stateReturn = await _blockchainExecutedDataManager.GetExecutedCacheAsync(key, blockStateSet.BlockHeight, + blockStateSet.BlockHash); + stateReturn.Value.ShouldBe(blockExecutedData); + return stateReturn.IsInStore; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainStateManagerTests.cs b/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainStateManagerTests.cs index 7f2d123530..062eca8ca6 100644 --- a/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainStateManagerTests.cs +++ b/test/AElf.Kernel.Core.Tests/SmartContract/Domain/BlockchainStateManagerTests.cs @@ -1,390 +1,381 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Types; -using Google.Protobuf; -using Shouldly; -using Xunit; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockchainStateManagerTests : AElfKernelTestBase { - public sealed class BlockchainStateManagerTests : AElfKernelTestBase - { - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainStateManager _blockchainStateManager; + private readonly IBlockchainStateManager _blockchainStateManager; + private readonly IBlockStateSetManger _blockStateSetManger; - private List _tv; + private readonly List _tv; - public BlockchainStateManagerTests() - { - _blockStateSetManger = GetRequiredService(); - _blockchainStateManager = GetRequiredService(); - _tv = new List(); - for (var i = 0; i < 200; i++) + public BlockchainStateManagerTests() + { + _blockStateSetManger = GetRequiredService(); + _blockchainStateManager = GetRequiredService(); + _tv = new List(); + for (var i = 0; i < 200; i++) + _tv.Add(new TestPair { - _tv.Add(new TestPair() - { - BlockHash = HashHelper.ComputeFrom(new[] {Convert.ToByte(i)}), - BlockHeight = i, - Key = $"key{i}", - Value = ByteString.CopyFromUtf8($"value{i}") - }); - } - } - + BlockHash = HashHelper.ComputeFrom(new[] { Convert.ToByte(i) }), + BlockHeight = i, + Key = $"key{i}", + Value = ByteString.CopyFromUtf8($"value{i}") + }); + } - class TestPair - { - public Hash BlockHash; - public long BlockHeight; - public string Key; - public ByteString Value; - } - - [Fact] - public async Task AddBlockStateSet_Test() + [Fact] + public async Task AddBlockStateSet_Test() + { + // one level tests without best chain state + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - // one level tests without best chain state - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + PreviousHash = null, + Changes = { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - PreviousHash = null, - Changes = { - { - _tv[1].Key, - _tv[1].Value - }, - { - _tv[2].Key, - _tv[2].Value - }, + _tv[1].Key, + _tv[1].Value + }, + { + _tv[2].Key, + _tv[2].Value } - }); + } + }); - var check1 = new Func(async () => - { - (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) - .ShouldBe(_tv[1].Value); + var check1 = new Func(async () => + { + (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) + .ShouldBe(_tv[1].Value); - (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) - .ShouldBe(_tv[2].Value); - }); + (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[1].BlockHeight, _tv[1].BlockHash)) + .ShouldBe(_tv[2].Value); + }); - await check1(); + await check1(); - //two level tests without best chain state + //two level tests without best chain state - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[2].BlockHash, + BlockHeight = _tv[2].BlockHeight, + PreviousHash = _tv[1].BlockHash, + Changes = { - BlockHash = _tv[2].BlockHash, - BlockHeight = _tv[2].BlockHeight, - PreviousHash = _tv[1].BlockHash, - Changes = + //override key 1 { - //override key 1 - { - _tv[1].Key, - _tv[2].Value - }, + _tv[1].Key, + _tv[2].Value } - }); - var check2 = new Func(async () => - { - //key 1 was changed, value was changed to value 2 - (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) - .ShouldBe(_tv[2].Value); + } + }); + var check2 = new Func(async () => + { + //key 1 was changed, value was changed to value 2 + (await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) + .ShouldBe(_tv[2].Value); - (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) - .ShouldBe(_tv[2].Value); - }); + (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[2].BlockHeight, _tv[2].BlockHash)) + .ShouldBe(_tv[2].Value); + }); - await check2(); + await check2(); - //but when we we can get value at the height of block height 1, also block hash 1 - await check1(); + //but when we we can get value at the height of block height 1, also block hash 1 + await check1(); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[3].BlockHash, + BlockHeight = _tv[3].BlockHeight, + PreviousHash = _tv[2].BlockHash, + Changes = { - BlockHash = _tv[3].BlockHash, - BlockHeight = _tv[3].BlockHeight, - PreviousHash = _tv[2].BlockHash, - Changes = + //override key 2 at height 3 { - //override key 2 at height 3 - { - _tv[2].Key, - _tv[4].Value - }, + _tv[2].Key, + _tv[4].Value } - }); - var check3_1 = new Func(async () => - { - (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[3].BlockHash)) - .ShouldBe(_tv[4].Value); - }); + } + }); + var check31 = new Func(async () => + { + (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[3].BlockHash)) + .ShouldBe(_tv[4].Value); + }); - await check1(); - await check2(); - await check3_1(); + await check1(); + await check2(); + await check31(); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[4].BlockHash, + BlockHeight = _tv[3].BlockHeight, // it's a branch + PreviousHash = _tv[2].BlockHash, + Changes = { - BlockHash = _tv[4].BlockHash, - BlockHeight = _tv[3].BlockHeight, // it's a branch - PreviousHash = _tv[2].BlockHash, - Changes = + //override key 2 at height 3 { - //override key 2 at height 3 - { - _tv[2].Key, - _tv[5].Value - }, + _tv[2].Key, + _tv[5].Value } - }); + } + }); - var check3_2 = new Func(async () => - { - (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[4].BlockHash)) - .ShouldBe(_tv[5].Value); - }); + var check32 = new Func(async () => + { + (await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[3].BlockHeight, _tv[4].BlockHash)) + .ShouldBe(_tv[5].Value); + }); + + await check1(); + await check2(); + await check32(); + + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + + await check1(); + await check2(); + await check31(); + await check32(); + + await Assert.ThrowsAsync(async () => + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[3].BlockHash)); + + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash); + await Assert.ThrowsAsync(async () => + await check1()); + await check2(); + + //test failed merge recover + chainStateInfo.Status = ChainStateMergingStatus.Merging; + chainStateInfo.MergingBlockHash = _tv[4].BlockHash; + + //merge best to second branch + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); + await Assert.ThrowsAsync(async () => + await check1()); + await Assert.ThrowsAsync(async () => + await check2()); + await Assert.ThrowsAsync(async () => + await check31()); + await check32(); + + //test failed merge recover + chainStateInfo.Status = ChainStateMergingStatus.Merged; + chainStateInfo.MergingBlockHash = _tv[4].BlockHash; + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); + } - await check1(); - await check2(); - await check3_2(); - - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - - await check1(); - await check2(); - await check3_1(); - await check3_2(); - - await Assert.ThrowsAsync(async () => - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[3].BlockHash)); - - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash); - await Assert.ThrowsAsync(async () => - await check1()); - await check2(); - - //test failed merge recover - chainStateInfo.Status = ChainStateMergingStatus.Merging; - chainStateInfo.MergingBlockHash = _tv[4].BlockHash; - - //merge best to second branch - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); - await Assert.ThrowsAsync(async () => - await check1()); - await Assert.ThrowsAsync(async () => - await check2()); - await Assert.ThrowsAsync(async () => - await check3_1()); - await check3_2(); - - //test failed merge recover - chainStateInfo.Status = ChainStateMergingStatus.Merged; - chainStateInfo.MergingBlockHash = _tv[4].BlockHash; - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[4].BlockHash); - - } - - [Fact] - public async Task GetState_From_VersionedState_Test() + [Fact] + public async Task GetState_From_VersionedState_Test() + { + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() - { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - PreviousHash = null, - }); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + PreviousHash = null + }); + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[2].BlockHash, + BlockHeight = _tv[2].BlockHeight, + PreviousHash = _tv[1].BlockHash, + Changes = { - BlockHash = _tv[2].BlockHash, - BlockHeight = _tv[2].BlockHeight, - PreviousHash = _tv[1].BlockHash, - Changes = { - { - _tv[1].Key, - _tv[2].Value - } + _tv[1].Key, + _tv[2].Value } - }); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + } + }); + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[3].BlockHash, + BlockHeight = _tv[3].BlockHeight, + PreviousHash = null, + Changes = { - BlockHash = _tv[3].BlockHash, - BlockHeight = _tv[3].BlockHeight, - PreviousHash = null, - Changes = { - { - _tv[2].Key, - _tv[3].Value - } + _tv[2].Key, + _tv[3].Value } - }); + } + }); - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash); + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash); - var result = await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[3].BlockHeight, _tv[3].BlockHash); - result.ShouldNotBeNull(); - result.ShouldBe(_tv[2].Value); - } + var result = await _blockchainStateManager.GetStateAsync(_tv[1].Key, _tv[3].BlockHeight, _tv[3].BlockHash); + result.ShouldNotBeNull(); + result.ShouldBe(_tv[2].Value); + } - [Fact] - public async Task GetState_From_BlockStateSet_Test() + [Fact] + public async Task GetState_From_BlockStateSet_Test() + { + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() - { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - PreviousHash = null, - }); - var result = await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[2].BlockHeight, _tv[1].BlockHash); - result.ShouldBeNull(); - } + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + PreviousHash = null + }); + var result = await _blockchainStateManager.GetStateAsync(_tv[2].Key, _tv[2].BlockHeight, _tv[1].BlockHash); + result.ShouldBeNull(); + } - [Fact] - public async Task State_MergedSituation_Test() - { - var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.Status = ChainStateMergingStatus.Merged; - chainStateInfo.MergingBlockHash = _tv[1].BlockHash; - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - - chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); - chainStateInfo.MergingBlockHash.ShouldBeNull(); - } - - [Fact] - public async Task MergeBlockState_WithStatus_Merging() + [Fact] + public async Task State_MergedSituation_Test() + { + var chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.Status = ChainStateMergingStatus.Merged; + chainStateInfo.MergingBlockHash = _tv[1].BlockHash; + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + + chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); + chainStateInfo.MergingBlockHash.ShouldBeNull(); + } + + [Fact] + public async Task MergeBlockState_WithStatus_Merging() + { + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + BlockHash = _tv[0].BlockHash, + BlockHeight = _tv[0].BlockHeight, + PreviousHash = HashHelper.ComputeFrom("PreviousHash"), + Changes = { - BlockHash = _tv[0].BlockHash, - BlockHeight = _tv[0].BlockHeight, - PreviousHash = HashHelper.ComputeFrom("PreviousHash"), - Changes = { - { - _tv[1].Key, - _tv[1].Value - } + _tv[1].Key, + _tv[1].Value } - }); - - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + } + }); + + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + PreviousHash = _tv[0].BlockHash, + Changes = { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - PreviousHash = _tv[0].BlockHash, - Changes = { - { - _tv[1].Key, - _tv[1].Value - } + _tv[1].Key, + _tv[1].Value } - }); + } + }); - var chainStateInfo = new ChainStateInfo - { - BlockHash = _tv[0].BlockHash, - BlockHeight = _tv[0].BlockHeight, - MergingBlockHash = _tv[1].BlockHash, - Status = ChainStateMergingStatus.Merging - }; - - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - - chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); - chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); - chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); - chainStateInfo.MergingBlockHash.ShouldBeNull(); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(_tv[1].BlockHash); - blockStateSet.ShouldBeNull(); - } - - [Fact] - public async Task MergeBlockState_WithStatus_Merged_WithSet_Removed() + var chainStateInfo = new ChainStateInfo { - var chainStateInfo = new ChainStateInfo - { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - MergingBlockHash = _tv[1].BlockHash, - Status = ChainStateMergingStatus.Merged - }; - - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - - chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); - chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); - chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); - chainStateInfo.MergingBlockHash.ShouldBeNull(); - } - - [Fact] - public async Task MergeBlockState_WithStatus_Merged() + BlockHash = _tv[0].BlockHash, + BlockHeight = _tv[0].BlockHeight, + MergingBlockHash = _tv[1].BlockHash, + Status = ChainStateMergingStatus.Merging + }; + + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + + chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); + chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); + chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); + chainStateInfo.MergingBlockHash.ShouldBeNull(); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(_tv[1].BlockHash); + blockStateSet.ShouldBeNull(); + } + + [Fact] + public async Task MergeBlockState_WithStatus_Merged_WithSet_Removed() + { + var chainStateInfo = new ChainStateInfo { - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet() + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + MergingBlockHash = _tv[1].BlockHash, + Status = ChainStateMergingStatus.Merged + }; + + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + + chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); + chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); + chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); + chainStateInfo.MergingBlockHash.ShouldBeNull(); + } + + [Fact] + public async Task MergeBlockState_WithStatus_Merged() + { + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + PreviousHash = HashHelper.ComputeFrom("PreviousHash"), + Changes = { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - PreviousHash = HashHelper.ComputeFrom("PreviousHash"), - Changes = { - { - _tv[1].Key, - _tv[1].Value - } + _tv[1].Key, + _tv[1].Value } - }); + } + }); - var chainStateInfo = new ChainStateInfo - { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - MergingBlockHash = _tv[1].BlockHash, - Status = ChainStateMergingStatus.Merged - }; - - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); - - chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); - chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); - chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); - chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); - chainStateInfo.MergingBlockHash.ShouldBeNull(); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(_tv[1].BlockHash); - blockStateSet.ShouldBeNull(); - } - - [Fact] - public async Task MergeBlockState_ShouldThrowInvalidOperationException() + var chainStateInfo = new ChainStateInfo { - var chainStateInfo = new ChainStateInfo - { - BlockHash = _tv[1].BlockHash, - BlockHeight = _tv[1].BlockHeight, - MergingBlockHash = null, - Status = ChainStateMergingStatus.Common - }; - - await Assert.ThrowsAsync(async () => - await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash)); - } + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + MergingBlockHash = _tv[1].BlockHash, + Status = ChainStateMergingStatus.Merged + }; + + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[1].BlockHash); + + chainStateInfo = await _blockStateSetManger.GetChainStateInfoAsync(); + chainStateInfo.BlockHash.ShouldBe(_tv[1].BlockHash); + chainStateInfo.BlockHeight.ShouldBe(_tv[1].BlockHeight); + chainStateInfo.Status.ShouldBe(ChainStateMergingStatus.Common); + chainStateInfo.MergingBlockHash.ShouldBeNull(); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(_tv[1].BlockHash); + blockStateSet.ShouldBeNull(); + } + + [Fact] + public async Task MergeBlockState_ShouldThrowInvalidOperationException() + { + var chainStateInfo = new ChainStateInfo + { + BlockHash = _tv[1].BlockHash, + BlockHeight = _tv[1].BlockHeight, + MergingBlockHash = null, + Status = ChainStateMergingStatus.Common + }; + + await Assert.ThrowsAsync(async () => + await _blockStateSetManger.MergeBlockStateAsync(chainStateInfo, _tv[2].BlockHash)); + } + + private class TestPair + { + public Hash BlockHash; + public long BlockHeight; + public string Key; + public ByteString Value; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/SmartContract/Infrastructure/BlockchainExecutedDataCacheProviderTests.cs b/test/AElf.Kernel.Core.Tests/SmartContract/Infrastructure/BlockchainExecutedDataCacheProviderTests.cs index d5d2e36cb6..ba84e43045 100644 --- a/test/AElf.Kernel.Core.Tests/SmartContract/Infrastructure/BlockchainExecutedDataCacheProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/SmartContract/Infrastructure/BlockchainExecutedDataCacheProviderTests.cs @@ -1,38 +1,34 @@ +namespace AElf.Kernel.SmartContract.Infrastructure; -using Shouldly; -using Xunit; - -namespace AElf.Kernel.SmartContract.Infrastructure +[Trait("Category", AElfBlockchainModule)] +public sealed class BlockchainExecutedDataCacheProviderTests : AElfKernelTestBase { - public sealed class BlockchainExecutedDataCacheProviderTests : AElfKernelTestBase + private readonly IBlockchainExecutedDataCacheProvider _blockchainExecutedDataCacheProvider; + + public BlockchainExecutedDataCacheProviderTests() { - private readonly IBlockchainExecutedDataCacheProvider _blockchainExecutedDataCacheProvider; + _blockchainExecutedDataCacheProvider = GetRequiredService>(); + } - public BlockchainExecutedDataCacheProviderTests() - { - _blockchainExecutedDataCacheProvider = GetRequiredService>(); - } + [Fact] + public void BlockExecutedData_Test() + { + _blockchainExecutedDataCacheProvider.SetBlockExecutedData("key1", 1); + _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData("key1", out var value); + value.ShouldBe(1); - [Fact] - public void BlockExecutedData_Test() - { - _blockchainExecutedDataCacheProvider.SetBlockExecutedData("key1", 1); - _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData("key1", out var value); - value.ShouldBe(1); - - _blockchainExecutedDataCacheProvider.RemoveBlockExecutedData("key1"); - _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData("key1", out _).ShouldBeFalse(); - } + _blockchainExecutedDataCacheProvider.RemoveBlockExecutedData("key1"); + _blockchainExecutedDataCacheProvider.TryGetBlockExecutedData("key1", out _).ShouldBeFalse(); + } + + [Fact] + public void ChangeHeight_Test() + { + _blockchainExecutedDataCacheProvider.SetChangeHeight("key1", long.MaxValue); + _blockchainExecutedDataCacheProvider.TryGetChangeHeight("key1", out var value); + value.ShouldBe(long.MaxValue); - [Fact] - public void ChangeHeight_Test() - { - _blockchainExecutedDataCacheProvider.SetChangeHeight("key1", long.MaxValue); - _blockchainExecutedDataCacheProvider.TryGetChangeHeight("key1", out var value); - value.ShouldBe(long.MaxValue); - - _blockchainExecutedDataCacheProvider.CleanChangeHeight(long.MaxValue); - _blockchainExecutedDataCacheProvider.TryGetChangeHeight("key1", out _).ShouldBeFalse(); - } + _blockchainExecutedDataCacheProvider.CleanChangeHeight(long.MaxValue); + _blockchainExecutedDataCacheProvider.TryGetChangeHeight("key1", out _).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Txn/Application/TransactionPackingOptionProviderTests.cs b/test/AElf.Kernel.Core.Tests/Txn/Application/TransactionPackingOptionProviderTests.cs index 1d1d1e5d25..b659970439 100644 --- a/test/AElf.Kernel.Core.Tests/Txn/Application/TransactionPackingOptionProviderTests.cs +++ b/test/AElf.Kernel.Core.Tests/Txn/Application/TransactionPackingOptionProviderTests.cs @@ -1,74 +1,70 @@ -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Domain; -using AElf.Types; -using Shouldly; -using Xunit; -namespace AElf.Kernel.Txn.Application +namespace AElf.Kernel.Txn.Application; + +[Trait("Category", AElfBlockchainModule)] +public sealed class TransactionPackingOptionProviderTests : AElfKernelWithChainTestBase { - public class TransactionPackingOptionProviderTests : AElfKernelWithChainTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + + public TransactionPackingOptionProviderTests() { - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockStateSetManger _blockStateSetManger; + _transactionPackingOptionProvider = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } - public TransactionPackingOptionProviderTests() + [Fact] + public async Task TransactionPackingOption_Test() + { + await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[9]); + await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[10]); + await AddBlockStateSetAsync(_kernelTestHelper.ForkBranchBlockList[4]); + + var context = new ChainContext { - _transactionPackingOptionProvider = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } + BlockHash = _kernelTestHelper.BestBranchBlockList[9].GetHash(), + BlockHeight = _kernelTestHelper.BestBranchBlockList[9].Height + }; + + var isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); + isTransactionPackable.ShouldBeTrue(); + + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(context, false); - [Fact] - public async Task TransactionPackingOption_Test() + isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); + isTransactionPackable.ShouldBeFalse(); + + isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(new ChainContext + { + BlockHash = _kernelTestHelper.BestBranchBlockList[10].GetHash(), + BlockHeight = _kernelTestHelper.BestBranchBlockList[10].Height + }); + isTransactionPackable.ShouldBeFalse(); + + isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(new ChainContext { - await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[9]); - await AddBlockStateSetAsync(_kernelTestHelper.BestBranchBlockList[10]); - await AddBlockStateSetAsync(_kernelTestHelper.ForkBranchBlockList[4]); - - var context = new ChainContext - { - BlockHash = _kernelTestHelper.BestBranchBlockList[9].GetHash(), - BlockHeight = _kernelTestHelper.BestBranchBlockList[9].Height - }; - - var isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); - isTransactionPackable.ShouldBeTrue(); + BlockHash = _kernelTestHelper.ForkBranchBlockList[4].GetHash(), + BlockHeight = _kernelTestHelper.ForkBranchBlockList[4].Height + }); + isTransactionPackable.ShouldBeTrue(); - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(context, false); - - isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); - isTransactionPackable.ShouldBeFalse(); - - isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(new ChainContext - { - BlockHash = _kernelTestHelper.BestBranchBlockList[10].GetHash(), - BlockHeight = _kernelTestHelper.BestBranchBlockList[10].Height - }); - isTransactionPackable.ShouldBeFalse(); - - isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(new ChainContext - { - BlockHash = _kernelTestHelper.ForkBranchBlockList[4].GetHash(), - BlockHeight = _kernelTestHelper.ForkBranchBlockList[4].Height - }); - isTransactionPackable.ShouldBeTrue(); - - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(context, true); - - isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); - isTransactionPackable.ShouldBeTrue(); - } + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(context, true); - private async Task AddBlockStateSetAsync(Block block) + isTransactionPackable = _transactionPackingOptionProvider.IsTransactionPackable(context); + isTransactionPackable.ShouldBeTrue(); + } + + private async Task AddBlockStateSetAsync(Block block) + { + var blockStateSet = new BlockStateSet { - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height, - PreviousHash = block.Header.PreviousBlockHash - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height, + PreviousHash = block.Header.PreviousBlockHash + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeatureManager.Tests/AElf.Kernel.FeatureManager.Tests.csproj b/test/AElf.Kernel.FeatureManager.Tests/AElf.Kernel.FeatureManager.Tests.csproj index 667598e781..147be030df 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/AElf.Kernel.FeatureManager.Tests.csproj +++ b/test/AElf.Kernel.FeatureManager.Tests/AElf.Kernel.FeatureManager.Tests.csproj @@ -8,14 +8,14 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -38,8 +38,8 @@ Contract PreserveNewest - - + + diff --git a/test/AElf.Kernel.FeatureManager.Tests/FeatureActiveServiceTest.cs b/test/AElf.Kernel.FeatureManager.Tests/FeatureActiveServiceTest.cs index 657f48468f..e72b332dbc 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/FeatureActiveServiceTest.cs +++ b/test/AElf.Kernel.FeatureManager.Tests/FeatureActiveServiceTest.cs @@ -12,8 +12,8 @@ namespace AElf.Kernel.FeatureManager.Tests; public class FeatureActiveServiceTest : KernelFeatureManagerTestBase { - private readonly IMockService _mockService; private readonly IBlockchainService _blockchainService; + private readonly IMockService _mockService; public FeatureActiveServiceTest() { @@ -65,7 +65,7 @@ public async Task FeatureManageTest() var currentFeature = await _mockService.GetCurrentFeatureNameAsync(); currentFeature.ShouldBe("Version3"); } - + { var currentHeight = await GetCurrentHeight(); await ConfigFeatureActiveHeight("Version3", currentHeight + 5); diff --git a/test/AElf.Kernel.FeatureManager.Tests/IMockService.cs b/test/AElf.Kernel.FeatureManager.Tests/IMockService.cs index 3f396c2ca9..56c8a6330f 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/IMockService.cs +++ b/test/AElf.Kernel.FeatureManager.Tests/IMockService.cs @@ -10,11 +10,10 @@ public interface IMockService public class MockService : IMockService, ITransientDependency { - private readonly IFeatureActiveService _featureActiveService; - private const string Version1 = nameof(Version1); private const string Version2 = nameof(Version2); private const string Version3 = nameof(Version3); + private readonly IFeatureActiveService _featureActiveService; public MockService(IFeatureActiveService featureActiveService) { @@ -23,15 +22,9 @@ public MockService(IFeatureActiveService featureActiveService) public async Task GetCurrentFeatureNameAsync() { - if (await _featureActiveService.IsFeatureActive(Version3)) - { - return Version3; - } + if (await _featureActiveService.IsFeatureActive(Version3)) return Version3; - if (await _featureActiveService.IsFeatureActive(Version2)) - { - return Version2; - } + if (await _featureActiveService.IsFeatureActive(Version2)) return Version2; return Version1; } diff --git a/test/AElf.Kernel.FeatureManager.Tests/KernelFeatureManagerTestBase.cs b/test/AElf.Kernel.FeatureManager.Tests/KernelFeatureManagerTestBase.cs index ee4c985cbc..277fde204e 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/KernelFeatureManagerTestBase.cs +++ b/test/AElf.Kernel.FeatureManager.Tests/KernelFeatureManagerTestBase.cs @@ -16,10 +16,10 @@ namespace AElf.Kernel.FeatureManager.Tests; public class KernelFeatureManagerTestBase : ContractTestBase { - internal Address ParliamentContractAddress { get; set; } - internal Address ConfigurationContractAddress { get; set; } internal ConfigurationContainer.ConfigurationStub ConfigurationStub; internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; + internal Address ParliamentContractAddress { get; set; } + internal Address ConfigurationContractAddress { get; set; } internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; protected async Task DeployContractsAsync() diff --git a/test/AElf.Kernel.FeatureManager.Tests/MinerList.cs b/test/AElf.Kernel.FeatureManager.Tests/MinerList.cs index 96a1ddef1e..0ef019af8c 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/MinerList.cs +++ b/test/AElf.Kernel.FeatureManager.Tests/MinerList.cs @@ -4,51 +4,47 @@ using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.Consensus.AEDPoS +namespace AElf.Contracts.Consensus.AEDPoS; + +internal partial class MinerList { - internal partial class MinerList + public Round GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = - (from obj in Pubkeys - .ToDictionary(miner => miner.ToHex(), miner => miner[0]) - orderby obj.Value descending - select obj.Key).ToList(); - - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The first miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds((i * miningInterval) + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - - return round; - } + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); - public Hash GetMinersHash() + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) { - var orderedMiners = Pubkeys.OrderBy(p => p); - return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + + return round; + } + + public Hash GetMinersHash() + { + var orderedMiners = Pubkeys.OrderBy(p => p); + return HashHelper.ComputeFrom(orderedMiners.Aggregate("", (current, publicKey) => current + publicKey)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeatureManager.Tests/OptionalLogEventProcessingService.cs b/test/AElf.Kernel.FeatureManager.Tests/OptionalLogEventProcessingService.cs index 30f0837eac..4e6f52f26a 100644 --- a/test/AElf.Kernel.FeatureManager.Tests/OptionalLogEventProcessingService.cs +++ b/test/AElf.Kernel.FeatureManager.Tests/OptionalLogEventProcessingService.cs @@ -7,7 +7,7 @@ namespace AElf.Kernel.FeatureManager.Tests; public class OptionalLogEventProcessingService : ILogEventProcessingService where T : ILogEventProcessor { - private LogEventProcessingService _inner; + private readonly LogEventProcessingService _inner; public OptionalLogEventProcessingService(LogEventProcessingService inner) { @@ -18,9 +18,6 @@ public OptionalLogEventProcessingService(LogEventProcessingService inner) public async Task ProcessAsync(List blockExecutedSets) { - if (Enabled) - { - await _inner.ProcessAsync(blockExecutedSets); - } + if (Enabled) await _inner.ProcessAsync(blockExecutedSets); } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeeCalculation.Tests/AElf.Kernel.FeeCalculation.Tests.csproj b/test/AElf.Kernel.FeeCalculation.Tests/AElf.Kernel.FeeCalculation.Tests.csproj index c81570033c..882651719c 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/AElf.Kernel.FeeCalculation.Tests.csproj +++ b/test/AElf.Kernel.FeeCalculation.Tests/AElf.Kernel.FeeCalculation.Tests.csproj @@ -5,15 +5,15 @@ false - - - - - - + + + + + + - - + + diff --git a/test/AElf.Kernel.FeeCalculation.Tests/CalculateFunctionExecutedDataServiceTests.cs b/test/AElf.Kernel.FeeCalculation.Tests/CalculateFunctionExecutedDataServiceTests.cs index 37539999c7..96a804be96 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/CalculateFunctionExecutedDataServiceTests.cs +++ b/test/AElf.Kernel.FeeCalculation.Tests/CalculateFunctionExecutedDataServiceTests.cs @@ -8,77 +8,76 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.FeeCalculation +namespace AElf.Kernel.FeeCalculation; + +public sealed class CalculateFunctionExecutedDataServiceTests : TransactionFeeTestBase { - public sealed class CalculateFunctionExecutedDataServiceTests : TransactionFeeTestBase - { - private readonly ICachedBlockchainExecutedDataService> - _calculateFunctionExecutedDataService; + private readonly ICachedBlockchainExecutedDataService> + _calculateFunctionExecutedDataService; - public CalculateFunctionExecutedDataServiceTests() - { - _calculateFunctionExecutedDataService = - GetRequiredService>>(); - } + public CalculateFunctionExecutedDataServiceTests() + { + _calculateFunctionExecutedDataService = + GetRequiredService>>(); + } - [Fact] - public async Task CalculateFunctionMap_Test() + [Fact] + public async Task CalculateFunctionMap_Test() + { + var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); + var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); + var blockStateSet = new BlockStateSet { - var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); - var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); - var blockStateSet = new BlockStateSet - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); - var functionMapDict = new Dictionary>(); - var functionMap = GenerateFunctionMap(); - functionMapDict.Add(GetBlockExecutedDataKey(), functionMap); + var functionMapDict = new Dictionary>(); + var functionMap = GenerateFunctionMap(); + functionMapDict.Add(GetBlockExecutedDataKey(), functionMap); - await _calculateFunctionExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, - functionMapDict); + await _calculateFunctionExecutedDataService.AddBlockExecutedDataAsync(new BlockIndex + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, + functionMapDict); - var newBlockStateSet = await BlockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); - newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); - newBlockStateSet.BlockExecutedData.Count.ShouldBe(1); - newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => - key.Contains(typeof(AllCalculateFeeCoefficients).Name)); + var newBlockStateSet = await BlockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); + newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); + newBlockStateSet.BlockExecutedData.Count.ShouldBe(1); + newBlockStateSet.BlockExecutedData.Keys.ShouldContain(key => + key.Contains(typeof(AllCalculateFeeCoefficients).Name)); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - CheckBlockExecutedData(blockStateSet, functionMap); - await BlockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - CheckBlockExecutedData(blockStateSet, functionMap); + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + CheckBlockExecutedData(blockStateSet, functionMap); + await BlockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + CheckBlockExecutedData(blockStateSet, functionMap); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - CheckBlockExecutedData(blockStateSet, functionMap); - } + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + CheckBlockExecutedData(blockStateSet, functionMap); + } - private void CheckBlockExecutedData(BlockStateSet blockStateSet, - Dictionary functionMap) + private void CheckBlockExecutedData(BlockStateSet blockStateSet, + Dictionary functionMap) + { + var chainContext = new ChainContext { - var chainContext = new ChainContext - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }; - var functionMapFromBlockExecutedData = - _calculateFunctionExecutedDataService.GetBlockExecutedData(chainContext, - GetBlockExecutedDataKey()); - foreach (var key in functionMap.Keys) - { - var fromExecutedData = functionMapFromBlockExecutedData.Values.Single(d => - ((FeeTypeEnum) d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); - var actual = functionMap.Values.Single(d => - ((FeeTypeEnum) d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); - fromExecutedData.CalculateFeeCoefficients.ShouldBe(actual.CalculateFeeCoefficients); - } + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }; + var functionMapFromBlockExecutedData = + _calculateFunctionExecutedDataService.GetBlockExecutedData(chainContext, + GetBlockExecutedDataKey()); + foreach (var key in functionMap.Keys) + { + var fromExecutedData = functionMapFromBlockExecutedData.Values.Single(d => + ((FeeTypeEnum)d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); + var actual = functionMap.Values.Single(d => + ((FeeTypeEnum)d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); + fromExecutedData.CalculateFeeCoefficients.ShouldBe(actual.CalculateFeeCoefficients); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionProviderTests.cs b/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionProviderTests.cs index 7b7e4d0d23..30d77f3a4d 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionProviderTests.cs +++ b/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionProviderTests.cs @@ -8,114 +8,113 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.FeeCalculation.Infrastructure -{ - public sealed class CalculateFunctionProviderTests : TransactionFeeTestBase +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +public sealed class CalculateFunctionProviderTests : TransactionFeeTestBase +{ + private readonly ICalculateFunctionProvider _calculateFunctionProvider; + private readonly IPrimaryTokenFeeProvider _primaryTokenFeeProvider; + + public CalculateFunctionProviderTests() { - private readonly ICalculateFunctionProvider _calculateFunctionProvider; - private readonly IPrimaryTokenFeeProvider _primaryTokenFeeProvider; + _calculateFunctionProvider = GetRequiredService(); + _primaryTokenFeeProvider = GetRequiredService(); + } - public CalculateFunctionProviderTests() + [Fact] + public async Task CalculateFunctionMap_Test() + { + var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); + var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); + var blockStateSet = new BlockStateSet { - _calculateFunctionProvider =GetRequiredService(); - _primaryTokenFeeProvider = GetRequiredService(); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); - [Fact] - public async Task CalculateFunctionMap_Test() - { - var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); - var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); - var blockStateSet = new BlockStateSet + var blockExecutedDataKey = "BlockExecutedData/AllCalculateFeeCoefficients"; + blockStateSet.BlockExecutedData.ShouldNotContainKey(blockExecutedDataKey); + var functionMap = GenerateFunctionMap(); + await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); - - var blockExecutedDataKey = "BlockExecutedData/AllCalculateFeeCoefficients"; - blockStateSet.BlockExecutedData.ShouldNotContainKey(blockExecutedDataKey); - var functionMap = GenerateFunctionMap(); - await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, - functionMap); - - var newBlockStateSet = await BlockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); - newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); - newBlockStateSet.BlockExecutedData.Count.ShouldBe(1); - newBlockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }, + functionMap); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - CheckBlockExecutedData(blockStateSet, functionMap); - await BlockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - CheckBlockExecutedData(blockStateSet, functionMap); + var newBlockStateSet = await BlockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + newBlockStateSet.BlockHash.ShouldBe(blockStateSet.BlockHash); + newBlockStateSet.BlockHeight.ShouldBe(blockStateSet.BlockHeight); + newBlockStateSet.BlockExecutedData.Count.ShouldBe(1); + newBlockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); - blockStateSet = await AddBlockStateSetAsync(blockStateSet); - CheckBlockExecutedData(blockStateSet, functionMap); - } + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + CheckBlockExecutedData(blockStateSet, functionMap); + await BlockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + CheckBlockExecutedData(blockStateSet, functionMap); - [Fact] - public async Task TokenFeeProviderBase_Calculate_Test() - { - var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); - var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); - var blockStateSet = new BlockStateSet - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); - var functionMap = GenerateFunctionMap(); - await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex - { - BlockHash = blockStateSet.BlockHash, - BlockHeight = blockStateSet.BlockHeight - }, - functionMap); - var transaction = new Transaction - { - Params = new SInt64Value - { - Value = 100 - }.ToByteString() - }; - var transactionContext = new TransactionContext - { - Transaction = transaction - }; - var size = transaction.Size(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var sizeFee = await _primaryTokenFeeProvider.CalculateFeeAsync(transactionContext, chainContext); - var feeCalculatedByCoefficients = GetFeeForTx(size); - sizeFee.ShouldBe(feeCalculatedByCoefficients); - } + blockStateSet = await AddBlockStateSetAsync(blockStateSet); + CheckBlockExecutedData(blockStateSet, functionMap); + } - private void CheckBlockExecutedData(BlockStateSet blockStateSet, - Dictionary functionMap) + [Fact] + public async Task TokenFeeProviderBase_Calculate_Test() + { + var genesisBlock = KernelTestHelper.GenerateBlock(0, Hash.Empty, new List()); + var chain = await BlockchainService.CreateChainAsync(genesisBlock, new List()); + var blockStateSet = new BlockStateSet { - var chainContext = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); + var functionMap = GenerateFunctionMap(); + await _calculateFunctionProvider.AddCalculateFunctions(new BlockIndex { BlockHash = blockStateSet.BlockHash, BlockHeight = blockStateSet.BlockHeight - }; - var functionMapFromBlockExecutedData = - _calculateFunctionProvider.GetCalculateFunctions(chainContext); - foreach (var key in functionMap.Keys) + }, + functionMap); + var transaction = new Transaction + { + Params = new SInt64Value { - var fromExecutedData = functionMapFromBlockExecutedData.Values.Single(d => - ((FeeTypeEnum) d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); - var actual = functionMap.Values.Single(d => - ((FeeTypeEnum) d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); - fromExecutedData.CalculateFeeCoefficients.ShouldBe(actual.CalculateFeeCoefficients); - } + Value = 100 + }.ToByteString() + }; + var transactionContext = new TransactionContext + { + Transaction = transaction + }; + var size = transaction.Size(); + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var sizeFee = await _primaryTokenFeeProvider.CalculateFeeAsync(transactionContext, chainContext); + var feeCalculatedByCoefficients = GetFeeForTx(size); + sizeFee.ShouldBe(feeCalculatedByCoefficients); + } + + private void CheckBlockExecutedData(BlockStateSet blockStateSet, + Dictionary functionMap) + { + var chainContext = new ChainContext + { + BlockHash = blockStateSet.BlockHash, + BlockHeight = blockStateSet.BlockHeight + }; + var functionMapFromBlockExecutedData = + _calculateFunctionProvider.GetCalculateFunctions(chainContext); + foreach (var key in functionMap.Keys) + { + var fromExecutedData = functionMapFromBlockExecutedData.Values.Single(d => + ((FeeTypeEnum)d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); + var actual = functionMap.Values.Single(d => + ((FeeTypeEnum)d.CalculateFeeCoefficients.FeeTokenType).ToString().ToUpper() == key); + fromExecutedData.CalculateFeeCoefficients.ShouldBe(actual.CalculateFeeCoefficients); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionTest.cs b/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionTest.cs index 3a2dc3357c..11a0592ce1 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionTest.cs +++ b/test/AElf.Kernel.FeeCalculation.Tests/Infrastructure/CalculateFunctionTest.cs @@ -6,114 +6,113 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.FeeCalculation.Infrastructure +namespace AElf.Kernel.FeeCalculation.Infrastructure; + +public class CalculateFunctionTest { - public class CalculateFunctionTest + private readonly CalculateFunction _calculateFunction; + + public CalculateFunctionTest() { - private readonly CalculateFunction _calculateFunction; + var feeType = 1; + _calculateFunction = new CalculateFunction(feeType); + } - public CalculateFunctionTest() - { - var feeType = 1; - _calculateFunction = new CalculateFunction(feeType); - } + [Theory] + [InlineData(10, 100, 1000, 5, 5)] // 5 + [InlineData(10, 100, 1000, 10, 10)] // 10 + [InlineData(10, 100, 1000, 50, 4010)] // 10 + 40 * 100 + [InlineData(10, 100, 1000, 100, 9010)] // 10 + (100 - 10)* 100 + [InlineData(10, 100, 1000, 500, 409010)] // 10 + (100 - 10)* 100 +(500 -100)* 1000 + [InlineData(10, 100, 1000, 1000, 909010)] //10 + (100 - 10)* 100 +(1000 -100)* 1000 + [InlineData(10, 100, 1000, 1001, 909010)] //10 + (100 - 10)* 100 +(1000 -100)* 1000 + public void CalculateFunction_Piece_Wise_Test(int piece1, int piece2, int piece3, int input, long outCome) + { + _calculateFunction.AddFunction(new[] { piece1 }, Calculate1); + _calculateFunction.AddFunction(new[] { piece2 }, Calculate2); + _calculateFunction.AddFunction(new[] { piece3 }, Calculate3); - [Theory] - [InlineData( 10, 100, 1000, 5, 5)] // 5 - [InlineData( 10, 100, 1000, 10, 10)] // 10 - [InlineData( 10, 100, 1000, 50, 4010)] // 10 + 40 * 100 - [InlineData( 10, 100, 1000, 100, 9010)] // 10 + (100 - 10)* 100 - [InlineData( 10, 100, 1000, 500, 409010)] // 10 + (100 - 10)* 100 +(500 -100)* 1000 - [InlineData( 10, 100, 1000, 1000, 909010)] //10 + (100 - 10)* 100 +(1000 -100)* 1000 - [InlineData( 10, 100, 1000, 1001, 909010)] //10 + (100 - 10)* 100 +(1000 -100)* 1000 - public void CalculateFunction_Piece_Wise_Test(int piece1, int piece2, int piece3, int input, long outCome) - { - _calculateFunction.AddFunction(new []{piece1}, Calculate1); - _calculateFunction.AddFunction(new []{piece2}, Calculate2); - _calculateFunction.AddFunction(new []{piece3}, Calculate3); + var calculateOutcome = _calculateFunction.CalculateFee(input); + calculateOutcome.ShouldBe(outCome); + } - var calculateOutcome = _calculateFunction.CalculateFee(input); - calculateOutcome.ShouldBe(outCome); + [Fact] + public void CalculateFunction_With_Miss_Match_Functions_Test() + { + _calculateFunction.AddFunction(new[] { 1 }, Calculate1); + _calculateFunction.AddFunction(new[] { 10 }, Calculate2); + _calculateFunction.AddFunction(new[] { 100 }, Calculate3); + _calculateFunction.CalculateFeeCoefficients.PieceCoefficientsList.RemoveAt(0); + string errorMsg = null; + try + { + _calculateFunction.CalculateFee(1000); } - - [Fact] - public void CalculateFunction_With_Miss_Match_Functions_Test() + catch (ArgumentOutOfRangeException ex) { - _calculateFunction.AddFunction(new []{1}, Calculate1); - _calculateFunction.AddFunction(new []{10}, Calculate2); - _calculateFunction.AddFunction(new []{100}, Calculate3); - _calculateFunction.CalculateFeeCoefficients.PieceCoefficientsList.RemoveAt(0); - string errorMsg = null; - try - { - _calculateFunction.CalculateFee(1000); - } - catch(ArgumentOutOfRangeException ex) - { - errorMsg = ex.Message; - } - errorMsg.ShouldContain("Coefficients count not match"); + errorMsg = ex.Message; } - [Fact] - public void GetChargedTransactionFees_Test() + errorMsg.ShouldContain("Coefficients count not match"); + } + + [Fact] + public void GetChargedTransactionFees_Test() + { + var transactionResult = new TransactionResult(); + var feeDic = transactionResult.GetChargedTransactionFees(); + feeDic.Count.ShouldBe(0); + } + + [Fact] + public void GetConsumedResourceTokens_Test() + { + var transactionResult = new TransactionResult(); + var resourceTokenFeeDic = transactionResult.GetConsumedResourceTokens(); + resourceTokenFeeDic.Count.ShouldBe(0); + } + + [Fact] + public void GetOwningResourceTokens_Test() + { { var transactionResult = new TransactionResult(); - var feeDic = transactionResult.GetChargedTransactionFees(); - feeDic.Count.ShouldBe(0); + var owningTokenFeeDic = transactionResult.GetOwningResourceTokens(); + owningTokenFeeDic.Count.ShouldBe(0); } - - [Fact] - public void GetConsumedResourceTokens_Test() + { + var symbol = "ELF"; + var amount = 100; var transactionResult = new TransactionResult(); - var resourceTokenFeeDic = transactionResult.GetConsumedResourceTokens(); - resourceTokenFeeDic.Count.ShouldBe(0); - } - - [Fact] - public void GetOwningResourceTokens_Test() - { - { - var transactionResult = new TransactionResult(); - var owningTokenFeeDic = transactionResult.GetOwningResourceTokens(); - owningTokenFeeDic.Count.ShouldBe(0); - } - + transactionResult.Logs.Add(new LogEvent { - var symbol = "ELF"; - var amount = 100; - var transactionResult = new TransactionResult(); - transactionResult.Logs.Add(new LogEvent + Name = "ResourceTokenOwned", + NonIndexed = new ResourceTokenOwned { - Name = "ResourceTokenOwned", - NonIndexed = new ResourceTokenOwned - { - Symbol = symbol, - Amount = amount - }.ToByteString() - }); - var owningTokenFeeDic = transactionResult.GetOwningResourceTokens(); - owningTokenFeeDic.Count.ShouldBe(1); - owningTokenFeeDic[symbol].ShouldBe(amount); - } - + Symbol = symbol, + Amount = amount + }.ToByteString() + }); + var owningTokenFeeDic = transactionResult.GetOwningResourceTokens(); + owningTokenFeeDic.Count.ShouldBe(1); + owningTokenFeeDic[symbol].ShouldBe(amount); } + } - private long Calculate1(int count) - { - return count; - } - - private long Calculate2(int count) - { - return (long)count * 100; - } - - private long Calculate3(int count) - { - return (long)count * 1000; - } + private long Calculate1(int count) + { + return count; + } + + private long Calculate2(int count) + { + return (long)count * 100; + } + + private long Calculate3(int count) + { + return (long)count * 1000; } } \ No newline at end of file diff --git a/test/AElf.Kernel.FeeCalculation.Tests/KernelTransactionFeeTestAElfModule.cs b/test/AElf.Kernel.FeeCalculation.Tests/KernelTransactionFeeTestAElfModule.cs index 053d1de4e1..81e7b7316b 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/KernelTransactionFeeTestAElfModule.cs +++ b/test/AElf.Kernel.FeeCalculation.Tests/KernelTransactionFeeTestAElfModule.cs @@ -1,13 +1,11 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Kernel.FeeCalculation -{ - [DependsOn( - typeof(FeeCalculationModule), - typeof(TestBaseKernelAElfModule))] - public class KernelTransactionFeeTestAElfModule : AElfModule - { +namespace AElf.Kernel.FeeCalculation; - } +[DependsOn( + typeof(FeeCalculationModule), + typeof(TestBaseKernelAElfModule))] +public class KernelTransactionFeeTestAElfModule : AElfModule +{ } \ No newline at end of file diff --git a/test/AElf.Kernel.FeeCalculation.Tests/TransactionFeeTestBase.cs b/test/AElf.Kernel.FeeCalculation.Tests/TransactionFeeTestBase.cs index bbd26674bb..1b558a53fe 100644 --- a/test/AElf.Kernel.FeeCalculation.Tests/TransactionFeeTestBase.cs +++ b/test/AElf.Kernel.FeeCalculation.Tests/TransactionFeeTestBase.cs @@ -9,86 +9,86 @@ using AElf.TestBase; using Microsoft.Extensions.DependencyInjection; -namespace AElf.Kernel.FeeCalculation +namespace AElf.Kernel.FeeCalculation; + +public class TransactionFeeTestBase : AElfIntegratedTest { - public class TransactionFeeTestBase : AElfIntegratedTest + private const decimal Precision = 100000000; + protected readonly IBlockchainService BlockchainService; + protected readonly IBlockchainStateService BlockchainStateService; + protected readonly IBlockStateSetManger BlockStateSetManger; + protected readonly KernelTestHelper KernelTestHelper; + + protected TransactionFeeTestBase() { - protected readonly IBlockStateSetManger BlockStateSetManger; - protected readonly IBlockchainStateService BlockchainStateService; - protected readonly IBlockchainService BlockchainService; - protected readonly KernelTestHelper KernelTestHelper; + var serviceProvider = Application.ServiceProvider; + BlockStateSetManger = serviceProvider.GetRequiredService(); + BlockchainStateService = serviceProvider.GetRequiredService(); + BlockchainService = serviceProvider.GetRequiredService(); + KernelTestHelper = serviceProvider.GetRequiredService(); + } - protected TransactionFeeTestBase() - { - var serviceProvider = Application.ServiceProvider; - BlockStateSetManger = serviceProvider.GetRequiredService(); - BlockchainStateService = serviceProvider.GetRequiredService(); - BlockchainService = serviceProvider.GetRequiredService(); - KernelTestHelper = serviceProvider.GetRequiredService(); - } - - protected string GetBlockExecutedDataKey() - { - var list = new List {KernelConstants.BlockExecutedDataKey, nameof(AllCalculateFeeCoefficients)}; - return string.Join("/", list); - } - - protected async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) + protected string GetBlockExecutedDataKey() + { + var list = new List { KernelConstants.BlockExecutedDataKey, nameof(AllCalculateFeeCoefficients) }; + return string.Join("/", list); + } + + protected async Task AddBlockStateSetAsync(BlockStateSet previousBlockStateSet) + { + var block = await KernelTestHelper.AttachBlockToBestChain(); + var blockStateSet = new BlockStateSet { - var block = await KernelTestHelper.AttachBlockToBestChain(); - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height, - PreviousHash = previousBlockStateSet.BlockHash - }; - await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); - return blockStateSet; - } + BlockHash = block.GetHash(), + BlockHeight = block.Height, + PreviousHash = previousBlockStateSet.BlockHash + }; + await BlockStateSetManger.SetBlockStateSetAsync(blockStateSet); + return blockStateSet; + } - protected Dictionary GenerateFunctionMap() + protected Dictionary GenerateFunctionMap() + { + return new Dictionary { - return new Dictionary { + "TX", new CalculateFunction(4) { - "TX", new CalculateFunction(4) + CalculateFeeCoefficients = new CalculateFeeCoefficients { - CalculateFeeCoefficients = new CalculateFeeCoefficients + FeeTokenType = 4, + PieceCoefficientsList = { - FeeTokenType = 4, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients - { - Value = {10, 1, 2, 3} - } + Value = { 10, 1, 2, 3 } } } } - }, + } + }, + { + "STORAGE", new CalculateFunction(1) { - "STORAGE", new CalculateFunction(1) + CalculateFeeCoefficients = new CalculateFeeCoefficients { - CalculateFeeCoefficients = new CalculateFeeCoefficients + FeeTokenType = 1, + PieceCoefficientsList = { - FeeTokenType = 1, - PieceCoefficientsList = + new CalculateFeePieceCoefficients { - new CalculateFeePieceCoefficients - { - Value = {100, 1, 2, 3} - } + Value = { 100, 1, 2, 3 } } } } } - }; - } - private const decimal Precision = 100000000; - protected long GetFeeForTx(int count) - { - count = count > 10 ? 10 : count; - return (long) ((decimal) Math.Pow(count,1) * 2 / 3 * Precision); - } + } + }; + } + + protected long GetFeeForTx(int count) + { + count = count > 10 ? 10 : count; + return (long)((decimal)Math.Pow(count, 1) * 2 / 3 * Precision); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Node.Tests/AElf.Kernel.Node.Tests.csproj b/test/AElf.Kernel.Node.Tests/AElf.Kernel.Node.Tests.csproj index 2a417beab6..e8e288b470 100644 --- a/test/AElf.Kernel.Node.Tests/AElf.Kernel.Node.Tests.csproj +++ b/test/AElf.Kernel.Node.Tests/AElf.Kernel.Node.Tests.csproj @@ -5,16 +5,16 @@ AElf.Kernel.Node - - - - - - + + + + + + - - - + + + diff --git a/test/AElf.Kernel.Node.Tests/Application/BlockchainNodeContextServiceTests.cs b/test/AElf.Kernel.Node.Tests/Application/BlockchainNodeContextServiceTests.cs index dbfdcb1eef..08b792bc70 100644 --- a/test/AElf.Kernel.Node.Tests/Application/BlockchainNodeContextServiceTests.cs +++ b/test/AElf.Kernel.Node.Tests/Application/BlockchainNodeContextServiceTests.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Node.Application; using AElf.Kernel.Node.Events; using AElf.Types; using Moq; @@ -9,90 +8,89 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Kernel.Node.Application +namespace AElf.Kernel.Node.Application; + +public class BlockchainNodeContextServiceTests : NodeTestBase { - public class BlockchainNodeContextServiceTests : NodeTestBase + private readonly IBlockchainNodeContextService _blockchainNodeContextService; + private readonly IBlockchainService _blockchainService; + private readonly KernelNodeTestContext _kernelNodeTestContext; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ILocalEventBus _localEventBus; + + public BlockchainNodeContextServiceTests() { - private readonly IBlockchainNodeContextService _blockchainNodeContextService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockchainService _blockchainService; - private readonly KernelNodeTestContext _kernelNodeTestContext; - private readonly ILocalEventBus _localEventBus; + _blockchainNodeContextService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelNodeTestContext = GetRequiredService(); + _localEventBus = GetRequiredService(); + } - public BlockchainNodeContextServiceTests() + [Fact] + public async Task Start_Test() + { + var transactions = new List { - _blockchainNodeContextService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelNodeTestContext = GetRequiredService(); - _localEventBus = GetRequiredService(); - } + _kernelTestHelper.GenerateTransaction(), + _kernelTestHelper.GenerateTransaction() + }; - [Fact] - public async Task Start_Test() + var dto = new BlockchainNodeContextStartDto { - var transactions = new List - { - _kernelTestHelper.GenerateTransaction(), - _kernelTestHelper.GenerateTransaction() - }; - - var dto = new BlockchainNodeContextStartDto - { - ChainId = 1234, - ZeroSmartContractType = typeof(IBlockchainNodeContextService), - Transactions = transactions.ToArray() - }; - - _kernelNodeTestContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Never); + ChainId = 1234, + ZeroSmartContractType = typeof(IBlockchainNodeContextService), + Transactions = transactions.ToArray() + }; + + _kernelNodeTestContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Never); - var context = await _blockchainNodeContextService.StartAsync(dto); - _kernelNodeTestContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Once); + var context = await _blockchainNodeContextService.StartAsync(dto); + _kernelNodeTestContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Once); - context.ChainId.ShouldBe(dto.ChainId); - var chain = await _blockchainService.GetChainAsync(); - chain.Id.ShouldBe(dto.ChainId); - chain.BestChainHeight.ShouldBe(1); - var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); - block.Body.TransactionIds.Count.ShouldBe(2); - block.Body.TransactionIds.ShouldContain(transactions[0].GetHash()); - block.Body.TransactionIds.ShouldContain(transactions[1].GetHash()); + context.ChainId.ShouldBe(dto.ChainId); + var chain = await _blockchainService.GetChainAsync(); + chain.Id.ShouldBe(dto.ChainId); + chain.BestChainHeight.ShouldBe(1); + var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); + block.Body.TransactionIds.Count.ShouldBe(2); + block.Body.TransactionIds.ShouldContain(transactions[0].GetHash()); + block.Body.TransactionIds.ShouldContain(transactions[1].GetHash()); - var block2 = await _kernelTestHelper.AttachBlockToBestChain(); - var block3 = await _kernelTestHelper.AttachBlockToBestChain(); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(3); - chain.BestChainHash.ShouldBe(block3.GetHash()); + var block2 = await _kernelTestHelper.AttachBlockToBestChain(); + var block3 = await _kernelTestHelper.AttachBlockToBestChain(); - await _blockchainService.SetIrreversibleBlockAsync(chain, block2.Height, block2.GetHash()); - chain = await _blockchainService.GetChainAsync(); - chain.LastIrreversibleBlockHeight.ShouldBe(2); - - context = await _blockchainNodeContextService.StartAsync(dto); - chain = await _blockchainService.GetChainAsync(); - context.ChainId.ShouldBe(dto.ChainId); - chain.BestChainHeight.ShouldBe(2); - chain.BestChainHash.ShouldBe(block2.GetHash()); - - _kernelNodeTestContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(2)); - } + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(3); + chain.BestChainHash.ShouldBe(block3.GetHash()); - [Fact] - public async Task FinishInitialSync_Test() + await _blockchainService.SetIrreversibleBlockAsync(chain, block2.Height, block2.GetHash()); + chain = await _blockchainService.GetChainAsync(); + chain.LastIrreversibleBlockHeight.ShouldBe(2); + + context = await _blockchainNodeContextService.StartAsync(dto); + chain = await _blockchainService.GetChainAsync(); + context.ChainId.ShouldBe(dto.ChainId); + chain.BestChainHeight.ShouldBe(2); + chain.BestChainHash.ShouldBe(block2.GetHash()); + + _kernelNodeTestContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(2)); + } + + [Fact] + public async Task FinishInitialSync_Test() + { + InitialSyncFinishedEvent eventData = null; + _localEventBus.Subscribe(d => { - InitialSyncFinishedEvent eventData = null; - _localEventBus.Subscribe(d => - { - eventData = d; - return Task.CompletedTask; - }); + eventData = d; + return Task.CompletedTask; + }); - await _blockchainNodeContextService.FinishInitialSyncAsync(); - eventData.ShouldNotBeNull(); - } + await _blockchainNodeContextService.FinishInitialSyncAsync(); + eventData.ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Node.Tests/NodeTestAElfModule.cs b/test/AElf.Kernel.Node.Tests/NodeTestAElfModule.cs index aa19010656..9b424a8399 100644 --- a/test/AElf.Kernel.Node.Tests/NodeTestAElfModule.cs +++ b/test/AElf.Kernel.Node.Tests/NodeTestAElfModule.cs @@ -6,57 +6,55 @@ using AElf.Kernel.SmartContractExecution.Application; using AElf.Modularity; using AElf.Types; -using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.Node +namespace AElf.Kernel.Node; + +[DependsOn(typeof(NodeAElfModule), typeof(KernelCoreTestAElfModule))] +public class NodeTestAElfModule : AElfModule { - [DependsOn(typeof(NodeAElfModule), typeof(KernelCoreTestAElfModule))] - public class NodeTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => { o.ChainId = 1234; }); + Configure(o => { o.ChainId = 1234; }); - var mockConsensusService = new Mock(); - var kernelNodeTestContext = new KernelNodeTestContext() - { - MockConsensusService = mockConsensusService - }; + var mockConsensusService = new Mock(); + var kernelNodeTestContext = new KernelNodeTestContext + { + MockConsensusService = mockConsensusService + }; - context.Services.AddSingleton(kernelNodeTestContext); - context.Services.AddSingleton(mockConsensusService.Object); + context.Services.AddSingleton(kernelNodeTestContext); + context.Services.AddSingleton(mockConsensusService.Object); - context.Services.AddTransient(p => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) - .Returns>((blockHeader, transactions) => + context.Services.AddTransient(p => + { + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) + .Returns>((blockHeader, transactions) => + { + var block = new Block { - var block = new Block + Header = new BlockHeader(blockHeader) { - Header = new BlockHeader(blockHeader) - { - MerkleTreeRootOfTransactions = HashHelper.ComputeFrom("MerkleTreeRootOfTransactions"), - MerkleTreeRootOfWorldState = HashHelper.ComputeFrom("MerkleTreeRootOfWorldState"), - MerkleTreeRootOfTransactionStatus = - HashHelper.ComputeFrom("MerkleTreeRootOfTransactionStatus") - }, - Body = new BlockBody() - }; - block.Body.AddTransactions(transactions.Select(x => x.GetHash())); - return Task.FromResult(new BlockExecutedSet() {Block = block}); - }); - return mockService.Object; - }); - } - } - - public class KernelNodeTestContext - { - public Mock MockConsensusService { get; set; } + MerkleTreeRootOfTransactions = HashHelper.ComputeFrom("MerkleTreeRootOfTransactions"), + MerkleTreeRootOfWorldState = HashHelper.ComputeFrom("MerkleTreeRootOfWorldState"), + MerkleTreeRootOfTransactionStatus = + HashHelper.ComputeFrom("MerkleTreeRootOfTransactionStatus") + }, + Body = new BlockBody() + }; + block.Body.AddTransactions(transactions.Select(x => x.GetHash())); + return Task.FromResult(new BlockExecutedSet { Block = block }); + }); + return mockService.Object; + }); } +} + +public class KernelNodeTestContext +{ + public Mock MockConsensusService { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Node.Tests/NodeTestBase.cs b/test/AElf.Kernel.Node.Tests/NodeTestBase.cs index 34ac412705..604cdeb344 100644 --- a/test/AElf.Kernel.Node.Tests/NodeTestBase.cs +++ b/test/AElf.Kernel.Node.Tests/NodeTestBase.cs @@ -1,9 +1,7 @@ using AElf.TestBase; -namespace AElf.Kernel.Node +namespace AElf.Kernel.Node; + +public class NodeTestBase : AElfIntegratedTest { - public class NodeTestBase : AElfIntegratedTest - { - - } } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/AElf.Kernel.Proposal.Tests.csproj b/test/AElf.Kernel.Proposal.Tests/AElf.Kernel.Proposal.Tests.csproj index 83c4f9466f..f11cfb7f88 100644 --- a/test/AElf.Kernel.Proposal.Tests/AElf.Kernel.Proposal.Tests.csproj +++ b/test/AElf.Kernel.Proposal.Tests/AElf.Kernel.Proposal.Tests.csproj @@ -5,17 +5,17 @@ - - - - - - + + + + + + - - + + @@ -29,7 +29,7 @@ Protobuf\Proto\acs3.proto - + Protobuf\Proto\reference\parliament_contract.proto diff --git a/test/AElf.Kernel.Proposal.Tests/Application/ProposalApprovalTransactionGeneratorTests.cs b/test/AElf.Kernel.Proposal.Tests/Application/ProposalApprovalTransactionGeneratorTests.cs index 5013ec6a14..ff5374551c 100644 --- a/test/AElf.Kernel.Proposal.Tests/Application/ProposalApprovalTransactionGeneratorTests.cs +++ b/test/AElf.Kernel.Proposal.Tests/Application/ProposalApprovalTransactionGeneratorTests.cs @@ -1,78 +1,82 @@ using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.Miner.Application; -using AElf.Kernel.Proposal.Application; using AElf.Kernel.Proposal.Infrastructure; using AElf.Kernel.Txn.Application; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Kernel.Proposal.Tests.Application +namespace AElf.Kernel.Proposal.Tests.Application; + +public class ProposalApprovalTransactionGeneratorTests : ProposalTestBase { - public class ProposalApprovalTransactionGeneratorTests : ProposalTestBase + private readonly ISystemTransactionGenerator _proposalApprovalTransactionGenerator; + private readonly ProposalTestHelper _proposalTestHelper; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + + public ProposalApprovalTransactionGeneratorTests() { - private readonly ISystemTransactionGenerator _proposalApprovalTransactionGenerator; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - private readonly ProposalTestHelper _proposalTestHelper; - - public ProposalApprovalTransactionGeneratorTests() - { - _proposalApprovalTransactionGenerator = GetRequiredService(); - _transactionPackingOptionProvider = GetRequiredService(); - _proposalTestHelper = GetRequiredService(); - } - - [Fact] - public async Task GenerateTransactionsAsync_Without_PackedTransaction_Test() + _proposalApprovalTransactionGenerator = GetRequiredService(); + _transactionPackingOptionProvider = GetRequiredService(); + _proposalTestHelper = GetRequiredService(); + } + + [Fact] + public async Task GenerateTransactionsAsync_Without_PackedTransaction_Test() + { + var address = NormalAddress; + var blockIndex = new BlockIndex { - var address = NormalAddress; - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 10 - }; - var proposalId = HashHelper.ComputeFrom("proposal"); - _proposalTestHelper.AddNotVotedProposalIdList(new List{proposalId}); - - var proposalCacheProvider = GetRequiredService(); - proposalCacheProvider.AddProposal(proposalId, 5); - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, false); - var transactionList = await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, blockIndex.BlockHash); - transactionList.Count.ShouldBe(1); - } - - [Fact] - public async Task GenerateTransactionsAsync_Without_NotApprovedProposal_Test() + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 10 + }; + var proposalId = HashHelper.ComputeFrom("proposal"); + _proposalTestHelper.AddNotVotedProposalIdList(new List { proposalId }); + + var proposalCacheProvider = GetRequiredService(); + proposalCacheProvider.AddProposal(proposalId, 5); + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, false); + var transactionList = + await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, + blockIndex.BlockHash); + transactionList.Count.ShouldBe(1); + } + + [Fact] + public async Task GenerateTransactionsAsync_Without_NotApprovedProposal_Test() + { + var address = NormalAddress; + var blockIndex = new BlockIndex { - var address = NormalAddress; - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 10 - }; - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, true); - var transactionList = await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, blockIndex.BlockHash); - transactionList.Count.ShouldBe(0); - } + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 10 + }; + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, true); + var transactionList = + await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, + blockIndex.BlockHash); + transactionList.Count.ShouldBe(0); + } - [Fact] - public async Task GenerateTransactionsAsync_Success_Test() + [Fact] + public async Task GenerateTransactionsAsync_Success_Test() + { + var address = NormalAddress; + var blockIndex = new BlockIndex { - var address = NormalAddress; - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 10 - }; - var proposalId = HashHelper.ComputeFrom("proposal"); - _proposalTestHelper.AddNotVotedProposalIdList(new List{proposalId}); - - var proposalCacheProvider = GetRequiredService(); - proposalCacheProvider.AddProposal(proposalId, 5); - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, true); - var transactionList = await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, blockIndex.BlockHash); - transactionList.Count.ShouldBe(1); - } + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 10 + }; + var proposalId = HashHelper.ComputeFrom("proposal"); + _proposalTestHelper.AddNotVotedProposalIdList(new List { proposalId }); + + var proposalCacheProvider = GetRequiredService(); + proposalCacheProvider.AddProposal(proposalId, 5); + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(blockIndex, true); + var transactionList = + await _proposalApprovalTransactionGenerator.GenerateTransactionsAsync(address, blockIndex.BlockHeight, + blockIndex.BlockHash); + transactionList.Count.ShouldBe(1); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/Application/ProposalServiceTests.cs b/test/AElf.Kernel.Proposal.Tests/Application/ProposalServiceTests.cs index dd441686d9..ca8eb46985 100644 --- a/test/AElf.Kernel.Proposal.Tests/Application/ProposalServiceTests.cs +++ b/test/AElf.Kernel.Proposal.Tests/Application/ProposalServiceTests.cs @@ -6,146 +6,145 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Proposal.Tests.Application +namespace AElf.Kernel.Proposal.Tests.Application; + +public class ProposalServiceTests : ProposalTestBase { - public class ProposalServiceTests : ProposalTestBase + private readonly IProposalService _proposalService; + private readonly ProposalTestHelper _proposalTestHelper; + + public ProposalServiceTests() + { + _proposalService = GetRequiredService(); + _proposalTestHelper = GetRequiredService(); + } + + [Fact] + public void AddNotApprovedProposalTest() { - private readonly IProposalService _proposalService; - private readonly ProposalTestHelper _proposalTestHelper; + var proposalCacheProvider = GetRequiredService(); - public ProposalServiceTests() { - _proposalService = GetRequiredService(); - _proposalTestHelper = GetRequiredService(); + var proposalId = HashHelper.ComputeFrom("proposal"); + const int height = 100; + _proposalService.AddNotApprovedProposal(proposalId, height); + var exist = proposalCacheProvider.TryGetProposalCreatedHeight(proposalId, out var h); + exist.ShouldBeTrue(); + h.ShouldBe(height); } - [Fact] - public void AddNotApprovedProposalTest() { - var proposalCacheProvider = GetRequiredService(); - - { - var proposalId = HashHelper.ComputeFrom("proposal"); - const int height = 100; - _proposalService.AddNotApprovedProposal(proposalId, height); - var exist = proposalCacheProvider.TryGetProposalCreatedHeight(proposalId, out var h); - exist.ShouldBeTrue(); - h.ShouldBe(height); - } - - { - var proposalId = HashHelper.ComputeFrom("proposal"); - const int height1 = 101; - const int height2 = 100; - _proposalService.AddNotApprovedProposal(proposalId, height1); - _proposalService.AddNotApprovedProposal(proposalId, height2); - var exist = proposalCacheProvider.TryGetProposalCreatedHeight(proposalId, out var h); - exist.ShouldBeTrue(); - h.ShouldBe(height1); - } + var proposalId = HashHelper.ComputeFrom("proposal"); + const int height1 = 101; + const int height2 = 100; + _proposalService.AddNotApprovedProposal(proposalId, height1); + _proposalService.AddNotApprovedProposal(proposalId, height2); + var exist = proposalCacheProvider.TryGetProposalCreatedHeight(proposalId, out var h); + exist.ShouldBeTrue(); + h.ShouldBe(height1); } + } + + [Fact] + public async Task GetNotApprovedProposalIdListTest() + { + var proposalId1 = HashHelper.ComputeFrom("proposalId1"); + var proposalId2 = HashHelper.ComputeFrom("proposalId2"); + var proposalId3 = HashHelper.ComputeFrom("proposalId3"); + var proposalId4 = HashHelper.ComputeFrom("proposalId4"); - [Fact] - public async Task GetNotApprovedProposalIdListTest() + var notApprovedProposalIdList = new List { - var proposalId1 = HashHelper.ComputeFrom("proposalId1"); - var proposalId2 = HashHelper.ComputeFrom("proposalId2"); - var proposalId3 = HashHelper.ComputeFrom("proposalId3"); - var proposalId4 = HashHelper.ComputeFrom("proposalId4"); - - var notApprovedProposalIdList = new List - { - proposalId1, proposalId2, proposalId3, proposalId4 - }; - _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); - - var blockHash = HashHelper.ComputeFrom("BlockHash"); - var blockHeight = 10; - - var proposalCacheProvider = GetRequiredService(); - proposalCacheProvider.AddProposal(proposalId1, 5); - - { - var queryResultNotApprovedProposalIdList = - await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); - queryResultNotApprovedProposalIdList.Count.ShouldBe(1); - queryResultNotApprovedProposalIdList.ShouldContain(proposalId1); - } - - proposalCacheProvider.AddProposal(proposalId2, 6); - { - var queryResultNotApprovedProposalIdList = - await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); - queryResultNotApprovedProposalIdList.Count.ShouldBe(2); - queryResultNotApprovedProposalIdList.ShouldContain(proposalId1); - queryResultNotApprovedProposalIdList.ShouldContain(proposalId2); - } - } - - [Fact] - public async Task GetNotApprovedProposalIdListTest_ReturnEmpty() + proposalId1, proposalId2, proposalId3, proposalId4 + }; + _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); + + var blockHash = HashHelper.ComputeFrom("BlockHash"); + var blockHeight = 10; + + var proposalCacheProvider = GetRequiredService(); + proposalCacheProvider.AddProposal(proposalId1, 5); + { - var proposalId1 = HashHelper.ComputeFrom("proposalId1"); - var proposalId2 = HashHelper.ComputeFrom("proposalId2"); - var proposalId3 = HashHelper.ComputeFrom("proposalId3"); - var proposalId4 = HashHelper.ComputeFrom("proposalId4"); - - var proposalCacheProvider = GetRequiredService(); - proposalCacheProvider.AddProposal(proposalId1, 5); - proposalCacheProvider.AddProposal(proposalId2, 5); - - var notApprovedProposalIdList = new List - { - proposalId3, proposalId4 - }; - _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); - - var blockHash = HashHelper.ComputeFrom("BlockHash"); - var blockHeight = 10; var queryResultNotApprovedProposalIdList = await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); - queryResultNotApprovedProposalIdList.ShouldBeEmpty(); + queryResultNotApprovedProposalIdList.Count.ShouldBe(1); + queryResultNotApprovedProposalIdList.ShouldContain(proposalId1); } - [Fact] - public async Task ClearProposalTest() + proposalCacheProvider.AddProposal(proposalId2, 6); { - var proposalId1 = HashHelper.ComputeFrom("proposalId1"); - var proposalId2 = HashHelper.ComputeFrom("proposalId2"); - var proposalId3 = HashHelper.ComputeFrom("proposalId3"); - var proposalId4 = HashHelper.ComputeFrom("proposalId4"); - - var proposalCacheProvider = GetRequiredService(); - var blockHeight = 5; - - proposalCacheProvider.AddProposal(proposalId1, blockHeight); - proposalCacheProvider.AddProposal(proposalId2, blockHeight); - proposalCacheProvider.AddProposal(proposalId3, blockHeight); - proposalCacheProvider.AddProposal(proposalId4, blockHeight); - - var notApprovedProposalIdList = new List - { - proposalId3, proposalId4 - }; - _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); - var notApprovedPendingProposalIdList = new List - { - proposalId3 - }; - _proposalTestHelper.AddNotVotedPendingProposalIdList(notApprovedPendingProposalIdList); - - var libHash = HashHelper.ComputeFrom("BlockHash"); - var libHeight = blockHeight; - await _proposalService.ClearProposalByLibAsync(libHash, libHeight); - var cachedProposalIdList = proposalCacheProvider.GetAllProposals(); - cachedProposalIdList.Count.ShouldBe(1); - cachedProposalIdList.ShouldContain(proposalId3); - - var blockHash = HashHelper.ComputeFrom("BlockHash"); var queryResultNotApprovedProposalIdList = await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); - queryResultNotApprovedProposalIdList.Count.ShouldBe(1); - queryResultNotApprovedProposalIdList.ShouldContain(proposalId3); + queryResultNotApprovedProposalIdList.Count.ShouldBe(2); + queryResultNotApprovedProposalIdList.ShouldContain(proposalId1); + queryResultNotApprovedProposalIdList.ShouldContain(proposalId2); } } + + [Fact] + public async Task GetNotApprovedProposalIdListTest_ReturnEmpty() + { + var proposalId1 = HashHelper.ComputeFrom("proposalId1"); + var proposalId2 = HashHelper.ComputeFrom("proposalId2"); + var proposalId3 = HashHelper.ComputeFrom("proposalId3"); + var proposalId4 = HashHelper.ComputeFrom("proposalId4"); + + var proposalCacheProvider = GetRequiredService(); + proposalCacheProvider.AddProposal(proposalId1, 5); + proposalCacheProvider.AddProposal(proposalId2, 5); + + var notApprovedProposalIdList = new List + { + proposalId3, proposalId4 + }; + _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); + + var blockHash = HashHelper.ComputeFrom("BlockHash"); + var blockHeight = 10; + var queryResultNotApprovedProposalIdList = + await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); + queryResultNotApprovedProposalIdList.ShouldBeEmpty(); + } + + [Fact] + public async Task ClearProposalTest() + { + var proposalId1 = HashHelper.ComputeFrom("proposalId1"); + var proposalId2 = HashHelper.ComputeFrom("proposalId2"); + var proposalId3 = HashHelper.ComputeFrom("proposalId3"); + var proposalId4 = HashHelper.ComputeFrom("proposalId4"); + + var proposalCacheProvider = GetRequiredService(); + var blockHeight = 5; + + proposalCacheProvider.AddProposal(proposalId1, blockHeight); + proposalCacheProvider.AddProposal(proposalId2, blockHeight); + proposalCacheProvider.AddProposal(proposalId3, blockHeight); + proposalCacheProvider.AddProposal(proposalId4, blockHeight); + + var notApprovedProposalIdList = new List + { + proposalId3, proposalId4 + }; + _proposalTestHelper.AddNotVotedProposalIdList(notApprovedProposalIdList); + var notApprovedPendingProposalIdList = new List + { + proposalId3 + }; + _proposalTestHelper.AddNotVotedPendingProposalIdList(notApprovedPendingProposalIdList); + + var libHash = HashHelper.ComputeFrom("BlockHash"); + var libHeight = blockHeight; + await _proposalService.ClearProposalByLibAsync(libHash, libHeight); + var cachedProposalIdList = proposalCacheProvider.GetAllProposals(); + cachedProposalIdList.Count.ShouldBe(1); + cachedProposalIdList.ShouldContain(proposalId3); + + var blockHash = HashHelper.ComputeFrom("BlockHash"); + var queryResultNotApprovedProposalIdList = + await _proposalService.GetNotApprovedProposalIdListAsync(NormalAddress, blockHash, blockHeight); + queryResultNotApprovedProposalIdList.Count.ShouldBe(1); + queryResultNotApprovedProposalIdList.ShouldContain(proposalId3); + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/Infrastructure/ProposalProviderTests.cs b/test/AElf.Kernel.Proposal.Tests/Infrastructure/ProposalProviderTests.cs index edbb7732c9..4af8775d7d 100644 --- a/test/AElf.Kernel.Proposal.Tests/Infrastructure/ProposalProviderTests.cs +++ b/test/AElf.Kernel.Proposal.Tests/Infrastructure/ProposalProviderTests.cs @@ -1,65 +1,63 @@ using AElf.Kernel.Proposal.Infrastructure; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Kernel.Proposal.Tests.Infrastructure +namespace AElf.Kernel.Proposal.Tests.Infrastructure; + +public class ProposalProviderTests : ProposalTestBase { - public class ProposalProviderTests : ProposalTestBase + private readonly IProposalProvider _proposalProvider; + + public ProposalProviderTests() + { + _proposalProvider = GetRequiredService(); + } + + [Fact] + public void GetAllProposalsTest() { - private readonly IProposalProvider _proposalProvider; + var proposalId = HashHelper.ComputeFrom("ProposalId"); + var blockHeight = 10; + var proposalIdList = _proposalProvider.GetAllProposals(); + proposalIdList.ShouldBeEmpty(); - public ProposalProviderTests() - { - _proposalProvider = GetRequiredService(); - } - - [Fact] - public void GetAllProposalsTest() - { - var proposalId = HashHelper.ComputeFrom("ProposalId"); - var blockHeight = 10; - var proposalIdList = _proposalProvider.GetAllProposals(); - proposalIdList.ShouldBeEmpty(); - - _proposalProvider.AddProposal(proposalId, blockHeight); - proposalIdList = _proposalProvider.GetAllProposals(); - proposalIdList.Count.ShouldBe(1); - proposalIdList.ShouldContain(proposalId); + _proposalProvider.AddProposal(proposalId, blockHeight); + proposalIdList = _proposalProvider.GetAllProposals(); + proposalIdList.Count.ShouldBe(1); + proposalIdList.ShouldContain(proposalId); - var lowerHeight = blockHeight - 1; - _proposalProvider.AddProposal(proposalId, lowerHeight); - proposalIdList = _proposalProvider.GetAllProposals(); - proposalIdList.Count.ShouldBe(1); - proposalIdList.ShouldContain(proposalId); - } - - [Fact] - public void AddProposalTest() - { - var proposalId = HashHelper.ComputeFrom("ProposalId"); - var blockHeight = 10; - _proposalProvider.AddProposal(proposalId, blockHeight); - var exist = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out var height); - exist.ShouldBeTrue(); - height.ShouldBe(blockHeight); + var lowerHeight = blockHeight - 1; + _proposalProvider.AddProposal(proposalId, lowerHeight); + proposalIdList = _proposalProvider.GetAllProposals(); + proposalIdList.Count.ShouldBe(1); + proposalIdList.ShouldContain(proposalId); + } - var lowerHeight = blockHeight - 1; - _proposalProvider.AddProposal(proposalId, lowerHeight); - exist = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out height); - exist.ShouldBeTrue(); - height.ShouldBe(blockHeight); - } + [Fact] + public void AddProposalTest() + { + var proposalId = HashHelper.ComputeFrom("ProposalId"); + var blockHeight = 10; + _proposalProvider.AddProposal(proposalId, blockHeight); + var exist = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out var height); + exist.ShouldBeTrue(); + height.ShouldBe(blockHeight); - [Fact] - public void RemoveProposalByIdTest() - { - var proposalId = HashHelper.ComputeFrom("ProposalId"); - var blockHeight = 10; - _proposalProvider.AddProposal(proposalId, blockHeight); - _proposalProvider.RemoveProposalById(proposalId); - var targetProposal = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out _); - targetProposal.ShouldBeFalse(); - } + var lowerHeight = blockHeight - 1; + _proposalProvider.AddProposal(proposalId, lowerHeight); + exist = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out height); + exist.ShouldBeTrue(); + height.ShouldBe(blockHeight); + } + + [Fact] + public void RemoveProposalByIdTest() + { + var proposalId = HashHelper.ComputeFrom("ProposalId"); + var blockHeight = 10; + _proposalProvider.AddProposal(proposalId, blockHeight); + _proposalProvider.RemoveProposalById(proposalId); + var targetProposal = _proposalProvider.TryGetProposalCreatedHeight(proposalId, out _); + targetProposal.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/ProposalTestBase.cs b/test/AElf.Kernel.Proposal.Tests/ProposalTestBase.cs index 761eccf85b..61bb875e30 100644 --- a/test/AElf.Kernel.Proposal.Tests/ProposalTestBase.cs +++ b/test/AElf.Kernel.Proposal.Tests/ProposalTestBase.cs @@ -2,11 +2,10 @@ using AElf.TestBase; using AElf.Types; -namespace AElf.Kernel.Proposal.Tests +namespace AElf.Kernel.Proposal.Tests; + +public class ProposalTestBase : AElfIntegratedTest { - public class ProposalTestBase : AElfIntegratedTest - { - public static Address NormalAddress = SampleAddress.AddressList.Last(); - public static Address ParliamentContractFakeAddress = SampleAddress.AddressList.First(); - } + public static Address NormalAddress = SampleAddress.AddressList.Last(); + public static Address ParliamentContractFakeAddress = SampleAddress.AddressList.First(); } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/ProposalTestHelper.cs b/test/AElf.Kernel.Proposal.Tests/ProposalTestHelper.cs index 8d1bdae656..5052a3e6d3 100644 --- a/test/AElf.Kernel.Proposal.Tests/ProposalTestHelper.cs +++ b/test/AElf.Kernel.Proposal.Tests/ProposalTestHelper.cs @@ -4,42 +4,41 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.Proposal.Tests +namespace AElf.Kernel.Proposal.Tests; + +public class ProposalTestHelper : ISingletonDependency { - public class ProposalTestHelper : ISingletonDependency - { - private readonly List _notApprovedProposalIdList = new List(); - private readonly List _notApprovedPendingProposalIdList = new List(); + private readonly List _notApprovedPendingProposalIdList = new(); + private readonly List _notApprovedProposalIdList = new(); - internal void AddNotVotedProposalIdList(List proposalIdList) - { - _notApprovedProposalIdList.AddRange(proposalIdList); - } + internal void AddNotVotedProposalIdList(List proposalIdList) + { + _notApprovedProposalIdList.AddRange(proposalIdList); + } - internal void AddNotVotedPendingProposalIdList(List proposalIdList) - { - _notApprovedPendingProposalIdList.AddRange(proposalIdList); - } + internal void AddNotVotedPendingProposalIdList(List proposalIdList) + { + _notApprovedPendingProposalIdList.AddRange(proposalIdList); + } - internal ProposalIdList GetNotVotedProposalIdList(ProposalIdList proposalIdList) + internal ProposalIdList GetNotVotedProposalIdList(ProposalIdList proposalIdList) + { + return new ProposalIdList { - return new ProposalIdList - { - ProposalIds = - {proposalIdList.ProposalIds.Where(proposalId => _notApprovedProposalIdList.Contains(proposalId))} - }; - } + ProposalIds = + { proposalIdList.ProposalIds.Where(proposalId => _notApprovedProposalIdList.Contains(proposalId)) } + }; + } - internal ProposalIdList GetNotVotedPendingProposalIdList(ProposalIdList proposalIdList) + internal ProposalIdList GetNotVotedPendingProposalIdList(ProposalIdList proposalIdList) + { + return new ProposalIdList { - return new ProposalIdList + ProposalIds = { - ProposalIds = - { - proposalIdList.ProposalIds.Where(proposalId => - _notApprovedPendingProposalIdList.Contains(proposalId)) - } - }; - } + proposalIdList.ProposalIds.Where(proposalId => + _notApprovedPendingProposalIdList.Contains(proposalId)) + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Proposal.Tests/ProposalTestModule.cs b/test/AElf.Kernel.Proposal.Tests/ProposalTestModule.cs index cdb90d8d2b..4c2b28054f 100644 --- a/test/AElf.Kernel.Proposal.Tests/ProposalTestModule.cs +++ b/test/AElf.Kernel.Proposal.Tests/ProposalTestModule.cs @@ -10,72 +10,71 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.Proposal.Tests +namespace AElf.Kernel.Proposal.Tests; + +[DependsOn( + typeof(KernelTestAElfModule), + typeof(ProposalAElfModule))] +public class ProposalTestModule : AElfModule { - [DependsOn( - typeof(KernelTestAElfModule), - typeof(ProposalAElfModule))] - public class ProposalTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddTransient(provider => { - context.Services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(o => - o.GetAddressByContractNameAsync(It.IsAny(), It.Is(hash => - hash == ParliamentSmartContractAddressNameProvider.StringName))) - .Returns(Task.FromResult(ProposalTestBase.ParliamentContractFakeAddress)); + var mockService = new Mock(); + mockService.Setup(o => + o.GetAddressByContractNameAsync(It.IsAny(), It.Is(hash => + hash == ParliamentSmartContractAddressNameProvider.StringName))) + .Returns(Task.FromResult(ProposalTestBase.ParliamentContractFakeAddress)); - return mockService.Object; - }); + return mockService.Object; + }); - context.Services.AddTransient(provider => - { - var proposalTestHelper = context.Services.GetServiceLazy().Value; - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns((chainContext, txn, timestamp) => - { - var input = ProposalIdList.Parser.ParseFrom(txn.Params); - if (txn.MethodName == nameof(ParliamentContractContainer.ParliamentContractStub + context.Services.AddTransient(provider => + { + var proposalTestHelper = context.Services.GetServiceLazy().Value; + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns((chainContext, txn, timestamp) => + { + var input = ProposalIdList.Parser.ParseFrom(txn.Params); + if (txn.MethodName == nameof(ParliamentContractContainer.ParliamentContractStub .GetNotVotedProposals)) + { + var notApprovedProposalIdList = proposalTestHelper.GetNotVotedProposalIdList(input); + return Task.FromResult(new TransactionTrace { - var notApprovedProposalIdList = proposalTestHelper.GetNotVotedProposalIdList(input); - return Task.FromResult(new TransactionTrace + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = new ProposalIdList { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = new ProposalIdList - { - ProposalIds = {notApprovedProposalIdList.ProposalIds.Intersect(input.ProposalIds)} - }.ToByteString() - }); - } + ProposalIds = { notApprovedProposalIdList.ProposalIds.Intersect(input.ProposalIds) } + }.ToByteString() + }); + } - if (txn.MethodName == nameof(ParliamentContractContainer.ParliamentContractStub + if (txn.MethodName == nameof(ParliamentContractContainer.ParliamentContractStub .GetNotVotedPendingProposals)) + { + var notApprovedPendingProposalIdList = + proposalTestHelper.GetNotVotedPendingProposalIdList(input); + return Task.FromResult(new TransactionTrace { - var notApprovedPendingProposalIdList = - proposalTestHelper.GetNotVotedPendingProposalIdList(input); - return Task.FromResult(new TransactionTrace + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = new ProposalIdList { - ExecutionStatus = ExecutionStatus.Executed, - ReturnValue = new ProposalIdList - { - ProposalIds = - {notApprovedPendingProposalIdList.ProposalIds.Intersect(input.ProposalIds)} - }.ToByteString() - }); - } + ProposalIds = + { notApprovedPendingProposalIdList.ProposalIds.Intersect(input.ProposalIds) } + }.ToByteString() + }); + } - return null; - }); + return null; + }); - return mockService.Object; - }); - } + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj index 49383883b3..cc88e79370 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract.csproj @@ -4,13 +4,13 @@ AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract - true + true - true + true - + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/Contract.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/Contract.cs index de6b2de89a..bcabe975cd 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/Contract.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/Contract.cs @@ -1,50 +1,45 @@ using AElf.Standards.ACS5; -using AElf.Sdk.CSharp; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract; + +public class Contract : ContractContainer.ContractBase { - public class Contract : ContractContainer.ContractBase + public override Empty SetMethodCallingThreshold(SetMethodCallingThresholdInput input) { - public override Empty SetMethodCallingThreshold(SetMethodCallingThresholdInput input) - { - AssertPerformedByContractOwner(); - - State.MethodCallingThresholdFees[input.Method] = new MethodCallingThreshold - { - SymbolToAmount = { input.SymbolToAmount }, - ThresholdCheckType = input.ThresholdCheckType - }; + AssertPerformedByContractOwner(); - return new Empty(); - } - - public override MethodCallingThreshold GetMethodCallingThreshold(StringValue input) + State.MethodCallingThresholdFees[input.Method] = new MethodCallingThreshold { - if(State.MethodCallingThresholdFees[input.Value] == null) - return new MethodCallingThreshold(); - return new MethodCallingThreshold - { - SymbolToAmount = - { - State.MethodCallingThresholdFees[input.Value].SymbolToAmount - } - }; - } + SymbolToAmount = { input.SymbolToAmount }, + ThresholdCheckType = input.ThresholdCheckType + }; - public override Empty DummyMethod(Empty input) - { - return new Empty(); - } + return new Empty(); + } - private void AssertPerformedByContractOwner() + public override MethodCallingThreshold GetMethodCallingThreshold(StringValue input) + { + if (State.MethodCallingThresholdFees[input.Value] == null) + return new MethodCallingThreshold(); + return new MethodCallingThreshold { - if (State.Acs0Contract.Value == null) + SymbolToAmount = { - State.Acs0Contract.Value = Context.GetZeroSmartContractAddress(); + State.MethodCallingThresholdFees[input.Value].SymbolToAmount } - var contractInfo = State.Acs0Contract.GetContractInfo.Call(Context.Self); - Assert(Context.Sender == contractInfo.Author, "Only owner are permitted to call this method."); - } + }; + } + + public override Empty DummyMethod(Empty input) + { + return new Empty(); + } + + private void AssertPerformedByContractOwner() + { + if (State.Acs0Contract.Value == null) State.Acs0Contract.Value = Context.GetZeroSmartContractAddress(); + var contractInfo = State.Acs0Contract.GetContractInfo.Call(Context.Self); + Assert(Context.Sender == contractInfo.Author, "Only owner are permitted to call this method."); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/ContractState.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/ContractState.cs index 9d9f109d8d..af581a1f50 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/ContractState.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract/ContractState.cs @@ -1,12 +1,11 @@ +using AElf.Sdk.CSharp.State; using AElf.Standards.ACS0; using AElf.Standards.ACS5; -using AElf.Sdk.CSharp.State; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract; + +public class ContractState : Sdk.CSharp.State.ContractState { - public class ContractState : AElf.Sdk.CSharp.State.ContractState - { - public MappedState MethodCallingThresholdFees { get; set; } - internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } - } + public MappedState MethodCallingThresholdFees { get; set; } + internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj index 2ef10f79e6..24c0a485c3 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj @@ -8,21 +8,21 @@ 0436 - - - - - - + + + + + + - - - - + + + + - + false Contract diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTest.cs index bafcdd0172..a247981d73 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTest.cs @@ -1,248 +1,249 @@ using System.Collections.Generic; using System.Linq; -using AElf.Standards.ACS5; using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract; +using AElf.Standards.ACS5; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests; + +public class ExecutionPluginForCallThresholdTest : ExecutionPluginForCallThresholdTestBase { - public class ExecutionPluginForCallThresholdTest : ExecutionPluginForCallThresholdTestBase + [Fact] + public async Task GetPreTransactionsTest() { - [Fact] - public async Task GetPreTransactionsTest() - { - const long feeAmount = 10; - - await InitializeContracts(); - await SetThresholdFee(feeAmount); - - var plugins = Application.ServiceProvider.GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); - var plugin = plugins.SingleOrDefault(p => p.GetType() == typeof(MethodCallingThresholdPreExecutionPlugin)); - plugin.ShouldNotBeNull(); - - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); - var transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + const long feeAmount = 10; + + await InitializeContracts(); + await SetThresholdFee(feeAmount); + + var plugins = Application.ServiceProvider.GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); + var plugin = plugins.SingleOrDefault(p => p.GetType() == typeof(MethodCallingThresholdPreExecutionPlugin)); + plugin.ShouldNotBeNull(); + + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); + var transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TestContractAddress, - MethodName = nameof(DefaultTester.DummyMethod) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.ShouldNotBeEmpty(); - transactions[0].From.ShouldBe(TestContractAddress); - transactions[0].To.ShouldBe(TokenContractAddress); - } + From = DefaultSender, + To = TestContractAddress, + MethodName = nameof(DefaultTester.DummyMethod) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + + transactions.ShouldNotBeEmpty(); + transactions[0].From.ShouldBe(TestContractAddress); + transactions[0].To.ShouldBe(TokenContractAddress); + } - [Fact] - public async Task CheckThreshold_Successful() + [Fact] + public async Task CheckThreshold_Successful() + { + const long feeAmount = 10; + + await InitializeContracts(); + await SetThresholdFee(feeAmount); + + var dummy = await DefaultTester.DummyMethod.SendAsync(new Empty()); + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task CheckThreshold_PreFailed() + { + const long feeAmount = 5_0000_0000L; + + await InitializeContracts(); + await SetThresholdFee(feeAmount); + + var originalBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + })).Balance; + + var targetAmount = originalBalance - feeAmount; + var burnResult = await TokenContractStub.Burn.SendAsync(new BurnInput { - const long feeAmount = 10; - - await InitializeContracts(); - await SetThresholdFee(feeAmount); + Symbol = "ELF", + Amount = targetAmount + 1 + }); + burnResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var dummy = await DefaultTester.DummyMethod.SendWithExceptionAsync(new Empty()); + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + dummy.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold."); + } + + [Fact] + public async Task CheckMultipleThreshold_Enough_ELF() + { + const long elfFeeAmount = 10; + const long ramFeeAmount = 20; + + await InitializeContracts(); + await SetMultipleThresholdFee(elfFeeAmount, ramFeeAmount); + + var ramBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "WRITE" + })).Balance; + + //enough ELF + { + var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Symbol = "WRITE", + To = Address.FromPublicKey(OtherTester.PublicKey), + Amount = ramBalance, + Memo = "transfer write to other user" + }); + transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var dummy = await DefaultTester.DummyMethod.SendAsync(new Empty()); dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - [Fact] - public async Task CheckThreshold_PreFailed() - { - const long feeAmount = 5_0000_0000L; - - await InitializeContracts(); - await SetThresholdFee(feeAmount); + [Fact] + public async Task CheckMultipleThreshold_Enough_RAM() + { + const long elfFeeAmount = 10; + const long writeFeeAmount = 20; - var originalBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "ELF" - })).Balance; + await InitializeContracts(); + await SetMultipleThresholdFee(elfFeeAmount, writeFeeAmount); + + var writeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "WRITE" + })).Balance; - var targetAmount = originalBalance - feeAmount; - var burnResult = await TokenContractStub.Burn.SendAsync(new BurnInput + //enough WRITE + { + var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput { Symbol = "ELF", - Amount = targetAmount + 1 + To = Address.FromPublicKey(OtherTester.PublicKey), + Amount = writeBalance, + Memo = "transfer elf to other user" }); - burnResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var dummy = await DefaultTester.DummyMethod.SendWithExceptionAsync(new Empty()); - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - dummy.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold."); + var dummy = await DefaultTester.DummyMethod.SendAsync(new Empty()); + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - [Fact] - public async Task CheckMultipleThreshold_Enough_ELF() - { - const long elfFeeAmount = 10; - const long ramFeeAmount = 20; + [Fact] + public async Task CheckMultipleThreshold_Failed() + { + const long elfFeeAmount = 1_0000_0000L; + const long ramFeeAmount = 50_0000L; - await InitializeContracts(); - await SetMultipleThresholdFee(elfFeeAmount, ramFeeAmount); - - var ramBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "WRITE" - })).Balance; - - //enough ELF - { - var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "WRITE", - To = Address.FromPublicKey(OtherTester.PublicKey), - Amount = ramBalance, - Memo = "transfer write to other user" - }); - transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var dummy = await DefaultTester.DummyMethod.SendAsync(new Empty()); - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } - - [Fact] - public async Task CheckMultipleThreshold_Enough_RAM() - { - const long elfFeeAmount = 10; - const long writeFeeAmount = 20; + await InitializeContracts(); + await SetMultipleThresholdFee(elfFeeAmount, ramFeeAmount); - await InitializeContracts(); - await SetMultipleThresholdFee(elfFeeAmount, writeFeeAmount); - - var writeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "WRITE" - })).Balance; - - //enough WRITE - { - var transferResult = await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "ELF", - To = Address.FromPublicKey(OtherTester.PublicKey), - Amount = writeBalance, - Memo = "transfer elf to other user" - }); - transferResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var dummy = await DefaultTester.DummyMethod.SendAsync(new Empty()); - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } - - [Fact] - public async Task CheckMultipleThreshold_Failed() + var elfBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + })).Balance; + var writeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - const long elfFeeAmount = 1_0000_0000L; - const long ramFeeAmount = 50_0000L; + Owner = DefaultSender, + Symbol = "WRITE" + })).Balance; - await InitializeContracts(); - await SetMultipleThresholdFee(elfFeeAmount, ramFeeAmount); - - var elfBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "ELF" - })).Balance; - var writeBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + //both ELF and WRITE are not enough + { + var transferElfResult = await TokenContractStub.Transfer.SendAsync(new TransferInput { - Owner = DefaultSender, - Symbol = "WRITE" - })).Balance; - - //both ELF and WRITE are not enough + Symbol = "ELF", + To = Address.FromPublicKey(OtherTester.PublicKey), + Amount = elfBalance - (elfFeeAmount - 50), + Memo = "transfer elf to other user" + }); + transferElfResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transferWriteResult = await TokenContractStub.Transfer.SendAsync(new TransferInput { - var transferElfResult = await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "ELF", - To = Address.FromPublicKey(OtherTester.PublicKey), - Amount = elfBalance - (elfFeeAmount - 50), - Memo = "transfer elf to other user" - }); - transferElfResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var transferWriteResult = await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Symbol = "WRITE", - To = Address.FromPublicKey(OtherTester.PublicKey), - Amount = writeBalance - (ramFeeAmount - 50), - Memo = "transfer write to other user" - }); - transferWriteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var dummy = await DefaultTester.DummyMethod.SendWithExceptionAsync(new Empty()); - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - dummy.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold."); - } - } + Symbol = "WRITE", + To = Address.FromPublicKey(OtherTester.PublicKey), + Amount = writeBalance - (ramFeeAmount - 50), + Memo = "transfer write to other user" + }); + transferWriteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - [Fact] - public async Task GetPreTransactions_Token_CheckThreshold_Test() - { - var plugins = Application.ServiceProvider.GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); - var plugin = plugins.SingleOrDefault(p => p.GetType() == typeof(MethodCallingThresholdPreExecutionPlugin)); - plugin.ShouldNotBeNull(); - - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); - var transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext - { - Transaction = new Transaction - { - From = DefaultSender, - To = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.CheckThreshold) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - transactions.Count.ShouldBe(0); + var dummy = await DefaultTester.DummyMethod.SendWithExceptionAsync(new Empty()); + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + dummy.TransactionResult.Error.ShouldContain("Cannot meet the calling threshold."); } - - private async Task SetThresholdFee(long callingFee) - { - await DefaultTester.SetMethodCallingThreshold.SendAsync(new SetMethodCallingThresholdInput + } + + [Fact] + public async Task GetPreTransactions_Token_CheckThreshold_Test() + { + var plugins = Application.ServiceProvider.GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); + var plugin = plugins.SingleOrDefault(p => p.GetType() == typeof(MethodCallingThresholdPreExecutionPlugin)); + plugin.ShouldNotBeNull(); + + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); + var transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext { - Method = nameof(DefaultTester.DummyMethod), - SymbolToAmount = + Transaction = new Transaction { - {"ELF", callingFee} + From = DefaultSender, + To = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.CheckThreshold) }, - ThresholdCheckType = ThresholdCheckType.Balance - }); + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + transactions.Count.ShouldBe(0); + } - var callingThreshold = await DefaultTester.GetMethodCallingThreshold.CallAsync(new StringValue + private async Task SetThresholdFee(long callingFee) + { + await DefaultTester.SetMethodCallingThreshold.SendAsync(new SetMethodCallingThresholdInput + { + Method = nameof(DefaultTester.DummyMethod), + SymbolToAmount = { - Value = nameof(DefaultTester.DummyMethod) - }); - callingThreshold.SymbolToAmount["ELF"].ShouldBe(callingFee); - } + { "ELF", callingFee } + }, + ThresholdCheckType = ThresholdCheckType.Balance + }); - private async Task SetMultipleThresholdFee(long elfFeeAmount, long writeFeeAmount) + var callingThreshold = await DefaultTester.GetMethodCallingThreshold.CallAsync(new StringValue { - var setThresholdResult = await DefaultTester.SetMethodCallingThreshold.SendAsync(new SetMethodCallingThresholdInput + Value = nameof(DefaultTester.DummyMethod) + }); + callingThreshold.SymbolToAmount["ELF"].ShouldBe(callingFee); + } + + private async Task SetMultipleThresholdFee(long elfFeeAmount, long writeFeeAmount) + { + var setThresholdResult = await DefaultTester.SetMethodCallingThreshold.SendAsync( + new SetMethodCallingThresholdInput { Method = nameof(DefaultTester.DummyMethod), SymbolToAmount = @@ -252,14 +253,13 @@ private async Task SetMultipleThresholdFee(long elfFeeAmount, long writeFeeAmoun }, ThresholdCheckType = ThresholdCheckType.Balance }); - setThresholdResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + setThresholdResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var callingThreshold = await DefaultTester.GetMethodCallingThreshold.CallAsync(new StringValue - { - Value = nameof(DefaultTester.DummyMethod) - }); - callingThreshold.SymbolToAmount["ELF"].ShouldBe(elfFeeAmount); - callingThreshold.SymbolToAmount["WRITE"].ShouldBe(writeFeeAmount); - } + var callingThreshold = await DefaultTester.GetMethodCallingThreshold.CallAsync(new StringValue + { + Value = nameof(DefaultTester.DummyMethod) + }); + callingThreshold.SymbolToAmount["ELF"].ShouldBe(elfFeeAmount); + callingThreshold.SymbolToAmount["WRITE"].ShouldBe(writeFeeAmount); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs index 3f6f3036c0..62a7a04a85 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs @@ -1,154 +1,153 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; -using AElf.ContractTestKit; using AElf.Contracts.TokenConverter; +using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.EconomicSystem; +using AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract; using AElf.Kernel.Token; using AElf.Types; using Shouldly; -using InitializeInput = AElf.Contracts.TokenConverter.InitializeInput; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests; + +public class ExecutionPluginForCallThresholdTestBase : ContractTestBase { - public class ExecutionPluginForCallThresholdTestBase : ContractTestBase + //init connector + internal Connector ELFConnector = new() + { + Symbol = "ELF", + VirtualBalance = 100_0000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true + }; + + internal Connector WriteConnector = new() { - //init connector - internal Connector ELFConnector = new Connector + Symbol = "WRITE", + VirtualBalance = 0, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = false + }; + + internal Address TestContractAddress { get; set; } + internal Address TokenContractAddress { get; set; } + internal Address TokenConverterAddress { get; set; } + internal ContractContainer.ContractStub DefaultTester { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } + + internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + internal ECKeyPair OtherTester => Accounts[1].KeyPair; + internal Address DefaultSender => Address.FromPublicKey(DefaultSenderKeyPair.PublicKey); + protected ECKeyPair FeeReceiverKeyPair => Accounts[10].KeyPair; + protected Address FeeReceiverAddress => Accounts[10].Address; + protected ECKeyPair ManagerKeyPair => Accounts[11].KeyPair; + protected Address ManagerAddress => Accounts[11].Address; + + protected async Task InitializeContracts() + { + await DeployContractsAsync(); + await InitializeTokenAsync(); + await InitializeTokenConverterAsync(); + } + + private async Task DeployContractsAsync() + { + const int category = KernelConstants.CodeCoverageRunnerCategory; + //Token contract { - Symbol = "ELF", - VirtualBalance = 100_0000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true - }; + var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + TokenContractAddress = await DeploySystemSmartContract(category, code, + TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TokenContractStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); + } - internal Connector WriteConnector = new Connector + //Token converter { - Symbol = "WRITE", - VirtualBalance = 0, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = false - }; + var code = Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value; + TokenConverterAddress = await DeploySystemSmartContract(category, code, + TokenConverterSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TokenConverterContractStub = + GetTester(TokenConverterAddress, + DefaultSenderKeyPair); + } - internal Address TestContractAddress { get; set; } - internal Address TokenContractAddress { get; set; } - internal Address TokenConverterAddress { get; set; } - internal TestContract.ContractContainer.ContractStub DefaultTester { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } - - internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - internal ECKeyPair OtherTester => Accounts[1].KeyPair; - internal Address DefaultSender => Address.FromPublicKey(DefaultSenderKeyPair.PublicKey); - protected ECKeyPair FeeReceiverKeyPair => Accounts[10].KeyPair; - protected Address FeeReceiverAddress => Accounts[10].Address; - protected ECKeyPair ManagerKeyPair => Accounts[11].KeyPair; - protected Address ManagerAddress => Accounts[11].Address; - - protected async Task InitializeContracts() + //Test contract { - await DeployContractsAsync(); - await InitializeTokenAsync(); - await InitializeTokenConverterAsync(); + var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; + TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), + DefaultSenderKeyPair); + DefaultTester = + GetTester(TestContractAddress, DefaultSenderKeyPair); } + } - private async Task DeployContractsAsync() + private async Task InitializeTokenAsync() + { + //init elf token { - const int category = KernelConstants.CodeCoverageRunnerCategory; - //Token contract + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - TokenContractAddress = await DeploySystemSmartContract(category, code, - TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TokenContractStub = - GetTester(TokenContractAddress, DefaultSenderKeyPair); - } - - //Token converter - { - var code = Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value; - TokenConverterAddress = await DeploySystemSmartContract(category, code, - TokenConverterSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TokenConverterContractStub = - GetTester(TokenConverterAddress, - DefaultSenderKeyPair); - } - - //Test contract + Symbol = "ELF", + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = 1000_00000000L, + Issuer = DefaultSender + }); + + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; - TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), - DefaultSenderKeyPair); - DefaultTester = - GetTester(TestContractAddress, DefaultSenderKeyPair); - } + Symbol = "ELF", + Amount = 1000_00000000L, + To = DefaultSender, + Memo = "Set for elf token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private async Task InitializeTokenAsync() + //init resource token { - //init elf token + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "ELF", - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = 1000_00000000L, - Issuer = DefaultSender - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = 1000_00000000L, - To = DefaultSender, - Memo = "Set for elf token converter." - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - //init resource token + Symbol = "WRITE", + Decimals = 2, + IsBurnable = true, + TokenName = "WRITE token", + TotalSupply = 1000_0000L, + Issuer = DefaultSender + }); + + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "WRITE", - Decimals = 2, - IsBurnable = true, - TokenName = "WRITE token", - TotalSupply = 1000_0000L, - Issuer = DefaultSender - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "WRITE", - Amount = 1000_000L, - To = DefaultSender, - Memo = "Set for net token converter." - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = "WRITE", + Amount = 1000_000L, + To = DefaultSender, + Memo = "Set for net token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + } - private async Task InitializeTokenConverterAsync() + private async Task InitializeTokenConverterAsync() + { + var input = new InitializeInput { - var input = new InitializeInput - { - BaseTokenSymbol = "WRITE", - FeeRate = "0.005", - Connectors = { ELFConnector, WriteConnector } - }; + BaseTokenSymbol = "WRITE", + FeeRate = "0.005", + Connectors = { ELFConnector, WriteConnector } + }; - var initializeResult = await TokenConverterContractStub.Initialize.SendAsync(input); - initializeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var initializeResult = await TokenConverterContractStub.Initialize.SendAsync(input); + initializeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestModule.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestModule.cs index 7d4c1b9c63..dbf2a00ee1 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestModule.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestModule.cs @@ -1,22 +1,20 @@ using AElf.ContractTestKit; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract.Application; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests; + +[DependsOn(typeof(ContractTestModule), + typeof(ExecutionPluginForCallThresholdModule))] +public class ExecutionPluginForCallThresholdTestModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule), - typeof(ExecutionPluginForCallThresholdModule))] - public class ExecutionPluginForCallThresholdTestModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.AddSingleton(); - // context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); + // context.Services.AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj index fbb0f3ff4c..d2729b3029 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract.csproj @@ -4,13 +4,13 @@ AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract - true + true - true + true - + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/Contract.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/Contract.cs index be60bc90aa..61bed98bfc 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/Contract.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/Contract.cs @@ -1,25 +1,24 @@ using AElf.Standards.ACS1; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract; + +public class Contract : ContractContainer.ContractBase { - public class Contract : ContractContainer.ContractBase + public override Empty DummyMethod(Empty input) { - public override Empty DummyMethod(Empty input) - { - // Do nothing - return new Empty(); - } + // Do nothing + return new Empty(); + } - public override Empty SetMethodFee(MethodFees input) - { - State.TransactionFees[input.MethodName] = input; - return new Empty(); - } + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); + } - public override MethodFees GetMethodFee(StringValue input) - { - return State.TransactionFees[input.Value]; - } + public override MethodFees GetMethodFee(StringValue input) + { + return State.TransactionFees[input.Value]; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/ContractState.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/ContractState.cs index 0b42167d11..b82998b0b4 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/ContractState.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract/ContractState.cs @@ -1,10 +1,9 @@ -using AElf.Standards.ACS1; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; + +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract +public class ContractState : Sdk.CSharp.State.ContractState { - public class ContractState : AElf.Sdk.CSharp.State.ContractState - { - public MappedState TransactionFees { get; set; } - } + public MappedState TransactionFees { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AEDPoSContractInitializationDataProvider.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AEDPoSContractInitializationDataProvider.cs index 626d7d099c..938a04af6c 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AEDPoSContractInitializationDataProvider.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AEDPoSContractInitializationDataProvider.cs @@ -3,20 +3,19 @@ using AElf.Kernel.Consensus.AEDPoS; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class AEDPoSContractInitializationDataProvider : IAEDPoSContractInitializationDataProvider { - public class AEDPoSContractInitializationDataProvider: IAEDPoSContractInitializationDataProvider + public AEDPoSContractInitializationData GetContractInitializationData() { - public AEDPoSContractInitializationData GetContractInitializationData() + return new AEDPoSContractInitializationData { - return new AEDPoSContractInitializationData - { - MiningInterval = 4000, - PeriodSeconds = 604800, - StartTimestamp = new Timestamp {Seconds = 0}, - InitialMinerList = new List {SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex()}, - MinerIncreaseInterval = 31536000 - }; - } + MiningInterval = 4000, + PeriodSeconds = 604800, + StartTimestamp = new Timestamp { Seconds = 0 }, + InitialMinerList = new List { SampleAccount.Accounts[0].KeyPair.PublicKey.ToHex() }, + MinerIncreaseInterval = 31536000 + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj index db99acb9e1..93b9c8a963 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj @@ -10,20 +10,20 @@ - - - - - - + + + + + + - - - + + + - + false Contract diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 2337a20a95..5b5ef2633a 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -1,351 +1,356 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class ExecutePluginTransactionDirectlyTest : ExecutePluginTransactionDirectlyForMethodFeeTestBase { - public class ExecutePluginTransactionDirectlyTest: ExecutePluginTransactionDirectlyForMethodFeeTestBase + [Fact] + public async Task ChargeTransactionFees_Invalid_Input_Test() { - [Fact] - public async Task ChargeTransactionFees_Invalid_Input_Test() + // contract address should not be null { - // contract address should not be null - { - var ret = - await TokenContractStub.ChargeTransactionFees.SendWithExceptionAsync(new ChargeTransactionFeesInput - { - MethodName = "asd" - }); - ret.TransactionResult.Error.ShouldContain("Invalid charge transaction fees input"); - } + var ret = + await TokenContractStub.ChargeTransactionFees.SendWithExceptionAsync(new ChargeTransactionFeesInput + { + MethodName = "asd" + }); + ret.TransactionResult.Error.ShouldContain("Invalid charge transaction fees input"); } - - [Fact] - public async Task ChargeTransactionFees_Without_Primary_Token_Test() + } + + [Fact] + public async Task ChargeTransactionFees_Without_Primary_Token_Test() + { + await IssueTokenAsync(NativeTokenSymbol, 100000_00000000); + var address = DefaultSender; + var nativeTokenSymbol = NativeTokenSymbol; + var methodName = nameof(TokenContractContainer.TokenContractStub.Create); + + // input With Primary Token + await SetPrimaryTokenSymbolAsync(); + var beforeChargeBalance = await GetBalanceAsync(address, nativeTokenSymbol); + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(new ChargeTransactionFeesInput { - await IssueTokenAsync(NativeTokenSymbol, 100000_00000000); - var address = DefaultSender; - var nativeTokenSymbol = NativeTokenSymbol; - var methodName = nameof(TokenContractContainer.TokenContractStub.Create); - - // input With Primary Token - await SetPrimaryTokenSymbolAsync(); - var beforeChargeBalance = await GetBalanceAsync(address, nativeTokenSymbol); - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(new ChargeTransactionFeesInput - { - ContractAddress = TokenContractAddress, - MethodName = methodName, - }); - chargeFeeRet.Output.Success.ShouldBe(true); - var afterChargeBalance = await GetBalanceAsync(address, nativeTokenSymbol); - afterChargeBalance.ShouldBeLessThan(beforeChargeBalance); - } + ContractAddress = TokenContractAddress, + MethodName = methodName + }); + chargeFeeRet.Output.Success.ShouldBe(true); + var afterChargeBalance = await GetBalanceAsync(address, nativeTokenSymbol); + afterChargeBalance.ShouldBeLessThan(beforeChargeBalance); + } - [Fact] - public async Task Set_Repeat_Token_Test() + [Fact] + public async Task Set_Repeat_Token_Test() + { + await IssueTokenAsync(NativeTokenSymbol, 100000_00000000); + await SetPrimaryTokenSymbolAsync(); + var address = DefaultSender; + var methodName = nameof(TokenContractContainer.TokenContractStub.Transfer); + var basicMethodFee = 1000; + var methodFee = new MethodFees { - await IssueTokenAsync(NativeTokenSymbol, 100000_00000000); - await SetPrimaryTokenSymbolAsync(); - var address = DefaultSender; - var methodName = nameof(TokenContractContainer.TokenContractStub.Transfer); - var basicMethodFee = 1000; - var methodFee = new MethodFees + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = + new MethodFee { - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicMethodFee - }, - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicMethodFee - } + Symbol = NativeTokenSymbol, + BasicFee = basicMethodFee + }, + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicMethodFee } - }; - var sizeFee = 0; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - var beforeChargeBalance = await GetBalanceAsync(address, NativeTokenSymbol); - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = methodName, - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; + } + }; + var sizeFee = 0; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + var beforeChargeBalance = await GetBalanceAsync(address, NativeTokenSymbol); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = methodName, + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee + }; - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBeTrue(); - var afterChargeBalance = await GetBalanceAsync(address, NativeTokenSymbol); - beforeChargeBalance.Sub(afterChargeBalance).ShouldBe(basicMethodFee.Add(basicMethodFee)); - } - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBeTrue(); + var afterChargeBalance = await GetBalanceAsync(address, NativeTokenSymbol); + beforeChargeBalance.Sub(afterChargeBalance).ShouldBe(basicMethodFee.Add(basicMethodFee)); + } - // 1 => ELF 2 => CWJ 3 => YPA method fee : native token: 1000 - [Theory] - [InlineData(new []{1,2,3}, new []{10000L, 0, 0}, new []{1,1,1}, new []{1,1,1}, 1000, "ELF", 2000, true)] - [InlineData(new []{2,1,3}, new []{10000L, 10000L, 0}, new []{1,1,1}, new []{1,1,1}, 1000, "CWJ", 1000, true)] - [InlineData(new []{2,1,3}, new []{10000L, 10000L, 0}, new []{1,1,1}, new []{2,1,1}, 1000, "CWJ", 2000, true)] - [InlineData(new []{2,1,3}, new []{10000L, 10000L, 0}, new []{4,1,1}, new []{2,1,1}, 1000, "CWJ", 500, true)] - [InlineData(new []{2,1,3}, new []{100L, 1000L, 0}, new []{1,1,1}, new []{1,1,1}, 1000, "CWJ", 100, false)] - [InlineData(new []{3,1,2}, new []{10L, 1000L, 100}, new []{1,1,1}, new []{1,1,1}, 1000, "YPA", 10, false)] - public async Task ChargeTransactionFees_With_Different_Transaction_Size_Fee_Token(int[] order, long[] balance, - int[] baseWeight, int[] tokenWeight, long sizeFee, string chargeSymbol, long chargeAmount, bool isSuccess) - { - await SetPrimaryTokenSymbolAsync(); - var methodName = nameof(TokenContractContainer.TokenContractStub.Transfer); - var basicMethodFee = 1000; - var methodFee = new MethodFees + // 1 => ELF 2 => CWJ 3 => YPA method fee : native token: 1000 + [Theory] + [InlineData(new[] { 1, 2, 3 }, new[] { 10000L, 0, 0 }, new[] { 1, 1, 1 }, new[] { 1, 1, 1 }, 1000, "ELF", 2000, + true)] + [InlineData(new[] { 2, 1, 3 }, new[] { 10000L, 10000L, 0 }, new[] { 1, 1, 1 }, new[] { 1, 1, 1 }, 1000, "CWJ", 1000, + true)] + [InlineData(new[] { 2, 1, 3 }, new[] { 10000L, 10000L, 0 }, new[] { 1, 1, 1 }, new[] { 2, 1, 1 }, 1000, "CWJ", 2000, + true)] + [InlineData(new[] { 2, 1, 3 }, new[] { 10000L, 10000L, 0 }, new[] { 4, 1, 1 }, new[] { 2, 1, 1 }, 1000, "CWJ", 500, + true)] + [InlineData(new[] { 2, 1, 3 }, new[] { 100L, 1000L, 0 }, new[] { 1, 1, 1 }, new[] { 1, 1, 1 }, 1000, "CWJ", 100, + false)] + [InlineData(new[] { 3, 1, 2 }, new[] { 10L, 1000L, 100 }, new[] { 1, 1, 1 }, new[] { 1, 1, 1 }, 1000, "YPA", 10, + false)] + public async Task ChargeTransactionFees_With_Different_Transaction_Size_Fee_Token(int[] order, long[] balance, + int[] baseWeight, int[] tokenWeight, long sizeFee, string chargeSymbol, long chargeAmount, bool isSuccess) + { + await SetPrimaryTokenSymbolAsync(); + + var methodName = nameof(TokenContractContainer.TokenContractStub.Transfer); + var basicMethodFee = 1000; + var methodFee = new MethodFees + { + MethodName = methodName, + Fees = { - MethodName = methodName, - Fees = + new MethodFee { - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicMethodFee - } + Symbol = NativeTokenSymbol, + BasicFee = basicMethodFee } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - var tokenSymbolList = new [] {NativeTokenSymbol, "CWJ", "YPA"}; - var tokenCount = 3; - var orderedSymbolList = new string[tokenCount]; - var index = 0; - foreach (var o in order) - { - orderedSymbolList[index++] = tokenSymbolList[o - 1]; } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + var tokenSymbolList = new[] { NativeTokenSymbol, "CWJ", "YPA" }; + var tokenCount = 3; + var orderedSymbolList = new string[tokenCount]; + var index = 0; + foreach (var o in order) orderedSymbolList[index++] = tokenSymbolList[o - 1]; - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee(); - for (var i = 0; i < tokenCount; i++) + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee(); + for (var i = 0; i < tokenCount; i++) + { + var tokenSymbol = orderedSymbolList[i]; + if (tokenSymbol != NativeTokenSymbol) + await CreateTokenAsync(DefaultSender, tokenSymbol); + if (balance[i] > 0) + await IssueTokenAsync(tokenSymbol, balance[i]); + sizeFeeSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee { - var tokenSymbol = orderedSymbolList[i]; - if (tokenSymbol != NativeTokenSymbol) - await CreateTokenAsync(DefaultSender, tokenSymbol); - if(balance[i] > 0) - await IssueTokenAsync(tokenSymbol, balance[i]); - sizeFeeSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee - { - TokenSymbol = tokenSymbol, - AddedTokenWeight = tokenWeight[i], - BaseTokenWeight = baseWeight[i] - }); - } + TokenSymbol = tokenSymbol, + AddedTokenWeight = tokenWeight[i], + BaseTokenWeight = baseWeight[i] + }); + } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var beforeBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = methodName, - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var beforeBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = methodName, + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(isSuccess); - var afterBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); - for (var i = 0; i < tokenCount; i++) - { - var balanceDiff = beforeBalanceList[i] - afterBalanceList[i]; - if(orderedSymbolList[i] == chargeSymbol) - balanceDiff.ShouldBe(chargeAmount); - else - { - if (orderedSymbolList[i] == NativeTokenSymbol) - balanceDiff -= basicMethodFee; - balanceDiff.ShouldBe(0); - } - } - } - - [Theory] - [InlineData(new[] {100L, 100, 100}, new[] {100L, 100, 100}, new[] {0L, 0, 0}, true)] - [InlineData(new[] {100L, 100, 100}, new[] {20L, 30, 40}, new[] {80L, 70, 60}, true)] - [InlineData(new[] {100L, 100, 100}, new[] {120L, 130, 140}, new[] {0L, 0, 0}, true)] - [InlineData(new[] {100L, 100, 100}, new[] {100L, 100, 100}, new[] {0L, 0, 0}, false)] - [InlineData(new[] {100L, 100, 100}, new[] {20L, 30, 40}, new[] {80L, 70, 60}, false)] - [InlineData(new[] {100L, 100, 100}, new[] {120L, 130, 140}, new[] {0L, 0, 0}, false)] - public async Task DonateResourceToken_Test(long[] initialBalances, long[] tokenFee, long[] lastBalances, - bool isMainChain) + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(isSuccess); + var afterBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); + for (var i = 0; i < tokenCount; i++) { - var symbolList = new [] {"WEO", "CWJ", "YPA"}; - var feeMap = new TotalResourceTokensMaps(); - for (var i = 0; i < symbolList.Length; i++) + var balanceDiff = beforeBalanceList[i] - afterBalanceList[i]; + if (orderedSymbolList[i] == chargeSymbol) { - await CreateTokenAsync(DefaultSender, symbolList[i]); - await IssueTokenAsync(symbolList[i], initialBalances[i]); - feeMap.Value.Add(new ContractTotalResourceTokens - { - ContractAddress = DefaultSender, - TokensMap = new TotalResourceTokensMap - { - Value = { {symbolList[i], tokenFee[i]}} - } - }); + balanceDiff.ShouldBe(chargeAmount); } - - if (!isMainChain) + else { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), - new InitializeFromParentChainInput - { - Creator = defaultParliament - }); - } - await TokenContractStub.DonateResourceToken.SendAsync(feeMap); - - for (var i = 0; i < symbolList.Length; i++) - { - var balance = await GetBalanceAsync(DefaultSender,symbolList[i]); - balance.ShouldBe(lastBalances[i]); - if (!isMainChain) - { - var consensusBalance = await GetBalanceAsync(ConsensusContractAddress, symbolList[i]); - consensusBalance.ShouldBe(initialBalances[i] - lastBalances[i]); - } + if (orderedSymbolList[i] == NativeTokenSymbol) + balanceDiff -= basicMethodFee; + balanceDiff.ShouldBe(0); } } + } - [Fact] - public async Task ClaimTransactionFee_Balance_WithOut_Receiver_Test() + [Theory] + [InlineData(new[] { 100L, 100, 100 }, new[] { 100L, 100, 100 }, new[] { 0L, 0, 0 }, true)] + [InlineData(new[] { 100L, 100, 100 }, new[] { 20L, 30, 40 }, new[] { 80L, 70, 60 }, true)] + [InlineData(new[] { 100L, 100, 100 }, new[] { 120L, 130, 140 }, new[] { 0L, 0, 0 }, true)] + [InlineData(new[] { 100L, 100, 100 }, new[] { 100L, 100, 100 }, new[] { 0L, 0, 0 }, false)] + [InlineData(new[] { 100L, 100, 100 }, new[] { 20L, 30, 40 }, new[] { 80L, 70, 60 }, false)] + [InlineData(new[] { 100L, 100, 100 }, new[] { 120L, 130, 140 }, new[] { 0L, 0, 0 }, false)] + public async Task DonateResourceToken_Test(long[] initialBalances, long[] tokenFee, long[] lastBalances, + bool isMainChain) + { + var symbolList = new[] { "WEO", "CWJ", "YPA" }; + var feeMap = new TotalResourceTokensMaps(); + for (var i = 0; i < symbolList.Length; i++) { - var tokenSymbol = "JAN"; - var feeAmount = 10000; - await CreateTokenAsync(DefaultSender, tokenSymbol); - var beforeBurned = await GetTokenSupplyAmount(tokenSymbol); - var claimFeeInput = new TotalTransactionFeesMap + await CreateTokenAsync(DefaultSender, symbolList[i]); + await IssueTokenAsync(symbolList[i], initialBalances[i]); + feeMap.Value.Add(new ContractTotalResourceTokens { - Value = + ContractAddress = DefaultSender, + TokensMap = new TotalResourceTokensMap { - {tokenSymbol, feeAmount} + Value = { { symbolList[i], tokenFee[i] } } } - }; - await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); - var afterBurned = await GetTokenSupplyAmount(tokenSymbol); - (beforeBurned - afterBurned).ShouldBe(feeAmount); + }); } - - [Fact] - public async Task ClaimTransactionFee_Balance_With_Receiver_Test() + + if (!isMainChain) { - var tokenSymbol = "JAN"; - var feeAmount = 10000; - await CreateTokenAsync(DefaultSender, tokenSymbol); - var receiver = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var input = new InitializeFromParentChainInput - { - Creator = receiver - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), input); + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetFeeReceiver), receiver); - var beforeBurned = await GetTokenSupplyAmount(tokenSymbol); - var beforeBalance = await GetBalanceAsync(receiver, tokenSymbol); - var claimFeeInput = new TotalTransactionFeesMap - { - Value = + nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), + new InitializeFromParentChainInput { - {tokenSymbol, feeAmount} - } - }; - await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); - var afterBurned = await GetTokenSupplyAmount(tokenSymbol); - var afterBalance = await GetBalanceAsync(receiver, tokenSymbol); - var shouldBurned = feeAmount.Div(10); - (beforeBurned - afterBurned).ShouldBe(shouldBurned); - (afterBalance - beforeBalance).ShouldBe(feeAmount - shouldBurned); + Creator = defaultParliament + }); } - private async Task GetTokenSupplyAmount(string tokenSymbol) + await TokenContractStub.DonateResourceToken.SendAsync(feeMap); + + for (var i = 0; i < symbolList.Length; i++) { - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + var balance = await GetBalanceAsync(DefaultSender, symbolList[i]); + balance.ShouldBe(lastBalances[i]); + if (!isMainChain) { - Symbol = tokenSymbol - }); - return tokenInfo.Supply; + var consensusBalance = await GetBalanceAsync(ConsensusContractAddress, symbolList[i]); + consensusBalance.ShouldBe(initialBalances[i] - lastBalances[i]); + } } + } - private async Task> GetDefaultBalancesAsync(string[] tokenSymbolList) + [Fact] + public async Task ClaimTransactionFee_Balance_WithOut_Receiver_Test() + { + var tokenSymbol = "JAN"; + var feeAmount = 10000; + await CreateTokenAsync(DefaultSender, tokenSymbol); + var beforeBurned = await GetTokenSupplyAmount(tokenSymbol); + var claimFeeInput = new TotalTransactionFeesMap { - var balances = new List(); - foreach (var symbol in tokenSymbolList) - balances.Add(await GetBalanceAsync(DefaultSender,symbol)); - return balances; - } + Value = + { + { tokenSymbol, feeAmount } + } + }; + await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); + (beforeBurned - afterBurned).ShouldBe(feeAmount); + } - private async Task CreateTokenAsync(Address creator, string tokenSymbol, bool isBurned = true) + [Fact] + public async Task ClaimTransactionFee_Balance_With_Receiver_Test() + { + var tokenSymbol = "JAN"; + var feeAmount = 10000; + await CreateTokenAsync(DefaultSender, tokenSymbol); + var receiver = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var input = new InitializeFromParentChainInput + { + Creator = receiver + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), input); + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetFeeReceiver), receiver); + var beforeBurned = await GetTokenSupplyAmount(tokenSymbol); + var beforeBalance = await GetBalanceAsync(receiver, tokenSymbol); + var claimFeeInput = new TotalTransactionFeesMap { - await TokenContractStub.Create.SendAsync(new CreateInput + Value = { - Symbol = tokenSymbol, - TokenName = tokenSymbol + " name", - TotalSupply = 1000_00000000, - IsBurnable = isBurned, - Issuer = creator, - }); - } + { tokenSymbol, feeAmount } + } + }; + await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); + var afterBalance = await GetBalanceAsync(receiver, tokenSymbol); + var shouldBurned = feeAmount.Div(10); + (beforeBurned - afterBurned).ShouldBe(shouldBurned); + (afterBalance - beforeBalance).ShouldBe(feeAmount - shouldBurned); + } - private async Task IssueTokenAsync(string tokenSymbol, long amount) + private async Task GetTokenSupplyAmount(string tokenSymbol) + { + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = tokenSymbol, - Amount = amount, - To = DefaultSender, - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = tokenSymbol + }); + return tokenInfo.Supply; + } - // single node - private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, IMessage input) + private async Task> GetDefaultBalancesAsync(string[] tokenSymbolList) + { + var balances = new List(); + foreach (var symbol in tokenSymbolList) + balances.Add(await GetBalanceAsync(DefaultSender, symbol)); + return balances; + } + + private async Task CreateTokenAsync(Address creator, string tokenSymbol, bool isBurned = true) + { + await TokenContractStub.Create.SendAsync(new CreateInput { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = defaultParliament, - ToAddress = contractAddress, - Params = input.ToByteString(), - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = createProposalRet.Output; - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = tokenSymbol, + TokenName = tokenSymbol + " name", + TotalSupply = 1000_00000000, + IsBurnable = isBurned, + Issuer = creator + }); + } - private async Task GetBalanceAsync(Address address, string tokenSymbol) + private async Task IssueTokenAsync(string tokenSymbol, long amount) + { + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = tokenSymbol, - Owner = address - }); - return balance.Balance; - } - + Symbol = tokenSymbol, + Amount = amount, + To = DefaultSender + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + // single node + private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, + IMessage input) + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = defaultParliament, + ToAddress = contractAddress, + Params = input.ToByteString(), + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = createProposalRet.Output; + await ParliamentContractStub.Approve.SendAsync(proposalId); + var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private async Task GetBalanceAsync(Address address, string tokenSymbol) + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = tokenSymbol, + Owner = address + }); + return balance.Balance; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs index fd6fc1a0ea..f8707ff049 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Cryptography.ECDSA; @@ -10,482 +9,479 @@ using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Domain; -using AElf.Kernel.SmartContract.Events; -using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.TestContract; using AElf.Kernel.Token; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -using Xunit; using Shouldly; -using Volo.Abp.EventBus; +using Xunit; + +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +public sealed class ExecutionPluginForMethodFeeTest : ExecutionPluginForMethodFeeTestBase { - public sealed class ExecutionPluginForMethodFeeTest : ExecutionPluginForMethodFeeTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; + private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; + private Address _testContractAddress; + private ContractContainer.ContractStub _testContractStub; + + public ExecutionPluginForMethodFeeTest() { - private Address _testContractAddress; - private TestContract.ContractContainer.ContractStub _testContractStub; - private ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - private Address DefaultSender => Accounts[0].Address; - - private readonly IBlockchainService _blockchainService; - private readonly ITransactionSizeFeeSymbolsProvider _transactionSizeFeeSymbolsProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly ITotalTransactionFeesMapProvider _totalTransactionFeesMapProvider; - - public ExecutionPluginForMethodFeeTest() - { - _blockchainService = GetRequiredService(); - _transactionSizeFeeSymbolsProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _totalTransactionFeesMapProvider = GetRequiredService(); - } + _blockchainService = GetRequiredService(); + _transactionSizeFeeSymbolsProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _totalTransactionFeesMapProvider = GetRequiredService(); + } - private async Task DeployTestContractAsync() - { - var category = KernelConstants.CodeCoverageRunnerCategory; - var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; - _testContractAddress = await DeploySystemSmartContract(category, code, - HashHelper.ComputeFrom("TestContract"), - DefaultSenderKeyPair); - _testContractStub = - GetTester(_testContractAddress, DefaultSenderKeyPair); - } + private ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + private Address DefaultSender => Accounts[0].Address; - private async Task CreateAndIssueTokenAsync(string symbol, long issueAmount, Address to) + private async Task DeployTestContractAsync() + { + var category = KernelConstants.CodeCoverageRunnerCategory; + var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; + _testContractAddress = await DeploySystemSmartContract(category, code, + HashHelper.ComputeFrom("TestContract"), + DefaultSenderKeyPair); + _testContractStub = + GetTester(_testContractAddress, DefaultSenderKeyPair); + } + + private async Task CreateAndIssueTokenAsync(string symbol, long issueAmount, Address to) + { + var tokenStub = await GetTokenContractStubAsync(); + await tokenStub.Create.SendAsync(new CreateInput { - var tokenStub = await GetTokenContractStubAsync(); - await tokenStub.Create.SendAsync(new CreateInput + Symbol = symbol, + Decimals = 2, + IsBurnable = true, + TokenName = "test token", + TotalSupply = 1_000_000_00000000L, + Issuer = DefaultSender + }); + + if (issueAmount != 0) + await tokenStub.Issue.SendAsync(new IssueInput { Symbol = symbol, - Decimals = 2, - IsBurnable = true, - TokenName = "test token", - TotalSupply = 1_000_000_00000000L, - Issuer = DefaultSender + Amount = issueAmount, + To = to, + Memo = "Set for token converter." }); + } - if (issueAmount != 0) - { - await tokenStub.Issue.SendAsync(new IssueInput - { - Symbol = symbol, - Amount = issueAmount, - To = to, - Memo = "Set for token converter." - }); - } - } - - private async Task GetTokenContractStubAsync() - { - var tokenContractAddress = await GetTokenContractAddressAsync(); - var tokenStub = GetTester( - tokenContractAddress, DefaultSenderKeyPair); + private async Task GetTokenContractStubAsync() + { + var tokenContractAddress = await GetTokenContractAddressAsync(); + var tokenStub = GetTester( + tokenContractAddress, DefaultSenderKeyPair); - return tokenStub; - } + return tokenStub; + } - private async Task
GetTokenContractAddressAsync() + private async Task
GetTokenContractAddressAsync() + { + var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); + var chainContext = new ChainContext { - var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync(); - var chainContext = new ChainContext - { - BlockHash = preBlockHeader.GetHash(), - BlockHeight = preBlockHeader.Height - }; - var contractMapping = - await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); + BlockHash = preBlockHeader.GetHash(), + BlockHeight = preBlockHeader.Height + }; + var contractMapping = + await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - return contractMapping[TokenSmartContractAddressNameProvider.Name]; - } + return contractMapping[TokenSmartContractAddressNameProvider.Name]; + } - [Fact] - public async Task GetPreTransactionsTest() - { - await DeployTestContractAsync(); - await SetMethodFee_Successful(10); - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); - var transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + [Fact] + public async Task GetPreTransactionsTest() + { + await DeployTestContractAsync(); + await SetMethodFee_Successful(10); + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); + var transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = _testContractAddress, - MethodName = nameof(_testContractStub.DummyMethod) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.ShouldNotBeEmpty(); - transactions[0].From.ShouldBe(DefaultSender); - transactions[0].To.ShouldBe(await GetTokenContractAddressAsync()); - } + From = DefaultSender, + To = _testContractAddress, + MethodName = nameof(_testContractStub.DummyMethod) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + + transactions.ShouldNotBeEmpty(); + transactions[0].From.ShouldBe(DefaultSender); + transactions[0].To.ShouldBe(await GetTokenContractAddressAsync()); + } - private I GetCreateInstance() where T: I - { - var implements = Application.ServiceProvider.GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per t - var implement = implements.SingleOrDefault(p => p.GetType() == typeof(T)); - return implement; - } - - [Fact] - public async Task GetPreTransactions_None_PreTransaction_Generate_Test() - { - await DeployTestContractAsync(); - await SetMethodFee_Successful(10); - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); - - //height == 1 - var transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + private I GetCreateInstance() where T : I + { + var implements = Application.ServiceProvider.GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per t + var implement = implements.SingleOrDefault(p => p.GetType() == typeof(T)); + return implement; + } + + [Fact] + public async Task GetPreTransactions_None_PreTransaction_Generate_Test() + { + await DeployTestContractAsync(); + await SetMethodFee_Successful(10); + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); + + //height == 1 + var transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = _testContractAddress, - MethodName = nameof(_testContractStub.DummyMethod) - }, - BlockHeight = 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.Count.ShouldBe(0); - - // invalid contract descriptor - transactions = (await plugin.GetPreTransactionsAsync(AEDPoSContractContainer.Descriptors, - new TransactionContext + From = DefaultSender, + To = _testContractAddress, + MethodName = nameof(_testContractStub.DummyMethod) + }, + BlockHeight = 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + + transactions.Count.ShouldBe(0); + + // invalid contract descriptor + transactions = (await plugin.GetPreTransactionsAsync(AEDPoSContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = DefaultSender, - MethodName = nameof(_testContractStub.DummyMethod) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.Count.ShouldBe(0); - - // method name == ChargeTransactionFees, to == token contract address - var tokenContractAddress = await GetTokenContractAddressAsync(); - transactions = (await plugin.GetPreTransactionsAsync(AEDPoSContractContainer.Descriptors, - new TransactionContext + From = DefaultSender, + To = DefaultSender, + MethodName = nameof(_testContractStub.DummyMethod) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + + transactions.Count.ShouldBe(0); + + // method name == ChargeTransactionFees, to == token contract address + var tokenContractAddress = await GetTokenContractAddressAsync(); + transactions = (await plugin.GetPreTransactionsAsync(AEDPoSContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = tokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.ChargeTransactionFees) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.Count.ShouldBe(0); - } + From = DefaultSender, + To = tokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.ChargeTransactionFees) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); + + transactions.Count.ShouldBe(0); + } - [Fact] - public async Task GenerateTransactions_Transaction_Success_Test() - { - await DeployTestContractAsync(); - - var tokenContractStub = await GetTokenContractStubAsync(); - await SetPrimaryTokenSymbolAsync(tokenContractStub); - var feeAmount = 7; - await SetMethodFee_Successful(feeAmount); - var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var bcs = Application.ServiceProvider.GetRequiredService(); - var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); - var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); - var systemTransactionGenerator = GetCreateInstance(); - systemTransactionGenerator.ShouldNotBeNull(); - var transactions = await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, blockHeader.GetHash()); - transactions.Count.ShouldBe(1); - var claimFeeTransaction = transactions[0]; - claimFeeTransaction.MethodName.ShouldBe(nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees)); - var txFeeMap = TotalTransactionFeesMap.Parser.ParseFrom(claimFeeTransaction.Params); - txFeeMap.Value.ContainsKey("ELF"); - - var transactionValidations = Application.ServiceProvider.GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per type - var claimTransactionValidation = transactionValidations.SingleOrDefault(p => p.GetType() == typeof(ClaimTransactionFeesValidationProvider)); - claimTransactionValidation.ShouldNotBeNull(); - var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); - validateRet.ShouldBe(true); - } + [Fact] + public async Task GenerateTransactions_Transaction_Success_Test() + { + await DeployTestContractAsync(); + + var tokenContractStub = await GetTokenContractStubAsync(); + await SetPrimaryTokenSymbolAsync(tokenContractStub); + var feeAmount = 7; + await SetMethodFee_Successful(feeAmount); + var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var bcs = Application.ServiceProvider.GetRequiredService(); + var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); + var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); + var systemTransactionGenerator = GetCreateInstance(); + systemTransactionGenerator.ShouldNotBeNull(); + var transactions = + await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, + blockHeader.GetHash()); + transactions.Count.ShouldBe(1); + var claimFeeTransaction = transactions[0]; + claimFeeTransaction.MethodName.ShouldBe(nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees)); + var txFeeMap = TotalTransactionFeesMap.Parser.ParseFrom(claimFeeTransaction.Params); + txFeeMap.Value.ContainsKey("ELF"); + + var transactionValidations = Application.ServiceProvider + .GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per type + var claimTransactionValidation = + transactionValidations.SingleOrDefault(p => p.GetType() == typeof(ClaimTransactionFeesValidationProvider)); + claimTransactionValidation.ShouldNotBeNull(); + var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); + validateRet.ShouldBe(true); + } - private async Task SetMethodFee_Successful(long feeAmount) + private async Task SetMethodFee_Successful(long feeAmount) + { + await _testContractStub.SetMethodFee.SendAsync(new MethodFees { - await _testContractStub.SetMethodFee.SendAsync(new MethodFees + MethodName = nameof(_testContractStub.DummyMethod), + Fees = { - MethodName = nameof(_testContractStub.DummyMethod), - Fees = - { - new MethodFee {Symbol = "ELF", BasicFee = feeAmount} - } - }); - var fee = await _testContractStub.GetMethodFee.CallAsync(new StringValue - { - Value = nameof(_testContractStub.DummyMethod) - }); - fee.Fees.First(a => a.Symbol == "ELF").BasicFee.ShouldBe(feeAmount); - } - - [Fact] - public async Task ChargeFee_SuccessfulTest() + new MethodFee { Symbol = "ELF", BasicFee = feeAmount } + } + }); + var fee = await _testContractStub.GetMethodFee.CallAsync(new StringValue { - await DeployTestContractAsync(); + Value = nameof(_testContractStub.DummyMethod) + }); + fee.Fees.First(a => a.Symbol == "ELF").BasicFee.ShouldBe(feeAmount); + } - var tokenContractStub = await GetTokenContractStubAsync(); - await SetPrimaryTokenSymbolAsync(tokenContractStub); - var feeAmount = 7; - await SetMethodFee_Successful(feeAmount); + [Fact] + public async Task ChargeFee_SuccessfulTest() + { + await DeployTestContractAsync(); - var before = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultSender, - Symbol = "ELF" - }); + var tokenContractStub = await GetTokenContractStubAsync(); + await SetPrimaryTokenSymbolAsync(tokenContractStub); + var feeAmount = 7; + await SetMethodFee_Successful(feeAmount); - var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var before = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = "ELF" + }); - var transactionFeeDic = dummy.TransactionResult.GetChargedTransactionFees(); - await CheckTransactionFeesMapAsync(transactionFeeDic); - - var after = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultSender, - Symbol = "ELF" - }); - after.Balance.ShouldBe(before.Balance - transactionFeeDic[before.Symbol]); - } + var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var transactionFeeDic = dummy.TransactionResult.GetChargedTransactionFees(); + await CheckTransactionFeesMapAsync(transactionFeeDic); - private async Task CheckTransactionFeesMapAsync(Dictionary transactionFeeDic) + var after = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var chain = await _blockchainService.GetChainAsync(); - var transactionFeesMap = await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }); - foreach (var transactionFee in transactionFeeDic) - { - transactionFeesMap.Value[transactionFee.Key].ShouldBe(transactionFee.Value); - } - } + Owner = DefaultSender, + Symbol = "ELF" + }); + after.Balance.ShouldBe(before.Balance - transactionFeeDic[before.Symbol]); + } - [Fact] - public async Task ChargeFee_TxFee_FailedTest() + private async Task CheckTransactionFeesMapAsync(Dictionary transactionFeeDic) + { + var chain = await _blockchainService.GetChainAsync(); + var transactionFeesMap = await _totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(new ChainContext { - await DeployTestContractAsync(); - - var issueAmount = 99999; - var tokenContractStub = await GetTokenContractStubAsync(); - await SetPrimaryTokenSymbolAsync(tokenContractStub); + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }); + foreach (var transactionFee in transactionFeeDic) + transactionFeesMap.Value[transactionFee.Key].ShouldBe(transactionFee.Value); + } - await tokenContractStub.Transfer.SendAsync(new TransferInput() - { - Symbol = "ELF", - Amount = issueAmount, - To = Accounts[1].Address, - Memo = "Set for token converter." - }); + [Fact] + public async Task ChargeFee_TxFee_FailedTest() + { + await DeployTestContractAsync(); - var feeAmount = 100000; - await SetMethodFee_Successful(feeAmount); - - var userTestContractStub = - GetTester(_testContractAddress, - Accounts[1].KeyPair); - var dummy = await userTestContractStub.DummyMethod - .SendWithExceptionAsync(new Empty()); // This will deduct the fee - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - dummy.TransactionResult.Error.ShouldBe("Pre-Error: Transaction fee not enough."); - var transactionFeeDic = dummy.TransactionResult.GetChargedTransactionFees(); - await CheckTransactionFeesMapAsync(transactionFeeDic); - - var afterFee = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = Accounts[1].Address, - Symbol = "ELF" - })).Balance; - afterFee.ShouldBe(0); - transactionFeeDic["ELF"].ShouldBe(issueAmount); - } + var issueAmount = 99999; + var tokenContractStub = await GetTokenContractStubAsync(); + await SetPrimaryTokenSymbolAsync(tokenContractStub); - [Theory] - [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260010, true)] - [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] - [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] - [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] - [InlineData(100000000, 2, 2, 0, 20, 20, "TSB", 2, false)] - [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] - [InlineData(10, 0, 0, 0, 1, 2, "ELF", 10, false)] // Charge 10 ELFs tx size fee. - public async Task ChargeFee_Set_Method_Fees_Tests(long balance1, long balance2, long balance3, long fee1, long fee2, - long fee3, string chargedSymbol, long chargedAmount, bool isChargingSuccessful) + await tokenContractStub.Transfer.SendAsync(new TransferInput { - await DeployTestContractAsync(); - - var tokenContractStub = await GetTokenContractStubAsync(); - await SetPrimaryTokenSymbolAsync(tokenContractStub); - await tokenContractStub.Transfer.SendAsync(new TransferInput() - { - Symbol = "ELF", - Amount = balance1, - To = Accounts[1].Address, - Memo = "Set for token converter." - }); - await CreateAndIssueTokenAsync("TSA", balance2,Accounts[1].Address); - await CreateAndIssueTokenAsync("TSB", balance3,Accounts[1].Address); + Symbol = "ELF", + Amount = issueAmount, + To = Accounts[1].Address, + Memo = "Set for token converter." + }); + + var feeAmount = 100000; + await SetMethodFee_Successful(feeAmount); + + var userTestContractStub = + GetTester(_testContractAddress, + Accounts[1].KeyPair); + var dummy = await userTestContractStub.DummyMethod + .SendWithExceptionAsync(new Empty()); // This will deduct the fee + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + dummy.TransactionResult.Error.ShouldBe("Pre-Error: Transaction fee not enough."); + var transactionFeeDic = dummy.TransactionResult.GetChargedTransactionFees(); + await CheckTransactionFeesMapAsync(transactionFeeDic); + + var afterFee = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Accounts[1].Address, + Symbol = "ELF" + })).Balance; + afterFee.ShouldBe(0); + transactionFeeDic["ELF"].ShouldBe(issueAmount); + } - var methodFee = new MethodFees - { - MethodName = nameof(_testContractStub.DummyMethod) - }; - if (fee1 > 0) - methodFee.Fees.Add(new MethodFee {Symbol = "ELF", BasicFee = fee1}); - if (fee2 > 0) - methodFee.Fees.Add(new MethodFee {Symbol = "TSA", BasicFee = fee2}); - if (fee3 > 0) - methodFee.Fees.Add(new MethodFee {Symbol = "TSB", BasicFee = fee3}); - await _testContractStub.SetMethodFee.SendAsync(methodFee); - - var originBalance = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Accounts[1].Address, - Symbol = chargedSymbol ?? "ELF" - })).Balance; - - Dictionary transactionFeeDic; - var userTestContractStub = - GetTester(_testContractAddress, Accounts[1].KeyPair); - if (isChargingSuccessful) - { - var dummyResult = await userTestContractStub.DummyMethod.SendAsync(new Empty()); - dummyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - if (chargedSymbol != null) - { - dummyResult.TransactionResult.GetChargedTransactionFees().Keys.ShouldContain(chargedSymbol); - dummyResult.TransactionResult.GetChargedTransactionFees().Values.ShouldContain(chargedAmount); - } + [Theory] + [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260010, true)] + [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] + [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] + [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] + [InlineData(100000000, 2, 2, 0, 20, 20, "TSB", 2, false)] + [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] + [InlineData(10, 0, 0, 0, 1, 2, "ELF", 10, false)] // Charge 10 ELFs tx size fee. + public async Task ChargeFee_Set_Method_Fees_Tests(long balance1, long balance2, long balance3, long fee1, long fee2, + long fee3, string chargedSymbol, long chargedAmount, bool isChargingSuccessful) + { + await DeployTestContractAsync(); - transactionFeeDic = dummyResult.TransactionResult.GetChargedTransactionFees(); - } - else + var tokenContractStub = await GetTokenContractStubAsync(); + await SetPrimaryTokenSymbolAsync(tokenContractStub); + await tokenContractStub.Transfer.SendAsync(new TransferInput + { + Symbol = "ELF", + Amount = balance1, + To = Accounts[1].Address, + Memo = "Set for token converter." + }); + await CreateAndIssueTokenAsync("TSA", balance2, Accounts[1].Address); + await CreateAndIssueTokenAsync("TSB", balance3, Accounts[1].Address); + + var methodFee = new MethodFees + { + MethodName = nameof(_testContractStub.DummyMethod) + }; + if (fee1 > 0) + methodFee.Fees.Add(new MethodFee { Symbol = "ELF", BasicFee = fee1 }); + if (fee2 > 0) + methodFee.Fees.Add(new MethodFee { Symbol = "TSA", BasicFee = fee2 }); + if (fee3 > 0) + methodFee.Fees.Add(new MethodFee { Symbol = "TSB", BasicFee = fee3 }); + await _testContractStub.SetMethodFee.SendAsync(methodFee); + + var originBalance = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Accounts[1].Address, + Symbol = chargedSymbol ?? "ELF" + })).Balance; + + Dictionary transactionFeeDic; + var userTestContractStub = + GetTester(_testContractAddress, Accounts[1].KeyPair); + if (isChargingSuccessful) + { + var dummyResult = await userTestContractStub.DummyMethod.SendAsync(new Empty()); + dummyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + if (chargedSymbol != null) { - var dummyResult = await userTestContractStub.DummyMethod.SendWithExceptionAsync(new Empty()); - dummyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - dummyResult.TransactionResult.Error.ShouldBe("Pre-Error: Transaction fee not enough."); - if (chargedSymbol != null) - { - dummyResult.TransactionResult.GetChargedTransactionFees().Keys.ShouldContain(chargedSymbol); - } - transactionFeeDic = dummyResult.TransactionResult.GetChargedTransactionFees(); + dummyResult.TransactionResult.GetChargedTransactionFees().Keys.ShouldContain(chargedSymbol); + dummyResult.TransactionResult.GetChargedTransactionFees().Values.ShouldContain(chargedAmount); } - await CheckTransactionFeesMapAsync(transactionFeeDic); + + transactionFeeDic = dummyResult.TransactionResult.GetChargedTransactionFees(); + } + else + { + var dummyResult = await userTestContractStub.DummyMethod.SendWithExceptionAsync(new Empty()); + dummyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + dummyResult.TransactionResult.Error.ShouldBe("Pre-Error: Transaction fee not enough."); if (chargedSymbol != null) - transactionFeeDic[chargedSymbol].ShouldBe(chargedAmount); + dummyResult.TransactionResult.GetChargedTransactionFees().Keys.ShouldContain(chargedSymbol); + transactionFeeDic = dummyResult.TransactionResult.GetChargedTransactionFees(); + } - var finalBalance = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Accounts[1].Address, - Symbol = chargedSymbol ?? "ELF" - })).Balance; + await CheckTransactionFeesMapAsync(transactionFeeDic); + if (chargedSymbol != null) + transactionFeeDic[chargedSymbol].ShouldBe(chargedAmount); - (originBalance - finalBalance).ShouldBe(chargedAmount); - } - - [Fact] - public async Task TransactionSizeFeeSymbolsSetAndGet_Test() + var finalBalance = (await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var blockExecutedDataKey = "BlockExecutedData/TransactionSizeFeeSymbols"; - var chain = await _blockchainService.GetChainAsync(); - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.Keys.ShouldNotContain(blockExecutedDataKey); + Owner = Accounts[1].Address, + Symbol = chargedSymbol ?? "ELF" + })).Balance; + + (originBalance - finalBalance).ShouldBe(chargedAmount); + } + + [Fact] + public async Task TransactionSizeFeeSymbolsSetAndGet_Test() + { + var blockExecutedDataKey = "BlockExecutedData/TransactionSizeFeeSymbols"; + var chain = await _blockchainService.GetChainAsync(); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.Keys.ShouldNotContain(blockExecutedDataKey); - var transactionSizeFeeSymbols = new TransactionSizeFeeSymbols + var transactionSizeFeeSymbols = new TransactionSizeFeeSymbols + { + TransactionSizeFeeSymbolList = { - TransactionSizeFeeSymbolList = + new TransactionSizeFeeSymbol { - new TransactionSizeFeeSymbol - { - TokenSymbol = "ELF", - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } + TokenSymbol = "ELF", + AddedTokenWeight = 1, + BaseTokenWeight = 1 } - }; - await _transactionSizeFeeSymbolsProvider.SetTransactionSizeFeeSymbolsAsync(new BlockIndex + } + }; + await _transactionSizeFeeSymbolsProvider.SetTransactionSizeFeeSymbolsAsync(new BlockIndex + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, transactionSizeFeeSymbols); + + blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.Keys.ShouldContain(blockExecutedDataKey); + + var symbols = await _transactionSizeFeeSymbolsProvider.GetTransactionSizeFeeSymbolsAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight - }, transactionSizeFeeSymbols); + }); + symbols.ShouldBe(transactionSizeFeeSymbols); + } - blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.Keys.ShouldContain(blockExecutedDataKey); - var symbols = await _transactionSizeFeeSymbolsProvider.GetTransactionSizeFeeSymbolsAsync( - new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }); - symbols.ShouldBe(transactionSizeFeeSymbols); - } - - - [Fact] - public async Task Method_Fee_Set_Zero_ChargeFee_Should_Be_Zero() + [Fact] + public async Task Method_Fee_Set_Zero_ChargeFee_Should_Be_Zero() + { + await DeployTestContractAsync(); + await SetMethodFee_Successful(0); + + var tokenContractStub = await GetTokenContractStubAsync(); + var before = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await DeployTestContractAsync(); - await SetMethodFee_Successful(0); + Owner = DefaultSender, + Symbol = "ELF" + }); - var tokenContractStub = await GetTokenContractStubAsync(); - var before = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultSender, - Symbol = "ELF" - }); + var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee + dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await _testContractStub.DummyMethod.SendAsync(new Empty()); - var dummy = await _testContractStub.DummyMethod.SendAsync(new Empty()); // This will deduct the fee - dummy.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - await _testContractStub.DummyMethod.SendAsync(new Empty()); - - var after = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput() - { - Owner = DefaultSender, - Symbol = "ELF" - }); - before.Balance.ShouldBe(after.Balance); - } - - private async Task SetPrimaryTokenSymbolAsync(TokenContractContainer.TokenContractStub tokenContractStub) - { - await tokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput - {Symbol = "ELF"}); - } - - - [Fact] - public async Task IBlockValidationProvider_ValidateBeforeAttachAsync_Test() + var after = await tokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var blockValidationProvider = GetRequiredService(); - var ret = await blockValidationProvider.ValidateBeforeAttachAsync(null); - ret.ShouldBeTrue(); - } + Owner = DefaultSender, + Symbol = "ELF" + }); + before.Balance.ShouldBe(after.Balance); + } + + private async Task SetPrimaryTokenSymbolAsync(TokenContractContainer.TokenContractStub tokenContractStub) + { + await tokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput + { Symbol = "ELF" }); + } + + + [Fact] + public async Task IBlockValidationProvider_ValidateBeforeAttachAsync_Test() + { + var blockValidationProvider = GetRequiredService(); + var ret = await blockValidationProvider.ValidateBeforeAttachAsync(null); + ret.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index f62372b782..e9de6dc53e 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -2,263 +2,267 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; +using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class ExecutionPluginForMethodFeeTestBase : ContractTestBase { - public class ExecutionPluginForMethodFeeTestBase : ContractTestKit.ContractTestBase +} + +public class ExecutionPluginForMethodFeeWithForkTestBase : Contracts.TestBase.ContractTestBase< + ExecutionPluginForMethodFeeWithForkTestModule> +{ + private readonly Address _parliamentAddress; + protected readonly Address TokenContractAddress; + + protected ExecutionPluginForMethodFeeWithForkTestBase() + { + AsyncHelper.RunSync(() => + Tester.InitialChainAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), out _, out _, + out _))); + TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); + _parliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); + var amount = 1000_00000000; + AsyncHelper.RunSync(() => + IssueNativeTokenAsync(Address.FromPublicKey(Tester.InitialMinerList[0].PublicKey), amount)); + AsyncHelper.RunSync(() => + IssueNativeTokenAsync(Address.FromPublicKey(Tester.InitialMinerList[2].PublicKey), amount)); + } + + private async Task IssueNativeTokenAsync(Address address, long amount) { + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput + { + Amount = amount, + Memo = Guid.NewGuid().ToString(), + Symbol = "ELF", + To = address + }); } - public class ExecutionPluginForMethodFeeWithForkTestBase : Contracts.TestBase.ContractTestBase< - ExecutionPluginForMethodFeeWithForkTestModule> + protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) { - protected readonly Address TokenContractAddress; - private readonly Address _parliamentAddress; + var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + new CreateProposalInput + { + ContractMethodName = + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = methodFee, + ToAddress = TokenContractAddress, + OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); + } - protected ExecutionPluginForMethodFeeWithForkTestBase() - { - AsyncHelper.RunSync(() => - Tester.InitialChainAsync(Tester.GetDefaultContractTypes(Tester.GetCallOwnerAddress(), out _, out _, - out _))); - TokenContractAddress = Tester.GetContractAddress(TokenSmartContractAddressNameProvider.Name); - _parliamentAddress = Tester.GetContractAddress(ParliamentSmartContractAddressNameProvider.Name); - var amount = 1000_00000000; - AsyncHelper.RunSync(() => - IssueNativeTokenAsync(Address.FromPublicKey(Tester.InitialMinerList[0].PublicKey), amount)); - AsyncHelper.RunSync(() => - IssueNativeTokenAsync(Address.FromPublicKey(Tester.InitialMinerList[2].PublicKey), amount)); - } + private async Task
GetParliamentDefaultOrganizationAddressAsync() + { + var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( + _parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), + new Empty())) + .ReturnValue); + return organizationAddress; + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + var approveTransaction1 = await GenerateTransactionAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[0], + proposalId); + var approveTransaction2 = await GenerateTransactionAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[1], + proposalId); + var approveTransaction3 = await GenerateTransactionAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[2], + proposalId); - private async Task IssueNativeTokenAsync(Address address,long amount) + // Mine a block with given normal txs and system txs. + await Tester.MineAsync( + new List { approveTransaction1, approveTransaction2, approveTransaction3 }); + } + + private async Task GenerateTransactionAsync(Address contractAddress, string methodName, + ECKeyPair ecKeyPair, IMessage input) + { + return ecKeyPair == null + ? await Tester.GenerateTransactionAsync(contractAddress, methodName, input) + : await Tester.GenerateTransactionAsync(contractAddress, methodName, ecKeyPair, input); + } + + private async Task ReleaseProposalAsync(Hash proposalId) + { + await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); + } +} + +public class ExecutePluginTransactionDirectlyForMethodFeeTestBase : ContractTestBase< + ExecutionPluginTransactionDirectlyForMethodFeeTestModule> +{ + protected const string NativeTokenSymbol = "ELF"; + + protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() + { + AsyncHelper.RunSync(InitializeContracts); + } + + internal Address TokenContractAddress { get; set; } + internal Address TreasuryContractAddress { get; set; } + internal Address ConsensusContractAddress { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } + internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } + internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(1).Select(a => a.KeyPair).ToList(); + + internal Address DefaultSender => Accounts[0].Address; + + private async Task InitializeContracts() + { + await DeployContractsAsync(); + await InitializeAElfConsensus(); + await InitializedParliament(); + await CreateNativeTokenAsync(); + } + + private async Task InitializedParliament() + { + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput { - await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput - { - Amount = amount, - Memo = Guid.NewGuid().ToString(), - Symbol = "ELF", - To = address - }); - } + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultSender + }); + } - protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) + private async Task DeployContractsAsync() + { + const int category = KernelConstants.CodeCoverageRunnerCategory; + // Token contract { - var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = methodFee, - ToAddress = TokenContractAddress, - OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); + var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + TokenContractAddress = await DeploySystemSmartContract(category, code, + TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TokenContractStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); } - private async Task
GetParliamentDefaultOrganizationAddressAsync() + // Parliament { - var organizationAddress = Address.Parser.ParseFrom((await Tester.ExecuteContractWithMiningAsync( - _parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.GetDefaultOrganizationAddress), - new Empty())) - .ReturnValue); - return organizationAddress; + var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + var parliamentContractAddress = await DeploySystemSmartContract(category, code, + ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ParliamentContractStub = + GetTester(parliamentContractAddress, + DefaultSenderKeyPair); } - private async Task ApproveWithMinersAsync(Hash proposalId) - { - var approveTransaction1 = await GenerateTransactionAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[0], - proposalId); - var approveTransaction2 = await GenerateTransactionAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[1], - proposalId); - var approveTransaction3 = await GenerateTransactionAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Approve), Tester.InitialMinerList[2], - proposalId); - // Mine a block with given normal txs and system txs. - await Tester.MineAsync( - new List {approveTransaction1, approveTransaction2, approveTransaction3}); - } - - private async Task GenerateTransactionAsync(Address contractAddress, string methodName, - ECKeyPair ecKeyPair, IMessage input) + //Consensus { - return ecKeyPair == null - ? await Tester.GenerateTransactionAsync(contractAddress, methodName, input) - : await Tester.GenerateTransactionAsync(contractAddress, methodName, ecKeyPair, input); + var code = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; + ConsensusContractAddress = await DeploySystemSmartContract(category, code, + HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); + AEDPoSContractStub = + GetTester(ConsensusContractAddress, + DefaultSenderKeyPair); } - private async Task ReleaseProposalAsync(Hash proposalId) + // Treasury { - await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.Release), proposalId); + var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; + TreasuryContractAddress = await DeploySystemSmartContract(category, code, + HashHelper.ComputeFrom("Treasury"), DefaultSenderKeyPair); } } - public class ExecutePluginTransactionDirectlyForMethodFeeTestBase : ContractTestKit.ContractTestBase< - ExecutionPluginTransactionDirectlyForMethodFeeTestModule> + private async Task CreateNativeTokenAsync() { - protected const string NativeTokenSymbol = "ELF"; - internal Address TokenContractAddress { get; set; } - internal Address TreasuryContractAddress { get; set; } - internal Address ConsensusContractAddress { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } - internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } - internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(1).Select(a => a.KeyPair).ToList(); - internal Address DefaultSender => Accounts[0].Address; - protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() + const long totalSupply = 1_000_000_000_00000000; + //init elf token + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - AsyncHelper.RunSync(InitializeContracts); - } - private async Task InitializeContracts() - { - await DeployContractsAsync(); - await InitializeAElfConsensus(); - await InitializedParliament(); - await CreateNativeTokenAsync(); - } + Symbol = NativeTokenSymbol, + Decimals = 8, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender + }); + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - private async Task InitializedParliament() + protected async Task SetPrimaryTokenSymbolAsync() + { + await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput + { Symbol = NativeTokenSymbol }); + } + + private async Task InitializeAElfConsensus() + { { - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput - { - ProposerAuthorityRequired = false, - PrivilegedProposer = DefaultSender - }); + await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput + { + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000 + }); } - - private async Task DeployContractsAsync() { - const int category = KernelConstants.CodeCoverageRunnerCategory; - // Token contract - { - var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - TokenContractAddress = await DeploySystemSmartContract(category, code, - TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TokenContractStub = - GetTester(TokenContractAddress, DefaultSenderKeyPair); - } - - // Parliament - { - var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; - var parliamentContractAddress = await DeploySystemSmartContract(category, code, - ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - ParliamentContractStub = - GetTester(parliamentContractAddress, - DefaultSenderKeyPair); - } - - //Consensus - { - var code = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; - ConsensusContractAddress = await DeploySystemSmartContract(category, code, - HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); - AEDPoSContractStub = - GetTester(ConsensusContractAddress, - DefaultSenderKeyPair); - } - - // Treasury - { - var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; - TreasuryContractAddress = await DeploySystemSmartContract(category, code, - HashHelper.ComputeFrom("Treasury"), DefaultSenderKeyPair); - } + await AEDPoSContractStub.FirstRound.SendAsync( + GenerateFirstRoundOfNewTerm( + new MinerList + { Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } }, + 4000, TimestampHelper.GetUtcNow())); } + } - private async Task CreateNativeTokenAsync() - { - const long totalSupply = 1_000_000_000_00000000; - //init elf token - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = NativeTokenSymbol, - Decimals = 8, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); + var round = new Round(); - protected async Task SetPrimaryTokenSymbolAsync() + for (var i = 0; i < sortedMiners.Count; i++) { - await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput - {Symbol = NativeTokenSymbol}); - } + var minerInRound = new MinerInRound(); - private async Task InitializeAElfConsensus() - { - { - await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000 - }); - } - { - await AEDPoSContractStub.FirstRound.SendAsync( - GenerateFirstRoundOfNewTerm( - new MinerList - {Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))}}, - 4000, TimestampHelper.GetUtcNow())); - } - } - private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) - { - var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The third miner will be the extra block producer of first round of each term. - if (i == 0) - { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; - - return round; + // The third miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); } - } + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; + + return round; + } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs index 915b3f56c9..b8009f89c0 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs @@ -16,76 +16,75 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +[DependsOn( + typeof(ContractTestModule), + typeof(ExecutionPluginForMethodFeeModule), + typeof(FeeCalculationModule))] +public class ExecutionPluginForMethodFeeTestModule : ContractTestModule { - [DependsOn( - typeof(ContractTestModule), - typeof(ExecutionPluginForMethodFeeModule), - typeof(FeeCalculationModule))] - public class ExecutionPluginForMethodFeeTestModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); - context.Services.RemoveAll(s => s.ImplementationType == typeof(TransactionFeeChargedLogEventProcessor)); - context.Services.AddTransient(); - context.Services.RemoveAll(); - context.Services - .AddTransient(); - context.Services - .AddTransient(); - context.Services - .AddTransient(); - context.Services - .AddTransient(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); + context.Services.RemoveAll(s => s.ImplementationType == typeof(TransactionFeeChargedLogEventProcessor)); + context.Services.AddTransient(); + context.Services.RemoveAll(); + context.Services + .AddTransient(); + context.Services + .AddTransient(); + context.Services + .AddTransient(); + context.Services + .AddTransient(); } +} - [DependsOn(typeof(ContractTestAElfModule), - typeof(ExecutionPluginForMethodFeeModule), - typeof(FeeCalculationModule))] - public class ExecutionPluginForMethodFeeWithForkTestModule : ContractTestAElfModule +[DependsOn(typeof(ContractTestAElfModule), + typeof(ExecutionPluginForMethodFeeModule), + typeof(FeeCalculationModule))] +public class ExecutionPluginForMethodFeeWithForkTestModule : ContractTestAElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.RemoveAll(); + var initializeMiner = SampleAccount.Accounts[0].KeyPair; + context.Services.AddTransient(o => { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.RemoveAll(); - var initializeMiner = SampleAccount.Accounts[0].KeyPair; - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(initializeMiner.PrivateKey, data))); - - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(initializeMiner.PublicKey); - - return mockService.Object; - }); - context.Services - .AddTransient(); - } + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(initializeMiner.PrivateKey, data))); + + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(initializeMiner.PublicKey); + + return mockService.Object; + }); + context.Services + .AddTransient(); } - - [DependsOn( - typeof(ContractTestModule))] - public class ExecutionPluginTransactionDirectlyForMethodFeeTestModule : ContractTestModule +} + +[DependsOn( + typeof(ContractTestModule))] +public class ExecutionPluginTransactionDirectlyForMethodFeeTestModule : ContractTestModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false); - context.Services.RemoveAll(); - context.Services.RemoveAll(); - context.Services.RemoveAll(); - context.Services.Replace(ServiceDescriptor - .Singleton()); - context.Services.Replace(ServiceDescriptor - .Singleton()); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.RemoveAll(); + context.Services.RemoveAll(); + context.Services.RemoveAll(); + context.Services.Replace(ServiceDescriptor + .Singleton()); + context.Services.Replace(ServiceDescriptor + .Singleton()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs index 407fe7feeb..e6bebf3081 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs @@ -2,44 +2,78 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS1; using AElf.Contracts.MultiToken; using AElf.Contracts.TestBase; -using AElf.ContractTestKit; using AElf.Kernel.FeeCalculation.Extensions; using AElf.Kernel.SmartContract.Events; using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf; -using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Volo.Abp.EventBus; using Xunit; -using Xunit.Abstractions; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public sealed class ExecutionPluginForMethodFeeWithForkTest : ExecutionPluginForMethodFeeWithForkTestBase { - public sealed class ExecutionPluginForMethodFeeWithForkTest : ExecutionPluginForMethodFeeWithForkTestBase + private async Task> GetTransactionFeesMapAsync(IChainContext chainContext) { - private async Task> GetTransactionFeesMapAsync(IChainContext chainContext) + var totalTransactionFeesMapProvider = Tester.GetService(); + var transactionFeesMap = + await totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(chainContext); + if (chainContext.BlockHash != transactionFeesMap.BlockHash || + chainContext.BlockHeight != transactionFeesMap.BlockHeight) + return null; + + return transactionFeesMap.Value; + } + + [Fact] + public async Task ChargeFee_With_Fork_Test() + { + var amount = 100000; + + await SetMethodFeeWithProposalAsync(new MethodFees { - var totalTransactionFeesMapProvider = Tester.GetService(); - var transactionFeesMap = - await totalTransactionFeesMapProvider.GetTotalTransactionFeesMapAsync(chainContext); - if (chainContext.BlockHash != transactionFeesMap.BlockHash || - chainContext.BlockHeight != transactionFeesMap.BlockHeight) + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - return null; + new MethodFee + { + Symbol = "ELF", + BasicFee = 100000 + } } + }.ToByteString()); - return transactionFeesMap.Value; - } + var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput + { + Amount = amount, + Symbol = "ELF", + Memo = Guid.NewGuid().ToString(), + To = SampleAddress.AddressList[0] + }); + var transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); + var targetFee = transactionResult.GetChargedTransactionFees().First().Value; - [Fact] - public async Task ChargeFee_With_Fork_Test() + var transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext { - var amount = 100000; + BlockHash = result.Item1.GetHash(), BlockHeight = result.Item1.Height + }); + transactionFeesMap.First().Value.ShouldBe(targetFee); + var chain = await Tester.GetChainAsync(); + // branch one + { + var branchOneBlock = await Tester.MineEmptyBlockAsync(); + + transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext + { + BlockHash = branchOneBlock.GetHash(), BlockHeight = branchOneBlock.Height + }); + transactionFeesMap.ShouldBeNull(); await SetMethodFeeWithProposalAsync(new MethodFees { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -48,12 +82,12 @@ await SetMethodFeeWithProposalAsync(new MethodFees new MethodFee { Symbol = "ELF", - BasicFee = 100000 + BasicFee = 200000 } } }.ToByteString()); - var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, + result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput { Amount = amount, @@ -61,142 +95,101 @@ await SetMethodFeeWithProposalAsync(new MethodFees Memo = Guid.NewGuid().ToString(), To = SampleAddress.AddressList[0] }); - var transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); - var targetFee = transactionResult.GetChargedTransactionFees().First().Value; - - var transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext + transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); + var fee = transactionResult.GetChargedTransactionFees().First().Value; + transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext { BlockHash = result.Item1.GetHash(), BlockHeight = result.Item1.Height }); - transactionFeesMap.First().Value.ShouldBe(targetFee); - var chain = await Tester.GetChainAsync(); - - // branch one - { - var branchOneBlock = await Tester.MineEmptyBlockAsync(); - - transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext - { - BlockHash = branchOneBlock.GetHash(), BlockHeight = branchOneBlock.Height - }); - transactionFeesMap.ShouldBeNull(); - await SetMethodFeeWithProposalAsync(new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = "ELF", - BasicFee = 200000 - } - } - }.ToByteString()); + transactionFeesMap.First().Value.ShouldBe(fee); //300000 + targetFee.ShouldNotBe(fee); + } - result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput - { - Amount = amount, - Symbol = "ELF", - Memo = Guid.NewGuid().ToString(), - To = SampleAddress.AddressList[0] - }); - transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); - var fee = transactionResult.GetChargedTransactionFees().First().Value; - transactionFeesMap = await GetTransactionFeesMapAsync(new ChainContext - { - BlockHash = result.Item1.GetHash(), BlockHeight = result.Item1.Height - }); - transactionFeesMap.First().Value.ShouldBe(fee); //300000 - targetFee.ShouldNotBe(fee); - } + // branch two + { + var branchTwoBlocks = await GenerateEmptyBlocksAsync(13, chain.BestChainHash, chain.BestChainHeight); + chain = await Tester.GetChainAsync(); + chain.BestChainHash.ShouldBe(result.Item1.GetHash()); + var branchTwoBlock = + await Tester.MineEmptyBlockAsync(branchTwoBlocks.Last().GetHash(), branchTwoBlocks.Last().Height); + chain = await Tester.GetChainAsync(); + chain.BestChainHash.ShouldBe(branchTwoBlock.GetHash()); - // branch two - { - var branchTwoBlocks = await GenerateEmptyBlocksAsync(13, chain.BestChainHash, chain.BestChainHeight); - chain = await Tester.GetChainAsync(); - chain.BestChainHash.ShouldBe(result.Item1.GetHash()); - var branchTwoBlock = - await Tester.MineEmptyBlockAsync(branchTwoBlocks.Last().GetHash(), branchTwoBlocks.Last().Height); - chain = await Tester.GetChainAsync(); - chain.BestChainHash.ShouldBe(branchTwoBlock.GetHash()); - - var transactions = - await Tester.GetTransactionsAsync(branchTwoBlocks.First().Body.TransactionIds); - var transaction = transactions.Single(t => - t.MethodName == nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees)); - var feesMap = TotalTransactionFeesMap.Parser.ParseFrom(transaction.Params); - feesMap.Value.First().Value.ShouldBe(targetFee); - } + var transactions = + await Tester.GetTransactionsAsync(branchTwoBlocks.First().Body.TransactionIds); + var transaction = transactions.Single(t => + t.MethodName == nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees)); + var feesMap = TotalTransactionFeesMap.Parser.ParseFrom(transaction.Params); + feesMap.Value.First().Value.ShouldBe(targetFee); } - - [Fact] - public async Task Claim_Fee_Send_By_User_Fail_Test() + } + + [Fact] + public async Task Claim_Fee_Send_By_User_Fail_Test() + { + var amount = 100000; + await SetMethodFeeWithProposalAsync(new MethodFees { - var amount = 100000; - await SetMethodFeeWithProposalAsync(new MethodFees + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = "ELF", - BasicFee = amount - } - } - }.ToByteString()); - - await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput + new MethodFee { - Amount = amount, Symbol = "ELF", - Memo = Guid.NewGuid().ToString(), - To = SampleAddress.AddressList[0] - }); - var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees), new TotalTransactionFeesMap(), - SampleECKeyPairs.KeyPairs.Last()); - var transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); - transactionResult.Error.ShouldContain("No permission."); - } - - [Fact] - public async Task CleanBlockExecutedDataChangeHeightEventHandler_Handle_Test() - { - var blockchainExecutedDataCacheProvider = - GetRequiredService>(); - blockchainExecutedDataCacheProvider.SetChangeHeight("test1", 1); - blockchainExecutedDataCacheProvider.SetChangeHeight("test2", 2); - blockchainExecutedDataCacheProvider.SetChangeHeight("test3", 3); - blockchainExecutedDataCacheProvider.SetChangeHeight("test4", 4); - - var cleanHandler = - GetRequiredService(); - await cleanHandler.HandleEventAsync(new CleanBlockExecutedDataChangeHeightEventData + BasicFee = amount + } + } + }.ToByteString()); + + await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput { - IrreversibleBlockHeight = 3 + Amount = amount, + Symbol = "ELF", + Memo = Guid.NewGuid().ToString(), + To = SampleAddress.AddressList[0] }); - blockchainExecutedDataCacheProvider.TryGetChangeHeight("test1", out _).ShouldBeFalse(); - blockchainExecutedDataCacheProvider.TryGetChangeHeight("test2", out _).ShouldBeFalse(); - blockchainExecutedDataCacheProvider.TryGetChangeHeight("test3", out _).ShouldBeFalse(); - blockchainExecutedDataCacheProvider.TryGetChangeHeight("test4", out _).ShouldBeTrue(); - } + var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.ClaimTransactionFees), new TotalTransactionFeesMap(), + SampleECKeyPairs.KeyPairs.Last()); + var transactionResult = await Tester.GetTransactionResultAsync(result.Item2.GetHash()); + transactionResult.Error.ShouldContain("No permission."); + } + + [Fact] + public async Task CleanBlockExecutedDataChangeHeightEventHandler_Handle_Test() + { + var blockchainExecutedDataCacheProvider = + GetRequiredService>(); + blockchainExecutedDataCacheProvider.SetChangeHeight("test1", 1); + blockchainExecutedDataCacheProvider.SetChangeHeight("test2", 2); + blockchainExecutedDataCacheProvider.SetChangeHeight("test3", 3); + blockchainExecutedDataCacheProvider.SetChangeHeight("test4", 4); - private async Task> GenerateEmptyBlocksAsync(int count, Hash previousBlockHash, - long previousBlockHeight) + var cleanHandler = + GetRequiredService(); + await cleanHandler.HandleEventAsync(new CleanBlockExecutedDataChangeHeightEventData { - var blocks = new List(); - var block = await Tester.MineEmptyBlockAsync(previousBlockHash, previousBlockHeight); - blocks.Add(block.Block); - for (var i = 0; i < count - 1; i++) - { - block = await Tester.MineEmptyBlockAsync(block.GetHash(), block.Height); - blocks.Add(block.Block); - } + IrreversibleBlockHeight = 3 + }); + blockchainExecutedDataCacheProvider.TryGetChangeHeight("test1", out _).ShouldBeFalse(); + blockchainExecutedDataCacheProvider.TryGetChangeHeight("test2", out _).ShouldBeFalse(); + blockchainExecutedDataCacheProvider.TryGetChangeHeight("test3", out _).ShouldBeFalse(); + blockchainExecutedDataCacheProvider.TryGetChangeHeight("test4", out _).ShouldBeTrue(); + } - return blocks; + private async Task> GenerateEmptyBlocksAsync(int count, Hash previousBlockHash, + long previousBlockHeight) + { + var blocks = new List(); + var block = await Tester.MineEmptyBlockAsync(previousBlockHash, previousBlockHeight); + blocks.Add(block.Block); + for (var i = 0; i < count - 1; i++) + { + block = await Tester.MineEmptyBlockAsync(block.GetHash(), block.Height); + blocks.Add(block.Block); } + + return blocks; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestContractDeploymentListProvider.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestContractDeploymentListProvider.cs index dcc015a061..cf55f08a4c 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestContractDeploymentListProvider.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestContractDeploymentListProvider.cs @@ -5,17 +5,16 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class MethodFeeTestContractDeploymentListProvider : IContractDeploymentListProvider, ITransientDependency { - public class MethodFeeTestContractDeploymentListProvider : IContractDeploymentListProvider, ITransientDependency + public List GetDeployContractNameList() { - public List GetDeployContractNameList() + return new List { - return new List - { - ConsensusSmartContractAddressNameProvider.Name, - TokenSmartContractAddressNameProvider.Name - }; - } + ConsensusSmartContractAddressNameProvider.Name, + TokenSmartContractAddressNameProvider.Name + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestGenesisSmartContractDtoProvider.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestGenesisSmartContractDtoProvider.cs index d2a104a97d..267799a6c4 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestGenesisSmartContractDtoProvider.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestGenesisSmartContractDtoProvider.cs @@ -5,46 +5,42 @@ using AElf.OS.Node.Application; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class MethodFeeTestGenesisSmartContractDtoProvider : IGenesisSmartContractDtoProvider, ITransientDependency { - public class MethodFeeTestGenesisSmartContractDtoProvider : IGenesisSmartContractDtoProvider, ITransientDependency - { - private readonly IContractDeploymentListProvider _contractDeploymentListProvider; - private readonly IEnumerable _contractInitializationProviders; + private readonly IContractDeploymentListProvider _contractDeploymentListProvider; + private readonly IEnumerable _contractInitializationProviders; - public MethodFeeTestGenesisSmartContractDtoProvider( - IContractDeploymentListProvider contractDeploymentListProvider, - IEnumerable contractInitializationProviders) - { - _contractDeploymentListProvider = contractDeploymentListProvider; - _contractInitializationProviders = contractInitializationProviders; - } + public MethodFeeTestGenesisSmartContractDtoProvider( + IContractDeploymentListProvider contractDeploymentListProvider, + IEnumerable contractInitializationProviders) + { + _contractDeploymentListProvider = contractDeploymentListProvider; + _contractInitializationProviders = contractInitializationProviders; + } - public IEnumerable GetGenesisSmartContractDtos() - { - var codes = ContractsDeployer.GetContractCodes(); + public IEnumerable GetGenesisSmartContractDtos() + { + var codes = ContractsDeployer.GetContractCodes(); - var deploymentList = _contractDeploymentListProvider.GetDeployContractNameList(); - return _contractInitializationProviders - .Where(p => deploymentList.Contains(p.SystemSmartContractName)) - .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) - .Select(p => + var deploymentList = _contractDeploymentListProvider.GetDeployContractNameList(); + return _contractInitializationProviders + .Where(p => deploymentList.Contains(p.SystemSmartContractName)) + .OrderBy(p => deploymentList.IndexOf(p.SystemSmartContractName)) + .Select(p => + { + var code = codes[p.ContractCodeName]; + var methodList = p.GetInitializeMethodList(code); + var genesisSmartContractDto = new GenesisSmartContractDto { - var code = codes[p.ContractCodeName]; - var methodList = p.GetInitializeMethodList(code); - var genesisSmartContractDto = new GenesisSmartContractDto - { - Code = code, - SystemSmartContractName = p.SystemSmartContractName, - ContractInitializationMethodCallList = new List() - }; - foreach (var method in methodList) - { - genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - } + Code = code, + SystemSmartContractName = p.SystemSmartContractName, + ContractInitializationMethodCallList = new List() + }; + foreach (var method in methodList) genesisSmartContractDto.AddGenesisTransactionMethodCall(method); - return genesisSmartContractDto; - }); - } + return genesisSmartContractDto; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs index ed20641f65..38cc9592d0 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs @@ -5,46 +5,45 @@ using AElf.Kernel.Token; using Google.Protobuf; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class MethodFeeTestTokenContractInitializationProvider : TokenContractInitializationProvider, + IContractInitializationProvider { - public class MethodFeeTestTokenContractInitializationProvider : TokenContractInitializationProvider, - IContractInitializationProvider + public MethodFeeTestTokenContractInitializationProvider() : base(null) { - public MethodFeeTestTokenContractInitializationProvider() : base(null) - { - } + } - public new List GetInitializeMethodList(byte[] contractCode) + public new List GetInitializeMethodList(byte[] contractCode) + { + var methodList = new List(); + // native token + methodList.Add(new ContractInitializationMethodCall { - var methodList = new List(); - // native token - methodList.Add(new ContractInitializationMethodCall + MethodName = nameof(TokenContractContainer.TokenContractStub.Create), + Params = new CreateInput { - MethodName = nameof(TokenContractContainer.TokenContractStub.Create), - Params = new CreateInput - { - Symbol = "ELF", - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = 1_000_000_00000000L, - Issuer = SampleAccount.Accounts[0].Address - }.ToByteString() - }); + Symbol = "ELF", + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = 1_000_000_00000000L, + Issuer = SampleAccount.Accounts[0].Address + }.ToByteString() + }); - methodList.Add(new ContractInitializationMethodCall + methodList.Add(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), + Params = new IssueInput { - MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), - Params = new IssueInput - { - Symbol = "ELF", - Amount = 1_000_000_00000000L, - To = SampleAccount.Accounts[0].Address, - Memo = "Set for token converter." - }.ToByteString() - }); + Symbol = "ELF", + Amount = 1_000_000_00000000L, + To = SampleAccount.Accounts[0].Address, + Memo = "Set for token converter." + }.ToByteString() + }); - return methodList; - } + return methodList; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MockTransactionGenerator.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MockTransactionGenerator.cs index a6869be486..6ed7a8233e 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MockTransactionGenerator.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MockTransactionGenerator.cs @@ -9,44 +9,43 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public class MockTransactionGenerator : ISystemTransactionGenerator { - public class MockTransactionGenerator : ISystemTransactionGenerator + private readonly Address _addressWithoutToken; + private readonly ISmartContractAddressService _smartContractAddressService; + + public MockTransactionGenerator(ISmartContractAddressService smartContractAddressService) { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly Address _addressWithoutToken; + _smartContractAddressService = smartContractAddressService; + _addressWithoutToken = SampleAccount.Accounts[5].Address; + } - public MockTransactionGenerator(ISmartContractAddressService smartContractAddressService) - { - _smartContractAddressService = smartContractAddressService; - _addressWithoutToken = SampleAccount.Accounts[5].Address; - } - - public async Task> GenerateTransactionsAsync(Address @from, long preBlockHeight, Hash preBlockHash) + public async Task> GenerateTransactionsAsync(Address from, long preBlockHeight, Hash preBlockHash) + { + var transactions = new List(); + var transaction = new Transaction { - var transactions = new List(); - var transaction = new Transaction + From = _addressWithoutToken, + To = await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext + { + BlockHash = preBlockHash, + BlockHeight = preBlockHeight + }, TokenSmartContractAddressNameProvider.StringName), + MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), + Params = new TransferInput { - From = _addressWithoutToken, - To = await _smartContractAddressService.GetAddressByContractNameAsync(new ChainContext - { - BlockHash = preBlockHash, - BlockHeight = preBlockHeight - }, TokenSmartContractAddressNameProvider.StringName), - MethodName = nameof(TokenContractImplContainer.TokenContractImplStub.Transfer), - Params = new TransferInput - { - Amount = 1000, - Memo = "transfer test", - Symbol = "ELF", - To = SampleAddress.AddressList[0] - }.ToByteString(), - RefBlockNumber = preBlockHeight, - RefBlockPrefix = ByteString.CopyFrom(preBlockHash.Value.Take(4).ToArray()) - }; + Amount = 1000, + Memo = "transfer test", + Symbol = "ELF", + To = SampleAddress.AddressList[0] + }.ToByteString(), + RefBlockNumber = preBlockHeight, + RefBlockPrefix = ByteString.CopyFrom(preBlockHash.Value.Take(4).ToArray()) + }; - transactions.Add(transaction); - return transactions; - } + transactions.Add(transaction); + return transactions; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/Service/PlainTransactionExecutingAsPluginService.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/Service/PlainTransactionExecutingAsPluginService.cs index 24929637b3..2ea2db6654 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/Service/PlainTransactionExecutingAsPluginService.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/Service/PlainTransactionExecutingAsPluginService.cs @@ -9,111 +9,109 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; -namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.Service +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.Service; + +public class PlainTransactionExecutingAsPluginService : PlainTransactionExecutingService { - public class PlainTransactionExecutingAsPluginService : PlainTransactionExecutingService + // for sending transaction + private readonly Hash _pluginOriginId = new(); + private readonly ISmartContractExecutiveService _smartContractExecutiveService; + + public PlainTransactionExecutingAsPluginService + (ISmartContractExecutiveService smartContractExecutiveService, + IEnumerable postPlugins, IEnumerable prePlugins, + ITransactionContextFactory transactionContextFactory) : base( + smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory) { - private readonly ISmartContractExecutiveService _smartContractExecutiveService; - // for sending transaction - private readonly Hash _pluginOriginId = new Hash(); - public PlainTransactionExecutingAsPluginService - (ISmartContractExecutiveService smartContractExecutiveService, - IEnumerable postPlugins, IEnumerable prePlugins, - ITransactionContextFactory transactionContextFactory) : base( - smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory) + _smartContractExecutiveService = smartContractExecutiveService; + } + + protected override async Task ExecuteOneAsync( + SingleTransactionExecutingDto singleTxExecutingDto, + CancellationToken cancellationToken) + { + if (singleTxExecutingDto.IsCancellable) + cancellationToken.ThrowIfCancellationRequested(); + + singleTxExecutingDto.OriginTransactionId = _pluginOriginId; + var txContext = CreateTransactionContext(singleTxExecutingDto); + var trace = txContext.Trace; + + var internalStateCache = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache); + var internalChainContext = + new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache); + + IExecutive executive; + try { - _smartContractExecutiveService = smartContractExecutiveService; + executive = await _smartContractExecutiveService.GetExecutiveAsync( + internalChainContext, + singleTxExecutingDto.Transaction.To); } - - protected override async Task ExecuteOneAsync( - SingleTransactionExecutingDto singleTxExecutingDto, - CancellationToken cancellationToken) + catch (SmartContractFindRegistrationException) { - if (singleTxExecutingDto.IsCancellable) - cancellationToken.ThrowIfCancellationRequested(); + txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; + txContext.Trace.Error += "Invalid contract address.\n"; + return trace; + } - singleTxExecutingDto.OriginTransactionId = _pluginOriginId; - var txContext = CreateTransactionContext(singleTxExecutingDto); - var trace = txContext.Trace; - - var internalStateCache = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache); - var internalChainContext = - new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache); + try + { + await executive.ApplyAsync(txContext); - IExecutive executive; - try - { - executive = await _smartContractExecutiveService.GetExecutiveAsync( + if (txContext.Trace.IsSuccessful()) + await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime, + txContext, internalStateCache, internalChainContext, - singleTxExecutingDto.Transaction.To); - } - catch (SmartContractFindRegistrationException) - { - txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; - txContext.Trace.Error += "Invalid contract address.\n"; - return trace; - } - - try - { - await executive.ApplyAsync(txContext); + singleTxExecutingDto.OriginTransactionId, + cancellationToken); + } + catch (Exception ex) + { + Logger.LogError(ex, "Transaction execution failed."); + txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; + txContext.Trace.Error += ex + "\n"; + throw; + } + finally + { + await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext, + singleTxExecutingDto.Transaction.To, executive); + } - if (txContext.Trace.IsSuccessful()) - await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime, - txContext, internalStateCache, - internalChainContext, - singleTxExecutingDto.OriginTransactionId, - cancellationToken); - } - catch (Exception ex) - { - Logger.LogError(ex, "Transaction execution failed."); - txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError; - txContext.Trace.Error += ex + "\n"; - throw; - } - finally - { - await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext, - singleTxExecutingDto.Transaction.To, executive); - } + return trace; + } - return trace; - } - - private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTime, - ITransactionContext txContext, TieredStateCache internalStateCache, - IChainContext internalChainContext, - Hash originTransactionId, - CancellationToken cancellationToken) + private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTime, + ITransactionContext txContext, TieredStateCache internalStateCache, + IChainContext internalChainContext, + Hash originTransactionId, + CancellationToken cancellationToken) + { + var trace = txContext.Trace; + internalStateCache.Update(txContext.Trace.GetStateSets()); + foreach (var inlineTx in txContext.Trace.InlineTransactions) { - var trace = txContext.Trace; - internalStateCache.Update(txContext.Trace.GetStateSets()); - foreach (var inlineTx in txContext.Trace.InlineTransactions) + var singleTxExecutingDto = new SingleTransactionExecutingDto { - var singleTxExecutingDto = new SingleTransactionExecutingDto - { - Depth = depth + 1, - ChainContext = internalChainContext, - Transaction = inlineTx, - CurrentBlockTime = currentBlockTime, - Origin = txContext.Origin, - OriginTransactionId = originTransactionId - }; + Depth = depth + 1, + ChainContext = internalChainContext, + Transaction = inlineTx, + CurrentBlockTime = currentBlockTime, + Origin = txContext.Origin, + OriginTransactionId = originTransactionId + }; - var inlineTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); + var inlineTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken); - if (inlineTrace == null) - break; - trace.InlineTraces.Add(inlineTrace); - if (!inlineTrace.IsSuccessful()) - { - // Already failed, no need to execute remaining inline transactions - break; - } + if (inlineTrace == null) + break; + trace.InlineTraces.Add(inlineTrace); + if (!inlineTrace.IsSuccessful()) + // Already failed, no need to execute remaining inline transactions + break; - internalStateCache.Update(inlineTrace.GetStateSets()); - } + internalStateCache.Update(inlineTrace.GetStateSets()); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj index ff9dba124e..a52621689a 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract.csproj @@ -5,13 +5,13 @@ true - true + true - true + true - + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/Contract.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/Contract.cs index bcd531ba68..1d3b809104 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/Contract.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/Contract.cs @@ -1,81 +1,68 @@ -using AElf.Standards.ACS8; -using AElf.Contracts.MultiToken; using AElf.Contracts.TokenConverter; using AElf.CSharp.Core; using AElf.Sdk.CSharp; -using AElf.Types; +using AElf.Standards.ACS8; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; + +public class Contract : ContractContainer.ContractBase { - public class Contract : ContractContainer.ContractBase + public override Empty BuyResourceToken(BuyResourceTokenInput input) { - public override Empty BuyResourceToken(BuyResourceTokenInput input) - { - if (State.TokenConverterContract.Value == null) - { - State.TokenConverterContract.Value = - Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - } + if (State.TokenConverterContract.Value == null) + State.TokenConverterContract.Value = + Context.GetContractAddressByName(SmartContractConstants.TokenConverterContractSystemName); - if (input.Amount > 0) + if (input.Amount > 0) + State.TokenConverterContract.Buy.Send(new BuyInput { - State.TokenConverterContract.Buy.Send(new BuyInput - { - Symbol = input.Symbol, - Amount = input.Amount, - PayLimit = input.PayLimit - }); - } + Symbol = input.Symbol, + Amount = input.Amount, + PayLimit = input.PayLimit + }); - return new Empty(); - } + return new Empty(); + } - /// - /// Time consuming. - /// - /// - /// - public override Empty CpuConsumingMethod(Empty input) - { - var sum = 0L; - for (var i = 0; i < 99; i++) - { - sum = sum.Add(i); - } + /// + /// Time consuming. + /// + /// + /// + public override Empty CpuConsumingMethod(Empty input) + { + var sum = 0L; + for (var i = 0; i < 99; i++) sum = sum.Add(i); - State.Map[sum.ToString()] = sum.ToString(); - return new Empty(); - } + State.Map[sum.ToString()] = sum.ToString(); + return new Empty(); + } - /// - /// Large writes count. - /// - /// - /// - public override Empty StoConsumingMethod(Empty input) - { - for (var i = 0; i < 99; i++) - { - State.Map[i.ToString()] = i.ToString(); - } + /// + /// Large writes count. + /// + /// + /// + public override Empty StoConsumingMethod(Empty input) + { + for (var i = 0; i < 99; i++) State.Map[i.ToString()] = i.ToString(); - return new Empty(); - } + return new Empty(); + } - /// - /// Large parameter. - /// - /// - /// - public override Empty TrafficConsumingMethod(TrafficConsumingMethodInput input) - { - return new Empty(); - } + /// + /// Large parameter. + /// + /// + /// + public override Empty TrafficConsumingMethod(TrafficConsumingMethodInput input) + { + return new Empty(); + } - public override Empty FewConsumingMethod(Empty input) - { - return new Empty(); - } + public override Empty FewConsumingMethod(Empty input) + { + return new Empty(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/ContractState.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/ContractState.cs index 5b7fc05324..34e4f122b7 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/ContractState.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract/ContractState.cs @@ -1,15 +1,14 @@ -using AElf.Standards.ACS0; -using AElf.Contracts.MultiToken; +using AElf.Contracts.MultiToken; using AElf.Contracts.TokenConverter; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS0; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; + +public class ContractState : Sdk.CSharp.State.ContractState { - public class ContractState : AElf.Sdk.CSharp.State.ContractState - { - public MappedState Map { get; set; } - internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } - internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } - internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } - } + public MappedState Map { get; set; } + internal ACS0Container.ACS0ReferenceState Acs0Contract { get; set; } + internal TokenConverterContractContainer.TokenConverterContractReferenceState TokenConverterContract { get; set; } + internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj index 1765e93f23..a748b27ecf 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj @@ -4,19 +4,19 @@ false - - - - - - + + + + + + - - - - - + + + + + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTest.cs index d5e3d3b892..6a47875b59 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTest.cs @@ -3,385 +3,379 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using AElf.Standards.ACS8; using AElf.Contracts.MultiToken; using AElf.Contracts.TokenConverter; using AElf.CSharp.Core; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.FeeCalculation.Extensions; -using AElf.Kernel.SmartContract.Events; using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; -using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS8; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; -using Volo.Abp.EventBus; using Volo.Abp.Threading; using Xunit; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests; + +public partial class ExecutionPluginForResourceFeeTest : ExecutionPluginForResourceFeeTestBase { - public partial class ExecutionPluginForResourceFeeTest : ExecutionPluginForResourceFeeTestBase + public ExecutionPluginForResourceFeeTest() + { + AsyncHelper.RunSync(InitializeContracts); + } + + [Fact] + public async Task BuyResourceToken_Test() { - public ExecutionPluginForResourceFeeTest() + var beforeElf = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - AsyncHelper.RunSync(InitializeContracts); - } + Owner = DefaultSender, + Symbol = "ELF" + })).Balance; - [Fact] - public async Task BuyResourceToken_Test() + var approveResult = await TokenContractStub.Transfer.SendAsync(new TransferInput { - var beforeElf = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = "ELF" - })).Balance; + Symbol = "ELF", + Amount = beforeElf / 2, + To = TestContractAddress + }); + approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var buyResult = await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput + { + Symbol = "READ", + Amount = 100_00000000 + }); + buyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var approveResult = await TokenContractStub.Transfer.SendAsync(new TransferInput + private async Task AdvanceResourceToken(List except = null, long amount = 10_000_00000000) + { + var resourceTokenList = new List { "READ", "WRITE", "STORAGE", "TRAFFIC" }; + if (except != null && except.Any()) resourceTokenList = resourceTokenList.Except(except).ToList(); + + foreach (var symbol in resourceTokenList) + { + await TokenConverterContractStub.Buy.SendAsync(new BuyInput { - Symbol = "ELF", - Amount = beforeElf / 2, - To = TestContractAddress + Symbol = symbol, + Amount = amount }); - approveResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var buyResult = await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput + await TokenContractStub.Transfer.SendAsync(new TransferInput { - Symbol = "READ", - Amount = 100_00000000, + To = TestContractAddress, + Amount = amount, + Symbol = symbol }); - buyResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private async Task AdvanceResourceToken(List except = null, long amount = 10_000_00000000) + foreach (var symbol in resourceTokenList) { - var resourceTokenList = new List {"READ", "WRITE", "STORAGE", "TRAFFIC"}; - if (except != null && except.Any()) - { - resourceTokenList = resourceTokenList.Except(except).ToList(); - } - - foreach (var symbol in resourceTokenList) - { - await TokenConverterContractStub.Buy.SendAsync(new BuyInput - { - Symbol = symbol, - Amount = amount - }); - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = TestContractAddress, - Amount = amount, - Symbol = symbol - }); - } - - foreach (var symbol in resourceTokenList) + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = symbol - })).Balance; - balance.ShouldBe(amount); - } + Owner = TestContractAddress, + Symbol = symbol + })).Balance; + balance.ShouldBe(amount); } + } + + /// + /// CpuConsumingMethod vs FewConsumingMethod + /// + /// + [Fact] + public async Task CompareCpuTokenConsumption() + { + await AdvanceResourceToken(); - /// - /// CpuConsumingMethod vs FewConsumingMethod - /// - /// - [Fact] - public async Task CompareCpuTokenConsumption() + const string symbol = "READ"; + + var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await AdvanceResourceToken(); + Owner = TestContractAddress, Symbol = symbol + }); + var consumption = balanceBefore.Balance - balanceAfter.Balance; + consumption.ShouldBeGreaterThan(0); - const string symbol = "READ"; + balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); - var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - var consumption = balanceBefore.Balance - balanceAfter.Balance; - consumption.ShouldBeGreaterThan(0); + var lesserConsumption = balanceBefore.Balance - balanceAfter.Balance; - balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); + consumption.ShouldBeGreaterThan(lesserConsumption); + } - var lesserConsumption = balanceBefore.Balance - balanceAfter.Balance; + /// + /// StoConsumingMethod vs FewConsumingMethod + /// + /// + [Fact] + public async Task CompareStoTokenConsumption() + { + await AdvanceResourceToken(); - consumption.ShouldBeGreaterThan(lesserConsumption); - } + const string symbol = "STORAGE"; - /// - /// StoConsumingMethod vs FewConsumingMethod - /// - /// - [Fact] - public async Task CompareStoTokenConsumption() + var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.StoConsumingMethod.SendAsync(new Empty()); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await AdvanceResourceToken(); + Owner = TestContractAddress, Symbol = symbol + }); - const string symbol = "STORAGE"; + var consumption = balanceBefore.Balance - balanceAfter.Balance; - var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.StoConsumingMethod.SendAsync(new Empty()); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); + balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); - var consumption = balanceBefore.Balance - balanceAfter.Balance; + var lesserConsumption = balanceAfter.Balance - balanceBefore.Balance; - balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); + consumption.ShouldBeGreaterThan(lesserConsumption); + } - var lesserConsumption = balanceAfter.Balance - balanceBefore.Balance; + /// + /// TrafficConsumingMethod vs FewConsumingMethod + /// + /// + [Fact] + public async Task CompareTrafficTokenConsumption() + { + await AdvanceResourceToken(); - consumption.ShouldBeGreaterThan(lesserConsumption); - } + const string symbol = "TRAFFIC"; - /// - /// TrafficConsumingMethod vs FewConsumingMethod - /// - /// - [Fact] - public async Task CompareTrafficTokenConsumption() + var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.TrafficConsumingMethod.SendAsync(new TrafficConsumingMethodInput + { + Blob = ByteString.CopyFrom("TrafficConsumingMethod vs FewConsumingMethod", Encoding.Default) + }); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await AdvanceResourceToken(); + Owner = TestContractAddress, Symbol = symbol + }); - const string symbol = "TRAFFIC"; + var consumption = balanceBefore.Balance - balanceAfter.Balance; - var balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.TrafficConsumingMethod.SendAsync(new TrafficConsumingMethodInput - { - Blob = ByteString.CopyFrom("TrafficConsumingMethod vs FewConsumingMethod", Encoding.Default) - }); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - var balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); + consumption.ShouldBeGreaterThan(0); - var consumption = balanceBefore.Balance - balanceAfter.Balance; + balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); + await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, Symbol = symbol + }); - consumption.ShouldBeGreaterThan(0); + var lesserConsumption = balanceBefore.Balance - balanceAfter.Balance; - balanceBefore = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); - await TestContractStub.FewConsumingMethod.SendAsync(new Empty()); - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - balanceAfter = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, Symbol = symbol - }); + consumption.ShouldBeGreaterThan(lesserConsumption); + } - var lesserConsumption = balanceBefore.Balance - balanceAfter.Balance; + [Fact] + public async Task CompareCpuTokenConsumption_WithoutResource() + { + var txResult = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + txResult.TransactionResult.Error.ShouldContain("is not enough"); + } - consumption.ShouldBeGreaterThan(lesserConsumption); - } + [Fact] + public async Task Consumption_WithoutInsufficientStorageToken() + { + await AdvanceResourceToken(new List { "STORAGE" }); + const long stoAmount = 100; // Not enough. - [Fact] - public async Task CompareCpuTokenConsumption_WithoutResource() + // Advance some STORAGE tokens. + await TokenConverterContractStub.Buy.SendAsync(new BuyInput { - var txResult = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - txResult.TransactionResult.Error.ShouldContain("is not enough"); - } - - [Fact] - public async Task Consumption_WithoutInsufficientStorageToken() + Symbol = "STORAGE", + Amount = 100_00000000L + }); + await TokenContractStub.Transfer.SendAsync(new TransferInput { - await AdvanceResourceToken(new List {"STORAGE"}); - const long stoAmount = 100; // Not enough. + To = TestContractAddress, + Amount = stoAmount, + Symbol = "STORAGE" + }); - // Advance some STORAGE tokens. - await TokenConverterContractStub.Buy.SendAsync(new BuyInput - { - Symbol = "STORAGE", - Amount = 100_00000000L - }); - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = TestContractAddress, - Amount = stoAmount, - Symbol = "STORAGE" - }); - - var txResult = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); - txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - } + var txResult = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); + txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + } - [Fact] - public async Task CompareConsumptions() - { - await AdvanceResourceToken(); + [Fact] + public async Task CompareConsumptions() + { + await AdvanceResourceToken(); - var (read, write, traffic, storage, txResult1) = - await GetTransactionResourcesCost(TestContractStub.CpuConsumingMethod.SendAsync); - var (read1, write1, traffic1, storage2, txResult2) = - await GetTransactionResourcesCost(TestContractStub.FewConsumingMethod.SendAsync); + var (read, write, traffic, storage, txResult1) = + await GetTransactionResourcesCost(TestContractStub.CpuConsumingMethod.SendAsync); + var (read1, write1, traffic1, storage2, txResult2) = + await GetTransactionResourcesCost(TestContractStub.FewConsumingMethod.SendAsync); - read.ShouldBeGreaterThan(read1); - write.ShouldBeGreaterThan(write1); - traffic.ShouldBe(traffic1); + read.ShouldBeGreaterThan(read1); + write.ShouldBeGreaterThan(write1); + traffic.ShouldBe(traffic1); - var consumedTokens1 = txResult1.GetConsumedResourceTokens(); - var consumedTokens2 = txResult2.GetConsumedResourceTokens(); - consumedTokens1["READ"].ShouldBeGreaterThan(consumedTokens2["READ"]); - consumedTokens1["WRITE"].ShouldBeGreaterThan(consumedTokens2["WRITE"]); - consumedTokens1["TRAFFIC"].ShouldBe(consumedTokens2["TRAFFIC"]); - consumedTokens1["STORAGE"].ShouldBe(consumedTokens2["STORAGE"]); + var consumedTokens1 = txResult1.GetConsumedResourceTokens(); + var consumedTokens2 = txResult2.GetConsumedResourceTokens(); + consumedTokens1["READ"].ShouldBeGreaterThan(consumedTokens2["READ"]); + consumedTokens1["WRITE"].ShouldBeGreaterThan(consumedTokens2["WRITE"]); + consumedTokens1["TRAFFIC"].ShouldBe(consumedTokens2["TRAFFIC"]); + consumedTokens1["STORAGE"].ShouldBe(consumedTokens2["STORAGE"]); - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = Accounts.Last().Address, - Symbol = "ELF", - Amount = 10 - }); - - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = Accounts.Last().Address, - Symbol = "ELF", - Amount = 10 - }); - - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - To = Accounts.Last().Address, - Symbol = "ELF", - Amount = 10 - }); + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + To = Accounts.Last().Address, + Symbol = "ELF", + Amount = 10 + }); - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = Accounts.Last().Address, - Symbol = "ELF" - })).Balance; - balance.ShouldBe(30); - } + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + To = Accounts.Last().Address, + Symbol = "ELF", + Amount = 10 + }); - private async Task<(long read, long write, long traffic, long storage, TransactionResult txResult)> - GetTransactionResourcesCost( - Func>> action) + await TokenContractStub.Transfer.SendAsync(new TransferInput { - var beforeRead = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "READ" - })).Balance; - var beforeWrite = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "WRITE" - })).Balance; - var beforeTraffic = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "TRAFFIC" - })).Balance; - var beforeStorage = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "STORAGE" - })).Balance; + To = Accounts.Last().Address, + Symbol = "ELF", + Amount = 10 + }); - var txResult = (await action(new Empty())).TransactionResult; - // Mine a block to use plugin to really consume resource tokens. - await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); + var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = Accounts.Last().Address, + Symbol = "ELF" + })).Balance; + balance.ShouldBe(30); + } - var afterRead = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "READ" - })).Balance; - var afterWrite = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "WRITE" - })).Balance; - var afterTraffic = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "TRAFFIC" - })).Balance; - var afterStorage = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = TestContractAddress, - Symbol = "STORAGE" - })).Balance; + private async Task<(long read, long write, long traffic, long storage, TransactionResult txResult)> + GetTransactionResourcesCost( + Func>> action) + { + var beforeRead = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, + Symbol = "READ" + })).Balance; + var beforeWrite = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, + Symbol = "WRITE" + })).Balance; + var beforeTraffic = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, + Symbol = "TRAFFIC" + })).Balance; + var beforeStorage = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = TestContractAddress, + Symbol = "STORAGE" + })).Balance; - return (beforeRead - afterRead, beforeWrite - afterWrite, beforeTraffic - afterTraffic, - beforeStorage - afterStorage, txResult); - } + var txResult = (await action(new Empty())).TransactionResult; + // Mine a block to use plugin to really consume resource tokens. + await TestContractStub.BuyResourceToken.SendAsync(new BuyResourceTokenInput()); - [Fact] - public async Task Donate_Resource_Token_Send_By_User_False() + var afterRead = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var result = (await TokenContractStub.DonateResourceToken.SendWithExceptionAsync(new TotalResourceTokensMaps())).TransactionResult; - result.Error.Contains("This method already executed in height").ShouldBeTrue(); - } - - [Fact] - public async Task CheckResourceToken_Fail_Test() + Owner = TestContractAddress, + Symbol = "READ" + })).Balance; + var afterWrite = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); - var checkResourceTokenRet = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); - checkResourceTokenRet.TransactionResult.Error.ShouldContain("token is not enough. Owning"); - } - - [Fact] - public async Task GetResourceTokenInfo_Test() + Owner = TestContractAddress, + Symbol = "WRITE" + })).Balance; + var afterTraffic = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var resourceToken = await TokenContractStub.GetResourceTokenInfo.CallAsync(new Empty()); - resourceToken.Value.Count.ShouldBe(4); - } - - [Fact] - async Task DonateResourceTokenValidationProvider_ValidateBeforeAttachAsync_Test() + Owner = TestContractAddress, + Symbol = "TRAFFIC" + })).Balance; + var afterStorage = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - var validator = GetRequiredService(); - var result = await validator.ValidateBeforeAttachAsync(null); - result.ShouldBeTrue(); - } + Owner = TestContractAddress, + Symbol = "STORAGE" + })).Balance; + + return (beforeRead - afterRead, beforeWrite - afterWrite, beforeTraffic - afterTraffic, + beforeStorage - afterStorage, txResult); + } + + [Fact] + public async Task Donate_Resource_Token_Send_By_User_False() + { + var result = (await TokenContractStub.DonateResourceToken.SendWithExceptionAsync(new TotalResourceTokensMaps())) + .TransactionResult; + result.Error.Contains("This method already executed in height").ShouldBeTrue(); + } + + [Fact] + public async Task CheckResourceToken_Fail_Test() + { + await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); + var checkResourceTokenRet = await TestContractStub.CpuConsumingMethod.SendWithExceptionAsync(new Empty()); + checkResourceTokenRet.TransactionResult.Error.ShouldContain("token is not enough. Owning"); + } + + [Fact] + public async Task GetResourceTokenInfo_Test() + { + var resourceToken = await TokenContractStub.GetResourceTokenInfo.CallAsync(new Empty()); + resourceToken.Value.Count.ShouldBe(4); + } + + [Fact] + private async Task DonateResourceTokenValidationProvider_ValidateBeforeAttachAsync_Test() + { + var validator = GetRequiredService(); + var result = await validator.ValidateBeforeAttachAsync(null); + result.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs index 3008a2bfe6..7d73b285db 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs @@ -4,13 +4,14 @@ using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; -using AElf.ContractTestKit; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; +using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.EconomicSystem; using AElf.Kernel.Proposal; +using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; using AElf.Kernel.Token; using AElf.Types; using Google.Protobuf; @@ -18,420 +19,425 @@ using Shouldly; using InitializeInput = AElf.Contracts.TokenConverter.InitializeInput; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests; + +public class ExecutionPluginForResourceFeeTestBase : ContractTestBase { - public class ExecutionPluginForResourceFeeTestBase : ContractTestBase + internal const long StoUnitPrice = 1_00000000; + + //init connectors + internal Connector ElfConnector = new() { - internal const long StoUnitPrice = 1_00000000; + Symbol = "ELF", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true + }; - //init connectors - internal Connector ElfConnector = new Connector - { - Symbol = "ELF", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true - }; + internal Connector NativeToNetConnector = new() + { + Symbol = "NTTRAFFIC", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "TRAFFIC" + }; - internal Connector ReadConnector = new Connector - { - Symbol = "READ", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "NTREAD" - }; - internal Connector NativeToReadConnector = new Connector - { - Symbol = "NTREAD", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - RelatedSymbol = "READ" - }; - - internal Connector StoConnector = new Connector - { - Symbol = "STORAGE", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "NTSTORAGE" - }; - internal Connector NativeToStoConnector = new Connector - { - Symbol = "NTSTORAGE", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true, - RelatedSymbol = "STORAGE" - }; - internal Connector NetConnector = new Connector - { - Symbol = "TRAFFIC", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "NTTRAFFIC" - }; - internal Connector NativeToNetConnector = new Connector - { - Symbol = "NTTRAFFIC", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "TRAFFIC" - }; - internal Connector WriteConnector = new Connector + internal Connector NativeToReadConnector = new() + { + Symbol = "NTREAD", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + RelatedSymbol = "READ" + }; + + internal Connector NativeToStoConnector = new() + { + Symbol = "NTSTORAGE", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, + RelatedSymbol = "STORAGE" + }; + + internal Connector NativeToWriteConnector = new() + { + Symbol = "NTWRITE", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "WRITE" + }; + + internal Connector NetConnector = new() + { + Symbol = "TRAFFIC", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "NTTRAFFIC" + }; + + internal Connector ReadConnector = new() + { + Symbol = "READ", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "NTREAD" + }; + + internal Connector StoConnector = new() + { + Symbol = "STORAGE", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "NTSTORAGE" + }; + + internal Connector WriteConnector = new() + { + Symbol = "WRITE", + VirtualBalance = 100_000_00000000, + Weight = "0.5", + IsPurchaseEnabled = true, + IsVirtualBalanceEnabled = true, // For testing + RelatedSymbol = "NTWRITE" + }; + + internal Address TestContractAddress { get; set; } + internal Address TokenContractAddress { get; set; } + internal Address TokenConverterAddress { get; set; } + internal Address TreasuryContractAddress { get; set; } + internal ContractContainer.ContractStub TestContractStub { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } + internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub { get; set; } + internal ParliamentContractContainer.ParliamentContractStub ParliamentContractStub { get; set; } + internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } + + internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(1).Select(a => a.KeyPair).ToList(); + + internal ECKeyPair OtherTester => Accounts[1].KeyPair; + internal Address DefaultSender => Accounts[0].Address; + protected Address FeeReceiverAddress => Accounts[10].Address; + protected Address ManagerAddress => Accounts[11].Address; + + protected async Task InitializeContracts() + { + await DeployContractsAsync(); + await InitializeTokenAsync(); + await InitializeParliament(); + await InitializeAElfConsensus(); + await InitializeTreasuryContractAsync(); + await InitializeTokenConverterAsync(); + } + + private async Task DeployContractsAsync() + { + const int category = KernelConstants.CodeCoverageRunnerCategory; + // Profit contract { - Symbol = "WRITE", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "NTWRITE" - }; - internal Connector NativeToWriteConnector = new Connector + var code = Codes.Single(kv => kv.Key.Contains("Profit")).Value; + await DeploySystemSmartContract(category, code, + ProfitSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + } + + // Token contract { - Symbol = "NTWRITE", - VirtualBalance = 100_000_00000000, - Weight = "0.5", - IsPurchaseEnabled = true, - IsVirtualBalanceEnabled = true,// For testing - RelatedSymbol = "WRITE" - }; + var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; + TokenContractAddress = await DeploySystemSmartContract(category, code, + TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TokenContractStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); + } - internal Address TestContractAddress { get; set; } - internal Address TokenContractAddress { get; set; } - internal Address TokenConverterAddress { get; set; } - internal Address TreasuryContractAddress { get; set; } - internal TestContract.ContractContainer.ContractStub TestContractStub { get; set; } - internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } - internal TokenConverterContractContainer.TokenConverterContractStub TokenConverterContractStub { get; set; } - internal TreasuryContractContainer.TreasuryContractStub TreasuryContractStub { get; set; } - internal ParliamentContractContainer.ParliamentContractStub ParliamentContractStub { get; set; } - internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } - - internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; - protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(1).Select(a => a.KeyPair).ToList(); - internal ECKeyPair OtherTester => Accounts[1].KeyPair; - internal Address DefaultSender => Accounts[0].Address; - protected Address FeeReceiverAddress => Accounts[10].Address; - protected Address ManagerAddress => Accounts[11].Address; - - protected async Task InitializeContracts() + // Token converter { - await DeployContractsAsync(); - await InitializeTokenAsync(); - await InitializeParliament(); - await InitializeAElfConsensus(); - await InitializeTreasuryContractAsync(); - await InitializeTokenConverterAsync(); + var code = Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value; + TokenConverterAddress = await DeploySystemSmartContract(category, code, + TokenConverterSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TokenConverterContractStub = + GetTester(TokenConverterAddress, + DefaultSenderKeyPair); } - - private async Task DeployContractsAsync() + + // Treasury { - const int category = KernelConstants.CodeCoverageRunnerCategory; - // Profit contract - { - var code = Codes.Single(kv => kv.Key.Contains("Profit")).Value; - await DeploySystemSmartContract(category, code, - ProfitSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - } + var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; + TreasuryContractAddress = await DeploySystemSmartContract(category, code, + TreasurySmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + TreasuryContractStub = + GetTester(TreasuryContractAddress, + DefaultSenderKeyPair); + } - // Token contract - { - var code = Codes.Single(kv => kv.Key.Contains("MultiToken")).Value; - TokenContractAddress = await DeploySystemSmartContract(category, code, - TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TokenContractStub = - GetTester(TokenContractAddress, DefaultSenderKeyPair); - } + // Test contract + { + var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; + TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), + DefaultSenderKeyPair); + TestContractStub = + GetTester(TestContractAddress, DefaultSenderKeyPair); + } - // Token converter - { - var code = Codes.Single(kv => kv.Key.Contains("TokenConverter")).Value; - TokenConverterAddress = await DeploySystemSmartContract(category, code, - TokenConverterSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TokenConverterContractStub = - GetTester(TokenConverterAddress, - DefaultSenderKeyPair); - } - - // Treasury - { - var code = Codes.Single(kv => kv.Key.Contains("Treasury")).Value; - TreasuryContractAddress = await DeploySystemSmartContract(category, code, - TreasurySmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - TreasuryContractStub = - GetTester(TreasuryContractAddress, - DefaultSenderKeyPair); - } + // Parliament + { + var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + var parliamentContractAddress = await DeploySystemSmartContract(category, code, + ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ParliamentContractStub = + GetTester(parliamentContractAddress, + DefaultSenderKeyPair); + } - // Test contract - { - var code = Codes.Single(kv => kv.Key.Contains("TestContract")).Value; - TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), + //Consensus + { + var code = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; + var consensusContractAddress = await DeploySystemSmartContract(category, code, + HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); + AEDPoSContractStub = + GetTester(consensusContractAddress, DefaultSenderKeyPair); - TestContractStub = - GetTester(TestContractAddress, DefaultSenderKeyPair); - } - - // Parliament - { - var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; - var parliamentContractAddress = await DeploySystemSmartContract(category, code, - ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); - ParliamentContractStub = - GetTester(parliamentContractAddress, - DefaultSenderKeyPair); - } - - //Consensus - { - var code = Codes.Single(kv => kv.Key.Contains("AEDPoS")).Value; - var consensusContractAddress = await DeploySystemSmartContract(category, code, - HashHelper.ComputeFrom("AElf.ContractNames.Consensus"), DefaultSenderKeyPair); - AEDPoSContractStub = - GetTester(consensusContractAddress, - DefaultSenderKeyPair); - } } + } - private async Task InitializeTokenAsync() + private async Task InitializeTokenAsync() + { + const long totalSupply = 1_000_000_000_00000000; + const long issueAmount = 1_000_000_00000000; + const long issueAmountToConverter = 100_000_000_00000000; + //init elf token { - const long totalSupply = 1_000_000_000_00000000; - const long issueAmount = 1_000_000_00000000; - const long issueAmountToConverter = 100_000_000_00000000; - //init elf token + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "ELF", - Decimals = 8, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = {TreasuryContractAddress, TokenConverterAddress} - }); + Symbol = "ELF", + Decimals = 8, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - { - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = issueAmount, - To = DefaultSender, - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - { - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "ELF", - Amount = issueAmountToConverter, - To = TokenConverterAddress, - Memo = "Set for elf token converter." - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - } + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - //init resource token - CPU { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - Symbol = "READ", - Decimals = 2, - IsBurnable = true, - TokenName = "read token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = {TreasuryContractAddress, TokenConverterAddress} - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "READ", + Symbol = "ELF", Amount = issueAmount, - To = TokenConverterAddress, - Memo = "Set for read token converter." + To = DefaultSender }); issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - //init resource token - STO { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "STORAGE", - Decimals = 2, - IsBurnable = true, - TokenName = "sto token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = {TreasuryContractAddress, TokenConverterAddress} - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - Symbol = "STORAGE", - Amount = issueAmount, + Symbol = "ELF", + Amount = issueAmountToConverter, To = TokenConverterAddress, - Memo = "Set for sto token converter." + Memo = "Set for elf token converter." }); issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - //init resource token - NET - { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "TRAFFIC", - Decimals = 2, - IsBurnable = true, - TokenName = "net token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = {TreasuryContractAddress, TokenConverterAddress} - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "TRAFFIC", - Amount = issueAmount, - To = TokenConverterAddress, - Memo = "Set for net token converter." - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - //init resource token - WRITE + //init resource token - CPU + { + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "WRITE", - Decimals = 2, - IsBurnable = true, - TokenName = "WRITE token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = {TreasuryContractAddress, TokenConverterAddress} - }); + Symbol = "READ", + Decimals = 2, + IsBurnable = true, + TokenName = "read token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = "WRITE", - Amount = issueAmount, - To = TokenConverterAddress, - Memo = "Set for WRITE token converter." - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "READ", + Amount = issueAmount, + To = TokenConverterAddress, + Memo = "Set for read token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private async Task InitializeTokenConverterAsync() + //init resource token - STO { - var input = new InitializeInput + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - BaseTokenSymbol = "ELF", - FeeRate = "0.005", - Connectors = - { - ElfConnector, ReadConnector, StoConnector, NetConnector, NativeToReadConnector, NativeToStoConnector, - NativeToNetConnector, WriteConnector, NativeToWriteConnector - } - }; + Symbol = "STORAGE", + Decimals = 2, + IsBurnable = true, + TokenName = "sto token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); + + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var initializeResult = await TokenConverterContractStub.Initialize.SendAsync(input); - initializeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "STORAGE", + Amount = issueAmount, + To = TokenConverterAddress, + Memo = "Set for sto token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private async Task InitializeTreasuryContractAsync() + //init resource token - NET { + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput { - var result = - await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = "TRAFFIC", + Decimals = 2, + IsBurnable = true, + TokenName = "net token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); + + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { - var result = - await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( - new Empty()); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + Symbol = "TRAFFIC", + Amount = issueAmount, + To = TokenConverterAddress, + Memo = "Set for net token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - private async Task InitializeParliament() + //init resource token - WRITE { - await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput()); + var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "WRITE", + Decimals = 2, + IsBurnable = true, + TokenName = "WRITE token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); + + createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = "WRITE", + Amount = issueAmount, + To = TokenConverterAddress, + Memo = "Set for WRITE token converter." + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - - private async Task InitializeAElfConsensus() + } + + private async Task InitializeTokenConverterAsync() + { + var input = new InitializeInput { + BaseTokenSymbol = "ELF", + FeeRate = "0.005", + Connectors = { - await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( - new InitialAElfConsensusContractInput - { - PeriodSeconds = 604800L, - MinerIncreaseInterval = 31536000 - }); - } - { - await AEDPoSContractStub.FirstRound.SendAsync( - GenerateFirstRoundOfNewTerm( - new MinerList - {Pubkeys = {InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey))}}, - 4000, TimestampHelper.GetUtcNow())); + ElfConnector, ReadConnector, StoConnector, NetConnector, NativeToReadConnector, NativeToStoConnector, + NativeToNetConnector, WriteConnector, NativeToWriteConnector } + }; + + var initializeResult = await TokenConverterContractStub.Initialize.SendAsync(input); + initializeResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private async Task InitializeTreasuryContractAsync() + { + { + var result = + await TreasuryContractStub.InitialTreasuryContract.SendAsync(new Empty()); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { - var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); - var round = new Round(); - - for (var i = 0; i < sortedMiners.Count; i++) - { - var minerInRound = new MinerInRound(); - - // The third miner will be the extra block producer of first round of each term. - if (i == 0) + var result = + await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( + new Empty()); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + } + + private async Task InitializeParliament() + { + await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput()); + } + + private async Task InitializeAElfConsensus() + { + { + await AEDPoSContractStub.InitialAElfConsensusContract.SendAsync( + new InitialAElfConsensusContractInput { - minerInRound.IsExtraBlockProducer = true; - } - - minerInRound.Pubkey = sortedMiners[i]; - minerInRound.Order = i + 1; - minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); - // Should be careful during validation. - minerInRound.PreviousInValue = Hash.Empty; - round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); - } - - round.RoundNumber = currentRoundNumber + 1; - round.TermNumber = currentTermNumber + 1; - round.IsMinerListJustChanged = true; - round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; - - return round; + PeriodSeconds = 604800L, + MinerIncreaseInterval = 31536000 + }); } + { + await AEDPoSContractStub.FirstRound.SendAsync( + GenerateFirstRoundOfNewTerm( + new MinerList + { Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } }, + 4000, TimestampHelper.GetUtcNow())); + } + } + + private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = minerList.Pubkeys.Select(x => x.ToHex()).ToList(); + var round = new Round(); + + for (var i = 0; i < sortedMiners.Count; i++) + { + var minerInRound = new MinerInRound(); + + // The third miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + round.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); + } + + round.RoundNumber = currentRoundNumber + 1; + round.TermNumber = currentTermNumber + 1; + round.IsMinerListJustChanged = true; + round.ExtraBlockProducerOfPreviousRound = sortedMiners[0]; + + return round; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs index c796f9d81f..22d634ad0b 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs @@ -1,27 +1,21 @@ -using AElf.Contracts.MultiToken; using AElf.ContractTestKit; using AElf.Kernel.FeeCalculation; using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract.Events; -using AElf.Kernel.SmartContract.Infrastructure; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Volo.Abp.EventBus; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests; + +[DependsOn(typeof(ContractTestModule), + typeof(ExecutionPluginForResourceFeeModule), + typeof(FeeCalculationModule))] +public class ExecutionPluginForResourceFeeTestModule : ContractTestModule { - [DependsOn(typeof(ContractTestModule), - typeof(ExecutionPluginForResourceFeeModule), - typeof(FeeCalculationModule))] - public class ExecutionPluginForResourceFeeTestModule : ContractTestModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => o.ContractDeploymentAuthorityRequired = false ); - context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); - context.Services.AddSingleton(); - } + Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddTransient(typeof(ILogEventProcessingService<>), typeof(LogEventProcessingService<>)); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ResourceTokenPluginAndSystemGeneratorTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ResourceTokenPluginAndSystemGeneratorTest.cs index 0f739f8f1e..6532126f42 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ResourceTokenPluginAndSystemGeneratorTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ResourceTokenPluginAndSystemGeneratorTest.cs @@ -7,285 +7,285 @@ using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.TestContract; using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; -using Xunit; using Shouldly; +using Xunit; + +namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests; -namespace AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests +public partial class ExecutionPluginForResourceFeeTest { - public partial class ExecutionPluginForResourceFeeTest + [Fact] + public async Task GenerateTransactions_NoneTransaction_Generate_Test() { - [Fact] - public async Task GenerateTransactions_NoneTransaction_Generate_Test() - { - // block height == 0 - var systemTransactionGenerator = - GetCreateInstance(); - systemTransactionGenerator.ShouldNotBeNull(); - var transactions = await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, 0, new Hash()); - transactions.Count.ShouldBe(0); + // block height == 0 + var systemTransactionGenerator = + GetCreateInstance(); + systemTransactionGenerator.ShouldNotBeNull(); + var transactions = await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, 0, new Hash()); + transactions.Count.ShouldBe(0); - await AdvanceResourceToken(); - await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); - await TokenContractStub.Approve.SendAsync(new ApproveInput - { - Symbol = "ELF", - Amount = 1000, - Spender = TokenConverterAddress - }); + await AdvanceResourceToken(); + await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); + await TokenContractStub.Approve.SendAsync(new ApproveInput + { + Symbol = "ELF", + Amount = 1000, + Spender = TokenConverterAddress + }); - //no new token fee information - var bcs = Application.ServiceProvider.GetRequiredService(); - var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); - transactions = - await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, - blockHeader.GetHash()); - transactions.Count.ShouldBe(1); - var systemTransaction = transactions[0]; - systemTransaction.MethodName.ShouldBe(nameof(TokenContractStub.DonateResourceToken)); - var tokenFeeInfo = TotalResourceTokensMaps.Parser.ParseFrom(systemTransaction.Params); - tokenFeeInfo.Value.Count.ShouldBe(0); - } + //no new token fee information + var bcs = Application.ServiceProvider.GetRequiredService(); + var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); + transactions = + await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, + blockHeader.GetHash()); + transactions.Count.ShouldBe(1); + var systemTransaction = transactions[0]; + systemTransaction.MethodName.ShouldBe(nameof(TokenContractStub.DonateResourceToken)); + var tokenFeeInfo = TotalResourceTokensMaps.Parser.ParseFrom(systemTransaction.Params); + tokenFeeInfo.Value.Count.ShouldBe(0); + } - [Fact] - public async Task GenerateTransactions_Success_Test() - { - const string symbol = "READ"; - await AdvanceResourceToken(); - await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); - var bcs = Application.ServiceProvider.GetRequiredService(); - var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); - var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); - var systemTransactionGenerator = - GetCreateInstance(); - systemTransactionGenerator.ShouldNotBeNull(); - var transactions = - await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, - blockHeader.GetHash()); - transactions.Count.ShouldBe(1); - var donateResourceTransaction = transactions[0]; - donateResourceTransaction.MethodName.ShouldBe(nameof(TokenContractContainer.TokenContractStub - .DonateResourceToken)); - var txFeeMap = TotalTransactionFeesMap.Parser.ParseFrom(donateResourceTransaction.Params); - txFeeMap.Value.ContainsKey(symbol); + [Fact] + public async Task GenerateTransactions_Success_Test() + { + const string symbol = "READ"; + await AdvanceResourceToken(); + await TestContractStub.CpuConsumingMethod.SendAsync(new Empty()); + var bcs = Application.ServiceProvider.GetRequiredService(); + var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); + var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); + var systemTransactionGenerator = + GetCreateInstance(); + systemTransactionGenerator.ShouldNotBeNull(); + var transactions = + await systemTransactionGenerator.GenerateTransactionsAsync(DefaultSender, blockHeader.Height, + blockHeader.GetHash()); + transactions.Count.ShouldBe(1); + var donateResourceTransaction = transactions[0]; + donateResourceTransaction.MethodName.ShouldBe(nameof(TokenContractContainer.TokenContractStub + .DonateResourceToken)); + var txFeeMap = TotalTransactionFeesMap.Parser.ParseFrom(donateResourceTransaction.Params); + txFeeMap.Value.ContainsKey(symbol); - var transactionValidations = Application.ServiceProvider - .GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per type - var claimTransactionValidation = - transactionValidations.SingleOrDefault( - p => p.GetType() == typeof(DonateResourceTokenValidationProvider)); - claimTransactionValidation.ShouldNotBeNull(); - var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); - validateRet.ShouldBe(true); - } + var transactionValidations = Application.ServiceProvider + .GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per type + var claimTransactionValidation = + transactionValidations.SingleOrDefault( + p => p.GetType() == typeof(DonateResourceTokenValidationProvider)); + claimTransactionValidation.ShouldNotBeNull(); + var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); + validateRet.ShouldBe(true); + } - [Fact] - public async Task ValidateBlockAfterExecute_Without_ResourceTokenFee_Test() - { - // without resource token fee - var bcs = Application.ServiceProvider.GetRequiredService(); - var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); - var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); - var claimTransactionValidation = GetCreateInstance(); - claimTransactionValidation.ShouldNotBeNull(); - var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); - validateRet.ShouldBe(true); + [Fact] + public async Task ValidateBlockAfterExecute_Without_ResourceTokenFee_Test() + { + // without resource token fee + var bcs = Application.ServiceProvider.GetRequiredService(); + var blockHeader = await bcs.GetBestChainLastBlockHeaderAsync(); + var block = await bcs.GetBlockByHashAsync(blockHeader.GetHash()); + var claimTransactionValidation = + GetCreateInstance(); + claimTransactionValidation.ShouldNotBeNull(); + var validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); + validateRet.ShouldBe(true); - // with invalid block height - block.Header.Height = block.Header.Height.Add(1); - validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); - validateRet.ShouldBe(false); - } + // with invalid block height + block.Header.Height = block.Header.Height.Add(1); + validateRet = await claimTransactionValidation.ValidateBlockAfterExecuteAsync(block); + validateRet.ShouldBe(false); + } - [Fact] - public async Task GetPreTransactions_None_PreTransaction_Generate_Test() - { - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); + [Fact] + public async Task GetPreTransactions_None_PreTransaction_Generate_Test() + { + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); - // invalid contract descriptor - var transactions = (await plugin.GetPreTransactionsAsync(TokenConverterContractContainer.Descriptors, - new TransactionContext + // invalid contract descriptor + var transactions = (await plugin.GetPreTransactionsAsync(TokenConverterContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TokenConverterAddress, - MethodName = nameof(TokenConverterContractStub.SetConnector) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + From = DefaultSender, + To = TokenConverterAddress, + MethodName = nameof(TokenConverterContractStub.SetConnector) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - transactions.Count.ShouldBe(0); + transactions.Count.ShouldBe(0); - // token contract address and method name is ChargeResourceToken - transactions = (await plugin.GetPreTransactionsAsync(TokenContractContainer.Descriptors, - new TransactionContext + // token contract address and method name is ChargeResourceToken + transactions = (await plugin.GetPreTransactionsAsync(TokenContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TokenContractAddress, - MethodName = nameof(TokenContractStub.ChargeResourceToken) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + From = DefaultSender, + To = TokenContractAddress, + MethodName = nameof(TokenContractStub.ChargeResourceToken) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - transactions.Count.ShouldBe(0); + transactions.Count.ShouldBe(0); - //method name is BuyResourceToken - transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + //method name is BuyResourceToken + transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TestContractAddress, - MethodName = "BuyResourceToken" - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + From = DefaultSender, + To = TestContractAddress, + MethodName = "BuyResourceToken" + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - transactions.Count.ShouldBe(0); - } + transactions.Count.ShouldBe(0); + } - [Fact] - public async Task GetPreTransactions_Success_Test() - { - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); + [Fact] + public async Task GetPreTransactions_Success_Test() + { + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); - var transactions = (await plugin.GetPreTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + var transactions = (await plugin.GetPreTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = TestContractAddress, - To = TokenConverterAddress, - MethodName = nameof(TestContractStub.CpuConsumingMethod) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); - - transactions.Count.ShouldBe(1); - var preTransaction = transactions[0]; - preTransaction.MethodName.ShouldBe(nameof(TokenContractStub.CheckResourceToken)); - } - - [Fact] - public async Task GetPreTransactions_None_PostTransaction_Generate_Test() - { - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); + From = TestContractAddress, + To = TokenConverterAddress, + MethodName = nameof(TestContractStub.CpuConsumingMethod) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - // invalid contract descriptor - var transactions = (await plugin.GetPostTransactionsAsync(TokenConverterContractContainer.Descriptors, - new TransactionContext - { - Transaction = new Transaction - { - From = DefaultSender, - To = TokenConverterAddress, - MethodName = nameof(TokenConverterContractStub.SetConnector) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + transactions.Count.ShouldBe(1); + var preTransaction = transactions[0]; + preTransaction.MethodName.ShouldBe(nameof(TokenContractStub.CheckResourceToken)); + } - transactions.Count.ShouldBe(0); + [Fact] + public async Task GetPreTransactions_None_PostTransaction_Generate_Test() + { + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); - // token contract address and method name is ChargeResourceToken - transactions = (await plugin.GetPostTransactionsAsync(TokenContractContainer.Descriptors, - new TransactionContext + // invalid contract descriptor + var transactions = (await plugin.GetPostTransactionsAsync(TokenConverterContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TokenContractAddress, - MethodName = nameof(TokenContractStub.ChargeResourceToken) - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + From = DefaultSender, + To = TokenConverterAddress, + MethodName = nameof(TokenConverterContractStub.SetConnector) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - transactions.Count.ShouldBe(0); + transactions.Count.ShouldBe(0); - //method name is BuyResourceToken - transactions = (await plugin.GetPostTransactionsAsync(TestContract.ContractContainer.Descriptors, - new TransactionContext + // token contract address and method name is ChargeResourceToken + transactions = (await plugin.GetPostTransactionsAsync(TokenContractContainer.Descriptors, + new TransactionContext + { + Transaction = new Transaction { - Transaction = new Transaction - { - From = DefaultSender, - To = TestContractAddress, - MethodName = "BuyResourceToken" - }, - BlockHeight = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash - })).ToList(); + From = DefaultSender, + To = TokenContractAddress, + MethodName = nameof(TokenContractStub.ChargeResourceToken) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + })).ToList(); - transactions.Count.ShouldBe(0); - } + transactions.Count.ShouldBe(0); - [Fact] - public async Task GetPostTransactions_Success_Test() - { - const string symbol = "READ"; - var plugin = GetCreateInstance(); - plugin.ShouldNotBeNull(); - var bcs = Application.ServiceProvider.GetRequiredService(); - var chain = await bcs.GetChainAsync(); - var transactionContext = new TransactionContext + //method name is BuyResourceToken + transactions = (await plugin.GetPostTransactionsAsync(ContractContainer.Descriptors, + new TransactionContext { Transaction = new Transaction { - From = TestContractAddress, - To = TokenConverterAddress, - MethodName = nameof(TestContractStub.CpuConsumingMethod) + From = DefaultSender, + To = TestContractAddress, + MethodName = "BuyResourceToken" }, BlockHeight = chain.BestChainHeight + 1, PreviousBlockHash = chain.BestChainHash - }; - transactionContext.Trace = new TransactionTrace - { - StateSet = new TransactionExecutingStateSet() - }; - var stateCounts = transactionContext.Trace.StateSet; - stateCounts.Reads["read"] = true; - var transactions = (await plugin.GetPostTransactionsAsync(TestContract.ContractContainer.Descriptors, - transactionContext)).ToList(); + })).ToList(); - transactions.Count.ShouldBe(1); - var postTransaction = transactions[0]; - postTransaction.MethodName.ShouldBe(nameof(TokenContractStub.ChargeResourceToken)); - var tokenFeeInfo = ChargeResourceTokenInput.Parser.ParseFrom(postTransaction.Params); - tokenFeeInfo.CostDic.ContainsKey(symbol); - tokenFeeInfo.CostDic[symbol].ShouldBeGreaterThan(0); - } + transactions.Count.ShouldBe(0); + } - private I GetCreateInstance() where T : I + [Fact] + public async Task GetPostTransactions_Success_Test() + { + const string symbol = "READ"; + var plugin = GetCreateInstance(); + plugin.ShouldNotBeNull(); + var bcs = Application.ServiceProvider.GetRequiredService(); + var chain = await bcs.GetChainAsync(); + var transactionContext = new TransactionContext + { + Transaction = new Transaction + { + From = TestContractAddress, + To = TokenConverterAddress, + MethodName = nameof(TestContractStub.CpuConsumingMethod) + }, + BlockHeight = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash + }; + transactionContext.Trace = new TransactionTrace { - var implements = Application.ServiceProvider.GetRequiredService>() - .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per t - var implement = implements.SingleOrDefault(p => p.GetType() == typeof(T)); - return implement; - } + StateSet = new TransactionExecutingStateSet() + }; + var stateCounts = transactionContext.Trace.StateSet; + stateCounts.Reads["read"] = true; + var transactions = (await plugin.GetPostTransactionsAsync(ContractContainer.Descriptors, + transactionContext)).ToList(); + + transactions.Count.ShouldBe(1); + var postTransaction = transactions[0]; + postTransaction.MethodName.ShouldBe(nameof(TokenContractStub.ChargeResourceToken)); + var tokenFeeInfo = ChargeResourceTokenInput.Parser.ParseFrom(postTransaction.Params); + tokenFeeInfo.CostDic.ContainsKey(symbol); + tokenFeeInfo.CostDic[symbol].ShouldBeGreaterThan(0); + } + + private I GetCreateInstance() where T : I + { + var implements = Application.ServiceProvider.GetRequiredService>() + .ToLookup(p => p.GetType()).Select(coll => coll.First()); // One instance per t + var implement = implements.SingleOrDefault(p => p.GetType() == typeof(T)); + return implement; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/AElf.Kernel.SmartContract.Parallel.Tests.csproj b/test/AElf.Kernel.SmartContract.Parallel.Tests/AElf.Kernel.SmartContract.Parallel.Tests.csproj index d980d043cd..b97f886c9c 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/AElf.Kernel.SmartContract.Parallel.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/AElf.Kernel.SmartContract.Parallel.Tests.csproj @@ -4,14 +4,14 @@ false - - - - - + + + + + - + false Contract @@ -60,13 +60,13 @@ - - - - - - - + + + + + + + diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/ConflictingTransactionIdentificationServiceTest.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/ConflictingTransactionIdentificationServiceTest.cs index 9263251007..92b49f7cd9 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/ConflictingTransactionIdentificationServiceTest.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/ConflictingTransactionIdentificationServiceTest.cs @@ -12,109 +12,106 @@ using Volo.Abp.Modularity; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ConflictingTransactionIdentificationServiceTestModule : AElfModule { - public class ConflictingTransactionIdentificationServiceTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - var blockchainService = new MockBlockchainService(); - context.Services.AddSingleton(_ => blockchainService); - context.Services - .AddSingleton(); - } + context.Services.AddSingleton(); + var blockchainService = new MockBlockchainService(); + context.Services.AddSingleton(_ => blockchainService); + context.Services + .AddSingleton(); } +} - public class ConflictingTransactionIdentificationServiceTest : AElfIntegratedTest - { - private IConflictingTransactionIdentificationService Service => - Application.ServiceProvider.GetRequiredService(); +public class + ConflictingTransactionIdentificationServiceTest : AElfIntegratedTest< + ConflictingTransactionIdentificationServiceTestModule> +{ + private IConflictingTransactionIdentificationService Service => + Application.ServiceProvider.GetRequiredService(); - private IBlockchainService BlockchainService => - Application.ServiceProvider.GetRequiredService(); + private IBlockchainService BlockchainService => + Application.ServiceProvider.GetRequiredService(); - [Fact] - public async Task IdentifyProblematicTransactionTest() + [Fact] + public async Task IdentifyProblematicTransactionTest() + { + var includedInBlock = new[] { - var includedInBlock = new[] - { - GetFakePairs(SampleAddress.AddressList[0], new[] {1, 2, 3}), // independent - GetFakePairs(SampleAddress.AddressList[1], new[] {4, 5, 6}), - GetFakePairs(SampleAddress.AddressList[2], new[] {6, 7, 8}) - }; - var conflicting = new[] - { - GetFakePairs(SampleAddress.AddressList[3], new[] {10, 11, 12}, new[] {4, 10, 11, 12}), - GetFakePairs(SampleAddress.AddressList[4], new[] {16, 17, 18}, new[] {3,16, 17, 18, 19}, new[] {3}) - }; - var okTxnInConflictingSet = new[] - { - GetFakePairs(SampleAddress.AddressList[5], new[] {13, 14, 15}), - GetFakePairs(SampleAddress.AddressList[6], new[] {20, 21, 22}, new[] {20, 21, 22, 13}, new[] {13}, - new[] {13}), - GetFakePairs(SampleAddress.AddressList[6], new[] {24, 25, 26}, new[] {24, 25, 26, 13}, new[] {26}, - new[] {13}) + GetFakePairs(SampleAddress.AddressList[0], new[] { 1, 2, 3 }), // independent + GetFakePairs(SampleAddress.AddressList[1], new[] { 4, 5, 6 }), + GetFakePairs(SampleAddress.AddressList[2], new[] { 6, 7, 8 }) + }; + var conflicting = new[] + { + GetFakePairs(SampleAddress.AddressList[3], new[] { 10, 11, 12 }, new[] { 4, 10, 11, 12 }), + GetFakePairs(SampleAddress.AddressList[4], new[] { 16, 17, 18 }, new[] { 3, 16, 17, 18, 19 }, new[] { 3 }) + }; + var okTxnInConflictingSet = new[] + { + GetFakePairs(SampleAddress.AddressList[5], new[] { 13, 14, 15 }), + GetFakePairs(SampleAddress.AddressList[6], new[] { 20, 21, 22 }, new[] { 20, 21, 22, 13 }, new[] { 13 }, + new[] { 13 }), + GetFakePairs(SampleAddress.AddressList[6], new[] { 24, 25, 26 }, new[] { 24, 25, 26, 13 }, new[] { 26 }, + new[] { 13 }) + }; - }; + await BlockchainService.AddTransactionsAsync(includedInBlock.Concat(conflicting).Concat(okTxnInConflictingSet) + .Select(x => x.Item2)); - await BlockchainService.AddTransactionsAsync(includedInBlock.Concat(conflicting).Concat(okTxnInConflictingSet) - .Select(x => x.Item2)); + var wrong = await Service.IdentifyConflictingTransactionsAsync(new Mock().Object, + includedInBlock.Select(x => x.Item1).ToList(), + conflicting.Concat(okTxnInConflictingSet).Select(x => x.Item1).ToList()); + wrong.Count.ShouldBe(2); + conflicting.First().Item2.ShouldBe(wrong.First().Transaction); + conflicting[1].Item2.ShouldBe(wrong[1].Transaction); + } - var wrong = await Service.IdentifyConflictingTransactionsAsync(new Mock().Object, - includedInBlock.Select(x => x.Item1).ToList(), - conflicting.Concat(okTxnInConflictingSet).Select(x => x.Item1).ToList()); - wrong.Count.ShouldBe(2); - conflicting.First().Item2.ShouldBe(wrong.First().Transaction); - conflicting[1].Item2.ShouldBe(wrong[1].Transaction); - } - - private (ExecutionReturnSet, Transaction) GetFakePairs(Address destination, int[] expectedKeys, - int[] actualKeys = null, int[] readExpectedKeys = null, int[] readOnlyActualKeys = null) + private (ExecutionReturnSet, Transaction) GetFakePairs(Address destination, int[] expectedKeys, + int[] actualKeys = null, int[] readExpectedKeys = null, int[] readOnlyActualKeys = null) + { + var tri = new TransactionResourceInfo { - var tri = new TransactionResourceInfo - { - WritePaths = - { - expectedKeys.Select(GetPath) - } - }; - if (readExpectedKeys != null) + WritePaths = { - tri.ReadPaths.AddRange(readExpectedKeys.Select(GetPath)); + expectedKeys.Select(GetPath) } - var txn = new Transaction - { - From = SampleAddress.AddressList[7], - To = destination, - MethodName = "Dummy", - Params = tri.ToByteString(), - Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) - }; - var rs = new ExecutionReturnSet {TransactionId = txn.GetHash()}; - actualKeys ??= expectedKeys; - var readOnlyStateKeys = readOnlyActualKeys?.Select(GetPath).Select(p => p.ToStateKey()).ToList(); - foreach (var key in actualKeys.Select(GetPath).Select(p => p.ToStateKey())) - { - rs.StateAccesses[key] = true; - if(readOnlyActualKeys != null && readOnlyStateKeys.Contains(key)) continue; - rs.StateChanges[key] = ByteString.Empty; - } - - return (rs, txn); + }; + if (readExpectedKeys != null) tri.ReadPaths.AddRange(readExpectedKeys.Select(GetPath)); + var txn = new Transaction + { + From = SampleAddress.AddressList[7], + To = destination, + MethodName = "Dummy", + Params = tri.ToByteString(), + Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) + }; + var rs = new ExecutionReturnSet { TransactionId = txn.GetHash() }; + actualKeys ??= expectedKeys; + var readOnlyStateKeys = readOnlyActualKeys?.Select(GetPath).Select(p => p.ToStateKey()).ToList(); + foreach (var key in actualKeys.Select(GetPath).Select(p => p.ToStateKey())) + { + rs.StateAccesses[key] = true; + if (readOnlyActualKeys != null && readOnlyStateKeys.Contains(key)) continue; + rs.StateChanges[key] = ByteString.Empty; } - private ScopedStatePath GetPath(int value) + return (rs, txn); + } + + private ScopedStatePath GetPath(int value) + { + return new ScopedStatePath { - return new ScopedStatePath + Address = SampleAddress.AddressList[0], + Path = new StatePath { - Address = SampleAddress.AddressList[0], - Path = new StatePath - { - Parts = {value.ToString()} - } - }; - } + Parts = { value.ToString() } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/InternalConstants.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/InternalConstants.cs index 5e361e747a..f4a8a74323 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/InternalConstants.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/InternalConstants.cs @@ -1,9 +1,8 @@ -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +internal class InternalConstants { - internal class InternalConstants - { - public const string NonAcs2 = "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7"; - public const string Acs2 = "ZJjdajAmP5HpWgvLkXa5mm6gcuGWwKjN3Kos89ZJogHYDgTsB"; - public const string NonParallel = "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi"; - } + public const string NonAcs2 = "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7"; + public const string Acs2 = "ZJjdajAmP5HpWgvLkXa5mm6gcuGWwKjN3Kos89ZJogHYDgTsB"; + public const string NonParallel = "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi"; } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/LocalParallelTransactionExecutingServiceTests.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/LocalParallelTransactionExecutingServiceTests.cs index 657924ef55..dae47de047 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/LocalParallelTransactionExecutingServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/LocalParallelTransactionExecutingServiceTests.cs @@ -8,61 +8,61 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public sealed class LocalParallelTransactionExecutingServiceTests : ParallelExecutionTestBase { - public sealed class LocalParallelTransactionExecutingServiceTests : ParallelExecutionTestBase + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ITransactionExecutingService _transactionExecutingService; + + public LocalParallelTransactionExecutingServiceTests() + { + _transactionExecutingService = GetRequiredService(); + _systemTransactionExtraDataProvider = GetRequiredService(); + } + + [Fact] + public async Task ExecuteAsync_Test() { - private readonly ITransactionExecutingService _transactionExecutingService; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + var chain = await BlockchainService.GetChainAsync(); - public LocalParallelTransactionExecutingServiceTests() + (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); + Block = OsTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, PrepareTransactions); + PrepareTransactions[0].To = SampleAccount.Accounts[0].Address; + await OsTestHelper.BroadcastTransactions(PrepareTransactions); + var executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto { - _transactionExecutingService = GetRequiredService(); - _systemTransactionExtraDataProvider = GetRequiredService(); - } + Transactions = PrepareTransactions, + BlockHeader = Block.Header + }, CancellationToken.None); + executionReturnSets.Count.ShouldBe(PrepareTransactions.Count); + executionReturnSets.Count(set => set.TransactionResult.Status == TransactionResultStatus.Failed) + .ShouldBe(1); + executionReturnSets.First(set => set.TransactionResult.Status == TransactionResultStatus.Failed) + .TransactionResult.Error.ShouldBe("Invalid contract address."); + executionReturnSets.Count(set => set.TransactionResult.Status == TransactionResultStatus.Mined).ShouldBe(9); - [Fact] - public async Task ExecuteAsync_Test() + (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); + Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, PrepareTransactions); + await OsTestHelper.BroadcastTransactions(PrepareTransactions); + var cancelTokenSource = new CancellationTokenSource(); + cancelTokenSource.Cancel(); + executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto { - var chain = await BlockchainService.GetChainAsync(); + Transactions = PrepareTransactions, + BlockHeader = Block.Header + }, cancelTokenSource.Token); + executionReturnSets.Count.ShouldBe(0); - (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); - Block = OsTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, PrepareTransactions); - PrepareTransactions[0].To = SampleAccount.Accounts[0].Address; - await OsTestHelper.BroadcastTransactions(PrepareTransactions); - var executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto - { - Transactions = PrepareTransactions, - BlockHeader = Block.Header - }, CancellationToken.None); - executionReturnSets.Count.ShouldBe(PrepareTransactions.Count); - executionReturnSets.Count(set => set.TransactionResult.Status == TransactionResultStatus.Failed) - .ShouldBe(1); - executionReturnSets.First(set => set.TransactionResult.Status == TransactionResultStatus.Failed).TransactionResult.Error.ShouldBe("Invalid contract address."); - executionReturnSets.Count(set => set.TransactionResult.Status == TransactionResultStatus.Mined).ShouldBe(9); - - (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); - Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, PrepareTransactions); - await OsTestHelper.BroadcastTransactions(PrepareTransactions); - var cancelTokenSource = new CancellationTokenSource(); - cancelTokenSource.Cancel(); - executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto - { - Transactions = PrepareTransactions, - BlockHeader = Block.Header - }, cancelTokenSource.Token); - executionReturnSets.Count.ShouldBe(0); - - (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); - Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, PrepareTransactions); - _systemTransactionExtraDataProvider.SetSystemTransactionCount(1,Block.Header); - executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto - { - Transactions = PrepareTransactions, - BlockHeader = Block.Header - }, CancellationToken.None); - executionReturnSets.Count.ShouldBe(PrepareTransactions.Count); - executionReturnSets.ShouldAllBe(set => set.TransactionResult.Status == TransactionResultStatus.Mined); - } + (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); + Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, PrepareTransactions); + _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, Block.Header); + executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto + { + Transactions = PrepareTransactions, + BlockHeader = Block.Header + }, CancellationToken.None); + executionReturnSets.Count.ShouldBe(PrepareTransactions.Count); + executionReturnSets.ShouldAllBe(set => set.TransactionResult.Status == TransactionResultStatus.Mined); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockBlockchainService.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockBlockchainService.cs index 27bfaa12e9..311f1e22ed 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockBlockchainService.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockBlockchainService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -5,112 +6,112 @@ using AElf.Kernel.Blockchain.Domain; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class MockBlockchainService : IBlockchainService { - public class MockBlockchainService : IBlockchainService - { - private List _data = new List(); - - public int GetChainId() - { - throw new System.NotImplementedException(); - } - - public async Task CreateChainAsync(Block block, IEnumerable transactions) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public Task AddTransactionsAsync(IEnumerable transactions) - { - _data.AddRange(transactions); - - return Task.CompletedTask; - } - - public Task> GetTransactionsAsync(IEnumerable transactionHashes) - { - return Task.FromResult(_data.Where(d => transactionHashes.Contains(d.GetHash())).ToList()); - } - - public Task HasTransactionAsync(Hash transactionId) - { - throw new System.NotImplementedException(); - } - - public async Task AddBlockAsync(Block block) - { - await Task.FromException(new System.NotImplementedException()); - } - - public async Task HasBlockAsync(Hash blockId) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task GetBlockByHashAsync(Hash blockId) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task GetBlockHeaderByHashAsync(Hash blockId) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task GetChainAsync() - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task> GetReversedBlockIndexes(Hash lastBlockHash, int count) - { - return await Task.FromException>(new System.NotImplementedException()); - } - - public async Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, Hash chainBranchBlockHash = null) - { - return await Task.FromException>(new System.NotImplementedException()); - } - - public async Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task AttachBlockToChainAsync(Chain chain, Block block) - { - return await Task.FromException(new System.NotImplementedException()); - } - - public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) - { - await Task.FromException(new System.NotImplementedException()); - } - - public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, Hash irreversibleBlockHash) - { - await Task.FromException(new System.NotImplementedException()); - } - - public Task GetDiscardedBranchAsync(Chain chain) - { - throw new System.NotImplementedException(); - } - - public Task CleanChainBranchAsync(DiscardedBranch discardedBranch) - { - throw new System.NotImplementedException(); - } - - public Task ResetChainToLibAsync(Chain chain) - { - throw new System.NotImplementedException(); - } - - public Task RemoveLongestBranchAsync(Chain chain) - { - throw new System.NotImplementedException(); - } + private readonly List _data = new(); + + public int GetChainId() + { + throw new NotImplementedException(); + } + + public async Task CreateChainAsync(Block block, IEnumerable transactions) + { + return await Task.FromException(new NotImplementedException()); + } + + public Task AddTransactionsAsync(IEnumerable transactions) + { + _data.AddRange(transactions); + + return Task.CompletedTask; + } + + public Task> GetTransactionsAsync(IEnumerable transactionHashes) + { + return Task.FromResult(_data.Where(d => transactionHashes.Contains(d.GetHash())).ToList()); + } + + public Task HasTransactionAsync(Hash transactionId) + { + throw new NotImplementedException(); + } + + public async Task AddBlockAsync(Block block) + { + await Task.FromException(new NotImplementedException()); + } + + public async Task HasBlockAsync(Hash blockId) + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task GetBlockByHashAsync(Hash blockId) + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task GetBlockHeaderByHashAsync(Hash blockId) + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task GetChainAsync() + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task> GetReversedBlockIndexes(Hash lastBlockHash, int count) + { + return await Task.FromException>(new NotImplementedException()); + } + + public async Task> GetBlockHashesAsync(Chain chain, Hash firstHash, int count, + Hash chainBranchBlockHash = null) + { + return await Task.FromException>(new NotImplementedException()); + } + + public async Task GetBlockHashByHeightAsync(Chain chain, long height, Hash chainBranchBlockHash) + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task AttachBlockToChainAsync(Chain chain, Block block) + { + return await Task.FromException(new NotImplementedException()); + } + + public async Task SetBestChainAsync(Chain chain, long bestChainHeight, Hash bestChainHash) + { + await Task.FromException(new NotImplementedException()); + } + + public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight, Hash irreversibleBlockHash) + { + await Task.FromException(new NotImplementedException()); + } + + public Task GetDiscardedBranchAsync(Chain chain) + { + throw new NotImplementedException(); + } + + public Task CleanChainBranchAsync(DiscardedBranch discardedBranch) + { + throw new NotImplementedException(); + } + + public Task ResetChainToLibAsync(Chain chain) + { + throw new NotImplementedException(); + } + + public Task RemoveLongestBranchAsync(Chain chain) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockResourceExtractionService.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockResourceExtractionService.cs index 584e830f18..9e52817e66 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockResourceExtractionService.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockResourceExtractionService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -6,38 +7,37 @@ using AElf.Kernel.TransactionPool; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class MockResourceExtractionService : IResourceExtractionService { - public class MockResourceExtractionService : IResourceExtractionService + public async Task> GetResourcesAsync(IChainContext chainContext, + IEnumerable transactions, CancellationToken ct) { - public async Task> GetResourcesAsync(IChainContext chainContext, - IEnumerable transactions, CancellationToken ct) + return await Task.FromResult(transactions.Select(tx => new TransactionWithResourceInfo { - return await Task.FromResult(transactions.Select(tx => new TransactionWithResourceInfo - { - Transaction = tx, - TransactionResourceInfo = TransactionResourceInfo.Parser.ParseFrom(tx.Params) - })); - } + Transaction = tx, + TransactionResourceInfo = TransactionResourceInfo.Parser.ParseFrom(tx.Params) + })); + } - public Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData) - { - throw new System.NotImplementedException(); - } + public Task HandleTransactionAcceptedEvent(TransactionAcceptedEvent eventData) + { + throw new NotImplementedException(); + } - public Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData) - { - throw new System.NotImplementedException(); - } - - public Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData) - { - throw new System.NotImplementedException(); - } + public Task HandleNewIrreversibleBlockFoundAsync(NewIrreversibleBlockFoundEvent eventData) + { + throw new NotImplementedException(); + } - public void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds) - { - throw new System.NotImplementedException(); - } + public Task HandleBlockAcceptedAsync(BlockAcceptedEvent eventData) + { + throw new NotImplementedException(); + } + + public void ClearConflictingTransactionsResourceCache(IEnumerable transactionIds) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockSystemTransactionExtraDataProvider.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockSystemTransactionExtraDataProvider.cs index ee514029b8..f0693fbd6e 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/MockSystemTransactionExtraDataProvider.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/MockSystemTransactionExtraDataProvider.cs @@ -1,29 +1,27 @@ -using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner.Application; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class MockSystemTransactionExtraDataProvider : ISystemTransactionExtraDataProvider { - public class MockSystemTransactionExtraDataProvider : ISystemTransactionExtraDataProvider + private const string BlockHeaderExtraDataKey = "SystemTransactionCount"; + + public bool TryGetSystemTransactionCount(BlockHeader blockHeader, out int count) { - private const string BlockHeaderExtraDataKey = "SystemTransactionCount"; + count = 0; - public bool TryGetSystemTransactionCount(BlockHeader blockHeader,out int count) - { - count = 0; - - var byteString = blockHeader.ExtraData.TryGetValue(BlockHeaderExtraDataKey, out var extraData) - ? extraData - : null; - if (byteString == null) return false; - count = Int32Value.Parser.ParseFrom(byteString).Value; - return true; - } + var byteString = blockHeader.ExtraData.TryGetValue(BlockHeaderExtraDataKey, out var extraData) + ? extraData + : null; + if (byteString == null) return false; + count = Int32Value.Parser.ParseFrom(byteString).Value; + return true; + } - public void SetSystemTransactionCount(int count, BlockHeader blockHeader) - { - blockHeader.ExtraData.Add(BlockHeaderExtraDataKey, new Int32Value {Value = count}.ToByteString()); - } + public void SetSystemTransactionCount(int count, BlockHeader blockHeader) + { + blockHeader.ExtraData.Add(BlockHeaderExtraDataKey, new Int32Value { Value = count }.ToByteString()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/NonparallelContractCodeProviderTests.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/NonparallelContractCodeProviderTests.cs index b249d9a0bd..f80de4e255 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/NonparallelContractCodeProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/NonparallelContractCodeProviderTests.cs @@ -11,73 +11,72 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public sealed class NonparallelContractCodeProviderTests : AElfIntegratedTest { - public sealed class NonparallelContractCodeProviderTests : AElfIntegratedTest + private readonly IBlockchainExecutedDataCacheProvider + _blockchainExecutedDataCacheProvider; + + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly CleanBlockExecutedDataChangeHeightEventHandler _cleanBlockExecutedDataChangeHeightEventHandler; + private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; + + public NonparallelContractCodeProviderTests() { - private readonly IBlockchainService _blockchainService; - private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly CleanBlockExecutedDataChangeHeightEventHandler _cleanBlockExecutedDataChangeHeightEventHandler; + _blockchainService = GetRequiredService(); + _nonparallelContractCodeProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _blockchainExecutedDataCacheProvider = + GetRequiredService>(); + _cleanBlockExecutedDataChangeHeightEventHandler = + GetRequiredService(); + } - private readonly IBlockchainExecutedDataCacheProvider - _blockchainExecutedDataCacheProvider; + [Fact] + public async Task NonparallelContractCodeSetAndGet_Test() + { + var chain = await _blockchainService.GetChainAsync(); + + var blockExecutedDataKey = $"BlockExecutedData/NonparallelContractCode/{SampleAddress.AddressList[0]}"; + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.ShouldNotContainKey(blockExecutedDataKey); - public NonparallelContractCodeProviderTests() + var nonparallelContractCode = new NonparallelContractCode { - _blockchainService = GetRequiredService(); - _nonparallelContractCodeProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _blockchainExecutedDataCacheProvider = - GetRequiredService>(); - _cleanBlockExecutedDataChangeHeightEventHandler = - GetRequiredService(); - } - - [Fact] - public async Task NonparallelContractCodeSetAndGet_Test() + CodeHash = HashHelper.ComputeFrom(blockExecutedDataKey) + }; + + var dictionary = new Dictionary { - var chain = await _blockchainService.GetChainAsync(); + { SampleAddress.AddressList[0], nonparallelContractCode } + }; - var blockExecutedDataKey = $"BlockExecutedData/NonparallelContractCode/{SampleAddress.AddressList[0]}"; - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.ShouldNotContainKey(blockExecutedDataKey); - - var nonparallelContractCode = new NonparallelContractCode - { - CodeHash = HashHelper.ComputeFrom(blockExecutedDataKey) - }; + await _nonparallelContractCodeProvider.SetNonparallelContractCodeAsync(new BlockIndex + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, dictionary); - var dictionary = new Dictionary - { - {SampleAddress.AddressList[0], nonparallelContractCode} - }; + blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); - await _nonparallelContractCodeProvider.SetNonparallelContractCodeAsync(new BlockIndex + _blockchainExecutedDataCacheProvider.TryGetChangeHeight(blockExecutedDataKey, out _).ShouldBeTrue(); + + var nonparallelContractCodeFromState = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight - }, dictionary); - - blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); - - _blockchainExecutedDataCacheProvider.TryGetChangeHeight(blockExecutedDataKey,out _).ShouldBeTrue(); - - var nonparallelContractCodeFromState = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, SampleAddress.AddressList[0]); - nonparallelContractCodeFromState.ShouldBe(nonparallelContractCode); + }, SampleAddress.AddressList[0]); + nonparallelContractCodeFromState.ShouldBe(nonparallelContractCode); - await _cleanBlockExecutedDataChangeHeightEventHandler.HandleEventAsync( - new CleanBlockExecutedDataChangeHeightEventData - { - IrreversibleBlockHeight = chain.BestChainHeight - }); - _blockchainExecutedDataCacheProvider.TryGetChangeHeight(blockExecutedDataKey,out _).ShouldBeFalse(); - } + await _cleanBlockExecutedDataChangeHeightEventHandler.HandleEventAsync( + new CleanBlockExecutedDataChangeHeightEventData + { + IrreversibleBlockHeight = chain.BestChainHeight + }); + _blockchainExecutedDataCacheProvider.TryGetChangeHeight(blockExecutedDataKey, out _).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelExecutionTestBase.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelExecutionTestBase.cs index d8787a9822..eea92d1553 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelExecutionTestBase.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelExecutionTestBase.cs @@ -10,43 +10,44 @@ using AElf.TestBase; using AElf.Types; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ParallelExecutionTestBase : AElfIntegratedTest { - public class ParallelExecutionTestBase : AElfIntegratedTest - { - protected IBlockExecutingService BlockExecutingService { get; set; } - protected IBlockchainService BlockchainService { get; set; } - protected IBlockAttachService BlockAttachService { get; set; } - protected IMinerService MinerService { get; set; } - - protected ISmartContractAddressService SmartContractAddressService { get; set; } - protected ITransactionResultManager TransactionResultManager { get; set; } - protected ITransactionReadOnlyExecutionService TransactionReadOnlyExecutionService { get; set; } - protected INotModifiedCachedStateStore BlockStateSets { get; set; } - protected OSTestHelper OsTestHelper { get; set; } + protected Block Block; + protected List CancellableTransactions; + protected List KeyPairs; + protected List PrepareTransactions; + + protected List SystemTransactions; - protected List SystemTransactions; - protected List PrepareTransactions; - protected List CancellableTransactions; - protected List KeyPairs; - protected Block Block; + public ParallelExecutionTestBase() + { + BlockchainService = GetRequiredService(); + BlockExecutingService = GetRequiredService(); + MinerService = GetRequiredService(); + SmartContractAddressService = GetRequiredService(); + TransactionResultManager = GetRequiredService(); + TransactionReadOnlyExecutionService = GetRequiredService(); + BlockStateSets = GetRequiredService>(); + OsTestHelper = GetRequiredService(); + BlockAttachService = GetRequiredService(); - public ParallelExecutionTestBase() - { - BlockchainService = GetRequiredService(); - BlockExecutingService = GetRequiredService(); - MinerService = GetRequiredService(); - SmartContractAddressService = GetRequiredService(); - TransactionResultManager = GetRequiredService(); - TransactionReadOnlyExecutionService = GetRequiredService(); - BlockStateSets = GetRequiredService>(); - OsTestHelper = GetRequiredService(); - BlockAttachService = GetRequiredService(); - - PrepareTransactions = new List(); - SystemTransactions = new List(); - CancellableTransactions = new List(); - KeyPairs = new List();; - } + PrepareTransactions = new List(); + SystemTransactions = new List(); + CancellableTransactions = new List(); + KeyPairs = new List(); + ; } + + protected IBlockExecutingService BlockExecutingService { get; set; } + protected IBlockchainService BlockchainService { get; set; } + protected IBlockAttachService BlockAttachService { get; set; } + protected IMinerService MinerService { get; set; } + + protected ISmartContractAddressService SmartContractAddressService { get; set; } + protected ITransactionResultManager TransactionResultManager { get; set; } + protected ITransactionReadOnlyExecutionService TransactionReadOnlyExecutionService { get; set; } + protected INotModifiedCachedStateStore BlockStateSets { get; set; } + protected OSTestHelper OsTestHelper { get; set; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTestTransactionContextFactory.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTestTransactionContextFactory.cs index e937c966e7..eb21a8f0ad 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTestTransactionContextFactory.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTestTransactionContextFactory.cs @@ -1,42 +1,41 @@ +using System; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContractExecution; using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ParallelTestTransactionContextFactory : ITransactionContextFactory { - public class ParallelTestTransactionContextFactory : ITransactionContextFactory + public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Timestamp blockTime = null, + int callDepth = 0) { - public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Timestamp blockTime = null, - int callDepth = 0) + return new TransactionContext { - return new TransactionContext + Trace = new TransactionTrace + { + TransactionId = transaction.GetHash() + }, + Transaction = transaction, + PreviousBlockHash = chainContext.BlockHash, + BlockHeight = chainContext.BlockHeight + 1, + CurrentBlockTime = blockTime ?? TimestampHelper.GetUtcNow(), + CallDepth = callDepth, + MaxCallDepth = 64, + Origin = transaction.From, + OriginTransactionId = transaction.GetHash(), + ExecutionObserverThreshold = new ExecutionObserverThreshold { - Trace = new TransactionTrace - { - TransactionId = transaction.GetHash() - }, - Transaction = transaction, - PreviousBlockHash = chainContext.BlockHash, - BlockHeight = chainContext.BlockHeight + 1, - CurrentBlockTime = blockTime ?? TimestampHelper.GetUtcNow(), - CallDepth = callDepth, - MaxCallDepth = 64, - Origin = transaction.From, - OriginTransactionId = transaction.GetHash(), - ExecutionObserverThreshold = new ExecutionObserverThreshold - { - ExecutionBranchThreshold = SmartContractConstants.ExecutionBranchThreshold, - ExecutionCallThreshold = SmartContractConstants.ExecutionCallThreshold - }, - StateCache = chainContext.StateCache - }; - } + ExecutionBranchThreshold = SmartContractConstants.ExecutionBranchThreshold, + ExecutionCallThreshold = SmartContractConstants.ExecutionCallThreshold + }, + StateCache = chainContext.StateCache + }; + } - public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, - Address originAddress, int callDepth = 0, Timestamp blockTime = null) - { - throw new System.NotImplementedException(); - } + public ITransactionContext Create(Transaction transaction, IChainContext chainContext, Hash originTransactionId, + Address originAddress, int callDepth = 0, Timestamp blockTime = null) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTransactionExecutionTests.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTransactionExecutionTests.cs index 397c38de01..233114d043 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTransactionExecutionTests.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/ParallelTransactionExecutionTests.cs @@ -7,136 +7,138 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ParallelTransactionExecutionTests : ParallelExecutionTestBase { - public class ParallelTransactionExecutionTests : ParallelExecutionTestBase + [Fact] + public async Task ParallelExecuteAsync_Test() { - [Fact] - public async Task ParallelExecuteAsync_Test() - { - var chain = await BlockchainService.GetChainAsync(); + var chain = await BlockchainService.GetChainAsync(); - (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); - Block = OsTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, PrepareTransactions); - //await BlockExecutingService.ExecuteBlockAsync(Block.Header, PrepareTransactions); - await OsTestHelper.BroadcastTransactions(PrepareTransactions); - Block = (await MinerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; - await BlockchainService.AddBlockAsync(Block); - await BlockAttachService.AttachBlockAsync(Block); + (PrepareTransactions, KeyPairs) = await OsTestHelper.PrepareTokenForParallel(10); + Block = OsTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, PrepareTransactions); + //await BlockExecutingService.ExecuteBlockAsync(Block.Header, PrepareTransactions); + await OsTestHelper.BroadcastTransactions(PrepareTransactions); + Block = (await MinerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromSeconds(4))).Block; + await BlockchainService.AddBlockAsync(Block); + await BlockAttachService.AttachBlockAsync(Block); - SystemTransactions = await OsTestHelper.GenerateTransferTransactions(1); - CancellableTransactions = await OsTestHelper.GenerateTransactionsWithoutConflictAsync(KeyPairs); - Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, - SystemTransactions.Concat(CancellableTransactions)); + SystemTransactions = await OsTestHelper.GenerateTransferTransactions(1); + CancellableTransactions = await OsTestHelper.GenerateTransactionsWithoutConflictAsync(KeyPairs); + Block = OsTestHelper.GenerateBlock(Block.GetHash(), Block.Height, + SystemTransactions.Concat(CancellableTransactions)); - await OsTestHelper.BroadcastTransactions(SystemTransactions.Concat(CancellableTransactions)); - var block = (await BlockExecutingService.ExecuteBlockAsync(Block.Header, - SystemTransactions, CancellableTransactions, CancellationToken.None)).Block; - block.TransactionIds.Count().ShouldBeGreaterThan(10); - } + await OsTestHelper.BroadcastTransactions(SystemTransactions.Concat(CancellableTransactions)); + var block = (await BlockExecutingService.ExecuteBlockAsync(Block.Header, + SystemTransactions, CancellableTransactions, CancellationToken.None)).Block; + block.TransactionIds.Count().ShouldBeGreaterThan(10); + } - [Fact] - public async Task GetTransactionParametersAsync_Test() + [Fact] + public async Task GetTransactionParametersAsync_Test() + { + var chain = await BlockchainService.GetChainAsync(); + var context = new ChainContext { - var chain = await BlockchainService.GetChainAsync(); - var context = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var transaction = await OsTestHelper.GenerateTransferTransaction(); + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var transaction = await OsTestHelper.GenerateTransferTransaction(); - var jsonResult = - await TransactionReadOnlyExecutionService.GetTransactionParametersAsync(context, transaction); + var jsonResult = + await TransactionReadOnlyExecutionService.GetTransactionParametersAsync(context, transaction); - jsonResult.ShouldNotBeEmpty(); - jsonResult.ShouldContain("to"); - jsonResult.ShouldContain("symbol"); - jsonResult.ShouldContain("amount"); - } + jsonResult.ShouldNotBeEmpty(); + jsonResult.ShouldContain("to"); + jsonResult.ShouldContain("symbol"); + jsonResult.ShouldContain("amount"); + } - [Fact] - public async Task TransactionReadOnlyExecutionServiceExtensions_Test() + [Fact] + public async Task TransactionReadOnlyExecutionServiceExtensions_Test() + { + var chain = await BlockchainService.GetChainAsync(); + var context = new ChainContext { - var chain = await BlockchainService.GetChainAsync(); - var context = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], + await SmartContractAddressService.GetAddressByContractNameAsync(context, + TokenSmartContractAddressNameProvider.StringName), + "GetBalance", new GetBalanceInput { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], - await SmartContractAddressService.GetAddressByContractNameAsync(context, TokenSmartContractAddressNameProvider.StringName), - "GetBalance", new GetBalanceInput - { - Owner = SampleAddress.AddressList[0], - Symbol = "ELF" - }); + Owner = SampleAddress.AddressList[0], + Symbol = "ELF" + }); + + var result = await TransactionReadOnlyExecutionService.ExecuteAsync(context, transaction, + TimestampHelper.GetUtcNow(), + true); + result.Balance.ShouldBe(0); + result.Symbol.ShouldBe("ELF"); - var result = await TransactionReadOnlyExecutionService.ExecuteAsync(context, transaction, + //without such method and call + transaction.MethodName = "NotExist"; + await Should.ThrowAsync(async () => + { + await TransactionReadOnlyExecutionService.ExecuteAsync(context, transaction, TimestampHelper.GetUtcNow(), true); - result.Balance.ShouldBe(0); - result.Symbol.ShouldBe("ELF"); - - //without such method and call - transaction.MethodName = "NotExist"; - await Should.ThrowAsync(async () => - { - await TransactionReadOnlyExecutionService.ExecuteAsync(context, transaction, - TimestampHelper.GetUtcNow(), - true); - }); - } + }); + } - [Fact] - public async Task GetFileDescriptorsAsync_Test() + [Fact] + public async Task GetFileDescriptorsAsync_Test() + { + var chain = await BlockchainService.GetChainAsync(); + var context = new ChainContext { - var chain = await BlockchainService.GetChainAsync(); - var context = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var tokenAddress = - await SmartContractAddressService.GetAddressByContractNameAsync(context, TokenSmartContractAddressNameProvider.StringName); - var fileDescriptor = - (await TransactionReadOnlyExecutionService.GetFileDescriptorsAsync(context, tokenAddress)).ToList(); - fileDescriptor.Count.ShouldBeGreaterThan(0); - fileDescriptor.ShouldAllBe(o => o.Name.Contains("proto")); - } - - [Fact] - public async Task IsViewTransactionAsync_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var tokenAddress = + await SmartContractAddressService.GetAddressByContractNameAsync(context, + TokenSmartContractAddressNameProvider.StringName); + var fileDescriptor = + (await TransactionReadOnlyExecutionService.GetFileDescriptorsAsync(context, tokenAddress)).ToList(); + fileDescriptor.Count.ShouldBeGreaterThan(0); + fileDescriptor.ShouldAllBe(o => o.Name.Contains("proto")); + } + + [Fact] + public async Task IsViewTransactionAsync_Test() + { + var chain = await BlockchainService.GetChainAsync(); + var context = new ChainContext { - var chain = await BlockchainService.GetChainAsync(); - var context = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], + await SmartContractAddressService.GetAddressByContractNameAsync(context, + TokenSmartContractAddressNameProvider.StringName), + "GetBalance", new GetBalanceInput { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], - await SmartContractAddressService.GetAddressByContractNameAsync(context, TokenSmartContractAddressNameProvider.StringName), - "GetBalance", new GetBalanceInput - { - Owner = SampleAddress.AddressList[0], - Symbol = "ELF" - }); + Owner = SampleAddress.AddressList[0], + Symbol = "ELF" + }); - var result = await TransactionReadOnlyExecutionService.IsViewTransactionAsync(context, transaction); - result.ShouldBeTrue(); + var result = await TransactionReadOnlyExecutionService.IsViewTransactionAsync(context, transaction); + result.ShouldBeTrue(); - transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], - await SmartContractAddressService.GetAddressByContractNameAsync(context, - TokenSmartContractAddressNameProvider.StringName), - "Transfer", new TransferInput - { - To = SampleAddress.AddressList[1], - Symbol = "ELF", - Amount = 10 - }); - result = await TransactionReadOnlyExecutionService.IsViewTransactionAsync(context, transaction); - result.ShouldBeFalse(); - } + transaction = OsTestHelper.GenerateTransaction(SampleAddress.AddressList[0], + await SmartContractAddressService.GetAddressByContractNameAsync(context, + TokenSmartContractAddressNameProvider.StringName), + "Transfer", new TransferInput + { + To = SampleAddress.AddressList[1], + Symbol = "ELF", + Amount = 10 + }); + result = await TransactionReadOnlyExecutionService.IsViewTransactionAsync(context, transaction); + result.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/ResourceExtractionServiceTest.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/ResourceExtractionServiceTest.cs index 5bf33cb970..56eb669ddb 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/ResourceExtractionServiceTest.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/ResourceExtractionServiceTest.cs @@ -1,16 +1,14 @@ -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS2; -using AElf.ContractTestKit; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Events; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Parallel.Domain; -using AElf.Kernel.SmartContractExecution.Application; +using AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract; using AElf.Kernel.TransactionPool; +using AElf.Standards.ACS2; using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; @@ -19,286 +17,287 @@ using Volo.Abp.Testing; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ResourceExtractionServiceTest : AbpIntegratedTest { - public class ResourceExtractionServiceTest : AbpIntegratedTest - { - private IResourceExtractionService Service => - Application.ServiceProvider.GetRequiredService(); + private IResourceExtractionService Service => + Application.ServiceProvider.GetRequiredService(); + + private ISmartContractExecutiveService SmartContractExecutiveService => + Application.ServiceProvider.GetRequiredService(); - private ISmartContractExecutiveService SmartContractExecutiveService => - Application.ServiceProvider.GetRequiredService(); + private ParallelExecutionInterestedEventsHandler ParallelExecutionInterestedEventsHandler => + Application.ServiceProvider.GetRequiredService(); - private ParallelExecutionInterestedEventsHandler ParallelExecutionInterestedEventsHandler => - Application.ServiceProvider.GetRequiredService(); + [Fact] + public async Task GetResourcesAsync_NonAcs2_Test() + { + var txn = GetNonAcs2Transaction(new ResourceInfo()); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn }, CancellationToken.None)) + .ToList(); - [Fact] - public async Task GetResourcesAsync_NonAcs2_Test() + resourceInfos.Count.ShouldBe(1); + resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo { - var txn = GetNonAcs2Transaction(new ResourceInfo()); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn}, CancellationToken.None)) - .ToList(); + TransactionId = txn.GetHash(), + ParallelType = ParallelType.NonParallelizable + }); + } - resourceInfos.Count.ShouldBe(1); - resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo() + [Fact] + public async Task GetResourcesAsync_Acs2_Parallelizable_Test() + { + var txn = GetAcs2Transaction(new ResourceInfo + { + WritePaths = { - TransactionId = txn.GetHash(), - ParallelType = ParallelType.NonParallelizable - }); - } - - [Fact] - public async Task GetResourcesAsync_Acs2_Parallelizable_Test() + GetPath(12345) + }, + ReadPaths = + { + GetPath(123) + } + }); + var otherTxn = GetAcs2Transaction(new ResourceInfo { - var txn = GetAcs2Transaction(new ResourceInfo + WritePaths = { - WritePaths = - { - GetPath(12345) - }, - ReadPaths = - { - GetPath(123) - } - }); - var otherTxn = GetAcs2Transaction(new ResourceInfo + GetPath(6789) + }, + ReadPaths = { - WritePaths = - { - GetPath(6789) - }, - ReadPaths = - { - GetPath(12345), - GetPath(123) - } - }); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn,otherTxn}, CancellationToken.None)) - .ToList(); - var readOnlyPaths = resourceInfos.GetReadOnlyPaths(); - readOnlyPaths.Count.ShouldBe(1); - readOnlyPaths.ShouldContain(GetPath(123)); - var executive = - await SmartContractExecutiveService.GetExecutiveAsync(new Mock().Object, txn.To); - resourceInfos.Count.ShouldBe(2); - resourceInfos[0].TransactionResourceInfo.ShouldBe(new TransactionResourceInfo + GetPath(12345), + GetPath(123) + } + }); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn, otherTxn }, + CancellationToken.None)) + .ToList(); + var readOnlyPaths = resourceInfos.GetReadOnlyPaths(); + readOnlyPaths.Count.ShouldBe(1); + readOnlyPaths.ShouldContain(GetPath(123)); + var executive = + await SmartContractExecutiveService.GetExecutiveAsync(new Mock().Object, txn.To); + resourceInfos.Count.ShouldBe(2); + resourceInfos[0].TransactionResourceInfo.ShouldBe(new TransactionResourceInfo + { + TransactionId = txn.GetHash(), + WritePaths = { - TransactionId = txn.GetHash(), - WritePaths = - { - GetPath(12345) - }, - ReadPaths = - { - GetPath(123) - }, - ContractHash = executive.ContractHash - }); - resourceInfos[1].TransactionResourceInfo.ShouldBe(new TransactionResourceInfo + GetPath(12345) + }, + ReadPaths = { - TransactionId = otherTxn.GetHash(), - WritePaths = - { - GetPath(6789) - }, - ReadPaths = - { - GetPath(12345), - GetPath(123) - }, - ContractHash = executive.ContractHash - }); - } - - [Fact] - public async Task GetResourcesAsync_Acs2_CancellationRequested_Test() + GetPath(123) + }, + ContractHash = executive.ContractHash + }); + resourceInfos[1].TransactionResourceInfo.ShouldBe(new TransactionResourceInfo { - var cancelTokenSource = new CancellationTokenSource(); - cancelTokenSource.Cancel(); - var txn = GetAcs2Transaction(new ResourceInfo + TransactionId = otherTxn.GetHash(), + WritePaths = { - WritePaths = - { - GetPath(12345) - } - }); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn}, cancelTokenSource.Token)) - .ToList(); - resourceInfos.Count.ShouldBe(1); - resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo() + GetPath(6789) + }, + ReadPaths = { - TransactionId = txn.GetHash(), - ParallelType = ParallelType.NonParallelizable - }); - } + GetPath(12345), + GetPath(123) + }, + ContractHash = executive.ContractHash + }); + } - [Fact] - public async Task GetResourcesAsync_Acs2_NonParallelizable_Test() + [Fact] + public async Task GetResourcesAsync_Acs2_CancellationRequested_Test() + { + var cancelTokenSource = new CancellationTokenSource(); + cancelTokenSource.Cancel(); + var txn = GetAcs2Transaction(new ResourceInfo { - var txn = GetAcs2Transaction(new ResourceInfo + WritePaths = { - NonParallelizable = true - }); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn}, CancellationToken.None)) - .ToList(); + GetPath(12345) + } + }); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn }, cancelTokenSource.Token)) + .ToList(); + resourceInfos.Count.ShouldBe(1); + resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo + { + TransactionId = txn.GetHash(), + ParallelType = ParallelType.NonParallelizable + }); + } - var executive = await SmartContractExecutiveService.GetExecutiveAsync(new Mock().Object, txn.To); - resourceInfos.Count.ShouldBe(1); - resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo() - { - TransactionId = txn.GetHash(), - ParallelType = ParallelType.NonParallelizable, - ContractHash = executive.ContractHash - }); - } - - [Fact] - public async Task GetResourcesAsync_WithNonParallelCode_Test() + [Fact] + public async Task GetResourcesAsync_Acs2_NonParallelizable_Test() + { + var txn = GetAcs2Transaction(new ResourceInfo { - var txn = GetNonParallelCodeTransaction(new ResourceInfo()); - await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent - { - Transaction = txn - }); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn}, CancellationToken.None)) - .ToList(); + NonParallelizable = true + }); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn }, CancellationToken.None)) + .ToList(); - resourceInfos.Count.ShouldBe(1); - var testContractFile = typeof(SmartContractExecution.Parallel.Tests.TestContract.TestContract).Assembly - .Location; - var code = File.ReadAllBytes(testContractFile); - var transactionResourceInfo = new TransactionResourceInfo - { - TransactionId = txn.GetHash(), - ParallelType = ParallelType.NonParallelizable, - IsNonparallelContractCode = true, - ContractHash = HashHelper.ComputeFrom(code) - }; - resourceInfos.First().TransactionResourceInfo.ShouldBe(transactionResourceInfo); - } - - [Fact] - public async Task GetResourcesAsync_WithCache_Test() + var executive = await SmartContractExecutiveService.GetExecutiveAsync(new Mock().Object, txn.To); + resourceInfos.Count.ShouldBe(1); + resourceInfos.First().TransactionResourceInfo.ShouldBe(new TransactionResourceInfo { - var txn = GetNonAcs2Transaction(new ResourceInfo()); - await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent - { - Transaction = txn - }); - var otherTxn = GetNonAcs2Transaction(new ResourceInfo()); - var resourceInfos = - (await Service.GetResourcesAsync(new Mock().Object, new[] {txn,otherTxn}, CancellationToken.None)) - .ToList(); + TransactionId = txn.GetHash(), + ParallelType = ParallelType.NonParallelizable, + ContractHash = executive.ContractHash + }); + } - resourceInfos.Count.ShouldBe(2); - var transactionResourceInfo = new TransactionResourceInfo - { - TransactionId = txn.GetHash(), - ParallelType = ParallelType.NonParallelizable - }; - resourceInfos.First().TransactionResourceInfo.ShouldBe(transactionResourceInfo); - resourceInfos[1].TransactionResourceInfo.ShouldBe(transactionResourceInfo); - } + [Fact] + public async Task GetResourcesAsync_WithNonParallelCode_Test() + { + var txn = GetNonParallelCodeTransaction(new ResourceInfo()); + await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent + { + Transaction = txn + }); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn }, CancellationToken.None)) + .ToList(); - [Fact] - public async Task HandleNewIrreversibleBlockFoundAsync_Test() + resourceInfos.Count.ShouldBe(1); + var testContractFile = typeof(TestContract).Assembly + .Location; + var code = File.ReadAllBytes(testContractFile); + var transactionResourceInfo = new TransactionResourceInfo { - var txn = GetNonAcs2Transaction(new ResourceInfo()); - await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent - { - Transaction = txn - }); - await Service.HandleNewIrreversibleBlockFoundAsync(new NewIrreversibleBlockFoundEvent - { - BlockHeight = 600 - }); - } + TransactionId = txn.GetHash(), + ParallelType = ParallelType.NonParallelizable, + IsNonparallelContractCode = true, + ContractHash = HashHelper.ComputeFrom(code) + }; + resourceInfos.First().TransactionResourceInfo.ShouldBe(transactionResourceInfo); + } + + [Fact] + public async Task GetResourcesAsync_WithCache_Test() + { + var txn = GetNonAcs2Transaction(new ResourceInfo()); + await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent + { + Transaction = txn + }); + var otherTxn = GetNonAcs2Transaction(new ResourceInfo()); + var resourceInfos = + (await Service.GetResourcesAsync(new Mock().Object, new[] { txn, otherTxn }, + CancellationToken.None)) + .ToList(); - [Fact] - public async Task ClearConflictingTransactionsResourceCache_Test() + resourceInfos.Count.ShouldBe(2); + var transactionResourceInfo = new TransactionResourceInfo { - var txn = GetNonAcs2Transaction(new ResourceInfo()); - await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent - { - Transaction = txn - }); - Service.ClearConflictingTransactionsResourceCache(new []{txn.GetHash()}); - } + TransactionId = txn.GetHash(), + ParallelType = ParallelType.NonParallelizable + }; + resourceInfos.First().TransactionResourceInfo.ShouldBe(transactionResourceInfo); + resourceInfos[1].TransactionResourceInfo.ShouldBe(transactionResourceInfo); + } - [Fact] - public async Task HandleBlockAcceptedAsync_Test() + [Fact] + public async Task HandleNewIrreversibleBlockFoundAsync_Test() + { + var txn = GetNonAcs2Transaction(new ResourceInfo()); + await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent + { + Transaction = txn + }); + await Service.HandleNewIrreversibleBlockFoundAsync(new NewIrreversibleBlockFoundEvent + { + BlockHeight = 600 + }); + } + + [Fact] + public async Task ClearConflictingTransactionsResourceCache_Test() + { + var txn = GetNonAcs2Transaction(new ResourceInfo()); + await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent { - var txn = GetNonAcs2Transaction(new ResourceInfo()); - await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent + Transaction = txn + }); + Service.ClearConflictingTransactionsResourceCache(new[] { txn.GetHash() }); + } + + [Fact] + public async Task HandleBlockAcceptedAsync_Test() + { + var txn = GetNonAcs2Transaction(new ResourceInfo()); + await Service.HandleTransactionAcceptedEvent(new TransactionAcceptedEvent + { + Transaction = txn + }); + await Service.HandleBlockAcceptedAsync( + new BlockAcceptedEvent { - Transaction = txn - }); - await Service.HandleBlockAcceptedAsync( - new BlockAcceptedEvent + BlockExecutedSet = new BlockExecutedSet { - BlockExecutedSet = new BlockExecutedSet + Block = new Block { - Block = new Block + Body = new BlockBody { - Body = new BlockBody - { - TransactionIds = {txn.GetHash()} - } + TransactionIds = { txn.GetHash() } } } - }); - } + } + }); + } - private Transaction GetAcs2Transaction(ResourceInfo resourceInfo) + private Transaction GetAcs2Transaction(ResourceInfo resourceInfo) + { + return new Transaction { - return new Transaction() - { - From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), - To = Address.FromBase58(InternalConstants.Acs2), - MethodName = nameof(SmartContractExecution.Parallel.Tests.TestContract.TestContract.GetResourceInfo), - Params = resourceInfo.ToByteString(), - Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) - }; - } + From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), + To = Address.FromBase58(InternalConstants.Acs2), + MethodName = nameof(TestContract.GetResourceInfo), + Params = resourceInfo.ToByteString(), + Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) + }; + } - private Transaction GetNonAcs2Transaction(ResourceInfo resourceInfo) + private Transaction GetNonAcs2Transaction(ResourceInfo resourceInfo) + { + return new Transaction { - return new Transaction() - { - From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), - To = Address.FromBase58(InternalConstants.NonAcs2), - MethodName = nameof(SmartContractExecution.Parallel.Tests.TestContract.TestContract.GetResourceInfo), - Params = resourceInfo.ToByteString(), - Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) - }; - } - - private Transaction GetNonParallelCodeTransaction(ResourceInfo resourceInfo) + From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), + To = Address.FromBase58(InternalConstants.NonAcs2), + MethodName = nameof(TestContract.GetResourceInfo), + Params = resourceInfo.ToByteString(), + Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) + }; + } + + private Transaction GetNonParallelCodeTransaction(ResourceInfo resourceInfo) + { + return new Transaction { - return new Transaction - { - From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), - To = Address.FromBase58(InternalConstants.NonParallel), - MethodName = nameof(SmartContractExecution.Parallel.Tests.TestContract.TestContract.GetResourceInfo), - Params = resourceInfo.ToByteString(), - Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) - }; - } + From = Address.FromBase58("9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq"), + To = Address.FromBase58(InternalConstants.NonParallel), + MethodName = nameof(TestContract.GetResourceInfo), + Params = resourceInfo.ToByteString(), + Signature = ByteString.CopyFromUtf8(KernelConstants.SignaturePlaceholder) + }; + } - private ScopedStatePath GetPath(int value) + private ScopedStatePath GetPath(int value) + { + return new ScopedStatePath { - return new ScopedStatePath + Path = new StatePath { - Path = new StatePath - { - Parts = {value.ToString()} - } - }; - } + Parts = { value.ToString() } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestAElfModule.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestAElfModule.cs index a89e52e101..756a10961d 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestAElfModule.cs @@ -1,13 +1,11 @@ using AElf.Runtime.CSharp; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +[DependsOn(typeof(ParallelExecutionModule), + typeof(KernelCoreTestAElfModule), + typeof(CSharpRuntimeAElfModule))] +public class SmartContractParallelTestAElfModule { - [DependsOn(typeof(ParallelExecutionModule), - typeof(KernelCoreTestAElfModule), - typeof(CSharpRuntimeAElfModule))] - public class SmartContractParallelTestAElfModule - { - - } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestModule.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestModule.cs index 4d2e8a85ae..d8345def17 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestModule.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/SmartContractParallelTestModule.cs @@ -5,6 +5,7 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Kernel.SmartContract.Parallel.Domain; +using AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract; using AElf.Modularity; using AElf.OS; using AElf.Runtime.CSharp; @@ -14,135 +15,135 @@ using Moq; using Volo.Abp.Modularity; using Volo.Abp.Threading; +using CleanBlockExecutedDataChangeHeightEventHandler = + AElf.Kernel.SmartContract.Parallel.Application.CleanBlockExecutedDataChangeHeightEventHandler; using ServiceDescriptor = Google.Protobuf.Reflection.ServiceDescriptor; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class ParallelMockTestModule : AElfModule { - public class ParallelMockTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - services.AddTransient(); - var executiveService = GetSmartContractExecutiveService( - (InternalConstants.NonAcs2, GetNonAcs2Executive()), - (InternalConstants.Acs2, GetAcs2Executive()),(InternalConstants.NonParallel,GetNonParallelExecutive()) - ); - services.AddSingleton(executiveService); - context.Services.AddSingleton( - _ => + var services = context.Services; + services.AddSingleton(); + services.AddTransient(); + var executiveService = GetSmartContractExecutiveService( + (InternalConstants.NonAcs2, GetNonAcs2Executive()), + (InternalConstants.Acs2, GetAcs2Executive()), (InternalConstants.NonParallel, GetNonParallelExecutive()) + ); + services.AddSingleton(executiveService); + context.Services.AddSingleton( + _ => + { + var mock = new Mock(); + mock.Setup(s => s.GetChainAsync()).Returns(Task.FromResult(new Chain { - var mock = new Mock(); - mock.Setup(s => s.GetChainAsync()).Returns(Task.FromResult(new Chain() + BestChainHash = Hash.Empty + })); + return mock.Object; + }); + context.Services.AddSingleton( + _ => + { + var mock = new Mock(); + mock.Setup(s => + s.GetNonparallelContractCodeAsync(It.IsAny(), + It.Is
(address => address == Address.FromBase58(InternalConstants.NonParallel)))) + .Returns(Task.FromResult(new NonparallelContractCode { - BestChainHash = Hash.Empty + CodeHash = GetNonParallelExecutive().ContractHash })); - return mock.Object; - }); - context.Services.AddSingleton( - _ => - { - var mock = new Mock(); - mock.Setup(s => - s.GetNonparallelContractCodeAsync(It.IsAny(), It.Is
(address => address == Address.FromBase58(InternalConstants.NonParallel)))) - .Returns(Task.FromResult(new NonparallelContractCode - { - CodeHash = GetNonParallelExecutive().ContractHash - })); - mock.Setup(s => - s.GetNonparallelContractCodeAsync(It.IsAny(), It.Is
(address => address != Address.FromBase58(InternalConstants.NonParallel)))) - .Returns(Task.FromResult((NonparallelContractCode) null)); - return mock.Object; - }); + mock.Setup(s => + s.GetNonparallelContractCodeAsync(It.IsAny(), + It.Is
(address => address != Address.FromBase58(InternalConstants.NonParallel)))) + .Returns(Task.FromResult((NonparallelContractCode)null)); + return mock.Object; + }); - context.Services.AddTransient(); - } + context.Services.AddTransient(); + } - #region Mocks + #region Mocks - #region NonAcs2 + #region NonAcs2 - private static IExecutive GetNonAcs2Executive() - { - var emptyServiceDescriptors = new ServiceDescriptor[0]; - var executive = new Mock(); - executive.SetupGet(e => e.Descriptors).Returns(emptyServiceDescriptors); - return executive.Object; - } + private static IExecutive GetNonAcs2Executive() + { + var emptyServiceDescriptors = new ServiceDescriptor[0]; + var executive = new Mock(); + executive.SetupGet(e => e.Descriptors).Returns(emptyServiceDescriptors); + return executive.Object; + } - #endregion + #endregion - #region Acs2 + #region Acs2 - private static IExecutive GetAcs2Executive() + private static IExecutive GetAcs2Executive() + { + var testContractFile = typeof(TestContract).Assembly + .Location; + var code = File.ReadAllBytes(testContractFile); + var runner = new CSharpSmartContractRunner( + Path.GetDirectoryName(testContractFile) + ); + var executive = AsyncHelper.RunSync(() => runner.RunAsync(new SmartContractRegistration { - var testContractFile = typeof(SmartContractExecution.Parallel.Tests.TestContract.TestContract).Assembly - .Location; - var code = File.ReadAllBytes(testContractFile); - var runner = new CSharpSmartContractRunner( - Path.GetDirectoryName(testContractFile) - ); - var executive = AsyncHelper.RunSync(() => runner.RunAsync(new SmartContractRegistration() - { - Category = 0, - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - })); - executive.SetHostSmartContractBridgeContext(Mock.Of()); - return executive; - } + Category = 0, + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + })); + executive.SetHostSmartContractBridgeContext(Mock.Of()); + return executive; + } - #endregion - - private static IExecutive GetNonParallelExecutive() - { - var testContractFile = typeof(SmartContractExecution.Parallel.Tests.TestContract.TestContract).Assembly - .Location; - var code = File.ReadAllBytes(testContractFile); - var runner = new CSharpSmartContractRunner( - Path.GetDirectoryName(testContractFile) - ); - var executive = AsyncHelper.RunSync(() => runner.RunAsync(new SmartContractRegistration() - { - Category = 0, - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - })); - executive.SetHostSmartContractBridgeContext(Mock.Of()); - return executive; - } + #endregion - private static ISmartContractExecutiveService GetSmartContractExecutiveService( - params (string, IExecutive)[] named) + private static IExecutive GetNonParallelExecutive() + { + var testContractFile = typeof(TestContract).Assembly + .Location; + var code = File.ReadAllBytes(testContractFile); + var runner = new CSharpSmartContractRunner( + Path.GetDirectoryName(testContractFile) + ); + var executive = AsyncHelper.RunSync(() => runner.RunAsync(new SmartContractRegistration { - var executiveService = new Mock(); - foreach (var tuple in named) - { - executiveService.Setup( - s => s.GetExecutiveAsync(It.IsAny(), - It.Is
(address => address == Address.FromBase58(tuple.Item1))) - ).Returns(Task.FromResult(tuple.Item2)); - } + Category = 0, + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + })); + executive.SetHostSmartContractBridgeContext(Mock.Of()); + return executive; + } - return executiveService.Object; - } + private static ISmartContractExecutiveService GetSmartContractExecutiveService( + params (string, IExecutive)[] named) + { + var executiveService = new Mock(); + foreach (var tuple in named) + executiveService.Setup( + s => s.GetExecutiveAsync(It.IsAny(), + It.Is
(address => address == Address.FromBase58(tuple.Item1))) + ).Returns(Task.FromResult(tuple.Item2)); - #endregion + return executiveService.Object; } - [DependsOn( - typeof(OSCoreWithChainTestAElfModule), - typeof(ParallelExecutionModule) - )] - public class ParallelExecutionTestModule : AElfModule + #endregion +} + +[DependsOn( + typeof(OSCoreWithChainTestAElfModule), + typeof(ParallelExecutionModule) +)] +public class ParallelExecutionTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services - .AddSingleton(); - context.Services.AddSingleton(); - } + context.Services + .AddSingleton(); + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionGrouperTest.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionGrouperTest.cs index 55e8333e78..f889fa76a3 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionGrouperTest.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionGrouperTest.cs @@ -8,206 +8,213 @@ using Microsoft.Extensions.DependencyInjection; using Moq; using Shouldly; -using Volo.Abp.Testing; using Volo.Abp.Modularity; +using Volo.Abp.Testing; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class TransactionGrouperTestModule : AbpModule { - public class TransactionGrouperTestModule : AbpModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o => + o.GroupingTimeOut = 200; + o.MaxTransactions = 10; + }); + context.Services.AddSingleton(); + context.Services.AddSingleton( + _ => { - o.GroupingTimeOut = 200; - o.MaxTransactions = 10; - }); - context.Services.AddSingleton(); - context.Services.AddSingleton( - _ => + var mock = new Mock(); + mock.Setup(s => s.GetChainAsync()).Returns(Task.FromResult(new Chain { - var mock = new Mock(); - mock.Setup(s => s.GetChainAsync()).Returns(Task.FromResult(new Chain() - { - BestChainHash = Hash.Empty - })); - return mock.Object; - }); - context.Services.AddSingleton(); - } + BestChainHash = Hash.Empty + })); + return mock.Object; + }); + context.Services.AddSingleton(); } +} - public class TransactionGrouperTest : AbpIntegratedTest +public class TransactionGrouperTest : AbpIntegratedTest +{ + private ITransactionGrouper Grouper => Application.ServiceProvider.GetRequiredService(); + + [Fact] + public async Task Group_Test() { - private ITransactionGrouper Grouper => Application.ServiceProvider.GetRequiredService(); + var group1Resources = new[] { (0, 1), (2, 1), (2, 4), (3, 2), (4, 5) }; + var group1 = + group1Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2) }) + .ToList(); + var group2Resources = new[] { (6, 7), (8, 7) }; + var group2 = + group2Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g2", r.Item1, r.Item2) }) + .ToList(); + var group3Resources = new[] { (9, 10), (10, 11) }; + var group3 = + group3Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g3", r.Item1, r.Item2) }) + .ToList(); + var groups = new[] { group1, group2, group3 }; + var txLookup = groups.SelectMany(x => x).ToDictionary(x => x.Transaction.Params, x => x.Resource); + var allTxns = groups.SelectMany(x => x).Select(x => x.Transaction).OrderBy(x => Guid.NewGuid()).ToList(); - [Fact] - public async Task Group_Test() + var chainContext = new ChainContext { - var group1Resources = new[] {(0, 1), (2, 1), (2, 4), (3, 2), (4, 5)}; - var group1 = - group1Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2)}) - .ToList(); - var group2Resources = new[] {(6, 7), (8, 7)}; - var group2 = - group2Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g2", r.Item1, r.Item2)}) - .ToList(); - var group3Resources = new[] {(9, 10), (10, 11)}; - var group3 = - group3Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g3", r.Item1, r.Item2)}) - .ToList(); - var groups = new[] {group1, group2, group3}; - var txLookup = groups.SelectMany(x => x).ToDictionary(x => x.Transaction.Params, x => x.Resource); - var allTxns = groups.SelectMany(x => x).Select(x => x.Transaction).OrderBy(x => Guid.NewGuid()).ToList(); - - var chainContext = new ChainContext - { - BlockHeight = 10, - BlockHash = HashHelper.ComputeFrom("blockHash") - }; - var grouped = await Grouper.GroupAsync(chainContext, allTxns); - var groupedResources = grouped.Parallelizables.Select(g => g.Select(t => txLookup[t.Params]).ToList()).ToList(); - var expected = groups.Select(g => g.Select(x => x.Resource).ToList()).Select(StringRepresentation) - .OrderBy(x => x); - var actual = groupedResources.Select(StringRepresentation).OrderBy(x => x); - Assert.Equal(expected, actual); - } - - [Fact] - public async Task Group_With_OverMaxTransactions_Test() + BlockHeight = 10, + BlockHash = HashHelper.ComputeFrom("blockHash") + }; + var grouped = await Grouper.GroupAsync(chainContext, allTxns); + var groupedResources = grouped.Parallelizables.Select(g => g.Select(t => txLookup[t.Params]).ToList()).ToList(); + var expected = groups.Select(g => g.Select(x => x.Resource).ToList()).Select(StringRepresentation) + .OrderBy(x => x); + var actual = groupedResources.Select(StringRepresentation).OrderBy(x => x); + Assert.Equal(expected, actual); + } + + [Fact] + public async Task Group_With_OverMaxTransactions_Test() + { + var group1Resources = new[] { (0, 1), (2, 1), (2, 4), (3, 2), (4, 5) }; + var group1 = + group1Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2) }) + .ToList(); + var group2Resources = new[] { (6, 7), (8, 7) }; + var group2 = + group2Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g2", r.Item1, r.Item2) }) + .ToList(); + var group3Resources = new[] { (9, 10), (10, 11) }; + var group3 = + group3Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g3", r.Item1, r.Item2) }) + .ToList(); + var group4Resources = new[] { (12, 13), (13, 15) }; + var group4 = + group4Resources.Select(r => new { Resource = r, Transaction = GetTransaction("g4", r.Item1, r.Item2) }) + .ToList(); + + var groups = new[] { group1, group2, group3, group4 }; + var allTxns = groups.SelectMany(x => x).Select(x => x.Transaction).OrderBy(x => Guid.NewGuid()).ToList(); + allTxns.Count.ShouldBeGreaterThan(10); + + var chainContext = new ChainContext { - var group1Resources = new[] {(0, 1), (2, 1), (2, 4), (3, 2), (4, 5)}; - var group1 = - group1Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2)}) - .ToList(); - var group2Resources = new[] {(6, 7), (8, 7)}; - var group2 = - group2Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g2", r.Item1, r.Item2)}) - .ToList(); - var group3Resources = new[] {(9, 10), (10, 11)}; - var group3 = - group3Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g3", r.Item1, r.Item2)}) - .ToList(); - var group4Resources = new[] {(12, 13), (13, 15)}; - var group4 = - group4Resources.Select(r => new {Resource = r, Transaction = GetTransaction("g4", r.Item1, r.Item2)}) - .ToList(); - - var groups = new[] {group1, group2, group3, group4}; - var allTxns = groups.SelectMany(x => x).Select(x => x.Transaction).OrderBy(x => Guid.NewGuid()).ToList(); - allTxns.Count.ShouldBeGreaterThan(10); - - var chainContext = new ChainContext - { - BlockHeight = 10, - BlockHash = HashHelper.ComputeFrom("blockHash") - }; - var grouped = await Grouper.GroupAsync(chainContext, allTxns); - - grouped.Parallelizables.Count.ShouldBeGreaterThanOrEqualTo(4); - grouped.NonParallelizables.Count.ShouldBe(1); - } - - [Fact] - public async Task Group_With_InvalidContractAddress_Test() + BlockHeight = 10, + BlockHash = HashHelper.ComputeFrom("blockHash") + }; + var grouped = await Grouper.GroupAsync(chainContext, allTxns); + + grouped.Parallelizables.Count.ShouldBeGreaterThanOrEqualTo(4); + grouped.NonParallelizables.Count.ShouldBe(1); + } + + [Fact] + public async Task Group_With_InvalidContractAddress_Test() + { + var groupResources = new[] { (0, 1) }; + var group = + groupResources.Select(r => new + { + Resource = r, + Transaction = GetTransaction("g1", r.Item1, r.Item2, ParallelType.InvalidContractAddress) + }) + .ToList(); + var chainContext = new ChainContext { - var groupResources = new[] {(0, 1)}; - var group = - groupResources.Select(r => new {Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2,ParallelType.InvalidContractAddress)}) - .ToList(); - var chainContext = new ChainContext - { - BlockHeight = 10, - BlockHash = HashHelper.ComputeFrom("blockHash") - }; - var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); - - grouped.TransactionsWithoutContract.Count.ShouldBe(1); - grouped.Parallelizables.Count.ShouldBe(0); - grouped.NonParallelizables.Count.ShouldBe(0); - } - - [Fact] - public async Task Group_With_NonParallelizable_Test() + BlockHeight = 10, + BlockHash = HashHelper.ComputeFrom("blockHash") + }; + var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); + + grouped.TransactionsWithoutContract.Count.ShouldBe(1); + grouped.Parallelizables.Count.ShouldBe(0); + grouped.NonParallelizables.Count.ShouldBe(0); + } + + [Fact] + public async Task Group_With_NonParallelizable_Test() + { + var groupResources = new[] { (0, 1) }; + var group = + groupResources.Select(r => new + { + Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2, ParallelType.NonParallelizable) + }) + .ToList(); + var chainContext = new ChainContext { - var groupResources = new[] {(0, 1)}; - var group = - groupResources.Select(r => new {Resource = r, Transaction = GetTransaction("g1", r.Item1, r.Item2,ParallelType.NonParallelizable)}) - .ToList(); - var chainContext = new ChainContext - { - BlockHeight = 10, - BlockHash = HashHelper.ComputeFrom("blockHash") - }; - var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); - - grouped.NonParallelizables.Count.ShouldBe(1); - grouped.TransactionsWithoutContract.Count.ShouldBe(0); - grouped.Parallelizables.Count.ShouldBe(0); - } - - [Fact] - public async Task Group_Without_Paths_Test() + BlockHeight = 10, + BlockHash = HashHelper.ComputeFrom("blockHash") + }; + var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); + + grouped.NonParallelizables.Count.ShouldBe(1); + grouped.TransactionsWithoutContract.Count.ShouldBe(0); + grouped.Parallelizables.Count.ShouldBe(0); + } + + [Fact] + public async Task Group_Without_Paths_Test() + { + var groupResources = new[] { (0, 1) }; + var group = + groupResources.Select(r => new + { Resource = r, Transaction = GetTransactionWithoutPaths("g1", r.Item1, r.Item2) }) + .ToList(); + var chainContext = new ChainContext { - var groupResources = new[] {(0, 1)}; - var group = - groupResources.Select(r => new {Resource = r, Transaction = GetTransactionWithoutPaths("g1", r.Item1, r.Item2)}) - .ToList(); - var chainContext = new ChainContext - { - BlockHeight = 10, - BlockHash = HashHelper.ComputeFrom("blockHash") - }; - var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); + BlockHeight = 10, + BlockHash = HashHelper.ComputeFrom("blockHash") + }; + var grouped = await Grouper.GroupAsync(chainContext, group.Select(g => g.Transaction).ToList()); - grouped.NonParallelizables.Count.ShouldBe(1); - grouped.TransactionsWithoutContract.Count.ShouldBe(0); - grouped.Parallelizables.Count.ShouldBe(0); - } + grouped.NonParallelizables.Count.ShouldBe(1); + grouped.TransactionsWithoutContract.Count.ShouldBe(0); + grouped.Parallelizables.Count.ShouldBe(0); + } - private Transaction GetTransaction(string methodName, int from, int to, ParallelType parallelType = ParallelType.Parallelizable) + private Transaction GetTransaction(string methodName, int from, int to, + ParallelType parallelType = ParallelType.Parallelizable) + { + var tx = new Transaction { - var tx = new Transaction + MethodName = methodName, + Params = new TransactionResourceInfo { - MethodName = methodName, - Params = new TransactionResourceInfo + WritePaths = { - WritePaths = - { - GetPath(from), GetPath(to) - }, - ParallelType = parallelType - - }.ToByteString() - }; - return tx; - } - - private Transaction GetTransactionWithoutPaths(string methodName, int from, int to) - { - var tx = new Transaction - { - MethodName = methodName, - Params = new TransactionResourceInfo().ToByteString() - }; - return tx; - } + GetPath(from), GetPath(to) + }, + ParallelType = parallelType + }.ToByteString() + }; + return tx; + } - private string StringRepresentation(List<(int, int)> resources) + private Transaction GetTransactionWithoutPaths(string methodName, int from, int to) + { + var tx = new Transaction { - return string.Join(" ", resources.Select(r => r.ToString()).OrderBy(x => x)); - } + MethodName = methodName, + Params = new TransactionResourceInfo().ToByteString() + }; + return tx; + } - private ScopedStatePath GetPath(int value) + private string StringRepresentation(List<(int, int)> resources) + { + return string.Join(" ", resources.Select(r => r.ToString()).OrderBy(x => x)); + } + + private ScopedStatePath GetPath(int value) + { + return new ScopedStatePath { - return new ScopedStatePath + Path = new StatePath { - Path = new StatePath - { - Parts = {value.ToString()} - } - }; - } + Parts = { value.ToString() } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionWithResourceInfoExtensionsTests.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionWithResourceInfoExtensionsTests.cs index e84ce421ab..4571a9c0ed 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionWithResourceInfoExtensionsTests.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/TransactionWithResourceInfoExtensionsTests.cs @@ -1,44 +1,42 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using AElf.Kernel.SmartContract.Parallel.Domain; using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class TransactionWithResourceInfoExtensionsTests { - public class TransactionWithResourceInfoExtensionsTests + [Fact] + public void TransactionWithResourceInfoExtensionsTest() { - [Fact] - public void TransactionWithResourceInfoExtensionsTest() + var transactionWithResourceInfos = new List { - var transactionWithResourceInfos = new List() + new() { - new TransactionWithResourceInfo + TransactionResourceInfo = new TransactionResourceInfo { - TransactionResourceInfo = new TransactionResourceInfo - { - ReadPaths = {new[] {1, 2, 3}.Select(GetPath)}, - WritePaths = {new[] {2, 3, 4}.Select(GetPath)} - } + ReadPaths = { new[] { 1, 2, 3 }.Select(GetPath) }, + WritePaths = { new[] { 2, 3, 4 }.Select(GetPath) } } - }; - var readOnlyPaths = transactionWithResourceInfos.GetReadOnlyPaths(); - readOnlyPaths.Count.ShouldBe(1); - readOnlyPaths.First().ShouldBe(GetPath(1)); - } - - private ScopedStatePath GetPath(int value) + } + }; + var readOnlyPaths = transactionWithResourceInfos.GetReadOnlyPaths(); + readOnlyPaths.Count.ShouldBe(1); + readOnlyPaths.First().ShouldBe(GetPath(1)); + } + + private ScopedStatePath GetPath(int value) + { + return new ScopedStatePath { - return new ScopedStatePath + Address = SampleAddress.AddressList[0], + Path = new StatePath { - Address = SampleAddress.AddressList[0], - Path = new StatePath - { - Parts = {value.ToString()} - } - }; - } + Parts = { value.ToString() } + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Parallel.Tests/UnionFindNodeTest.cs b/test/AElf.Kernel.SmartContract.Parallel.Tests/UnionFindNodeTest.cs index cda30c9be2..e1af6592c1 100644 --- a/test/AElf.Kernel.SmartContract.Parallel.Tests/UnionFindNodeTest.cs +++ b/test/AElf.Kernel.SmartContract.Parallel.Tests/UnionFindNodeTest.cs @@ -1,48 +1,47 @@ using System; using Xunit; -namespace AElf.Kernel.SmartContract.Parallel.Tests +namespace AElf.Kernel.SmartContract.Parallel.Tests; + +public class UnionFindNodeTest { - public class UnionFindNodeTest + [Fact] + public void Trivial_Test() + { + var n1 = new UnionFindNode(); + var n2 = new UnionFindNode(); + + Assert.True(n1.IsUnionedWith(n1)); + Assert.False(n1.IsUnionedWith(n2)); + + Assert.Throws(() => n1.Union(null)); + Assert.Throws(() => n1.IsUnionedWith(null)); + } + + [Fact] + public void Union_Test() { - [Fact] - public void Trivial_Test() - { - var n1 = new UnionFindNode(); - var n2 = new UnionFindNode(); - - Assert.True(n1.IsUnionedWith(n1)); - Assert.False(n1.IsUnionedWith(n2)); - - Assert.Throws(() => n1.Union(null)); - Assert.Throws(() => n1.IsUnionedWith(null)); - } - - [Fact] - public void Union_Test() - { - var n1 = new UnionFindNode(); - var n2 = new UnionFindNode(); - var n3 = new UnionFindNode(); - var n4 = new UnionFindNode(); - var n5 = new UnionFindNode(); - - Assert.True(n1.Union(n2)); - Assert.True(n2.Union(n3)); - Assert.False(n3.Union(n1)); - - Assert.True(n4.Union(n5)); - Assert.False(n5.Union(n4)); - - Assert.True(n1.IsUnionedWith(n1)); - Assert.True(n2.IsUnionedWith(n2)); - Assert.True(n1.IsUnionedWith(n2)); - Assert.True(n1.IsUnionedWith(n3)); - - Assert.False(n4.IsUnionedWith(n1)); - Assert.False(n5.IsUnionedWith(n2)); - - Assert.True(n4.IsUnionedWith(n5)); - } + var n1 = new UnionFindNode(); + var n2 = new UnionFindNode(); + var n3 = new UnionFindNode(); + var n4 = new UnionFindNode(); + var n5 = new UnionFindNode(); + + Assert.True(n1.Union(n2)); + Assert.True(n2.Union(n3)); + Assert.False(n3.Union(n1)); + + Assert.True(n4.Union(n5)); + Assert.False(n5.Union(n4)); + + Assert.True(n1.IsUnionedWith(n1)); + Assert.True(n2.IsUnionedWith(n2)); + Assert.True(n1.IsUnionedWith(n2)); + Assert.True(n1.IsUnionedWith(n3)); + + Assert.False(n4.IsUnionedWith(n1)); + Assert.False(n5.IsUnionedWith(n2)); + + Assert.True(n4.IsUnionedWith(n5)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Shared.Tests/AElf.Kernel.SmartContract.Shared.Tests.csproj b/test/AElf.Kernel.SmartContract.Shared.Tests/AElf.Kernel.SmartContract.Shared.Tests.csproj index bc137cb9c2..7bf21aaa68 100644 --- a/test/AElf.Kernel.SmartContract.Shared.Tests/AElf.Kernel.SmartContract.Shared.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.Shared.Tests/AElf.Kernel.SmartContract.Shared.Tests.csproj @@ -6,15 +6,15 @@ - + - - - - - + + + + + diff --git a/test/AElf.Kernel.SmartContract.Shared.Tests/ContextVariableDictionaryTests.cs b/test/AElf.Kernel.SmartContract.Shared.Tests/ContextVariableDictionaryTests.cs index be43ab9a2e..10c84abc4f 100644 --- a/test/AElf.Kernel.SmartContract.Shared.Tests/ContextVariableDictionaryTests.cs +++ b/test/AElf.Kernel.SmartContract.Shared.Tests/ContextVariableDictionaryTests.cs @@ -1,82 +1,74 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Shared.Tests +namespace AElf.Kernel.SmartContract.Shared.Tests; + +public class ContextVariableDictionaryTests { - public class ContextVariableDictionaryTests + [Fact] + public void GetStringArray_Test() { - [Fact] - public void GetStringArray_Test() - { - var dictionary= new Dictionary() - { - {"key1","Value1"}, - {"key2","Value2"}, - {"key3","Value3"}, - {"key4","Value4"}, - } - ; - var contextVariableDictionary = new ContextVariableDictionary(dictionary); - var result=contextVariableDictionary.GetStringArray("key1"); - //not in property yet - foreach (var r in result) - { - r.ShouldBe("Value1"); - } - // already in property - var result1=contextVariableDictionary.GetStringArray("key1"); - foreach (var r in result1) - { - r.ShouldBe("Value1"); - } - var result2 = contextVariableDictionary.GetStringArray("key5"); - result2.ShouldBeEmpty(); - } + var dictionary = new Dictionary + { + { "key1", "Value1" }, + { "key2", "Value2" }, + { "key3", "Value3" }, + { "key4", "Value4" } + } + ; + var contextVariableDictionary = new ContextVariableDictionary(dictionary); + var result = contextVariableDictionary.GetStringArray("key1"); + //not in property yet + foreach (var r in result) r.ShouldBe("Value1"); + // already in property + var result1 = contextVariableDictionary.GetStringArray("key1"); + foreach (var r in result1) r.ShouldBe("Value1"); + var result2 = contextVariableDictionary.GetStringArray("key5"); + result2.ShouldBeEmpty(); + } - [Fact] - public void ContractCallException_Test() - { - Should.Throw(() => createException()); - Should.Throw(() => createExceptionWithMessage("ContractCallException")); - Should.Throw(() => createExceptionWithMessageAndError("ContractCallException")); + [Fact] + public void ContractCallException_Test() + { + Should.Throw(() => createException()); + Should.Throw(() => createExceptionWithMessage("ContractCallException")); + Should.Throw(() => createExceptionWithMessageAndError("ContractCallException")); - Should.Throw(() => createException()); - Should.Throw(() => createExceptionWithMessage("NoPermissionException")); - Should.Throw(() => createExceptionWithMessageAndError("NoPermissionException")); - - Should.Throw(() => createException()); - Should.Throw(() => createExceptionWithMessage("StateOverSizeException")); - Should.Throw(() => createExceptionWithMessageAndError("StateOverSizeException")); + Should.Throw(() => createException()); + Should.Throw(() => createExceptionWithMessage("NoPermissionException")); + Should.Throw(() => createExceptionWithMessageAndError("NoPermissionException")); - } - private void createException() where T:SmartContractBridgeException,new() - { - T t = System.Activator.CreateInstance(); - throw t; - } - private void createExceptionWithMessage(string type) + Should.Throw(() => createException()); + Should.Throw(() => createExceptionWithMessage("StateOverSizeException")); + Should.Throw(() => createExceptionWithMessageAndError("StateOverSizeException")); + } + + private void createException() where T : SmartContractBridgeException, new() + { + var t = Activator.CreateInstance(); + throw t; + } + + private void createExceptionWithMessage(string type) + { + switch (type) { - switch (type) - { - case "ContractCallException":throw new ContractCallException(type); - case "NoPermissionException":throw new NoPermissionException(type); - case "StateOverSizeException":throw new StateOverSizeException(type); - } + case "ContractCallException": throw new ContractCallException(type); + case "NoPermissionException": throw new NoPermissionException(type); + case "StateOverSizeException": throw new StateOverSizeException(type); } - private void createExceptionWithMessageAndError(string type) + } + + private void createExceptionWithMessageAndError(string type) + { + var error = new Exception(); + switch (type) { - var error= new Exception(); - switch (type) - { - case "ContractCallException":throw new ContractCallException(type,error); - case "NoPermissionException":throw new NoPermissionException(type,error); - case "StateOverSizeException":throw new StateOverSizeException(type,error); - } + case "ContractCallException": throw new ContractCallException(type, error); + case "NoPermissionException": throw new NoPermissionException(type, error); + case "StateOverSizeException": throw new StateOverSizeException(type, error); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/AElf.Kernel.SmartContract.Tests.csproj b/test/AElf.Kernel.SmartContract.Tests/AElf.Kernel.SmartContract.Tests.csproj index 66efd88ad1..8baf42e73c 100644 --- a/test/AElf.Kernel.SmartContract.Tests/AElf.Kernel.SmartContract.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.Tests/AElf.Kernel.SmartContract.Tests.csproj @@ -5,11 +5,11 @@ false - - - - - + + + + + @@ -24,11 +24,11 @@ - - - - - - + + + + + + diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/ExecutionObserverThresholdProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/ExecutionObserverThresholdProviderTests.cs index 05712c6048..c02b49e817 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/ExecutionObserverThresholdProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/ExecutionObserverThresholdProviderTests.cs @@ -4,114 +4,113 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class ExecutionObserverThresholdProviderTests : AElfIntegratedTest { - public class ExecutionObserverThresholdProviderTests : AElfIntegratedTest + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; + + public ExecutionObserverThresholdProviderTests() { - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IExecutionObserverThresholdProvider _executionObserverThresholdProvider; + _blockStateSetManger = GetRequiredService(); + _executionObserverThresholdProvider = GetRequiredService(); + } - public ExecutionObserverThresholdProviderTests() + [Fact] + public async Task ExecutionObserverThresholdProvider_GetAndSet_Test() + { + var blockIndex = new BlockIndex { - _blockStateSetManger = GetRequiredService(); - _executionObserverThresholdProvider = GetRequiredService(); + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 1 + }; + + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + + { + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex); + executionObserverThreshold.ExecutionBranchThreshold.ShouldBe(SmartContractConstants + .ExecutionBranchThreshold); + executionObserverThreshold.ExecutionCallThreshold.ShouldBe( + SmartContractConstants.ExecutionCallThreshold); } - [Fact] - public async Task ExecutionObserverThresholdProvider_GetAndSet_Test() + var newExecutionObserverThreshold = new ExecutionObserverThreshold { - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 1 - }; + ExecutionBranchThreshold = 1, + ExecutionCallThreshold = 1 + }; - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); + { + await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex, + newExecutionObserverThreshold); + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex); + executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); + } + var blockIndex2 = new BlockIndex + { + BlockHash = HashHelper.ComputeFrom("BlockHash1"), + BlockHeight = blockIndex.BlockHeight + 1 + }; + + var blockStateSet2 = new BlockStateSet + { + PreviousHash = blockIndex.BlockHash, + BlockHash = blockIndex2.BlockHash, + BlockHeight = blockIndex2.BlockHeight + 1 + }; + + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet2); + + { + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); + executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); + } + + { + var invalidThreshold = new ExecutionObserverThreshold { - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex); - executionObserverThreshold.ExecutionBranchThreshold.ShouldBe(SmartContractConstants - .ExecutionBranchThreshold); - executionObserverThreshold.ExecutionCallThreshold.ShouldBe( - SmartContractConstants.ExecutionCallThreshold); - } - - var newExecutionObserverThreshold = new ExecutionObserverThreshold - { - ExecutionBranchThreshold = 1, - ExecutionCallThreshold = 1 + ExecutionBranchThreshold = 1 }; - - { - await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex, - newExecutionObserverThreshold); - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex); - executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); - } + await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, + invalidThreshold); + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); + executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); + } - var blockIndex2 = new BlockIndex + { + var invalidThreshold = new ExecutionObserverThreshold { - BlockHash = HashHelper.ComputeFrom("BlockHash1"), - BlockHeight = blockIndex.BlockHeight + 1 + ExecutionCallThreshold = 1 }; - - var blockStateSet2 = new BlockStateSet + await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, + invalidThreshold); + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); + executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); + } + + { + var validThreshold = new ExecutionObserverThreshold { - PreviousHash = blockIndex.BlockHash, - BlockHash = blockIndex2.BlockHash, - BlockHeight = blockIndex2.BlockHeight + 1 + ExecutionCallThreshold = 2, + ExecutionBranchThreshold = 2 }; - - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet2); - - { - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); - executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); - } - - { - var invalidThreshold = new ExecutionObserverThreshold - { - ExecutionBranchThreshold = 1 - }; - await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, - invalidThreshold); - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); - executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); - } - - { - var invalidThreshold = new ExecutionObserverThreshold - { - ExecutionCallThreshold = 1 - }; - await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, - invalidThreshold); - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); - executionObserverThreshold.ShouldBe(newExecutionObserverThreshold); - } - - { - var validThreshold = new ExecutionObserverThreshold - { - ExecutionCallThreshold = 2, - ExecutionBranchThreshold = 2 - }; - await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, - validThreshold); - var executionObserverThreshold = - _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); - executionObserverThreshold.ShouldBe(validThreshold); - } + await _executionObserverThresholdProvider.SetExecutionObserverThresholdAsync(blockIndex2, + validThreshold); + var executionObserverThreshold = + _executionObserverThresholdProvider.GetExecutionObserverThreshold(blockIndex2); + executionObserverThreshold.ShouldBe(validThreshold); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/LogEventProcessingServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/LogEventProcessingServiceTests.cs index f0f7fbd613..f49feada4c 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/LogEventProcessingServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/LogEventProcessingServiceTests.cs @@ -1,193 +1,186 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain; -using AElf.Kernel.Blockchain.Domain; using AElf.Types; using Google.Protobuf; -using Google.Protobuf.Collections; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class LogEventProcessingServiceTests : LogEventTestBase { - public class LogEventProcessingServiceTests : LogEventTestBase + private readonly KernelTestHelper _kernelTestHelper; + private readonly ILogEventProcessingService _logEventProcessingService; + private readonly ITestLogEventProcessor _testLogEventProcessor; + + public LogEventProcessingServiceTests() { - private readonly ILogEventProcessingService _logEventProcessingService; - private readonly ITestLogEventProcessor _testLogEventProcessor; - private readonly KernelTestHelper _kernelTestHelper; + _logEventProcessingService = GetRequiredService>(); + _testLogEventProcessor = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public LogEventProcessingServiceTests() + [Fact] + public async Task Process_Test() + { + var interestedLogEvent = new LogEvent { - _logEventProcessingService = GetRequiredService>(); - _testLogEventProcessor = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + Name = "TestLogEvent", + Address = SampleAddress.AddressList[0] + }; - [Fact] - public async Task Process_Test() + var notInterestedLogEvent = new LogEvent { - var interestedLogEvent = new LogEvent - { - Name = "TestLogEvent", - Address = SampleAddress.AddressList[0] - }; + Name = "TestLogEvent2", + Address = SampleAddress.AddressList[0] + }; - var notInterestedLogEvent = new LogEvent - { - Name = "TestLogEvent2", - Address = SampleAddress.AddressList[0] - }; - - var notInterestedLogEvent2 = new LogEvent - { - Name = "TestLogEvent", - Address = SampleAddress.AddressList[1] - }; + var notInterestedLogEvent2 = new LogEvent + { + Name = "TestLogEvent", + Address = SampleAddress.AddressList[1] + }; - var blockExecutedSetList = new List(); + var blockExecutedSetList = new List(); + { + blockExecutedSetList.Add(new BlockExecutedSet { - blockExecutedSetList.Add(new BlockExecutedSet - { - Block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")), - TransactionResultMap = new Dictionary() - }); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(0); - } + Block = _kernelTestHelper.GenerateBlock(9, HashHelper.ComputeFrom("PreviousBlockHash")), + TransactionResultMap = new Dictionary() + }); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - { - blockExecutedSetList.Add(GenerateBlockExecutedSet(10, new List())); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(0); + } - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(0); - } + { + blockExecutedSetList.Add(GenerateBlockExecutedSet(10, new List())); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - { - blockExecutedSetList.Add(GenerateBlockExecutedSet(11, new List - { - notInterestedLogEvent - })); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(0); - } + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(0); + } + { + blockExecutedSetList.Add(GenerateBlockExecutedSet(11, new List { - blockExecutedSetList.Add(GenerateBlockExecutedSet(12, new List - { - notInterestedLogEvent, - notInterestedLogEvent2 - })); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(0); - } + notInterestedLogEvent + })); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); + + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(0); + } - var blockExecutedSet13 = GenerateBlockExecutedSet(13, new List + { + blockExecutedSetList.Add(GenerateBlockExecutedSet(12, new List { notInterestedLogEvent, - notInterestedLogEvent2, - interestedLogEvent - }); - { - blockExecutedSetList.Add(blockExecutedSet13); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(1); - result[13].Values.Count.ShouldBe(1); - result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]].Count - .ShouldBe(1); - result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]][0] - .ShouldBe(interestedLogEvent); - - _testLogEventProcessor.CleanProcessedResult(); - } + notInterestedLogEvent2 + })); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - var blockExecutedSet14 = GenerateBlockExecutedSet(14, new List - { - interestedLogEvent, - interestedLogEvent - }); - { - blockExecutedSetList.Add(blockExecutedSet14); - await _logEventProcessingService.ProcessAsync(blockExecutedSetList); - - var result = _testLogEventProcessor.GetProcessedResult(); - result.Count.ShouldBe(2); - result[13].Values.Count.ShouldBe(1); - result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]].Count - .ShouldBe(1); - result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]][0] - .ShouldBe(interestedLogEvent); - - result[14].Values.Count.ShouldBe(2); - result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[1]]].Count - .ShouldBe(1); - result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[1]]][0] - .ShouldBe(interestedLogEvent); - - result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]].Count - .ShouldBe(2); - result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]][0] - .ShouldBe(interestedLogEvent); - result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]][1] - .ShouldBe(interestedLogEvent); - - _testLogEventProcessor.CleanProcessedResult(); - } + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(0); + } + + var blockExecutedSet13 = GenerateBlockExecutedSet(13, new List + { + notInterestedLogEvent, + notInterestedLogEvent2, + interestedLogEvent + }); + { + blockExecutedSetList.Add(blockExecutedSet13); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); + + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(1); + result[13].Values.Count.ShouldBe(1); + result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]].Count + .ShouldBe(1); + result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]][0] + .ShouldBe(interestedLogEvent); + + _testLogEventProcessor.CleanProcessedResult(); } - private BlockExecutedSet GenerateBlockExecutedSet(long blockHeight, List logEvents) + var blockExecutedSet14 = GenerateBlockExecutedSet(14, new List { - var blockExecutedSet = new BlockExecutedSet(); - var transactions = new List(); + interestedLogEvent, + interestedLogEvent + }); + { + blockExecutedSetList.Add(blockExecutedSet14); + await _logEventProcessingService.ProcessAsync(blockExecutedSetList); + + var result = _testLogEventProcessor.GetProcessedResult(); + result.Count.ShouldBe(2); + result[13].Values.Count.ShouldBe(1); + result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]].Count + .ShouldBe(1); + result[13][blockExecutedSet13.TransactionResultMap[blockExecutedSet13.Block.Body.TransactionIds[3]]][0] + .ShouldBe(interestedLogEvent); + + result[14].Values.Count.ShouldBe(2); + result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[1]]].Count + .ShouldBe(1); + result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[1]]][0] + .ShouldBe(interestedLogEvent); + + result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]].Count + .ShouldBe(2); + result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]][0] + .ShouldBe(interestedLogEvent); + result[14][blockExecutedSet14.TransactionResultMap[blockExecutedSet14.Block.Body.TransactionIds[2]]][1] + .ShouldBe(interestedLogEvent); + + _testLogEventProcessor.CleanProcessedResult(); + } + } - for (var i = 0; i < logEvents.Count + 1; i++) + private BlockExecutedSet GenerateBlockExecutedSet(long blockHeight, List logEvents) + { + var blockExecutedSet = new BlockExecutedSet(); + var transactions = new List(); + + for (var i = 0; i < logEvents.Count + 1; i++) transactions.Add(_kernelTestHelper.GenerateTransaction()); + + var block = _kernelTestHelper.GenerateBlock(blockHeight - 1, HashHelper.ComputeFrom("PreviousBlockHash"), + transactions); + blockExecutedSet.Block = block; + blockExecutedSet.TransactionResultMap = new Dictionary + { { - transactions.Add(_kernelTestHelper.GenerateTransaction()); + transactions[0].GetHash(), + new TransactionResult { TransactionId = transactions[0].GetHash(), Bloom = ByteString.Empty } } + }; - var block = _kernelTestHelper.GenerateBlock(blockHeight - 1, HashHelper.ComputeFrom("PreviousBlockHash"), - transactions); - blockExecutedSet.Block = block; - blockExecutedSet.TransactionResultMap = new Dictionary + var bloom = new Bloom(); + var logs = new List(); + var txIndex = 1; + foreach (var logEvent in logEvents) + { + bloom.Combine(new List { logEvent.GetBloom() }); + logs.Add(logEvent); + + var transactionResult = new TransactionResult { - { - transactions[0].GetHash(), - new TransactionResult {TransactionId = transactions[0].GetHash(), Bloom = ByteString.Empty} - } + TransactionId = transactions[txIndex].GetHash(), + Bloom = ByteString.CopyFrom(bloom.Data) }; + transactionResult.Logs.AddRange(logs); - var bloom = new Bloom(); - var logs = new List(); - var txIndex = 1; - foreach (var logEvent in logEvents) - { - bloom.Combine(new List {logEvent.GetBloom()}); - logs.Add(logEvent); - - var transactionResult = new TransactionResult - { - TransactionId = transactions[txIndex].GetHash(), - Bloom = ByteString.CopyFrom(bloom.Data), - }; - transactionResult.Logs.AddRange(logs); - - blockExecutedSet.TransactionResultMap.Add(transactions[txIndex].GetHash(), transactionResult); - txIndex++; - } + blockExecutedSet.TransactionResultMap.Add(transactions[txIndex].GetHash(), transactionResult); + txIndex++; + } - block.Header.Bloom = ByteString.CopyFrom(bloom.Data); + block.Header.Bloom = ByteString.CopyFrom(bloom.Data); - return blockExecutedSet; - } + return blockExecutedSet; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressProviderTests.cs index 29dc0791a7..b36ad56a73 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressProviderTests.cs @@ -1,56 +1,52 @@ -using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Domain; using AElf.Types; -using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractAddressProviderTests : SmartContractTestBase { - public sealed class SmartContractAddressProviderTests : SmartContractTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ISmartContractAddressProvider _smartContractAddressProvider; + private readonly SmartContractHelper _smartContractHelper; + + public SmartContractAddressProviderTests() { - private readonly ISmartContractAddressProvider _smartContractAddressProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly SmartContractHelper _smartContractHelper; + _smartContractAddressProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + } - public SmartContractAddressProviderTests() - { - _smartContractAddressProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _smartContractHelper = GetRequiredService(); - } - - [Fact] - public async Task SmartContractAddress_Set_And_Get_Test() + [Fact] + public async Task SmartContractAddress_Set_And_Get_Test() + { + var chain = await _smartContractHelper.CreateChainAsync(); + var contractName = Hash.Empty.ToStorageKey(); + + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainAsync(); - var contractName = Hash.Empty.ToStorageKey(); - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - - var smartContractAddress = - await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, contractName); - smartContractAddress.ShouldBeNull(); - - await _smartContractAddressProvider.SetSmartContractAddressAsync(chainContext, contractName, - SampleAddress.AddressList[0]); - - var blockExecutedDataKey = $"BlockExecutedData/SmartContractAddress/{contractName}"; - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); - - smartContractAddress = - await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, contractName); - smartContractAddress.Address.ShouldBe(SampleAddress.AddressList[0]); - smartContractAddress.BlockHeight = chainContext.BlockHeight; - smartContractAddress.BlockHash = chainContext.BlockHash; - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + + var smartContractAddress = + await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, contractName); + smartContractAddress.ShouldBeNull(); + + await _smartContractAddressProvider.SetSmartContractAddressAsync(chainContext, contractName, + SampleAddress.AddressList[0]); + + var blockExecutedDataKey = $"BlockExecutedData/SmartContractAddress/{contractName}"; + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); + + smartContractAddress = + await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, contractName); + smartContractAddress.Address.ShouldBe(SampleAddress.AddressList[0]); + smartContractAddress.BlockHeight = chainContext.BlockHeight; + smartContractAddress.BlockHash = chainContext.BlockHash; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressServiceTests.cs index 52db15ccc5..b48eaafa31 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractAddressServiceTests.cs @@ -1,151 +1,152 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Domain; -using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -using Google.Protobuf; using Microsoft.Extensions.Options; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractAddressServiceTests : SmartContractTestBase { - public sealed class SmartContractAddressServiceTests : SmartContractTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ChainOptions _chainOptions; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly SmartContractHelper _smartContractHelper; + + public SmartContractAddressServiceTests() { - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ChainOptions _chainOptions; - private readonly SmartContractHelper _smartContractHelper; - - public SmartContractAddressServiceTests() - { - _smartContractAddressService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _chainOptions = GetRequiredService>().Value; - _smartContractHelper = GetRequiredService(); - } - - [Fact] - public async Task SmartContractAddress_Set_And_Get_Test() + _smartContractAddressService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _chainOptions = GetRequiredService>().Value; + _smartContractHelper = GetRequiredService(); + } + + [Fact] + public async Task SmartContractAddress_Set_And_Get_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - TestSmartContractAddressNameProvider.StringName); - address.ShouldBeNull(); - var dto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TestSmartContractAddressNameProvider.StringName); + address.ShouldBeNull(); + var dto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, + TestSmartContractAddressNameProvider.StringName); + dto.ShouldBeNull(); + + dto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, + ZeroSmartContractAddressNameProvider.StringName); + dto.SmartContractAddress.Address.ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); + dto.Irreversible.ShouldBeFalse(); + address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + ZeroSmartContractAddressNameProvider.StringName); + address.ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); + + + await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, + TestSmartContractAddressNameProvider.StringName, + SampleAddress.AddressList[0]); + + address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TestSmartContractAddressNameProvider.StringName); + address.ShouldBe(SampleAddress.AddressList[0]); + + var smartContractAddressDto = + await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, TestSmartContractAddressNameProvider.StringName); - dto.ShouldBeNull(); - - dto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, - ZeroSmartContractAddressNameProvider.StringName); - dto.SmartContractAddress.Address.ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); - dto.Irreversible.ShouldBeFalse(); - address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - ZeroSmartContractAddressNameProvider.StringName); - address.ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); - - - await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, TestSmartContractAddressNameProvider.StringName, - SampleAddress.AddressList[0]); - - address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TestSmartContractAddressNameProvider.StringName); - address.ShouldBe(SampleAddress.AddressList[0]); - - var smartContractAddressDto = - await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, TestSmartContractAddressNameProvider.StringName); - smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress - { - Address = SampleAddress.AddressList[0], - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }); - smartContractAddressDto.Irreversible.ShouldBeTrue(); - - var map = await _smartContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); - map.Count.ShouldBe(2); - map[ZeroSmartContractAddressNameProvider.Name].ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); - map[TestSmartContractAddressNameProvider.Name].ShouldBe(SampleAddress.AddressList[0]); - } - - [Fact] - public async Task SmartContractAddress_Get_WithHeightLargeThanLIB_Test() + smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress + { + Address = SampleAddress.AddressList[0], + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }); + smartContractAddressDto.Irreversible.ShouldBeTrue(); + + var map = await _smartContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext); + map.Count.ShouldBe(2); + map[ZeroSmartContractAddressNameProvider.Name] + .ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress()); + map[TestSmartContractAddressNameProvider.Name].ShouldBe(SampleAddress.AddressList[0]); + } + + [Fact] + public async Task SmartContractAddress_Get_WithHeightLargeThanLIB_Test() + { + await _smartContractHelper.CreateChainAsync(); + + var block = await _kernelTestHelper.AttachBlockToBestChain(); + var chainContext = new ChainContext { - await _smartContractHelper.CreateChainAsync(); - - var block = await _kernelTestHelper.AttachBlockToBestChain(); - var chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - var contractName = Hash.Empty.ToStorageKey(); - await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, contractName, - SampleAddress.AddressList[0]); - - var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, contractName); - address.ShouldBe(SampleAddress.AddressList[0]); - - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, contractName); - smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress - { - Address = SampleAddress.AddressList[0], - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - smartContractAddressDto.Irreversible.ShouldBeFalse(); - } - - [Fact] - public async Task SmartContractAddress_Get_WithFork_Test() + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var contractName = Hash.Empty.ToStorageKey(); + await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, contractName, + SampleAddress.AddressList[0]); + + var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, contractName); + address.ShouldBe(SampleAddress.AddressList[0]); + + var smartContractAddressDto = + await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, contractName); + smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress { - var chain = await _smartContractHelper.CreateChainAsync(); - - var block = await _kernelTestHelper.AttachBlockToBestChain(); - await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, - block.GetHash()); - block = _kernelTestHelper.GenerateBlock(block.Header.Height - 1, block.Header.PreviousBlockHash); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - var chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - var contractName = Hash.Empty.ToStorageKey(); - await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, contractName, - SampleAddress.AddressList[0]); - var smartContractAddressDto = await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, contractName); - smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress - { - Address = SampleAddress.AddressList[0], - BlockHash = block.GetHash(), - BlockHeight = block.Height - }); - smartContractAddressDto.Irreversible.ShouldBeFalse(); - } - - [Fact] - public void GetZeroSmartContractAddress_Test() + Address = SampleAddress.AddressList[0], + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); + smartContractAddressDto.Irreversible.ShouldBeFalse(); + } + + [Fact] + public async Task SmartContractAddress_Get_WithFork_Test() + { + var chain = await _smartContractHelper.CreateChainAsync(); + + var block = await _kernelTestHelper.AttachBlockToBestChain(); + await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, + block.GetHash()); + block = _kernelTestHelper.GenerateBlock(block.Header.Height - 1, block.Header.PreviousBlockHash); + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); + var chainContext = new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var contractName = Hash.Empty.ToStorageKey(); + await _smartContractAddressService.SetSmartContractAddressAsync(chainContext, contractName, + SampleAddress.AddressList[0]); + var smartContractAddressDto = + await _smartContractAddressService.GetSmartContractAddressAsync(chainContext, contractName); + smartContractAddressDto.SmartContractAddress.ShouldBe(new SmartContractAddress { - var zeroSmartContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - zeroSmartContractAddress.ShouldBe(_smartContractAddressService.GetZeroSmartContractAddress(_chainOptions.ChainId)); - } + Address = SampleAddress.AddressList[0], + BlockHash = block.GetHash(), + BlockHeight = block.Height + }); + smartContractAddressDto.Irreversible.ShouldBeFalse(); + } + + [Fact] + public void GetZeroSmartContractAddress_Test() + { + var zeroSmartContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); + zeroSmartContractAddress.ShouldBe( + _smartContractAddressService.GetZeroSmartContractAddress(_chainOptions.ChainId)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractBridgeServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractBridgeServiceTests.cs index f2c1b9302b..1356cfcbdb 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractBridgeServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractBridgeServiceTests.cs @@ -9,89 +9,90 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractBridgeServiceTests : SmartContractTestBase { - public sealed class SmartContractBridgeServiceTests : SmartContractTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ChainOptions _chainOptions; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractBridgeService _smartContractBridgeService; + private readonly SmartContractHelper _smartContractHelper; + + public SmartContractBridgeServiceTests() { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractBridgeService _smartContractBridgeService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ChainOptions _chainOptions; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly SmartContractHelper _smartContractHelper; + _blockchainService = GetRequiredService(); + _smartContractBridgeService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _chainOptions = GetRequiredService>().Value; + _blockStateSetManger = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + } - public SmartContractBridgeServiceTests() + [Fact] + public async Task GetBlockTransactions_Test() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) { - _blockchainService = GetRequiredService(); - _smartContractBridgeService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _chainOptions = GetRequiredService>().Value; - _blockStateSetManger = GetRequiredService(); - _smartContractHelper = GetRequiredService(); + var transaction = _kernelTestHelper.GenerateTransaction(); + transactions.Add(transaction); } - [Fact] - public async Task GetBlockTransactions_Test() - { - var transactions = new List(); - for (var i = 0; i < 3; i++) - { - var transaction = _kernelTestHelper.GenerateTransaction(); - transactions.Add(transaction); - } + var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); - var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions); + await _blockchainService.AddBlockAsync(block); + await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockchainService.AddTransactionsAsync(transactions); + var blockTransactions = await _smartContractBridgeService.GetBlockTransactions(block.GetHash()); + blockTransactions.ShouldBe(transactions); + } - var blockTransactions = await _smartContractBridgeService.GetBlockTransactions(block.GetHash()); - blockTransactions.ShouldBe(transactions); - } + [Fact] + public void GetChainId_Test() + { + _smartContractBridgeService.GetChainId().ShouldBe(_chainOptions.ChainId); + } - [Fact] - public void GetChainId_Test() - { - _smartContractBridgeService.GetChainId().ShouldBe(_chainOptions.ChainId); - } + [Fact] + public void GetZeroSmartContractAddress_Test() + { + _smartContractBridgeService.GetZeroSmartContractAddress() + .ShouldBe(_smartContractBridgeService.GetZeroSmartContractAddress(_chainOptions.ChainId)); + } - [Fact] - public void GetZeroSmartContractAddress_Test() - { - _smartContractBridgeService.GetZeroSmartContractAddress() - .ShouldBe(_smartContractBridgeService.GetZeroSmartContractAddress(_chainOptions.ChainId)); - } + [Fact] + public async Task GetStateAsync_Test() + { + var chain = await _smartContractHelper.CreateChainAsync(); - [Fact] - public async Task GetStateAsync_Test() - { - var chain = await _smartContractHelper.CreateChainAsync(); + await Assert.ThrowsAsync(() => _smartContractBridgeService.GetStateAsync( + SampleAddress.AddressList[0], string.Empty, + chain.BestChainHeight, + chain.BestChainHash)); - await Assert.ThrowsAsync(() => _smartContractBridgeService.GetStateAsync( - SampleAddress.AddressList[0], string.Empty, - chain.BestChainHeight, - chain.BestChainHash)); - - - var scopedStatePath = new ScopedStatePath + + var scopedStatePath = new ScopedStatePath + { + Address = SampleAddress.AddressList[0], + Path = new StatePath { - Address = SampleAddress.AddressList[0], - Path = new StatePath - { - Parts = { "part"} - } - }; - var state = await _smartContractBridgeService.GetStateAsync(SampleAddress.AddressList[0], scopedStatePath.ToStateKey(), - chain.BestChainHeight, chain.BestChainHash); - state.ShouldBeNull(); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.Changes[scopedStatePath.ToStateKey()] = ByteString.Empty; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - - state = await _smartContractBridgeService.GetStateAsync(SampleAddress.AddressList[0], scopedStatePath.ToStateKey(), - chain.BestChainHeight, chain.BestChainHash); - state.ShouldBe(ByteString.Empty); - } + Parts = { "part" } + } + }; + var state = await _smartContractBridgeService.GetStateAsync(SampleAddress.AddressList[0], + scopedStatePath.ToStateKey(), + chain.BestChainHeight, chain.BestChainHash); + state.ShouldBeNull(); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.Changes[scopedStatePath.ToStateKey()] = ByteString.Empty; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + + state = await _smartContractBridgeService.GetStateAsync(SampleAddress.AddressList[0], + scopedStatePath.ToStateKey(), + chain.BestChainHeight, chain.BestChainHash); + state.ShouldBe(ByteString.Empty); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveProviderTests.cs index e66daa0f44..4aea47b703 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveProviderTests.cs @@ -1,39 +1,38 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractExecutiveProviderTests : SmartContractTestBase { - public sealed class SmartContractExecutiveProviderTests : SmartContractTestBase + private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; + + public SmartContractExecutiveProviderTests() + { + _smartContractExecutiveProvider = GetRequiredService(); + } + + [Fact] + public void SmartContractExecutiveProvider_Test() { - private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; + var address = SampleAddress.AddressList[0]; + _smartContractExecutiveProvider.TryGetValue(address, out var executives).ShouldBeFalse(); + executives.ShouldBeNull(); + _smartContractExecutiveProvider.TryRemove(address, out executives).ShouldBeFalse(); + executives.ShouldBeNull(); - public SmartContractExecutiveProviderTests() - { - _smartContractExecutiveProvider = GetRequiredService(); - } + var executivePools = _smartContractExecutiveProvider.GetExecutivePools(); + executivePools.Count.ShouldBe(0); + var pool = _smartContractExecutiveProvider.GetPool(address); + pool.Count.ShouldBe(0); + _smartContractExecutiveProvider.TryGetValue(address, out executives).ShouldBeTrue(); + executives.ShouldBe(pool); + executivePools = _smartContractExecutiveProvider.GetExecutivePools(); + executivePools.Count.ShouldBe(1); - [Fact] - public void SmartContractExecutiveProvider_Test() - { - var address = SampleAddress.AddressList[0]; - _smartContractExecutiveProvider.TryGetValue(address, out var executives).ShouldBeFalse(); - executives.ShouldBeNull(); - _smartContractExecutiveProvider.TryRemove(address, out executives).ShouldBeFalse(); - executives.ShouldBeNull(); - - var executivePools = _smartContractExecutiveProvider.GetExecutivePools(); - executivePools.Count.ShouldBe(0); - var pool = _smartContractExecutiveProvider.GetPool(address); - pool.Count.ShouldBe(0); - _smartContractExecutiveProvider.TryGetValue(address,out executives).ShouldBeTrue(); - executives.ShouldBe(pool); - executivePools = _smartContractExecutiveProvider.GetExecutivePools(); - executivePools.Count.ShouldBe(1); - - _smartContractExecutiveProvider.TryRemove(address,out executives).ShouldBeTrue(); - executives.ShouldBe(pool); - _smartContractExecutiveProvider.TryGetValue(address, out executives).ShouldBeFalse(); - executives.ShouldBeNull(); - } + _smartContractExecutiveProvider.TryRemove(address, out executives).ShouldBeTrue(); + executives.ShouldBe(pool); + _smartContractExecutiveProvider.TryGetValue(address, out executives).ShouldBeFalse(); + executives.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveServiceTests.cs index bd6fafd292..c75d5d4a53 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractExecutiveServiceTests.cs @@ -2,296 +2,296 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Configuration; using AElf.Kernel.SmartContract.Infrastructure; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractExecutiveServiceTests : SmartContractTestBase { - public sealed class SmartContractExecutiveServiceTests : SmartContractTestBase + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; + private readonly SmartContractExecutiveService _smartContractExecutiveService; + private readonly SmartContractHelper _smartContractHelper; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + private readonly ITransactionResultQueryService _transactionResultQueryService; + + public SmartContractExecutiveServiceTests() { - private readonly SmartContractExecutiveService _smartContractExecutiveService; - private readonly SmartContractHelper _smartContractHelper; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; - private readonly ITransactionResultQueryService _transactionResultQueryService; - private readonly KernelTestHelper _kernelTestHelper; - - public SmartContractExecutiveServiceTests() - { - _smartContractExecutiveService = GetRequiredService(); - _smartContractHelper = GetRequiredService(); - _smartContractRegistrationProvider = GetRequiredService(); - _defaultContractZeroCodeProvider = GetRequiredService(); - _smartContractExecutiveProvider = GetRequiredService(); - _transactionResultQueryService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + _smartContractExecutiveService = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + _smartContractRegistrationProvider = GetRequiredService(); + _defaultContractZeroCodeProvider = GetRequiredService(); + _smartContractExecutiveProvider = GetRequiredService(); + _transactionResultQueryService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - [Fact] - public void GetExecutive_ThrowArgumentNullException() + [Fact] + public void GetExecutive_ThrowArgumentNullException() + { + _smartContractExecutiveService.GetExecutiveAsync(new ChainContext { - _smartContractExecutiveService.GetExecutiveAsync(new ChainContext - { - BlockHash = Hash.Empty, - BlockHeight = 0 - }, null).ShouldThrow(); - } + BlockHash = Hash.Empty, + BlockHeight = 0 + }, null).ShouldThrow(); + } - [Fact] - public async Task GetExecutive_ThrowSmartContractFindRegistrationException() + [Fact] + public async Task GetExecutive_ThrowSmartContractFindRegistrationException() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + _smartContractExecutiveService.GetExecutiveAsync(new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - _smartContractExecutiveService.GetExecutiveAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, SampleAddress.AddressList[0]).ShouldThrow(); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, SampleAddress.AddressList[0]).ShouldThrow(); + } - [Fact] - public async Task GetExecutive_With_SmartContractRegistrationProvider_Test() + [Fact] + public async Task GetExecutive_With_SmartContractRegistrationProvider_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - - var chainContext = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + //Get executive by smartContractRegistration in SmartContractRegistrationProvider + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress, + _defaultContractZeroCodeProvider.DefaultContractZeroRegistration); + var executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress, executive); + + //Get executive from executive pool + executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + + var otherExecutive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress, executive); + + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress, otherExecutive); + + _smartContractExecutiveProvider.GetExecutivePools()[_defaultContractZeroCodeProvider.ContractZeroAddress] + .Count.ShouldBe(2); + + //Make codeHash different between smartContractRegistration and executive + var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; + var codeHash = HashHelper.ComputeFrom(code); + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress, new SmartContractRegistration { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - //Get executive by smartContractRegistration in SmartContractRegistrationProvider - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress, - _defaultContractZeroCodeProvider.DefaultContractZeroRegistration); - var executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress, executive); - - //Get executive from executive pool - executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - - var otherExecutive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress, executive); - - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress, otherExecutive); - - _smartContractExecutiveProvider.GetExecutivePools()[_defaultContractZeroCodeProvider.ContractZeroAddress] - .Count.ShouldBe(2); - - //Make codeHash different between smartContractRegistration and executive - var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; - var codeHash = HashHelper.ComputeFrom(code); - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress,new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - }); - - executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - executive.ContractHash.ShouldBe(codeHash); - _smartContractExecutiveProvider.GetExecutivePools() - .TryGetValue(_defaultContractZeroCodeProvider.ContractZeroAddress, out _).ShouldBeFalse(); - } - - [Fact] - public async Task GetExecutive_With_GenesisContract_Test() + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + }); + + executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + executive.ContractHash.ShouldBe(codeHash); + _smartContractExecutiveProvider.GetExecutivePools() + .TryGetValue(_defaultContractZeroCodeProvider.ContractZeroAddress, out _).ShouldBeFalse(); + } + + [Fact] + public async Task GetExecutive_With_GenesisContract_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=1 - var executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - - var transaction = _smartContractHelper.BuildDeploySystemSmartContractTransaction( - ConfigurationSmartContractAddressNameProvider.Name, - _smartContractHelper.Codes["AElf.Contracts.Configuration"]); - var block = await _smartContractHelper.GenerateBlockAsync(chain.BestChainHeight, chain.BestChainHash, new List + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=1 + var executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + + var transaction = _smartContractHelper.BuildDeploySystemSmartContractTransaction( + ConfigurationSmartContractAddressNameProvider.Name, + _smartContractHelper.Codes["AElf.Contracts.Configuration"]); + var block = await _smartContractHelper.GenerateBlockAsync(chain.BestChainHeight, chain.BestChainHash, + new List { transaction }); - await _smartContractHelper.MineBlockAsync(block); - - chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - - var transactionResult = await _transactionResultQueryService.GetTransactionResultAsync(transaction.GetHash(), block.GetHash()); - var contractDeployed = new ContractDeployed(); - contractDeployed.MergeFrom(transactionResult.Logs.First(l=>l.Name == nameof(ContractDeployed))); - - //Get executive of configuration contract in genesis contract - executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, contractDeployed.Address); - executive.ContractHash.ShouldBe( - HashHelper.ComputeFrom(_smartContractHelper.Codes["AElf.Contracts.Configuration"])); - - //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=2 - executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); - executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } + await _smartContractHelper.MineBlockAsync(block); - [Fact] - public async Task CleanExecutive_Test() - { - await _smartContractHelper.CreateChainWithGenesisContractAsync(); - - var address = _defaultContractZeroCodeProvider.ContractZeroAddress; - _smartContractExecutiveProvider.TryGetValue(address, out var pool).ShouldBeTrue(); - pool.Count.ShouldBe(1); - _smartContractExecutiveService.CleanExecutive(_defaultContractZeroCodeProvider.ContractZeroAddress); - _smartContractExecutiveProvider.TryGetValue(address,out _).ShouldBeFalse(); - } - - [Fact] - public async Task CleanIdleExecutive_Test() + chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - - var address = _defaultContractZeroCodeProvider.ContractZeroAddress; - _smartContractExecutiveProvider.TryGetValue(address, out var pool).ShouldBeTrue(); - pool.Count.ShouldBe(1); - _smartContractExecutiveService.CleanIdleExecutive(); - _smartContractExecutiveProvider.TryGetValue(address, out pool).ShouldBeTrue(); - pool.Count.ShouldBe(1); - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; - var executives = new List(); - for (var i = 0; i < 11; i++) - { - var executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); - executives.Add(executive); - } + var transactionResult = + await _transactionResultQueryService.GetTransactionResultAsync(transaction.GetHash(), block.GetHash()); + var contractDeployed = new ContractDeployed(); + contractDeployed.MergeFrom(transactionResult.Logs.First(l => l.Name == nameof(ContractDeployed))); - foreach (var executive in executives) - { - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - } - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(11); - _smartContractExecutiveService.CleanIdleExecutive(); - pool.Count.ShouldBe(10); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(10); - - pool.TryPeek(out var item); - item.LastUsedTime = item.LastUsedTime.AddHours(-2); - _smartContractExecutiveService.CleanIdleExecutive(); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(9); - - pool.TryPeek(out item); - item.LastUsedTime = item.LastUsedTime.AddHours(-2); - _smartContractExecutiveService.CleanIdleExecutive(); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(8); + //Get executive of configuration contract in genesis contract + executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, contractDeployed.Address); + executive.ContractHash.ShouldBe( + HashHelper.ComputeFrom(_smartContractHelper.Codes["AElf.Contracts.Configuration"])); + + //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=2 + executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress); + executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + } + + [Fact] + public async Task CleanExecutive_Test() + { + await _smartContractHelper.CreateChainWithGenesisContractAsync(); + + var address = _defaultContractZeroCodeProvider.ContractZeroAddress; + _smartContractExecutiveProvider.TryGetValue(address, out var pool).ShouldBeTrue(); + pool.Count.ShouldBe(1); + _smartContractExecutiveService.CleanExecutive(_defaultContractZeroCodeProvider.ContractZeroAddress); + _smartContractExecutiveProvider.TryGetValue(address, out _).ShouldBeFalse(); + } + + [Fact] + public async Task CleanIdleExecutive_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + + var address = _defaultContractZeroCodeProvider.ContractZeroAddress; + _smartContractExecutiveProvider.TryGetValue(address, out var pool).ShouldBeTrue(); + pool.Count.ShouldBe(1); + _smartContractExecutiveService.CleanIdleExecutive(); + _smartContractExecutiveProvider.TryGetValue(address, out pool).ShouldBeTrue(); + pool.Count.ShouldBe(1); + + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + + var executives = new List(); + for (var i = 0; i < 11; i++) + { + var executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address); + executives.Add(executive); } - [Fact] - public async Task Put_Executive_Success() + + foreach (var executive in executives) + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(11); + _smartContractExecutiveService.CleanIdleExecutive(); + pool.Count.ShouldBe(10); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(10); + + pool.TryPeek(out var item); + item.LastUsedTime = item.LastUsedTime.AddHours(-2); + _smartContractExecutiveService.CleanIdleExecutive(); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(9); + + pool.TryPeek(out item); + item.LastUsedTime = item.LastUsedTime.AddHours(-2); + _smartContractExecutiveService.CleanIdleExecutive(); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(8); + } + + [Fact] + public async Task Put_Executive_Success() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var address = _defaultContractZeroCodeProvider.ContractZeroAddress; + var executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, address); + _smartContractExecutiveProvider.TryGetValue(address, out var pool); + pool.Count.ShouldBe(0); + + var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, + address, new SmartContractRegistration { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var address = _defaultContractZeroCodeProvider.ContractZeroAddress; - var executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, address); - _smartContractExecutiveProvider.TryGetValue(address, out var pool); - pool.Count.ShouldBe(0); - - var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, - address,new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - }); - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(1); + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + }); + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(1); - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, address, - _defaultContractZeroCodeProvider.DefaultContractZeroRegistration); + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, address, + _defaultContractZeroCodeProvider.DefaultContractZeroRegistration); - var block = await _kernelTestHelper.AttachBlockToBestChain(); - chainContext.BlockHash = block.GetHash(); - chainContext.BlockHeight = block.Height; - pool.TryTake(out _); - pool.Count.ShouldBe(0); - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - pool.Count.ShouldBe(1); - } - - [Fact] - public async Task Put_Executive_Failed() + var block = await _kernelTestHelper.AttachBlockToBestChain(); + chainContext.BlockHash = block.GetHash(); + chainContext.BlockHeight = block.Height; + pool.TryTake(out _); + pool.Count.ShouldBe(0); + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + pool.Count.ShouldBe(1); + } + + [Fact] + public async Task Put_Executive_Failed() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var address = _defaultContractZeroCodeProvider.ContractZeroAddress; + var executive = await _smartContractExecutiveService + .GetExecutiveAsync(chainContext, address); + _smartContractExecutiveProvider.TryGetValue(address, out var pool); + pool.Count.ShouldBe(0); + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, SampleAddress.AddressList[0], executive); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(0); + + var block = await _kernelTestHelper.AttachBlockToBestChain(); + chainContext.BlockHash = block.GetHash(); + chainContext.BlockHeight = block.Height; + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(0); + + var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, + address, new SmartContractRegistration { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var address = _defaultContractZeroCodeProvider.ContractZeroAddress; - var executive = await _smartContractExecutiveService - .GetExecutiveAsync(chainContext, address); - _smartContractExecutiveProvider.TryGetValue(address, out var pool); - pool.Count.ShouldBe(0); - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, SampleAddress.AddressList[0], executive); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(0); - - var block = await _kernelTestHelper.AttachBlockToBestChain(); - chainContext.BlockHash = block.GetHash(); - chainContext.BlockHeight = block.Height; - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(0); - - var code = _smartContractHelper.Codes["AElf.Contracts.Configuration"]; - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, - address,new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(code), - CodeHash = HashHelper.ComputeFrom(code) - }); - await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); - _smartContractExecutiveProvider.TryGetValue(address, out pool); - pool.Count.ShouldBe(0); - } + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(code), + CodeHash = HashHelper.ComputeFrom(code) + }); + await _smartContractExecutiveService.PutExecutiveAsync(chainContext, address, executive); + _smartContractExecutiveProvider.TryGetValue(address, out pool); + pool.Count.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractRegistrationProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractRegistrationProviderTests.cs index bb243f31e7..32f57116dc 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractRegistrationProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractRegistrationProviderTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; @@ -6,56 +5,55 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class SmartContractRegistrationProviderTests : SmartContractTestBase { - public sealed class SmartContractRegistrationProviderTests : SmartContractTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly SmartContractHelper _smartContractHelper; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + + public SmartContractRegistrationProviderTests() + { + _blockchainService = GetRequiredService(); + _smartContractRegistrationProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + } + + [Fact] + public async Task SmartContractRegistrationSetAndGet_Test() { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly SmartContractHelper _smartContractHelper; + var chain = await _smartContractHelper.CreateChainAsync(); + var blockExecutedDataKey = $"BlockExecutedData/SmartContractRegistration/{SampleAddress.AddressList[0]}"; - public SmartContractRegistrationProviderTests() + var chainContext = new ChainContext { - _blockchainService = GetRequiredService(); - _smartContractRegistrationProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _smartContractHelper = GetRequiredService(); - } - - [Fact] - public async Task SmartContractRegistrationSetAndGet_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + + var smartContractRegistrationFromProvider = + await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, + SampleAddress.AddressList[0]); + smartContractRegistrationFromProvider.ShouldBeNull(); + + var smartContractRegistration = new SmartContractRegistration { - var chain = await _smartContractHelper.CreateChainAsync(); - var blockExecutedDataKey = $"BlockExecutedData/SmartContractRegistration/{SampleAddress.AddressList[0]}"; - - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - - var smartContractRegistrationFromProvider = - await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, - SampleAddress.AddressList[0]); - smartContractRegistrationFromProvider.ShouldBeNull(); - - var smartContractRegistration = new SmartContractRegistration - { - CodeHash = HashHelper.ComputeFrom(blockExecutedDataKey), - Category = KernelConstants.CodeCoverageRunnerCategory, - Version = 1 - }; - await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, - SampleAddress.AddressList[0], smartContractRegistration); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); - blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); - - smartContractRegistrationFromProvider = - await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, - SampleAddress.AddressList[0]); - smartContractRegistrationFromProvider.ShouldBe(smartContractRegistration); - } + CodeHash = HashHelper.ComputeFrom(blockExecutedDataKey), + Category = KernelConstants.CodeCoverageRunnerCategory, + Version = 1 + }; + await _smartContractRegistrationProvider.SetSmartContractRegistrationAsync(chainContext, + SampleAddress.AddressList[0], smartContractRegistration); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(chain.BestChainHash); + blockStateSet.BlockExecutedData.ShouldContainKey(blockExecutedDataKey); + + smartContractRegistrationFromProvider = + await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, + SampleAddress.AddressList[0]); + smartContractRegistrationFromProvider.ShouldBe(smartContractRegistration); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractServiceTests.cs index 678e2e98f2..87b573173f 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/SmartContractServiceTests.cs @@ -5,100 +5,100 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class SmartContractServiceTests : SmartContractRunnerTestBase { - public class SmartContractServiceTests : SmartContractRunnerTestBase - { - private readonly SmartContractService _smartContractService; + private readonly SmartContractService _smartContractService; - public SmartContractServiceTests() - { - _smartContractService = GetRequiredService(); - } + public SmartContractServiceTests() + { + _smartContractService = GetRequiredService(); + } - [Fact] - public async Task Deploy_Contract_Success() + [Fact] + public async Task Deploy_Contract_Success() + { + var registration = new SmartContractRegistration { - var registration = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = HashHelper.ComputeFrom("TestDeployContract").ToByteString(), - CodeHash = HashHelper.ComputeFrom("TestDeployContract") - }; + Category = KernelConstants.DefaultRunnerCategory, + Code = HashHelper.ComputeFrom("TestDeployContract").ToByteString(), + CodeHash = HashHelper.ComputeFrom("TestDeployContract") + }; - await _smartContractService.DeployContractAsync(new ContractDto - { - BlockHeight = 1, - ContractAddress = SampleAddress.AddressList[0], - ContractName = null, - IsPrivileged = false, - SmartContractRegistration = registration - }); + await _smartContractService.DeployContractAsync(new ContractDto + { + BlockHeight = 1, + ContractAddress = SampleAddress.AddressList[0], + ContractName = null, + IsPrivileged = false, + SmartContractRegistration = registration + }); + } - } + [Fact] + public async Task Update_Contract_Success() + { + var registrationA = new SmartContractRegistration + { + Category = KernelConstants.DefaultRunnerCategory, + Code = HashHelper.ComputeFrom("TestContractA").ToByteString(), + CodeHash = HashHelper.ComputeFrom("TestContractA") + }; - [Fact] - public async Task Update_Contract_Success() + var registrationANew = new SmartContractRegistration { - var registrationA = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = HashHelper.ComputeFrom("TestContractA").ToByteString(), - CodeHash = HashHelper.ComputeFrom("TestContractA") - }; + Category = KernelConstants.DefaultRunnerCategory, + Code = HashHelper.ComputeFrom("TestContractA_New").ToByteString(), + CodeHash = HashHelper.ComputeFrom("TestContractA") + }; - var registrationANew = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = HashHelper.ComputeFrom("TestContractA_New").ToByteString(), - CodeHash = HashHelper.ComputeFrom("TestContractA") - }; + var registrationB = new SmartContractRegistration + { + Category = KernelConstants.DefaultRunnerCategory, + Code = HashHelper.ComputeFrom("TestContractB").ToByteString(), + CodeHash = HashHelper.ComputeFrom("TestContractB") + }; - var registrationB = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = HashHelper.ComputeFrom("TestContractB").ToByteString(), - CodeHash = HashHelper.ComputeFrom("TestContractB") - }; + await _smartContractService.DeployContractAsync(new ContractDto + { + BlockHeight = 1, + ContractAddress = SampleAddress.AddressList[0], + ContractName = null, + IsPrivileged = false, + SmartContractRegistration = registrationA + }); - await _smartContractService.DeployContractAsync(new ContractDto - { - BlockHeight = 1, - ContractAddress = SampleAddress.AddressList[0], - ContractName = null, - IsPrivileged = false, - SmartContractRegistration = registrationA - }); - - await _smartContractService.UpdateContractAsync(new ContractDto - { - ContractAddress = SampleAddress.AddressList[1], - SmartContractRegistration = registrationANew, - BlockHeight = 2, - IsPrivileged = false, - ContractName = null - }); - - await _smartContractService.UpdateContractAsync(new ContractDto - { - ContractAddress = SampleAddress.AddressList[2], - SmartContractRegistration = registrationB, - BlockHeight = 2, - IsPrivileged = false, - ContractName = null - }); - } + await _smartContractService.UpdateContractAsync(new ContractDto + { + ContractAddress = SampleAddress.AddressList[1], + SmartContractRegistration = registrationANew, + BlockHeight = 2, + IsPrivileged = false, + ContractName = null + }); - [Fact] - public void ExceptionTest() + await _smartContractService.UpdateContractAsync(new ContractDto { - var message = "message"; - var exception = new Exception(); - Should.Throw(() => throw new SmartContractExecutingException()); - Should.Throw(() => throw new SmartContractExecutingException(message, exception)); - Should.Throw(() => throw new SmartContractFindRegistrationException()); - Should.Throw(() => throw new SmartContractFindRegistrationException(message, exception)); - } + ContractAddress = SampleAddress.AddressList[2], + SmartContractRegistration = registrationB, + BlockHeight = 2, + IsPrivileged = false, + ContractName = null + }); + } + + [Fact] + public void ExceptionTest() + { + var message = "message"; + var exception = new Exception(); + Should.Throw(() => throw new SmartContractExecutingException()); + Should.Throw(() => + throw new SmartContractExecutingException(message, exception)); + Should.Throw(() => throw new SmartContractFindRegistrationException()); + Should.Throw(() => + throw new SmartContractFindRegistrationException(message, exception)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/StateCacheFromPartialBlockStateSetTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/StateCacheFromPartialBlockStateSetTests.cs index dc37977f5a..b7baa37808 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/StateCacheFromPartialBlockStateSetTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/StateCacheFromPartialBlockStateSetTests.cs @@ -3,50 +3,49 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class StateCacheFromPartialBlockStateSetTests { - public class StateCacheFromPartialBlockStateSetTests + [Fact] + public void StateCacheFromPartialBlockStateSet_Test() { - [Fact] - public void StateCacheFromPartialBlockStateSet_Test() + var path = new StatePath(); + var deleteStatePath = new ScopedStatePath + { + Address = SampleAddress.AddressList[0], + Path = path + }; + var changeStatePath = new ScopedStatePath + { + Address = SampleAddress.AddressList[1], + Path = path + }; + var blockStateSet = new BlockStateSet + { + Deletes = { deleteStatePath.ToStateKey() }, + Changes = { { changeStatePath.ToStateKey(), ByteString.Empty } } + }; + var stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(blockStateSet); + var notExistStatePath = new ScopedStatePath { - var path = new StatePath(); - var deleteStatePath = new ScopedStatePath - { - Address = SampleAddress.AddressList[0], - Path = path - }; - var changeStatePath = new ScopedStatePath - { - Address = SampleAddress.AddressList[1], - Path = path - }; - var blockStateSet = new BlockStateSet - { - Deletes = {deleteStatePath.ToStateKey()}, - Changes = {{changeStatePath.ToStateKey(), ByteString.Empty}}, - }; - var stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(blockStateSet); - var notExistStatePath = new ScopedStatePath - { - Address = SampleAddress.AddressList[2], - Path = path - }; - - stateCacheFromPartialBlockStateSet.TryGetValue(deleteStatePath,out var deletedValue).ShouldBeTrue(); - deletedValue.ShouldBeNull(); - stateCacheFromPartialBlockStateSet[deleteStatePath].ShouldBeNull(); - - stateCacheFromPartialBlockStateSet.TryGetValue(changeStatePath,out var changeValue).ShouldBeTrue(); - changeValue.ShouldBe(ByteString.Empty); - stateCacheFromPartialBlockStateSet[changeStatePath].ShouldBe(ByteString.Empty.ToByteArray()); - - stateCacheFromPartialBlockStateSet.TryGetValue(notExistStatePath, out var value).ShouldBeFalse(); - value.ShouldBeNull(); - stateCacheFromPartialBlockStateSet[notExistStatePath].ShouldBeNull(); + Address = SampleAddress.AddressList[2], + Path = path + }; + + stateCacheFromPartialBlockStateSet.TryGetValue(deleteStatePath, out var deletedValue).ShouldBeTrue(); + deletedValue.ShouldBeNull(); + stateCacheFromPartialBlockStateSet[deleteStatePath].ShouldBeNull(); + + stateCacheFromPartialBlockStateSet.TryGetValue(changeStatePath, out var changeValue).ShouldBeTrue(); + changeValue.ShouldBe(ByteString.Empty); + stateCacheFromPartialBlockStateSet[changeStatePath].ShouldBe(ByteString.Empty.ToByteArray()); + + stateCacheFromPartialBlockStateSet.TryGetValue(notExistStatePath, out var value).ShouldBeFalse(); + value.ShouldBeNull(); + stateCacheFromPartialBlockStateSet[notExistStatePath].ShouldBeNull(); - stateCacheFromPartialBlockStateSet[notExistStatePath] = ByteString.Empty.ToByteArray(); - stateCacheFromPartialBlockStateSet[notExistStatePath].ShouldBeNull(); - } + stateCacheFromPartialBlockStateSet[notExistStatePath] = ByteString.Empty.ToByteArray(); + stateCacheFromPartialBlockStateSet[notExistStatePath].ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/StateSizeLimitProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/StateSizeLimitProviderTests.cs index 02d86175d4..363207b5c2 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/StateSizeLimitProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/StateSizeLimitProviderTests.cs @@ -4,81 +4,80 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public class StateSizeLimitProviderTests : AElfIntegratedTest { - public class StateSizeLimitProviderTests : AElfIntegratedTest + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IStateSizeLimitProvider _stateSizeLimitProvider; + + public StateSizeLimitProviderTests() + { + _stateSizeLimitProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } + + [Fact] + public async Task StateSizeLimitStateProvider_GetAndSet_Test() { - private readonly IStateSizeLimitProvider _stateSizeLimitProvider; - private readonly IBlockStateSetManger _blockStateSetManger; + var blockIndex = new BlockIndex + { + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 1 + }; + + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + + { + var limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); + limit.ShouldBe(SmartContractConstants.StateSizeLimit); + } + + var expectedLimit = 50; - public StateSizeLimitProviderTests() { - _stateSizeLimitProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); + await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, expectedLimit); + var limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); + limit.ShouldBe(expectedLimit); + + expectedLimit = 1; + await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, expectedLimit); + limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); + limit.ShouldBe(expectedLimit); + + await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, 0); + limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync( + new ChainContext + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + limit.ShouldBe(expectedLimit); } - [Fact] - public async Task StateSizeLimitStateProvider_GetAndSet_Test() + var blockIndex2 = new BlockIndex { - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 1 - }; + BlockHash = HashHelper.ComputeFrom("BlockHash1"), + BlockHeight = blockIndex.BlockHeight + 1 + }; - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - - { - var limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); - limit.ShouldBe(SmartContractConstants.StateSizeLimit); - } - - var expectedLimit = 50; - - { - await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, expectedLimit); - var limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); - limit.ShouldBe(expectedLimit); - - expectedLimit = 1; - await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, expectedLimit); - limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex); - limit.ShouldBe(expectedLimit); - - await _stateSizeLimitProvider.SetStateSizeLimitAsync(blockIndex, 0); - limit = await _stateSizeLimitProvider.GetStateSizeLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(expectedLimit); - } - - var blockIndex2 = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash1"), - BlockHeight = blockIndex.BlockHeight + 1 - }; - - var blockStateSet2 = new BlockStateSet - { - PreviousHash = blockIndex.BlockHash, - BlockHash = blockIndex2.BlockHash, - BlockHeight = blockIndex2.BlockHeight + 1 - }; - - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet2); - - { - var stateSizeLimit = - await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex2); - stateSizeLimit.ShouldBe(expectedLimit); - } + var blockStateSet2 = new BlockStateSet + { + PreviousHash = blockIndex.BlockHash, + BlockHash = blockIndex2.BlockHash, + BlockHeight = blockIndex2.BlockHeight + 1 + }; + + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet2); + + { + var stateSizeLimit = + await _stateSizeLimitProvider.GetStateSizeLimitAsync(blockIndex2); + stateSizeLimit.ShouldBe(expectedLimit); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/TestLogEventProcessor.cs b/test/AElf.Kernel.SmartContract.Tests/Application/TestLogEventProcessor.cs index a4f72c7ca3..7d0aa934e4 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/TestLogEventProcessor.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/TestLogEventProcessor.cs @@ -1,50 +1,48 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Types; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public interface ITestLogEventProcessor : ILogEventProcessor +{ + Dictionary>> GetProcessedResult(); + + void CleanProcessedResult(); +} + +public class TestLogEventProcessor : ITestLogEventProcessor { - public interface ITestLogEventProcessor : ILogEventProcessor + private readonly LogEvent _logEvent = new() { - Dictionary>> GetProcessedResult(); + Name = "TestLogEvent", + Address = SampleAddress.AddressList[0] + }; - void CleanProcessedResult(); - } + private readonly Dictionary>> _processedResult = new(); - public class TestLogEventProcessor : ITestLogEventProcessor + public Task GetInterestedEventAsync(IChainContext chainContext) { - private readonly LogEvent _logEvent = new LogEvent + return Task.FromResult(new InterestedEvent { - Name = "TestLogEvent", - Address = SampleAddress.AddressList[0] - }; + LogEvent = _logEvent, + Bloom = _logEvent.GetBloom() + }); + } - private readonly Dictionary>> _processedResult = - new Dictionary>>(); + public Task ProcessAsync(Block block, Dictionary> logEventsMap) + { + _processedResult.Add(block.Height, logEventsMap); + return Task.CompletedTask; + } - public Task GetInterestedEventAsync(IChainContext chainContext) - { - return Task.FromResult(new InterestedEvent - { - LogEvent = _logEvent, - Bloom = _logEvent.GetBloom() - }); - } - - public Task ProcessAsync(Block block, Dictionary> logEventsMap) - { - _processedResult.Add(block.Height, logEventsMap); - return Task.CompletedTask; - } - public Dictionary>> GetProcessedResult() - { - return _processedResult; - } + public Dictionary>> GetProcessedResult() + { + return _processedResult; + } - public void CleanProcessedResult() - { - _processedResult.Clear(); - } + public void CleanProcessedResult() + { + _processedResult.Clear(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Application/TransactionReadOnlyExecutionServiceTests.cs b/test/AElf.Kernel.SmartContract.Tests/Application/TransactionReadOnlyExecutionServiceTests.cs index bb17aa6094..5b8d7203a3 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Application/TransactionReadOnlyExecutionServiceTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Application/TransactionReadOnlyExecutionServiceTests.cs @@ -8,186 +8,189 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Application +namespace AElf.Kernel.SmartContract.Application; + +public sealed class TransactionReadOnlyExecutionServiceTests : SmartContractTestBase { - public sealed class TransactionReadOnlyExecutionServiceTests : SmartContractTestBase + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; + private readonly SmartContractHelper _smartContractHelper; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + + public TransactionReadOnlyExecutionServiceTests() + { + _transactionReadOnlyExecutionService = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _defaultContractZeroCodeProvider = GetRequiredService(); + _smartContractExecutiveProvider = GetRequiredService(); + } + + [Fact] + public async Task ExecuteAsync_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var transaction = new Transaction + { + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[0], + MethodName = "NotExistMethod", + Params = ByteString.Empty + }; + _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, TimestampHelper.GetUtcNow()) + .ShouldThrow(); + _transactionReadOnlyExecutionService + .ExecuteAsync
(chainContext, transaction, TimestampHelper.GetUtcNow(), false) + .ShouldThrow(); + + transaction = new Transaction + { + From = SampleAddress.AddressList[0], + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = "NotExistMethod", + Params = ByteString.Empty + }; + var trace = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, + TimestampHelper.GetUtcNow()); + trace.Error.ShouldContain("Failed to find handler for NotExistMethod"); + trace.ExecutionStatus.ShouldBe(ExecutionStatus.SystemError); + var hash = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, + TimestampHelper.GetUtcNow(), false); + hash.ShouldBeNull(); + _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, + TimestampHelper.GetUtcNow(), true).ShouldThrow(); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + transaction = new Transaction + { + From = SampleAddress.AddressList[0], + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), + Params = _defaultContractZeroCodeProvider.ContractZeroAddress.ToByteString() + }; + trace = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, + TimestampHelper.GetUtcNow()); + trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + var smartContractRegistration = SmartContractRegistration.Parser.ParseFrom(trace.ReturnValue); + CheckSmartContractRegistration(smartContractRegistration); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + + smartContractRegistration = await _transactionReadOnlyExecutionService.ExecuteAsync( + chainContext, transaction, + TimestampHelper.GetUtcNow(), true); + + CheckSmartContractRegistration(smartContractRegistration); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + } + + private void CheckSmartContractRegistration(SmartContractRegistration smartContractRegistration) + { + smartContractRegistration.Category.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration + .Category); + smartContractRegistration.Code.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration + .Code); + smartContractRegistration.CodeHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration + .CodeHash); + } + + [Fact] + public async Task GetFileDescriptorSetAsync_Test() { - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private readonly SmartContractHelper _smartContractHelper; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ISmartContractExecutiveProvider _smartContractExecutiveProvider; - - public TransactionReadOnlyExecutionServiceTests() + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext { - _transactionReadOnlyExecutionService = GetRequiredService(); - _smartContractHelper = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _defaultContractZeroCodeProvider = GetRequiredService(); - _smartContractExecutiveProvider = GetRequiredService(); - } - - [Fact] - public async Task ExecuteAsync_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + _transactionReadOnlyExecutionService.GetFileDescriptorSetAsync(chainContext, SampleAddress.AddressList[0]) + .ShouldThrow(); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + var bytes = await _transactionReadOnlyExecutionService.GetFileDescriptorSetAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress); + var fileDescriptorSet = FileDescriptorSet.Parser.ParseFrom(bytes); + fileDescriptorSet.ShouldNotBeNull(); + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + } + + [Fact] + public async Task GetFileDescriptorsAsync_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[0], - MethodName = "NotExistMethod", - Params = ByteString.Empty - }; - _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, TimestampHelper.GetUtcNow()) - .ShouldThrow(); - _transactionReadOnlyExecutionService.ExecuteAsync
(chainContext, transaction, TimestampHelper.GetUtcNow(),false) - .ShouldThrow(); - - transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = "NotExistMethod", - Params = ByteString.Empty - }; - var trace = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - TimestampHelper.GetUtcNow()); - trace.Error.ShouldContain("Failed to find handler for NotExistMethod"); - trace.ExecutionStatus.ShouldBe(ExecutionStatus.SystemError); - var hash = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - TimestampHelper.GetUtcNow(), false); - hash.ShouldBeNull(); - _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - TimestampHelper.GetUtcNow(), true).ShouldThrow(); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), - Params = _defaultContractZeroCodeProvider.ContractZeroAddress.ToByteString() - }; - trace = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - TimestampHelper.GetUtcNow()); - trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); - var smartContractRegistration = SmartContractRegistration.Parser.ParseFrom(trace.ReturnValue); - CheckSmartContractRegistration(smartContractRegistration); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - - smartContractRegistration = await _transactionReadOnlyExecutionService.ExecuteAsync(chainContext, transaction, - TimestampHelper.GetUtcNow(), true); - - CheckSmartContractRegistration(smartContractRegistration); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } - - private void CheckSmartContractRegistration(SmartContractRegistration smartContractRegistration) + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + _transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, SampleAddress.AddressList[0]) + .ShouldThrow(); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + var fileDescriptors = await _transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress); + fileDescriptors.Count().ShouldBeGreaterThan(0); + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + } + + [Fact] + public async Task GetTransactionParametersAsync_Test() + { + var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); + var chainContext = new ChainContext { - smartContractRegistration.Category.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration - .Category); - smartContractRegistration.Code.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration - .Code); - smartContractRegistration.CodeHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration - .CodeHash); - } - - [Fact] - public async Task GetFileDescriptorSetAsync_Test() + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var transaction = new Transaction { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - _transactionReadOnlyExecutionService.GetFileDescriptorSetAsync(chainContext, SampleAddress.AddressList[0]) - .ShouldThrow(); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - var bytes = await _transactionReadOnlyExecutionService.GetFileDescriptorSetAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress); - var fileDescriptorSet = FileDescriptorSet.Parser.ParseFrom(bytes); - fileDescriptorSet.ShouldNotBeNull(); - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } - - [Fact] - public async Task GetFileDescriptorsAsync_Test() + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[0], + MethodName = "NotExistMethod", + Params = ByteString.Empty + }; + _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction) + .ShouldThrow(); + + transaction = new Transaction { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - _transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, SampleAddress.AddressList[0]) - .ShouldThrow(); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - var fileDescriptors = await _transactionReadOnlyExecutionService.GetFileDescriptorsAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress); - fileDescriptors.Count().ShouldBeGreaterThan(0); - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } - - [Fact] - public async Task GetTransactionParametersAsync_Test() + From = SampleAddress.AddressList[0], + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = "NotExistMethod", + Params = ByteString.Empty + }; + var parameters = + await _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction); + parameters.ShouldBeEmpty(); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); + transaction = new Transaction { - var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[0], - MethodName = "NotExistMethod", - Params = ByteString.Empty - }; - _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction) - .ShouldThrow(); - - transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = "NotExistMethod", - Params = ByteString.Empty - }; - var parameters = await _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction); - parameters.ShouldBeEmpty(); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), - Params = _defaultContractZeroCodeProvider.ContractZeroAddress.ToByteString() - }; - parameters = await _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction); - parameters.Trim('"').ShouldBe(_defaultContractZeroCodeProvider.ContractZeroAddress.ToBase58()); - - _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() - .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } + From = SampleAddress.AddressList[0], + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.GetSmartContractRegistrationByAddress), + Params = _defaultContractZeroCodeProvider.ContractZeroAddress.ToByteString() + }; + parameters = + await _transactionReadOnlyExecutionService.GetTransactionParametersAsync(chainContext, transaction); + parameters.Trim('"').ShouldBe(_defaultContractZeroCodeProvider.ContractZeroAddress.ToBase58()); + + _smartContractExecutiveProvider.GetPool(_defaultContractZeroCodeProvider.ContractZeroAddress).Single() + .ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Domain/ExecutionReturnSetCollectionTests.cs b/test/AElf.Kernel.SmartContract.Tests/Domain/ExecutionReturnSetCollectionTests.cs index 86c71ad6d1..5bc53d49f7 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Domain/ExecutionReturnSetCollectionTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Domain/ExecutionReturnSetCollectionTests.cs @@ -5,66 +5,65 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public class ExecutionReturnSetCollectionTests { - public class ExecutionReturnSetCollectionTests + [Fact] + public void ExecutionReturnSetCollection_Test() { - [Fact] - public void ExecutionReturnSetCollection_Test() + var executionReturnSetCollection = new ExecutionReturnSetCollection(new List()); + executionReturnSetCollection.GetExecutionReturnSetList().Count.ShouldBe(0); + + executionReturnSetCollection.AddRange(GetExecutionReturnSets()); + executionReturnSetCollection.Executed.Count.ShouldBe(2); + executionReturnSetCollection.Executed.First(r => r.Status == TransactionResultStatus.Mined).TransactionId + .ShouldBe(HashHelper.ComputeFrom("minedTxId")); + executionReturnSetCollection.Executed.First(r => r.Status == TransactionResultStatus.Failed).TransactionId + .ShouldBe(HashHelper.ComputeFrom("failedTxId")); + var executionReturnSet = executionReturnSetCollection.Conflict.Single(); + executionReturnSet.Status.ShouldBe(TransactionResultStatus.Conflict); + executionReturnSet.TransactionId.ShouldBe(HashHelper.ComputeFrom("conflictTxId")); + + var blockStateSet = executionReturnSetCollection.ToBlockStateSet(); + var change = blockStateSet.Changes.Single(); + change.Key.ShouldBe("secondKey"); + change.Value.ShouldBe(ByteString.Empty); + blockStateSet.Deletes.Single().ShouldBe("firstKey"); + } + + private List GetExecutionReturnSets() + { + var firstKey = "firstKey"; + var secondKey = "secondKey"; + var executionReturnSets = new List(); + var minedTransactionId = HashHelper.ComputeFrom("minedTxId"); + var minedExecutionReturnSet = new ExecutionReturnSet { - var executionReturnSetCollection = new ExecutionReturnSetCollection(new List()); - executionReturnSetCollection.GetExecutionReturnSetList().Count.ShouldBe(0); - - executionReturnSetCollection.AddRange(GetExecutionReturnSets()); - executionReturnSetCollection.Executed.Count.ShouldBe(2); - executionReturnSetCollection.Executed.First(r => r.Status == TransactionResultStatus.Mined).TransactionId - .ShouldBe(HashHelper.ComputeFrom("minedTxId")); - executionReturnSetCollection.Executed.First(r => r.Status == TransactionResultStatus.Failed).TransactionId - .ShouldBe(HashHelper.ComputeFrom("failedTxId")); - var executionReturnSet = executionReturnSetCollection.Conflict.Single(); - executionReturnSet.Status.ShouldBe(TransactionResultStatus.Conflict); - executionReturnSet.TransactionId.ShouldBe(HashHelper.ComputeFrom("conflictTxId")); + TransactionId = minedTransactionId, + Status = TransactionResultStatus.Mined, + StateChanges = { { "firstKey", ByteString.Empty } }, + StateDeletes = { { "secondKey", true } } + }; + executionReturnSets.Add(minedExecutionReturnSet); - var blockStateSet = executionReturnSetCollection.ToBlockStateSet(); - var change = blockStateSet.Changes.Single(); - change.Key.ShouldBe("secondKey"); - change.Value.ShouldBe(ByteString.Empty); - blockStateSet.Deletes.Single().ShouldBe("firstKey"); - } + var failedTransactionId = HashHelper.ComputeFrom("failedTxId"); + var failedExecutionReturnSet = new ExecutionReturnSet + { + TransactionId = failedTransactionId, + Status = TransactionResultStatus.Failed, + StateChanges = { { "secondKey", ByteString.Empty } }, + StateDeletes = { { "firstKey", true } } + }; + executionReturnSets.Add(failedExecutionReturnSet); - private List GetExecutionReturnSets() + var conflictTransactionId = HashHelper.ComputeFrom("conflictTxId"); + var conflictExecutionReturnSet = new ExecutionReturnSet { - var firstKey = "firstKey"; - var secondKey = "secondKey"; - var executionReturnSets = new List(); - var minedTransactionId = HashHelper.ComputeFrom("minedTxId"); - var minedExecutionReturnSet = new ExecutionReturnSet - { - TransactionId = minedTransactionId, - Status = TransactionResultStatus.Mined, - StateChanges = {{"firstKey", ByteString.Empty}}, - StateDeletes = {{"secondKey", true}} - }; - executionReturnSets.Add(minedExecutionReturnSet); - - var failedTransactionId = HashHelper.ComputeFrom("failedTxId"); - var failedExecutionReturnSet = new ExecutionReturnSet - { - TransactionId = failedTransactionId, - Status = TransactionResultStatus.Failed, - StateChanges = {{"secondKey", ByteString.Empty}}, - StateDeletes = {{"firstKey", true}} - }; - executionReturnSets.Add(failedExecutionReturnSet); - - var conflictTransactionId = HashHelper.ComputeFrom("conflictTxId"); - var conflictExecutionReturnSet = new ExecutionReturnSet - { - TransactionId = conflictTransactionId, - Status = TransactionResultStatus.Conflict - }; - executionReturnSets.Add(conflictExecutionReturnSet); - return executionReturnSets; - } + TransactionId = conflictTransactionId, + Status = TransactionResultStatus.Conflict + }; + executionReturnSets.Add(conflictExecutionReturnSet); + return executionReturnSets; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Domain/TieredStateCacheTests.cs b/test/AElf.Kernel.SmartContract.Tests/Domain/TieredStateCacheTests.cs index dd62056e77..543feda7e5 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Domain/TieredStateCacheTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Domain/TieredStateCacheTests.cs @@ -5,86 +5,88 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Domain +namespace AElf.Kernel.SmartContract.Domain; + +public class TieredStateCacheTests { - public class TieredStateCacheTests + private readonly ScopedStatePath FirstPath = new() { - private readonly ScopedStatePath FirstPath = new ScopedStatePath - { - Address = SampleAddress.AddressList[0], - Path = new StatePath() - }; - private readonly ScopedStatePath SecondPath = new ScopedStatePath + Address = SampleAddress.AddressList[0], + Path = new StatePath() + }; + + private readonly ByteString FirstValue = ByteString.CopyFromUtf8(nameof(FirstValue)); + + private readonly ScopedStatePath SecondPath = new() + { + Address = SampleAddress.AddressList[1], + Path = new StatePath() + }; + + private readonly ByteString SecondValue = ByteString.CopyFromUtf8(nameof(SecondValue)); + private readonly ByteString ThirdValue = ByteString.CopyFromUtf8(nameof(ThirdValue)); + + [Fact] + public void TieredStateCache_Test() + { + var path = new ScopedStatePath { - Address = SampleAddress.AddressList[1], + Address = SampleAddress.AddressList[2], Path = new StatePath() }; - private readonly ByteString FirstValue = ByteString.CopyFromUtf8(nameof(FirstValue)); - private readonly ByteString SecondValue = ByteString.CopyFromUtf8(nameof(SecondValue)); - private readonly ByteString ThirdValue = ByteString.CopyFromUtf8(nameof(ThirdValue)); - - [Fact] - public void TieredStateCache_Test() + var cache = new TieredStateCache(); + cache.TryGetValue(path, out var value).ShouldBeFalse(); + value.ShouldBeNull(); + cache[path].ShouldBeNull(); + + cache.Update(GetTransactionExecutingStateSets()); + cache.TryGetValue(FirstPath, out var firstValue).ShouldBeTrue(); + firstValue.ShouldBeNull(); + cache.TryGetValue(SecondPath, out var secondValue).ShouldBeTrue(); + secondValue.ShouldBe(SecondValue.ToByteArray()); + + var stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(new BlockStateSet { - var path = new ScopedStatePath - { - Address = SampleAddress.AddressList[2], - Path = new StatePath() - }; - var cache = new TieredStateCache(); - cache.TryGetValue(path, out var value).ShouldBeFalse(); - value.ShouldBeNull(); - cache[path].ShouldBeNull(); - - cache.Update(GetTransactionExecutingStateSets()); - cache.TryGetValue(FirstPath, out var firstValue).ShouldBeTrue(); - firstValue.ShouldBeNull(); - cache.TryGetValue(SecondPath, out var secondValue).ShouldBeTrue(); - secondValue.ShouldBe(SecondValue.ToByteArray()); + Changes = { { SecondPath.ToStateKey(), ThirdValue } } + }); + cache = new TieredStateCache(stateCacheFromPartialBlockStateSet); + cache.TryGetValue(SecondPath, out secondValue).ShouldBeTrue(); + secondValue.ShouldBe(ThirdValue.ToByteArray()); + cache[SecondPath] = FirstValue.ToByteArray(); + cache[SecondPath].ShouldBe(FirstValue.ToByteArray()); + cache.TryGetValue(SecondPath, out secondValue); + secondValue.ShouldBe(FirstValue.ToByteArray()); - var stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(new BlockStateSet - { - Changes = { {SecondPath.ToStateKey(),ThirdValue}} - }); - cache = new TieredStateCache(stateCacheFromPartialBlockStateSet); - cache.TryGetValue(SecondPath,out secondValue).ShouldBeTrue(); - secondValue.ShouldBe(ThirdValue.ToByteArray()); - cache[SecondPath] = FirstValue.ToByteArray(); - cache[SecondPath].ShouldBe(FirstValue.ToByteArray()); - cache.TryGetValue(SecondPath, out secondValue); - secondValue.ShouldBe(FirstValue.ToByteArray()); - - cache.Update(GetTransactionExecutingStateSets()); - cache.TryGetValue(SecondPath, out secondValue); - secondValue.ShouldBe(SecondValue.ToByteArray()); - - stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(new BlockStateSet - { - Changes = { {SecondPath.ToStateKey(),ThirdValue}} - }); - cache.Update(GetTransactionExecutingStateSets()); - cache.TryGetValue(SecondPath, out secondValue); - secondValue.ShouldBe(SecondValue.ToByteArray()); - } + cache.Update(GetTransactionExecutingStateSets()); + cache.TryGetValue(SecondPath, out secondValue); + secondValue.ShouldBe(SecondValue.ToByteArray()); - private IEnumerable GetTransactionExecutingStateSets() + stateCacheFromPartialBlockStateSet = new StateCacheFromPartialBlockStateSet(new BlockStateSet { - var firstKey = FirstPath.ToStateKey(); - var secondKey = SecondPath.ToStateKey(); - var transactionExecutingStateSets = new List(); - var transactionExecutingStateSet = new TransactionExecutingStateSet - { - Writes = {{firstKey, FirstValue}}, - Deletes = {{secondKey, true}} - }; - transactionExecutingStateSets.Add(transactionExecutingStateSet); - transactionExecutingStateSet = new TransactionExecutingStateSet - { - Writes = {{secondKey, SecondValue}}, - Deletes = {{firstKey, true}} - }; - transactionExecutingStateSets.Add(transactionExecutingStateSet); - return transactionExecutingStateSets; - } + Changes = { { SecondPath.ToStateKey(), ThirdValue } } + }); + cache.Update(GetTransactionExecutingStateSets()); + cache.TryGetValue(SecondPath, out secondValue); + secondValue.ShouldBe(SecondValue.ToByteArray()); + } + + private IEnumerable GetTransactionExecutingStateSets() + { + var firstKey = FirstPath.ToStateKey(); + var secondKey = SecondPath.ToStateKey(); + var transactionExecutingStateSets = new List(); + var transactionExecutingStateSet = new TransactionExecutingStateSet + { + Writes = { { firstKey, FirstValue } }, + Deletes = { { secondKey, true } } + }; + transactionExecutingStateSets.Add(transactionExecutingStateSet); + transactionExecutingStateSet = new TransactionExecutingStateSet + { + Writes = { { secondKey, SecondValue } }, + Deletes = { { firstKey, true } } + }; + transactionExecutingStateSets.Add(transactionExecutingStateSet); + return transactionExecutingStateSets; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Extension/TaskExtensionTests.cs b/test/AElf.Kernel.SmartContract.Tests/Extension/TaskExtensionTests.cs index 532366da95..7f7765d445 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Extension/TaskExtensionTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Extension/TaskExtensionTests.cs @@ -3,114 +3,114 @@ using System.Threading.Tasks; using Xunit; -namespace AElf.Kernel.SmartContract.Extension +namespace AElf.Kernel.SmartContract.Extension; + +public class TaskExtensionTests { - public class TaskExtensionTests + private static int Counter { get; set; } + + [Fact] + public async Task Task_Extensions_Test_One_Cancellation() { - [Fact] - public async Task Task_Extensions_Test_One_Cancellation() - { - var ct = new CancellationTokenSource(100); - int times = 2; - var task = CountWithReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct.Token)); - } + var ct = new CancellationTokenSource(100); + var times = 2; + var task = CountWithReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct.Token)); + } - [Fact] - public async Task Task_Extensions_Test_One_Cancellation_NotCancelled() - { - var ct = new CancellationTokenSource(1000); - int times = 2; - var task = CountWithReturnAsync(times, 100); - int res = await task.WithCancellation(ct.Token); - Assert.Equal(times, res); - } + [Fact] + public async Task Task_Extensions_Test_One_Cancellation_NotCancelled() + { + var ct = new CancellationTokenSource(1000); + var times = 2; + var task = CountWithReturnAsync(times, 100); + var res = await task.WithCancellation(ct.Token); + Assert.Equal(times, res); + } - [Fact] - public async Task Task_Extensions_Test_Two_BothCanceled() - { - var ct1 = new CancellationTokenSource(100); - var ct2 = new CancellationTokenSource(100); - int times = 2; - var task = CountWithReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); - } + [Fact] + public async Task Task_Extensions_Test_Two_BothCanceled() + { + var ct1 = new CancellationTokenSource(100); + var ct2 = new CancellationTokenSource(100); + var times = 2; + var task = CountWithReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); + } - [Fact] - public async Task Task_Extensions_Test_Two_Cancellations() - { - var ct1 = new CancellationTokenSource(1000); - var ct2 = new CancellationTokenSource(100); - int times = 2; - var task = CountWithReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); - } + [Fact] + public async Task Task_Extensions_Test_Two_Cancellations() + { + var ct1 = new CancellationTokenSource(1000); + var ct2 = new CancellationTokenSource(100); + var times = 2; + var task = CountWithReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); + } - [Fact] - public async Task Task_Extensions_Test_Two_CancellationTask_Extensions_Test_Two_Cancellations_NotCanceleds_NotCanceled() - { - var ct1 = new CancellationTokenSource(10000); - var ct2 = new CancellationTokenSource(10000); - int times = 2; - var task = CountWithReturnAsync(times, 1000); - var res = await task.WithCancellation(ct1.Token, ct2.Token); - Assert.Equal(times, res); - } + [Fact] + public async Task + Task_Extensions_Test_Two_CancellationTask_Extensions_Test_Two_Cancellations_NotCanceleds_NotCanceled() + { + var ct1 = new CancellationTokenSource(10000); + var ct2 = new CancellationTokenSource(10000); + var times = 2; + var task = CountWithReturnAsync(times, 1000); + var res = await task.WithCancellation(ct1.Token, ct2.Token); + Assert.Equal(times, res); + } - [Fact] - public async Task Task_Extensions_Test_WithOneCancellation() - { - int times = 2; - var ct = new CancellationTokenSource(100); - var task = CountWithoutReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct.Token)); + [Fact] + public async Task Task_Extensions_Test_WithOneCancellation() + { + var times = 2; + var ct = new CancellationTokenSource(100); + var task = CountWithoutReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct.Token)); - Counter = 0; - var newCt = new CancellationTokenSource(1000); - var newTask = CountWithoutReturnAsync(times, 100); - await newTask.WithCancellation(newCt.Token); - Assert.Equal(times, Counter); - } + Counter = 0; + var newCt = new CancellationTokenSource(1000); + var newTask = CountWithoutReturnAsync(times, 100); + await newTask.WithCancellation(newCt.Token); + Assert.Equal(times, Counter); + } - [Fact] - public async Task Task_Extensions_Test_WithTwoCancellation() - { - int times = 2; - var ct1 = new CancellationTokenSource(100); - var ct2 = new CancellationTokenSource(100); - var task = CountWithoutReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); + [Fact] + public async Task Task_Extensions_Test_WithTwoCancellation() + { + var times = 2; + var ct1 = new CancellationTokenSource(100); + var ct2 = new CancellationTokenSource(100); + var task = CountWithoutReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); - ct1 = new CancellationTokenSource(1000); - ct2 = new CancellationTokenSource(100); - task = CountWithoutReturnAsync(times, 100); - await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); + ct1 = new CancellationTokenSource(1000); + ct2 = new CancellationTokenSource(100); + task = CountWithoutReturnAsync(times, 100); + await Assert.ThrowsAsync(() => task.WithCancellation(ct1.Token, ct2.Token)); - Counter = 0; - ct1 = new CancellationTokenSource(1000); - ct2 = new CancellationTokenSource(1000); - task = CountWithoutReturnAsync(times, 100); - await task.WithCancellation(ct1.Token, ct2.Token); - Assert.Equal(times, Counter); - } + Counter = 0; + ct1 = new CancellationTokenSource(1000); + ct2 = new CancellationTokenSource(1000); + task = CountWithoutReturnAsync(times, 100); + await task.WithCancellation(ct1.Token, ct2.Token); + Assert.Equal(times, Counter); + } - private async Task CountWithReturnAsync(int times, int waitingPeriodMilliSecond) + private async Task CountWithReturnAsync(int times, int waitingPeriodMilliSecond) + { + var i = 0; + while (i < times) { - int i = 0; - while (i < times) - { - await Task.Delay(waitingPeriodMilliSecond); - i++; - } - - return i; + await Task.Delay(waitingPeriodMilliSecond); + i++; } - private static int Counter { get; set; } + return i; + } - private async Task CountWithoutReturnAsync(int times, int waitingPeriodMilliSecond) - { - Counter = await CountWithReturnAsync(times, waitingPeriodMilliSecond); - } + private async Task CountWithoutReturnAsync(int times, int waitingPeriodMilliSecond) + { + Counter = await CountWithReturnAsync(times, waitingPeriodMilliSecond); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/HostSmartContractBridgeContextTests.cs b/test/AElf.Kernel.SmartContract.Tests/HostSmartContractBridgeContextTests.cs index 1e5c71ca3e..aa2df6aa7f 100644 --- a/test/AElf.Kernel.SmartContract.Tests/HostSmartContractBridgeContextTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/HostSmartContractBridgeContextTests.cs @@ -1,271 +1,268 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; using AElf.Cryptography; using AElf.Cryptography.ECDSA; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; -using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -using Org.BouncyCastle.Security; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class HostSmartContractBridgeContextTests : SmartContractRunnerTestBase { - public class HostSmartContractBridgeContextTests : SmartContractRunnerTestBase + private readonly IBlockchainService _blockchainService; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ECKeyPair _keyPair; + private readonly ISmartContractAddressService _smartContractAddressService; + + private IHostSmartContractBridgeContext _bridgeContext; + + public HostSmartContractBridgeContextTests() { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly ECKeyPair _keyPair; - private readonly KernelTestHelper _kernelTestHelper; + _blockchainService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _defaultContractZeroCodeProvider = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _keyPair = CryptoHelper.GenerateKeyPair(); + _bridgeContext = CreateNewContext(); + } - private IHostSmartContractBridgeContext _bridgeContext; + [Fact] + public void Recover_Context_PublicKey_Success() + { + var recoverPublicKey = _bridgeContext.RecoverPublicKey(); + recoverPublicKey.ShouldNotBeNull(); + recoverPublicKey.ShouldBe(_keyPair.PublicKey); + } - public HostSmartContractBridgeContextTests() - { - _blockchainService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _defaultContractZeroCodeProvider = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _keyPair = CryptoHelper.GenerateKeyPair(); - _bridgeContext = CreateNewContext(); - } - - [Fact] - public void Recover_Context_PublicKey_Success() - { - var recoverPublicKey = _bridgeContext.RecoverPublicKey(); - recoverPublicKey.ShouldNotBeNull(); - recoverPublicKey.ShouldBe(_keyPair.PublicKey); - } + [Fact] + public void Send_Inline_Success() + { + var to = SampleAddress.AddressList[0]; + var methodName = "TestSendInline"; + var arg = "Arg"; + var argBytes = new StringValue { Value = arg }.ToByteString(); + _bridgeContext.SendInline(to, methodName, argBytes); + + var inlineTransaction = _bridgeContext.TransactionContext.Trace.InlineTransactions; + inlineTransaction.Count.ShouldBe(1); + inlineTransaction[0].From.ShouldBe(_bridgeContext.Self); + inlineTransaction[0].To.ShouldBe(to); + inlineTransaction[0].MethodName.ShouldBe(methodName); + inlineTransaction[0].Params.ShouldBe(argBytes); + } - [Fact] - public void Send_Inline_Success() - { - var to = SampleAddress.AddressList[0]; - var methodName = "TestSendInline"; - var arg = "Arg"; - var argBytes = new StringValue {Value = arg}.ToByteString(); - _bridgeContext.SendInline(to, methodName, argBytes); - - var inlineTransaction = _bridgeContext.TransactionContext.Trace.InlineTransactions; - inlineTransaction.Count.ShouldBe(1); - inlineTransaction[0].From.ShouldBe(_bridgeContext.Self); - inlineTransaction[0].To.ShouldBe(to); - inlineTransaction[0].MethodName.ShouldBe(methodName); - inlineTransaction[0].Params.ShouldBe(argBytes); - } - - [Fact] - public void Send_VirtualInline_Success() - { - var from = HashHelper.ComputeFrom("hash"); - var to = SampleAddress.AddressList[0]; - var methodName = "TestVirtualInline"; - var arg = "Arg"; - var argBytes = new StringValue {Value = arg}.ToByteString(); - _bridgeContext.SendVirtualInline(from, to, methodName, argBytes); - - var inlineTransaction = _bridgeContext.TransactionContext.Trace.InlineTransactions; - inlineTransaction.Count.ShouldBe(1); - inlineTransaction[0].From.ShouldNotBe(_bridgeContext.Self); - inlineTransaction[0].To.ShouldBe(to); - inlineTransaction[0].MethodName.ShouldBe(methodName); - inlineTransaction[0].Params.ShouldBe(argBytes); - } - - [Fact] - public void Get_GetPreviousTransactions_Success() - { - var transaction = GetNewTransaction(); + [Fact] + public void Send_VirtualInline_Success() + { + var from = HashHelper.ComputeFrom("hash"); + var to = SampleAddress.AddressList[0]; + var methodName = "TestVirtualInline"; + var arg = "Arg"; + var argBytes = new StringValue { Value = arg }.ToByteString(); + _bridgeContext.SendVirtualInline(from, to, methodName, argBytes); + + var inlineTransaction = _bridgeContext.TransactionContext.Trace.InlineTransactions; + inlineTransaction.Count.ShouldBe(1); + inlineTransaction[0].From.ShouldNotBe(_bridgeContext.Self); + inlineTransaction[0].To.ShouldBe(to); + inlineTransaction[0].MethodName.ShouldBe(methodName); + inlineTransaction[0].Params.ShouldBe(argBytes); + } + + [Fact] + public void Get_GetPreviousTransactions_Success() + { + var transaction = GetNewTransaction(); - var newBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List {transaction}); + var newBlock = _kernelTestHelper.GenerateBlock(0, Hash.Empty, new List { transaction }); - _blockchainService.AddTransactionsAsync(new List {transaction}); - _blockchainService.AddBlockAsync(newBlock); + _blockchainService.AddTransactionsAsync(new List { transaction }); + _blockchainService.AddBlockAsync(newBlock); - _bridgeContext.TransactionContext.PreviousBlockHash = newBlock.GetHash(); + _bridgeContext.TransactionContext.PreviousBlockHash = newBlock.GetHash(); - var previousBlockTransactions = _bridgeContext.GetPreviousBlockTransactions(); + var previousBlockTransactions = _bridgeContext.GetPreviousBlockTransactions(); - previousBlockTransactions.ShouldNotBeNull(); - previousBlockTransactions.ShouldContain(transaction); - } + previousBlockTransactions.ShouldNotBeNull(); + previousBlockTransactions.ShouldContain(transaction); + } + + [Fact] + public void Verify_Signature_NoSignature_ReturnFalse() + { + var tx = new Transaction(); + var verifyResult = _bridgeContext.VerifySignature(tx); + verifyResult.ShouldBe(false); + } - [Fact] - public void Verify_Signature_NoSignature_ReturnFalse() + [Fact] + public void Verify_Signature_SingleSignature_ReturnTrue() + { + var tx = new Transaction { - var tx = new Transaction(); - var verifyResult = _bridgeContext.VerifySignature(tx); - verifyResult.ShouldBe(false); - } + From = Address.FromPublicKey(_keyPair.PublicKey), + To = SampleAddress.AddressList[0], + MethodName = "TestMethod", + Params = ByteString.CopyFrom(new byte[10]), + RefBlockNumber = 1, + RefBlockPrefix = ByteString.CopyFrom(new byte[4]) + }; + var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, tx.GetHash().ToByteArray()); + tx.Signature = ByteString.CopyFrom(signature); + + var verifyResult = _bridgeContext.VerifySignature(tx); + verifyResult.ShouldBe(true); + } + + [Fact] + public void Verify_Signature_SingleSignature_ReturnFalse() + { + var tx = GetNewTransaction(); + + var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, tx.GetHash().ToByteArray()); + tx.Signature = ByteString.CopyFrom(signature); + + var verifyResult = _bridgeContext.VerifySignature(tx); + verifyResult.ShouldBe(false); + } - [Fact] - public void Verify_Signature_SingleSignature_ReturnTrue() + [Fact] + public void Deploy_Contract_ThrowNoPermissionException() + { + Should.Throw(() => + _bridgeContext.DeployContract(_smartContractAddressService.GetZeroSmartContractAddress(), + new SmartContractRegistration(), null)); + } + + [Fact] + public void Deploy_Contract_Success() + { + _bridgeContext.TransactionContext.Transaction = new Transaction { - var tx = new Transaction - { - From = Address.FromPublicKey(_keyPair.PublicKey), - To = SampleAddress.AddressList[0], - MethodName = "TestMethod", - Params = ByteString.CopyFrom(new byte[10]), - RefBlockNumber = 1, - RefBlockPrefix = ByteString.CopyFrom(new byte[4]) - }; - var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, tx.GetHash().ToByteArray()); - tx.Signature = ByteString.CopyFrom(signature); - - var verifyResult = _bridgeContext.VerifySignature(tx); - verifyResult.ShouldBe(true); - } - - [Fact] - public void Verify_Signature_SingleSignature_ReturnFalse() + To = _smartContractAddressService.GetZeroSmartContractAddress() + }; + + var registration = new SmartContractRegistration { - var tx = GetNewTransaction(); + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.Empty, + CodeHash = HashHelper.ComputeFrom("hash") + }; - var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, tx.GetHash().ToByteArray()); - tx.Signature = ByteString.CopyFrom(signature); + _bridgeContext.DeployContract(SampleAddress.AddressList[0], registration, + HashHelper.ComputeFrom(registration.CodeHash)); + } - var verifyResult = _bridgeContext.VerifySignature(tx); - verifyResult.ShouldBe(false); - } + [Fact] + public void Update_Contract_Success() + { + _bridgeContext.TransactionContext.Transaction = new Transaction + { + To = _smartContractAddressService.GetZeroSmartContractAddress() + }; - [Fact] - public void Deploy_Contract_ThrowNoPermissionException() + var registration = new SmartContractRegistration { - Should.Throw(() => - _bridgeContext.DeployContract(_smartContractAddressService.GetZeroSmartContractAddress(), - new SmartContractRegistration(), null)); - } + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.Empty, + CodeHash = Hash.Empty + }; + + _bridgeContext.UpdateContract(SampleAddress.AddressList[0], registration, null); + } - [Fact] - public void Deploy_Contract_Success() + [Fact] + public void Update_Contract_WithoutPermission() + { + _bridgeContext.TransactionContext.Transaction = new Transaction { - _bridgeContext.TransactionContext.Transaction = new Transaction() - { - To = _smartContractAddressService.GetZeroSmartContractAddress() - }; - - var registration = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.Empty, - CodeHash = HashHelper.ComputeFrom("hash") - }; - - _bridgeContext.DeployContract(SampleAddress.AddressList[0], registration, HashHelper.ComputeFrom(registration.CodeHash)); - } - - [Fact] - public void Update_Contract_Success() + To = SampleAddress.AddressList[0] + }; + + var registration = new SmartContractRegistration { - _bridgeContext.TransactionContext.Transaction = new Transaction() - { - To = _smartContractAddressService.GetZeroSmartContractAddress() - }; - - var registration = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.Empty, - CodeHash = Hash.Empty - }; + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.Empty, + CodeHash = Hash.Empty + }; + Should.Throw(() => + { _bridgeContext.UpdateContract(SampleAddress.AddressList[0], registration, null); - } + }); + } - [Fact] - public void Update_Contract_WithoutPermission() - { - _bridgeContext.TransactionContext.Transaction = new Transaction() - { - To = SampleAddress.AddressList[0] - }; - - var registration = new SmartContractRegistration - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.Empty, - CodeHash = Hash.Empty - }; - - Should.Throw(() => - { - _bridgeContext.UpdateContract(SampleAddress.AddressList[0], registration, null); - }); - } - - [Fact] - public void Test_OriginTransactionId() - { - var hostSmartContractBridgeContext = CreateNewContext(); - hostSmartContractBridgeContext.OriginTransactionId.ShouldBe(_bridgeContext.TransactionContext - .OriginTransactionId); - hostSmartContractBridgeContext.OriginTransactionId.ShouldBe(_bridgeContext.TransactionContext.Transaction - .GetHash()); - } - - [Fact] - public void Test_GenerateId() + [Fact] + public void Test_OriginTransactionId() + { + var hostSmartContractBridgeContext = CreateNewContext(); + hostSmartContractBridgeContext.OriginTransactionId.ShouldBe(_bridgeContext.TransactionContext + .OriginTransactionId); + hostSmartContractBridgeContext.OriginTransactionId.ShouldBe(_bridgeContext.TransactionContext.Transaction + .GetHash()); + } + + [Fact] + public void Test_GenerateId() + { + var hostSmartContractBridgeContext = CreateNewContext(); + Should.NotThrow(() => hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], null)); + var bytes = new List { 0x01 }; + Should.Throw(() => hostSmartContractBridgeContext.GenerateId(null, bytes)); + var res1 = hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], bytes); + var res2 = hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], bytes.ToArray()); + res1.ShouldBe(res2); + } + + private IHostSmartContractBridgeContext CreateNewContext() + { + _bridgeContext = GetRequiredService(); + + var transaction = new Transaction { - var hostSmartContractBridgeContext = CreateNewContext(); - Should.NotThrow(() => hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], null)); - var bytes = new List {0x01}; - Should.Throw(() => hostSmartContractBridgeContext.GenerateId(null, bytes)); - var res1 = hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], bytes); - var res2 = hostSmartContractBridgeContext.GenerateId(SampleAddress.AddressList[0], bytes.ToArray()); - res1.ShouldBe(res2); - } - - private IHostSmartContractBridgeContext CreateNewContext() + From = Address.FromPublicKey(_keyPair.PublicKey), + To = SampleAddress.AddressList[0], + MethodName = "Test", + Params = ByteString.CopyFrom(new byte[10]), + RefBlockNumber = 1, + RefBlockPrefix = ByteString.CopyFrom(new byte[4]) + }; + var transactionContext = new TransactionContext { - _bridgeContext = GetRequiredService(); - - var transaction = new Transaction() - { - From = Address.FromPublicKey(_keyPair.PublicKey), - To = SampleAddress.AddressList[0], - MethodName = "Test", - Params = ByteString.CopyFrom(new byte[10]), - RefBlockNumber = 1, - RefBlockPrefix = ByteString.CopyFrom(new byte[4]) - }; - var transactionContext = new TransactionContext() - { - Transaction = transaction, - BlockHeight = 3, - CurrentBlockTime = TimestampHelper.GetUtcNow(), - PreviousBlockHash = Hash.Empty, - Trace = new TransactionTrace(), - StateCache = new NullStateCache(), - OriginTransactionId = transaction.GetHash() - }; - var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, transactionContext.Transaction - .GetHash().ToByteArray()); - transactionContext.Transaction.Signature = ByteString.CopyFrom(signature); - _bridgeContext.Initialize(transactionContext); - - return _bridgeContext; - } - - private Transaction GetNewTransaction() + Transaction = transaction, + BlockHeight = 3, + CurrentBlockTime = TimestampHelper.GetUtcNow(), + PreviousBlockHash = Hash.Empty, + Trace = new TransactionTrace(), + StateCache = new NullStateCache(), + OriginTransactionId = transaction.GetHash() + }; + var signature = CryptoHelper.SignWithPrivateKey(_keyPair.PrivateKey, transactionContext.Transaction + .GetHash().ToByteArray()); + transactionContext.Transaction.Signature = ByteString.CopyFrom(signature); + _bridgeContext.Initialize(transactionContext); + + return _bridgeContext; + } + + private Transaction GetNewTransaction() + { + var tx = new Transaction { - var tx = new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[1], - MethodName = Guid.NewGuid().ToString(), - Params = ByteString.CopyFrom(new byte[10]), - RefBlockNumber = 1, - RefBlockPrefix = ByteString.CopyFrom(new byte[4]) - }; - return tx; - } + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[1], + MethodName = Guid.NewGuid().ToString(), + Params = ByteString.CopyFrom(new byte[10]), + RefBlockNumber = 1, + RefBlockPrefix = ByteString.CopyFrom(new byte[4]) + }; + return tx; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Infrastructure/SmartContractRunnerContainerTests.cs b/test/AElf.Kernel.SmartContract.Tests/Infrastructure/SmartContractRunnerContainerTests.cs index a801ccbb50..49f4a8341e 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Infrastructure/SmartContractRunnerContainerTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Infrastructure/SmartContractRunnerContainerTests.cs @@ -1,85 +1,82 @@ -using System; -using System.Threading.Tasks; using Moq; using Org.BouncyCastle.Security; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract.Infrastructure +namespace AElf.Kernel.SmartContract.Infrastructure; + +public class SmartContractRunnerContainerTests : SmartContractRunnerTestBase { - public class SmartContractRunnerContainerTests : SmartContractRunnerTestBase + private readonly SmartContractRunnerContainer _smartContractRunnerContainer; + + public SmartContractRunnerContainerTests() + { + _smartContractRunnerContainer = GetRequiredService(); + } + + [Fact] + public void Get_Runner_ReturnRunner() + { + var runner = _smartContractRunnerContainer.GetRunner(KernelConstants.DefaultRunnerCategory); + + runner.ShouldNotBeNull(); + } + + [Fact] + public void Get_Runner_ThrowInvalidParameterException() { - private readonly SmartContractRunnerContainer _smartContractRunnerContainer; - - public SmartContractRunnerContainerTests() - { - _smartContractRunnerContainer = GetRequiredService(); - } - - [Fact] - public void Get_Runner_ReturnRunner() - { - var runner = _smartContractRunnerContainer.GetRunner(KernelConstants.DefaultRunnerCategory); - - runner.ShouldNotBeNull(); - } - - [Fact] - public void Get_Runner_ThrowInvalidParameterException() - { - Assert.Throws - ( - () => _smartContractRunnerContainer.GetRunner(7) - ); - } - - [Fact] - public void Add_Runner_Success() - { - var mockSmartContractRunner = new Mock(); - _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); - - var runner = _smartContractRunnerContainer.GetRunner(5); - - runner.ShouldNotBeNull(); - } - - [Fact] - public void Add_Runner_ThrowInvalidParameterException() - { - var mockSmartContractRunner = new Mock(); - _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); - - Assert.Throws - ( - () => _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object) - ); - } - - [Fact] - public void Update_Runner_Success() - { - var mockSmartContractRunner = new Mock(); - _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); - - var mockSmartContractRunnerNew = new Mock(); - _smartContractRunnerContainer.UpdateRunner(5,mockSmartContractRunnerNew.Object); - - var runner = _smartContractRunnerContainer.GetRunner(5); - runner.ShouldNotBeSameAs(mockSmartContractRunner.Object); - runner.ShouldBeSameAs(mockSmartContractRunnerNew.Object); - } - - [Fact] - public void Update_Runner_Fail() - { - var mockSmartContractRunner = new Mock(); - _smartContractRunnerContainer.UpdateRunner(5, mockSmartContractRunner.Object); - - Assert.Throws - ( - () => _smartContractRunnerContainer.GetRunner(5) - ); - } + Assert.Throws + ( + () => _smartContractRunnerContainer.GetRunner(7) + ); + } + + [Fact] + public void Add_Runner_Success() + { + var mockSmartContractRunner = new Mock(); + _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); + + var runner = _smartContractRunnerContainer.GetRunner(5); + + runner.ShouldNotBeNull(); + } + + [Fact] + public void Add_Runner_ThrowInvalidParameterException() + { + var mockSmartContractRunner = new Mock(); + _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); + + Assert.Throws + ( + () => _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object) + ); + } + + [Fact] + public void Update_Runner_Success() + { + var mockSmartContractRunner = new Mock(); + _smartContractRunnerContainer.AddRunner(5, mockSmartContractRunner.Object); + + var mockSmartContractRunnerNew = new Mock(); + _smartContractRunnerContainer.UpdateRunner(5, mockSmartContractRunnerNew.Object); + + var runner = _smartContractRunnerContainer.GetRunner(5); + runner.ShouldNotBeSameAs(mockSmartContractRunner.Object); + runner.ShouldBeSameAs(mockSmartContractRunnerNew.Object); + } + + [Fact] + public void Update_Runner_Fail() + { + var mockSmartContractRunner = new Mock(); + _smartContractRunnerContainer.UpdateRunner(5, mockSmartContractRunner.Object); + + Assert.Throws + ( + () => _smartContractRunnerContainer.GetRunner(5) + ); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/LogEventTestAElfModule.cs b/test/AElf.Kernel.SmartContract.Tests/LogEventTestAElfModule.cs index 0d67f5f2e2..80c4c7559c 100644 --- a/test/AElf.Kernel.SmartContract.Tests/LogEventTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContract.Tests/LogEventTestAElfModule.cs @@ -3,15 +3,14 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +[DependsOn( + typeof(SmartContractTestAElfModule))] +public class LogEventTestAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractTestAElfModule))] - public class LogEventTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/Sdk/CacheProviderTests.cs b/test/AElf.Kernel.SmartContract.Tests/Sdk/CacheProviderTests.cs index 4fccf3c052..26794dd03c 100644 --- a/test/AElf.Kernel.SmartContract.Tests/Sdk/CacheProviderTests.cs +++ b/test/AElf.Kernel.SmartContract.Tests/Sdk/CacheProviderTests.cs @@ -3,122 +3,120 @@ using AElf.Kernel.SmartContract.Domain; using AElf.Types; using Google.Protobuf; -using QuickGraph; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public sealed class CacheProviderTests : SmartContractTestBase { - public sealed class CacheProviderTests : SmartContractTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; + private readonly IStateProviderFactory _providerFactory; + private readonly SmartContractHelper _smartContractHelper; + private readonly ScopedStateProvider _innerProvider; + + public CacheProviderTests() { - private readonly IStateProviderFactory _providerFactory; - private ScopedStateProvider _innerProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly SmartContractHelper _smartContractHelper; - private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; + _providerFactory = GetRequiredService(); + _innerProvider = _providerFactory.CreateStateProvider() as ScopedStateProvider; + _blockStateSetManger = GetRequiredService(); + _smartContractHelper = GetRequiredService(); + _hostSmartContractBridgeContextService = GetRequiredService(); + } - public CacheProviderTests() - { - _providerFactory = GetRequiredService(); - _innerProvider = _providerFactory.CreateStateProvider() as ScopedStateProvider; - _blockStateSetManger = GetRequiredService(); - _smartContractHelper = GetRequiredService(); - _hostSmartContractBridgeContextService = GetRequiredService(); - } + [Fact] + public async Task TryGetValue_Test() + { + var cachedStateProvider = await GenerateStateProviderAsync(); - [Fact] - public async Task TryGetValue_Test() + var result = cachedStateProvider.Get(new StatePath { - var cachedStateProvider = await GenerateStateProviderAsync(); - - var result = cachedStateProvider.Get(new StatePath - { - Parts = {"test1"} - }); - result.Length.ShouldBe(4); - result.ShouldBe(new byte[] {0, 1, 2, 3}); + Parts = { "test1" } + }); + result.Length.ShouldBe(4); + result.ShouldBe(new byte[] { 0, 1, 2, 3 }); - result = cachedStateProvider.Get(new StatePath - { - Parts = {"test2"} - }); - result.Length.ShouldBe(4); - result.ShouldBe(new byte[] {1, 2, 3, 4}); + result = cachedStateProvider.Get(new StatePath + { + Parts = { "test2" } + }); + result.Length.ShouldBe(4); + result.ShouldBe(new byte[] { 1, 2, 3, 4 }); - result = cachedStateProvider.Get(new StatePath - { - Parts = {"test3"} - }); - result.ShouldBe(null); - } + result = cachedStateProvider.Get(new StatePath + { + Parts = { "test3" } + }); + result.ShouldBe(null); + } - private async Task GenerateStateProviderAsync() + private async Task GenerateStateProviderAsync() + { + var chain = await _smartContractHelper.CreateChainAsync(); + var smartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + smartContractBridgeContext.TransactionContext = new TransactionContext { - var chain = await _smartContractHelper.CreateChainAsync(); - var smartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - smartContractBridgeContext.TransactionContext = new TransactionContext + Transaction = new Transaction { - Transaction = new Transaction - { - To = SampleAddress.AddressList[0] - }, - BlockHeight = chain.BestChainHeight, - PreviousBlockHash = chain.BestChainHash - }; - _innerProvider.ContractAddress = SampleAddress.AddressList[0]; - _innerProvider.HostSmartContractBridgeContext = smartContractBridgeContext; - var statePath = new ScopedStatePath + To = SampleAddress.AddressList[0] + }, + BlockHeight = chain.BestChainHeight, + PreviousBlockHash = chain.BestChainHash + }; + _innerProvider.ContractAddress = SampleAddress.AddressList[0]; + _innerProvider.HostSmartContractBridgeContext = smartContractBridgeContext; + var statePath = new ScopedStatePath + { + Address = _innerProvider.ContractAddress, + Path = new StatePath { - Address = _innerProvider.ContractAddress, - Path = new StatePath - { - Parts = {"test2"} - } - }; - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + Parts = { "test2" } + } + }; + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight, + Changes = { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight, - Changes = { - { - statePath.ToStateKey(), ByteString.CopyFrom(1, 2, 3, 4) - } + statePath.ToStateKey(), ByteString.CopyFrom(1, 2, 3, 4) } - }); - - var cachedStateProvider = new CachedStateProvider(_innerProvider); - var cacheProvider = cachedStateProvider as CachedStateProvider; - cacheProvider.Cache[new ScopedStatePath + } + }); + + var cachedStateProvider = new CachedStateProvider(_innerProvider); + var cacheProvider = cachedStateProvider; + cacheProvider.Cache[new ScopedStatePath + { + Address = _innerProvider.ContractAddress, + Path = new StatePath { - Address = _innerProvider.ContractAddress, - Path = new StatePath - { - Parts = {"test1"} - } - }] = new byte[] {0, 1, 2, 3}; + Parts = { "test1" } + } + }] = new byte[] { 0, 1, 2, 3 }; - return cachedStateProvider; - } + return cachedStateProvider; } +} - public sealed class NullStateCacheTests +public sealed class NullStateCacheTests +{ + [Fact] + public void TryGetValue_Test() { - [Fact] - public void TryGetValue_Test() + var stateCache = new NullStateCache(); + var scopedStatePath = new ScopedStatePath { - var stateCache = new NullStateCache(); - var scopedStatePath = new ScopedStatePath - { - Address = SampleAddress.AddressList[0], - Path = new StatePath() - }; - stateCache.TryGetValue(scopedStatePath, out var value).ShouldBeFalse(); - value.ShouldBeNull(); - - stateCache[scopedStatePath].ShouldBeNull(); - stateCache[scopedStatePath] = new byte[0]; - stateCache[scopedStatePath].ShouldBeNull(); - } + Address = SampleAddress.AddressList[0], + Path = new StatePath() + }; + stateCache.TryGetValue(scopedStatePath, out var value).ShouldBeFalse(); + value.ShouldBeNull(); + + stateCache[scopedStatePath].ShouldBeNull(); + stateCache[scopedStatePath] = new byte[0]; + stateCache[scopedStatePath].ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/SmartContractHelper.cs b/test/AElf.Kernel.SmartContract.Tests/SmartContractHelper.cs index fc84fb7823..d775435a18 100644 --- a/test/AElf.Kernel.SmartContract.Tests/SmartContractHelper.cs +++ b/test/AElf.Kernel.SmartContract.Tests/SmartContractHelper.cs @@ -11,108 +11,105 @@ using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; -using Mono.Cecil.Cil; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class SmartContractHelper { - public class SmartContractHelper + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITransactionExecutingService _transactionExecutingService; + private readonly ITransactionResultManager _transactionResultManager; + + internal IReadOnlyDictionary Codes; + + public SmartContractHelper(ITransactionExecutingService transactionExecutingService, + IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, IBlockStateSetManger blockStateSetManger, + IBlockchainService blockchainService, ITransactionResultManager transactionResultManager, + KernelTestHelper kernelTestHelper) { - private readonly ITransactionExecutingService _transactionExecutingService; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionResultManager _transactionResultManager; - private readonly KernelTestHelper _kernelTestHelper; - - internal IReadOnlyDictionary Codes; + _transactionExecutingService = transactionExecutingService; + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + _blockStateSetManger = blockStateSetManger; + _blockchainService = blockchainService; + _transactionResultManager = transactionResultManager; + _kernelTestHelper = kernelTestHelper; + Codes = ContractsDeployer.GetContractCodes(); + } - public SmartContractHelper(ITransactionExecutingService transactionExecutingService, - IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, IBlockStateSetManger blockStateSetManger, - IBlockchainService blockchainService, ITransactionResultManager transactionResultManager, - KernelTestHelper kernelTestHelper) - { - _transactionExecutingService = transactionExecutingService; - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - _blockStateSetManger = blockStateSetManger; - _blockchainService = blockchainService; - _transactionResultManager = transactionResultManager; - _kernelTestHelper = kernelTestHelper; - Codes = ContractsDeployer.GetContractCodes(); - } + internal async Task GenerateBlockAsync(long previousBlockHeight, Hash previousBlockHash, + List transactions = null) + { + var block = _kernelTestHelper.GenerateBlock(previousBlockHeight, previousBlockHash, transactions); + await _blockchainService.AddBlockAsync(block); + await _blockchainService.AddTransactionsAsync(transactions); + return block; + } - internal async Task GenerateBlockAsync(long previousBlockHeight, Hash previousBlockHash, - List transactions = null) - { - var block = _kernelTestHelper.GenerateBlock(previousBlockHeight, previousBlockHash, transactions); - await _blockchainService.AddBlockAsync(block); - await _blockchainService.AddTransactionsAsync(transactions); - return block; - } - - internal Transaction BuildDeploySystemSmartContractTransaction(Hash contractName,byte[] contractCode) - { - var address = _defaultContractZeroCodeProvider.ContractZeroAddress; - return new Transaction - { - From = address, - To = address, - MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), - Params = new SystemContractDeploymentInput - { - Category = 0, - Code = ByteString.CopyFrom(contractCode), - Name = contractName - }.ToByteString() - }; - } - - internal async Task MineBlockAsync(Block block) + internal Transaction BuildDeploySystemSmartContractTransaction(Hash contractName, byte[] contractCode) + { + var address = _defaultContractZeroCodeProvider.ContractZeroAddress; + return new Transaction { - var transactions = block.Body.TransactionIds.Count > 0 - ? await _blockchainService.GetTransactionsAsync(block.TransactionIds) - : new List(); - var executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto + From = address, + To = address, + MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), + Params = new SystemContractDeploymentInput { - BlockHeader = block.Header, - Transactions = transactions, - }, CancellationToken.None); + Category = 0, + Code = ByteString.CopyFrom(contractCode), + Name = contractName + }.ToByteString() + }; + } - await _transactionResultManager.AddTransactionResultsAsync( - executionReturnSets.Select(s => s.TransactionResult).ToList(), block.GetHash()); - - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - PreviousHash = block.Header.PreviousBlockHash, - BlockHeight = block.Height - }; - foreach (var stateChange in executionReturnSets.SelectMany(executionReturnSet => executionReturnSet.StateChanges)) - { - blockStateSet.Changes[stateChange.Key] = stateChange.Value; - } + internal async Task MineBlockAsync(Block block) + { + var transactions = block.Body.TransactionIds.Count > 0 + ? await _blockchainService.GetTransactionsAsync(block.TransactionIds) + : new List(); + var executionReturnSets = await _transactionExecutingService.ExecuteAsync(new TransactionExecutingDto + { + BlockHeader = block.Header, + Transactions = transactions + }, CancellationToken.None); - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - } + await _transactionResultManager.AddTransactionResultsAsync( + executionReturnSets.Select(s => s.TransactionResult).ToList(), block.GetHash()); - internal async Task CreateChainWithGenesisContractAsync() - { - _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(null); - var chain = await _kernelTestHelper.CreateChain(); - var transaction = BuildDeploySystemSmartContractTransaction(ZeroSmartContractAddressNameProvider.Name, - Codes["AElf.Contracts.Genesis"]); - var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); - block.Body.TransactionIds.Add(transaction.GetHash()); - await _blockchainService.AddTransactionsAsync(new[] {transaction}); - await MineBlockAsync(block); - return chain; - } - - internal async Task CreateChainAsync() + var blockStateSet = new BlockStateSet { - var chain = await _kernelTestHelper.CreateChain(); - var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); - await MineBlockAsync(block); - return chain; - } + BlockHash = block.GetHash(), + PreviousHash = block.Header.PreviousBlockHash, + BlockHeight = block.Height + }; + foreach (var stateChange in executionReturnSets.SelectMany( + executionReturnSet => executionReturnSet.StateChanges)) + blockStateSet.Changes[stateChange.Key] = stateChange.Value; + + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + } + + internal async Task CreateChainWithGenesisContractAsync() + { + _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(null); + var chain = await _kernelTestHelper.CreateChain(); + var transaction = BuildDeploySystemSmartContractTransaction(ZeroSmartContractAddressNameProvider.Name, + Codes["AElf.Contracts.Genesis"]); + var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); + block.Body.TransactionIds.Add(transaction.GetHash()); + await _blockchainService.AddTransactionsAsync(new[] { transaction }); + await MineBlockAsync(block); + return chain; + } + + internal async Task CreateChainAsync() + { + var chain = await _kernelTestHelper.CreateChain(); + var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); + await MineBlockAsync(block); + return chain; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/SmartContractRunnerTestAElfModule.cs b/test/AElf.Kernel.SmartContract.Tests/SmartContractRunnerTestAElfModule.cs index f27d819c02..08ea682d21 100644 --- a/test/AElf.Kernel.SmartContract.Tests/SmartContractRunnerTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContract.Tests/SmartContractRunnerTestAElfModule.cs @@ -1,6 +1,5 @@ using System.Threading.Tasks; using AElf.Kernel.Account.Application; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Modularity; using AElf.Types; @@ -8,27 +7,26 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +[DependsOn( + typeof(SmartContractTestAElfModule))] +public class SmartContractRunnerTestAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractTestAElfModule))] - public class SmartContractRunnerTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddTransient(p => - { - var mockExecutive = new Mock(); + services.AddTransient(p => + { + var mockExecutive = new Mock(); - var mockSmartContractRunner = new Mock(); - mockSmartContractRunner.SetupGet(m => m.Category).Returns(KernelConstants.DefaultRunnerCategory); - mockSmartContractRunner.Setup(m => m.RunAsync(It.IsAny())) - .Returns(Task.FromResult(mockExecutive.Object)); - return mockSmartContractRunner.Object; - }); - services.AddSingleton(); - } + var mockSmartContractRunner = new Mock(); + mockSmartContractRunner.SetupGet(m => m.Category).Returns(KernelConstants.DefaultRunnerCategory); + mockSmartContractRunner.Setup(m => m.RunAsync(It.IsAny())) + .Returns(Task.FromResult(mockExecutive.Object)); + return mockSmartContractRunner.Object; + }); + services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/SmartContractTestAElfModule.cs b/test/AElf.Kernel.SmartContract.Tests/SmartContractTestAElfModule.cs index c99f999713..a8281410b4 100644 --- a/test/AElf.Kernel.SmartContract.Tests/SmartContractTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContract.Tests/SmartContractTestAElfModule.cs @@ -1,32 +1,28 @@ -using System.Collections.Generic; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Modularity; using AElf.Runtime.CSharp; using Microsoft.Extensions.DependencyInjection; -using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +[DependsOn( + typeof(SmartContractAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(CSharpRuntimeAElfModule))] +public class SmartContractTestAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(CSharpRuntimeAElfModule))] - public class SmartContractTestAElfModule: AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + Configure(options => { - var services = context.Services; - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - Configure(options => - { - options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; - options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,STO,READ,NET"; - }); - } + options.ContextVariables[ContextVariableDictionary.NativeSymbolName] = "ELF"; + options.ContextVariables["SymbolListToPayTxFee"] = "WRITE,STO,READ,NET"; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/SmartContractTestBase.cs b/test/AElf.Kernel.SmartContract.Tests/SmartContractTestBase.cs index 184a233e46..693c0d04ee 100644 --- a/test/AElf.Kernel.SmartContract.Tests/SmartContractTestBase.cs +++ b/test/AElf.Kernel.SmartContract.Tests/SmartContractTestBase.cs @@ -1,17 +1,15 @@ -using System; -using AElf.TestBase; +using AElf.TestBase; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class SmartContractTestBase : AElfIntegratedTest +{ +} + +public class SmartContractRunnerTestBase : AElfIntegratedTest { - public class SmartContractTestBase : AElfIntegratedTest - { - } - - public class SmartContractRunnerTestBase : AElfIntegratedTest - { - } +} - public class LogEventTestBase : AElfIntegratedTest - { - } +public class LogEventTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/TestSmartContractNameProvider.cs b/test/AElf.Kernel.SmartContract.Tests/TestSmartContractNameProvider.cs index 9096577897..abadbd8ed7 100644 --- a/test/AElf.Kernel.SmartContract.Tests/TestSmartContractNameProvider.cs +++ b/test/AElf.Kernel.SmartContract.Tests/TestSmartContractNameProvider.cs @@ -2,13 +2,12 @@ using AElf.Types; using Volo.Abp.DependencyInjection; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class TestSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency { - public class TestSmartContractAddressNameProvider : ISmartContractAddressNameProvider, ISingletonDependency - { - public static readonly Hash Name = HashHelper.ComputeFrom("AElf.Contracts.Test"); - public static readonly string StringName = Name.ToStorageKey(); - public Hash ContractName => Name; - public string ContractStringName => StringName; - } + public static readonly Hash Name = HashHelper.ComputeFrom("AElf.Contracts.Test"); + public static readonly string StringName = Name.ToStorageKey(); + public Hash ContractName => Name; + public string ContractStringName => StringName; } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.Tests/UnitTestContractZeroCodeProvider.cs b/test/AElf.Kernel.SmartContract.Tests/UnitTestContractZeroCodeProvider.cs index 1e3795fdb2..8d6bdb8355 100644 --- a/test/AElf.Kernel.SmartContract.Tests/UnitTestContractZeroCodeProvider.cs +++ b/test/AElf.Kernel.SmartContract.Tests/UnitTestContractZeroCodeProvider.cs @@ -1,30 +1,28 @@ using System; using AElf.ContractDeployer; using AElf.Kernel.Blockchain.Infrastructure; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; using Google.Protobuf; using Microsoft.Extensions.Options; -namespace AElf.Kernel.SmartContract +namespace AElf.Kernel.SmartContract; + +public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider { - public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider + public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, + IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) { - public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, - IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) - { - } + } - public override void SetDefaultContractZeroRegistrationByType(Type defaultZero) + public override void SetDefaultContractZeroRegistrationByType(Type defaultZero) + { + var codes = ContractsDeployer.GetContractCodes(); + DefaultContractZeroRegistration = new SmartContractRegistration { - var codes = ContractsDeployer.GetContractCodes(); - DefaultContractZeroRegistration= new SmartContractRegistration - { - Category = GetCategory(), - Code = ByteString.CopyFrom(codes["AElf.Contracts.Genesis"]), - CodeHash = HashHelper.ComputeFrom(codes["AElf.Contracts.Genesis"]) - }; - } + Category = GetCategory(), + Code = ByteString.CopyFrom(codes["AElf.Contracts.Genesis"]), + CodeHash = HashHelper.ComputeFrom(codes["AElf.Contracts.Genesis"]) + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/Properties/InternalVisibleTo.cs b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/Properties/InternalVisibleTo.cs index c717c8cfa2..2f712fbc28 100644 --- a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/Properties/InternalVisibleTo.cs +++ b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/Properties/InternalVisibleTo.cs @@ -1,3 +1,3 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("AElf.Kernel.SmartContract.Parallel.Tests")] +[assembly: InternalsVisibleTo("AElf.Kernel.SmartContract.Parallel.Tests")] \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContract.cs b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContract.cs index 4cfd93ea05..d14dfe9b74 100644 --- a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContract.cs +++ b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContract.cs @@ -1,14 +1,13 @@ using AElf.Standards.ACS2; using AElf.Types; -namespace AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract +namespace AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract; + +public class TestContract : TestContractContainer.TestContractBase { - public class TestContract : TestContractContainer.TestContractBase + public override ResourceInfo GetResourceInfo(Transaction input) { - public override ResourceInfo GetResourceInfo(Transaction input) - { - // Just echo input params - return ResourceInfo.Parser.ParseFrom(input.Params); - } + // Just echo input params + return ResourceInfo.Parser.ParseFrom(input.Params); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContractState.cs b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContractState.cs index 9cf854f0f7..bd234cd627 100644 --- a/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContractState.cs +++ b/test/AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract/TestContractState.cs @@ -1,8 +1,7 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract +namespace AElf.Kernel.SmartContractExecution.Parallel.Tests.TestContract; + +public class TestContractState : ContractState { - public class TestContractState : ContractState - { - } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/AElf.Kernel.SmartContractExecution.Tests.csproj b/test/AElf.Kernel.SmartContractExecution.Tests/AElf.Kernel.SmartContractExecution.Tests.csproj index b3cc440791..d8edaff985 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/AElf.Kernel.SmartContractExecution.Tests.csproj +++ b/test/AElf.Kernel.SmartContractExecution.Tests/AElf.Kernel.SmartContractExecution.Tests.csproj @@ -5,17 +5,17 @@ false - - - - - - + + + + + + - - - + + + diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockAttachServiceTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockAttachServiceTests.cs index 37312b05e6..7a3d3d8577 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockAttachServiceTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockAttachServiceTests.cs @@ -1,74 +1,73 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Cryptography; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class BlockAttachServiceTests : SmartContractExecutionTestBase { - public sealed class BlockAttachServiceTests : SmartContractExecutionTestBase + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + + public BlockAttachServiceTests() { - private readonly IBlockAttachService _blockAttachService; - private readonly SmartContractExecutionHelper _smartContractExecutionHelper; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockchainService _blockchainService; - private readonly IBlockExecutingService _blockExecutingService; - private readonly ISmartContractAddressService _smartContractAddressService; + _blockAttachService = GetRequiredService(); + _smartContractExecutionHelper = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + } - public BlockAttachServiceTests() + [Fact] + public async Task AttachBlockAsync_Test() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + await _blockAttachService.AttachBlockAsync(_kernelTestHelper.GenerateBlock(0, Hash.Empty)); + + var blockHeader = new BlockHeader { - _blockAttachService = GetRequiredService(); - _smartContractExecutionHelper = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - } + Height = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash, + Time = TimestampHelper.GetUtcNow(), + SignerPubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) + }; - [Fact] - public async Task AttachBlockAsync_Test() + var transactions = new List { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - await _blockAttachService.AttachBlockAsync(_kernelTestHelper.GenerateBlock(0, Hash.Empty)); - - var blockHeader = new BlockHeader + new() { - Height = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash, - Time = TimestampHelper.GetUtcNow(), - SignerPubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) - }; - - var transactions = new List - { - new Transaction + From = _smartContractAddressService.GetZeroSmartContractAddress(), + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.DeploySmartContract), + Params = new ContractDeploymentInput { - From = _smartContractAddressService.GetZeroSmartContractAddress(), - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.DeploySmartContract), - Params = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom( - _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]) - }.ToByteString() - } - }; + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom( + _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]) + }.ToByteString() + } + }; + + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + await _blockchainService.AddBlockAsync(blockExecutedSet.Block); + _blockAttachService.AttachBlockAsync(blockExecutedSet.Block).ShouldThrow(); - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - await _blockchainService.AddBlockAsync(blockExecutedSet.Block); - _blockAttachService.AttachBlockAsync(blockExecutedSet.Block).ShouldThrow(); - - await _blockchainService.AddTransactionsAsync(transactions); - await _blockAttachService.AttachBlockAsync(blockExecutedSet.Block); - var newChain = await _blockchainService.GetChainAsync(); - newChain.BestChainHeight.ShouldBe(chain.BestChainHeight + 1); - } + await _blockchainService.AddTransactionsAsync(transactions); + await _blockAttachService.AttachBlockAsync(blockExecutedSet.Block); + var newChain = await _blockchainService.GetChainAsync(); + newChain.BestChainHeight.ShouldBe(chain.BestChainHeight + 1); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutingServiceTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutingServiceTests.cs index 70da94b456..68d2f4e0c0 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutingServiceTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutingServiceTests.cs @@ -1,148 +1,143 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Domain; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class BlockExecutingServiceTests : SmartContractExecutionTestBase { - public sealed class BlockExecutingServiceTests : SmartContractExecutionTestBase + private readonly BlockExecutingService _blockExecutingService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + private readonly ITransactionResultManager _transactionResultManager; + + public BlockExecutingServiceTests() { - private readonly BlockExecutingService _blockExecutingService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly SmartContractExecutionHelper _smartContractExecutionHelper; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly ITransactionResultManager _transactionResultManager; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; - - public BlockExecutingServiceTests() - { - _blockExecutingService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _smartContractExecutionHelper = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _transactionResultManager = GetRequiredService(); - _systemTransactionExtraDataProvider = GetRequiredService(); - } - - [Fact] - public async Task Execute_Block_NonCancellable_Without_SystemTransactionCount() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; - var transactions = GetTransactions(); - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - await CheckBlockExecutedSetAsync(blockExecutedSet, 2); - } - - [Fact] - public async Task Execute_Block_NonCancellable_With_SystemTransactionCount() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; - _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, blockHeader); - var transactions = GetTransactions(); - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - await CheckBlockExecutedSetAsync(blockExecutedSet, 2); - } - - [Fact] - public async Task Execute_Block_Cancellable_Empty() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); + _blockExecutingService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _smartContractExecutionHelper = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _transactionResultManager = GetRequiredService(); + _systemTransactionExtraDataProvider = GetRequiredService(); + } - var transactions = GetTransactions(); + [Fact] + public async Task Execute_Block_NonCancellable_Without_SystemTransactionCount() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; + var transactions = GetTransactions(); + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + await CheckBlockExecutedSetAsync(blockExecutedSet, 2); + } - var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; - var nonCancellableTxs = new[] {transactions[0]}; - var cancellableTxs = new Transaction[0]; + [Fact] + public async Task Execute_Block_NonCancellable_With_SystemTransactionCount() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; + _systemTransactionExtraDataProvider.SetSystemTransactionCount(1, blockHeader); + var transactions = GetTransactions(); + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + await CheckBlockExecutedSetAsync(blockExecutedSet, 2); + } - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, - cancellableTxs, CancellationToken.None); - await CheckBlockExecutedSetAsync(blockExecutedSet, 1); - } + [Fact] + public async Task Execute_Block_Cancellable_Empty() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); - [Fact] - public async Task Execute_Block_Cancellable_Cancelled() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - - var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; - var transactions = GetTransactions(); - var nonCancellableTxs = new[] {transactions[0]}; - var cancellableTxs = new[] {transactions[1]}; - var cancelToken = new CancellationTokenSource(); - cancelToken.Cancel(); - - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, - cancellableTxs, cancelToken.Token); - await CheckBlockExecutedSetAsync(blockExecutedSet, 1); - } - - [Fact] - public async Task Execute_Block_Cancellable() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); + var transactions = GetTransactions(); - var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; - var transactions = GetTransactions(); - var nonCancellableTxs = new[] {transactions[0]}; - var cancellableTxs = new[] {transactions[1]}; + var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; + var nonCancellableTxs = new[] { transactions[0] }; + var cancellableTxs = new Transaction[0]; - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, - cancellableTxs, CancellationToken.None); - await CheckBlockExecutedSetAsync(blockExecutedSet, 2); - } + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, + cancellableTxs, CancellationToken.None); + await CheckBlockExecutedSetAsync(blockExecutedSet, 1); + } - private async Task CheckBlockExecutedSetAsync(BlockExecutedSet blockExecutedSet, int transactionCount) - { - blockExecutedSet.Block.Body.TransactionIds.Count.ShouldBe(transactionCount); - blockExecutedSet.TransactionResultMap.Values.Select(t => t.Status) - .ShouldAllBe(status => status == TransactionResultStatus.Mined); - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(blockExecutedSet.GetHash()); - blockStateSet.ShouldNotBeNull(); - var transactionResults = await _transactionResultManager.GetTransactionResultsAsync( - blockExecutedSet.TransactionIds.ToList(), - blockExecutedSet.GetHash()); - transactionResults.Count.ShouldBe(transactionCount); - foreach (var transactionResult in transactionResults) - { - blockExecutedSet.TransactionResultMap[transactionResult.TransactionId].ShouldBe(transactionResult); - } - } + [Fact] + public async Task Execute_Block_Cancellable_Cancelled() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + + var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; + var transactions = GetTransactions(); + var nonCancellableTxs = new[] { transactions[0] }; + var cancellableTxs = new[] { transactions[1] }; + var cancelToken = new CancellationTokenSource(); + cancelToken.Cancel(); + + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, + cancellableTxs, cancelToken.Token); + await CheckBlockExecutedSetAsync(blockExecutedSet, 1); + } + + [Fact] + public async Task Execute_Block_Cancellable() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + + var blockHeader = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash).Header; + var transactions = GetTransactions(); + var nonCancellableTxs = new[] { transactions[0] }; + var cancellableTxs = new[] { transactions[1] }; - private List GetTransactions() + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, nonCancellableTxs, + cancellableTxs, CancellationToken.None); + await CheckBlockExecutedSetAsync(blockExecutedSet, 2); + } + + private async Task CheckBlockExecutedSetAsync(BlockExecutedSet blockExecutedSet, int transactionCount) + { + blockExecutedSet.Block.Body.TransactionIds.Count.ShouldBe(transactionCount); + blockExecutedSet.TransactionResultMap.Values.Select(t => t.Status) + .ShouldAllBe(status => status == TransactionResultStatus.Mined); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(blockExecutedSet.GetHash()); + blockStateSet.ShouldNotBeNull(); + var transactionResults = await _transactionResultManager.GetTransactionResultsAsync( + blockExecutedSet.TransactionIds.ToList(), + blockExecutedSet.GetHash()); + transactionResults.Count.ShouldBe(transactionCount); + foreach (var transactionResult in transactionResults) + blockExecutedSet.TransactionResultMap[transactionResult.TransactionId].ShouldBe(transactionResult); + } + + private List GetTransactions() + { + return new List { - return new List + new() { - new Transaction - { - From = SampleAddress.AddressList[0], - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), - Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() - }, - new Transaction - { - From = SampleAddress.AddressList[0], - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.GetContractHash), - Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() - } - }; - } + From = SampleAddress.AddressList[0], + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), + Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() + }, + new() + { + From = SampleAddress.AddressList[0], + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.GetContractHash), + Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() + } + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutionResultProcessingServiceTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutionResultProcessingServiceTests.cs index a6b26e002a..074fcb0c26 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutionResultProcessingServiceTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/BlockExecutionResultProcessingServiceTests.cs @@ -7,103 +7,104 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class BlockExecutionResultProcessingServiceTests : SmartContractExecutionExecutingTestBase { - public sealed class BlockExecutionResultProcessingServiceTests : SmartContractExecutionExecutingTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; + private readonly IChainBlockLinkService _chainBlockLinkService; + private readonly IChainManager _chainManager; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockExecutionResultProcessingServiceTests() { - private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IChainManager _chainManager; - private readonly IChainBlockLinkService _chainBlockLinkService; + _blockExecutionResultProcessingService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _chainManager = GetRequiredService(); + _chainBlockLinkService = GetRequiredService(); + } - public BlockExecutionResultProcessingServiceTests() - { - _blockExecutionResultProcessingService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _chainManager = GetRequiredService(); - _chainBlockLinkService = GetRequiredService(); - } - - [Fact] - public async Task Process_LessThanBestChainHeight_BlockExecutionResult() - { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.RemoveLongestBranchAsync(chain); - - var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); - await _blockchainService.AttachBlockToChainAsync(chain, block); - - var executionResult = new BlockExecutionResult - { - SuccessBlockExecutedSets = {new BlockExecutedSet {Block = block}} - }; - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); - - chain = await _blockchainService.GetChainAsync(); - chain.LongestChainHash.ShouldBe(chain.BestChainHash); - chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); - } - - [Fact] - public async Task Process_Success_BlockExecutionResult() - { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.RemoveLongestBranchAsync(chain); - - var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); - await _blockchainService.AttachBlockToChainAsync(chain, block); - - chain = await _blockchainService.GetChainAsync(); - var block2 = _kernelTestHelper.GenerateBlock(block.Height, block.GetHash()); - await _blockchainService.AttachBlockToChainAsync(chain, block2); - - var executionResult = new BlockExecutionResult - { - SuccessBlockExecutedSets = {new BlockExecutedSet {Block = block}, new BlockExecutedSet {Block = block2}} - }; - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(block2.Height); - chain.BestChainHash.ShouldBe(block2.GetHash()); - - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - var chainBlockLink2 = await _chainManager.GetChainBlockLinkAsync(block2.GetHash()); - chainBlockLink2.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); - } - - [Fact] - public async Task Process_Empty_BlockExecutionResult() + [Fact] + public async Task Process_LessThanBestChainHeight_BlockExecutionResult() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.RemoveLongestBranchAsync(chain); + + var block = _kernelTestHelper.GenerateBlock(1, Hash.Empty); + await _blockchainService.AttachBlockToChainAsync(chain, block); + + var executionResult = new BlockExecutionResult { - var chain = await _blockchainService.GetChainAsync(); - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, new BlockExecutionResult()); - - chain = await _blockchainService.GetChainAsync(); - chain.LongestChainHash.ShouldBe(chain.BestChainHash); - chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); - } - - [Fact] - public async Task Process_Failed_BlockExecutionResult() + SuccessBlockExecutedSets = { new BlockExecutedSet { Block = block } } + }; + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); + + chain = await _blockchainService.GetChainAsync(); + chain.LongestChainHash.ShouldBe(chain.BestChainHash); + chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); + } + + [Fact] + public async Task Process_Success_BlockExecutionResult() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.RemoveLongestBranchAsync(chain); + + var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); + await _blockchainService.AttachBlockToChainAsync(chain, block); + + chain = await _blockchainService.GetChainAsync(); + var block2 = _kernelTestHelper.GenerateBlock(block.Height, block.GetHash()); + await _blockchainService.AttachBlockToChainAsync(chain, block2); + + var executionResult = new BlockExecutionResult { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.AttachBlockToChainAsync(chain, _kernelTestHelper.LongestBranchBlockList.Last()); - - var executionResult = new BlockExecutionResult(); - executionResult.ExecutedFailedBlocks.Add(_kernelTestHelper.LongestBranchBlockList.Last()); - - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); - - chain = await _blockchainService.GetChainAsync(); - chain.LongestChainHash.ShouldBe(chain.BestChainHash); - chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); - - var chainBlockLink = - await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.LongestBranchBlockList.Last().GetHash()); - chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionFailed); - } + SuccessBlockExecutedSets = + { new BlockExecutedSet { Block = block }, new BlockExecutedSet { Block = block2 } } + }; + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(block2.Height); + chain.BestChainHash.ShouldBe(block2.GetHash()); + + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + var chainBlockLink2 = await _chainManager.GetChainBlockLinkAsync(block2.GetHash()); + chainBlockLink2.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionSuccess); + } + + [Fact] + public async Task Process_Empty_BlockExecutionResult() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, + new BlockExecutionResult()); + + chain = await _blockchainService.GetChainAsync(); + chain.LongestChainHash.ShouldBe(chain.BestChainHash); + chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); + } + + [Fact] + public async Task Process_Failed_BlockExecutionResult() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.AttachBlockToChainAsync(chain, _kernelTestHelper.LongestBranchBlockList.Last()); + + var executionResult = new BlockExecutionResult(); + executionResult.ExecutedFailedBlocks.Add(_kernelTestHelper.LongestBranchBlockList.Last()); + + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, executionResult); + + chain = await _blockchainService.GetChainAsync(); + chain.LongestChainHash.ShouldBe(chain.BestChainHash); + chain.LongestChainHeight.ShouldBe(chain.BestChainHeight); + + var chainBlockLink = + await _chainManager.GetChainBlockLinkAsync(_kernelTestHelper.LongestBranchBlockList.Last().GetHash()); + chainBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionFailed); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceExecuteFailedTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceExecuteFailedTests.cs index 8c38a66ee5..3cf1688421 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceExecuteFailedTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceExecuteFailedTests.cs @@ -6,51 +6,50 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class FullBlockchainExecutingServiceValidateBeforeFailedTests : ValidateBeforeFailedTestBase { - public sealed class FullBlockchainExecutingServiceValidateBeforeFailedTests : ValidateBeforeFailedTestBase + private readonly IBlockchainService _blockchainService; + private readonly IChainManager _chainManager; + private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; + private readonly KernelTestHelper _kernelTestHelper; + + public FullBlockchainExecutingServiceValidateBeforeFailedTests() { - private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly IChainManager _chainManager; - private readonly KernelTestHelper _kernelTestHelper; + _fullBlockchainExecutingService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _chainManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public FullBlockchainExecutingServiceValidateBeforeFailedTests() - { - _fullBlockchainExecutingService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _chainManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + [Fact] + public async Task ExecuteBlock_ValidateFailed() + { + var chain = await _blockchainService.GetChainAsync(); - [Fact] - public async Task ExecuteBlock_ValidateFailed() + var previousHash = chain.BestChainHash; + var previousHeight = chain.BestChainHeight; + var blockList = new List(); + for (var i = 0; i < 3; i++) { - var chain = await _blockchainService.GetChainAsync(); - - var previousHash = chain.BestChainHash; - var previousHeight = chain.BestChainHeight; - var blockList = new List(); - for (var i = 0; i < 3; i++) - { - var transactions = new List {_kernelTestHelper.GenerateTransaction()}; - var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions); - - await _blockchainService.AddBlockAsync(lastBlock); - await _blockchainService.AddTransactionsAsync(transactions); - - await _blockchainService.AttachBlockToChainAsync(chain, lastBlock); - previousHash = lastBlock.GetHash(); - previousHeight = lastBlock.Height; - blockList.Add(lastBlock); - } - - var executionResult = - await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); - - executionResult.SuccessBlockExecutedSets.Count.ShouldBe(0); - executionResult.ExecutedFailedBlocks.Count.ShouldBe(1); - executionResult.ExecutedFailedBlocks[0].GetHash().ShouldBe(blockList[0].GetHash()); + var transactions = new List { _kernelTestHelper.GenerateTransaction() }; + var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions); + + await _blockchainService.AddBlockAsync(lastBlock); + await _blockchainService.AddTransactionsAsync(transactions); + + await _blockchainService.AttachBlockToChainAsync(chain, lastBlock); + previousHash = lastBlock.GetHash(); + previousHeight = lastBlock.Height; + blockList.Add(lastBlock); } + + var executionResult = + await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); + + executionResult.SuccessBlockExecutedSets.Count.ShouldBe(0); + executionResult.ExecutedFailedBlocks.Count.ShouldBe(1); + executionResult.ExecutedFailedBlocks[0].GetHash().ShouldBe(blockList[0].GetHash()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceTests.cs index f75063118c..b45940c577 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceTests.cs @@ -1,98 +1,91 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Domain; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class FullBlockchainExecutingServiceTests : SmartContractExecutionTestBase { - public sealed class FullBlockchainExecutingServiceTests : SmartContractExecutionTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + + public FullBlockchainExecutingServiceTests() { - private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly SmartContractExecutionHelper _smartContractExecutionHelper; - private readonly IBlockExecutingService _blockExecutingService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IBlockStateSetManger _blockStateSetManger; + _fullBlockchainExecutingService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _smartContractExecutionHelper = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } - public FullBlockchainExecutingServiceTests() - { - _fullBlockchainExecutingService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _smartContractExecutionHelper = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } + [Fact] + public async Task ExecuteBlocks_Success() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); - [Fact] - public async Task ExecuteBlocks_Success() + var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); + var transactions = new List { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - - var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); - var transactions = new List + new() { - new Transaction - { - From = SampleAddress.AddressList[0], - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), - Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() - } - }; - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); - await _blockStateSetManger.RemoveBlockStateSetsAsync(new List {blockExecutedSet.GetHash()}); - await _blockchainService.AddTransactionsAsync(transactions); - await ExecuteBlocksAsync(new List{blockExecutedSet.Block}); - } - - [Fact] - public async Task ExecuteBlocks_Success_WithExistBlockStateSet() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); + From = SampleAddress.AddressList[0], + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), + Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() + } + }; + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); + await _blockStateSetManger.RemoveBlockStateSetsAsync(new List { blockExecutedSet.GetHash() }); + await _blockchainService.AddTransactionsAsync(transactions); + await ExecuteBlocksAsync(new List { blockExecutedSet.Block }); + } - var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); - var transactions = new List - { - new Transaction - { - From = SampleAddress.AddressList[0], - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), - Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() - } - }; - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); - await _blockchainService.AddTransactionsAsync(transactions); - await ExecuteBlocksAsync(new List{blockExecutedSet.Block}); - } + [Fact] + public async Task ExecuteBlocks_Success_WithExistBlockStateSet() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); - private async Task ExecuteBlocksAsync(List blockList) + var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash); + var transactions = new List { - foreach (var block in blockList) + new() { - await _blockchainService.AddBlockAsync(block); + From = SampleAddress.AddressList[0], + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.GetContractInfo), + Params = _smartContractAddressService.GetZeroSmartContractAddress().ToByteString() } - - var executionResult = - await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); + }; + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions); + await _blockchainService.AddTransactionsAsync(transactions); + await ExecuteBlocksAsync(new List { blockExecutedSet.Block }); + } - executionResult.SuccessBlockExecutedSets.Count.ShouldBe(blockList.Count()); - for (var i = 0; i < blockList.Count; i++) - { - executionResult.SuccessBlockExecutedSets[i].GetHash().ShouldBe(blockList[i].GetHash()); - } - executionResult.ExecutedFailedBlocks.Count.ShouldBe(0); - } + private async Task ExecuteBlocksAsync(List blockList) + { + foreach (var block in blockList) await _blockchainService.AddBlockAsync(block); + + var executionResult = + await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); + + executionResult.SuccessBlockExecutedSets.Count.ShouldBe(blockList.Count()); + for (var i = 0; i < blockList.Count; i++) + executionResult.SuccessBlockExecutedSets[i].GetHash().ShouldBe(blockList[i].GetHash()); + executionResult.ExecutedFailedBlocks.Count.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceValidateAfterFailedTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceValidateAfterFailedTests.cs index eeab97a93a..d40d860d46 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceValidateAfterFailedTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/FullBlockchainExecutingServiceValidateAfterFailedTests.cs @@ -1,60 +1,57 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; using AElf.Types; -using AElf.Kernel.Infrastructure; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class FullBlockchainExecutingServiceValidateAfterFailedTests : ValidateAfterFailedTestBase { - public sealed class FullBlockchainExecutingServiceValidateAfterFailedTests : ValidateAfterFailedTestBase + private readonly IBlockchainService _blockchainService; + private readonly IChainManager _chainManager; + private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; + private readonly KernelTestHelper _kernelTestHelper; + + public FullBlockchainExecutingServiceValidateAfterFailedTests() { - private readonly FullBlockchainExecutingService _fullBlockchainExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly IChainManager _chainManager; - private readonly KernelTestHelper _kernelTestHelper; - - public FullBlockchainExecutingServiceValidateAfterFailedTests() - { - _fullBlockchainExecutingService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _chainManager = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } - - [Fact] - public async Task ExecuteBlocks_ValidateFailed() + _fullBlockchainExecutingService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _chainManager = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } + + [Fact] + public async Task ExecuteBlocks_ValidateFailed() + { + var chain = await _blockchainService.GetChainAsync(); + + var previousHash = chain.BestChainHash; + var previousHeight = chain.BestChainHeight; + + var blockList = new List(); + for (var i = 0; i < 3; i++) { - var chain = await _blockchainService.GetChainAsync(); - - var previousHash = chain.BestChainHash; - var previousHeight = chain.BestChainHeight; - - var blockList = new List(); - for (var i = 0; i < 3; i++) - { - var transactions = new List {_kernelTestHelper.GenerateTransaction() }; - var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions); - - await _blockchainService.AddBlockAsync(lastBlock); - await _blockchainService.AddTransactionsAsync(transactions); - - await _blockchainService.AttachBlockToChainAsync(chain, lastBlock); - - previousHash = lastBlock.GetHash(); - previousHeight = lastBlock.Height; - blockList.Add(lastBlock); - } - - var executionResult = - await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); - - executionResult.SuccessBlockExecutedSets.Count.ShouldBe(0); - executionResult.ExecutedFailedBlocks.Count.ShouldBe(1); - executionResult.ExecutedFailedBlocks[0].GetHash().ShouldBe(blockList[0].GetHash()); + var transactions = new List { _kernelTestHelper.GenerateTransaction() }; + var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions); + + await _blockchainService.AddBlockAsync(lastBlock); + await _blockchainService.AddTransactionsAsync(transactions); + + await _blockchainService.AttachBlockToChainAsync(chain, lastBlock); + + previousHash = lastBlock.GetHash(); + previousHeight = lastBlock.Height; + blockList.Add(lastBlock); } + + var executionResult = + await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList); + + executionResult.SuccessBlockExecutedSets.Count.ShouldBe(0); + executionResult.ExecutedFailedBlocks.Count.ShouldBe(1); + executionResult.ExecutedFailedBlocks[0].GetHash().ShouldBe(blockList[0].GetHash()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/LogEventProcessorTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/LogEventProcessorTests.cs index 0adcb55c19..48603dced2 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/LogEventProcessorTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/LogEventProcessorTests.cs @@ -1,187 +1,198 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Configuration; using AElf.Kernel.Infrastructure; using AElf.Kernel.SmartContract.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class LogEventProcessorTests : SmartContractExecutionTestBase { - public sealed class LogEventProcessorTests : SmartContractExecutionTestBase + private readonly IBlockchainService _blockchainService; + private readonly CodeUpdatedLogEventProcessor _codeUpdatedLogEventProcessor; + private readonly ContractDeployedLogEventProcessor _contractDeployedLogEventProcessor; + private readonly ISmartContractAddressProvider _smartContractAddressProvider; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; + private readonly ITransactionResultQueryService _transactionResultQueryService; + + public LogEventProcessorTests() { - private readonly ContractDeployedLogEventProcessor _contractDeployedLogEventProcessor; - private readonly CodeUpdatedLogEventProcessor _codeUpdatedLogEventProcessor; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly SmartContractExecutionHelper _smartContractExecutionHelper; - private readonly ITransactionResultQueryService _transactionResultQueryService; - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressProvider _smartContractAddressProvider; - private readonly ISmartContractRegistrationProvider _smartContractRegistrationProvider; - - public LogEventProcessorTests() - { - _contractDeployedLogEventProcessor = GetRequiredService(); - _codeUpdatedLogEventProcessor = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _smartContractExecutionHelper = GetRequiredService(); - _transactionResultQueryService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _smartContractAddressProvider = GetRequiredService(); - _smartContractRegistrationProvider = GetRequiredService(); - } + _contractDeployedLogEventProcessor = GetRequiredService(); + _codeUpdatedLogEventProcessor = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _smartContractExecutionHelper = GetRequiredService(); + _transactionResultQueryService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _smartContractAddressProvider = GetRequiredService(); + _smartContractRegistrationProvider = GetRequiredService(); + } + + [Fact] + public async Task GetInterestedEventAsync_Test() + { + var contractDeployedInterestedEvent = + await _contractDeployedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); + CheckInterestedEvent(contractDeployedInterestedEvent); + var contractDeployedInterestedEventInCache = + await _contractDeployedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); + CheckInterestedEvent(contractDeployedInterestedEventInCache); + + var codeUpdatedInterestedEvent = + await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); + CheckInterestedEvent(codeUpdatedInterestedEvent); + var codeUpdatedInterestedEventInCache = + await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); + CheckInterestedEvent(codeUpdatedInterestedEventInCache); + } - [Fact] - public async Task GetInterestedEventAsync_Test() + private void CheckInterestedEvent(InterestedEvent interestedEvent) where T : IEvent, new() + { + var zeroSmartContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); + var logEvent = new T().ToLogEvent(zeroSmartContractAddress); + var contractDeployedEvent = new InterestedEvent { - var contractDeployedInterestedEvent = await _contractDeployedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); - CheckInterestedEvent(contractDeployedInterestedEvent); - var contractDeployedInterestedEventInCache = await _contractDeployedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); - CheckInterestedEvent(contractDeployedInterestedEventInCache); - - var codeUpdatedInterestedEvent = await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); - CheckInterestedEvent(codeUpdatedInterestedEvent); - var codeUpdatedInterestedEventInCache = await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(new ChainContext()); - CheckInterestedEvent(codeUpdatedInterestedEventInCache); - } + LogEvent = logEvent, + Bloom = logEvent.GetBloom() + }; + interestedEvent.LogEvent.ShouldBe(contractDeployedEvent.LogEvent); + interestedEvent.Bloom.Data.ShouldBe(contractDeployedEvent.Bloom.Data); + } + + [Fact] + public async Task ProcessAsync_Test() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); + var tasks = block.Body.TransactionIds + .Select(t => _transactionResultQueryService.GetTransactionResultAsync(t)).ToList(); + var transactionResultList = await Task.WhenAll(tasks); - private void CheckInterestedEvent(InterestedEvent interestedEvent) where T : IEvent, new() + await ProcessTransactionResultsAsync(transactionResultList, block); + + var transaction = new Transaction { - var zeroSmartContractAddress = _smartContractAddressService.GetZeroSmartContractAddress(); - var logEvent = new T().ToLogEvent(zeroSmartContractAddress); - var contractDeployedEvent = new InterestedEvent + From = _smartContractAddressService.GetZeroSmartContractAddress(), + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.DeploySmartContract), + Params = new ContractDeploymentInput { - LogEvent = logEvent, - Bloom = logEvent.GetBloom() - }; - interestedEvent.LogEvent.ShouldBe(contractDeployedEvent.LogEvent); - interestedEvent.Bloom.Data.ShouldBe(contractDeployedEvent.Bloom.Data); - } + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom( + _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]) + }.ToByteString() + }; + var blockExecutedSet = await _smartContractExecutionHelper.ExecuteTransactionAsync(transaction); - [Fact] - public async Task ProcessAsync_Test() - { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash); - var tasks = block.Body.TransactionIds - .Select(t => _transactionResultQueryService.GetTransactionResultAsync(t)).ToList(); - var transactionResultList = await Task.WhenAll(tasks); + await ProcessTransactionResultsAsync(blockExecutedSet.TransactionResultMap.Values.ToArray(), + blockExecutedSet.Block); - await ProcessTransactionResultsAsync(transactionResultList, block); + await ProcessCodeUpdateAsync(chain); + } - var transaction = new Transaction + private async Task ProcessCodeUpdateAsync(Chain chain) + { + var chainContext = new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + ConfigurationSmartContractAddressNameProvider.StringName); + var transaction = new Transaction + { + From = _smartContractAddressService.GetZeroSmartContractAddress(), + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(ACS0Container.ACS0Stub.UpdateSmartContract), + Params = new ContractUpdateInput { - From = _smartContractAddressService.GetZeroSmartContractAddress(), - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.DeploySmartContract), - Params = new ContractDeploymentInput - { - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom( - _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]) - }.ToByteString() - }; - var blockExecutedSet = await _smartContractExecutionHelper.ExecuteTransactionAsync(transaction); - - await ProcessTransactionResultsAsync(blockExecutedSet.TransactionResultMap.Values.ToArray(), blockExecutedSet.Block); + Code = ByteString.CopyFrom( + _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]), + Address = address + }.ToByteString() + }; + var blockExecutedSet = await _smartContractExecutionHelper.ExecuteTransactionAsync(transaction, chain); - await ProcessCodeUpdateAsync(chain); - } - - private async Task ProcessCodeUpdateAsync(Chain chain) + var interestedEvent = await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(chainContext); + foreach (var transactionResult in blockExecutedSet.TransactionResultMap.Values) { - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var address = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, - ConfigurationSmartContractAddressNameProvider.StringName); - var transaction = new Transaction + var logEvent = transactionResult.Logs.First(l => + l.Address == interestedEvent.LogEvent.Address && l.Name == interestedEvent.LogEvent.Name); + var codeUpdated = new CodeUpdated(); + codeUpdated.MergeFrom(logEvent); + var smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync( + chainContext, + codeUpdated.Address); + + await _codeUpdatedLogEventProcessor.ProcessAsync(blockExecutedSet.Block, + new Dictionary> + { { transactionResult, new List { logEvent } } }); + + chainContext = new ChainContext { - From = _smartContractAddressService.GetZeroSmartContractAddress(), - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(ACS0Container.ACS0Stub.UpdateSmartContract), - Params = new ContractUpdateInput - { - Code = ByteString.CopyFrom( - _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"]), - Address = address - }.ToByteString() + BlockHash = blockExecutedSet.Block.GetHash(), + BlockHeight = blockExecutedSet.Block.Height }; - var blockExecutedSet = await _smartContractExecutionHelper.ExecuteTransactionAsync(transaction, chain); - - var interestedEvent = await _codeUpdatedLogEventProcessor.GetInterestedEventAsync(chainContext); - foreach (var transactionResult in blockExecutedSet.TransactionResultMap.Values) - { - var logEvent = transactionResult.Logs.First(l => - l.Address == interestedEvent.LogEvent.Address && l.Name == interestedEvent.LogEvent.Name); - var codeUpdated = new CodeUpdated(); - codeUpdated.MergeFrom(logEvent); - var smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, + var updatedSmartContractRegistration = + await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, codeUpdated.Address); - - await _codeUpdatedLogEventProcessor.ProcessAsync(blockExecutedSet.Block, - new Dictionary> - {{transactionResult, new List {logEvent}}}); - - chainContext = new ChainContext - { - BlockHash = blockExecutedSet.Block.GetHash(), - BlockHeight = blockExecutedSet.Block.Height - }; - var updatedSmartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, - codeUpdated.Address); - updatedSmartContractRegistration.ShouldNotBe(smartContractRegistration); - updatedSmartContractRegistration.Code.ShouldBe(ByteString.CopyFrom( - _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"])); - } + updatedSmartContractRegistration.ShouldNotBe(smartContractRegistration); + updatedSmartContractRegistration.Code.ShouldBe(ByteString.CopyFrom( + _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"])); } + } - private async Task ProcessTransactionResultsAsync(TransactionResult[] transactionResultList,Block block) + private async Task ProcessTransactionResultsAsync(TransactionResult[] transactionResultList, Block block) + { + var chainContext = new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var interestedEvent = await _contractDeployedLogEventProcessor.GetInterestedEventAsync(chainContext); + foreach (var transactionResult in transactionResultList) { - var chainContext = new ChainContext + var logEvent = transactionResult.Logs.First(l => + l.Address == interestedEvent.LogEvent.Address && l.Name == interestedEvent.LogEvent.Name); + var contractDeployed = new ContractDeployed(); + contractDeployed.MergeFrom(logEvent); + if (contractDeployed.Name != null) { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - var interestedEvent = await _contractDeployedLogEventProcessor.GetInterestedEventAsync(chainContext); - foreach (var transactionResult in transactionResultList) + var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync( + chainContext, + contractDeployed.Name.ToStorageKey()); + smartContractAddress.ShouldBeNull(); + } + + var smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync( + chainContext, + contractDeployed.Address); + smartContractRegistration.ShouldBeNull(); + + await _contractDeployedLogEventProcessor.ProcessAsync(block, + new Dictionary> + { { transactionResult, new List { logEvent } } }); + + smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync( + chainContext, + contractDeployed.Address); + smartContractRegistration.ShouldNotBeNull(); + if (contractDeployed.Name == null) continue; { - var logEvent = transactionResult.Logs.First(l => - l.Address == interestedEvent.LogEvent.Address && l.Name == interestedEvent.LogEvent.Name); - var contractDeployed = new ContractDeployed(); - contractDeployed.MergeFrom(logEvent); - if (contractDeployed.Name != null) - { - var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, - contractDeployed.Name.ToStorageKey()); - smartContractAddress.ShouldBeNull(); - } - var smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, - contractDeployed.Address); - smartContractRegistration.ShouldBeNull(); - - await _contractDeployedLogEventProcessor.ProcessAsync(block, - new Dictionary> - {{transactionResult, new List {logEvent}}}); - - smartContractRegistration = await _smartContractRegistrationProvider.GetSmartContractRegistrationAsync(chainContext, - contractDeployed.Address); - smartContractRegistration.ShouldNotBeNull(); - if (contractDeployed.Name == null) continue; - { - var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync(chainContext, - contractDeployed.Name.ToStorageKey()); - smartContractAddress.ShouldNotBeNull(); - } + var smartContractAddress = await _smartContractAddressProvider.GetSmartContractAddressAsync( + chainContext, + contractDeployed.Name.ToStorageKey()); + smartContractAddress.ShouldNotBeNull(); } } } diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Application/SmartContractRegistrationInStateProviderTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Application/SmartContractRegistrationInStateProviderTests.cs index 5b8aa6fff6..06200a2a3e 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Application/SmartContractRegistrationInStateProviderTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Application/SmartContractRegistrationInStateProviderTests.cs @@ -4,39 +4,42 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Application +namespace AElf.Kernel.SmartContractExecution.Application; + +public sealed class SmartContractRegistrationInStateProviderTests : SmartContractExecutionTestBase { - public sealed class SmartContractRegistrationInStateProviderTests : SmartContractExecutionTestBase - { - private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly SmartContractExecutionHelper _smartContractExecutionHelper; + private readonly ISmartContractRegistrationInStateProvider _smartContractRegistrationInStateProvider; - public SmartContractRegistrationInStateProviderTests() - { - _smartContractRegistrationInStateProvider = GetRequiredService(); - _defaultContractZeroCodeProvider = GetRequiredService(); - _smartContractExecutionHelper = GetRequiredService(); - } + public SmartContractRegistrationInStateProviderTests() + { + _smartContractRegistrationInStateProvider = GetRequiredService(); + _defaultContractZeroCodeProvider = GetRequiredService(); + _smartContractExecutionHelper = GetRequiredService(); + } - [Fact] - public async Task GetSmartContractRegistrationAsync_Test() + [Fact] + public async Task GetSmartContractRegistrationAsync_Test() + { + var chain = await _smartContractExecutionHelper.CreateChainAsync(); + var chainContext = new ChainContext { - var chain = await _smartContractExecutionHelper.CreateChainAsync(); - var chainContext = new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - var smartContractRegistration = await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext, + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + var smartContractRegistration = + await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext, SampleAddress.AddressList[0]); - smartContractRegistration.ShouldBe(new SmartContractRegistration()); - - smartContractRegistration = await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync(chainContext, - _defaultContractZeroCodeProvider.ContractZeroAddress); - smartContractRegistration.Category.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.Category); - smartContractRegistration.Code.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.Code); - smartContractRegistration.CodeHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash); - } + smartContractRegistration.ShouldBe(new SmartContractRegistration()); + + smartContractRegistration = await _smartContractRegistrationInStateProvider.GetSmartContractRegistrationAsync( + chainContext, + _defaultContractZeroCodeProvider.ContractZeroAddress); + smartContractRegistration.Category.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration + .Category); + smartContractRegistration.Code.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.Code); + smartContractRegistration.CodeHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration + .CodeHash); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/Extensions/BlockchainServiceExtensionsTests.cs b/test/AElf.Kernel.SmartContractExecution.Tests/Extensions/BlockchainServiceExtensionsTests.cs index e55287394f..04dd543fca 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/Extensions/BlockchainServiceExtensionsTests.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/Extensions/BlockchainServiceExtensionsTests.cs @@ -5,35 +5,34 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.SmartContractExecution.Extensions +namespace AElf.Kernel.SmartContractExecution.Extensions; + +public sealed class BlockchainServiceExtensionsTests : SmartContractExecutionTestBase { - public sealed class BlockchainServiceExtensionsTests : SmartContractExecutionTestBase + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockchainServiceExtensionsTests() { - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public BlockchainServiceExtensionsTests() + [Fact] + public async Task GetBlocksAsync_Test() + { + var blockHashes = new List(); + var chain = await _kernelTestHelper.MockChainAsync(); + var blockHash = chain.BestChainHash; + for (var i = 0; i < chain.BestChainHeight; i++) { - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); + var block = await _blockchainService.GetBlockByHashAsync(blockHash); + if (block == null) break; + blockHashes.Add(blockHash); + blockHash = block.Header.PreviousBlockHash; } - [Fact] - public async Task GetBlocksAsync_Test() - { - var blockHashes = new List(); - var chain = await _kernelTestHelper.MockChainAsync(); - var blockHash = chain.BestChainHash; - for (var i = 0; i < chain.BestChainHeight; i++) - { - var block = await _blockchainService.GetBlockByHashAsync(blockHash); - if(block == null) break; - blockHashes.Add(blockHash); - blockHash = block.Header.PreviousBlockHash; - } - - var blocks = await _blockchainService.GetBlocksAsync(blockHashes); - blocks.Count.ShouldBe(blockHashes.Count); - } + var blocks = await _blockchainService.GetBlocksAsync(blockHashes); + blocks.Count.ShouldBe(blockHashes.Count); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionExecutingTestAElfModule.cs b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionExecutingTestAElfModule.cs index a462786c76..e014c71080 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionExecutingTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionExecutingTestAElfModule.cs @@ -3,10 +3,9 @@ using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Blockchain; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; -using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContractExecution.Application; using AElf.Modularity; using AElf.Types; @@ -17,162 +16,151 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +[DependsOn( + typeof(SmartContractExecutionTestAElfModule), + typeof(KernelCoreWithChainTestAElfModule) +)] +public class SmartContractExecutionExecutingTestAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractExecutionTestAElfModule), - typeof(KernelCoreWithChainTestAElfModule) - )] - public class SmartContractExecutionExecutingTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + services.AddTransient(p => { - var services = context.Services; - services.AddTransient(p => - { - var mockService = new Mock(); - mockService.Setup(m => m.ExecuteAsync(It.IsAny(), - It.IsAny())) - .Returns( - (transactionExecutingDto, cancellationToken) => + var mockService = new Mock(); + mockService.Setup(m => m.ExecuteAsync(It.IsAny(), + It.IsAny())) + .Returns( + (transactionExecutingDto, cancellationToken) => + { + var returnSets = new List(); + + var count = 0; + foreach (var tx in transactionExecutingDto.Transactions) { - var returnSets = new List(); + if (cancellationToken.IsCancellationRequested && count >= 3) break; - var count = 0; - foreach (var tx in transactionExecutingDto.Transactions) + var returnSet = new ExecutionReturnSet { - if (cancellationToken.IsCancellationRequested && count >= 3) - { - break; - } - - var returnSet = new ExecutionReturnSet - { - TransactionId = tx.GetHash() - }; - returnSet.StateChanges.Add(tx.GetHash().ToHex(), tx.ToByteString()); - returnSets.Add(returnSet); - count++; - } - - return Task.FromResult(returnSets); - }); - - return mockService.Object; - }); - services.AddTransient(p => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) - .Returns>((blockHeader, transactions) => - { - var block = new Block - { - Header = blockHeader, - Body = new BlockBody() - }; - block.Body.AddTransactions(transactions.Select(x => x.GetHash())); - return Task.FromResult(new BlockExecutedSet(){Block = block}); + TransactionId = tx.GetHash() + }; + returnSet.StateChanges.Add(tx.GetHash().ToHex(), tx.ToByteString()); + returnSets.Add(returnSet); + count++; + } + + return Task.FromResult(returnSets); }); - return mockService.Object; - }); - } - public override void OnApplicationInitialization(ApplicationInitializationContext context) + return mockService.Object; + }); + services.AddTransient(p => { - var kernelTestHelper = context.ServiceProvider.GetService(); - for (var i = 0; i < 4; i++) - { - AsyncHelper.RunSync(() => kernelTestHelper.AttachBlockToBestChain()); - } - } + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) + .Returns>((blockHeader, transactions) => + { + var block = new Block + { + Header = blockHeader, + Body = new BlockBody() + }; + block.Body.AddTransactions(transactions.Select(x => x.GetHash())); + return Task.FromResult(new BlockExecutedSet { Block = block }); + }); + return mockService.Object; + }); } - [DependsOn( - typeof(SmartContractExecutionExecutingTestAElfModule) - )] - public class ValidateBeforeFailedTestAElfModule : AElfModule + public override void OnApplicationInitialization(ApplicationInitializationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - - services.AddTransient(p => - { - var mockProvider = new Mock(); + var kernelTestHelper = context.ServiceProvider.GetService(); + for (var i = 0; i < 4; i++) AsyncHelper.RunSync(() => kernelTestHelper.AttachBlockToBestChain()); + } +} - mockProvider.Setup(m => m.ValidateBlockAfterExecuteAsync(It.IsAny())) - .ReturnsAsync(true); +[DependsOn( + typeof(SmartContractExecutionExecutingTestAElfModule) +)] +public class ValidateBeforeFailedTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var services = context.Services; - return mockProvider.Object; - }); + services.AddTransient(p => + { + var mockProvider = new Mock(); - services.AddTransient(p => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) - .Returns>((blockHeader, transactions) => - { - Block result; - if (blockHeader.Height == AElfConstants.GenesisBlockHeight) - { - result = new Block {Header = blockHeader}; - } - else - { - result = new Block - {Header = new BlockHeader {Time = TimestampHelper.GetUtcNow()}}; - } + mockProvider.Setup(m => m.ValidateBlockAfterExecuteAsync(It.IsAny())) + .ReturnsAsync(true); - return Task.FromResult(new BlockExecutedSet() {Block = result}); - }); + return mockProvider.Object; + }); - return mockService.Object; - }); - } + services.AddTransient(p => + { + var mockService = new Mock(); + mockService.Setup(m => + m.ExecuteBlockAsync(It.IsAny(), It.IsAny>())) + .Returns>((blockHeader, transactions) => + { + Block result; + if (blockHeader.Height == AElfConstants.GenesisBlockHeight) + result = new Block { Header = blockHeader }; + else + result = new Block + { Header = new BlockHeader { Time = TimestampHelper.GetUtcNow() } }; + + return Task.FromResult(new BlockExecutedSet { Block = result }); + }); + + return mockService.Object; + }); } +} - [DependsOn( - typeof(SmartContractExecutionExecutingTestAElfModule) - )] - public class ValidateAfterFailedTestAElfModule : AElfModule +[DependsOn( + typeof(SmartContractExecutionExecutingTestAElfModule) +)] +public class ValidateAfterFailedTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddTransient(p => - { - var mockProvider = new Mock(); - mockProvider.Setup(m => m.ValidateBlockAfterExecuteAsync(It.IsAny())) - .Returns( - (block) => Task.FromResult(block.Header.Height == AElfConstants.GenesisBlockHeight)); + services.AddTransient(p => + { + var mockProvider = new Mock(); + mockProvider.Setup(m => m.ValidateBlockAfterExecuteAsync(It.IsAny())) + .Returns( + block => Task.FromResult(block.Header.Height == AElfConstants.GenesisBlockHeight)); - mockProvider.Setup(m => m.ValidateBlockBeforeExecuteAsync(It.IsAny())) - .ReturnsAsync(true); + mockProvider.Setup(m => m.ValidateBlockBeforeExecuteAsync(It.IsAny())) + .ReturnsAsync(true); - return mockProvider.Object; - }); - } + return mockProvider.Object; + }); } +} - [DependsOn(typeof(SmartContractExecutionExecutingTestAElfModule))] - public class FullBlockChainExecutingTestModule : AElfModule +[DependsOn(typeof(SmartContractExecutionExecutingTestAElfModule))] +public class FullBlockChainExecutingTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddTransient(p => - { - var mockProvider = new Mock(); - mockProvider.Setup(m => m.AddTransactionResultAsync(It.IsAny(), It.IsAny())) - .Returns((txResult, hash) => Task.CompletedTask); + services.AddTransient(p => + { + var mockProvider = new Mock(); + mockProvider.Setup(m => m.AddTransactionResultAsync(It.IsAny(), It.IsAny())) + .Returns((txResult, hash) => Task.CompletedTask); - return mockProvider.Object; - }); - } + return mockProvider.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionHelper.cs b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionHelper.cs index fadf3e13bc..e5df4d4669 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionHelper.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionHelper.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Cryptography; using AElf.Kernel.Blockchain; @@ -9,103 +8,104 @@ using AElf.Kernel.Configuration; using AElf.Kernel.SmartContract.Infrastructure; using AElf.Kernel.SmartContractExecution.Application; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +public class SmartContractExecutionHelper { - public class SmartContractExecutionHelper - { - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockchainExecutingService _blockchainExecutingService; - private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; - private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; + private readonly IBlockchainExecutingService _blockchainExecutingService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockExecutionResultProcessingService _blockExecutionResultProcessingService; + private readonly IDefaultContractZeroCodeProvider _defaultContractZeroCodeProvider; - public SmartContractExecutionHelper(IBlockExecutingService blockExecutingService, - IBlockchainService blockchainService, IBlockchainExecutingService blockchainExecutingService, - IBlockExecutionResultProcessingService blockExecutionResultProcessingService, - IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider) - { - _blockExecutingService = blockExecutingService; - _blockchainService = blockchainService; - _blockchainExecutingService = blockchainExecutingService; - _blockExecutionResultProcessingService = blockExecutionResultProcessingService; - _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; - ContractCodes= ContractsDeployer.GetContractCodes(); - } + public IReadOnlyDictionary ContractCodes; - public IReadOnlyDictionary ContractCodes; + public SmartContractExecutionHelper(IBlockExecutingService blockExecutingService, + IBlockchainService blockchainService, IBlockchainExecutingService blockchainExecutingService, + IBlockExecutionResultProcessingService blockExecutionResultProcessingService, + IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider) + { + _blockExecutingService = blockExecutingService; + _blockchainService = blockchainService; + _blockchainExecutingService = blockchainExecutingService; + _blockExecutionResultProcessingService = blockExecutionResultProcessingService; + _defaultContractZeroCodeProvider = defaultContractZeroCodeProvider; + ContractCodes = ContractsDeployer.GetContractCodes(); + } - public async Task CreateChainAsync() + public async Task CreateChainAsync() + { + _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(null); + var blockHeader = new BlockHeader { - _defaultContractZeroCodeProvider.SetDefaultContractZeroRegistrationByType(null); - var blockHeader = new BlockHeader - { - Height = AElfConstants.GenesisBlockHeight, - PreviousBlockHash = Hash.Empty, - Time = new Timestamp {Seconds = 0} - }; - var transactions = new List + Height = AElfConstants.GenesisBlockHeight, + PreviousBlockHash = Hash.Empty, + Time = new Timestamp { Seconds = 0 } + }; + var transactions = new List + { + new() { - new Transaction + From = _defaultContractZeroCodeProvider.ContractZeroAddress, + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), + Params = new SystemContractDeploymentInput { - From = _defaultContractZeroCodeProvider.ContractZeroAddress, - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), - Params = new SystemContractDeploymentInput - { - Name = ZeroSmartContractAddressNameProvider.Name, - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(ContractCodes["AElf.Contracts.Genesis"]), - }.ToByteString() - }, - new Transaction + Name = ZeroSmartContractAddressNameProvider.Name, + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(ContractCodes["AElf.Contracts.Genesis"]) + }.ToByteString() + }, + new() + { + From = _defaultContractZeroCodeProvider.ContractZeroAddress, + To = _defaultContractZeroCodeProvider.ContractZeroAddress, + MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), + Params = new SystemContractDeploymentInput { - From = _defaultContractZeroCodeProvider.ContractZeroAddress, - To = _defaultContractZeroCodeProvider.ContractZeroAddress, - MethodName = nameof(ACS0Container.ACS0Stub.DeploySystemSmartContract), - Params = new SystemContractDeploymentInput - { - Name = ConfigurationSmartContractAddressNameProvider.Name, - Category = KernelConstants.DefaultRunnerCategory, - Code = ByteString.CopyFrom(ContractCodes["AElf.Contracts.Configuration"]) - }.ToByteString() - } - }; + Name = ConfigurationSmartContractAddressNameProvider.Name, + Category = KernelConstants.DefaultRunnerCategory, + Code = ByteString.CopyFrom(ContractCodes["AElf.Contracts.Configuration"]) + }.ToByteString() + } + }; - var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - var chain = await _blockchainService.CreateChainAsync(block.Block, transactions); - var blockExecutionResult = await _blockchainExecutingService.ExecuteBlocksAsync(new[] {block.Block}); - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); + var block = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + var chain = await _blockchainService.CreateChainAsync(block.Block, transactions); + var blockExecutionResult = await _blockchainExecutingService.ExecuteBlocksAsync(new[] { block.Block }); + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); + + return await _blockchainService.GetChainAsync(); + } - return await _blockchainService.GetChainAsync(); - } + public async Task ExecuteTransactionAsync(Transaction transaction, Chain chain = null) + { + chain ??= await _blockchainService.GetChainAsync(); + var blockHeader = new BlockHeader + { + Height = chain.BestChainHeight + 1, + PreviousBlockHash = chain.BestChainHash, + Time = TimestampHelper.GetUtcNow(), + SignerPubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) + }; - public async Task ExecuteTransactionAsync(Transaction transaction, Chain chain = null) + var transactions = new List { - chain ??= await _blockchainService.GetChainAsync(); - var blockHeader = new BlockHeader - { - Height = chain.BestChainHeight + 1, - PreviousBlockHash = chain.BestChainHash, - Time = TimestampHelper.GetUtcNow(), - SignerPubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) - }; - - var transactions = new List - { - transaction - }; + transaction + }; - var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(blockExecutedSet.Block); - await _blockchainService.AttachBlockToChainAsync(chain, blockExecutedSet.Block); - var blockExecutionResult = await _blockchainExecutingService.ExecuteBlocksAsync(new[] {blockExecutedSet.Block}); - await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); - return blockExecutionResult.SuccessBlockExecutedSets.Single(); - } + var blockExecutedSet = await _blockExecutingService.ExecuteBlockAsync(blockHeader, transactions); + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(blockExecutedSet.Block); + await _blockchainService.AttachBlockToChainAsync(chain, blockExecutedSet.Block); + var blockExecutionResult = + await _blockchainExecutingService.ExecuteBlocksAsync(new[] { blockExecutedSet.Block }); + await _blockExecutionResultProcessingService.ProcessBlockExecutionResultAsync(chain, blockExecutionResult); + return blockExecutionResult.SuccessBlockExecutedSets.Single(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestAElfModule.cs b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestAElfModule.cs index bd493372e2..d5ab6d8db1 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestAElfModule.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestAElfModule.cs @@ -4,24 +4,23 @@ using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Shouldly; using Volo.Abp.Modularity; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +[DependsOn( + typeof(SmartContractExecutionAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(SmartContractTestAElfModule) +)] +public class SmartContractExecutionTestAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractExecutionAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(SmartContractTestAElfModule) - )] - public class SmartContractExecutionTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services.Replace(ServiceDescriptor.Singleton()); - } + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services.Replace(ServiceDescriptor + .Singleton()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestBase.cs b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestBase.cs index b5753de8db..99dafef28e 100644 --- a/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestBase.cs +++ b/test/AElf.Kernel.SmartContractExecution.Tests/SmartContractExecutionTestBase.cs @@ -1,24 +1,19 @@ using AElf.TestBase; -namespace AElf.Kernel.SmartContractExecution +namespace AElf.Kernel.SmartContractExecution; + +public class SmartContractExecutionTestBase : AElfIntegratedTest { - public class SmartContractExecutionTestBase : AElfIntegratedTest - { - - } - - public class SmartContractExecutionExecutingTestBase : AElfIntegratedTest - { - - } +} - public class ValidateBeforeFailedTestBase : AElfIntegratedTest - { - - } +public class SmartContractExecutionExecutingTestBase : AElfIntegratedTest +{ +} - public class ValidateAfterFailedTestBase : AElfIntegratedTest - { - - } +public class ValidateBeforeFailedTestBase : AElfIntegratedTest +{ +} + +public class ValidateAfterFailedTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.Kernel.TestBase/KernelTestHelper.cs b/test/AElf.Kernel.TestBase/KernelTestHelper.cs index abf6f791d7..1aed1b336a 100644 --- a/test/AElf.Kernel.TestBase/KernelTestHelper.cs +++ b/test/AElf.Kernel.TestBase/KernelTestHelper.cs @@ -10,311 +10,285 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class KernelTestHelper { - public class KernelTestHelper + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IChainManager _chainManager; + private readonly ITransactionResultService _transactionResultService; + public ECKeyPair KeyPair = CryptoHelper.GenerateKeyPair(); + + public KernelTestHelper(IBlockchainService blockchainService, + ITransactionResultService transactionResultService, + IChainManager chainManager, IBlockStateSetManger blockStateSetManger) { - public ECKeyPair KeyPair = CryptoHelper.GenerateKeyPair(); - private readonly IBlockchainService _blockchainService; - private readonly ITransactionResultService _transactionResultService; - private readonly IChainManager _chainManager; - private readonly IBlockStateSetManger _blockStateSetManger; - - /// - /// 12 Blocks: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - /// - public List BestBranchBlockList { get; set; } - - /// - /// 5 Blocks: l -> m -> n -> o -> p - /// - public List LongestBranchBlockList { get; set; } - - /// - /// 5 Blocks: q -> r -> s -> t -> u - /// - public List ForkBranchBlockList { get; set; } - - /// - /// 5 Blocks: v -> w -> x -> y -> z - /// - public List NotLinkedBlockList { get; set; } - - public KernelTestHelper(IBlockchainService blockchainService, - ITransactionResultService transactionResultService, - IChainManager chainManager, IBlockStateSetManger blockStateSetManger) - { - BestBranchBlockList = new List(); - LongestBranchBlockList = new List(); - ForkBranchBlockList = new List(); - NotLinkedBlockList = new List(); - - _blockchainService = blockchainService; - _transactionResultService = transactionResultService; - _chainManager = chainManager; - _blockStateSetManger = blockStateSetManger; - } + BestBranchBlockList = new List(); + LongestBranchBlockList = new List(); + ForkBranchBlockList = new List(); + NotLinkedBlockList = new List(); + + _blockchainService = blockchainService; + _transactionResultService = transactionResultService; + _chainManager = chainManager; + _blockStateSetManger = blockStateSetManger; + } - /// - /// Mock a chain with a best branch, and some fork branches - /// - /// - /// Mock Chain - /// BestChainHeight: 11 - /// LongestChainHeight: 13 - /// LIB height: 5 - /// - /// Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18 -> 19 - /// Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - /// Longest Branch: (h)-> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> v - /// Fork Branch: (e)-> q -> r -> s -> t -> u - /// Unlinked Branch: v -> w -> x -> y -> z - /// - public async Task MockChainAsync() - { - var chain = await CreateChain(); + /// + /// 12 Blocks: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + /// + public List BestBranchBlockList { get; set; } + + /// + /// 5 Blocks: l -> m -> n -> o -> p + /// + public List LongestBranchBlockList { get; set; } + + /// + /// 5 Blocks: q -> r -> s -> t -> u + /// + public List ForkBranchBlockList { get; set; } + + /// + /// 5 Blocks: v -> w -> x -> y -> z + /// + public List NotLinkedBlockList { get; set; } + + /// + /// Mock a chain with a best branch, and some fork branches + /// + /// + /// Mock Chain + /// BestChainHeight: 11 + /// LongestChainHeight: 13 + /// LIB height: 5 + /// Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18 -> 19 + /// Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + /// Longest Branch: (h)-> l -> m -> n -> o -> p -> q -> r -> s -> t -> u -> + /// v + /// Fork Branch: (e)-> q -> r -> s -> t -> u + /// Unlinked Branch: v -> w -> x -> y -> z + /// + public async Task MockChainAsync() + { + var chain = await CreateChain(); - var genesisBlock = await _blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); - BestBranchBlockList.Add(genesisBlock); + var genesisBlock = await _blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); + BestBranchBlockList.Add(genesisBlock); - BestBranchBlockList.AddRange(await AddBestBranch()); + BestBranchBlockList.AddRange(await AddBestBranch()); - LongestBranchBlockList = - await AddForkBranch(BestBranchBlockList[7].Height, BestBranchBlockList[7].GetHash(), 11); + LongestBranchBlockList = + await AddForkBranch(BestBranchBlockList[7].Height, BestBranchBlockList[7].GetHash(), 11); - foreach (var block in LongestBranchBlockList) - { - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, - ChainBlockLinkExecutionStatus.ExecutionFailed); - } + foreach (var block in LongestBranchBlockList) + { + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, + ChainBlockLinkExecutionStatus.ExecutionFailed); + } - ForkBranchBlockList = - await AddForkBranch(BestBranchBlockList[4].Height, BestBranchBlockList[4].GetHash()); + ForkBranchBlockList = + await AddForkBranch(BestBranchBlockList[4].Height, BestBranchBlockList[4].GetHash()); - NotLinkedBlockList = await AddForkBranch(9, HashHelper.ComputeFrom("UnlinkBlock")); - // Set lib - chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, BestBranchBlockList[4].Height, - BestBranchBlockList[4].GetHash()); + NotLinkedBlockList = await AddForkBranch(9, HashHelper.ComputeFrom("UnlinkBlock")); + // Set lib + chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, BestBranchBlockList[4].Height, + BestBranchBlockList[4].GetHash()); - return chain; - } + return chain; + } - public Transaction GenerateTransaction(long refBlockNumber = 0, Hash refBlockHash = null) + public Transaction GenerateTransaction(long refBlockNumber = 0, Hash refBlockHash = null) + { + var transaction = new Transaction { - var transaction = new Transaction - { - From = Address.FromPublicKey(KeyPair.PublicKey), - To = SampleAddress.AddressList[0], - MethodName = Guid.NewGuid().ToString(), - Params = ByteString.Empty, - RefBlockNumber = refBlockNumber, - RefBlockPrefix = refBlockHash == null - ? ByteString.Empty - : ByteString.CopyFrom(refBlockHash.ToByteArray().Take(4).ToArray()) - }; - - var signature = CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - return transaction; - } + From = Address.FromPublicKey(KeyPair.PublicKey), + To = SampleAddress.AddressList[0], + MethodName = Guid.NewGuid().ToString(), + Params = ByteString.Empty, + RefBlockNumber = refBlockNumber, + RefBlockPrefix = refBlockHash == null + ? ByteString.Empty + : ByteString.CopyFrom(refBlockHash.ToByteArray().Take(4).ToArray()) + }; + + var signature = CryptoHelper.SignWithPrivateKey(KeyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + return transaction; + } - public List GenerateTransactions(int count, long refBlockNumber = 0, Hash refBlockHash = null) - { - var transactions = new List(); - for (int i = 0; i < count; i++) - { - transactions.Add(GenerateTransaction(refBlockNumber, refBlockHash)); - } + public List GenerateTransactions(int count, long refBlockNumber = 0, Hash refBlockHash = null) + { + var transactions = new List(); + for (var i = 0; i < count; i++) transactions.Add(GenerateTransaction(refBlockNumber, refBlockHash)); - return transactions; - } + return transactions; + } - public TransactionResult GenerateTransactionResult(Transaction transaction, TransactionResultStatus status, - LogEvent logEvent = null) + public TransactionResult GenerateTransactionResult(Transaction transaction, TransactionResultStatus status, + LogEvent logEvent = null) + { + var transactionResult = new TransactionResult { - var transactionResult = new TransactionResult - { - TransactionId = transaction.GetHash(), - Status = status - }; + TransactionId = transaction.GetHash(), + Status = status + }; - if (logEvent != null) - { - transactionResult.Logs.Add(logEvent); - } + if (logEvent != null) transactionResult.Logs.Add(logEvent); - transactionResult.UpdateBloom(); - return transactionResult; - } + transactionResult.UpdateBloom(); + return transactionResult; + } - public Block GenerateBlock(long previousBlockHeight, Hash previousBlockHash, - List transactions = null, Dictionary extraData = null) + public Block GenerateBlock(long previousBlockHeight, Hash previousBlockHash, + List transactions = null, Dictionary extraData = null) + { + var newBlock = new Block { - - var newBlock = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - Height = previousBlockHeight + 1, - PreviousBlockHash = previousBlockHash, - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfWorldState = Hash.Empty, - MerkleTreeRootOfTransactionStatus = Hash.Empty, - MerkleTreeRootOfTransactions = Hash.Empty, - SignerPubkey = ByteString.CopyFrom(KeyPair.PublicKey) - }, - Body = new BlockBody() - }; - - if (extraData != null) - newBlock.Header.ExtraData.Add(extraData); - - if (transactions != null) - { - foreach (var transaction in transactions) - { - newBlock.AddTransaction(transaction); - } - - newBlock.Header.MerkleTreeRootOfTransactions = newBlock.Body.CalculateMerkleTreeRoot(); - } + Height = previousBlockHeight + 1, + PreviousBlockHash = previousBlockHash, + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfWorldState = Hash.Empty, + MerkleTreeRootOfTransactionStatus = Hash.Empty, + MerkleTreeRootOfTransactions = Hash.Empty, + SignerPubkey = ByteString.CopyFrom(KeyPair.PublicKey) + }, + Body = new BlockBody() + }; + + if (extraData != null) + newBlock.Header.ExtraData.Add(extraData); + + if (transactions != null) + { + foreach (var transaction in transactions) newBlock.AddTransaction(transaction); - return newBlock; + newBlock.Header.MerkleTreeRootOfTransactions = newBlock.Body.CalculateMerkleTreeRoot(); } - public async Task AttachBlock(long previousBlockHeight, Hash previousBlockHash, - List transactions = null, List transactionResults = null) - { - if (transactions == null || transactions.Count == 0) - { - transactions = new List(); - } + return newBlock; + } - if (transactions.Count == 0) - { - transactions.Add(GenerateTransaction()); - } + public async Task AttachBlock(long previousBlockHeight, Hash previousBlockHash, + List transactions = null, List transactionResults = null) + { + if (transactions == null || transactions.Count == 0) transactions = new List(); - if (transactionResults == null) - { - transactionResults = new List(); - } + if (transactions.Count == 0) transactions.Add(GenerateTransaction()); - if (transactionResults.Count == 0) - { - foreach (var transaction in transactions) - { - transactionResults.Add(GenerateTransactionResult(transaction, TransactionResultStatus.Mined)); - } - } + if (transactionResults == null) transactionResults = new List(); - var newBlock = GenerateBlock(previousBlockHeight, previousBlockHash, transactions); + if (transactionResults.Count == 0) + foreach (var transaction in transactions) + transactionResults.Add(GenerateTransactionResult(transaction, TransactionResultStatus.Mined)); - var bloom = new Bloom(); - foreach (var transactionResult in transactionResults) - { - transactionResult.UpdateBloom(); - if (transactionResult.Status == TransactionResultStatus.Mined) - { - bloom.Combine(new[] {new Bloom(transactionResult.Bloom.ToByteArray())}); - } - } + var newBlock = GenerateBlock(previousBlockHeight, previousBlockHash, transactions); - newBlock.Header.Bloom = ByteString.CopyFrom(bloom.Data); + var bloom = new Bloom(); + foreach (var transactionResult in transactionResults) + { + transactionResult.UpdateBloom(); + if (transactionResult.Status == TransactionResultStatus.Mined) + bloom.Combine(new[] { new Bloom(transactionResult.Bloom.ToByteArray()) }); + } - await _transactionResultService.AddTransactionResultsAsync(transactionResults, newBlock.Header); + newBlock.Header.Bloom = ByteString.CopyFrom(bloom.Data); - await _blockchainService.AddBlockAsync(newBlock); - await _blockchainService.AddTransactionsAsync(transactions); - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.AttachBlockToChainAsync(chain, newBlock); + await _transactionResultService.AddTransactionResultsAsync(transactionResults, newBlock.Header); - return newBlock; - } + await _blockchainService.AddBlockAsync(newBlock); + await _blockchainService.AddTransactionsAsync(transactions); + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.AttachBlockToChainAsync(chain, newBlock); - public async Task AttachBlockToBestChain(List transactions = null, - List transactionResults = null) + return newBlock; + } + + public async Task AttachBlockToBestChain(List transactions = null, + List transactionResults = null) + { + var chain = await _blockchainService.GetChainAsync(); + var block = await AttachBlock(chain.BestChainHeight, chain.BestChainHash, transactions, transactionResults); + var blockStateSet = new BlockStateSet { - var chain = await _blockchainService.GetChainAsync(); - var block = await AttachBlock(chain.BestChainHeight, chain.BestChainHash, transactions, transactionResults); - var blockStateSet = new BlockStateSet - { - BlockHash = block.GetHash(), - BlockHeight = block.Height, - PreviousHash = block.Header.PreviousBlockHash - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - - chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); + BlockHash = block.GetHash(), + BlockHeight = block.Height, + PreviousHash = block.Header.PreviousBlockHash + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); - await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, - ChainBlockLinkExecutionStatus.ExecutionSuccess); + chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetBestChainAsync(chain, block.Height, block.GetHash()); - return block; - } + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(block.GetHash()); + await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, + ChainBlockLinkExecutionStatus.ExecutionSuccess); - public async Task GetChainContextAsync() - { - var chain = await _blockchainService.GetChainAsync(); - return new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - } - - public async Task CreateChain() + return block; + } + + public async Task GetChainContextAsync() + { + var chain = await _blockchainService.GetChainAsync(); + return new ChainContext { - var genesisBlock = GenerateBlock(0, Hash.Empty, new List()); + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + } - var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); + public async Task CreateChain() + { + var genesisBlock = GenerateBlock(0, Hash.Empty, new List()); - return chain; - } + var chain = await _blockchainService.CreateChainAsync(genesisBlock, new List()); - #region private methods + return chain; + } - private async Task> AddBestBranch() - { - var bestBranchBlockList = new List(); + #region private methods - for (var i = 0; i < 10; i++) - { - var chain = await _blockchainService.GetChainAsync(); - var newBlock = await AttachBlock(chain.BestChainHeight, chain.BestChainHash); - bestBranchBlockList.Add(newBlock); + private async Task> AddBestBranch() + { + var bestBranchBlockList = new List(); - var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(newBlock.GetHash()); - await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, - ChainBlockLinkExecutionStatus.ExecutionSuccess); + for (var i = 0; i < 10; i++) + { + var chain = await _blockchainService.GetChainAsync(); + var newBlock = await AttachBlock(chain.BestChainHeight, chain.BestChainHash); + bestBranchBlockList.Add(newBlock); - chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash()); - } + var chainBlockLink = await _chainManager.GetChainBlockLinkAsync(newBlock.GetHash()); + await _chainManager.SetChainBlockLinkExecutionStatusAsync(chainBlockLink, + ChainBlockLinkExecutionStatus.ExecutionSuccess); - return bestBranchBlockList; + chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash()); } - private async Task> AddForkBranch(long previousHeight, Hash previousHash, int count = 5) - { - var forkBranchBlockList = new List(); + return bestBranchBlockList; + } - for (var i = 0; i < count; i++) - { - var newBlock = await AttachBlock(previousHeight, previousHash); - forkBranchBlockList.Add(newBlock); + private async Task> AddForkBranch(long previousHeight, Hash previousHash, int count = 5) + { + var forkBranchBlockList = new List(); - previousHeight++; - previousHash = newBlock.GetHash(); - } + for (var i = 0; i < count; i++) + { + var newBlock = await AttachBlock(previousHeight, previousHash); + forkBranchBlockList.Add(newBlock); - return forkBranchBlockList; + previousHeight++; + previousHash = newBlock.GetHash(); } - #endregion + return forkBranchBlockList; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Kernel.TestBase/SampleAddress.cs b/test/AElf.Kernel.TestBase/SampleAddress.cs index 95d789026e..d20c8e567d 100644 --- a/test/AElf.Kernel.TestBase/SampleAddress.cs +++ b/test/AElf.Kernel.TestBase/SampleAddress.cs @@ -1,32 +1,31 @@ -using AElf.Types; -using System.Linq; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; +using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public static class SampleAddress { - public static class SampleAddress - { - public static readonly IReadOnlyList
AddressList; + public static readonly IReadOnlyList
AddressList; - private static readonly string[] Base58Strings = - { - "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", - "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", - "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", - "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", - "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", - "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", - "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", - "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", - "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", - "ZJjdajAmP5HpWgvLkXa5mm6gcuGWwKjN3Kos89ZJogHYDgTsB" - }; + private static readonly string[] Base58Strings = + { + "2EM5uV6bSJh6xJfZTUa1pZpYsYcCUAdPvZvFUJzMDJEx3rbioz", + "2ktxGpyiYCjFU5KwuXtbBckczX6uPmEtesJEsQPqMukcHZFY9a", + "2LdrKw6vi2uWSSGhiS1MBUPANFuhJzBPYDsQ65Jm7C2uEy5KKW", + "2ohojn441KmsVkaDS3wEL928gbpan352ZJ5ruMFxoa8iorUce", + "2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7", + "4v9cdSsn2PmZuFCxoSZhtY7Q2yUjdTNz6sQQdHNibdgaRg8Wx", + "9Njc5pXW9Rw499wqSJzrfQuJQFVCcWnLNjZispJM4LjKmRPyq", + "Lib8JSzdsFC7uCwvEwviadh3kp9LzaLMCauK4fSzrwc2qtHVi", + "LYKSAU799wDphRK7W5ZsMBF2vDG8ijeuESk1R7Xpi6hBpdnX4", + "ZJjdajAmP5HpWgvLkXa5mm6gcuGWwKjN3Kos89ZJogHYDgTsB" + }; - static SampleAddress() - { - AddressList = new ReadOnlyCollection
( - Base58Strings.Select(Address.FromBase58).ToList()); - } + static SampleAddress() + { + AddressList = new ReadOnlyCollection
( + Base58Strings.Select(Address.FromBase58).ToList()); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TestBase/TestBaseKernelAElfModule.cs b/test/AElf.Kernel.TestBase/TestBaseKernelAElfModule.cs index ecc41c5fc9..ab0578bc66 100644 --- a/test/AElf.Kernel.TestBase/TestBaseKernelAElfModule.cs +++ b/test/AElf.Kernel.TestBase/TestBaseKernelAElfModule.cs @@ -5,20 +5,19 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(TestBaseAElfModule), typeof(CoreKernelAElfModule))] +public class TestBaseKernelAElfModule : AElfModule { - [DependsOn( - typeof(TestBaseAElfModule), typeof(CoreKernelAElfModule))] - public class TestBaseKernelAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); + services.AddKeyValueDbContext(o => o.UseInMemoryDatabase()); - services.AddSingleton(); - } + services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/AElf.Kernel.Tests.csproj b/test/AElf.Kernel.Tests/AElf.Kernel.Tests.csproj index f3fa53aa93..c3bf9780ac 100644 --- a/test/AElf.Kernel.Tests/AElf.Kernel.Tests.csproj +++ b/test/AElf.Kernel.Tests/AElf.Kernel.Tests.csproj @@ -5,19 +5,19 @@ false - - - - - - + + + + + + - - - - - - + + + + + + diff --git a/test/AElf.Kernel.Tests/BlockTemplateMinerServiceTests.cs b/test/AElf.Kernel.Tests/BlockTemplateMinerServiceTests.cs index a2505537f5..70a83c960c 100644 --- a/test/AElf.Kernel.Tests/BlockTemplateMinerServiceTests.cs +++ b/test/AElf.Kernel.Tests/BlockTemplateMinerServiceTests.cs @@ -2,95 +2,84 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Miner.Application; -using AElf.Types; -using Castle.Core.Internal; using Google.Protobuf; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class BlockTemplateMinerServiceTests : KernelWithChainTestBase { - public class BlockTemplateMinerServiceTests : KernelWithChainTestBase + private readonly IBlockchainService _chainService; + private readonly IBlockTemplateMinerService _minerService; + + public BlockTemplateMinerServiceTests() { - private IBlockTemplateMinerService _minerService; - private IBlockchainService _chainService; + _chainService = GetRequiredService(); + _minerService = GetRequiredService(); + } - public BlockTemplateMinerServiceTests() - { - _chainService = GetRequiredService(); - _minerService = GetRequiredService(); - } + [Fact] + public async Task MinAsync_Success_Test() + { + var chain = await _chainService.GetChainAsync(); + var hash = chain.BestChainHash; + var height = chain.BestChainHeight; - [Fact] - public async Task MinAsync_Success_Test() - { - var chain = await _chainService.GetChainAsync(); - var hash = chain.BestChainHash; - var height = chain.BestChainHeight; + var blockHeader = await _minerService.CreateTemplateCacheAsync(hash, height, TimestampHelper.GetUtcNow(), + TimestampHelper.DurationFromMinutes(1)); - var blockHeader = await _minerService.CreateTemplateCacheAsync(hash, height, TimestampHelper.GetUtcNow(), - TimestampHelper.DurationFromMinutes(1)); + var byteString = blockHeader.ToByteString(); - var byteString = blockHeader.ToByteString(); + var bytes = byteString.ToByteArray(); - var bytes = byteString.ToByteArray(); + //Send Bytes to Client - //Send Bytes to Client + #region Client Side - #region Client Side + //Client side, you can search nonce and replace it - //Client side, you can search nonce and replace it + var nonce = BitConverter.GetBytes(long.MaxValue - 1); - var nonce = BitConverter.GetBytes(long.MaxValue - 1); + var start = bytes.Find(nonce); - var start = bytes.Find(nonce); + start.ShouldBeGreaterThan(0); - start.ShouldBeGreaterThan(0); + for (var i = 0; i < nonce.Length; i++) bytes[start + i] = 9; //change nonce - for (int i = 0; i < nonce.Length; i++) - { - bytes[start + i] = 9; //change nonce - } + bytes.Find(nonce).ShouldBe(-1); - bytes.Find(nonce).ShouldBe(-1); + var newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes)); - var newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes)); + //Test mining method + newHeader.GetHash().ShouldBe(HashHelper.ComputeFrom(newHeader.ToByteArray())); + newHeader.GetHash().ShouldBe(HashHelper.ComputeFrom(bytes)); - //Test mining method - newHeader.GetHash().ShouldBe(HashHelper.ComputeFrom(newHeader.ToByteArray())); - newHeader.GetHash().ShouldBe(HashHelper.ComputeFrom(bytes)); + //Start mining - //Start mining + var r = new Random(); - Random r = new Random(); + while (HashHelper.ComputeFrom(bytes).Value[0] != 0) + //find first hash byte is 0 - while (HashHelper.ComputeFrom(bytes).Value[0] != 0) - { - //find first hash byte is 0 + for (var i = 0; i < nonce.Length; i++) + bytes[start + i] = (byte)r.Next(); //change nonce, very slow, just for demo - for (int i = 0; i < nonce.Length; i++) - { - bytes[start + i] = (byte) r.Next(); //change nonce, very slow, just for demo - } - } + #endregion - #endregion + //Send bytes to Server - //Send bytes to Server + newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes)); - newHeader = BlockHeader.Parser.ParseFrom(ByteString.CopyFrom(bytes)); + var newHeaderHash = newHeader.GetHash(); - var newHeaderHash = newHeader.GetHash(); + newHeaderHash.Value[0].ShouldBe((byte)0); // first byte should be zero - newHeaderHash.Value[0].ShouldBe((byte) 0); // first byte should be zero + var block = await _minerService.ChangeTemplateCacheBlockHeaderAndClearCacheAsync(newHeader); - var block = await _minerService.ChangeTemplateCacheBlockHeaderAndClearCacheAsync(newHeader); - - block.GetHash().ShouldBe(newHeader.GetHash()); // check new block's header - block.Header.Signature.ShouldBeEmpty(); // check signature - } + block.GetHash().ShouldBe(newHeader.GetHash()); // check new block's header + block.Header.Signature.ShouldBeEmpty(); // check signature } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/ConsensusRequestMiningEventHandlerTests.cs b/test/AElf.Kernel.Tests/ConsensusRequestMiningEventHandlerTests.cs index 13b35fb04b..fd6ffd6e34 100644 --- a/test/AElf.Kernel.Tests/ConsensusRequestMiningEventHandlerTests.cs +++ b/test/AElf.Kernel.Tests/ConsensusRequestMiningEventHandlerTests.cs @@ -2,104 +2,101 @@ using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus; -using AElf.Kernel.Consensus.Application; using AElf.Kernel.Infrastructure; -using Autofac.Core; using Moq; using Shouldly; using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class ConsensusRequestMiningEventHandlerTests : KernelConsensusRequestMiningTestBase { - public class ConsensusRequestMiningEventHandlerTests : KernelConsensusRequestMiningTestBase + private readonly IBlockchainService _blockchainService; + private readonly ConsensusRequestMiningEventHandler _consensusRequestMiningEventHandler; + private readonly ILocalEventBus _localEventBus; + private readonly KernelConsensusRequestMiningTestContext _testContext; + + public ConsensusRequestMiningEventHandlerTests() { - private readonly IBlockchainService _blockchainService; - private readonly ConsensusRequestMiningEventHandler _consensusRequestMiningEventHandler; - private readonly ILocalEventBus _localEventBus; - private readonly KernelConsensusRequestMiningTestContext _testContext; + _blockchainService = GetRequiredService(); + _consensusRequestMiningEventHandler = GetRequiredService(); + _localEventBus = GetRequiredService(); + _testContext = GetRequiredService(); + } - public ConsensusRequestMiningEventHandlerTests() + [Fact] + public async Task HandleEvent_Test() + { + BlockMinedEventData blockMinedEventData = null; + _localEventBus.Subscribe(d => { - _blockchainService = GetRequiredService(); - _consensusRequestMiningEventHandler = GetRequiredService(); - _localEventBus = GetRequiredService(); - _testContext = GetRequiredService(); - } + blockMinedEventData = d; + return Task.CompletedTask; + }); + + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + _testContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(10)); - [Fact] - public async Task HandleEvent_Test() { - BlockMinedEventData blockMinedEventData = null; - _localEventBus.Subscribe(d => - { - blockMinedEventData = d; - return Task.CompletedTask; - }); - - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - + var eventData = new ConsensusRequestMiningEventData(HashHelper.ComputeFrom("NotBestChain"), + bestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), + TimestampHelper.GetUtcNow().AddMilliseconds(499)); + + await HandleConsensusRequestMiningEventAsync(eventData); + blockMinedEventData.ShouldBeNull(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(bestChainHeight); + chain.BestChainHash.ShouldBe(bestChainHash); + _testContext.MockConsensusService.Verify( s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(10)); + } + + { + var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), + TimestampHelper.GetUtcNow().AddMilliseconds(499)); + + await HandleConsensusRequestMiningEventAsync(eventData); + blockMinedEventData.ShouldBeNull(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(bestChainHeight); + chain.BestChainHash.ShouldBe(bestChainHash); - { - var eventData = new ConsensusRequestMiningEventData(HashHelper.ComputeFrom("NotBestChain"), - bestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), - TimestampHelper.GetUtcNow().AddMilliseconds(499)); - - await HandleConsensusRequestMiningEventAsync(eventData); - blockMinedEventData.ShouldBeNull(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(bestChainHeight); - chain.BestChainHash.ShouldBe(bestChainHash); - - _testContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(10)); - } - - { - var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), - TimestampHelper.GetUtcNow().AddMilliseconds(499)); - - await HandleConsensusRequestMiningEventAsync(eventData); - blockMinedEventData.ShouldBeNull(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(bestChainHeight); - chain.BestChainHash.ShouldBe(bestChainHash); - - _testContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(11)); - } - - { - var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), - TimestampHelper.GetUtcNow().AddSeconds(30)); - - await HandleConsensusRequestMiningEventAsync(eventData); - blockMinedEventData.ShouldNotBeNull(); - blockMinedEventData.BlockHeader.Height.ShouldBe(bestChainHeight +1); - blockMinedEventData.BlockHeader.PreviousBlockHash.ShouldBe(bestChainHash); - - chain = await _blockchainService.GetChainAsync(); - chain.Branches.ShouldContainKey(blockMinedEventData.BlockHeader.GetHash().ToStorageKey()); - - (await _blockchainService.HasBlockAsync(blockMinedEventData.BlockHeader.GetHash())).ShouldBeTrue(); - - _testContext.MockConsensusService.Verify( - s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(11)); - } + _testContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(11)); } - private async Task HandleConsensusRequestMiningEventAsync( - ConsensusRequestMiningEventData consensusRequestMiningEventData) { - await _consensusRequestMiningEventHandler.HandleEventAsync(consensusRequestMiningEventData); - await Task.Delay(500); + var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500), + TimestampHelper.GetUtcNow().AddSeconds(30)); + + await HandleConsensusRequestMiningEventAsync(eventData); + blockMinedEventData.ShouldNotBeNull(); + blockMinedEventData.BlockHeader.Height.ShouldBe(bestChainHeight + 1); + blockMinedEventData.BlockHeader.PreviousBlockHash.ShouldBe(bestChainHash); + + chain = await _blockchainService.GetChainAsync(); + chain.Branches.ShouldContainKey(blockMinedEventData.BlockHeader.GetHash().ToStorageKey()); + + (await _blockchainService.HasBlockAsync(blockMinedEventData.BlockHeader.GetHash())).ShouldBeTrue(); + + _testContext.MockConsensusService.Verify( + s => s.TriggerConsensusAsync(It.IsAny()), Times.Exactly(11)); } } + + private async Task HandleConsensusRequestMiningEventAsync( + ConsensusRequestMiningEventData consensusRequestMiningEventData) + { + await _consensusRequestMiningEventHandler.HandleEventAsync(consensusRequestMiningEventData); + await Task.Delay(500); + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/KernelTestAElfModule.cs b/test/AElf.Kernel.Tests/KernelTestAElfModule.cs index a9c2a3835a..095a446329 100644 --- a/test/AElf.Kernel.Tests/KernelTestAElfModule.cs +++ b/test/AElf.Kernel.Tests/KernelTestAElfModule.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Threading; using System.Threading.Tasks; using AElf.Kernel.Account.Application; using AElf.Kernel.Account.Infrastructure; @@ -19,163 +17,158 @@ using AElf.Modularity; using AElf.Types; using Google.Protobuf; -using Google.Protobuf.Collections; -using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Moq; -using NSubstitute; using Volo.Abp; using Volo.Abp.Modularity; -using Volo.Abp.Threading; using BlockValidationProvider = AElf.Kernel.Miner.Application.BlockValidationProvider; -namespace AElf.Kernel +namespace AElf.Kernel; + +[DependsOn( + typeof(KernelAElfModule), + typeof(SmartContractTestAElfModule), + typeof(SmartContractExecutionTestAElfModule), + typeof(TransactionPoolTestAElfModule), + typeof(ChainControllerTestAElfModule) +)] +public class KernelTestAElfModule : AElfModule { - [DependsOn( - typeof(KernelAElfModule), - typeof(SmartContractTestAElfModule), - typeof(SmartContractExecutionTestAElfModule), - typeof(TransactionPoolTestAElfModule), - typeof(ChainControllerTestAElfModule) - )] - public class KernelTestAElfModule : AElfModule - { - } +} - [DependsOn( - typeof(KernelTestAElfModule), - typeof(KernelCoreWithChainTestAElfModule))] - public class KernelWithChainTestAElfModule : AElfModule +[DependsOn( + typeof(KernelTestAElfModule), + typeof(KernelCoreWithChainTestAElfModule))] +public class KernelWithChainTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + var transactionList = new List { - var services = context.Services; - var transactionList = new List - { - new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[1], - MethodName = "GenerateConsensusTransactions" - } - }; - services.AddTransient(o => + new() { - var mockService = new Mock(); - mockService.Setup(m => - m.GenerateTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())); + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[1], + MethodName = "GenerateConsensusTransactions" + } + }; + services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(m => + m.GenerateTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())); - return mockService.Object; - }); + return mockService.Object; + }); - services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(m => - m.GenerateSystemTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(transactionList)); + services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(m => + m.GenerateSystemTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(transactionList)); - return mockService.Object; - }); + return mockService.Object; + }); - services.AddTransient(); + services.AddTransient(); - //For BlockExtraDataService testing. - services.AddTransient( - builder => - { - var dataProvider = new Mock(); + //For BlockExtraDataService testing. + services.AddTransient( + builder => + { + var dataProvider = new Mock(); - ByteString bs = ByteString.CopyFrom(BitConverter.GetBytes(long.MaxValue - 1)); + var bs = ByteString.CopyFrom(BitConverter.GetBytes(long.MaxValue - 1)); - dataProvider.Setup(m => m.GetBlockHeaderExtraDataAsync(It.IsAny())) - .Returns(Task.FromResult(bs)); + dataProvider.Setup(m => m.GetBlockHeaderExtraDataAsync(It.IsAny())) + .Returns(Task.FromResult(bs)); - dataProvider.Setup(d => d.BlockHeaderExtraDataKey).Returns("TestExtraDataKey"); + dataProvider.Setup(d => d.BlockHeaderExtraDataKey).Returns("TestExtraDataKey"); - return dataProvider.Object; - }); - services.AddTransient(provider => - { - var mockService = new Mock(); - return mockService.Object; + return dataProvider.Object; }); + services.AddTransient(provider => + { + var mockService = new Mock(); + return mockService.Object; + }); - services.AddTransient(); - } + services.AddTransient(); } +} - [DependsOn(typeof(KernelWithChainTestAElfModule))] - public class KernelMiningTestAElfModule : AElfModule +[DependsOn(typeof(KernelWithChainTestAElfModule))] +public class KernelMiningTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - context.Services.AddTransient(); + context.Services.AddTransient(); - services.AddSingleton(provider => - { - var mockService = new Mock(); - mockService.Setup(m => - m.ValidateTransactionWhileCollectingAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(true)); + services.AddSingleton(provider => + { + var mockService = new Mock(); + mockService.Setup(m => + m.ValidateTransactionWhileCollectingAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(true)); - return mockService.Object; - }); + return mockService.Object; + }); - services.AddTransient(provider => - { - var mockService = new Mock(); - return mockService.Object; - }); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) + services.AddTransient(provider => { - var kernelTestHelper = context.ServiceProvider.GetRequiredService(); - var ecKeyPairProvider = context.ServiceProvider.GetService(); - ecKeyPairProvider.SetKeyPair(kernelTestHelper.KeyPair); - } + var mockService = new Mock(); + return mockService.Object; + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var kernelTestHelper = context.ServiceProvider.GetRequiredService(); + var ecKeyPairProvider = context.ServiceProvider.GetService(); + ecKeyPairProvider.SetKeyPair(kernelTestHelper.KeyPair); } +} - [DependsOn(typeof(KernelMiningTestAElfModule), typeof(CoreConsensusAElfModule))] - public class KernelConsensusRequestMiningTestAElfModule : AElfModule +[DependsOn(typeof(KernelMiningTestAElfModule), typeof(CoreConsensusAElfModule))] +public class KernelConsensusRequestMiningTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + + services.AddTransient(provider => { - var services = context.Services; - - services.AddTransient(provider => - { - var mockService = new Mock(); - return mockService.Object; - }); + var mockService = new Mock(); + return mockService.Object; + }); - var consensusRequestMiningTestContext = new KernelConsensusRequestMiningTestContext(); - - services.AddSingleton(builder => - { - var mockConsensusService = new Mock(); + var consensusRequestMiningTestContext = new KernelConsensusRequestMiningTestContext(); - consensusRequestMiningTestContext.MockConsensusService = mockConsensusService; + services.AddSingleton(builder => + { + var mockConsensusService = new Mock(); - return mockConsensusService.Object; - }); + consensusRequestMiningTestContext.MockConsensusService = mockConsensusService; - services.AddSingleton(consensusRequestMiningTestContext); + return mockConsensusService.Object; + }); - services.AddTransient(provider => - { - var mockService = new Mock(); - return mockService.Object; - }); - } - } + services.AddSingleton(consensusRequestMiningTestContext); - public class KernelConsensusRequestMiningTestContext - { - public Mock MockConsensusService { get; set; } + services.AddTransient(provider => + { + var mockService = new Mock(); + return mockService.Object; + }); } } + +public class KernelConsensusRequestMiningTestContext +{ + public Mock MockConsensusService { get; set; } +} \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/KernelTestBase.cs b/test/AElf.Kernel.Tests/KernelTestBase.cs index c8a25ed673..a42e2f7f01 100644 --- a/test/AElf.Kernel.Tests/KernelTestBase.cs +++ b/test/AElf.Kernel.Tests/KernelTestBase.cs @@ -1,25 +1,19 @@ using AElf.TestBase; -namespace AElf.Kernel -{ - public class KernelTestBase : AElfIntegratedTest - { - - } - - public class KernelWithChainTestBase : AElfIntegratedTest - { +namespace AElf.Kernel; - } +public class KernelTestBase : AElfIntegratedTest +{ +} - public class KernelMiningTestBase : AElfIntegratedTest - { +public class KernelWithChainTestBase : AElfIntegratedTest +{ +} - } - - - public class KernelConsensusRequestMiningTestBase : AElfIntegratedTest - { +public class KernelMiningTestBase : AElfIntegratedTest +{ +} - } +public class KernelConsensusRequestMiningTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/Application/BlockValidationProviderTests.cs b/test/AElf.Kernel.Tests/Miner/Application/BlockValidationProviderTests.cs index 4d3f481eba..84a29c04a5 100644 --- a/test/AElf.Kernel.Tests/Miner/Application/BlockValidationProviderTests.cs +++ b/test/AElf.Kernel.Tests/Miner/Application/BlockValidationProviderTests.cs @@ -1,86 +1,83 @@ -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AElf.Kernel.SmartContract.Domain; using AElf.Types; -using Moq; using Shouldly; using Xunit; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class BlockValidationProviderTests : KernelWithChainTestBase { - public class BlockValidationProviderTests : KernelWithChainTestBase - { - private readonly BlockValidationProvider _blockValidationProvider; - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly KernelTestHelper _kernelTestHelper; - private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly BlockValidationProvider _blockValidationProvider; + private readonly KernelTestHelper _kernelTestHelper; - public BlockValidationProviderTests() - { - _blockValidationProvider = GetRequiredService(); - _blockTransactionLimitProvider = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } + public BlockValidationProviderTests() + { + _blockValidationProvider = GetRequiredService(); + _blockTransactionLimitProvider = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } - [Fact] - public async Task ValidateBlockBeforeExecute_Test() + [Fact] + public async Task ValidateBlockBeforeExecute_Test() + { + var previousBlockHash = _kernelTestHelper.BestBranchBlockList.Last().GetHash(); + var previousBlockHeight = _kernelTestHelper.BestBranchBlockList.Last().Height; + var blockWithTransaction2 = GenerateBlock(previousBlockHeight, previousBlockHash, 2); + var blockWithTransaction3 = GenerateBlock(previousBlockHeight, previousBlockHash, 3); + var blockWithTransaction4 = GenerateBlock(previousBlockHeight, previousBlockHash, 4); + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - var previousBlockHash = _kernelTestHelper.BestBranchBlockList.Last().GetHash(); - var previousBlockHeight = _kernelTestHelper.BestBranchBlockList.Last().Height; - var blockWithTransaction2 = GenerateBlock(previousBlockHeight, previousBlockHash, 2); - var blockWithTransaction3 = GenerateBlock(previousBlockHeight, previousBlockHash, 3); - var blockWithTransaction4 = GenerateBlock(previousBlockHeight, previousBlockHash, 4); - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = previousBlockHash, - BlockHeight = previousBlockHeight - }); + BlockHash = previousBlockHash, + BlockHeight = previousBlockHeight + }); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeTrue(); - await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex - { - BlockHeight = previousBlockHeight, - BlockHash = previousBlockHash - }, 3); + await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex + { + BlockHeight = previousBlockHeight, + BlockHash = previousBlockHash + }, 3); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeFalse(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeFalse(); - await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex - { - BlockHeight = previousBlockHeight, - BlockHash = previousBlockHash - }, 4); + await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex + { + BlockHeight = previousBlockHeight, + BlockHash = previousBlockHash + }, 4); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); - (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeTrue(); - } + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction2)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction3)).ShouldBeTrue(); + (await _blockValidationProvider.ValidateBlockBeforeExecuteAsync(blockWithTransaction4)).ShouldBeTrue(); + } - private Block GenerateBlock(long previousBlockHeight, Hash previousBlockHash, int transactionCount) - { - var transactions = _kernelTestHelper.GenerateTransactions(transactionCount); - return _kernelTestHelper.GenerateBlock(previousBlockHeight, previousBlockHash, transactions); - } + private Block GenerateBlock(long previousBlockHeight, Hash previousBlockHash, int transactionCount) + { + var transactions = _kernelTestHelper.GenerateTransactions(transactionCount); + return _kernelTestHelper.GenerateBlock(previousBlockHeight, previousBlockHash, transactions); + } - [Fact] - public async Task ValidateBeforeAttach_Test() - { - var result = await _blockValidationProvider.ValidateBeforeAttachAsync(null); - result.ShouldBeTrue(); - } + [Fact] + public async Task ValidateBeforeAttach_Test() + { + var result = await _blockValidationProvider.ValidateBeforeAttachAsync(null); + result.ShouldBeTrue(); + } - [Fact] - public async Task ValidateBlockAfterExecute_Test() - { - var result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(null); - result.ShouldBeTrue(); - } + [Fact] + public async Task ValidateBlockAfterExecute_Test() + { + var result = await _blockValidationProvider.ValidateBlockAfterExecuteAsync(null); + result.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/Application/MinerServiceTests.cs b/test/AElf.Kernel.Tests/Miner/Application/MinerServiceTests.cs index 6fbd748035..da05bb8ce8 100644 --- a/test/AElf.Kernel.Tests/Miner/Application/MinerServiceTests.cs +++ b/test/AElf.Kernel.Tests/Miner/Application/MinerServiceTests.cs @@ -1,102 +1,97 @@ -using System.Collections.Generic; using System.Threading.Tasks; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.TransactionPool.Application; using AElf.Kernel.Txn.Application; -using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class MinerServiceTests : KernelMiningTestBase { - public class MinerServiceTests : KernelMiningTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + private readonly KernelTestHelper _kernelTestHelper; + private readonly IMinerService _minerService; + private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; + private readonly ITransactionPoolService _transactionPoolService; + + public MinerServiceTests() { - private readonly ITransactionPoolService _transactionPoolService; - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly ITransactionPackingOptionProvider _transactionPackingOptionProvider; - private readonly IMinerService _minerService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; + _transactionPoolService = GetRequiredService(); + _blockTransactionLimitProvider = GetRequiredService(); + _transactionPackingOptionProvider = GetRequiredService(); + _minerService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public MinerServiceTests() + [Fact] + public async Task Mine_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var blockStateSet = new BlockStateSet { - _transactionPoolService = GetRequiredService(); - _blockTransactionLimitProvider = GetRequiredService(); - _transactionPackingOptionProvider = GetRequiredService(); - _minerService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + + var transactions = _kernelTestHelper.GenerateTransactions(5, chain.BestChainHeight, chain.BestChainHash); + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, + chain.BestChainHeight); + await _transactionPoolService.AddTransactionsAsync(transactions); + await Task.Delay(200); + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, + chain.BestChainHeight); - [Fact] - public async Task Mine_Test() { - var chain = await _blockchainService.GetChainAsync(); - var blockStateSet = new BlockStateSet + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex { BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight, - }; - await _blockStateSetManger.SetBlockStateSetAsync(blockStateSet); + BlockHeight = chain.BestChainHeight + }, false); + + var blockTime = TimestampHelper.GetUtcNow(); + var result = await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, blockTime, + TimestampHelper.DurationFromSeconds(4)); + await CheckMiningResultAsync(result, blockTime, 0); + } - var transactions = _kernelTestHelper.GenerateTransactions(5, chain.BestChainHeight, chain.BestChainHash); - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, - chain.BestChainHeight); - await _transactionPoolService.AddTransactionsAsync(transactions); - await Task.Delay(200); - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, - chain.BestChainHeight); - + { + await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex { - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, false); - - var blockTime = TimestampHelper.GetUtcNow(); - var result = await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, blockTime, - TimestampHelper.DurationFromSeconds(4)); - await CheckMiningResultAsync(result, blockTime, 0); - } - + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, true); + + await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex { - await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, true); - - await _blockTransactionLimitProvider.SetLimitAsync(new BlockIndex - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, 3); - - var blockTime = TimestampHelper.GetUtcNow(); - var result = await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, blockTime, - TimestampHelper.DurationFromSeconds(4)); - await CheckMiningResultAsync(result, blockTime, 2); - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, 3); + var blockTime = TimestampHelper.GetUtcNow(); + var result = await _minerService.MineAsync(chain.BestChainHash, chain.BestChainHeight, blockTime, + TimestampHelper.DurationFromSeconds(4)); + await CheckMiningResultAsync(result, blockTime, 2); } - - private async Task CheckMiningResultAsync(BlockExecutedSet blockExecutedSet, Timestamp blockTime, - int transactionCount) - { - var chain = await _blockchainService.GetChainAsync(); - - blockExecutedSet.Block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); - blockExecutedSet.Block.Header.Height.ShouldBe(chain.BestChainHeight + 1); - blockExecutedSet.Block.Header.Time.ShouldBe(blockTime); - blockExecutedSet.Block.VerifySignature().ShouldBeTrue(); - blockExecutedSet.Block.Body.TransactionsCount.ShouldBe(1 + transactionCount); - } + } + + private async Task CheckMiningResultAsync(BlockExecutedSet blockExecutedSet, Timestamp blockTime, + int transactionCount) + { + var chain = await _blockchainService.GetChainAsync(); + + blockExecutedSet.Block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); + blockExecutedSet.Block.Header.Height.ShouldBe(chain.BestChainHeight + 1); + blockExecutedSet.Block.Header.Time.ShouldBe(blockTime); + blockExecutedSet.Block.VerifySignature().ShouldBeTrue(); + blockExecutedSet.Block.Body.TransactionsCount.ShouldBe(1 + transactionCount); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/Application/MiningRequestServiceTests.cs b/test/AElf.Kernel.Tests/Miner/Application/MiningRequestServiceTests.cs index c1c9fbe225..88f11b2016 100644 --- a/test/AElf.Kernel.Tests/Miner/Application/MiningRequestServiceTests.cs +++ b/test/AElf.Kernel.Tests/Miner/Application/MiningRequestServiceTests.cs @@ -1,65 +1,62 @@ using System.Threading.Tasks; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.SmartContract.Domain; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class MiningRequestServiceTests : KernelMiningTestBase { - public class MiningRequestServiceTests: KernelMiningTestBase + private readonly IBlockchainService _blockchainService; + private readonly IMiningRequestService _miningRequestService; + + public MiningRequestServiceTests() { - private readonly IMiningRequestService _miningRequestService; - private readonly IBlockchainService _blockchainService; + _miningRequestService = GetRequiredService(); + _blockchainService = GetRequiredService(); + } - public MiningRequestServiceTests() - { - _miningRequestService = GetRequiredService(); - _blockchainService = GetRequiredService(); - } + [Fact] + public async Task RequestMining_Test() + { + var chain = await _blockchainService.GetChainAsync(); - [Fact] - public async Task RequestMining_Test() + var request = new ConsensusRequestMiningDto { - var chain = await _blockchainService.GetChainAsync(); + BlockTime = TimestampHelper.GetUtcNow(), + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), + MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(499), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight + }; - var request = new ConsensusRequestMiningDto - { - BlockTime = TimestampHelper.GetUtcNow(), - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), - MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(499), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight - }; + var block = await _miningRequestService.RequestMiningAsync(request); + block.ShouldBeNull(); - var block = await _miningRequestService.RequestMiningAsync(request); - block.ShouldBeNull(); + request = new ConsensusRequestMiningDto + { + BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-501), + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), + MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight + }; + block = await _miningRequestService.RequestMiningAsync(request); + block.ShouldBeNull(); - request = new ConsensusRequestMiningDto - { - BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-501), - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), - MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight - }; - block = await _miningRequestService.RequestMiningAsync(request); - block.ShouldBeNull(); - - request = new ConsensusRequestMiningDto - { - BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-400), - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), - MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight - }; - block = await _miningRequestService.RequestMiningAsync(request); - block.ShouldNotBeNull(); - block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); - block.Header.Height.ShouldBe(chain.BestChainHeight + 1); - block.Header.Time.ShouldBe(request.BlockTime); - } + request = new ConsensusRequestMiningDto + { + BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-400), + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), + MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight + }; + block = await _miningRequestService.RequestMiningAsync(request); + block.ShouldNotBeNull(); + block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); + block.Header.Height.ShouldBe(chain.BestChainHeight + 1); + block.Header.Time.ShouldBe(request.BlockTime); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/Application/MiningServiceTests.cs b/test/AElf.Kernel.Tests/Miner/Application/MiningServiceTests.cs index ac24ecc46b..d2fdf350ff 100644 --- a/test/AElf.Kernel.Tests/Miner/Application/MiningServiceTests.cs +++ b/test/AElf.Kernel.Tests/Miner/Application/MiningServiceTests.cs @@ -1,112 +1,107 @@ -using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.CSharp.Core.Extension; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; -using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; -namespace AElf.Kernel.Miner.Application +namespace AElf.Kernel.Miner.Application; + +public class MiningServiceTests : KernelMiningTestBase { - public class MiningServiceTests : KernelMiningTestBase + private readonly IAccountService _accountService; + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; + private readonly IMiningService _miningService; + private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; + + public MiningServiceTests() { - private readonly IMiningService _miningService; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ISystemTransactionExtraDataProvider _systemTransactionExtraDataProvider; - private readonly IAccountService _accountService; + _miningService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _systemTransactionExtraDataProvider = GetRequiredService(); + _accountService = GetRequiredService(); + } + + [Fact] + public async Task Mine_Test() + { + var chain = await _blockchainService.GetChainAsync(); + Timestamp blockTime; + BlockExecutedSet miningResult; - public MiningServiceTests() { - _miningService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _systemTransactionExtraDataProvider = GetRequiredService(); - _accountService = GetRequiredService(); + blockTime = TimestampHelper.GetUtcNow().AddSeconds(-4); + miningResult = await _miningService.MineAsync(new RequestMiningDto + { + BlockExecutionTime = TimestampHelper.DurationFromSeconds(1), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + TransactionCountLimit = 100 + }, + _kernelTestHelper.GenerateTransactions(10), blockTime); + await CheckMiningResultAsync(miningResult, blockTime, 0); } - [Fact] - public async Task Mine_Test() { - var chain = await _blockchainService.GetChainAsync(); - Timestamp blockTime; - BlockExecutedSet miningResult; - - { - blockTime = TimestampHelper.GetUtcNow().AddSeconds(-4); - miningResult = await _miningService.MineAsync(new RequestMiningDto - { - BlockExecutionTime = TimestampHelper.DurationFromSeconds(1), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - TransactionCountLimit = 100 - }, - _kernelTestHelper.GenerateTransactions(10), blockTime); - await CheckMiningResultAsync(miningResult, blockTime, 0); - } - - { - blockTime = TimestampHelper.GetUtcNow().AddSeconds(4); - miningResult = await _miningService.MineAsync(new RequestMiningDto - { - BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - TransactionCountLimit = 100 - }, - _kernelTestHelper.GenerateTransactions(10), blockTime); - await CheckMiningResultAsync(miningResult, blockTime, 10); - } - - { - blockTime = TimestampHelper.GetUtcNow(); - miningResult = await _miningService.MineAsync(new RequestMiningDto - { - BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - TransactionCountLimit = 100 - }, - _kernelTestHelper.GenerateTransactions(10), blockTime); - await CheckMiningResultAsync(miningResult, blockTime, 10); - } - - { - blockTime = TimestampHelper.GetUtcNow(); - miningResult = await _miningService.MineAsync(new RequestMiningDto - { - BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - TransactionCountLimit = 5 - }, - _kernelTestHelper.GenerateTransactions(10), blockTime); - await CheckMiningResultAsync(miningResult, blockTime, 4); - } + blockTime = TimestampHelper.GetUtcNow().AddSeconds(4); + miningResult = await _miningService.MineAsync(new RequestMiningDto + { + BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + TransactionCountLimit = 100 + }, + _kernelTestHelper.GenerateTransactions(10), blockTime); + await CheckMiningResultAsync(miningResult, blockTime, 10); } - private async Task CheckMiningResultAsync(BlockExecutedSet blockExecutedSet, Timestamp blockTime, - int transactionCount) { - var chain = await _blockchainService.GetChainAsync(); - var pubkey = await _accountService.GetPublicKeyAsync(); - - blockExecutedSet.Block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); - blockExecutedSet.Block.Header.Height.ShouldBe(chain.BestChainHeight + 1); - blockExecutedSet.Block.Header.Time.ShouldBe(blockTime); - blockExecutedSet.Block.Header.SignerPubkey.ShouldBe(ByteString.CopyFrom(pubkey)); - blockExecutedSet.Block.VerifySignature().ShouldBeTrue(); - blockExecutedSet.Block.Body.TransactionsCount.ShouldBe(1 + transactionCount); + blockTime = TimestampHelper.GetUtcNow(); + miningResult = await _miningService.MineAsync(new RequestMiningDto + { + BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + TransactionCountLimit = 100 + }, + _kernelTestHelper.GenerateTransactions(10), blockTime); + await CheckMiningResultAsync(miningResult, blockTime, 10); + } - _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockExecutedSet.Block.Header, - out var systemTransactionCount); - systemTransactionCount.ShouldBe(1); + { + blockTime = TimestampHelper.GetUtcNow(); + miningResult = await _miningService.MineAsync(new RequestMiningDto + { + BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + TransactionCountLimit = 5 + }, + _kernelTestHelper.GenerateTransactions(10), blockTime); + await CheckMiningResultAsync(miningResult, blockTime, 4); } } + + private async Task CheckMiningResultAsync(BlockExecutedSet blockExecutedSet, Timestamp blockTime, + int transactionCount) + { + var chain = await _blockchainService.GetChainAsync(); + var pubkey = await _accountService.GetPublicKeyAsync(); + + blockExecutedSet.Block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); + blockExecutedSet.Block.Header.Height.ShouldBe(chain.BestChainHeight + 1); + blockExecutedSet.Block.Header.Time.ShouldBe(blockTime); + blockExecutedSet.Block.Header.SignerPubkey.ShouldBe(ByteString.CopyFrom(pubkey)); + blockExecutedSet.Block.VerifySignature().ShouldBeTrue(); + blockExecutedSet.Block.Body.TransactionsCount.ShouldBe(1 + transactionCount); + + _systemTransactionExtraDataProvider.TryGetSystemTransactionCount(blockExecutedSet.Block.Header, + out var systemTransactionCount); + systemTransactionCount.ShouldBe(1); + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitConfigurationProcessorTests.cs b/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitConfigurationProcessorTests.cs index a13e5cba56..ae3e692db3 100644 --- a/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitConfigurationProcessorTests.cs +++ b/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitConfigurationProcessorTests.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using AElf.Kernel.Configuration; using AElf.Kernel.SmartContract.Domain; @@ -7,70 +6,69 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Miner +namespace AElf.Kernel.Miner; + +public class BlockTransactionLimitConfigurationProcessorTests : KernelTestBase { - public class BlockTransactionLimitConfigurationProcessorTests : KernelTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IConfigurationProcessor _blockTransactionLimitConfigurationProcessor; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + + public BlockTransactionLimitConfigurationProcessorTests() + { + _blockTransactionLimitProvider = GetRequiredService(); + _blockTransactionLimitConfigurationProcessor = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } + + [Fact] + public async Task ProcessConfiguration_Test() { - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly IConfigurationProcessor _blockTransactionLimitConfigurationProcessor; - private readonly IBlockStateSetManger _blockStateSetManger; - - public BlockTransactionLimitConfigurationProcessorTests() + var blockTransactionLimit = 50; + var blockIndex = new BlockIndex { - _blockTransactionLimitProvider = GetRequiredService(); - _blockTransactionLimitConfigurationProcessor = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } - - [Fact] - public async Task ProcessConfiguration_Test() + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 1 + }; + + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet { - var blockTransactionLimit = 50; - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 1 - }; - - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + + var limit = await _blockTransactionLimitProvider.GetLimitAsync( + new ChainContext { BlockHash = blockIndex.BlockHash, BlockHeight = blockIndex.BlockHeight }); - - var limit = await _blockTransactionLimitProvider.GetLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(int.MaxValue); - - await _blockTransactionLimitConfigurationProcessor.ProcessConfigurationAsync(new Int32Value + limit.ShouldBe(int.MaxValue); + + await _blockTransactionLimitConfigurationProcessor.ProcessConfigurationAsync(new Int32Value + { + Value = -1 + }.ToByteString(), blockIndex); + + limit = await _blockTransactionLimitProvider.GetLimitAsync( + new ChainContext { - Value = -1 - }.ToByteString(), blockIndex); - - limit = await _blockTransactionLimitProvider.GetLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(int.MaxValue); + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + limit.ShouldBe(int.MaxValue); - await _blockTransactionLimitConfigurationProcessor.ProcessConfigurationAsync(new Int32Value + await _blockTransactionLimitConfigurationProcessor.ProcessConfigurationAsync(new Int32Value + { + Value = blockTransactionLimit + }.ToByteString(), blockIndex); + + limit = await _blockTransactionLimitProvider.GetLimitAsync( + new ChainContext { - Value = blockTransactionLimit - }.ToByteString(), blockIndex); - - limit = await _blockTransactionLimitProvider.GetLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(blockTransactionLimit); - } + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + limit.ShouldBe(blockTransactionLimit); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitProviderTests.cs b/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitProviderTests.cs index 2c513f2836..573b08a90e 100644 --- a/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitProviderTests.cs +++ b/test/AElf.Kernel.Tests/Miner/BlockTransactionLimitProviderTests.cs @@ -7,67 +7,66 @@ using Shouldly; using Xunit; -namespace AElf.Kernel +namespace AElf.Kernel; + +public sealed class BlockTransactionLimitProviderTests : KernelTestBase { - public sealed class BlockTransactionLimitProviderTests : KernelTestBase + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; + + public BlockTransactionLimitProviderTests() { - private readonly IBlockTransactionLimitProvider _blockTransactionLimitProvider; - private readonly IBlockStateSetManger _blockStateSetManger; + _blockTransactionLimitProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } - public BlockTransactionLimitProviderTests() - { - _blockTransactionLimitProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } - - [Fact] - public async Task TransactionLimitSetAndGet_Test() + [Fact] + public async Task TransactionLimitSetAndGet_Test() + { + var blockIndex = new BlockIndex { - var blockIndex = new BlockIndex - { - BlockHash = HashHelper.ComputeFrom("BlockHash"), - BlockHeight = 1 - }; - - await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); + BlockHash = HashHelper.ComputeFrom("BlockHash"), + BlockHeight = 1 + }; - var blockTransactionLimit = 50; + await _blockStateSetManger.SetBlockStateSetAsync(new BlockStateSet + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); - { - var limit = await _blockTransactionLimitProvider.GetLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(int.MaxValue); - } + var blockTransactionLimit = 50; - { - await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, blockTransactionLimit); - var limit = await _blockTransactionLimitProvider.GetLimitAsync( - new ChainContext - { - BlockHash = blockIndex.BlockHash, - BlockHeight = blockIndex.BlockHeight - }); - limit.ShouldBe(blockTransactionLimit); - } + { + var limit = await _blockTransactionLimitProvider.GetLimitAsync( + new ChainContext + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + limit.ShouldBe(int.MaxValue); + } - var blockTransactionLimitLessThanSystemTransaction = - GetRequiredService>().Count(); - await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, blockTransactionLimitLessThanSystemTransaction); - var limit2 = await _blockTransactionLimitProvider.GetLimitAsync( + { + await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, blockTransactionLimit); + var limit = await _blockTransactionLimitProvider.GetLimitAsync( new ChainContext { BlockHash = blockIndex.BlockHash, BlockHeight = blockIndex.BlockHeight }); - limit2.ShouldBe(blockTransactionLimit); + limit.ShouldBe(blockTransactionLimit); } + + var blockTransactionLimitLessThanSystemTransaction = + GetRequiredService>().Count(); + await _blockTransactionLimitProvider.SetLimitAsync(blockIndex, blockTransactionLimitLessThanSystemTransaction); + var limit2 = await _blockTransactionLimitProvider.GetLimitAsync( + new ChainContext + { + BlockHash = blockIndex.BlockHash, + BlockHeight = blockIndex.BlockHeight + }); + limit2.ShouldBe(blockTransactionLimit); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/TestBlockExecutingService.cs b/test/AElf.Kernel.Tests/TestBlockExecutingService.cs index 4e77eb88fb..e146df0d1e 100644 --- a/test/AElf.Kernel.Tests/TestBlockExecutingService.cs +++ b/test/AElf.Kernel.Tests/TestBlockExecutingService.cs @@ -7,50 +7,48 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class TestBlockExecutingService : IBlockExecutingService { - public class TestBlockExecutingService : IBlockExecutingService + public Task ExecuteBlockAsync(BlockHeader blockHeader, + List nonCancellableTransactions) { - public Task ExecuteBlockAsync(BlockHeader blockHeader, - List nonCancellableTransactions) - { - var block = GenerateBlock(blockHeader, nonCancellableTransactions.Select(p => p.GetHash())); + var block = GenerateBlock(blockHeader, nonCancellableTransactions.Select(p => p.GetHash())); - return Task.FromResult(new BlockExecutedSet(){Block = block}); - } + return Task.FromResult(new BlockExecutedSet { Block = block }); + } - public Task ExecuteBlockAsync(BlockHeader blockHeader, - IEnumerable nonCancellableTransactions, - IEnumerable cancellableTransactions, CancellationToken cancellationToken) - { - var transactions = cancellationToken.IsCancellationRequested - ? nonCancellableTransactions.ToList() - : nonCancellableTransactions.Concat(cancellableTransactions).ToList(); + public Task ExecuteBlockAsync(BlockHeader blockHeader, + IEnumerable nonCancellableTransactions, + IEnumerable cancellableTransactions, CancellationToken cancellationToken) + { + var transactions = cancellationToken.IsCancellationRequested + ? nonCancellableTransactions.ToList() + : nonCancellableTransactions.Concat(cancellableTransactions).ToList(); - var block = GenerateBlock(blockHeader, transactions.Select(p => p.GetHash())); + var block = GenerateBlock(blockHeader, transactions.Select(p => p.GetHash())); - return Task.FromResult(new BlockExecutedSet() {Block = block}); - } + return Task.FromResult(new BlockExecutedSet { Block = block }); + } + + private Block GenerateBlock(BlockHeader blockHeader, IEnumerable transactionIds) + { + var leafNodes = transactionIds as Hash[] ?? transactionIds.ToArray(); + blockHeader.MerkleTreeRootOfTransactions = BinaryMerkleTree.FromLeafNodes(leafNodes).Root; + blockHeader.MerkleTreeRootOfWorldState = Hash.Empty; + blockHeader.MerkleTreeRootOfTransactionStatus = Hash.Empty; + if (blockHeader.SignerPubkey.IsEmpty) + blockHeader.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); - private Block GenerateBlock(BlockHeader blockHeader, IEnumerable transactionIds) + var block = new Block { - - var leafNodes = transactionIds as Hash[] ?? transactionIds.ToArray(); - blockHeader.MerkleTreeRootOfTransactions = BinaryMerkleTree.FromLeafNodes(leafNodes).Root; - blockHeader.MerkleTreeRootOfWorldState = Hash.Empty; - blockHeader.MerkleTreeRootOfTransactionStatus = Hash.Empty; - if (blockHeader.SignerPubkey.IsEmpty) - blockHeader.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); - - var block = new Block - { - Header = blockHeader, - Body = new BlockBody() - }; - - block.Body.TransactionIds.AddRange(leafNodes); - - return block; - } + Header = blockHeader, + Body = new BlockBody() + }; + + block.Body.TransactionIds.AddRange(leafNodes); + + return block; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/UnitTestContractZeroCodeProvider.cs b/test/AElf.Kernel.Tests/UnitTestContractZeroCodeProvider.cs index 0b167b7fb7..42ff693152 100644 --- a/test/AElf.Kernel.Tests/UnitTestContractZeroCodeProvider.cs +++ b/test/AElf.Kernel.Tests/UnitTestContractZeroCodeProvider.cs @@ -3,18 +3,17 @@ using AElf.Kernel.SmartContract.Infrastructure; using Microsoft.Extensions.Options; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider { - public class UnitTestContractZeroCodeProvider : DefaultContractZeroCodeProvider + public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, + IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) { - public UnitTestContractZeroCodeProvider(IStaticChainInformationProvider staticChainInformationProvider, - IOptionsSnapshot contractOptions) : base(staticChainInformationProvider, contractOptions) - { - } + } - protected override int GetCategory() - { - return KernelConstants.CodeCoverageRunnerCategory; - } + protected override int GetCategory() + { + return KernelConstants.CodeCoverageRunnerCategory; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Tests/UnitTestSmartContractAddressService.cs b/test/AElf.Kernel.Tests/UnitTestSmartContractAddressService.cs index ab7623c04e..314f831dc3 100644 --- a/test/AElf.Kernel.Tests/UnitTestSmartContractAddressService.cs +++ b/test/AElf.Kernel.Tests/UnitTestSmartContractAddressService.cs @@ -9,39 +9,35 @@ using AElf.Kernel.SmartContract.Infrastructure; using AElf.Types; -namespace AElf.Kernel +namespace AElf.Kernel; + +public class UnitTestSmartContractAddressService : SmartContractAddressService { - public class UnitTestSmartContractAddressService : SmartContractAddressService + private readonly ConcurrentDictionary _hashToAddressMap = new(); + + public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + ISmartContractAddressProvider smartContractAddressProvider, + IEnumerable smartContractAddressNameProviders, + IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, + transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, + blockchainService) + { + } + + public override async Task> GetSystemContractNameToAddressMappingAsync( + IChainContext chainContext) + { + var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); + var dictionary = new Dictionary(); + foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) + dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); + return new ReadOnlyDictionary(dictionary); + } + + public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) { - private readonly ConcurrentDictionary _hashToAddressMap = - new ConcurrentDictionary(); - - public UnitTestSmartContractAddressService(IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - ISmartContractAddressProvider smartContractAddressProvider, - IEnumerable smartContractAddressNameProviders, - IBlockchainService blockchainService) : base(defaultContractZeroCodeProvider, - transactionReadOnlyExecutionService, smartContractAddressProvider, smartContractAddressNameProviders, - blockchainService) - { - } - - public override async Task> GetSystemContractNameToAddressMappingAsync( - IChainContext chainContext) - { - var baseDictionary = await base.GetSystemContractNameToAddressMappingAsync(chainContext); - var dictionary = new Dictionary(); - foreach (var keyValuePair in baseDictionary.Concat(_hashToAddressMap)) - { - dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); - } - return new ReadOnlyDictionary(dictionary); - } - - public override Task SetSmartContractAddressAsync(IBlockIndex blockIndex, string contractName, Address address) - { - _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; - return base.SetSmartContractAddressAsync(blockIndex, contractName, address); - } + _hashToAddressMap[Hash.LoadFromBase64(contractName)] = address; + return base.SetSmartContractAddressAsync(blockIndex, contractName, address); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Token.Tests/AElf.Kernel.Token.Tests.csproj b/test/AElf.Kernel.Token.Tests/AElf.Kernel.Token.Tests.csproj index bb2ef8a499..e2d17677b0 100644 --- a/test/AElf.Kernel.Token.Tests/AElf.Kernel.Token.Tests.csproj +++ b/test/AElf.Kernel.Token.Tests/AElf.Kernel.Token.Tests.csproj @@ -9,20 +9,20 @@ - - - - - - + + + + + + - - - + + + - + Protobuf\Proto\token_contract.proto diff --git a/test/AElf.Kernel.Token.Tests/KernelTokenModule.cs b/test/AElf.Kernel.Token.Tests/KernelTokenModule.cs index 833196ab01..bc2297c815 100644 --- a/test/AElf.Kernel.Token.Tests/KernelTokenModule.cs +++ b/test/AElf.Kernel.Token.Tests/KernelTokenModule.cs @@ -1,15 +1,14 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Kernel.Token.Test +namespace AElf.Kernel.Token.Test; + +[DependsOn( + typeof(TokenKernelAElfModule), + typeof(KernelTestAElfModule))] +public class KernelTokenModule : AElfModule { - [DependsOn( - typeof(TokenKernelAElfModule), - typeof(KernelTestAElfModule))] - public class KernelTokenModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/test/AElf.Kernel.Token.Tests/KernelTokenTestBase.cs b/test/AElf.Kernel.Token.Tests/KernelTokenTestBase.cs index 88911ea267..a7feaf3927 100644 --- a/test/AElf.Kernel.Token.Tests/KernelTokenTestBase.cs +++ b/test/AElf.Kernel.Token.Tests/KernelTokenTestBase.cs @@ -1,9 +1,7 @@ using AElf.TestBase; -namespace AElf.Kernel.Token.Test +namespace AElf.Kernel.Token.Test; + +public class KernelTokenTestBase : AElfIntegratedTest { - public class KernelTokenTestBase: AElfIntegratedTest - { - - } } \ No newline at end of file diff --git a/test/AElf.Kernel.Token.Tests/TokenContractInitializationDataProvider.cs b/test/AElf.Kernel.Token.Tests/TokenContractInitializationDataProvider.cs index 0885ccc9f7..90ceabdae5 100644 --- a/test/AElf.Kernel.Token.Tests/TokenContractInitializationDataProvider.cs +++ b/test/AElf.Kernel.Token.Tests/TokenContractInitializationDataProvider.cs @@ -4,87 +4,87 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.Token.Test +namespace AElf.Kernel.Token.Test; + +internal static class TokenInfoGeneratorHelper { - internal static class TokenInfoGeneratorHelper + internal static ByteString GenerateTokenInfoByteStringBySymbol(string tokenSymbol) { - internal static ByteString GenerateTokenInfoByteStringBySymbol(string tokenSymbol) - { - return GenerateTokenInfoBySymbol(tokenSymbol).ToByteString(); - } + return GenerateTokenInfoBySymbol(tokenSymbol).ToByteString(); + } - private static TokenInfo GenerateTokenInfoBySymbol(string tokenSymbol) - { - return new TokenInfo - { - Symbol = tokenSymbol, - TokenName = tokenSymbol + "name", - TotalSupply = 1000_000_000, - Issuer = SampleAddress.AddressList[0], - }; - } - - internal static ByteString GenerateResourceTokenListByteString() + private static TokenInfo GenerateTokenInfoBySymbol(string tokenSymbol) + { + return new TokenInfo { - var resourceToken1 = GenerateTokenInfoBySymbol("CPU"); - var resourceToken2 = GenerateTokenInfoBySymbol("NET"); - return new TokenInfoList - { - Value = { resourceToken1, resourceToken2} - }.ToByteString(); - } + Symbol = tokenSymbol, + TokenName = tokenSymbol + "name", + TotalSupply = 1000_000_000, + Issuer = SampleAddress.AddressList[0] + }; } - - public class TokenContractInitializationDataProviderWithNull : ITokenContractInitializationDataProvider + + internal static ByteString GenerateResourceTokenListByteString() { - public TokenContractInitializationData GetContractInitializationData() + var resourceToken1 = GenerateTokenInfoBySymbol("CPU"); + var resourceToken2 = GenerateTokenInfoBySymbol("NET"); + return new TokenInfoList { - return null; - } + Value = { resourceToken1, resourceToken2 } + }.ToByteString(); } +} - public class TokenContractInitializationDataProviderWithPrimaryToken : ITokenContractInitializationDataProvider +public class TokenContractInitializationDataProviderWithNull : ITokenContractInitializationDataProvider +{ + public TokenContractInitializationData GetContractInitializationData() { - private readonly int _issueCount; + return null; + } +} - public TokenContractInitializationDataProviderWithPrimaryToken(int issueCount) - { - _issueCount = issueCount; - } - - public TokenContractInitializationData GetContractInitializationData() +public class TokenContractInitializationDataProviderWithPrimaryToken : ITokenContractInitializationDataProvider +{ + private readonly int _issueCount; + + public TokenContractInitializationDataProviderWithPrimaryToken(int issueCount) + { + _issueCount = issueCount; + } + + public TokenContractInitializationData GetContractInitializationData() + { + var tokenContractInitializationData = new TokenContractInitializationData { - var tokenContractInitializationData = new TokenContractInitializationData - { - NativeTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ALICE"), - ResourceTokenListData = TokenInfoGeneratorHelper.GenerateResourceTokenListByteString(), - PrimaryTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ELF"), - Creator = SampleAddress.AddressList[0], - TokenInitialIssueList = new List(), - ResourceAmount = new Dictionary{{"CPU", 100}}, - RegisteredOtherTokenContractAddresses = new Dictionary() - }; - tokenContractInitializationData.TokenInitialIssueList.AddRange(Enumerable.Range(0, _issueCount).Select(x => new TokenInitialIssue + NativeTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ALICE"), + ResourceTokenListData = TokenInfoGeneratorHelper.GenerateResourceTokenListByteString(), + PrimaryTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ELF"), + Creator = SampleAddress.AddressList[0], + TokenInitialIssueList = new List(), + ResourceAmount = new Dictionary { { "CPU", 100 } }, + RegisteredOtherTokenContractAddresses = new Dictionary() + }; + tokenContractInitializationData.TokenInitialIssueList.AddRange(Enumerable.Range(0, _issueCount).Select(x => + new TokenInitialIssue { Address = SampleAddress.AddressList[1], Amount = 100 })); - return tokenContractInitializationData; - } + return tokenContractInitializationData; } - - public class TokenContractInitializationDataProviderWithoutPrimaryToken : ITokenContractInitializationDataProvider +} + +public class TokenContractInitializationDataProviderWithoutPrimaryToken : ITokenContractInitializationDataProvider +{ + public TokenContractInitializationData GetContractInitializationData() { - public TokenContractInitializationData GetContractInitializationData() + return new TokenContractInitializationData { - return new TokenContractInitializationData - { - NativeTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ALICE"), - ResourceTokenListData = TokenInfoGeneratorHelper.GenerateResourceTokenListByteString(), - Creator = SampleAddress.AddressList[0], - ResourceAmount = new Dictionary{{"CPU", 100}}, - RegisteredOtherTokenContractAddresses = new Dictionary() - }; - } + NativeTokenInfoData = TokenInfoGeneratorHelper.GenerateTokenInfoByteStringBySymbol("ALICE"), + ResourceTokenListData = TokenInfoGeneratorHelper.GenerateResourceTokenListByteString(), + Creator = SampleAddress.AddressList[0], + ResourceAmount = new Dictionary { { "CPU", 100 } }, + RegisteredOtherTokenContractAddresses = new Dictionary() + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Token.Tests/TokenContractInitializationProviderTest.cs b/test/AElf.Kernel.Token.Tests/TokenContractInitializationProviderTest.cs index be995d4e3c..8544711c12 100644 --- a/test/AElf.Kernel.Token.Tests/TokenContractInitializationProviderTest.cs +++ b/test/AElf.Kernel.Token.Tests/TokenContractInitializationProviderTest.cs @@ -3,66 +3,65 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Token.Test +namespace AElf.Kernel.Token.Test; + +public class TokenContractInitializationProviderTest { - public class TokenContractInitializationProviderTest + [Fact] + public void GetContractInitializationData_Without_Data_Test() { - [Fact] - public void GetContractInitializationData_Without_Data_Test() - { - var provider = new TokenContractInitializationDataProviderWithNull(); - var contractInitializationProvider = new TokenContractInitializationProvider(provider); - contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); - } + var provider = new TokenContractInitializationDataProviderWithNull(); + var contractInitializationProvider = new TokenContractInitializationProvider(provider); + contractInitializationProvider.GetInitializeMethodList(null).Count.ShouldBe(0); + } - [Fact] - public void GetContractInitializationData_With_Primary_Token_Test() - { - var issueCount = 4; - var provider = new TokenContractInitializationDataProviderWithPrimaryToken(issueCount); - var contractInitializationProvider = new TokenContractInitializationProvider(provider); - var methodCallList = contractInitializationProvider.GetInitializeMethodList(null); - methodCallList.Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.Create)) - .ShouldBe(4); - methodCallList - .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitialCoefficients)) - .ShouldBe(1); - methodCallList - .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol)) - .ShouldBe(1); - methodCallList.Count(x => - x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController)) - .ShouldBe(1); - methodCallList.Count(x => - x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain)) - .ShouldBe(1); - methodCallList.Count(x => - x.MethodName == nameof(TokenContractContainer.TokenContractStub.Issue)) - .ShouldBe(issueCount); - methodCallList.Count.ShouldBe(8 + issueCount); - } + [Fact] + public void GetContractInitializationData_With_Primary_Token_Test() + { + var issueCount = 4; + var provider = new TokenContractInitializationDataProviderWithPrimaryToken(issueCount); + var contractInitializationProvider = new TokenContractInitializationProvider(provider); + var methodCallList = contractInitializationProvider.GetInitializeMethodList(null); + methodCallList.Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.Create)) + .ShouldBe(4); + methodCallList + .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitialCoefficients)) + .ShouldBe(1); + methodCallList + .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol)) + .ShouldBe(1); + methodCallList.Count(x => + x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController)) + .ShouldBe(1); + methodCallList.Count(x => + x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain)) + .ShouldBe(1); + methodCallList.Count(x => + x.MethodName == nameof(TokenContractContainer.TokenContractStub.Issue)) + .ShouldBe(issueCount); + methodCallList.Count.ShouldBe(8 + issueCount); + } - [Fact] - public void GetContractInitializationData_Without_Primary_Token_Test() - { - var provider = new TokenContractInitializationDataProviderWithoutPrimaryToken(); - var contractInitializationProvider = new TokenContractInitializationProvider(provider); - var methodCallList = contractInitializationProvider.GetInitializeMethodList(null); - methodCallList.Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.Create)) - .ShouldBe(3); - methodCallList - .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitialCoefficients)) - .ShouldBe(1); - methodCallList - .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol)) - .ShouldBe(1); - methodCallList.Count(x => - x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController)) - .ShouldBe(1); - methodCallList.Count(x => - x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain)) - .ShouldBe(1); - methodCallList.Count.ShouldBe(7); - } + [Fact] + public void GetContractInitializationData_Without_Primary_Token_Test() + { + var provider = new TokenContractInitializationDataProviderWithoutPrimaryToken(); + var contractInitializationProvider = new TokenContractInitializationProvider(provider); + var methodCallList = contractInitializationProvider.GetInitializeMethodList(null); + methodCallList.Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.Create)) + .ShouldBe(3); + methodCallList + .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitialCoefficients)) + .ShouldBe(1); + methodCallList + .Count(x => x.MethodName == nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol)) + .ShouldBe(1); + methodCallList.Count(x => + x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeAuthorizedController)) + .ShouldBe(1); + methodCallList.Count(x => + x.MethodName == nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain)) + .ShouldBe(1); + methodCallList.Count.ShouldBe(7); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/AElf.Kernel.TransactionPool.Tests.csproj b/test/AElf.Kernel.TransactionPool.Tests/AElf.Kernel.TransactionPool.Tests.csproj index 3b258ee428..ebb0f7be28 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/AElf.Kernel.TransactionPool.Tests.csproj +++ b/test/AElf.Kernel.TransactionPool.Tests/AElf.Kernel.TransactionPool.Tests.csproj @@ -5,16 +5,16 @@ false - - - - - - - + + + + + + + - - + + \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/Application/BlockchainServiceExtensionsTests.cs b/test/AElf.Kernel.TransactionPool.Tests/Application/BlockchainServiceExtensionsTests.cs index 7ebcf45183..75ec304cd6 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/Application/BlockchainServiceExtensionsTests.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/Application/BlockchainServiceExtensionsTests.cs @@ -3,33 +3,32 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.TransactionPool.Application +namespace AElf.Kernel.TransactionPool.Application; + +public class BlockchainServiceExtensionsTests : TransactionPoolWithChainTestBase { - public class BlockchainServiceExtensionsTests : TransactionPoolWithChainTestBase - { - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; - public BlockchainServiceExtensionsTests() - { - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + public BlockchainServiceExtensionsTests() + { + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - [Fact] - public async Task GetBlockIndexes_Test() - { - var chain = await _blockchainService.GetChainAsync(); - var result = await _blockchainService.GetBlockIndexesAsync(0, chain.BestChainHash, chain.BestChainHeight); - result.Count.ShouldBe(0); + [Fact] + public async Task GetBlockIndexes_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var result = await _blockchainService.GetBlockIndexesAsync(0, chain.BestChainHash, chain.BestChainHeight); + result.Count.ShouldBe(0); - result = await _blockchainService.GetBlockIndexesAsync(9, chain.BestChainHash, chain.BestChainHeight); - result.Count.ShouldBe(3); - result.ShouldContain(new BlockIndex(chain.BestChainHash, chain.BestChainHeight)); - result.ShouldContain(new BlockIndex(_kernelTestHelper.BestBranchBlockList[9].GetHash(), - _kernelTestHelper.BestBranchBlockList[9].Height)); - result.ShouldContain(new BlockIndex(_kernelTestHelper.BestBranchBlockList[8].GetHash(), - _kernelTestHelper.BestBranchBlockList[8].Height)); - } + result = await _blockchainService.GetBlockIndexesAsync(9, chain.BestChainHash, chain.BestChainHeight); + result.Count.ShouldBe(3); + result.ShouldContain(new BlockIndex(chain.BestChainHash, chain.BestChainHeight)); + result.ShouldContain(new BlockIndex(_kernelTestHelper.BestBranchBlockList[9].GetHash(), + _kernelTestHelper.BestBranchBlockList[9].Height)); + result.ShouldContain(new BlockIndex(_kernelTestHelper.BestBranchBlockList[8].GetHash(), + _kernelTestHelper.BestBranchBlockList[8].Height)); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/FakeTransaction.cs b/test/AElf.Kernel.TransactionPool.Tests/FakeTransaction.cs index 4b4ba0cf17..a80d77dd0f 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/FakeTransaction.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/FakeTransaction.cs @@ -1,21 +1,20 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public static class FakeTransaction { - public static class FakeTransaction + public static Transaction Generate() { - public static Transaction Generate() + var transaction = new Transaction { - var transaction = new Transaction() - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[1], - MethodName = "test", - Params = ByteString.CopyFromUtf8("test") - }; + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[1], + MethodName = "test", + Params = ByteString.CopyFromUtf8("test") + }; - return transaction; - } + return transaction; } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/BasicTransactionValidationProviderTests.cs b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/BasicTransactionValidationProviderTests.cs index 08dbc281de..9b07018930 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/BasicTransactionValidationProviderTests.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/BasicTransactionValidationProviderTests.cs @@ -4,77 +4,75 @@ using AElf.Types; using Google.Protobuf; using Shouldly; -using Virgil.Crypto; using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class BasicTransactionValidationProviderTests : TransactionPoolTestBase { - public class BasicTransactionValidationProviderTests : TransactionPoolTestBase - { - private readonly BasicTransactionValidationProvider _basicTransactionValidationProvider; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ILocalEventBus _eventBus; + private readonly BasicTransactionValidationProvider _basicTransactionValidationProvider; + private readonly ILocalEventBus _eventBus; + private readonly KernelTestHelper _kernelTestHelper; - public BasicTransactionValidationProviderTests() - { - _basicTransactionValidationProvider = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _eventBus = GetRequiredService(); - } + public BasicTransactionValidationProviderTests() + { + _basicTransactionValidationProvider = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _eventBus = GetRequiredService(); + } - [Fact] - public async Task ValidateTransaction_Test() + [Fact] + public async Task ValidateTransaction_Test() + { + TransactionValidationStatusChangedEvent eventData = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent eventData = null; - _eventBus.Subscribe(d => - { - eventData = d; - return Task.CompletedTask; - }); + eventData = d; + return Task.CompletedTask; + }); - var transaction = _kernelTestHelper.GenerateTransaction(); - var result = - await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); - result.ShouldBeTrue(); - eventData.ShouldBeNull(); + var transaction = _kernelTestHelper.GenerateTransaction(); + var result = + await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); + result.ShouldBeTrue(); + eventData.ShouldBeNull(); - transaction.Signature = ByteString.Empty; - result = - await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); - result.ShouldBeFalse(); - eventData.ShouldNotBeNull(); - eventData.TransactionId.ShouldBe(transaction.GetHash()); - eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed); - eventData.Error.ShouldBe("Incorrect transaction signature."); + transaction.Signature = ByteString.Empty; + result = + await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); + result.ShouldBeFalse(); + eventData.ShouldNotBeNull(); + eventData.TransactionId.ShouldBe(transaction.GetHash()); + eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed); + eventData.Error.ShouldBe("Incorrect transaction signature."); - eventData = null; - transaction = GenerateBigTransaction(); - result = - await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); - result.ShouldBeFalse(); - eventData.ShouldNotBeNull(); - eventData.TransactionId.ShouldBe(transaction.GetHash()); - eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed); - eventData.Error.ShouldBe("Transaction size exceeded."); - } + eventData = null; + transaction = GenerateBigTransaction(); + result = + await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext()); + result.ShouldBeFalse(); + eventData.ShouldNotBeNull(); + eventData.TransactionId.ShouldBe(transaction.GetHash()); + eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed); + eventData.Error.ShouldBe("Transaction size exceeded."); + } - private Transaction GenerateBigTransaction() + private Transaction GenerateBigTransaction() + { + var transaction = new Transaction { - var transaction = new Transaction - { - From = Address.FromPublicKey(_kernelTestHelper.KeyPair.PublicKey), - To = SampleAddress.AddressList[0], - MethodName = Guid.NewGuid().ToString(), - Params = ByteString.CopyFrom(new byte[TransactionPoolConsts.TransactionSizeLimit]), - RefBlockNumber = 0, - RefBlockPrefix = ByteString.Empty - }; + From = Address.FromPublicKey(_kernelTestHelper.KeyPair.PublicKey), + To = SampleAddress.AddressList[0], + MethodName = Guid.NewGuid().ToString(), + Params = ByteString.CopyFrom(new byte[TransactionPoolConsts.TransactionSizeLimit]), + RefBlockNumber = 0, + RefBlockPrefix = ByteString.Empty + }; - var signature = CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, - transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - return transaction; - } + var signature = CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey, + transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + return transaction; } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionExecutionValidationProviderTests.cs b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionExecutionValidationProviderTests.cs index d5667bfe0e..962df9e143 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionExecutionValidationProviderTests.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionExecutionValidationProviderTests.cs @@ -7,121 +7,123 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class TransactionExecutionValidationProviderTests : AElfIntegratedTest { - public class TransactionExecutionValidationProviderTests : AElfIntegratedTest + private readonly IBlockchainService _blockchainService; + private readonly ILocalEventBus _eventBus; + private readonly KernelTestHelper _kernelTestHelper; + private readonly TransactionExecutionValidationProvider _transactionExecutionValidationProvider; + private readonly TransactionOptions _transactionOptions; + + public TransactionExecutionValidationProviderTests() { - private readonly TransactionExecutionValidationProvider _transactionExecutionValidationProvider; - private readonly TransactionOptions _transactionOptions; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ILocalEventBus _eventBus; + _transactionExecutionValidationProvider = GetRequiredService(); + _transactionOptions = GetRequiredService>().CurrentValue; + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _eventBus = GetRequiredService(); + } - public TransactionExecutionValidationProviderTests() + [Fact] + public async Task ValidateTransactionTest() + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => { - _transactionExecutionValidationProvider = GetRequiredService(); - _transactionOptions = GetRequiredService>().CurrentValue; - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _eventBus = GetRequiredService(); - } - - [Fact] - public async Task ValidateTransactionTest() + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); + + TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - - TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; - _eventBus.Subscribe(d => - { - transactionExecutionValidationFailedEvent = d; - return Task.CompletedTask; - }); - - var transactionMockExecutionHelper = GetRequiredService(); - transactionMockExecutionHelper.SetTransactionResultStatus(TransactionResultStatus.Mined); - var kernelTestHelper = GetRequiredService(); - var transaction = kernelTestHelper.GenerateTransaction(); - - var result = - await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync()); - result.ShouldBeTrue(); - - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionExecutionValidationFailedEvent.ShouldBeNull(); - } - - [Theory] - [InlineData(TransactionResultStatus.Conflict)] - [InlineData(TransactionResultStatus.NotExisted)] - [InlineData(TransactionResultStatus.Failed)] - [InlineData(TransactionResultStatus.Pending)] - public async Task ValidateTransactionFailedTest(TransactionResultStatus status) + transactionExecutionValidationFailedEvent = d; + return Task.CompletedTask; + }); + + var transactionMockExecutionHelper = GetRequiredService(); + transactionMockExecutionHelper.SetTransactionResultStatus(TransactionResultStatus.Mined); + var kernelTestHelper = GetRequiredService(); + var transaction = kernelTestHelper.GenerateTransaction(); + + var result = + await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, + await _kernelTestHelper.GetChainContextAsync()); + result.ShouldBeTrue(); + + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionExecutionValidationFailedEvent.ShouldBeNull(); + } + + [Theory] + [InlineData(TransactionResultStatus.Conflict)] + [InlineData(TransactionResultStatus.NotExisted)] + [InlineData(TransactionResultStatus.Failed)] + [InlineData(TransactionResultStatus.Pending)] + public async Task ValidateTransactionFailedTest(TransactionResultStatus status) + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - - TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; - _eventBus.Subscribe(d => - { - transactionExecutionValidationFailedEvent = d; - return Task.CompletedTask; - }); - - var transactionMockExecutionHelper = GetRequiredService(); - transactionMockExecutionHelper.SetTransactionResultStatus(status); - var kernelTestHelper = GetRequiredService(); - var transaction = kernelTestHelper.GenerateTransaction(); - var result = - await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, - await _kernelTestHelper.GetChainContextAsync()); - result.ShouldBeFalse(); - - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transaction.GetHash()); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus - .NodeValidationFailed); - - transactionExecutionValidationFailedEvent.ShouldNotBeNull(); - transactionExecutionValidationFailedEvent.TransactionId.ShouldBe(transaction.GetHash()); - } - - [Fact] - public async Task ValidateTransactionTest_DisableTransactionExecutionValidation() + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); + + TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - - TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; - _eventBus.Subscribe(d => - { - transactionExecutionValidationFailedEvent = d; - return Task.CompletedTask; - }); - - _transactionOptions.EnableTransactionExecutionValidation = false; - var transactionMockExecutionHelper = GetRequiredService(); - transactionMockExecutionHelper.SetTransactionResultStatus(TransactionResultStatus.Failed); - var kernelTestHelper = GetRequiredService(); - var transaction = kernelTestHelper.GenerateTransaction(); - var result = await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync()); - result.ShouldBeTrue(); - - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionExecutionValidationFailedEvent.ShouldBeNull(); - } + transactionExecutionValidationFailedEvent = d; + return Task.CompletedTask; + }); + + var transactionMockExecutionHelper = GetRequiredService(); + transactionMockExecutionHelper.SetTransactionResultStatus(status); + var kernelTestHelper = GetRequiredService(); + var transaction = kernelTestHelper.GenerateTransaction(); + var result = + await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, + await _kernelTestHelper.GetChainContextAsync()); + result.ShouldBeFalse(); + + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transaction.GetHash()); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + + transactionExecutionValidationFailedEvent.ShouldNotBeNull(); + transactionExecutionValidationFailedEvent.TransactionId.ShouldBe(transaction.GetHash()); + } + + [Fact] + public async Task ValidateTransactionTest_DisableTransactionExecutionValidation() + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => + { + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); + + TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null; + _eventBus.Subscribe(d => + { + transactionExecutionValidationFailedEvent = d; + return Task.CompletedTask; + }); + + _transactionOptions.EnableTransactionExecutionValidation = false; + var transactionMockExecutionHelper = GetRequiredService(); + transactionMockExecutionHelper.SetTransactionResultStatus(TransactionResultStatus.Failed); + var kernelTestHelper = GetRequiredService(); + var transaction = kernelTestHelper.GenerateTransaction(); + var result = + await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, + await _kernelTestHelper.GetChainContextAsync()); + result.ShouldBeTrue(); + + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionExecutionValidationFailedEvent.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionMethodValidationProviderTests.cs b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionMethodValidationProviderTests.cs index a432b6ae43..8ba654e39d 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionMethodValidationProviderTests.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TransactionMethodValidationProviderTests.cs @@ -7,54 +7,55 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public class TransactionMethodValidationProviderTests : AElfIntegratedTest { - public class TransactionMethodValidationProviderTests : AElfIntegratedTest + private readonly IBlockchainService _blockchainService; + private readonly ILocalEventBus _eventBus; + private readonly KernelTestHelper _kernelTestHelper; + private readonly TransactionMethodValidationProvider _transactionMethodValidationProvider; + private readonly TransactionOptions _transactionOptions; + + public TransactionMethodValidationProviderTests() { - private readonly TransactionMethodValidationProvider _transactionMethodValidationProvider; - private readonly TransactionOptions _transactionOptions; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ILocalEventBus _eventBus; + _transactionMethodValidationProvider = GetRequiredService(); + _transactionOptions = GetRequiredService>().CurrentValue; + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _eventBus = GetRequiredService(); + } - public TransactionMethodValidationProviderTests() - { - _transactionMethodValidationProvider = GetRequiredService(); - _transactionOptions = GetRequiredService>().CurrentValue; - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _eventBus = GetRequiredService(); - } - - [Fact] - public async Task ValidateTransactionTest() + [Fact] + public async Task ValidateTransactionTest() + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - - var kernelTestHelper = GetRequiredService(); - var transaction = kernelTestHelper.GenerateTransaction(); - - var result = - await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync()); - result.ShouldBeTrue(); - - transactionValidationStatusChangedEventData.ShouldBeNull(); - - transaction.MethodName = "View"; - - result = - await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync()); - result.ShouldBeFalse(); - - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed); - transactionValidationStatusChangedEventData.Error.ShouldBe("View transaction is not allowed."); - - } + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); + + var kernelTestHelper = GetRequiredService(); + var transaction = kernelTestHelper.GenerateTransaction(); + + var result = + await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, + await _kernelTestHelper.GetChainContextAsync()); + result.ShouldBeTrue(); + + transactionValidationStatusChangedEventData.ShouldBeNull(); + + transaction.MethodName = "View"; + + result = + await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, + await _kernelTestHelper.GetChainContextAsync()); + result.ShouldBeFalse(); + + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + transactionValidationStatusChangedEventData.Error.ShouldBe("View transaction is not allowed."); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TxHubTests.cs b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TxHubTests.cs index 3470496eb1..958fc08c70 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TxHubTests.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/Infrastructure/TxHubTests.cs @@ -1,464 +1,456 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using AElf.Kernel.Blockchain; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Events; using AElf.Types; using Google.Protobuf; using Shouldly; -using Volo.Abp.EventBus; using Volo.Abp.EventBus.Local; -using Volo.Abp.Threading; using Xunit; -namespace AElf.Kernel.TransactionPool.Infrastructure +namespace AElf.Kernel.TransactionPool.Infrastructure; + +public sealed class TxHubTests : TransactionPoolTxHubTestBase { - public sealed class TxHubTests : TransactionPoolTxHubTestBase + private readonly IBlockchainService _blockchainService; + private readonly ILocalEventBus _eventBus; + private readonly KernelTestHelper _kernelTestHelper; + private readonly ITxHub _txHub; + + public TxHubTests() { - private readonly ITxHub _txHub; - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; - private readonly ILocalEventBus _eventBus; + _txHub = GetRequiredService(); + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _eventBus = GetRequiredService(); + } - public TxHubTests() + [Fact] + public async Task TxHub_Test() + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => { - _txHub = GetRequiredService(); - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _eventBus = GetRequiredService(); - } + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); - [Fact] - public async Task TxHub_Test() + TransactionAcceptedEvent transactionAcceptedEvent = null; + _eventBus.Subscribe(d => { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - - TransactionAcceptedEvent transactionAcceptedEvent = null; - _eventBus.Subscribe(d => - { - transactionAcceptedEvent = d; - return Task.CompletedTask; - }); + transactionAcceptedEvent = d; + return Task.CompletedTask; + }); - { - // Empty transaction pool - // Chain: - // BestChainHeight: 11 - // TxHub: - // BestChainHeight: 0 - // AllTransaction: 0 - // ValidatedTransaction: 0 - await TxHubBestChainShouldBeAsync(Hash.Empty, 0); - await TransactionPoolSizeShouldBeAsync(0, 0); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldBeNull(); - } - - { - // Receive a valid transaction - // Chain: - // BestChainHeight: 11 - // TxHub: - // BestChainHeight: 0 - // AllTransaction: 0 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); - var transactionValid = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - - await AddTransactionsAsync(new List {transactionValid}); - await TxHubBestChainShouldBeAsync(Hash.Empty, 0); - await TransactionPoolSizeShouldBeAsync(0, 0); - await CheckTransactionInPoolAsync(transactionValid, false); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldBeNull(); - } - - { - // Receive best chain found event - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 0 - // ValidatedTransaction: 0 - await _kernelTestHelper.AttachBlockToBestChain(); - var chain = await _blockchainService.GetChainAsync(); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(0, 0); - } - - { - // Receive a different branch transaction - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var transactionDifferent = _kernelTestHelper.GenerateTransaction(12); - var chain = await _blockchainService.GetChainAsync(); - await AddTransactionsAsync(new List {transactionDifferent}); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(1, 0); - await CheckTransactionInPoolAsync(transactionDifferent, true); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldBeNull(); - } - - { - // Receive a future transaction - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); - var transactionFuture = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 1); - await AddTransactionsAsync(new List {transactionFuture}); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(1, 0); - await CheckTransactionInPoolAsync(transactionFuture, false); - - transactionAcceptedEvent.ShouldBeNull(); - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionFuture.GetHash()); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus - .NodeValidationFailed); - transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired"); - - transactionValidationStatusChangedEventData = null; - } + { + // Empty transaction pool + // Chain: + // BestChainHeight: 11 + // TxHub: + // BestChainHeight: 0 + // AllTransaction: 0 + // ValidatedTransaction: 0 + await TxHubBestChainShouldBeAsync(Hash.Empty, 0); + await TransactionPoolSizeShouldBeAsync(0, 0); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldBeNull(); + } - { - // Receive a invalid transaction - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); - var transactionInvalid = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - transactionInvalid.Signature = ByteString.Empty; - await AddTransactionsAsync(new List {transactionInvalid}); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(1, 0); - await CheckTransactionInPoolAsync(transactionInvalid, false); - - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionInvalid.GetHash()); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus - .NodeValidationFailed); - transactionValidationStatusChangedEventData.Error.ShouldBe("Incorrect transaction signature."); - transactionAcceptedEvent.ShouldBeNull(); - - transactionValidationStatusChangedEventData = null; - } + { + // Receive a valid transaction + // Chain: + // BestChainHeight: 11 + // TxHub: + // BestChainHeight: 0 + // AllTransaction: 0 + // ValidatedTransaction: 0 + var chain = await _blockchainService.GetChainAsync(); + var transactionValid = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - { - // Receive a transaction already in DB - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); - var transactionInDB = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - await _blockchainService.AddTransactionsAsync(new List {transactionInDB}); - await AddTransactionsAsync(new List {transactionInDB}); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(1, 0); - await CheckTransactionInPoolAsync(transactionInDB, false); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldBeNull(); - } + await AddTransactionsAsync(new List { transactionValid }); + await TxHubBestChainShouldBeAsync(Hash.Empty, 0); + await TransactionPoolSizeShouldBeAsync(0, 0); + await CheckTransactionInPoolAsync(transactionValid, false); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldBeNull(); + } - { - // Receive a valid transaction - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 2 - // ValidatedTransaction: 1 - var chain = await _blockchainService.GetChainAsync(); - var transactionValid = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - - await AddTransactionsAsync(new List {transactionValid}); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(2, 1); - await CheckTransactionInPoolAsync(transactionValid, true); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldNotBeNull(); - transactionAcceptedEvent.Transaction.ShouldBe(transactionValid); - transactionAcceptedEvent.ChainId.ShouldBe(chain.Id); - - transactionAcceptedEvent = null; - - // Receive the valid transaction again - // Chain: - // BestChainHeight: 12 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 2 - // ValidatedTransaction: 1 - await AddTransactionsAsync(new List {transactionValid}); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(2, 1); - await CheckTransactionInPoolAsync(transactionValid, true); - transactionValidationStatusChangedEventData.ShouldBeNull(); - transactionAcceptedEvent.ShouldBeNull(); - - // Mined a block - // Chain: - // BestChainHeight: 13 - // TxHub: - // BestChainHeight: 12 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var transactionNotInPool = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - - var newBlock = await _kernelTestHelper.AttachBlockToBestChain(new List - { - transactionValid, - transactionNotInPool - }); - - await _txHub.CleanByTransactionIdsAsync(newBlock.TransactionIds); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); - await TransactionPoolSizeShouldBeAsync(1, 1); - await CheckTransactionInPoolAsync(transactionValid, false); - } + { + // Receive best chain found event + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 0 + // ValidatedTransaction: 0 + await _kernelTestHelper.AttachBlockToBestChain(); + var chain = await _blockchainService.GetChainAsync(); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(0, 0); + } - { - // Receive best chain found event - // Chain: - // BestChainHeight: 13 - // TxHub: - // BestChainHeight: 13 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); + { + // Receive a different branch transaction + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 1 + // ValidatedTransaction: 0 + var transactionDifferent = _kernelTestHelper.GenerateTransaction(12); + var chain = await _blockchainService.GetChainAsync(); + await AddTransactionsAsync(new List { transactionDifferent }); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(1, 0); + await CheckTransactionInPoolAsync(transactionDifferent, true); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldBeNull(); + } - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + { + // Receive a future transaction + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 1 + // ValidatedTransaction: 0 + var chain = await _blockchainService.GetChainAsync(); + var transactionFuture = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 1); + await AddTransactionsAsync(new List { transactionFuture }); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(1, 0); + await CheckTransactionInPoolAsync(transactionFuture, false); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); - await TransactionPoolSizeShouldBeAsync(1, 0); - } + transactionAcceptedEvent.ShouldBeNull(); + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionFuture.GetHash()); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired"); - { - // Receive a valid transaction and a expired transaction - // Chain: - // BestChainHeight: 13 - // TxHub: - // BestChainHeight: 13 - // AllTransaction: 2 - // ValidatedTransaction: 1 - var chain = await _blockchainService.GetChainAsync(); - var transactionValid = - _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - var transactionExpired = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 100); - - await AddTransactionsAsync(new List - { - transactionValid, - transactionExpired - }); + transactionValidationStatusChangedEventData = null; + } - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); - await TransactionPoolSizeShouldBeAsync(2, 1); - await CheckTransactionInPoolAsync(transactionValid, true); - await CheckTransactionInPoolAsync(transactionExpired, false); - - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionExpired.GetHash()); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus - .NodeValidationFailed); - transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired"); - - transactionAcceptedEvent.ShouldNotBeNull(); - transactionAcceptedEvent.Transaction.ShouldBe(transactionValid); - transactionAcceptedEvent.ChainId.ShouldBe(chain.Id); - - transactionAcceptedEvent = null; - transactionValidationStatusChangedEventData = null; - } + { + // Receive a invalid transaction + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 1 + // ValidatedTransaction: 0 + var chain = await _blockchainService.GetChainAsync(); + var transactionInvalid = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + transactionInvalid.Signature = ByteString.Empty; + await AddTransactionsAsync(new List { transactionInvalid }); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(1, 0); + await CheckTransactionInPoolAsync(transactionInvalid, false); - { - // Set lib 12 - // Chain: - // BestChainHeight: 13 - // TxHub: - // BestChainHeight: 13 - // AllTransaction: 1 - // ValidatedTransaction: 1 - var chain = await _blockchainService.GetChainAsync(); - - await _txHub.CleanByHeightAsync(12); - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); - await TransactionPoolSizeShouldBeAsync(1, 1); - } + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionInvalid.GetHash()); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + transactionValidationStatusChangedEventData.Error.ShouldBe("Incorrect transaction signature."); + transactionAcceptedEvent.ShouldBeNull(); - { - // After 513 blocks - // Chain: - // BestChainHeight: 526 - // TxHub: - // BestChainHeight: 526 - // AllTransaction: 1 - // ValidatedTransaction: 0 - var chain = await _blockchainService.GetChainAsync(); - var bestChainHeight = chain.BestChainHeight; - for (var i = 0; i < KernelConstants.ReferenceBlockValidPeriod + 1; i++) - { - var transaction = _kernelTestHelper.GenerateTransaction(bestChainHeight + i); - await _kernelTestHelper.AttachBlockToBestChain(new List {transaction}); - chain = await _blockchainService.GetChainAsync(); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - } - - await TxHubBestChainShouldBeAsync(chain.BestChainHash, 526); - - await TransactionPoolSizeShouldBeAsync(0, 0); - } + transactionValidationStatusChangedEventData = null; } - [Fact] - public async Task UpdateTransactionPoolByBestChain_Test() { + // Receive a transaction already in DB + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 1 + // ValidatedTransaction: 0 var chain = await _blockchainService.GetChainAsync(); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - var transaction = - _kernelTestHelper.GenerateTransaction(_kernelTestHelper.LongestBranchBlockList[2].Height, - _kernelTestHelper.LongestBranchBlockList[2].GetHash()); - await AddTransactionsAsync(new[] {transaction}); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - + var transactionInDB = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + await _blockchainService.AddTransactionsAsync(new List { transactionInDB }); + await AddTransactionsAsync(new List { transactionInDB }); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); await TransactionPoolSizeShouldBeAsync(1, 0); - - await _blockchainService.SetBestChainAsync(chain, _kernelTestHelper.LongestBranchBlockList.Last().Height, - _kernelTestHelper.LongestBranchBlockList.Last().GetHash()); - chain = await _blockchainService.GetChainAsync(); - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - - await TransactionPoolSizeShouldBeAsync(1, 1); + await CheckTransactionInPoolAsync(transactionInDB, false); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldBeNull(); } - [Fact] - public async Task AddTransactions_Limit_Test() { - TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; - _eventBus.Subscribe(d => - { - transactionValidationStatusChangedEventData = d; - return Task.CompletedTask; - }); - + // Receive a valid transaction + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 2 + // ValidatedTransaction: 1 var chain = await _blockchainService.GetChainAsync(); + var transactionValid = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + + await AddTransactionsAsync(new List { transactionValid }); await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - for (var i = 0; i < 20; i++) + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(2, 1); + await CheckTransactionInPoolAsync(transactionValid, true); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldNotBeNull(); + transactionAcceptedEvent.Transaction.ShouldBe(transactionValid); + transactionAcceptedEvent.ChainId.ShouldBe(chain.Id); + + transactionAcceptedEvent = null; + + // Receive the valid transaction again + // Chain: + // BestChainHeight: 12 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 2 + // ValidatedTransaction: 1 + await AddTransactionsAsync(new List { transactionValid }); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(2, 1); + await CheckTransactionInPoolAsync(transactionValid, true); + transactionValidationStatusChangedEventData.ShouldBeNull(); + transactionAcceptedEvent.ShouldBeNull(); + + // Mined a block + // Chain: + // BestChainHeight: 13 + // TxHub: + // BestChainHeight: 12 + // AllTransaction: 1 + // ValidatedTransaction: 0 + var transactionNotInPool = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + + var newBlock = await _kernelTestHelper.AttachBlockToBestChain(new List { - var tx = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - await AddTransactionsAsync(new[] {tx}); - } - await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - await TransactionPoolSizeShouldBeAsync(20, 20); + transactionValid, + transactionNotInPool + }); - var transaction = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); - await AddTransactionsAsync(new[] {transaction}); - await TransactionPoolSizeShouldBeAsync(20, 20); - - transactionValidationStatusChangedEventData.ShouldNotBeNull(); - transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transaction.GetHash()); - transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus - .NodeValidationFailed); - transactionValidationStatusChangedEventData.Error.ShouldBe("Transaction Pool is full."); + await _txHub.CleanByTransactionIdsAsync(newBlock.TransactionIds); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12); + await TransactionPoolSizeShouldBeAsync(1, 1); + await CheckTransactionInPoolAsync(transactionValid, false); } - [Fact] - public async Task GetExecutableTransactionSet_Test() { + // Receive best chain found event + // Chain: + // BestChainHeight: 13 + // TxHub: + // BestChainHeight: 13 + // AllTransaction: 1 + // ValidatedTransaction: 0 var chain = await _blockchainService.GetChainAsync(); await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); - - var transaction = + + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); + await TransactionPoolSizeShouldBeAsync(1, 0); + } + + { + // Receive a valid transaction and a expired transaction + // Chain: + // BestChainHeight: 13 + // TxHub: + // BestChainHeight: 13 + // AllTransaction: 2 + // ValidatedTransaction: 1 + var chain = await _blockchainService.GetChainAsync(); + var transactionValid = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + var transactionExpired = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 100); + await AddTransactionsAsync(new List { - transaction + transactionValid, + transactionExpired }); await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); + await TransactionPoolSizeShouldBeAsync(2, 1); + await CheckTransactionInPoolAsync(transactionValid, true); + await CheckTransactionInPoolAsync(transactionExpired, false); - var executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, 0); - executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); - executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); - executableTransactionSet.Transactions.Count.ShouldBe(0); - - executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); - executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); - executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); - executableTransactionSet.Transactions[0].ShouldBe(transaction); - - var wrongBlockHash = HashHelper.ComputeFrom("WrongBlockHash"); - executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(wrongBlockHash, int.MaxValue); - executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); - executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); - executableTransactionSet.Transactions.Count.ShouldBe(0); + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionExpired.GetHash()); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired"); + + transactionAcceptedEvent.ShouldNotBeNull(); + transactionAcceptedEvent.Transaction.ShouldBe(transactionValid); + transactionAcceptedEvent.ChainId.ShouldBe(chain.Id); + + transactionAcceptedEvent = null; + transactionValidationStatusChangedEventData = null; } - private async Task AddTransactionsAsync(IEnumerable transactions) { - await _txHub.AddTransactionsAsync(transactions); - await Task.Delay(200); - } + // Set lib 12 + // Chain: + // BestChainHeight: 13 + // TxHub: + // BestChainHeight: 13 + // AllTransaction: 1 + // ValidatedTransaction: 1 + var chain = await _blockchainService.GetChainAsync(); - #region check methods + await _txHub.CleanByHeightAsync(12); + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13); + await TransactionPoolSizeShouldBeAsync(1, 1); + } - private async Task CheckTransactionInPoolAsync(Transaction transaction, bool isInPool) { - var existQueuedTransaction = await _txHub.GetQueuedTransactionAsync(transaction.GetHash()); - if (isInPool) - { - existQueuedTransaction.Transaction.ShouldBe(transaction); - } - else + // After 513 blocks + // Chain: + // BestChainHeight: 526 + // TxHub: + // BestChainHeight: 526 + // AllTransaction: 1 + // ValidatedTransaction: 0 + var chain = await _blockchainService.GetChainAsync(); + var bestChainHeight = chain.BestChainHeight; + for (var i = 0; i < KernelConstants.ReferenceBlockValidPeriod + 1; i++) { - existQueuedTransaction.ShouldBeNull(); + var transaction = _kernelTestHelper.GenerateTransaction(bestChainHeight + i); + await _kernelTestHelper.AttachBlockToBestChain(new List { transaction }); + chain = await _blockchainService.GetChainAsync(); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); } + + await TxHubBestChainShouldBeAsync(chain.BestChainHash, 526); + + await TransactionPoolSizeShouldBeAsync(0, 0); } + } - private async Task TransactionPoolSizeShouldBeAsync(int allTransactionCount, int validatedTransactionCount) + [Fact] + public async Task UpdateTransactionPoolByBestChain_Test() + { + var chain = await _blockchainService.GetChainAsync(); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + var transaction = + _kernelTestHelper.GenerateTransaction(_kernelTestHelper.LongestBranchBlockList[2].Height, + _kernelTestHelper.LongestBranchBlockList[2].GetHash()); + await AddTransactionsAsync(new[] { transaction }); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + + await TransactionPoolSizeShouldBeAsync(1, 0); + + await _blockchainService.SetBestChainAsync(chain, _kernelTestHelper.LongestBranchBlockList.Last().Height, + _kernelTestHelper.LongestBranchBlockList.Last().GetHash()); + chain = await _blockchainService.GetChainAsync(); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + + await TransactionPoolSizeShouldBeAsync(1, 1); + } + + [Fact] + public async Task AddTransactions_Limit_Test() + { + TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null; + _eventBus.Subscribe(d => { - var transactionPoolStatus = await _txHub.GetTransactionPoolStatusAsync(); - transactionPoolStatus.AllTransactionCount.ShouldBe(allTransactionCount); - transactionPoolStatus.ValidatedTransactionCount.ShouldBe(validatedTransactionCount); - } + transactionValidationStatusChangedEventData = d; + return Task.CompletedTask; + }); - private async Task TxHubBestChainShouldBeAsync(Hash blockHash, long blockHeight) + var chain = await _blockchainService.GetChainAsync(); + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + for (var i = 0; i < 20; i++) { - var executableTxSet = await _txHub.GetExecutableTransactionSetAsync(blockHash, int.MaxValue); - executableTxSet.PreviousBlockHash.ShouldBe(blockHash); - executableTxSet.PreviousBlockHeight.ShouldBe(blockHeight); + var tx = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + await AddTransactionsAsync(new[] { tx }); } - #endregion + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + await TransactionPoolSizeShouldBeAsync(20, 20); + + var transaction = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + await AddTransactionsAsync(new[] { transaction }); + await TransactionPoolSizeShouldBeAsync(20, 20); + + transactionValidationStatusChangedEventData.ShouldNotBeNull(); + transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transaction.GetHash()); + transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus + .NodeValidationFailed); + transactionValidationStatusChangedEventData.Error.ShouldBe("Transaction Pool is full."); + } + + [Fact] + public async Task GetExecutableTransactionSet_Test() + { + var chain = await _blockchainService.GetChainAsync(); + + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + + var transaction = + _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash); + await AddTransactionsAsync(new List + { + transaction + }); + + await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight); + + var executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, 0); + executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); + executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); + executableTransactionSet.Transactions.Count.ShouldBe(0); + + executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); + executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); + executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); + executableTransactionSet.Transactions[0].ShouldBe(transaction); + + var wrongBlockHash = HashHelper.ComputeFrom("WrongBlockHash"); + executableTransactionSet = await _txHub.GetExecutableTransactionSetAsync(wrongBlockHash, int.MaxValue); + executableTransactionSet.PreviousBlockHash.ShouldBe(chain.BestChainHash); + executableTransactionSet.PreviousBlockHeight.ShouldBe(chain.BestChainHeight); + executableTransactionSet.Transactions.Count.ShouldBe(0); } + + private async Task AddTransactionsAsync(IEnumerable transactions) + { + await _txHub.AddTransactionsAsync(transactions); + await Task.Delay(200); + } + + #region check methods + + private async Task CheckTransactionInPoolAsync(Transaction transaction, bool isInPool) + { + var existQueuedTransaction = await _txHub.GetQueuedTransactionAsync(transaction.GetHash()); + if (isInPool) + existQueuedTransaction.Transaction.ShouldBe(transaction); + else + existQueuedTransaction.ShouldBeNull(); + } + + private async Task TransactionPoolSizeShouldBeAsync(int allTransactionCount, int validatedTransactionCount) + { + var transactionPoolStatus = await _txHub.GetTransactionPoolStatusAsync(); + transactionPoolStatus.AllTransactionCount.ShouldBe(allTransactionCount); + transactionPoolStatus.ValidatedTransactionCount.ShouldBe(validatedTransactionCount); + } + + private async Task TxHubBestChainShouldBeAsync(Hash blockHash, long blockHeight) + { + var executableTxSet = await _txHub.GetExecutableTransactionSetAsync(blockHash, int.MaxValue); + executableTxSet.PreviousBlockHash.ShouldBe(blockHash); + executableTxSet.PreviousBlockHeight.ShouldBe(blockHeight); + } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/TransactionMockExecutionHelper.cs b/test/AElf.Kernel.TransactionPool.Tests/TransactionMockExecutionHelper.cs index bd194b2327..2e0997892c 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/TransactionMockExecutionHelper.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/TransactionMockExecutionHelper.cs @@ -1,19 +1,18 @@ using AElf.Types; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionMockExecutionHelper { - public class TransactionMockExecutionHelper - { - private TransactionResultStatus _transactionResultStatus; + private TransactionResultStatus _transactionResultStatus; - internal void SetTransactionResultStatus(TransactionResultStatus transactionResultStatus) - { - _transactionResultStatus = transactionResultStatus; - } + internal void SetTransactionResultStatus(TransactionResultStatus transactionResultStatus) + { + _transactionResultStatus = transactionResultStatus; + } - internal TransactionResultStatus GetTransactionResultStatus() - { - return _transactionResultStatus; - } + internal TransactionResultStatus GetTransactionResultStatus() + { + return _transactionResultStatus; } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestAElfModule.cs b/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestAElfModule.cs index 3d8e119670..6dea5d64ed 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestAElfModule.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestAElfModule.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.TransactionPool.Application; using AElf.Kernel.TransactionPool.Infrastructure; using AElf.Kernel.Txn.Application; using AElf.Modularity; @@ -13,92 +12,92 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +[DependsOn( + typeof(TransactionPoolAElfModule), + typeof(KernelCoreTestAElfModule), + typeof(SmartContractAElfModule) +)] +public class TransactionPoolTestAElfModule : AElfModule { - [DependsOn( - typeof(TransactionPoolAElfModule), - typeof(KernelCoreTestAElfModule), - typeof(SmartContractAElfModule) - )] - public class TransactionPoolTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - } + context.Services.AddTransient(); } +} - [DependsOn( - typeof(TransactionPoolTestAElfModule), - typeof(KernelCoreWithChainTestAElfModule) - )] - public class TransactionPoolWithChainTestAElfModule : AElfModule +[DependsOn( + typeof(TransactionPoolTestAElfModule), + typeof(KernelCoreWithChainTestAElfModule) +)] +public class TransactionPoolWithChainTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } - - [DependsOn( - typeof(TransactionPoolWithChainTestAElfModule) - )] - public class TransactionPoolTxHubTestAElfModule : AElfModule +} + +[DependsOn( + typeof(TransactionPoolWithChainTestAElfModule) +)] +public class TransactionPoolTxHubTestAElfModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - Configure(o => { o.PoolLimit = 20; }); + var services = context.Services; + Configure(o => { o.PoolLimit = 20; }); - context.Services.RemoveAll(); - context.Services.AddTransient(); - } + context.Services.RemoveAll(); + context.Services.AddTransient(); } +} - [DependsOn( - typeof(TransactionPoolTestAElfModule), - typeof(KernelCoreWithChainTestAElfModule) - )] - public class TransactionExecutionValidationModule : AElfModule +[DependsOn( + typeof(TransactionPoolTestAElfModule), + typeof(KernelCoreWithChainTestAElfModule) +)] +public class TransactionExecutionValidationModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + var services = context.Services; + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); - services.AddSingleton(provider => - { - var mockService = new Mock(); + services.AddSingleton(provider => + { + var mockService = new Mock(); - mockService.Setup(m => - m.ExecuteAsync(It.IsAny(), It.IsAny())) - .Returns((transactionExecutingDto, cancellationToken) => + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), It.IsAny())) + .Returns((transactionExecutingDto, cancellationToken) => + { + var transactionMockExecutionHelper = + context.Services.GetRequiredServiceLazy().Value; + return Task.FromResult(new List { - var transactionMockExecutionHelper = - context.Services.GetRequiredServiceLazy().Value; - return Task.FromResult(new List + new() { - new ExecutionReturnSet - { - Status = transactionMockExecutionHelper.GetTransactionResultStatus() - } - }); + Status = transactionMockExecutionHelper.GetTransactionResultStatus() + } }); + }); + + return mockService.Object; + }); - return mockService.Object; - }); - - services.AddSingleton(provider => - { - var mockService = new Mock(); + services.AddSingleton(provider => + { + var mockService = new Mock(); - mockService.Setup(m => - m.IsViewTransactionAsync(It.IsAny(), It.IsAny())) - .Returns((chainContext, transaction) => Task.FromResult(transaction.MethodName == "View")); + mockService.Setup(m => + m.IsViewTransactionAsync(It.IsAny(), It.IsAny())) + .Returns((chainContext, transaction) => + Task.FromResult(transaction.MethodName == "View")); - return mockService.Object; - }); - } + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestBase.cs b/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestBase.cs index 6e828e0108..0cc85f5685 100644 --- a/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestBase.cs +++ b/test/AElf.Kernel.TransactionPool.Tests/TransactionPoolTestBase.cs @@ -1,16 +1,15 @@ using AElf.TestBase; -namespace AElf.Kernel.TransactionPool +namespace AElf.Kernel.TransactionPool; + +public class TransactionPoolWithChainTestBase : AElfIntegratedTest +{ +} + +public class TransactionPoolTxHubTestBase : AElfIntegratedTest +{ +} + +public class TransactionPoolTestBase : AElfIntegratedTest { - public class TransactionPoolWithChainTestBase : AElfIntegratedTest - { - } - - public class TransactionPoolTxHubTestBase : AElfIntegratedTest - { - } - - public class TransactionPoolTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/AElf.Kernel.Types.Tests.csproj b/test/AElf.Kernel.Types.Tests/AElf.Kernel.Types.Tests.csproj index f4444d8fd1..690a63ab96 100644 --- a/test/AElf.Kernel.Types.Tests/AElf.Kernel.Types.Tests.csproj +++ b/test/AElf.Kernel.Types.Tests/AElf.Kernel.Types.Tests.csproj @@ -4,15 +4,15 @@ false - - - - - - + + + + + + - - + + diff --git a/test/AElf.Kernel.Types.Tests/Block/BlockTests.cs b/test/AElf.Kernel.Types.Tests/Block/BlockTests.cs index fed9460c28..41714e9013 100644 --- a/test/AElf.Kernel.Types.Tests/Block/BlockTests.cs +++ b/test/AElf.Kernel.Types.Tests/Block/BlockTests.cs @@ -3,211 +3,211 @@ using System.Threading; using AElf.Types; using Google.Protobuf; -using Xunit; using Shouldly; +using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class BlockTests { - public class BlockTests + [Fact] + public void BlockHeader_Test() { - [Fact] - public void BlockHeader_Test() - { - var blockHeader = GenerateBlockHeader(); - var hash = blockHeader.GetHash(); - hash.ShouldNotBe(null); + var blockHeader = GenerateBlockHeader(); + var hash = blockHeader.GetHash(); + hash.ShouldNotBe(null); - var hashByte = blockHeader.GetHashBytes(); - hashByte.ShouldNotBe(null); + var hashByte = blockHeader.GetHashBytes(); + hashByte.ShouldNotBe(null); - //exception cases - blockHeader = GenerateBlockHeader(); - blockHeader.ChainId = -12; - Should.Throw(() => { blockHeader.GetHash(); }); + //exception cases + blockHeader = GenerateBlockHeader(); + blockHeader.ChainId = -12; + Should.Throw(() => { blockHeader.GetHash(); }); - blockHeader = GenerateBlockHeader(); - blockHeader.SignerPubkey = ByteString.Empty; - Should.Throw(() => { blockHeader.GetHash(); }); + blockHeader = GenerateBlockHeader(); + blockHeader.SignerPubkey = ByteString.Empty; + Should.Throw(() => { blockHeader.GetHash(); }); - blockHeader = GenerateBlockHeader(); - blockHeader.PreviousBlockHash = null; - Should.Throw(() => { blockHeader.GetHash(); }); + blockHeader = GenerateBlockHeader(); + blockHeader.PreviousBlockHash = null; + Should.Throw(() => { blockHeader.GetHash(); }); - blockHeader = GenerateBlockHeader(); - blockHeader.MerkleTreeRootOfTransactionStatus = null; - Should.Throw(() => { blockHeader.GetHash(); }); + blockHeader = GenerateBlockHeader(); + blockHeader.MerkleTreeRootOfTransactionStatus = null; + Should.Throw(() => { blockHeader.GetHash(); }); - blockHeader = GenerateBlockHeader(); - blockHeader.Time = null; - Should.Throw(() => { blockHeader.GetHash(); }); - } + blockHeader = GenerateBlockHeader(); + blockHeader.Time = null; + Should.Throw(() => { blockHeader.GetHash(); }); + } - [Fact] - public void BlockBody_Test() + [Fact] + public void BlockBody_Test() + { + var transactionItems = GenerateFakeTransactions(3); + var blockBody = new BlockBody { - var transactionItems = GenerateFakeTransactions(3); - var blockBody = new BlockBody() - { - TransactionIds = {transactionItems.Item2} - }; - blockBody.TransactionsCount.ShouldBe(3); - } + TransactionIds = { transactionItems.Item2 } + }; + blockBody.TransactionsCount.ShouldBe(3); + } - [Fact] - public void CalculateBodyHash_Test() - { - //transaction count == 0 - var blockBody = new BlockBody(); - Should.Throw(() => blockBody.GetHash()); + [Fact] + public void CalculateBodyHash_Test() + { + //transaction count == 0 + var blockBody = new BlockBody(); + Should.Throw(() => blockBody.GetHash()); - blockBody = new BlockBody + blockBody = new BlockBody + { + TransactionIds = { - TransactionIds = + new[] { - new[] - { - HashHelper.ComputeFrom("tx1"), - HashHelper.ComputeFrom("tx2"), - HashHelper.ComputeFrom("tx3"), - } + HashHelper.ComputeFrom("tx1"), + HashHelper.ComputeFrom("tx2"), + HashHelper.ComputeFrom("tx3") } - }; - var hash = blockBody.GetHash(); - hash.ShouldNotBeNull(); - } + } + }; + var hash = blockBody.GetHash(); + hash.ShouldNotBeNull(); + } - [Fact] - public void BlockIndex_Test() - { - var blockIndex = new BlockIndex(); - blockIndex.BlockHash = Hash.Empty; - blockIndex.BlockHeight = 1L; + [Fact] + public void BlockIndex_Test() + { + var blockIndex = new BlockIndex(); + blockIndex.BlockHash = Hash.Empty; + blockIndex.BlockHeight = 1L; - var blockIndex1 = new BlockIndex(Hash.Empty, 1L); + var blockIndex1 = new BlockIndex(Hash.Empty, 1L); - blockIndex.ToString().ShouldBe(blockIndex1.ToString()); - blockIndex.ToString().Contains(Hash.Empty.ToString()).ShouldBeTrue(); - blockIndex.ToString().Contains("1").ShouldBeTrue(); - - blockIndex.ToDiagnosticString().ShouldBe($"[{blockIndex.BlockHash}: {blockIndex.BlockHeight}]"); - } + blockIndex.ToString().ShouldBe(blockIndex1.ToString()); + blockIndex.ToString().Contains(Hash.Empty.ToString()).ShouldBeTrue(); + blockIndex.ToString().Contains("1").ShouldBeTrue(); - [Fact] - public void Block_Test() - { - var block = CreateBlock(HashHelper.ComputeFrom("hash"), 1234, 10); - block.Height.ShouldBe(10u); + blockIndex.ToDiagnosticString().ShouldBe($"[{blockIndex.BlockHash}: {blockIndex.BlockHeight}]"); + } - var hash = block.GetHash(); - hash.ShouldNotBe(null); - } + [Fact] + public void Block_Test() + { + var block = CreateBlock(HashHelper.ComputeFrom("hash"), 1234, 10); + block.Height.ShouldBe(10u); - [Fact] - public void Get_BlockHash_Test() - { - var blockHeader = GenerateBlockHeader(); - var hash = blockHeader.GetHash(); - hash.ShouldNotBeNull(); + var hash = block.GetHash(); + hash.ShouldNotBe(null); + } - var hashBytes = blockHeader.GetHashBytes(); - hashBytes.Length.ShouldBe(32); + [Fact] + public void Get_BlockHash_Test() + { + var blockHeader = GenerateBlockHeader(); + var hash = blockHeader.GetHash(); + hash.ShouldNotBeNull(); - var hash1 = Hash.LoadFromByteArray(hashBytes); - hash.ShouldBe(hash1); - } - [Fact] - public void GetHashWithoutCache_Test() - { - var blockHeader = GenerateBlockHeader(); - var hash = blockHeader.GetHashWithoutCache(); - hash.ShouldNotBe(null); - - var blockHeader1 = GenerateBlockHeader(); - blockHeader1.Signature = - ByteStringHelper.FromHexString("782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13"); - var hash1=blockHeader1.GetHash(); - hash1.ShouldNotBe(null); - - var block = CreateBlock(HashHelper.ComputeFrom("hash"), 123, 10); - block.Height.ShouldBe(10u); - var hash2 = block.GetHashWithoutCache(); - hash2.ShouldNotBe(null); - - var blockHeader3 = GenerateBlockHeader(); - blockHeader3.Height = 0; - Should.Throw(() => { blockHeader3.GetHash(); }); - } + var hashBytes = blockHeader.GetHashBytes(); + hashBytes.Length.ShouldBe(32); - [Fact] - public void BlockIndex_ToDiagnosticString_Test() - { - var hash = HashHelper.ComputeFrom("test"); - var height = 10; - var blockIndex = new BlockIndex - { - BlockHash = hash, - BlockHeight = height - }; - blockIndex.ToDiagnosticString().ShouldBe($"[{hash}: {height}]"); - } + var hash1 = Hash.LoadFromByteArray(hashBytes); + hash.ShouldBe(hash1); + } + + [Fact] + public void GetHashWithoutCache_Test() + { + var blockHeader = GenerateBlockHeader(); + var hash = blockHeader.GetHashWithoutCache(); + hash.ShouldNotBe(null); + + var blockHeader1 = GenerateBlockHeader(); + blockHeader1.Signature = + ByteStringHelper.FromHexString("782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13"); + var hash1 = blockHeader1.GetHash(); + hash1.ShouldNotBe(null); + + var block = CreateBlock(HashHelper.ComputeFrom("hash"), 123, 10); + block.Height.ShouldBe(10u); + var hash2 = block.GetHashWithoutCache(); + hash2.ShouldNotBe(null); + + var blockHeader3 = GenerateBlockHeader(); + blockHeader3.Height = 0; + Should.Throw(() => { blockHeader3.GetHash(); }); + } - private Block CreateBlock(Hash preBlockHash, int chainId, long height) + [Fact] + public void BlockIndex_ToDiagnosticString_Test() + { + var hash = HashHelper.ComputeFrom("test"); + var height = 10; + var blockIndex = new BlockIndex { - Interlocked.CompareExchange(ref preBlockHash, Hash.Empty, null); + BlockHash = hash, + BlockHeight = height + }; + blockIndex.ToDiagnosticString().ShouldBe($"[{hash}: {height}]"); + } - var block = new Block(HashHelper.ComputeFrom("hash1")); + private Block CreateBlock(Hash preBlockHash, int chainId, long height) + { + Interlocked.CompareExchange(ref preBlockHash, Hash.Empty, null); - block.Header.PreviousBlockHash = preBlockHash; - block.Header.ChainId = chainId; - block.Header.Time = TimestampHelper.GetUtcNow(); - block.Header.Height = height; - var transactionItems = GenerateFakeTransactions(3); - block.Body.TransactionIds.AddRange(transactionItems.Item2); + var block = new Block(HashHelper.ComputeFrom("hash1")); - block.Header.MerkleTreeRootOfTransactions = - BinaryMerkleTree.FromLeafNodes(block.Body.TransactionIds).Root; - block.Header.MerkleTreeRootOfWorldState = Hash.Empty; - block.Header.MerkleTreeRootOfTransactionStatus = Hash.Empty; - block.Header.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); + block.Header.PreviousBlockHash = preBlockHash; + block.Header.ChainId = chainId; + block.Header.Time = TimestampHelper.GetUtcNow(); + block.Header.Height = height; + var transactionItems = GenerateFakeTransactions(3); + block.Body.TransactionIds.AddRange(transactionItems.Item2); - return block; - } + block.Header.MerkleTreeRootOfTransactions = + BinaryMerkleTree.FromLeafNodes(block.Body.TransactionIds).Root; + block.Header.MerkleTreeRootOfWorldState = Hash.Empty; + block.Header.MerkleTreeRootOfTransactionStatus = Hash.Empty; + block.Header.SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey"); + + return block; + } - private (List, List) GenerateFakeTransactions(int count) + private (List, List) GenerateFakeTransactions(int count) + { + var transactions = new List(); + var transactionIds = new List(); + for (var i = 0; i < count; i++) { - var transactions = new List(); - var transactionIds = new List(); - for (int i = 0; i < count; i++) + var transaction = new Transaction { - var transaction = new Transaction() - { - From = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"), - To = Address.FromBase58("2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7"), - MethodName = $"Test{i}", - Params = ByteString.Empty - }; - var hash = transaction.GetHash(); - - transactions.Add(transaction); - transactionIds.Add(hash); - } + From = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"), + To = Address.FromBase58("2vNDCj1WjNLAXm3VnEeGGRMw3Aab4amVSEaYmCyxQKjNhLhfL7"), + MethodName = $"Test{i}", + Params = ByteString.Empty + }; + var hash = transaction.GetHash(); - return (transactions, transactionIds); + transactions.Add(transaction); + transactionIds.Add(hash); } - private BlockHeader GenerateBlockHeader() + return (transactions, transactionIds); + } + + private BlockHeader GenerateBlockHeader() + { + return new BlockHeader { - return new BlockHeader - { - ChainId = 1234, - Height = 10, - PreviousBlockHash = HashHelper.ComputeFrom("hash3"), - MerkleTreeRootOfTransactions = Hash.Empty, - MerkleTreeRootOfWorldState = Hash.Empty, - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfTransactionStatus = Hash.Empty, - SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey") - }; - } + ChainId = 1234, + Height = 10, + PreviousBlockHash = HashHelper.ComputeFrom("hash3"), + MerkleTreeRootOfTransactions = Hash.Empty, + MerkleTreeRootOfWorldState = Hash.Empty, + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfTransactionStatus = Hash.Empty, + SignerPubkey = ByteString.CopyFromUtf8("SignerPubkey") + }; } } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/BloomTests.cs b/test/AElf.Kernel.Types.Tests/BloomTests.cs index 11ce942170..3f7b352c9d 100644 --- a/test/AElf.Kernel.Types.Tests/BloomTests.cs +++ b/test/AElf.Kernel.Types.Tests/BloomTests.cs @@ -8,209 +8,206 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class BloomTests { - public class BloomTests + [Fact] + public void Length_Test() { - [Fact] - public void Length_Test() - { - var bloom = new Bloom(); - bloom.Data.Length.ShouldBe(0); - - var bloomData = Guid.NewGuid().ToByteArray(); - Should.Throw( - () => - { - new Bloom(bloomData); - }); - } - - [Fact] - public void Combine_Test() - { - var bloom = new Bloom(); - var byteString = ByteString.CopyFrom(new Bloom().Data); - bloom.Combine(new[] {new Bloom(byteString.ToByteArray())}); - bloom.Data.Length.ShouldBe(0); - var newBloom = new Bloom(); - newBloom.AddValue(new StringValue() - { - Value = "ELF" - }); - bloom.Combine(new[] - { - newBloom - }); - bloom.Data.Length.ShouldBe(256); - } - - [Fact] - public void AddHashAddValue_Test() - { - var empty = BytesValue.Parser.ParseFrom(ByteString.Empty); - var elf = new StringValue() - { - Value = "ELF" - }; // Serialized: 0a03454c46 - // sha256 of empty string: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - // sha256 of 0a03454c46: 782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13 - var expected = string.Concat( - "0000000000000000000000000000100000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000040000000000000000", - "0000000000000000000100000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000800200000" - ); - var bloom = new Bloom(); - bloom.AddSha256Hash( - ByteArrayHelper.HexStringToByteArray("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); - bloom.AddSha256Hash( - ByteArrayHelper.HexStringToByteArray("782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13")); - Assert.Equal(expected, bloom.Data.ToHex().Replace("0x", "")); - - new Bloom(bloom).Data.ShouldBe(bloom.Data); - // add value - var bloom1 = new Bloom(); - bloom1.AddValue(empty); - bloom1.AddValue(elf); - Assert.Equal(expected, bloom1.Data.ToHex().Replace("0x", "")); - - // Take only 12 characters (2 * 3 = 6 bytes) - var bloom2 = new Bloom(); - var fiftyTwoZeros = string.Join("", Enumerable.Repeat("0", 52)); - - // Too short - Assert.ThrowsAny(() => bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc"))); - Assert.ThrowsAny(() => bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c"))); - - // Too long - - Assert.ThrowsAny(() => - bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc" + "00" + fiftyTwoZeros))); - Assert.ThrowsAny(() => - bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c" + "00" + fiftyTwoZeros))); - - // Right size - bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc" + fiftyTwoZeros)); - bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c" + fiftyTwoZeros)); - Assert.Equal(expected, bloom2.Data.ToHex().Replace("0x", "")); - - // Incorrect value - var bloom3 = new Bloom(); - bloom3.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298f0" + fiftyTwoZeros)); - bloom3.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f80" + fiftyTwoZeros)); - Assert.NotEqual(expected, bloom3.Data.ToHex().Replace("0x", "")); - } - - [Fact] - public void MultiMerge_Test() + var bloom = new Bloom(); + bloom.Data.Length.ShouldBe(0); + + var bloomData = Guid.NewGuid().ToByteArray(); + Should.Throw( + () => { new Bloom(bloomData); }); + } + + [Fact] + public void Combine_Test() + { + var bloom = new Bloom(); + var byteString = ByteString.CopyFrom(new Bloom().Data); + bloom.Combine(new[] { new Bloom(byteString.ToByteArray()) }); + bloom.Data.Length.ShouldBe(0); + var newBloom = new Bloom(); + newBloom.AddValue(new StringValue { - var a = ByteArrayHelper.HexStringToByteArray(string.Concat( - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000" - )); - - var b = ByteArrayHelper.HexStringToByteArray(string.Concat( - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000", - "0100000000000000000000000000000000000000000000000000000000000000" - )); - - var c = ByteArrayHelper.HexStringToByteArray(string.Concat( - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000", - "1100000000000000000000000000000000000000000000000000000000000000" - )); - - var res = Bloom.AndMultipleBloomBytes(new List(){a, b}); - Assert.Equal(c, res); - } - - [Fact] - public void IsIn_Test() + Value = "ELF" + }); + bloom.Combine(new[] { - var target = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000" - ))); - var source = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "1000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000" - ))); - Assert.True(source.IsIn(target)); - - var wrongSource = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( - "1110000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000" - ))); - - Assert.False(wrongSource.IsIn(target)); - - var emptySource=new Bloom(); - Assert.False(emptySource.IsIn(target)); - } - - [Fact] - public async Task AddValue_With_Null_Test() + newBloom + }); + bloom.Data.Length.ShouldBe(256); + } + + [Fact] + public void AddHashAddValue_Test() + { + var empty = BytesValue.Parser.ParseFrom(ByteString.Empty); + var elf = new StringValue { - var bloom = new Bloom(); - bloom.AddValue((IMessage)null); - bloom.Data.Length.ShouldBe(0); - } - - #region AElf.Kernel.LogEventExtensions - - [Fact] - public async Task LogEventGetBloom_Test() + Value = "ELF" + }; // Serialized: 0a03454c46 + // sha256 of empty string: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + // sha256 of 0a03454c46: 782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13 + var expected = string.Concat( + "0000000000000000000000000000100000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000040000000000000000", + "0000000000000000000100000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000800200000" + ); + var bloom = new Bloom(); + bloom.AddSha256Hash( + ByteArrayHelper.HexStringToByteArray("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); + bloom.AddSha256Hash( + ByteArrayHelper.HexStringToByteArray("782330156f8c9403758ed30270a3e2d59e50b8f04c6779d819b72eee02addb13")); + Assert.Equal(expected, bloom.Data.ToHex().Replace("0x", "")); + + new Bloom(bloom).Data.ShouldBe(bloom.Data); + // add value + var bloom1 = new Bloom(); + bloom1.AddValue(empty); + bloom1.AddValue(elf); + Assert.Equal(expected, bloom1.Data.ToHex().Replace("0x", "")); + + // Take only 12 characters (2 * 3 = 6 bytes) + var bloom2 = new Bloom(); + var fiftyTwoZeros = string.Join("", Enumerable.Repeat("0", 52)); + + // Too short + Assert.ThrowsAny(() => bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc"))); + Assert.ThrowsAny(() => bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c"))); + + // Too long + + Assert.ThrowsAny(() => + bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc" + "00" + fiftyTwoZeros))); + Assert.ThrowsAny(() => + bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c" + "00" + fiftyTwoZeros))); + + // Right size + bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298fc" + fiftyTwoZeros)); + bloom2.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f8c" + fiftyTwoZeros)); + Assert.Equal(expected, bloom2.Data.ToHex().Replace("0x", "")); + + // Incorrect value + var bloom3 = new Bloom(); + bloom3.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("e3b0c44298f0" + fiftyTwoZeros)); + bloom3.AddSha256Hash(ByteArrayHelper.HexStringToByteArray("782330156f80" + fiftyTwoZeros)); + Assert.NotEqual(expected, bloom3.Data.ToHex().Replace("0x", "")); + } + + [Fact] + public void MultiMerge_Test() + { + var a = ByteArrayHelper.HexStringToByteArray(string.Concat( + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000" + )); + + var b = ByteArrayHelper.HexStringToByteArray(string.Concat( + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000", + "0100000000000000000000000000000000000000000000000000000000000000" + )); + + var c = ByteArrayHelper.HexStringToByteArray(string.Concat( + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000", + "1100000000000000000000000000000000000000000000000000000000000000" + )); + + var res = Bloom.AndMultipleBloomBytes(new List { a, b }); + Assert.Equal(c, res); + } + + [Fact] + public void IsIn_Test() + { + var target = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000" + ))); + var source = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "1000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000" + ))); + Assert.True(source.IsIn(target)); + + var wrongSource = new Bloom(ByteArrayHelper.HexStringToByteArray(string.Concat( + "1110000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000" + ))); + + Assert.False(wrongSource.IsIn(target)); + + var emptySource = new Bloom(); + Assert.False(emptySource.IsIn(target)); + } + + [Fact] + public async Task AddValue_With_Null_Test() + { + var bloom = new Bloom(); + bloom.AddValue((IMessage)null); + bloom.Data.Length.ShouldBe(0); + } + + #region AElf.Kernel.LogEventExtensions + + [Fact] + public async Task LogEventGetBloom_Test() + { + var logEvent = new LogEvent { - var logEvent = new LogEvent - { - Name = "test1" - }; - var bloom = logEvent.GetBloom(); - bloom.ShouldNotBeNull(); - logEvent = new LogEvent(); - bloom = logEvent.GetBloom(); - bloom.Data.Any(x => x != 0).ShouldBeTrue(); - } - #endregion + Name = "test1" + }; + var bloom = logEvent.GetBloom(); + bloom.ShouldNotBeNull(); + logEvent = new LogEvent(); + bloom = logEvent.GetBloom(); + bloom.Data.Any(x => x != 0).ShouldBeTrue(); } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/ChainHelperTests.cs b/test/AElf.Kernel.Types.Tests/ChainHelperTests.cs index 88dbf8c8b7..aeed066426 100644 --- a/test/AElf.Kernel.Types.Tests/ChainHelperTests.cs +++ b/test/AElf.Kernel.Types.Tests/ChainHelperTests.cs @@ -1,28 +1,27 @@ -using Xunit; -using Shouldly; +using Shouldly; +using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class ChainHelperTests { - public class ChainHelperTests + [Fact] + public void GetChainId_By_SerialNumber_Test() { - [Fact] - public void GetChainId_By_SerialNumber_Test() + // Have tested all the conditions (195112UL ~ 11316496UL), To save time, just do some random test + //var base58HashSet = new HashSet(); + //var intHashSet = new HashSet(); + // for (var i = ; i < 11316496UL; i++) + for (var i = 0; i < 1000; i++) { - // Have tested all the conditions (195112UL ~ 11316496UL), To save time, just do some random test - //var base58HashSet = new HashSet(); - //var intHashSet = new HashSet(); - // for (var i = ; i < 11316496UL; i++) - for (var i = 0; i < 1000; i++) - { - var chainId = 2111; - var base58String = ChainHelper.ConvertChainIdToBase58(chainId); - base58String.Length.ShouldBe(4); - var newChainId = ChainHelper.ConvertBase58ToChainId(base58String); - newChainId.ShouldBe(chainId); - // Uncomment this for go through all conditions - // base58HashSet.Add(base58String).ShouldBe(true); - // intHashSet.Add(newChainId).ShouldBe(true); - } + var chainId = 2111; + var base58String = ChainHelper.ConvertChainIdToBase58(chainId); + base58String.Length.ShouldBe(4); + var newChainId = ChainHelper.ConvertBase58ToChainId(base58String); + newChainId.ShouldBe(chainId); + // Uncomment this for go through all conditions + // base58HashSet.Add(base58String).ShouldBe(true); + // intHashSet.Add(newChainId).ShouldBe(true); } } } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/SerializationTests.cs b/test/AElf.Kernel.Types.Tests/SerializationTests.cs index b1153a41fb..6be8558c16 100644 --- a/test/AElf.Kernel.Types.Tests/SerializationTests.cs +++ b/test/AElf.Kernel.Types.Tests/SerializationTests.cs @@ -1,5 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Diagnostics; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -7,88 +7,83 @@ using Xunit; using Type = System.Type; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class SerializationTest { - public class SerializationTest + [Fact] + public void FromTo_Test() { - [Fact] - public void FromTo_Test() - { - var t = new Transaction(); - t.From = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); - t.To = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); - - byte[] b = t.ToByteArray(); - b.ShouldNotBe(null); - b.Length.ShouldBeGreaterThan(0); - - string bstr = b.ToHex(); - bstr.ShouldNotBe(string.Empty); + var t = new Transaction(); + t.From = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); + t.To = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); - } + var b = t.ToByteArray(); + b.ShouldNotBe(null); + b.Length.ShouldBeGreaterThan(0); + var bstr = b.ToHex(); + bstr.ShouldNotBe(string.Empty); + } - [Fact] - public void Deserialize_Test() - { - var bytes = ByteArrayHelper.HexStringToByteArray( - "0a200a1e9dee15619106b96861d52f03ad30ac7e57aa529eb2f05f7796472d8ce4a112200a1e96d8bf2dccf2ad419d02ed4a7b7a9d77df10617c4d731e766ce8dde63535320a496e697469616c697a653a0a0a015b120122180020005003"); - var txBytes = ByteString.CopyFrom(bytes).ToByteArray(); - var txn = Transaction.Parser.ParseFrom(txBytes); - string str =txn.From.Value.ToByteArray().ToHex(); - } - [Fact] - public void DefaultValue_Test() - { - System.Diagnostics.Debug.WriteLine(default(UInt64Value)); - } + [Fact] + public void Deserialize_Test() + { + var bytes = ByteArrayHelper.HexStringToByteArray( + "0a200a1e9dee15619106b96861d52f03ad30ac7e57aa529eb2f05f7796472d8ce4a112200a1e96d8bf2dccf2ad419d02ed4a7b7a9d77df10617c4d731e766ce8dde63535320a496e697469616c697a653a0a0a015b120122180020005003"); + var txBytes = ByteString.CopyFrom(bytes).ToByteArray(); + var txn = Transaction.Parser.ParseFrom(txBytes); + var str = txn.From.Value.ToByteArray().ToHex(); } - public enum ParamType + [Fact] + public void DefaultValue_Test() { - String, - Boolean, - Single, - Double, - Int16, - Int32, - Int64, - Byte, - Decimal, - UInt16, - UInt32, - UInt64, - Bytes, - Chars + Debug.WriteLine(default(UInt64Value)); } +} - public class SchemaGenerator +public enum ParamType +{ + String, + Boolean, + Single, + Double, + Int16, + Int32, + Int64, + Byte, + Decimal, + UInt16, + UInt32, + UInt64, + Bytes, + Chars +} + +public class SchemaGenerator +{ + private static readonly Dictionary Maps = new() { - private static readonly Dictionary Maps = new Dictionary( - ) - { - {typeof(String), ParamType.String}, - {typeof(Boolean), ParamType.Boolean}, - {typeof(Single), ParamType.Single}, - {typeof(Double), ParamType.Double}, - {typeof(Byte), ParamType.Byte}, - {typeof(Decimal), ParamType.Decimal}, - {typeof(UInt16), ParamType.UInt16}, - {typeof(UInt32), ParamType.UInt32}, - {typeof(UInt64), ParamType.UInt64}, - {typeof(Int16), ParamType.Int16}, - {typeof(Int32), ParamType.Int32}, - {typeof(Int64), ParamType.Int64}, - {typeof(byte[]), ParamType.Bytes}, - {typeof(char[]), ParamType.Chars}, - }; + { typeof(string), ParamType.String }, + { typeof(bool), ParamType.Boolean }, + { typeof(float), ParamType.Single }, + { typeof(double), ParamType.Double }, + { typeof(byte), ParamType.Byte }, + { typeof(decimal), ParamType.Decimal }, + { typeof(ushort), ParamType.UInt16 }, + { typeof(uint), ParamType.UInt32 }, + { typeof(ulong), ParamType.UInt64 }, + { typeof(short), ParamType.Int16 }, + { typeof(int), ParamType.Int32 }, + { typeof(long), ParamType.Int64 }, + { typeof(byte[]), ParamType.Bytes }, + { typeof(char[]), ParamType.Chars } + }; - public static ParamType ToType(Type t) - { - return Maps[t]; - } + public static ParamType ToType(Type t) + { + return Maps[t]; } - - } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/StateValueTests.cs b/test/AElf.Kernel.Types.Tests/StateValueTests.cs index c6862af363..b75c170a21 100644 --- a/test/AElf.Kernel.Types.Tests/StateValueTests.cs +++ b/test/AElf.Kernel.Types.Tests/StateValueTests.cs @@ -1,33 +1,31 @@ -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class StateValueTests { - public class StateValueTests + [Fact] + public void StateValue_Test() { - [Fact] - public void StateValue_Test() - { - var hashArray = HashHelper.ComputeFrom("hash").ToByteArray(); - var stateValue = StateValue.Create(hashArray); - var isDirty = stateValue.IsDirty; - isDirty.ShouldBeFalse(); + var hashArray = HashHelper.ComputeFrom("hash").ToByteArray(); + var stateValue = StateValue.Create(hashArray); + var isDirty = stateValue.IsDirty; + isDirty.ShouldBeFalse(); + + var hashArray1 = stateValue.Get(); + hashArray.ShouldBe(hashArray1); - var hashArray1 = stateValue.Get(); - hashArray.ShouldBe(hashArray1); + var hashArray2 = HashHelper.ComputeFrom("hash1").ToByteArray(); + stateValue.Set(hashArray2); - var hashArray2 = HashHelper.ComputeFrom("hash1").ToByteArray(); - stateValue.Set(hashArray2); + isDirty = stateValue.IsDirty; + isDirty.ShouldBeTrue(); - isDirty = stateValue.IsDirty; - isDirty.ShouldBeTrue(); + var hashArray3 = stateValue.Get(); + hashArray3.ShouldBe(hashArray2); - var hashArray3 = stateValue.Get(); - hashArray3.ShouldBe(hashArray2); - - stateValue.OriginalValue.ShouldBe(hashArray); - stateValue.CurrentValue.ShouldBe(hashArray2); - } + stateValue.OriginalValue.ShouldBe(hashArray); + stateValue.CurrentValue.ShouldBe(hashArray2); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/TimestampHelperTest.cs b/test/AElf.Kernel.Types.Tests/TimestampHelperTest.cs index 110f73adc8..c5ae2c4195 100644 --- a/test/AElf.Kernel.Types.Tests/TimestampHelperTest.cs +++ b/test/AElf.Kernel.Types.Tests/TimestampHelperTest.cs @@ -1,34 +1,35 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class TimestampHelperTest { - public class TimestampHelperTest + [Fact] + public void DurationFromMilliseconds_Test() + { + var result = TimestampHelper.DurationFromMilliseconds(1000); + result.Seconds.ShouldBe(1); + } + + [Fact] + public void DurationFromSeconds_Test() + { + var result = TimestampHelper.DurationFromSeconds(1000); + result.Seconds.ShouldBe(1000); + } + + [Fact] + public void DurationFromMinutes_Test() + { + var result = TimestampHelper.DurationFromMinutes(1); + result.Seconds.ShouldBe(60); + } + + [Fact] + public void GetUtcNow_Test() { - [Fact] - public void DurationFromMilliseconds_Test() - { - var result= TimestampHelper.DurationFromMilliseconds(1000); - result.Seconds.ShouldBe(1); - } - [Fact] - public void DurationFromSeconds_Test() - { - var result= TimestampHelper.DurationFromSeconds(1000); - result.Seconds.ShouldBe(1000); - } - [Fact] - public void DurationFromMinutes_Test() - { - var result= TimestampHelper.DurationFromMinutes(1); - result.Seconds.ShouldBe(60); - } - - [Fact] - public void GetUtcNow_Test() - { - var result= TimestampHelper.GetUtcNow(); - result.ShouldNotBeNull(); - } + var result = TimestampHelper.GetUtcNow(); + result.ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Types.Tests/TransactionTraceTest.cs b/test/AElf.Kernel.Types.Tests/TransactionTraceTest.cs index f6d4c3be8f..27cdb55b81 100644 --- a/test/AElf.Kernel.Types.Tests/TransactionTraceTest.cs +++ b/test/AElf.Kernel.Types.Tests/TransactionTraceTest.cs @@ -4,59 +4,62 @@ using Shouldly; using Xunit; -namespace AElf.Kernel.Types.Tests +namespace AElf.Kernel.Types.Tests; + +public class TransactionTraceTest { - public class TransactionTraceTest + [Fact] + public void TransactionTrace_Statistics_Test() { - [Fact] - public void TransactionTrace_Statistics_Test() - { - const int currentCount = 1; - var currentTransactionTrace = GetTransactionTraceWithSameCount(currentCount); + const int currentCount = 1; + var currentTransactionTrace = GetTransactionTraceWithSameCount(currentCount); - const int preTraceCount = 2; - var preTransactionTrace = GetTransactionTraceWithSameCount(preTraceCount); - const int prePreTraceCount = 1; - var prePreTransactionTrace = GetTransactionTraceWithSameCount(prePreTraceCount); - preTransactionTrace.PreTraces.Add(prePreTransactionTrace); - currentTransactionTrace.PreTraces.Add(preTransactionTrace); - - const int inLineTraceCount = 2; - var inLineTransactionTrace = GetTransactionTraceWithSameCount(inLineTraceCount); - const int inlineInlinePreTraceCount = 1; - var inlineInlineTransactionTrace = GetTransactionTraceWithSameCount(inlineInlinePreTraceCount); - inLineTransactionTrace.InlineTraces.Add(inlineInlineTransactionTrace); - currentTransactionTrace.InlineTraces.Add(inLineTransactionTrace); - - const int postTraceCount = 2; - var postTransactionTrace = GetTransactionTraceWithSameCount(postTraceCount); - const int postPostTraceCount = 1; - var postPostTransactionTrace = GetTransactionTraceWithSameCount(postPostTraceCount); - postPostTransactionTrace.PostTraces.Add(postTransactionTrace); - currentTransactionTrace.PostTraces.Add(postPostTransactionTrace); - currentTransactionTrace.FlattenedLogs.Count().ShouldBe(10); - currentTransactionTrace.GetFlattenedReads().Count().ShouldBe(10); - currentTransactionTrace.GetFlattenedWrites().Count().ShouldBe(10); - currentTransactionTrace.GetStateSets().Count().ShouldBe(7); - } + const int preTraceCount = 2; + var preTransactionTrace = GetTransactionTraceWithSameCount(preTraceCount); + const int prePreTraceCount = 1; + var prePreTransactionTrace = GetTransactionTraceWithSameCount(prePreTraceCount); + preTransactionTrace.PreTraces.Add(prePreTransactionTrace); + currentTransactionTrace.PreTraces.Add(preTransactionTrace); - private TransactionTrace GetTransactionTraceWithSameCount(int count) - { - return GetTransactionTrace(count, count, count, count); - } + const int inLineTraceCount = 2; + var inLineTransactionTrace = GetTransactionTraceWithSameCount(inLineTraceCount); + const int inlineInlinePreTraceCount = 1; + var inlineInlineTransactionTrace = GetTransactionTraceWithSameCount(inlineInlinePreTraceCount); + inLineTransactionTrace.InlineTraces.Add(inlineInlineTransactionTrace); + currentTransactionTrace.InlineTraces.Add(inLineTransactionTrace); + + const int postTraceCount = 2; + var postTransactionTrace = GetTransactionTraceWithSameCount(postTraceCount); + const int postPostTraceCount = 1; + var postPostTransactionTrace = GetTransactionTraceWithSameCount(postPostTraceCount); + postPostTransactionTrace.PostTraces.Add(postTransactionTrace); + currentTransactionTrace.PostTraces.Add(postPostTransactionTrace); + currentTransactionTrace.FlattenedLogs.Count().ShouldBe(10); + currentTransactionTrace.GetFlattenedReads().Count().ShouldBe(10); + currentTransactionTrace.GetFlattenedWrites().Count().ShouldBe(10); + currentTransactionTrace.GetStateSets().Count().ShouldBe(7); + } - private TransactionTrace GetTransactionTrace(int logEventCount = 0, int readsCount = 0, int writesCount = 0, int deletesCount = 0) + private TransactionTrace GetTransactionTraceWithSameCount(int count) + { + return GetTransactionTrace(count, count, count, count); + } + + private TransactionTrace GetTransactionTrace(int logEventCount = 0, int readsCount = 0, int writesCount = 0, + int deletesCount = 0) + { + var transactionTrace = new TransactionTrace { - var transactionTrace = new TransactionTrace - { - StateSet = new TransactionExecutingStateSet() - }; - var writeByteString = transactionTrace.ToByteString(); - transactionTrace.Logs.AddRange(Enumerable.Range(0, logEventCount).Select(x => new LogEvent()).ToArray()); - transactionTrace.StateSet.Reads.Add(Enumerable.Range(0, readsCount).ToDictionary(key=> key.ToString(), value => true)); - transactionTrace.StateSet.Writes.Add(Enumerable.Range(0, writesCount).ToDictionary(key=> key.ToString(), value => writeByteString)); - transactionTrace.StateSet.Deletes.Add(Enumerable.Range(0, deletesCount).ToDictionary(key=> key.ToString(), value => true)); - return transactionTrace; - } + StateSet = new TransactionExecutingStateSet() + }; + var writeByteString = transactionTrace.ToByteString(); + transactionTrace.Logs.AddRange(Enumerable.Range(0, logEventCount).Select(x => new LogEvent()).ToArray()); + transactionTrace.StateSet.Reads.Add(Enumerable.Range(0, readsCount) + .ToDictionary(key => key.ToString(), value => true)); + transactionTrace.StateSet.Writes.Add(Enumerable.Range(0, writesCount) + .ToDictionary(key => key.ToString(), value => writeByteString)); + transactionTrace.StateSet.Deletes.Add(Enumerable.Range(0, deletesCount) + .ToDictionary(key => key.ToString(), value => true)); + return transactionTrace; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/AElf.OS.Core.Tests.csproj b/test/AElf.OS.Core.Tests/AElf.OS.Core.Tests.csproj index 7814cf0c04..ae9352bf5f 100644 --- a/test/AElf.OS.Core.Tests/AElf.OS.Core.Tests.csproj +++ b/test/AElf.OS.Core.Tests/AElf.OS.Core.Tests.csproj @@ -5,17 +5,17 @@ false - - + + - - - - - - + + + + + + - + diff --git a/test/AElf.OS.Core.Tests/Application/NodeEnvironmentServiceTests.cs b/test/AElf.OS.Core.Tests/Application/NodeEnvironmentServiceTests.cs index d89030ded4..e5af6f6c9f 100644 --- a/test/AElf.OS.Core.Tests/Application/NodeEnvironmentServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Application/NodeEnvironmentServiceTests.cs @@ -3,22 +3,22 @@ using Shouldly; using Xunit; -namespace AElf.OS.Application +namespace AElf.OS.Application; + +public class NodeEnvironmentServiceTests : AElfIntegratedTest { - public class NodeEnvironmentServiceTests : AElfIntegratedTest + private readonly INodeEnvironmentService _nodeEnvironmentService; + + public NodeEnvironmentServiceTests() + { + _nodeEnvironmentService = GetRequiredService(); + } + + [Fact] + public void GetAppDataPath_Test() { - private readonly INodeEnvironmentService _nodeEnvironmentService; - public NodeEnvironmentServiceTests() - { - _nodeEnvironmentService = GetRequiredService(); - } - - [Fact] - public void GetAppDataPath_Test() - { - var path = _nodeEnvironmentService.GetAppDataPath(); - path.ShouldNotBeNull(); - path.ShouldContain("aelf"); - } + var path = _nodeEnvironmentService.GetAppDataPath(); + path.ShouldNotBeNull(); + path.ShouldContain("aelf"); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Helpers/OsCoreTestHelper.cs b/test/AElf.OS.Core.Tests/Helpers/OsCoreTestHelper.cs index 8e0c7d8259..e3383ccfe0 100644 --- a/test/AElf.OS.Core.Tests/Helpers/OsCoreTestHelper.cs +++ b/test/AElf.OS.Core.Tests/Helpers/OsCoreTestHelper.cs @@ -4,39 +4,38 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.OS.Helpers +namespace AElf.OS.Helpers; + +public static class OsCoreTestHelper { - public static class OsCoreTestHelper + public static BlockHeader CreateFakeBlockHeader(int chainId, long height, ECKeyPair producer = null) { - public static BlockHeader CreateFakeBlockHeader(int chainId, long height, ECKeyPair producer = null) + var signer = producer ?? CryptoHelper.GenerateKeyPair(); + + return new BlockHeader { - var signer = producer ?? CryptoHelper.GenerateKeyPair(); + ChainId = chainId, + Height = height, + PreviousBlockHash = HashHelper.ComputeFrom(new byte[] { 1, 2, 3 }), + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfTransactions = Hash.Empty, + MerkleTreeRootOfWorldState = Hash.Empty, + MerkleTreeRootOfTransactionStatus = Hash.Empty, + SignerPubkey = ByteString.CopyFrom(signer.PublicKey) + }; + } - return new BlockHeader - { - ChainId = chainId, - Height = height, - PreviousBlockHash = HashHelper.ComputeFrom(new byte[] {1, 2, 3} ), - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfTransactions = Hash.Empty, - MerkleTreeRootOfWorldState = Hash.Empty, - MerkleTreeRootOfTransactionStatus = Hash.Empty, - SignerPubkey = ByteString.CopyFrom(signer.PublicKey) - }; - } + public static Transaction CreateFakeTransaction() + { + var fromKeyPair = CryptoHelper.GenerateKeyPair(); + var toKeyPair = CryptoHelper.GenerateKeyPair(); - public static Transaction CreateFakeTransaction() + return new Transaction { - var fromKeyPair = CryptoHelper.GenerateKeyPair(); - var toKeyPair = CryptoHelper.GenerateKeyPair(); - - return new Transaction - { - From = Address.FromPublicKey(fromKeyPair.PublicKey), - To = Address.FromPublicKey(toKeyPair.PublicKey), - MethodName = "SomeMethod", - RefBlockNumber = 2 - }; - } + From = Address.FromPublicKey(fromKeyPair.PublicKey), + To = Address.FromPublicKey(toKeyPair.PublicKey), + MethodName = "SomeMethod", + RefBlockNumber = 2 + }; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/NetworkServicePropagationTest.cs b/test/AElf.OS.Core.Tests/Network/Application/NetworkServicePropagationTest.cs index 03694cb18f..e6a9e82b90 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/NetworkServicePropagationTest.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/NetworkServicePropagationTest.cs @@ -1,391 +1,395 @@ using System; -using System.Linq; using System.Threading.Tasks; using AElf.Kernel; using AElf.OS.Helpers; -using AElf.OS.Network.Application; using AElf.OS.Network.Infrastructure; using AElf.Types; using Moq; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class NetworkServicePropagationTest : NetworkServicePropagationTestBase { - public class NetworkServicePropagationTest : NetworkServicePropagationTestBase + private readonly INetworkService _networkService; + private readonly IPeerPool _peerPool; + private readonly NetworkServicePropagationTestContext _testContext; + + public NetworkServicePropagationTest() { - private readonly NetworkServicePropagationTestContext _testContext; - private readonly INetworkService _networkService; - private readonly IPeerPool _peerPool; + _testContext = GetRequiredService(); + _networkService = GetRequiredService(); + _peerPool = GetRequiredService(); + } - public NetworkServicePropagationTest() - { - _testContext = GetRequiredService(); - _networkService = GetRequiredService(); - _peerPool = GetRequiredService(); - } - - [Fact] - public async Task BroadcastBlock_OldBlock_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - blockHeader.Time = TimestampHelper.GetUtcNow() - - TimestampHelper.DurationFromMinutes( - NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes + 1); - var blockWithTx = new BlockWithTransactions { Header = blockHeader }; - - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Never); - } + [Fact] + public async Task BroadcastBlock_OldBlock_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + blockHeader.Time = TimestampHelper.GetUtcNow() - + TimestampHelper.DurationFromMinutes( + NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes + 1); + var blockWithTx = new BlockWithTransactions { Header = blockHeader }; - [Fact] - public async Task BroadcastBlock_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - var blockWithTx = new BlockWithTransactions { Header = blockHeader }; - - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); - } + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - [Fact] - public async Task BroadcastBlock_ThrowNetworkException_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException())); - _testContext.MockedPeers[1] - .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); - _testContext.MockedPeers[2] - .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); - - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - var blockWithTx = new BlockWithTransactions {Header = blockHeader}; - - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - - foreach (var peer in _testContext.MockedPeers) - { - peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - } - - _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), - Times.Once()); - } + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - [Fact] - public async Task BroadcastBlock_PeerNotReady_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) - .Throws(); + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Never); + } - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - var blockWithTx = new BlockWithTransactions {Header = blockHeader}; + [Fact] + public async Task BroadcastBlock_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + var blockWithTx = new BlockWithTransactions { Header = blockHeader }; - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - _testContext.MockedPeers[0].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - _testContext.MockedPeers[1].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - _testContext.MockedPeers[2].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - } + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - [Fact] - public async Task BroadcastAnnouncement_OldBlock_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - blockHeader.Time = TimestampHelper.GetUtcNow() - - TimestampHelper.DurationFromMinutes( - NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes + 1); - - await _networkService.BroadcastAnnounceAsync(blockHeader); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueAnnouncement(It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Never); - } - - [Fact] - public async Task BroadcastAnnouncement_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - - await _networkService.BroadcastAnnounceAsync(blockHeader); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueAnnouncement(It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Once()); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - - await _networkService.BroadcastAnnounceAsync(blockHeader); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueAnnouncement(It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Once()); - } - - [Fact] - public async Task BroadcastAnnouncement_ThrowNetworkException_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException())); - _testContext.MockedPeers[1] - .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); - _testContext.MockedPeers[2] - .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); - - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - - await _networkService.BroadcastAnnounceAsync(blockHeader); - - foreach (var peer in _testContext.MockedPeers) - { - peer.Verify(p => p.EnqueueAnnouncement(It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Once()); - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - - } - - _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), - Times.Once()); - } + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - [Fact] - public async Task BroadcastAnnouncement_PeerNotReady_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) - .Throws(); - - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(chainId: 1, height: 2); - - await _networkService.BroadcastAnnounceAsync(blockHeader); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueAnnouncement(It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Once()); - - _testContext.MockedPeers[0].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - _testContext.MockedPeers[1].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - _testContext.MockedPeers[2].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - } + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); + } - [Fact] - public async Task BroadcastTransaction_Test() - { - var transaction = OsCoreTestHelper.CreateFakeTransaction(); - - await _networkService.BroadcastTransactionAsync(transaction); - - foreach (var peer in _testContext.MockedPeers) - peer.Object.TryAddKnownTransaction(transaction.GetHash()); - - await _networkService.BroadcastTransactionAsync(transaction); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), - It.IsAny>()), Times.Once()); - } - - [Fact] - public async Task BroadcastTransaction_ThrowNetworkException_Test() + [Fact] + public async Task BroadcastBlock_ThrowNetworkException_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException())); + _testContext.MockedPeers[1] + .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); + _testContext.MockedPeers[2] + .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); + + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + var blockWithTx = new BlockWithTransactions { Header = blockHeader }; + + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); + + foreach (var peer in _testContext.MockedPeers) { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException())); - _testContext.MockedPeers[1] - .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); - _testContext.MockedPeers[2] - .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); - - var transaction = OsCoreTestHelper.CreateFakeTransaction(); - - await _networkService.BroadcastTransactionAsync(transaction); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), - It.IsAny>()), Times.Once()); - - _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), - Times.Once()); + peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); } - - [Fact] - public async Task BroadcastTransaction_PeerNotReady_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) - .Throws(); - var transaction = OsCoreTestHelper.CreateFakeTransaction(); - - await _networkService.BroadcastTransactionAsync(transaction); + _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), + Times.Once()); + } - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), - It.IsAny>()), Times.Once()); - } + [Fact] + public async Task BroadcastBlock_PeerNotReady_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) + .Throws(); - [Fact] - public async Task BroadcastLibAnnouncement_Test() - { - var libHash = HashHelper.ComputeFrom("LibHash"); - var libHeight = 2; + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + var blockWithTx = new BlockWithTransactions { Header = blockHeader }; - await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTx); - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueLibAnnouncement( - It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), - It.IsAny>()), Times.Once()); - } - - [Fact] - public async Task BroadcastLibAnnouncement_ThrowNetworkException_Test() - { - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException())); - _testContext.MockedPeers[1] - .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); - _testContext.MockedPeers[2] - .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => - action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); - - var libHash = HashHelper.ComputeFrom("LibHash"); - var libHeight = 2; - - await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueLibAnnouncement( - It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), - It.IsAny>()), Times.Once()); - - _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), - Times.Once()); - } - - [Fact] - public async Task BroadcastLibAnnouncement_PeerNotReady_Test() - { - var libHash = HashHelper.ComputeFrom("LibHash"); - var libHeight = 2; - - _testContext.MockedPeers[0] - .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) - .Throws(); - - await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); - - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.EnqueueLibAnnouncement( - It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), - It.IsAny>()), Times.Once()); - } + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueBlock(blockWithTx, It.IsAny>()), Times.Once()); - [Fact] - public async Task BroadcastBlock_OnePeerKnowsBlock_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); - var blockWithTransactions = new BlockWithTransactions {Header = blockHeader}; + _testContext.MockedPeers[0].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); + _testContext.MockedPeers[1].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + _testContext.MockedPeers[2].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + } - _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockWithTransactions.GetHash()); + [Fact] + public async Task BroadcastAnnouncement_OldBlock_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + blockHeader.Time = TimestampHelper.GetUtcNow() - + TimestampHelper.DurationFromMinutes( + NetworkConstants.DefaultMaxBlockAgeToBroadcastInMinutes + 1); - await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions); + await _networkService.BroadcastAnnounceAsync(blockHeader); - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); - _testContext.MockedPeers[0].Verify( - p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), - Times.Never); - _testContext.MockedPeers[1].Verify( - p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), - Times.Once()); - _testContext.MockedPeers[2].Verify( - p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), - Times.Once()); - } + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Never); + } - [Fact] - public async Task BroadcastAnnouncement_OnePeerKnowsBlock_Test() - { - var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + [Fact] + public async Task BroadcastAnnouncement_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); - _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockHeader.GetHash()); + await _networkService.BroadcastAnnounceAsync(blockHeader); - await _networkService.BroadcastAnnounceAsync(blockHeader); + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Once()); - foreach (var peer in _testContext.MockedPeers) - peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); - _testContext.MockedPeers[0].Verify(p => p.EnqueueAnnouncement( - It.Is(ba => ba.BlockHash == blockHeader.GetHash()), - It.IsAny>()), Times.Never); - _testContext.MockedPeers[1].Verify(p => p.EnqueueAnnouncement( + await _networkService.BroadcastAnnounceAsync(blockHeader); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueAnnouncement( It.Is(ba => ba.BlockHash == blockHeader.GetHash()), It.IsAny>()), Times.Once()); - _testContext.MockedPeers[2].Verify(p => p.EnqueueAnnouncement( + } + + [Fact] + public async Task BroadcastAnnouncement_ThrowNetworkException_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException())); + _testContext.MockedPeers[1] + .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); + _testContext.MockedPeers[2] + .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); + + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + + await _networkService.BroadcastAnnounceAsync(blockHeader); + + foreach (var peer in _testContext.MockedPeers) + { + peer.Verify(p => p.EnqueueAnnouncement( It.Is(ba => ba.BlockHash == blockHeader.GetHash()), It.IsAny>()), Times.Once()); + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); } - [Fact] - public async Task BroadcastTransaction_OnePeerKnowsTransaction_Test() - { - var transaction = OsCoreTestHelper.CreateFakeTransaction(); + _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), + Times.Once()); + } - _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownTransaction(transaction.GetHash()); - - await _networkService.BroadcastTransactionAsync(transaction); + [Fact] + public async Task BroadcastAnnouncement_PeerNotReady_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) + .Throws(); - _testContext.MockedPeers[0].Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), - It.IsAny>()), Times.Never); - _testContext.MockedPeers[1].Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + + await _networkService.BroadcastAnnounceAsync(blockHeader); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Once()); + + _testContext.MockedPeers[0].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Never); + _testContext.MockedPeers[1].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + _testContext.MockedPeers[2].Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + } + + [Fact] + public async Task BroadcastTransaction_Test() + { + var transaction = OsCoreTestHelper.CreateFakeTransaction(); + + await _networkService.BroadcastTransactionAsync(transaction); + + foreach (var peer in _testContext.MockedPeers) + peer.Object.TryAddKnownTransaction(transaction.GetHash()); + + await _networkService.BroadcastTransactionAsync(transaction); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), It.IsAny>()), Times.Once()); - _testContext.MockedPeers[2].Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), + } + + [Fact] + public async Task BroadcastTransaction_ThrowNetworkException_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException())); + _testContext.MockedPeers[1] + .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); + _testContext.MockedPeers[2] + .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); + + var transaction = OsCoreTestHelper.CreateFakeTransaction(); + + await _networkService.BroadcastTransactionAsync(transaction); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), It.IsAny>()), Times.Once()); - } + + _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), + Times.Once()); + } + + [Fact] + public async Task BroadcastTransaction_PeerNotReady_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) + .Throws(); + + var transaction = OsCoreTestHelper.CreateFakeTransaction(); + + await _networkService.BroadcastTransactionAsync(transaction); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueTransaction(It.Is(tx => tx.GetHash() == transaction.GetHash()), + It.IsAny>()), Times.Once()); + } + + [Fact] + public async Task BroadcastLibAnnouncement_Test() + { + var libHash = HashHelper.ComputeFrom("LibHash"); + var libHeight = 2; + + await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueLibAnnouncement( + It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), + It.IsAny>()), Times.Once()); + } + + [Fact] + public async Task BroadcastLibAnnouncement_ThrowNetworkException_Test() + { + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException())); + _testContext.MockedPeers[1] + .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("Unrecoverable", NetworkExceptionType.Unrecoverable))); + _testContext.MockedPeers[2] + .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => + action.Invoke(new NetworkException("PeerUnstable", NetworkExceptionType.PeerUnstable))); + + var libHash = HashHelper.ComputeFrom("LibHash"); + var libHeight = 2; + + await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueLibAnnouncement( + It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), + It.IsAny>()), Times.Once()); + + _testContext.MockAElfNetworkServer.Verify(s => s.TrySchedulePeerReconnectionAsync(It.IsAny()), + Times.Once()); + } + + [Fact] + public async Task BroadcastLibAnnouncement_PeerNotReady_Test() + { + var libHash = HashHelper.ComputeFrom("LibHash"); + var libHeight = 2; + + _testContext.MockedPeers[0] + .Setup(p => p.EnqueueLibAnnouncement(It.IsAny(), It.IsAny>())) + .Throws(); + + await _networkService.BroadcastLibAnnounceAsync(libHash, libHeight); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.EnqueueLibAnnouncement( + It.Is(a => a.LibHash == libHash && a.LibHeight == libHeight), + It.IsAny>()), Times.Once()); + } + + [Fact] + public async Task BroadcastBlock_OnePeerKnowsBlock_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + var blockWithTransactions = new BlockWithTransactions { Header = blockHeader }; + + _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockWithTransactions.GetHash()); + + await _networkService.BroadcastBlockWithTransactionsAsync(blockWithTransactions); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + + _testContext.MockedPeers[0].Verify( + p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), + Times.Never); + _testContext.MockedPeers[1].Verify( + p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), + Times.Once()); + _testContext.MockedPeers[2].Verify( + p => p.EnqueueBlock(blockWithTransactions, It.IsAny>()), + Times.Once()); + } + + [Fact] + public async Task BroadcastAnnouncement_OnePeerKnowsBlock_Test() + { + var blockHeader = OsCoreTestHelper.CreateFakeBlockHeader(1, 2); + + _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownBlock(blockHeader.GetHash()); + + await _networkService.BroadcastAnnounceAsync(blockHeader); + + foreach (var peer in _testContext.MockedPeers) + peer.Verify(p => p.TryAddKnownBlock(blockHeader.GetHash()), Times.Once()); + + _testContext.MockedPeers[0].Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Never); + _testContext.MockedPeers[1].Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Once()); + _testContext.MockedPeers[2].Verify(p => p.EnqueueAnnouncement( + It.Is(ba => ba.BlockHash == blockHeader.GetHash()), + It.IsAny>()), Times.Once()); + } + + [Fact] + public async Task BroadcastTransaction_OnePeerKnowsTransaction_Test() + { + var transaction = OsCoreTestHelper.CreateFakeTransaction(); + + _peerPool.FindPeerByPublicKey("Pubkey0").TryAddKnownTransaction(transaction.GetHash()); + + await _networkService.BroadcastTransactionAsync(transaction); + + _testContext.MockedPeers[0].Verify(p => p.EnqueueTransaction( + It.Is(tx => tx.GetHash() == transaction.GetHash()), + It.IsAny>()), Times.Never); + _testContext.MockedPeers[1].Verify(p => p.EnqueueTransaction( + It.Is(tx => tx.GetHash() == transaction.GetHash()), + It.IsAny>()), Times.Once()); + _testContext.MockedPeers[2].Verify(p => p.EnqueueTransaction( + It.Is(tx => tx.GetHash() == transaction.GetHash()), + It.IsAny>()), Times.Once()); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/NetworkServiceTests.cs b/test/AElf.OS.Core.Tests/Network/Application/NetworkServiceTests.cs index f02135e43b..7e7282342f 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/NetworkServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/NetworkServiceTests.cs @@ -1,229 +1,227 @@ using System; -using System.Linq; using System.Threading.Tasks; +using AElf.Cryptography; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class NetworkServiceTests : OSCoreNetworkServiceTestBase { - public class NetworkServiceTests : OSCoreNetworkServiceTestBase - { - private IBlockchainService _blockchainService; - private readonly INetworkService _networkService; - private readonly IPeerPool _peerPool; - private readonly IBlackListedPeerProvider _blackListProvider; - - private readonly KernelTestHelper _kernelTestHelper; - - public NetworkServiceTests() - { - _blockchainService = GetRequiredService(); - _networkService = GetRequiredService(); - _peerPool = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - _blackListProvider = GetRequiredService(); - } - - [Fact] - public async Task AddPeer_Test() - { - var endpoint = "127.0.0.1:5000"; - var result = await _networkService.AddPeerAsync(endpoint); - result.ShouldBeTrue(); - } - - [Fact] - public async Task AddInvalidPeer_Test() - { - var endpoint = "ipv6:192.168.197.54"; - var result = await _networkService.AddPeerAsync(endpoint); - result.ShouldBeFalse(); - - } - [Fact] - public async Task AddPeer_DotNotRemoveBlackList_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:5000", out var endpoint); - var host = endpoint.Host; - - _blackListProvider.AddHostToBlackList(host, NetworkConstants.DefaultPeerRemovalSeconds); - - await _networkService.AddPeerAsync(endpoint.ToString()); - - _blackListProvider.IsIpBlackListed(host).ShouldBeTrue(); - } - - [Fact] - public async Task AddTrustedPeer_Test() - { - var endpoint = "127.0.0.1:5000"; - AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint); - var host = aelfPeerEndpoint.Host; - - _blackListProvider.AddHostToBlackList(host, 5000); - - await _networkService.AddTrustedPeerAsync(endpoint); - - _blackListProvider.IsIpBlackListed(host).ShouldBeFalse(); - } - - [Fact] - public async Task AddTrustedInvalidPeer_Test() - { - var endpoint = "ipv6:192.168.197.54"; - var result = await _networkService.AddTrustedPeerAsync(endpoint); - - result.ShouldBeFalse(); - } - - [Fact] - public async Task RemovePeerByPubkey_Test() - { - AElfPeerEndpointHelper.TryParse("192.168.100.200:5000", out var endpoint); - var host = endpoint.Host; - - //invalid pubkey - var result = await _networkService.RemovePeerByPubkeyAsync("InvalidPubkey"); - result.ShouldBeFalse(); - - result = await _networkService.RemovePeerByPubkeyAsync("NormalPeer"); - result.ShouldBeTrue(); - _blackListProvider.IsIpBlackListed("192.168.100.200").ShouldBeTrue(); - } - - [Fact] - public async Task RemovePeerByEndpoint_Test() - { - var endpointString = "192.168.100.200:5000"; - AElfPeerEndpointHelper.TryParse(endpointString, out var endpoint); - var host = endpoint.Host; - - //invalid address - var result = await _networkService.RemovePeerByEndpointAsync(""); - result.ShouldBeFalse(); - - result = await _networkService.RemovePeerByEndpointAsync(endpointString); - result.ShouldBeTrue(); - _blackListProvider.IsIpBlackListed(host).ShouldBeTrue(); - } - - #region GetBlocks - - [Fact] - public async Task GetBlocks_FromNullPeerOrUnfindable_ThrowsException() - { - var exceptionNullPeer = await Assert.ThrowsAsync(async () => - await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("bHash1"), 1, null)); - - exceptionNullPeer.Message.ShouldBe("Could not find peer ."); - - string peerName = "peer_name"; - var exception = await Assert.ThrowsAsync(async () => - await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("bHash1"), 1, peerName)); - - exception.Message.ShouldBe($"Could not find peer {peerName}."); - } - - [Fact] - public async Task GetBlocks_NetworkException_ReturnsNonSuccessfulResponse() - { - var response = await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("block_hash"), 1, "FailedPeer"); - response.Success.ShouldBeFalse(); - response.Payload.ShouldBeNull(); - } - - #endregion GetBlocks - - #region GetBlockByHash - - [Fact] - public async Task GetBlockByHash_UnfindablePeer_ThrowsExceptionNull() - { - var exceptionNullPeer = await Assert.ThrowsAsync(async () => - await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"), null)); - - exceptionNullPeer.Message.ShouldBe("Could not find peer ."); - - string peerName = "peer_name"; - var exception = await Assert.ThrowsAsync(async () => - await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"), peerName)); - - exception.Message.ShouldBe($"Could not find peer {peerName}."); - } - - [Fact] - public async Task GetBlockByHash_FromSpecifiedPeer_ReturnsBlocks() - { - var block = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"), "NormalPeer"); - Assert.NotNull(block); - } - - #endregion GetBlockByHash - - #region GetPeers - - [Fact] - public void GetPeers_ShouldNotIncludeFailing() - { - Assert.Equal(_networkService.GetPeers(false).Count, _peerPool.GetPeers().Count); - } - - [Fact] - public void GetPeers_ShouldIncludeFailing() - { - Assert.Equal(_networkService.GetPeers().Count, _peerPool.GetPeers(true).Count); - } - - [Fact] - public void GetPeersByPubKey() - { - var pubkey = "NormalPeer"; - var peerInfo = _networkService.GetPeerByPubkey(pubkey); - peerInfo.ShouldNotBeNull(); - - var peer = _peerPool.FindPeerByPublicKey(pubkey); - peerInfo.IpAddress.ShouldBe(peer.RemoteEndpoint.ToString()); - peerInfo.Pubkey.ShouldBe(peer.Info.Pubkey); - peerInfo.LastKnownLibHeight.ShouldBe(peer.LastKnownLibHeight); - peerInfo.ProtocolVersion.ShouldBe(peer.Info.ProtocolVersion); - peerInfo.ConnectionTime.ShouldBe(peer.Info.ConnectionTime.Seconds); - peerInfo.ConnectionStatus.ShouldBe(peer.ConnectionStatus); - peerInfo.Inbound.ShouldBe(peer.Info.IsInbound); - peerInfo.SyncState.ShouldBe(peer.SyncState); - peerInfo.BufferedAnnouncementsCount.ShouldBe(peer.BufferedAnnouncementsCount); - peerInfo.BufferedBlocksCount.ShouldBe(peer.BufferedBlocksCount); - peerInfo.BufferedTransactionsCount.ShouldBe(peer.BufferedTransactionsCount); - - var fakePubkey = Cryptography.CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); - peerInfo = _networkService.GetPeerByPubkey(fakePubkey); - peerInfo.ShouldBeNull(); - } - - [Fact] - public void IsPeerPoolFull_Test() - { - var peerPoolIsFull = _peerPool.IsFull(); - _networkService.IsPeerPoolFull().ShouldBe(peerPoolIsFull); - } - - #endregion GetPeers - - [Fact] - public async Task CheckPeersHealth_Test() - { - var failedPeerPubkey = "FailedPeer"; - var peer = _peerPool.FindPeerByPublicKey(failedPeerPubkey); - peer.ShouldNotBeNull(); - - await _networkService.CheckPeersHealthAsync(); - - peer = _peerPool.FindPeerByPublicKey(failedPeerPubkey); - peer.ShouldBeNull(); - } + private readonly IBlackListedPeerProvider _blackListProvider; + + private readonly KernelTestHelper _kernelTestHelper; + private readonly INetworkService _networkService; + private readonly IPeerPool _peerPool; + private IBlockchainService _blockchainService; + + public NetworkServiceTests() + { + _blockchainService = GetRequiredService(); + _networkService = GetRequiredService(); + _peerPool = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + _blackListProvider = GetRequiredService(); + } + + [Fact] + public async Task AddPeer_Test() + { + var endpoint = "127.0.0.1:5000"; + var result = await _networkService.AddPeerAsync(endpoint); + result.ShouldBeTrue(); + } + + [Fact] + public async Task AddInvalidPeer_Test() + { + var endpoint = "ipv6:192.168.197.54"; + var result = await _networkService.AddPeerAsync(endpoint); + result.ShouldBeFalse(); } + + [Fact] + public async Task AddPeer_DotNotRemoveBlackList_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:5000", out var endpoint); + var host = endpoint.Host; + + _blackListProvider.AddHostToBlackList(host, NetworkConstants.DefaultPeerRemovalSeconds); + + await _networkService.AddPeerAsync(endpoint.ToString()); + + _blackListProvider.IsIpBlackListed(host).ShouldBeTrue(); + } + + [Fact] + public async Task AddTrustedPeer_Test() + { + var endpoint = "127.0.0.1:5000"; + AElfPeerEndpointHelper.TryParse(endpoint, out var aelfPeerEndpoint); + var host = aelfPeerEndpoint.Host; + + _blackListProvider.AddHostToBlackList(host, 5000); + + await _networkService.AddTrustedPeerAsync(endpoint); + + _blackListProvider.IsIpBlackListed(host).ShouldBeFalse(); + } + + [Fact] + public async Task AddTrustedInvalidPeer_Test() + { + var endpoint = "ipv6:192.168.197.54"; + var result = await _networkService.AddTrustedPeerAsync(endpoint); + + result.ShouldBeFalse(); + } + + [Fact] + public async Task RemovePeerByPubkey_Test() + { + AElfPeerEndpointHelper.TryParse("192.168.100.200:5000", out var endpoint); + var host = endpoint.Host; + + //invalid pubkey + var result = await _networkService.RemovePeerByPubkeyAsync("InvalidPubkey"); + result.ShouldBeFalse(); + + result = await _networkService.RemovePeerByPubkeyAsync("NormalPeer"); + result.ShouldBeTrue(); + _blackListProvider.IsIpBlackListed("192.168.100.200").ShouldBeTrue(); + } + + [Fact] + public async Task RemovePeerByEndpoint_Test() + { + var endpointString = "192.168.100.200:5000"; + AElfPeerEndpointHelper.TryParse(endpointString, out var endpoint); + var host = endpoint.Host; + + //invalid address + var result = await _networkService.RemovePeerByEndpointAsync(""); + result.ShouldBeFalse(); + + result = await _networkService.RemovePeerByEndpointAsync(endpointString); + result.ShouldBeTrue(); + _blackListProvider.IsIpBlackListed(host).ShouldBeTrue(); + } + + [Fact] + public async Task CheckPeersHealth_Test() + { + var failedPeerPubkey = "FailedPeer"; + var peer = _peerPool.FindPeerByPublicKey(failedPeerPubkey); + peer.ShouldNotBeNull(); + + await _networkService.CheckPeersHealthAsync(); + + peer = _peerPool.FindPeerByPublicKey(failedPeerPubkey); + peer.ShouldBeNull(); + } + + #region GetBlocks + + [Fact] + public async Task GetBlocks_FromNullPeerOrUnfindable_ThrowsException() + { + var exceptionNullPeer = await Assert.ThrowsAsync(async () => + await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("bHash1"), 1)); + + exceptionNullPeer.Message.ShouldBe("Could not find peer ."); + + var peerName = "peer_name"; + var exception = await Assert.ThrowsAsync(async () => + await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("bHash1"), 1, peerName)); + + exception.Message.ShouldBe($"Could not find peer {peerName}."); + } + + [Fact] + public async Task GetBlocks_NetworkException_ReturnsNonSuccessfulResponse() + { + var response = await _networkService.GetBlocksAsync(HashHelper.ComputeFrom("block_hash"), 1, "FailedPeer"); + response.Success.ShouldBeFalse(); + response.Payload.ShouldBeNull(); + } + + #endregion GetBlocks + + #region GetBlockByHash + + [Fact] + public async Task GetBlockByHash_UnfindablePeer_ThrowsExceptionNull() + { + var exceptionNullPeer = await Assert.ThrowsAsync(async () => + await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"))); + + exceptionNullPeer.Message.ShouldBe("Could not find peer ."); + + var peerName = "peer_name"; + var exception = await Assert.ThrowsAsync(async () => + await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"), peerName)); + + exception.Message.ShouldBe($"Could not find peer {peerName}."); + } + + [Fact] + public async Task GetBlockByHash_FromSpecifiedPeer_ReturnsBlocks() + { + var block = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("bHash1"), "NormalPeer"); + Assert.NotNull(block); + } + + #endregion GetBlockByHash + + #region GetPeers + + [Fact] + public void GetPeers_ShouldNotIncludeFailing() + { + Assert.Equal(_networkService.GetPeers(false).Count, _peerPool.GetPeers().Count); + } + + [Fact] + public void GetPeers_ShouldIncludeFailing() + { + Assert.Equal(_networkService.GetPeers().Count, _peerPool.GetPeers(true).Count); + } + + [Fact] + public void GetPeersByPubKey() + { + var pubkey = "NormalPeer"; + var peerInfo = _networkService.GetPeerByPubkey(pubkey); + peerInfo.ShouldNotBeNull(); + + var peer = _peerPool.FindPeerByPublicKey(pubkey); + peerInfo.IpAddress.ShouldBe(peer.RemoteEndpoint.ToString()); + peerInfo.Pubkey.ShouldBe(peer.Info.Pubkey); + peerInfo.LastKnownLibHeight.ShouldBe(peer.LastKnownLibHeight); + peerInfo.ProtocolVersion.ShouldBe(peer.Info.ProtocolVersion); + peerInfo.ConnectionTime.ShouldBe(peer.Info.ConnectionTime.Seconds); + peerInfo.ConnectionStatus.ShouldBe(peer.ConnectionStatus); + peerInfo.Inbound.ShouldBe(peer.Info.IsInbound); + peerInfo.SyncState.ShouldBe(peer.SyncState); + peerInfo.BufferedAnnouncementsCount.ShouldBe(peer.BufferedAnnouncementsCount); + peerInfo.BufferedBlocksCount.ShouldBe(peer.BufferedBlocksCount); + peerInfo.BufferedTransactionsCount.ShouldBe(peer.BufferedTransactionsCount); + + var fakePubkey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); + peerInfo = _networkService.GetPeerByPubkey(fakePubkey); + peerInfo.ShouldBeNull(); + } + + [Fact] + public void IsPeerPoolFull_Test() + { + var peerPoolIsFull = _peerPool.IsFull(); + _networkService.IsPeerPoolFull().ShouldBe(peerPoolIsFull); + } + + #endregion GetPeers } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/PeerDiscoveryServiceTests.cs b/test/AElf.OS.Core.Tests/Network/Application/PeerDiscoveryServiceTests.cs index 296f5999f7..3bd2599856 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/PeerDiscoveryServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/PeerDiscoveryServiceTests.cs @@ -5,91 +5,90 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class PeerDiscoveryServiceTests : PeerDiscoveryTestBase { - public class PeerDiscoveryServiceTests : PeerDiscoveryTestBase + private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; + private readonly INodeManager _nodeManager; + private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + private readonly IPeerDiscoveryService _peerDiscoveryService; + + public PeerDiscoveryServiceTests() + { + _peerDiscoveryService = GetRequiredService(); + _nodeManager = GetRequiredService(); + _discoveredNodeCacheProvider = GetRequiredService(); + _peerDiscoveryJobProcessor = GetRequiredService(); + } + + [Fact] + public async Task DiscoverNodes_Test() { - private readonly IPeerDiscoveryService _peerDiscoveryService; - private readonly INodeManager _nodeManager; - private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; - private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + await _peerDiscoveryService.DiscoverNodesAsync(); + await _peerDiscoveryJobProcessor.CompleteAsync(); - public PeerDiscoveryServiceTests() + var nodeList = await _nodeManager.GetRandomNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(1); + nodeList.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); + nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8("192.168.100.100:8003")); + } + + [Fact] + public async Task RefreshNode_Test() + { + var node1 = new NodeInfo { - _peerDiscoveryService = GetRequiredService(); - _nodeManager = GetRequiredService(); - _discoveredNodeCacheProvider = GetRequiredService(); - _peerDiscoveryJobProcessor = GetRequiredService(); - } - - [Fact] - public async Task DiscoverNodes_Test() + Endpoint = "192.168.100.1:8000", + Pubkey = ByteString.CopyFromUtf8("node1") + }; + await _peerDiscoveryService.AddNodeAsync(node1); + + var node2 = new NodeInfo { - await _peerDiscoveryService.DiscoverNodesAsync(); - await _peerDiscoveryJobProcessor.CompleteAsync(); + Endpoint = "192.168.100.1:8001", + Pubkey = ByteString.CopyFromUtf8("node2") + }; + await _peerDiscoveryService.AddNodeAsync(node2); - var nodeList = await _nodeManager.GetRandomNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(1); - nodeList.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); - nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8("192.168.100.100:8003")); - } + await _peerDiscoveryService.RefreshNodeAsync(); - [Fact] - public async Task RefreshNode_Test() - { - var node1 = new NodeInfo - { - Endpoint = "192.168.100.1:8000", - Pubkey = ByteString.CopyFromUtf8("node1") - }; - await _peerDiscoveryService.AddNodeAsync(node1); - - var node2 = new NodeInfo - { - Endpoint = "192.168.100.1:8001", - Pubkey = ByteString.CopyFromUtf8("node2") - }; - await _peerDiscoveryService.AddNodeAsync(node2); - - await _peerDiscoveryService.RefreshNodeAsync(); - - var nodeList = await _nodeManager.GetRandomNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(2); - nodeList.Nodes.ShouldContain(node1); - nodeList.Nodes.ShouldContain(node2); - - await _peerDiscoveryService.RefreshNodeAsync(); - - nodeList = await _nodeManager.GetRandomNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(1); - nodeList.Nodes[0].ShouldBe(node1); - - _discoveredNodeCacheProvider.TryTake(out var endpoint); - endpoint.ShouldBe(node1.Endpoint); - - _discoveredNodeCacheProvider.TryTake(out endpoint); - endpoint.ShouldBeNull(); - } - - [Fact] - public async Task AddNode_And_GetNodes_Test() + var nodeList = await _nodeManager.GetRandomNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(2); + nodeList.Nodes.ShouldContain(node1); + nodeList.Nodes.ShouldContain(node2); + + await _peerDiscoveryService.RefreshNodeAsync(); + + nodeList = await _nodeManager.GetRandomNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(1); + nodeList.Nodes[0].ShouldBe(node1); + + _discoveredNodeCacheProvider.TryTake(out var endpoint); + endpoint.ShouldBe(node1.Endpoint); + + _discoveredNodeCacheProvider.TryTake(out endpoint); + endpoint.ShouldBeNull(); + } + + [Fact] + public async Task AddNode_And_GetNodes_Test() + { + var node = new NodeInfo { - var node = new NodeInfo - { - Endpoint = "192.168.197.1:8000", - Pubkey = ByteString.CopyFromUtf8("test") - }; - - await _peerDiscoveryService.AddNodeAsync(node); - var result = await _nodeManager.GetRandomNodesAsync(10); - result.Nodes.Count.ShouldBe(1); - result.Nodes[0].ShouldBe(node); - - _discoveredNodeCacheProvider.TryTake(out var endpoint); - endpoint.ShouldBe(node.Endpoint); - - _discoveredNodeCacheProvider.TryTake(out endpoint); - endpoint.ShouldBeNull(); - } + Endpoint = "192.168.197.1:8000", + Pubkey = ByteString.CopyFromUtf8("test") + }; + + await _peerDiscoveryService.AddNodeAsync(node); + var result = await _nodeManager.GetRandomNodesAsync(10); + result.Nodes.Count.ShouldBe(1); + result.Nodes[0].ShouldBe(node); + + _discoveredNodeCacheProvider.TryTake(out var endpoint); + endpoint.ShouldBe(node.Endpoint); + + _discoveredNodeCacheProvider.TryTake(out endpoint); + endpoint.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/PeerInvalidTransactionProcessingServiceTests.cs b/test/AElf.OS.Core.Tests/Network/Application/PeerInvalidTransactionProcessingServiceTests.cs index 4c672b1fd6..4fcd658369 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/PeerInvalidTransactionProcessingServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/PeerInvalidTransactionProcessingServiceTests.cs @@ -1,94 +1,93 @@ using System.Threading.Tasks; using AElf.OS.Network.Infrastructure; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class PeerPeerInvalidTransactionProcessingServiceTests : PeerInvalidTransactionTestBase { - public class PeerPeerInvalidTransactionProcessingServiceTests : PeerInvalidTransactionTestBase + private readonly IBlackListedPeerProvider _blackListedPeerProvider; + private readonly IPeerInvalidTransactionProcessingService _peerInvalidTransactionProcessingService; + private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; + private readonly IPeerPool _peerPool; + + public PeerPeerInvalidTransactionProcessingServiceTests() { - private readonly IPeerInvalidTransactionProcessingService _peerInvalidTransactionProcessingService; - private readonly IBlackListedPeerProvider _blackListedPeerProvider; - private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; - private readonly IPeerPool _peerPool; + _peerInvalidTransactionProcessingService = GetRequiredService(); + _blackListedPeerProvider = GetRequiredService(); + _peerInvalidTransactionProvider = GetRequiredService(); + _peerPool = GetRequiredService(); + } - public PeerPeerInvalidTransactionProcessingServiceTests() - { - _peerInvalidTransactionProcessingService = GetRequiredService(); - _blackListedPeerProvider = GetRequiredService(); - _peerInvalidTransactionProvider = GetRequiredService(); - _peerPool = GetRequiredService(); - } + [Fact] + public async Task ProcessPeerInvalidTransaction_Test() + { + var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); + var peer3 = _peerPool.FindPeerByPublicKey("Peer3"); + + bool isInBlackList; - [Fact] - public async Task ProcessPeerInvalidTransaction_Test() + for (var i = 0; i < 5; i++) { - var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); - var peer3 = _peerPool.FindPeerByPublicKey("Peer3"); - - bool isInBlackList; - - for (var i = 0; i < 5; i++) - { - var txId = HashHelper.ComputeFrom("Tx" + i + "Peer3"); - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host); - isInBlackList.ShouldBeFalse(); - } - - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(HashHelper.ComputeFrom("Tx" + 5 + "Peer3")); + var txId = HashHelper.ComputeFrom("Tx" + i + "Peer3"); + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host); - isInBlackList.ShouldBeTrue(); - - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); isInBlackList.ShouldBeFalse(); } - [Fact] - public async Task ProcessPeerInvalidTransaction_MultiplePorts_Test() - { - var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); - var peer2 = _peerPool.FindPeerByPublicKey("Peer2"); - var peer3 = _peerPool.FindPeerByPublicKey("Peer3"); - - bool isInBlackList; - - for (var i = 0; i < 4; i++) - { - var txId = HashHelper.ComputeFrom("Tx" + i + "Peer1"); - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); - isInBlackList.ShouldBeFalse(); - } - - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(HashHelper.ComputeFrom("Tx0Peer2")); - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer2.RemoteEndpoint.Host); - isInBlackList.ShouldBeFalse(); + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync( + HashHelper.ComputeFrom("Tx" + 5 + "Peer3")); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host); + isInBlackList.ShouldBeTrue(); - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(HashHelper.ComputeFrom("Tx1Peer2")); - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); - isInBlackList.ShouldBeTrue(); - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer2.RemoteEndpoint.Host); - isInBlackList.ShouldBeTrue(); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); + isInBlackList.ShouldBeFalse(); + } - isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host); - isInBlackList.ShouldBeFalse(); - } + [Fact] + public async Task ProcessPeerInvalidTransaction_MultiplePorts_Test() + { + var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); + var peer2 = _peerPool.FindPeerByPublicKey("Peer2"); + var peer3 = _peerPool.FindPeerByPublicKey("Peer3"); + + bool isInBlackList; - [Fact] - public async Task ProcessPeerInvalidTransaction_RepeatedTransaction_Test() + for (var i = 0; i < 4; i++) { - var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); - - var txId = HashHelper.ComputeFrom("Tx0Peer1"); - for (var i = 0; i < 6; i++) - { - await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); - } - - var isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); + var txId = HashHelper.ComputeFrom("Tx" + i + "Peer1"); + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); isInBlackList.ShouldBeFalse(); } + + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync( + HashHelper.ComputeFrom("Tx0Peer2")); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer2.RemoteEndpoint.Host); + isInBlackList.ShouldBeFalse(); + + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync( + HashHelper.ComputeFrom("Tx1Peer2")); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); + isInBlackList.ShouldBeTrue(); + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer2.RemoteEndpoint.Host); + isInBlackList.ShouldBeTrue(); + + isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer3.RemoteEndpoint.Host); + isInBlackList.ShouldBeFalse(); + } + + [Fact] + public async Task ProcessPeerInvalidTransaction_RepeatedTransaction_Test() + { + var peer1 = _peerPool.FindPeerByPublicKey("Peer1"); + + var txId = HashHelper.ComputeFrom("Tx0Peer1"); + for (var i = 0; i < 6; i++) + await _peerInvalidTransactionProcessingService.ProcessPeerInvalidTransactionAsync(txId); + + var isInBlackList = _blackListedPeerProvider.IsIpBlackListed(peer1.RemoteEndpoint.Host); + isInBlackList.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/PeerReconnectionServiceTests.cs b/test/AElf.OS.Core.Tests/Network/Application/PeerReconnectionServiceTests.cs index e7dd22610f..9b44dee1bd 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/PeerReconnectionServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/PeerReconnectionServiceTests.cs @@ -5,89 +5,87 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class PeerReconnectionServiceTests : OSCoreNetworkServiceTestBase { - public class PeerReconnectionServiceTests : OSCoreNetworkServiceTestBase + private readonly IPeerReconnectionStateProvider _connectionStateProvider; + private readonly IReconnectionService _reconnectionService; + + public PeerReconnectionServiceTests() + { + _reconnectionService = GetRequiredService(); + _connectionStateProvider = GetRequiredService(); + } + + [Fact] + public void GetPeersReadyForReconnection_WithNull_ReturnsAll() + { + var endpoint = "127.0.0.1:5677"; + var endpointBeforeNow = "127.0.0.1:5678"; + var endpointAfterNow = "127.0.0.1:5679"; + + _reconnectionService.SchedulePeerForReconnection(endpoint); + _reconnectionService.SchedulePeerForReconnection(endpointBeforeNow); + _reconnectionService.SchedulePeerForReconnection(endpointAfterNow); + + var peers = _connectionStateProvider.GetPeersReadyForReconnection(null); + + peers.Count.ShouldBe(3); + } + + [Fact] + public void ScheduledPeer_CannotAddPeerTwice() + { + var endpoint = "127.0.0.1:5677"; + + _reconnectionService.SchedulePeerForReconnection(endpoint).ShouldBeTrue(); + _reconnectionService.SchedulePeerForReconnection(endpoint).ShouldBeFalse(); + + var peers = _connectionStateProvider.GetPeersReadyForReconnection(null); + + peers.Count.ShouldBe(1); + peers.First().Endpoint.ShouldBe(endpoint); + } + + [Fact] + public void ScheduledPeer_ShouldBeRetrievableWithTheProvider() + { + var endpoint = "127.0.0.1:5677"; + + _reconnectionService.SchedulePeerForReconnection(endpoint); + var peers = _connectionStateProvider.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow().AddMinutes(2)); + + peers.Count.ShouldBe(1); + peers.First().Endpoint.ShouldBe(endpoint); + } + + [Fact] + public void RemovePeer_ShouldNotRetrievableWithTheProvider() + { + var endpoint = "127.0.0.1:5677"; + + _reconnectionService.SchedulePeerForReconnection(endpoint); + _reconnectionService.CancelReconnection(endpoint); + + var peers = _connectionStateProvider.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow().AddSeconds(1)); + peers.Count.ShouldBe(0); + } + + [Fact] + public void CancelReconnection_NotExitEndpoint_ReturnFalse() + { + var result = _reconnectionService.CancelReconnection("127.0.0.1:5677"); + result.ShouldBeFalse(); + } + + [Fact] + public void GetReconnectingPeer_Test() { - private IReconnectionService _reconnectionService; - private IPeerReconnectionStateProvider _connectionStateProvider; - - public PeerReconnectionServiceTests() - { - _reconnectionService = GetRequiredService(); - _connectionStateProvider = GetRequiredService(); - } - - [Fact] - public void GetPeersReadyForReconnection_WithNull_ReturnsAll() - { - var endpoint = "127.0.0.1:5677"; - var endpointBeforeNow = "127.0.0.1:5678"; - var endpointAfterNow = "127.0.0.1:5679"; - - _reconnectionService.SchedulePeerForReconnection(endpoint); - _reconnectionService.SchedulePeerForReconnection(endpointBeforeNow); - _reconnectionService.SchedulePeerForReconnection(endpointAfterNow); - - var peers = _connectionStateProvider.GetPeersReadyForReconnection(null); - - peers.Count.ShouldBe(3); - } - - [Fact] - public void ScheduledPeer_CannotAddPeerTwice() - { - var endpoint = "127.0.0.1:5677"; - - _reconnectionService.SchedulePeerForReconnection(endpoint).ShouldBeTrue(); - _reconnectionService.SchedulePeerForReconnection(endpoint).ShouldBeFalse(); - - var peers = _connectionStateProvider.GetPeersReadyForReconnection(null); - - peers.Count.ShouldBe(1); - peers.First().Endpoint.ShouldBe(endpoint); - } - - [Fact] - public void ScheduledPeer_ShouldBeRetrievableWithTheProvider() - { - var endpoint = "127.0.0.1:5677"; - - _reconnectionService.SchedulePeerForReconnection(endpoint); - var peers = _connectionStateProvider.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow().AddMinutes(2)); - - peers.Count.ShouldBe(1); - peers.First().Endpoint.ShouldBe(endpoint); - } - - [Fact] - public void RemovePeer_ShouldNotRetrievableWithTheProvider() - { - var endpoint = "127.0.0.1:5677"; - - _reconnectionService.SchedulePeerForReconnection(endpoint); - _reconnectionService.CancelReconnection(endpoint); - - var peers = _connectionStateProvider.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow(). - AddSeconds(1)); - peers.Count.ShouldBe(0); - } - - [Fact] - public void CancelReconnection_NotExitEndpoint_ReturnFalse() - { - var result = _reconnectionService.CancelReconnection("127.0.0.1:5677"); - result.ShouldBeFalse(); - } - - [Fact] - public void GetReconnectingPeer_Test() - { - var endpoint = "127.0.0.1:5677"; - _reconnectionService.SchedulePeerForReconnection(endpoint); - var result = _reconnectionService.GetReconnectingPeer(endpoint); - result.ShouldNotBeNull(); - result.Endpoint.ShouldBe(endpoint); - } + var endpoint = "127.0.0.1:5677"; + _reconnectionService.SchedulePeerForReconnection(endpoint); + var result = _reconnectionService.GetReconnectingPeer(endpoint); + result.ShouldNotBeNull(); + result.Endpoint.ShouldBe(endpoint); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Application/SyncStateServiceTests.cs b/test/AElf.OS.Core.Tests/Network/Application/SyncStateServiceTests.cs index b89475f618..c471d5a4e9 100644 --- a/test/AElf.OS.Core.Tests/Network/Application/SyncStateServiceTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Application/SyncStateServiceTests.cs @@ -10,168 +10,163 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Network.Application +namespace AElf.OS.Network.Application; + +public class SyncStateServiceTests : SyncFlagTestBase { - public class SyncStateServiceTests : SyncFlagTestBase + private readonly IBlockchainService _blockchainService; + private readonly ILocalEventBus _eventBus; + + private readonly OSTestHelper _osTestHelper; + private readonly IPeerPool _peerPool; + private readonly INodeSyncStateProvider _syncStateProvider; + private readonly ISyncStateService _syncStateService; + + public SyncStateServiceTests() { - private readonly ISyncStateService _syncStateService; - private readonly IPeerPool _peerPool; - private readonly INodeSyncStateProvider _syncStateProvider; - private readonly IBlockchainService _blockchainService; - private readonly ILocalEventBus _eventBus; + _syncStateService = GetRequiredService(); + _peerPool = GetRequiredService(); + _syncStateProvider = GetRequiredService(); + _osTestHelper = GetService(); + _blockchainService = GetRequiredService(); + _eventBus = GetRequiredService(); + } - private readonly OSTestHelper _osTestHelper; + [Fact] + public async Task StartSync_CurrentSyncStateIsNotUnInitialized_Test() + { + _syncStateProvider.SetSyncTarget(10); - public SyncStateServiceTests() - { - _syncStateService = GetRequiredService(); - _peerPool = GetRequiredService(); - _syncStateProvider = GetRequiredService(); - _osTestHelper = GetService(); - _blockchainService = GetRequiredService(); - _eventBus = GetRequiredService(); - } - - [Fact] - public async Task StartSync_CurrentSyncStateIsNotUnInitialized_Test() - { - _syncStateProvider.SetSyncTarget(10); - - _peerPool.TryAddPeer(CreatePeer(15)); - _peerPool.TryAddPeer(CreatePeer(16)); - - await _syncStateService.StartSyncAsync(); - _syncStateService.GetCurrentSyncTarget().ShouldBe(10); - - } - - [Fact] - public async Task StartSync_NoEnoughPeer_Test() - { - _peerPool.TryAddPeer(CreatePeer(0)); - _peerPool.TryAddPeer(CreatePeer(16)); - - InitialSyncFinishedEvent eventData = null; - _eventBus.Subscribe(args => - { - eventData = args; - return Task.CompletedTask; - }); - - await _syncStateService.StartSyncAsync(); - _syncStateService.GetCurrentSyncTarget().ShouldBe(-1); - - eventData.ShouldNotBeNull(); - } - - [Fact] - public void Initial_State_Is_Syncing() - { - _syncStateService.SyncState.ShouldBe(SyncState.UnInitialized); - } + _peerPool.TryAddPeer(CreatePeer(15)); + _peerPool.TryAddPeer(CreatePeer(16)); - [Fact] - public async Task Cannot_Retrigger_Sync() - { - await _syncStateService.StartSyncAsync(); - await _syncStateService.UpdateSyncStateAsync(); - - _syncStateService.SyncState.ShouldBe(SyncState.Finished); - } - - [Fact] - public async Task UpdateSyncState_Test() - { - _peerPool.TryAddPeer(CreatePeer(15)); - _peerPool.TryAddPeer(CreatePeer(16)); - - InitialSyncFinishedEvent eventData = null; - _eventBus.Subscribe(args => - { - eventData = args; - return Task.CompletedTask; - }); - - await _syncStateService.StartSyncAsync(); - _syncStateService.SyncState.ShouldBe(SyncState.Syncing); - _syncStateService.GetCurrentSyncTarget().ShouldBe(15); - - await _syncStateService.UpdateSyncStateAsync(); - _syncStateService.SyncState.ShouldBe(SyncState.Syncing); - _syncStateService.GetCurrentSyncTarget().ShouldBe(15); - - for (var i = 0; i < 4; i++) - { - await _osTestHelper.MinedOneBlock(); - } - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, _osTestHelper.BestBranchBlockList.Last().Height, - _osTestHelper.BestBranchBlockList.Last().GetHash()); - - await _syncStateService.UpdateSyncStateAsync(); - _syncStateService.SyncState.ShouldBe(SyncState.Finished); - _syncStateService.GetCurrentSyncTarget().ShouldBe(-1); - - eventData.ShouldNotBeNull(); - } - - [Fact] - public async Task Sync_Finished_Should_Launch_Event() - { - InitialSyncFinishedEvent eventData = null; - _eventBus.Subscribe(args => - { - eventData = args; - return Task.CompletedTask; - }); - - await _syncStateService.StartSyncAsync(); - - eventData.ShouldNotBeNull(); - } - - [Fact] - public async Task No_Peers_Stops_Sync() - { - await _syncStateService.StartSyncAsync(); - _syncStateService.SyncState.ShouldBe(SyncState.Finished); - } - - [Fact] - public async Task Peers_WithNoLib_Stops_Sync() + await _syncStateService.StartSyncAsync(); + _syncStateService.GetCurrentSyncTarget().ShouldBe(10); + } + + [Fact] + public async Task StartSync_NoEnoughPeer_Test() + { + _peerPool.TryAddPeer(CreatePeer()); + _peerPool.TryAddPeer(CreatePeer(16)); + + InitialSyncFinishedEvent eventData = null; + _eventBus.Subscribe(args => { - _peerPool.TryAddPeer(CreatePeer()); - _peerPool.TryAddPeer(CreatePeer()); - - await _syncStateService.StartSyncAsync(); - - _syncStateService.SyncState.ShouldBe(SyncState.Finished); - } - - [Theory] - [InlineData(SyncState.Finished, new int[] {})] - [InlineData(SyncState.Syncing, new []{15, 15})] - [InlineData(SyncState.Finished, new []{5, 15})] - public async Task Trigger_Sync_Depends_On_Peers_And_Local_LIB(SyncState expectedSyncState, int[] peers) + eventData = args; + return Task.CompletedTask; + }); + + await _syncStateService.StartSyncAsync(); + _syncStateService.GetCurrentSyncTarget().ShouldBe(-1); + + eventData.ShouldNotBeNull(); + } + + [Fact] + public void Initial_State_Is_Syncing() + { + _syncStateService.SyncState.ShouldBe(SyncState.UnInitialized); + } + + [Fact] + public async Task Cannot_Retrigger_Sync() + { + await _syncStateService.StartSyncAsync(); + await _syncStateService.UpdateSyncStateAsync(); + + _syncStateService.SyncState.ShouldBe(SyncState.Finished); + } + + [Fact] + public async Task UpdateSyncState_Test() + { + _peerPool.TryAddPeer(CreatePeer(15)); + _peerPool.TryAddPeer(CreatePeer(16)); + + InitialSyncFinishedEvent eventData = null; + _eventBus.Subscribe(args => { - foreach (int peer in peers) - _peerPool.TryAddPeer(CreatePeer(peer)); - - await _syncStateService.StartSyncAsync(); - - _syncStateService.SyncState.ShouldBe(expectedSyncState); - } - - private IPeer CreatePeer(long libHeight = 0) + eventData = args; + return Task.CompletedTask; + }); + + await _syncStateService.StartSyncAsync(); + _syncStateService.SyncState.ShouldBe(SyncState.Syncing); + _syncStateService.GetCurrentSyncTarget().ShouldBe(15); + + await _syncStateService.UpdateSyncStateAsync(); + _syncStateService.SyncState.ShouldBe(SyncState.Syncing); + _syncStateService.GetCurrentSyncTarget().ShouldBe(15); + + for (var i = 0; i < 4; i++) await _osTestHelper.MinedOneBlock(); + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, _osTestHelper.BestBranchBlockList.Last().Height, + _osTestHelper.BestBranchBlockList.Last().GetHash()); + + await _syncStateService.UpdateSyncStateAsync(); + _syncStateService.SyncState.ShouldBe(SyncState.Finished); + _syncStateService.GetCurrentSyncTarget().ShouldBe(-1); + + eventData.ShouldNotBeNull(); + } + + [Fact] + public async Task Sync_Finished_Should_Launch_Event() + { + InitialSyncFinishedEvent eventData = null; + _eventBus.Subscribe(args => { - var peerMock = new Mock(); - - peerMock.Setup(p => p.Info) - .Returns(new PeerConnectionInfo {Pubkey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex()}); - - peerMock.Setup(p => p.LastKnownLibHeight).Returns(libHeight); - - return peerMock.Object; - } + eventData = args; + return Task.CompletedTask; + }); + + await _syncStateService.StartSyncAsync(); + + eventData.ShouldNotBeNull(); + } + + [Fact] + public async Task No_Peers_Stops_Sync() + { + await _syncStateService.StartSyncAsync(); + _syncStateService.SyncState.ShouldBe(SyncState.Finished); + } + + [Fact] + public async Task Peers_WithNoLib_Stops_Sync() + { + _peerPool.TryAddPeer(CreatePeer()); + _peerPool.TryAddPeer(CreatePeer()); + + await _syncStateService.StartSyncAsync(); + + _syncStateService.SyncState.ShouldBe(SyncState.Finished); + } + + [Theory] + [InlineData(SyncState.Finished, new int[] { })] + [InlineData(SyncState.Syncing, new[] { 15, 15 })] + [InlineData(SyncState.Finished, new[] { 5, 15 })] + public async Task Trigger_Sync_Depends_On_Peers_And_Local_LIB(SyncState expectedSyncState, int[] peers) + { + foreach (var peer in peers) + _peerPool.TryAddPeer(CreatePeer(peer)); + + await _syncStateService.StartSyncAsync(); + + _syncStateService.SyncState.ShouldBe(expectedSyncState); + } + + private IPeer CreatePeer(long libHeight = 0) + { + var peerMock = new Mock(); + + peerMock.Setup(p => p.Info) + .Returns(new PeerConnectionInfo { Pubkey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex() }); + + peerMock.Setup(p => p.LastKnownLibHeight).Returns(libHeight); + + return peerMock.Object; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Domain/NodeManagerTests.cs b/test/AElf.OS.Core.Tests/Network/Domain/NodeManagerTests.cs index e825ebe207..ceb4ae5247 100644 --- a/test/AElf.OS.Core.Tests/Network/Domain/NodeManagerTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Domain/NodeManagerTests.cs @@ -5,116 +5,115 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Domain +namespace AElf.OS.Network.Domain; + +public class NodeManagerTests : NetworkInfrastructureTestBase { - public class NodeManagerTests : NetworkInfrastructureTestBase + private readonly NetworkOptions _networkOptions; + private readonly INodeManager _nodeManager; + + public NodeManagerTests() { - private readonly INodeManager _nodeManager; - private readonly NetworkOptions _networkOptions; + _nodeManager = GetRequiredService(); + _networkOptions = GetRequiredService>().Value; + } - public NodeManagerTests() - { - _nodeManager = GetRequiredService(); - _networkOptions = GetRequiredService>().Value; - } + [Fact] + public async Task AddNode_Test() + { + var node = GenerateTestNode(100); + var addResult = await _nodeManager.AddNodeAsync(node); + addResult.ShouldBeTrue(); - [Fact] - public async Task AddNode_Test() - { - var node = GenerateTestNode(100); - var addResult = await _nodeManager.AddNodeAsync(node); - addResult.ShouldBeTrue(); - - addResult = await _nodeManager.AddNodeAsync(node); - addResult.ShouldBeFalse(); - - for (int i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep - 1; i++) - { - node = GenerateTestNode(i+1); - addResult = await _nodeManager.AddNodeAsync(node); - addResult.ShouldBeTrue(); - } - - node = GenerateTestNode(101); - addResult = await _nodeManager.AddNodeAsync(node); - addResult.ShouldBeFalse(); - } + addResult = await _nodeManager.AddNodeAsync(node); + addResult.ShouldBeFalse(); - [Fact] - public async Task GetRandomNodes_Test() + for (var i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep - 1; i++) { - var randomNode = await _nodeManager.GetRandomNodesAsync(1); - randomNode.Nodes.Count.ShouldBe(0); - - for (int i = 0; i < 3; i++) - { - var node = GenerateTestNode(i+1); - await _nodeManager.AddNodeAsync(node); - } - - randomNode = await _nodeManager.GetRandomNodesAsync(1); - randomNode.Nodes.Count.ShouldBe(1); - - randomNode = await _nodeManager.GetRandomNodesAsync(3); - randomNode.Nodes.Count.ShouldBe(3); - - randomNode = await _nodeManager.GetRandomNodesAsync(5); - randomNode.Nodes.Count.ShouldBe(3); + node = GenerateTestNode(i + 1); + addResult = await _nodeManager.AddNodeAsync(node); + addResult.ShouldBeTrue(); } - [Fact] - public async Task GetNode_Test() - { - var node = GenerateTestNode(100); - await _nodeManager.AddNodeAsync(node); - - var result = await _nodeManager.GetNodeAsync("192.168.100.1:80"); - result.ShouldBeNull(); + node = GenerateTestNode(101); + addResult = await _nodeManager.AddNodeAsync(node); + addResult.ShouldBeFalse(); + } - result = await _nodeManager.GetNodeAsync(node.Endpoint); - result.ShouldBe(node); - } + [Fact] + public async Task GetRandomNodes_Test() + { + var randomNode = await _nodeManager.GetRandomNodesAsync(1); + randomNode.Nodes.Count.ShouldBe(0); - [Fact] - public async Task UpdateNode_Test() + for (var i = 0; i < 3; i++) { - var node = GenerateTestNode(100); + var node = GenerateTestNode(i + 1); await _nodeManager.AddNodeAsync(node); - - var newNode = GenerateTestNode(100); - await _nodeManager.UpdateNodeAsync(newNode); - - var result = await _nodeManager.GetNodeAsync(node.Endpoint); - result.ShouldBe(newNode); - - var newNode2 = GenerateTestNode(200); - await _nodeManager.UpdateNodeAsync(newNode2); - - result = await _nodeManager.GetNodeAsync(node.Endpoint); - result.ShouldBe(newNode); } - [Fact] - public async Task RemoveNode_Test() - { - var node = GenerateTestNode(100); - await _nodeManager.AddNodeAsync(node); + randomNode = await _nodeManager.GetRandomNodesAsync(1); + randomNode.Nodes.Count.ShouldBe(1); - await _nodeManager.RemoveNodeAsync(node.Endpoint); - - var result = await _nodeManager.GetNodeAsync(node.Endpoint); - result.ShouldBeNull(); - } + randomNode = await _nodeManager.GetRandomNodesAsync(3); + randomNode.Nodes.Count.ShouldBe(3); - private NodeInfo GenerateTestNode(int port) + randomNode = await _nodeManager.GetRandomNodesAsync(5); + randomNode.Nodes.Count.ShouldBe(3); + } + + [Fact] + public async Task GetNode_Test() + { + var node = GenerateTestNode(100); + await _nodeManager.AddNodeAsync(node); + + var result = await _nodeManager.GetNodeAsync("192.168.100.1:80"); + result.ShouldBeNull(); + + result = await _nodeManager.GetNodeAsync(node.Endpoint); + result.ShouldBe(node); + } + + [Fact] + public async Task UpdateNode_Test() + { + var node = GenerateTestNode(100); + await _nodeManager.AddNodeAsync(node); + + var newNode = GenerateTestNode(100); + await _nodeManager.UpdateNodeAsync(newNode); + + var result = await _nodeManager.GetNodeAsync(node.Endpoint); + result.ShouldBe(newNode); + + var newNode2 = GenerateTestNode(200); + await _nodeManager.UpdateNodeAsync(newNode2); + + result = await _nodeManager.GetNodeAsync(node.Endpoint); + result.ShouldBe(newNode); + } + + [Fact] + public async Task RemoveNode_Test() + { + var node = GenerateTestNode(100); + await _nodeManager.AddNodeAsync(node); + + await _nodeManager.RemoveNodeAsync(node.Endpoint); + + var result = await _nodeManager.GetNodeAsync(node.Endpoint); + result.ShouldBeNull(); + } + + private NodeInfo GenerateTestNode(int port) + { + var node = new NodeInfo { - var node = new NodeInfo - { - Endpoint = $"192.168.197.100:{port}", - Pubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) - }; + Endpoint = $"192.168.197.100:{port}", + Pubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey) + }; - return node; - } + return node; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Helpers/AElfPeerEndpointHelperTests.cs b/test/AElf.OS.Core.Tests/Network/Helpers/AElfPeerEndpointHelperTests.cs index b29718ed04..161e6ae695 100644 --- a/test/AElf.OS.Core.Tests/Network/Helpers/AElfPeerEndpointHelperTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Helpers/AElfPeerEndpointHelperTests.cs @@ -1,36 +1,33 @@ -using AElf.OS.Network.Helpers; -using NuGet.Frameworks; using Shouldly; using Xunit; -namespace AElf.OS.Network.Helpers +namespace AElf.OS.Network.Helpers; + +public class AElfPeerEndpointHelperTests : OSCoreNetworkServiceTestBase { - public class AElfPeerEndpointHelperTests : OSCoreNetworkServiceTestBase + [Theory] + [InlineData("aelf.bp1.cn:8907", true, 8907)] + [InlineData("aelf.bp1.cn", true, NetworkConstants.DefaultPeerPort)] + [InlineData("127.0.0.1:13000", true, 13000)] + [InlineData("0.0.0.0:100", true, 100)] + [InlineData("0.0.0.0", true, NetworkConstants.DefaultPeerPort)] + [InlineData("::1", true, NetworkConstants.DefaultPeerPort)] + [InlineData("::", true, NetworkConstants.DefaultPeerPort)] + [InlineData("[1fff:0:a88:85a3::ac1f]:8001", true, 8001)] + [InlineData("[1fff:0:a88:85a3::ac1f]:8907333", false)] + [InlineData("", false)] + [InlineData(" ", false)] + [InlineData("aelf.bp1.cn:8907333", false)] + [InlineData("aelf.bp1.cn:abcs", false)] + [InlineData("0.0.0.0:100", false, 0, -2)] + [InlineData("0.0.0.0:100", false, 0, 65536)] + [InlineData("0.0.0.0", false, 0, -1)] + public void ParsingTest(string endpointToParse, bool isValid, int expectedPort = 0, + int defaultPort = NetworkConstants.DefaultPeerPort) { - [Theory] - [InlineData("aelf.bp1.cn:8907", true, 8907)] - [InlineData("aelf.bp1.cn", true, NetworkConstants.DefaultPeerPort)] - [InlineData("127.0.0.1:13000", true, 13000)] - [InlineData("0.0.0.0:100", true, 100)] - [InlineData("0.0.0.0", true, NetworkConstants.DefaultPeerPort)] - [InlineData("::1", true, NetworkConstants.DefaultPeerPort)] - [InlineData("::", true, NetworkConstants.DefaultPeerPort)] - [InlineData("[1fff:0:a88:85a3::ac1f]:8001", true, 8001)] - [InlineData("[1fff:0:a88:85a3::ac1f]:8907333", false)] - [InlineData("", false)] - [InlineData(" ", false)] - [InlineData("aelf.bp1.cn:8907333", false)] - [InlineData("aelf.bp1.cn:abcs", false)] - [InlineData("0.0.0.0:100", false, 0, -2)] - [InlineData("0.0.0.0:100", false, 0, 65536)] - [InlineData("0.0.0.0", false, 0, -1)] - public void ParsingTest(string endpointToParse, bool isValid, int expectedPort = 0, - int defaultPort = NetworkConstants.DefaultPeerPort) - { - AElfPeerEndpointHelper.TryParse(endpointToParse, out var endpoint, defaultPort).ShouldBe(isValid); + AElfPeerEndpointHelper.TryParse(endpointToParse, out var endpoint, defaultPort).ShouldBe(isValid); - if (isValid) - endpoint.Port.ShouldBe(expectedPort); - } + if (isValid) + endpoint.Port.ShouldBe(expectedPort); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/BlackListProviderTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/BlackListProviderTests.cs index 51eb1f09ed..3adf92fd70 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/BlackListProviderTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/BlackListProviderTests.cs @@ -1,74 +1,69 @@ -using System; -using System.Net; using System.Threading.Tasks; -using AElf.OS.Network.Helpers; -using AElf.OS.Network.Infrastructure; using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class BlackListProviderTests : NetworkInfrastructureTestBase { - public class BlackListProviderTests : NetworkInfrastructureTestBase + private readonly IBlackListedPeerProvider _blackListProvider; + + public BlackListProviderTests() + { + _blackListProvider = GetRequiredService(); + } + + [Fact] + public async Task IsIpBlackListed_Test() + { + var ipAddress = "127.0.0.1"; + + _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); + + _blackListProvider.AddHostToBlackList(ipAddress, 1); + _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeTrue(); + + await Task.Delay(1200); + + _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); + } + + [Fact] + public void RemovePeerFromBlacklist_Test() { - private IBlackListedPeerProvider _blackListProvider; - - public BlackListProviderTests() - { - _blackListProvider = GetRequiredService(); - } - - [Fact] - public async Task IsIpBlackListed_Test() - { - var ipAddress = "127.0.0.1"; - - _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); - - _blackListProvider.AddHostToBlackList(ipAddress, 1); - _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeTrue(); - - await Task.Delay(1200); - - _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); - } - - [Fact] - public void RemovePeerFromBlacklist_Test() - { - var ipAddress = "127.0.0.1"; - - _blackListProvider.AddHostToBlackList(ipAddress, int.MaxValue); - _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeTrue(); - - _blackListProvider.RemoveHostFromBlackList(ipAddress).ShouldBeTrue(); - - _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); - - _blackListProvider.RemoveHostFromBlackList(ipAddress).ShouldBeFalse(); - } - - [Fact] - public async Task AddHostToBlackList_Test() - { - var ipAddress1 = "192.168.100.1"; - var ipAddress2 = "192.168.100.2"; - _blackListProvider.AddHostToBlackList(ipAddress1, 1).ShouldBeTrue(); - - await Task.Delay(1200); - _blackListProvider.AddHostToBlackList(ipAddress2, 1).ShouldBeTrue(); - - var removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress1); - removeResult.ShouldBeFalse(); - removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress2); - removeResult.ShouldBeTrue(); - - _blackListProvider.AddHostToBlackList(ipAddress1, 1); - _blackListProvider.AddHostToBlackList(ipAddress2, 5); - - await Task.Delay(1200); - _blackListProvider.AddHostToBlackList(ipAddress2, 1).ShouldBeFalse(); - removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress1); - removeResult.ShouldBeFalse(); - } + var ipAddress = "127.0.0.1"; + + _blackListProvider.AddHostToBlackList(ipAddress, int.MaxValue); + _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeTrue(); + + _blackListProvider.RemoveHostFromBlackList(ipAddress).ShouldBeTrue(); + + _blackListProvider.IsIpBlackListed(ipAddress).ShouldBeFalse(); + + _blackListProvider.RemoveHostFromBlackList(ipAddress).ShouldBeFalse(); + } + + [Fact] + public async Task AddHostToBlackList_Test() + { + var ipAddress1 = "192.168.100.1"; + var ipAddress2 = "192.168.100.2"; + _blackListProvider.AddHostToBlackList(ipAddress1, 1).ShouldBeTrue(); + + await Task.Delay(1200); + _blackListProvider.AddHostToBlackList(ipAddress2, 1).ShouldBeTrue(); + + var removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress1); + removeResult.ShouldBeFalse(); + removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress2); + removeResult.ShouldBeTrue(); + + _blackListProvider.AddHostToBlackList(ipAddress1, 1); + _blackListProvider.AddHostToBlackList(ipAddress2, 5); + + await Task.Delay(1200); + _blackListProvider.AddHostToBlackList(ipAddress2, 1).ShouldBeFalse(); + removeResult = _blackListProvider.RemoveHostFromBlackList(ipAddress1); + removeResult.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/DiscoveredNodeCacheProviderTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/DiscoveredNodeCacheProviderTests.cs index 579859f48b..ff7a71fe73 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/DiscoveredNodeCacheProviderTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/DiscoveredNodeCacheProviderTests.cs @@ -1,39 +1,38 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class DiscoveredNodeCacheProviderTests : NetworkInfrastructureTestBase { - public class DiscoveredNodeCacheProviderTests : NetworkInfrastructureTestBase + private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; + + public DiscoveredNodeCacheProviderTests() + { + _discoveredNodeCacheProvider = GetRequiredService(); + } + + [Fact] + public void DiscoveredNodeCache_Test() { - private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; - - public DiscoveredNodeCacheProviderTests() - { - _discoveredNodeCacheProvider = GetRequiredService(); - } - - [Fact] - public void DiscoveredNodeCache_Test() - { - var endpoint1 = "192.168.100.100:101"; - var endpoint2 = "192.168.100.100:102"; - - var result = _discoveredNodeCacheProvider.TryTake(out var endpoint); - result.ShouldBeFalse(); - endpoint.ShouldBeNull(); - - _discoveredNodeCacheProvider.Add(endpoint1); - _discoveredNodeCacheProvider.Add(endpoint2); - - result = _discoveredNodeCacheProvider.TryTake(out endpoint); - result.ShouldBeTrue(); - endpoint.ShouldBe(endpoint1); - - _discoveredNodeCacheProvider.Add(endpoint1); - - result = _discoveredNodeCacheProvider.TryTake(out endpoint); - result.ShouldBeTrue(); - endpoint.ShouldBe(endpoint2); - } + var endpoint1 = "192.168.100.100:101"; + var endpoint2 = "192.168.100.100:102"; + + var result = _discoveredNodeCacheProvider.TryTake(out var endpoint); + result.ShouldBeFalse(); + endpoint.ShouldBeNull(); + + _discoveredNodeCacheProvider.Add(endpoint1); + _discoveredNodeCacheProvider.Add(endpoint2); + + result = _discoveredNodeCacheProvider.TryTake(out endpoint); + result.ShouldBeTrue(); + endpoint.ShouldBe(endpoint1); + + _discoveredNodeCacheProvider.Add(endpoint1); + + result = _discoveredNodeCacheProvider.TryTake(out endpoint); + result.ShouldBeTrue(); + endpoint.ShouldBe(endpoint2); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerDiscoveryJobProcessorTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerDiscoveryJobProcessorTests.cs index 4859c2909c..30cb6553a0 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerDiscoveryJobProcessorTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerDiscoveryJobProcessorTests.cs @@ -5,147 +5,146 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerDiscoveryJobProcessorTests : PeerDiscoveryTestBase { - public class PeerDiscoveryJobProcessorTests : PeerDiscoveryTestBase + private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; + private readonly NetworkOptions _networkOptions; + private readonly INodeManager _nodeManager; + private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + private readonly IPeerPool _peerPool; + + public PeerDiscoveryJobProcessorTests() { - private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; - private readonly IPeerPool _peerPool; - private readonly INodeManager _nodeManager; - private readonly IDiscoveredNodeCacheProvider _discoveredNodeCacheProvider; - private readonly NetworkOptions _networkOptions; + _peerDiscoveryJobProcessor = GetRequiredService(); + _peerPool = GetRequiredService(); + _nodeManager = GetRequiredService(); + _discoveredNodeCacheProvider = GetRequiredService(); + _networkOptions = GetRequiredService>().Value; + } - public PeerDiscoveryJobProcessorTests() - { - _peerDiscoveryJobProcessor = GetRequiredService(); - _peerPool = GetRequiredService(); - _nodeManager = GetRequiredService(); - _discoveredNodeCacheProvider = GetRequiredService(); - _networkOptions = GetRequiredService>().Value; - } + [Fact] + public async Task SendDiscoveryJob_NoNode_Test() + { + var peer = _peerPool.FindPeerByPublicKey("PeerWithNoNode"); + await SendDiscoveryJobAsync(peer); - [Fact] - public async Task SendDiscoveryJob_NoNode_Test() - { - var peer = _peerPool.FindPeerByPublicKey("PeerWithNoNode"); - await SendDiscoveryJobAsync(peer); + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(0); + } - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(0); - } - - [Fact] - public async Task SendDiscoveryJob_SamePubkeyNode_Test() - { - var peer = _peerPool.FindPeerByPublicKey("PeerWithSamePubkeyNode"); - await SendDiscoveryJobAsync(peer); + [Fact] + public async Task SendDiscoveryJob_SamePubkeyNode_Test() + { + var peer = _peerPool.FindPeerByPublicKey("PeerWithSamePubkeyNode"); + await SendDiscoveryJobAsync(peer); - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(0); - } - - [Fact] - public async Task SendDiscoveryJob_UnavailableNode_Test() - { - var peer = _peerPool.FindPeerByPublicKey("PeerWithUnavailableNode"); - await SendDiscoveryJobAsync(peer); + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(0); + } - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(0); - } - - [Fact] - public async Task SendDiscoveryJob_Test() + [Fact] + public async Task SendDiscoveryJob_UnavailableNode_Test() + { + var peer = _peerPool.FindPeerByPublicKey("PeerWithUnavailableNode"); + await SendDiscoveryJobAsync(peer); + + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(0); + } + + [Fact] + public async Task SendDiscoveryJob_Test() + { + var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); + await SendDiscoveryJobAsync(peer); + + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(1); + nodes.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); + } + + [Fact] + public async Task SendDiscoveryJob_NodeExist_Test() + { + var oldNode = new NodeInfo { - var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); - await SendDiscoveryJobAsync(peer); + Endpoint = "192.168.100.100:8003", + Pubkey = ByteString.CopyFromUtf8("OldPubkey") + }; + await _nodeManager.AddNodeAsync(oldNode); + _discoveredNodeCacheProvider.Add(oldNode.Endpoint); + + var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); + await SendDiscoveryJobAsync(peer); + + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(1); + nodes.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); + nodes.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8("192.168.100.100:8003")); + } - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(1); - nodes.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); - } - - [Fact] - public async Task SendDiscoveryJob_NodeExist_Test() + [Fact] + public async Task SendDiscoveryJob_NodeManagerIsFull_LocalAvailable_Test() + { + for (var i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep; i++) { - var oldNode = new NodeInfo + var nodeInfo = new NodeInfo { - Endpoint = "192.168.100.100:8003", - Pubkey = ByteString.CopyFromUtf8("OldPubkey") + Endpoint = "192.168.100.1:800" + i, + Pubkey = ByteString.CopyFromUtf8("pubkey") }; - await _nodeManager.AddNodeAsync(oldNode); - _discoveredNodeCacheProvider.Add(oldNode.Endpoint); - - var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); - await SendDiscoveryJobAsync(peer); - - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(1); - nodes.Nodes[0].Endpoint.ShouldBe("192.168.100.100:8003"); - nodes.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8("192.168.100.100:8003")); + await _nodeManager.AddNodeAsync(nodeInfo); + _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); } - - [Fact] - public async Task SendDiscoveryJob_NodeManagerIsFull_LocalAvailable_Test() - { - for (int i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep; i++) - { - var nodeInfo = new NodeInfo - { - Endpoint = "192.168.100.1:800"+i, - Pubkey = ByteString.CopyFromUtf8("pubkey") - }; - await _nodeManager.AddNodeAsync(nodeInfo); - _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); - } - - var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); - await SendDiscoveryJobAsync(peer); - - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(5); - - var node = await _nodeManager.GetNodeAsync("192.168.100.100:8003"); - node.ShouldBeNull(); - } - - [Fact] - public async Task SendDiscoveryJob_NodeManagerIsFull_LocalUnavailable_Test() - { - for (int i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep; i++) - { - var nodeInfo = new NodeInfo - { - Endpoint = "192.168.100.1:800"+(i+1), - Pubkey = ByteString.CopyFromUtf8("pubkey") - }; - await _nodeManager.AddNodeAsync(nodeInfo); - _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); - } - var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); - await SendDiscoveryJobAsync(peer); + var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); + await SendDiscoveryJobAsync(peer); - var nodes = await _nodeManager.GetRandomNodesAsync(10); - nodes.Nodes.Count.ShouldBe(5); + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(5); - var node = await _nodeManager.GetNodeAsync("192.168.100.100:8003"); - node.ShouldNotBeNull(); + var node = await _nodeManager.GetNodeAsync("192.168.100.100:8003"); + node.ShouldBeNull(); + } - for (int i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep -1; i++) + [Fact] + public async Task SendDiscoveryJob_NodeManagerIsFull_LocalUnavailable_Test() + { + for (var i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep; i++) + { + var nodeInfo = new NodeInfo { - _discoveredNodeCacheProvider.TryTake(out var endpoint); - endpoint.ShouldBe("192.168.100.1:800" + (i + 2)); - } - - _discoveredNodeCacheProvider.TryTake(out var newEndpoint); - newEndpoint.ShouldBe("192.168.100.100:8003"); + Endpoint = "192.168.100.1:800" + (i + 1), + Pubkey = ByteString.CopyFromUtf8("pubkey") + }; + await _nodeManager.AddNodeAsync(nodeInfo); + _discoveredNodeCacheProvider.Add(nodeInfo.Endpoint); } - private async Task SendDiscoveryJobAsync(IPeer peer) + var peer = _peerPool.FindPeerByPublicKey("PeerWithNormalNode"); + await SendDiscoveryJobAsync(peer); + + var nodes = await _nodeManager.GetRandomNodesAsync(10); + nodes.Nodes.Count.ShouldBe(5); + + var node = await _nodeManager.GetNodeAsync("192.168.100.100:8003"); + node.ShouldNotBeNull(); + + for (var i = 0; i < _networkOptions.PeerDiscoveryMaxNodesToKeep - 1; i++) { - await _peerDiscoveryJobProcessor.SendDiscoveryJobAsync(peer); - await _peerDiscoveryJobProcessor.CompleteAsync(); + _discoveredNodeCacheProvider.TryTake(out var endpoint); + endpoint.ShouldBe("192.168.100.1:800" + (i + 2)); } + + _discoveredNodeCacheProvider.TryTake(out var newEndpoint); + newEndpoint.ShouldBe("192.168.100.100:8003"); + } + + private async Task SendDiscoveryJobAsync(IPeer peer) + { + await _peerDiscoveryJobProcessor.SendDiscoveryJobAsync(peer); + await _peerDiscoveryJobProcessor.CompleteAsync(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerInvalidTransactionProviderTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerInvalidTransactionProviderTests.cs index c690bbcebb..73eac0ce6d 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerInvalidTransactionProviderTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerInvalidTransactionProviderTests.cs @@ -1,70 +1,67 @@ using System.Threading.Tasks; -using AElf.OS.Network.Application; -using AElf.OS.Network.Infrastructure; using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerInvalidTransactionProviderTests : NetworkInfrastructureTestBase { - public class PeerInvalidTransactionProviderTests : NetworkInfrastructureTestBase + private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; + + public PeerInvalidTransactionProviderTests() + { + _peerInvalidTransactionProvider = GetRequiredService(); + } + + [Fact] + public void MarkInvalidTransaction_Test() { - private readonly IPeerInvalidTransactionProvider _peerInvalidTransactionProvider; + var host = "127.0.0.1"; + bool markResult; - public PeerInvalidTransactionProviderTests() + _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host).ShouldBe(false); + + for (var i = 0; i < 5; i++) { - _peerInvalidTransactionProvider = GetRequiredService(); + var txId = HashHelper.ComputeFrom(i.ToString()); + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, txId); + markResult.ShouldBeTrue(); } - [Fact] - public void MarkInvalidTransaction_Test() - { - var host = "127.0.0.1"; - bool markResult; - - _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host).ShouldBe(false); - - for (var i = 0; i < 5; i++) - { - var txId = HashHelper.ComputeFrom(i.ToString()); - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, txId); - markResult.ShouldBeTrue(); - } + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("0")); + markResult.ShouldBeTrue(); - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("0")); - markResult.ShouldBeTrue(); + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("5")); + markResult.ShouldBeFalse(); - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("5")); - markResult.ShouldBeFalse(); + markResult = + _peerInvalidTransactionProvider.TryMarkInvalidTransaction("192.168.1.1", HashHelper.ComputeFrom("0")); + markResult.ShouldBeTrue(); - markResult = - _peerInvalidTransactionProvider.TryMarkInvalidTransaction("192.168.1.1", HashHelper.ComputeFrom("0")); - markResult.ShouldBeTrue(); + _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host).ShouldBe(true); - _peerInvalidTransactionProvider.TryRemoveInvalidRecord(host).ShouldBe(true); + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("0")); + markResult.ShouldBeTrue(); + } - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("0")); + [Fact] + public async Task MarkInvalidTransaction_Timeout_Test() + { + var host = "127.0.0.1"; + bool markResult; + for (var i = 0; i < 5; i++) + { + var txId = HashHelper.ComputeFrom(i.ToString()); + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, txId); markResult.ShouldBeTrue(); } - [Fact] - public async Task MarkInvalidTransaction_Timeout_Test() - { - var host = "127.0.0.1"; - bool markResult; - for (var i = 0; i < 5; i++) - { - var txId = HashHelper.ComputeFrom(i.ToString()); - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, txId); - markResult.ShouldBeTrue(); - } - - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("5")); - markResult.ShouldBeFalse(); + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("5")); + markResult.ShouldBeFalse(); - await Task.Delay(1500); + await Task.Delay(1500); - markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("6")); - markResult.ShouldBeTrue(); - } + markResult = _peerInvalidTransactionProvider.TryMarkInvalidTransaction(host, HashHelper.ComputeFrom("6")); + markResult.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolMaxPeersPerIpAddressTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolMaxPeersPerIpAddressTests.cs index 282ca8b4aa..984c1a9756 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolMaxPeersPerIpAddressTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolMaxPeersPerIpAddressTests.cs @@ -4,92 +4,91 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerPoolMaxPeersPerIpAddressTests : NetworkMaxPeersPerIpAddressTestBase { - public class PeerPoolMaxPeersPerIpAddressTests : NetworkMaxPeersPerIpAddressTestBase + private readonly IPeerPool _peerPool; + + public PeerPoolMaxPeersPerIpAddressTests() + { + _peerPool = GetRequiredService(); + } + + [Fact] + public void AddHandshakingPeer_LoopbackAddress_Test() { - private readonly IPeerPool _peerPool; + var handshakingPeerHost = "127.0.0.1"; - public PeerPoolMaxPeersPerIpAddressTests() + for (var i = 0; i < 3; i++) { - _peerPool = GetRequiredService(); + var pubkey = "pubkey" + i; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); + addResult.ShouldBeTrue(); + + var handshakingPeers = _peerPool.GetHandshakingPeers(); + handshakingPeers.ShouldContainKey(handshakingPeerHost); + handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); } + } - [Fact] - public void AddHandshakingPeer_LoopbackAddress_Test() + [Fact] + public void AddHandshakingPeer_OverIpLimit_Test() + { + var handshakingPeerHost = "192.168.100.1"; + + for (var i = 0; i < 2; i++) { - var handshakingPeerHost = "127.0.0.1"; - - for (int i = 0; i < 3; i++) - { - var pubkey = "pubkey" + i; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); - addResult.ShouldBeTrue(); - - var handshakingPeers = _peerPool.GetHandshakingPeers(); - handshakingPeers.ShouldContainKey(handshakingPeerHost); - handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); - } + var pubkey = "pubkey" + i; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); + addResult.ShouldBeTrue(); + + var handshakingPeers = _peerPool.GetHandshakingPeers(); + handshakingPeers.ShouldContainKey(handshakingPeerHost); + handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); } - [Fact] - public void AddHandshakingPeer_OverIpLimit_Test() { - var handshakingPeerHost = "192.168.100.1"; - - for (int i = 0; i < 2; i++) - { - var pubkey = "pubkey" + i; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); - addResult.ShouldBeTrue(); - - var handshakingPeers = _peerPool.GetHandshakingPeers(); - handshakingPeers.ShouldContainKey(handshakingPeerHost); - handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); - } - - { - var pubkey = "pubkey2"; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); - addResult.ShouldBeFalse(); - - var handshakingPeers = _peerPool.GetHandshakingPeers(); - handshakingPeers[handshakingPeerHost].ShouldNotContainKey(pubkey); - } + var pubkey = "pubkey2"; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); + addResult.ShouldBeFalse(); + + var handshakingPeers = _peerPool.GetHandshakingPeers(); + handshakingPeers[handshakingPeerHost].ShouldNotContainKey(pubkey); } + } + + [Fact] + public void AddHandshakingPeer_AlreadyInPeerPool_Test() + { + var handshakingPeerHost = "192.168.100.1"; + + var peerMock = new Mock(); + var peerInfo = new PeerConnectionInfo + { + Pubkey = "PeerPubkey" + }; + AElfPeerEndpointHelper.TryParse("192.168.100.1:8001", out var endpoint); + peerMock.Setup(p => p.RemoteEndpoint).Returns(endpoint); + peerMock.Setup(p => p.Info).Returns(peerInfo); + _peerPool.TryAddPeer(peerMock.Object); - [Fact] - public void AddHandshakingPeer_AlreadyInPeerPool_Test() { - var handshakingPeerHost = "192.168.100.1"; - - var peerMock = new Mock(); - var peerInfo = new PeerConnectionInfo - { - Pubkey = "PeerPubkey", - }; - AElfPeerEndpointHelper.TryParse("192.168.100.1:8001", out var endpoint); - peerMock.Setup(p => p.RemoteEndpoint).Returns(endpoint); - peerMock.Setup(p => p.Info).Returns(peerInfo); - _peerPool.TryAddPeer(peerMock.Object); - - { - var pubkey = "pubkey1"; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); - addResult.ShouldBeTrue(); - - var handshakingPeers = _peerPool.GetHandshakingPeers(); - handshakingPeers.ShouldContainKey(handshakingPeerHost); - handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); - } - { - var pubkey = "pubkey2"; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); - addResult.ShouldBeFalse(); - - var handshakingPeers = _peerPool.GetHandshakingPeers(); - handshakingPeers[handshakingPeerHost].ShouldNotContainKey(pubkey); - } + var pubkey = "pubkey1"; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); + addResult.ShouldBeTrue(); + + var handshakingPeers = _peerPool.GetHandshakingPeers(); + handshakingPeers.ShouldContainKey(handshakingPeerHost); + handshakingPeers[handshakingPeerHost].ShouldContainKey(pubkey); + } + { + var pubkey = "pubkey2"; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, pubkey); + addResult.ShouldBeFalse(); + + var handshakingPeers = _peerPool.GetHandshakingPeers(); + handshakingPeers[handshakingPeerHost].ShouldNotContainKey(pubkey); } } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolNotLimitMaxPeerTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolNotLimitMaxPeerTests.cs index 913029697a..9b7b8a2df5 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolNotLimitMaxPeerTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolNotLimitMaxPeerTests.cs @@ -5,46 +5,45 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerPoolNotLimitMaxPeerTests : NetworkPeerPoolNotLimitMaxPeerTestBase { - public class PeerPoolNotLimitMaxPeerTests : NetworkPeerPoolNotLimitMaxPeerTestBase + private readonly IPeerPool _peerPool; + + public PeerPoolNotLimitMaxPeerTests() { - private readonly IPeerPool _peerPool; + _peerPool = GetRequiredService(); + } - public PeerPoolNotLimitMaxPeerTests() - { - _peerPool = GetRequiredService(); - } + [Fact] + public void IsFull_Test() + { + var peer = CreatePeer(); + _peerPool.TryAddPeer(peer); + _peerPool.PeerCount.ShouldBe(1); + _peerPool.IsFull().ShouldBeFalse(); - [Fact] - public void IsFull_Test() - { - var peer = CreatePeer(); - _peerPool.TryAddPeer(peer); - _peerPool.PeerCount.ShouldBe(1); - _peerPool.IsFull().ShouldBeFalse(); - - peer = CreatePeer(); - _peerPool.TryAddPeer(peer); - _peerPool.PeerCount.ShouldBe(2); - _peerPool.IsFull().ShouldBeFalse(); - } - - private IPeer CreatePeer() + peer = CreatePeer(); + _peerPool.TryAddPeer(peer); + _peerPool.PeerCount.ShouldBe(2); + _peerPool.IsFull().ShouldBeFalse(); + } + + private IPeer CreatePeer() + { + var peerMock = new Mock(); + var pubkey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); + + var peerInfo = new PeerConnectionInfo { - var peerMock = new Mock(); - var pubkey = CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); - - var peerInfo = new PeerConnectionInfo - { - Pubkey = pubkey, - ProtocolVersion = KernelConstants.ProtocolVersion, - ConnectionTime = TimestampHelper.GetUtcNow(), - IsInbound = true - }; - peerMock.Setup(p => p.Info).Returns(peerInfo); - - return peerMock.Object; - } + Pubkey = pubkey, + ProtocolVersion = KernelConstants.ProtocolVersion, + ConnectionTime = TimestampHelper.GetUtcNow(), + IsInbound = true + }; + peerMock.Setup(p => p.Info).Returns(peerInfo); + + return peerMock.Object; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolTests.cs index de8b13a064..fdcd1fad20 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerPoolTests.cs @@ -1,230 +1,224 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Net; -using System.Threading.Tasks; using AElf.Cryptography; using AElf.Kernel; using AElf.OS.Network.Helpers; -using AElf.OS.Network.Infrastructure; using AElf.OS.Network.Protocol.Types; using Moq; using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerPoolTests : NetworkInfrastructureTestBase { - public class PeerPoolTests : NetworkInfrastructureTestBase + private readonly IBlackListedPeerProvider _blackListProvider; + private readonly IPeerPool _peerPool; + + public PeerPoolTests() { - private readonly IPeerPool _peerPool; - private readonly IBlackListedPeerProvider _blackListProvider; + _peerPool = GetRequiredService(); + _blackListProvider = GetRequiredService(); + } - public PeerPoolTests() - { - _peerPool = GetRequiredService(); - _blackListProvider = GetRequiredService(); - } + [Fact] + public void AddBlacklistedPeer_ShouldReturnFalse() + { + var host = "12.34.56.67"; + _blackListProvider.AddHostToBlackList(host, NetworkConstants.DefaultPeerRemovalSeconds); + _peerPool.AddHandshakingPeer(host, "somePubKey").ShouldBeFalse(); + } - [Fact] - public void AddBlacklistedPeer_ShouldReturnFalse() - { - var host = "12.34.56.67"; - _blackListProvider.AddHostToBlackList(host,NetworkConstants.DefaultPeerRemovalSeconds); - _peerPool.AddHandshakingPeer(host, "somePubKey").ShouldBeFalse(); - } + [Fact] + public void IsPeerBlackListed_Test() + { + var host = "12.34.56.67"; + _peerPool.IsPeerBlackListed(host).ShouldBeFalse(); + _blackListProvider.AddHostToBlackList(host, NetworkConstants.DefaultPeerRemovalSeconds); + _peerPool.IsPeerBlackListed(host).ShouldBeTrue(); + } - [Fact] - public void IsPeerBlackListed_Test() - { - var host = "12.34.56.67"; - _peerPool.IsPeerBlackListed(host).ShouldBeFalse(); - _blackListProvider.AddHostToBlackList(host,NetworkConstants.DefaultPeerRemovalSeconds); - _peerPool.IsPeerBlackListed(host).ShouldBeTrue(); - } - - [Fact] - public void QueryPeers_Test() - { - var commonHost = "12.34.56.67"; - string commonPort = "1900"; - string commonEndpoint = commonHost + ":" + commonPort; - - var peer1 = CreatePeer(commonEndpoint); - _peerPool.TryAddPeer(peer1); - var peer2 = CreatePeer(commonEndpoint); - _peerPool.TryAddPeer(peer2); - var peer3 = CreatePeer("12.34.56.64:1900"); - _peerPool.TryAddPeer(peer3); - var peer4 = CreatePeer("12.34.56.61:1900", isReady: false); - _peerPool.TryAddPeer(peer4); - - var peers = _peerPool.GetPeers(); - peers.Count.ShouldBe(3); - - peers = _peerPool.GetPeers(true); - peers.Count.ShouldBe(4); - - peers = _peerPool.GetPeersByHost(commonHost); - peers.Count.ShouldBe(2); - peers.ShouldContain(peer1); - peers.ShouldContain(peer2); - - var peer = _peerPool.FindPeerByEndpoint(peer3.RemoteEndpoint); - peer.ShouldBe(peer3); - - peer = _peerPool.FindPeerByPublicKey(peer3.Info.Pubkey); - peer.ShouldBe(peer3); - } - - [Fact] - public void AddHandshakingPeer_WithSameIp_ShouldAddToList() - { - var commonHost = "12.34.56.64"; - var mockPubkeyOne = "pub1"; - var mockPubkeyTwo = "pub2"; - - var addResult1 =_peerPool.AddHandshakingPeer(commonHost, mockPubkeyOne); - addResult1.ShouldBeTrue(); - var addResult2 = _peerPool.AddHandshakingPeer(commonHost, mockPubkeyTwo); - addResult2.ShouldBeFalse(); - - _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out var peers); - peers.Values.Count.ShouldBe(1); - peers.Values.ShouldContain(mockPubkeyOne); - } - - [Fact] - public void RemoveHandshakingPeer_Test() - { - var commonHost = "12.34.56.64"; - var mockPubkeyOne = "pub1"; - var mockPubkeyTwo = "pub2"; - - _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyOne).ShouldBeFalse(); - - _peerPool.AddHandshakingPeer(commonHost, mockPubkeyOne); - _peerPool.AddHandshakingPeer(commonHost, mockPubkeyTwo); - - _peerPool.RemoveHandshakingPeer(commonHost, "NotExist").ShouldBeFalse(); - _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyOne).ShouldBeTrue(); - _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out _).ShouldBeFalse(); - - // remove last should remove entry - _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyTwo).ShouldBeFalse(); - _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out _).ShouldBeFalse(); - - } - - [Fact] - public void AddedPeer_IsFindable_ByAddressAndPubkey() - { - var peer = CreatePeer(); - _peerPool.TryAddPeer(peer); - - _peerPool.PeerCount.ShouldBe(1); - _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldNotBeNull(); - _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); - } - - [Fact] - public void ReplacePeer_Test() - { - var peer = CreatePeer(); - var otherPeer = CreatePeer(NetworkTestConstants.FakeIpEndpoint, peer.Info.Pubkey); - - _peerPool.TryAddPeer(peer); - - peer.Equals(otherPeer).ShouldBeFalse(); - _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); - - _peerPool.TryReplace(peer.Info.Pubkey, peer, otherPeer); - var replaced = _peerPool.FindPeerByPublicKey(peer.Info.Pubkey); - replaced.ShouldNotBeNull(); - replaced.Equals(otherPeer).ShouldBeTrue(); - } - - [Fact] - public void RemovePeerByPublicKey_ShouldNotBeFindable() - { - var peer = CreatePeer(); - - _peerPool.TryAddPeer(peer); - _peerPool.RemovePeer(peer.Info.Pubkey); - - _peerPool.PeerCount.ShouldBe(0); - _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldBeNull(); - _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldBeNull(); - } - - [Fact] - public void CannotAddPeerTwice() - { - var peer = CreatePeer(); - _peerPool.TryAddPeer(peer); - _peerPool.TryAddPeer(peer).ShouldBeFalse(); - - _peerPool.PeerCount.ShouldBe(1); - _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldNotBeNull(); - _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); - } - - [Fact] - public void AddPeer_MultipleTimes_Test() - { - var peer = CreatePeer("127.0.0.1:1000"); - _peerPool.TryAddPeer(peer); - _peerPool.PeerCount.ShouldBe(1); - _peerPool.IsFull().ShouldBeFalse(); - - peer = CreatePeer("127.0.0.1:2000"); - _peerPool.TryAddPeer(peer); - _peerPool.PeerCount.ShouldBe(2); - _peerPool.IsFull().ShouldBeTrue(); - } - - [Fact] - public void AddHandshakingPeer_PeerPoolIsFull_ShouldReturnFalse() - { - var peer1 = CreatePeer("127.0.0.1:8801"); - _peerPool.TryAddPeer(peer1); - var peer2 = CreatePeer("127.0.0.1:8802"); - _peerPool.TryAddPeer(peer2); - - var handshakingPeerHost = "192.168.100.100"; - var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, "pubkey"); - addResult.ShouldBeFalse(); - _peerPool.GetHandshakingPeers().ShouldNotContainKey(handshakingPeerHost); - } - - private static IPeer CreatePeer(string ipEndpoint = NetworkTestConstants.FakeIpEndpoint, string pubKey = null, - bool isReady = true) - { - var peerMock = new Mock(); - var pubkey = pubKey ?? CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); + [Fact] + public void QueryPeers_Test() + { + var commonHost = "12.34.56.67"; + var commonPort = "1900"; + var commonEndpoint = commonHost + ":" + commonPort; + + var peer1 = CreatePeer(commonEndpoint); + _peerPool.TryAddPeer(peer1); + var peer2 = CreatePeer(commonEndpoint); + _peerPool.TryAddPeer(peer2); + var peer3 = CreatePeer("12.34.56.64:1900"); + _peerPool.TryAddPeer(peer3); + var peer4 = CreatePeer("12.34.56.61:1900", isReady: false); + _peerPool.TryAddPeer(peer4); + + var peers = _peerPool.GetPeers(); + peers.Count.ShouldBe(3); + + peers = _peerPool.GetPeers(true); + peers.Count.ShouldBe(4); + + peers = _peerPool.GetPeersByHost(commonHost); + peers.Count.ShouldBe(2); + peers.ShouldContain(peer1); + peers.ShouldContain(peer2); + + var peer = _peerPool.FindPeerByEndpoint(peer3.RemoteEndpoint); + peer.ShouldBe(peer3); + + peer = _peerPool.FindPeerByPublicKey(peer3.Info.Pubkey); + peer.ShouldBe(peer3); + } - var peerInfo = new PeerConnectionInfo - { - Pubkey = pubkey, - ProtocolVersion = KernelConstants.ProtocolVersion, - ConnectionTime = TimestampHelper.GetUtcNow(), - IsInbound = true - }; + [Fact] + public void AddHandshakingPeer_WithSameIp_ShouldAddToList() + { + var commonHost = "12.34.56.64"; + var mockPubkeyOne = "pub1"; + var mockPubkeyTwo = "pub2"; + + var addResult1 = _peerPool.AddHandshakingPeer(commonHost, mockPubkeyOne); + addResult1.ShouldBeTrue(); + var addResult2 = _peerPool.AddHandshakingPeer(commonHost, mockPubkeyTwo); + addResult2.ShouldBeFalse(); + + _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out var peers); + peers.Values.Count.ShouldBe(1); + peers.Values.ShouldContain(mockPubkeyOne); + } - var endpoint = ParseEndPoint(ipEndpoint); + [Fact] + public void RemoveHandshakingPeer_Test() + { + var commonHost = "12.34.56.64"; + var mockPubkeyOne = "pub1"; + var mockPubkeyTwo = "pub2"; + + _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyOne).ShouldBeFalse(); - peerMock.Setup(p => p.RemoteEndpoint).Returns(endpoint); - peerMock.Setup(p => p.Info).Returns(peerInfo); - peerMock.Setup(p => p.IsReady).Returns(isReady); + _peerPool.AddHandshakingPeer(commonHost, mockPubkeyOne); + _peerPool.AddHandshakingPeer(commonHost, mockPubkeyTwo); - return peerMock.Object; - } + _peerPool.RemoveHandshakingPeer(commonHost, "NotExist").ShouldBeFalse(); + _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyOne).ShouldBeTrue(); + _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out _).ShouldBeFalse(); + + // remove last should remove entry + _peerPool.RemoveHandshakingPeer(commonHost, mockPubkeyTwo).ShouldBeFalse(); + _peerPool.GetHandshakingPeers().TryGetValue(commonHost, out _).ShouldBeFalse(); + } - private static DnsEndPoint ParseEndPoint(string ipEndpoint) + [Fact] + public void AddedPeer_IsFindable_ByAddressAndPubkey() + { + var peer = CreatePeer(); + _peerPool.TryAddPeer(peer); + + _peerPool.PeerCount.ShouldBe(1); + _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldNotBeNull(); + _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); + } + + [Fact] + public void ReplacePeer_Test() + { + var peer = CreatePeer(); + var otherPeer = CreatePeer(NetworkTestConstants.FakeIpEndpoint, peer.Info.Pubkey); + + _peerPool.TryAddPeer(peer); + + peer.Equals(otherPeer).ShouldBeFalse(); + _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); + + _peerPool.TryReplace(peer.Info.Pubkey, peer, otherPeer); + var replaced = _peerPool.FindPeerByPublicKey(peer.Info.Pubkey); + replaced.ShouldNotBeNull(); + replaced.Equals(otherPeer).ShouldBeTrue(); + } + + [Fact] + public void RemovePeerByPublicKey_ShouldNotBeFindable() + { + var peer = CreatePeer(); + + _peerPool.TryAddPeer(peer); + _peerPool.RemovePeer(peer.Info.Pubkey); + + _peerPool.PeerCount.ShouldBe(0); + _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldBeNull(); + _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldBeNull(); + } + + [Fact] + public void CannotAddPeerTwice() + { + var peer = CreatePeer(); + _peerPool.TryAddPeer(peer); + _peerPool.TryAddPeer(peer).ShouldBeFalse(); + + _peerPool.PeerCount.ShouldBe(1); + _peerPool.FindPeerByEndpoint(peer.RemoteEndpoint).ShouldNotBeNull(); + _peerPool.FindPeerByPublicKey(peer.Info.Pubkey).ShouldNotBeNull(); + } + + [Fact] + public void AddPeer_MultipleTimes_Test() + { + var peer = CreatePeer("127.0.0.1:1000"); + _peerPool.TryAddPeer(peer); + _peerPool.PeerCount.ShouldBe(1); + _peerPool.IsFull().ShouldBeFalse(); + + peer = CreatePeer("127.0.0.1:2000"); + _peerPool.TryAddPeer(peer); + _peerPool.PeerCount.ShouldBe(2); + _peerPool.IsFull().ShouldBeTrue(); + } + + [Fact] + public void AddHandshakingPeer_PeerPoolIsFull_ShouldReturnFalse() + { + var peer1 = CreatePeer("127.0.0.1:8801"); + _peerPool.TryAddPeer(peer1); + var peer2 = CreatePeer("127.0.0.1:8802"); + _peerPool.TryAddPeer(peer2); + + var handshakingPeerHost = "192.168.100.100"; + var addResult = _peerPool.AddHandshakingPeer(handshakingPeerHost, "pubkey"); + addResult.ShouldBeFalse(); + _peerPool.GetHandshakingPeers().ShouldNotContainKey(handshakingPeerHost); + } + + private static IPeer CreatePeer(string ipEndpoint = NetworkTestConstants.FakeIpEndpoint, string pubKey = null, + bool isReady = true) + { + var peerMock = new Mock(); + var pubkey = pubKey ?? CryptoHelper.GenerateKeyPair().PublicKey.ToHex(); + + var peerInfo = new PeerConnectionInfo { - if (!AElfPeerEndpointHelper.TryParse(ipEndpoint, out var endpoint)) - throw new Exception($"Endpoint {ipEndpoint} could not be parsed."); + Pubkey = pubkey, + ProtocolVersion = KernelConstants.ProtocolVersion, + ConnectionTime = TimestampHelper.GetUtcNow(), + IsInbound = true + }; + + var endpoint = ParseEndPoint(ipEndpoint); + + peerMock.Setup(p => p.RemoteEndpoint).Returns(endpoint); + peerMock.Setup(p => p.Info).Returns(peerInfo); + peerMock.Setup(p => p.IsReady).Returns(isReady); + + return peerMock.Object; + } + + private static DnsEndPoint ParseEndPoint(string ipEndpoint) + { + if (!AElfPeerEndpointHelper.TryParse(ipEndpoint, out var endpoint)) + throw new Exception($"Endpoint {ipEndpoint} could not be parsed."); - return endpoint; - } + return endpoint; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerReconnectionStateProviderTests.cs b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerReconnectionStateProviderTests.cs index bc716b4e6f..6ff9737fac 100644 --- a/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerReconnectionStateProviderTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Infrastructure/PeerReconnectionStateProviderTests.cs @@ -1,71 +1,69 @@ using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.OS.Network.Infrastructure; -using AElf.Sdk.CSharp; using Shouldly; using Xunit; -namespace AElf.OS.Network.Infrastructure +namespace AElf.OS.Network.Infrastructure; + +public class PeerReconnectionStateProviderTests : NetworkInfrastructureTestBase { - public class PeerReconnectionStateProviderTests : NetworkInfrastructureTestBase + private readonly IPeerReconnectionStateProvider _reconnectionProvider; + + public PeerReconnectionStateProviderTests() { - private readonly IPeerReconnectionStateProvider _reconnectionProvider; + _reconnectionProvider = GetRequiredService(); + } - public PeerReconnectionStateProviderTests() - { - _reconnectionProvider = GetRequiredService(); - } - - [Fact] - public void AddReconnectingPeer_Test() - { - var endpoint = "127.0.0.1:5677"; - var utcNow = TimestampHelper.GetUtcNow(); + [Fact] + public void AddReconnectingPeer_Test() + { + var endpoint = "127.0.0.1:5677"; + var utcNow = TimestampHelper.GetUtcNow(); - _reconnectionProvider - .AddReconnectingPeer(endpoint, new ReconnectingPeer {Endpoint = endpoint, NextAttempt = utcNow}) - .ShouldBeTrue(); - - var reconnectingPeer = _reconnectionProvider.GetReconnectingPeer(endpoint); - reconnectingPeer.Endpoint.ShouldBe(endpoint); - reconnectingPeer.NextAttempt.ShouldBe(utcNow); - - _reconnectionProvider - .AddReconnectingPeer(endpoint, new ReconnectingPeer {Endpoint = endpoint, NextAttempt = utcNow}) - .ShouldBeFalse(); - } + _reconnectionProvider + .AddReconnectingPeer(endpoint, new ReconnectingPeer { Endpoint = endpoint, NextAttempt = utcNow }) + .ShouldBeTrue(); + + var reconnectingPeer = _reconnectionProvider.GetReconnectingPeer(endpoint); + reconnectingPeer.Endpoint.ShouldBe(endpoint); + reconnectingPeer.NextAttempt.ShouldBe(utcNow); + + _reconnectionProvider + .AddReconnectingPeer(endpoint, new ReconnectingPeer { Endpoint = endpoint, NextAttempt = utcNow }) + .ShouldBeFalse(); + } - [Fact] - public void GetPeersReadyForReconnection_Test() - { - var endpoint1 = "127.0.0.1:5671"; - var utcNow1 = TimestampHelper.GetUtcNow(); - _reconnectionProvider - .AddReconnectingPeer(endpoint1, new ReconnectingPeer {Endpoint = endpoint1, NextAttempt = utcNow1}); - - var endpoint2 = "127.0.0.1:5672"; - var utcNow2 = TimestampHelper.GetUtcNow().AddMinutes(1); - _reconnectionProvider - .AddReconnectingPeer(endpoint2, new ReconnectingPeer {Endpoint = endpoint2, NextAttempt = utcNow2}); - - _reconnectionProvider.GetPeersReadyForReconnection(null).Count.ShouldBe(2); - _reconnectionProvider.GetPeersReadyForReconnection(utcNow1.AddSeconds(1)).Count.ShouldBe(1); - _reconnectionProvider.GetPeersReadyForReconnection(utcNow2.AddSeconds(1)).Count.ShouldBe(2); - } + [Fact] + public void GetPeersReadyForReconnection_Test() + { + var endpoint1 = "127.0.0.1:5671"; + var utcNow1 = TimestampHelper.GetUtcNow(); + _reconnectionProvider + .AddReconnectingPeer(endpoint1, new ReconnectingPeer { Endpoint = endpoint1, NextAttempt = utcNow1 }); + + var endpoint2 = "127.0.0.1:5672"; + var utcNow2 = TimestampHelper.GetUtcNow().AddMinutes(1); + _reconnectionProvider + .AddReconnectingPeer(endpoint2, new ReconnectingPeer { Endpoint = endpoint2, NextAttempt = utcNow2 }); + + _reconnectionProvider.GetPeersReadyForReconnection(null).Count.ShouldBe(2); + _reconnectionProvider.GetPeersReadyForReconnection(utcNow1.AddSeconds(1)).Count.ShouldBe(1); + _reconnectionProvider.GetPeersReadyForReconnection(utcNow2.AddSeconds(1)).Count.ShouldBe(2); + } + + [Fact] + public void RemoveReconnectionPeer_Test() + { + var endpoint = "127.0.0.1:5677"; + var utcNow = TimestampHelper.GetUtcNow(); - [Fact] - public void RemoveReconnectionPeer_Test() - { - var endpoint = "127.0.0.1:5677"; - var utcNow = TimestampHelper.GetUtcNow(); + _reconnectionProvider.AddReconnectingPeer(endpoint, + new ReconnectingPeer { Endpoint = endpoint, NextAttempt = utcNow }); + _reconnectionProvider.RemoveReconnectionPeer(endpoint).ShouldBeTrue(); - _reconnectionProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer { Endpoint = endpoint, NextAttempt = utcNow }); - _reconnectionProvider.RemoveReconnectionPeer(endpoint).ShouldBeTrue(); + _reconnectionProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); + _reconnectionProvider.GetPeersReadyForReconnection(utcNow.AddSeconds(1)).Count.ShouldBe(0); - _reconnectionProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); - _reconnectionProvider.GetPeersReadyForReconnection(utcNow.AddSeconds(1)).Count.ShouldBe(0); - - _reconnectionProvider.RemoveReconnectionPeer(endpoint).ShouldBeFalse(); - } + _reconnectionProvider.RemoveReconnectionPeer(endpoint).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestBase.cs b/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestBase.cs index f43cb81a74..877f4d00cd 100644 --- a/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestBase.cs +++ b/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestBase.cs @@ -1,20 +1,15 @@ using AElf.TestBase; -using Volo.Abp.Modularity; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public class NetworkInfrastructureTestBase : AElfIntegratedTest +{ +} + +public class NetworkMaxPeersPerIpAddressTestBase : AElfIntegratedTest +{ +} + +public class NetworkPeerPoolNotLimitMaxPeerTestBase : AElfIntegratedTest { - public class NetworkInfrastructureTestBase : AElfIntegratedTest - { - - } - - public class NetworkMaxPeersPerIpAddressTestBase : AElfIntegratedTest - { - - } - - public class NetworkPeerPoolNotLimitMaxPeerTestBase : AElfIntegratedTest - { - - } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestModule.cs b/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestModule.cs index 977861db42..5c00349659 100644 --- a/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/NetworkInfrastructureTestModule.cs @@ -7,61 +7,57 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreTestAElfModule))] +public class NetworkInfrastructureTestModule : AElfModule { - [DependsOn(typeof(OSCoreTestAElfModule))] - public class NetworkInfrastructureTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o=> - { - o.MaxPeers = 2; - o.MaxPeersPerIpAddress = 1; - }); + o.MaxPeers = 2; + o.MaxPeersPerIpAddress = 1; + }); - var services = context.Services; + var services = context.Services; - services.AddSingleton(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetChainAsync()).Returns( - Task.FromResult(new Chain - { - BestChainHash = HashHelper.ComputeFrom("best"), - BestChainHeight = 10 - })); - mockService.Setup(m => m.GetBlockHeaderByHashAsync(It.IsAny())).Returns( - Task.FromResult(new BlockHeader( - ))); + services.AddSingleton(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetChainAsync()).Returns( + Task.FromResult(new Chain + { + BestChainHash = HashHelper.ComputeFrom("best"), + BestChainHeight = 10 + })); + mockService.Setup(m => m.GetBlockHeaderByHashAsync(It.IsAny())).Returns( + Task.FromResult(new BlockHeader( + ))); - return mockService.Object; - }); - } + return mockService.Object; + }); } +} - [DependsOn(typeof(NetworkInfrastructureTestModule))] - public class NetworkMaxPeersPerIpAddressTestModule : AElfModule +[DependsOn(typeof(NetworkInfrastructureTestModule))] +public class NetworkMaxPeersPerIpAddressTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o => - { - o.MaxPeers = 2; - o.MaxPeersPerIpAddress = 2; - }); - } + o.MaxPeers = 2; + o.MaxPeersPerIpAddress = 2; + }); } - - [DependsOn(typeof(NetworkInfrastructureTestModule))] - public class NetworkPeerPoolNotLimitMaxPeerTestModule : AElfModule +} + +[DependsOn(typeof(NetworkInfrastructureTestModule))] +public class NetworkPeerPoolNotLimitMaxPeerTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => - { - o.MaxPeers = 0; - }); - } + Configure(o => { o.MaxPeers = 0; }); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/NetworkServiceTestModule.cs b/test/AElf.OS.Core.Tests/Network/NetworkServiceTestModule.cs index 08cef86cc4..822f90164a 100644 --- a/test/AElf.OS.Core.Tests/Network/NetworkServiceTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/NetworkServiceTestModule.cs @@ -4,11 +4,8 @@ using System.Threading.Tasks; using AElf.Kernel; using AElf.Kernel.Consensus.Application; -using AElf.Kernel.SmartContract; using AElf.Modularity; -using AElf.OS.Helpers; using AElf.OS.Network.Application; -using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; using AElf.OS.Network.Protocol.Types; using AElf.Types; @@ -18,154 +15,154 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreTestAElfModule))] +public class NetworkServiceTestModule : AElfModule { - [DependsOn(typeof(OSCoreTestAElfModule))] - public class NetworkServiceTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(); + + context.Services.AddSingleton(); + context.Services.AddTransient(o => Mock.Of()); + context.Services.AddTransient(o => { - context.Services.AddSingleton(); - - context.Services.AddSingleton(); - context.Services.AddTransient(o => Mock.Of()); - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(s => s.ConnectAsync(It.IsAny())).ReturnsAsync(true); - - return mockService.Object; - }); - } + var mockService = new Mock(); + mockService.Setup(s => s.ConnectAsync(It.IsAny())).ReturnsAsync(true); + + return mockService.Object; + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var peerPool = context.ServiceProvider.GetRequiredService(); + var osTestHelper = context.ServiceProvider.GetRequiredService(); - public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var peerPool = context.ServiceProvider.GetRequiredService(); - var osTestHelper = context.ServiceProvider.GetRequiredService(); - - { - var normalPeer = new Mock(); - normalPeer.Setup(m => m.RemoteEndpoint).Returns(new DnsEndPoint("192.168.100.200", 5000)); - var blockWithTransactions = osTestHelper.GenerateBlockWithTransactions(Hash.Empty, 10); - normalPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "NormalPeer", ConnectionTime = TimestampHelper.GetUtcNow()}); - normalPeer.Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny())) - .Returns((h, cnt) => Task.FromResult(new List())); - normalPeer.Setup(p => p.IsReady).Returns(true); - normalPeer.Setup(p => p.GetBlockByHashAsync(It.Is(h => h == HashHelper.ComputeFrom("bHash1")))) - .Returns(h => Task.FromResult(blockWithTransactions)); - normalPeer.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList + var normalPeer = new Mock(); + normalPeer.Setup(m => m.RemoteEndpoint).Returns(new DnsEndPoint("192.168.100.200", 5000)); + var blockWithTransactions = osTestHelper.GenerateBlockWithTransactions(Hash.Empty, 10); + normalPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "NormalPeer", ConnectionTime = TimestampHelper.GetUtcNow() }); + normalPeer.Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny())) + .Returns((h, cnt) => Task.FromResult(new List())); + normalPeer.Setup(p => p.IsReady).Returns(true); + normalPeer.Setup(p => p.GetBlockByHashAsync(It.Is(h => h == HashHelper.ComputeFrom("bHash1")))) + .Returns(h => Task.FromResult(blockWithTransactions)); + normalPeer.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList + { + Nodes = { - Nodes = + new NodeInfo { - new NodeInfo - { - Endpoint = "http://192.168.100.88:8000", - Pubkey = ByteString.CopyFromUtf8("p2") - } + Endpoint = "http://192.168.100.88:8000", + Pubkey = ByteString.CopyFromUtf8("p2") } - })); - - peerPool.TryAddPeer(normalPeer.Object); - } - - { - var failedPeerPeer = new Mock(); - failedPeerPeer.Setup(p => p.RemoteEndpoint).Returns(new DnsEndPoint("192.168.100.400", 80)); - failedPeerPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "FailedPeer", ConnectionTime = TimestampHelper.GetUtcNow()}); - failedPeerPeer.Setup(p => p.IsInvalid).Returns(true); - failedPeerPeer.Setup(p => p.GetBlockByHashAsync(It.IsAny())).Throws(new NetworkException()); - failedPeerPeer.Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny())).Throws(new NetworkException()); - peerPool.TryAddPeer(failedPeerPeer.Object); - } + } + })); + + peerPool.TryAddPeer(normalPeer.Object); } + + { + var failedPeerPeer = new Mock(); + failedPeerPeer.Setup(p => p.RemoteEndpoint).Returns(new DnsEndPoint("192.168.100.400", 80)); + failedPeerPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "FailedPeer", ConnectionTime = TimestampHelper.GetUtcNow() }); + failedPeerPeer.Setup(p => p.IsInvalid).Returns(true); + failedPeerPeer.Setup(p => p.GetBlockByHashAsync(It.IsAny())).Throws(new NetworkException()); + failedPeerPeer.Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny())) + .Throws(new NetworkException()); + peerPool.TryAddPeer(failedPeerPeer.Object); + } + } +} + +[DependsOn(typeof(NetworkServiceTestModule))] +public class NetworkServicePropagationTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var testContext = new NetworkServicePropagationTestContext(); + var aelfNetworkServer = new Mock(); + testContext.MockAElfNetworkServer = aelfNetworkServer; + + context.Services.AddSingleton(aelfNetworkServer.Object); + context.Services.AddSingleton(testContext); + context.Services.AddTransient(o => Mock.Of()); } - [DependsOn(typeof(NetworkServiceTestModule))] - public class NetworkServicePropagationTestModule : AElfModule + public override void OnApplicationInitialization(ApplicationInitializationContext context) { - private class KnownHashContainer + var peerPool = context.ServiceProvider.GetRequiredService(); + var testContext = context.ServiceProvider.GetRequiredService(); + for (var i = 0; i < 3; i++) { - private readonly List _knownHashes = new List(); - public bool TryAdd(Hash hash) - { - if (HasHash(hash)) - return false; + var peer = new Mock(); + var knownBlockHashes = new KnownHashContainer(); + var knownTransactionHashes = new KnownHashContainer(); + + peer.Setup(p => p.Info).Returns(new PeerConnectionInfo { Pubkey = "Pubkey" + i }); + peer.Setup(p => p.IsReady).Returns(true); + peer.Setup(p => p.TryAddKnownBlock(It.IsAny())) + .Returns(blockHash => knownBlockHashes.TryAdd(blockHash)); + peer.Setup(p => p.KnowsBlock(It.IsAny())) + .Returns(blockHash => knownBlockHashes.HasHash(blockHash)); + + peer.Setup(p => p.TryAddKnownTransaction(It.IsAny())) + .Returns(txHash => knownTransactionHashes.TryAdd(txHash)); + peer.Setup(p => p.KnowsTransaction(It.IsAny())) + .Returns(txHash => knownTransactionHashes.HasHash(txHash)); + SetupBroadcastCallbacks(peer); + + peerPool.TryAddPeer(peer.Object); + testContext.MockedPeers.Add(peer); + } + } - _knownHashes.Add(hash); + private void SetupBroadcastCallbacks(Mock peerMock) + { + // set up the mock to execute the broadcast callbacks - return true; - } + peerMock + .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) + .Callback>((block, action) => action.Invoke(null)); - public bool HasHash(Hash hash) - { - return _knownHashes.Contains(hash); - } - } + peerMock + .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) + .Callback>((announce, action) => action.Invoke(null)); - public override void ConfigureServices(ServiceConfigurationContext context) - { - var testContext = new NetworkServicePropagationTestContext(); - var aelfNetworkServer = new Mock(); - testContext.MockAElfNetworkServer = aelfNetworkServer; + peerMock + .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) + .Callback>((transaction, action) => action.Invoke(null)); + } - context.Services.AddSingleton(aelfNetworkServer.Object); - context.Services.AddSingleton(testContext); - context.Services.AddTransient(o => Mock.Of()); - } - - public override void OnApplicationInitialization(ApplicationInitializationContext context) + private class KnownHashContainer + { + private readonly List _knownHashes = new(); + + public bool TryAdd(Hash hash) { - var peerPool = context.ServiceProvider.GetRequiredService(); - var testContext = context.ServiceProvider.GetRequiredService(); - for (var i = 0; i < 3; i++) - { - var peer = new Mock(); - var knownBlockHashes = new KnownHashContainer(); - var knownTransactionHashes = new KnownHashContainer(); - - peer.Setup(p => p.Info).Returns(new PeerConnectionInfo {Pubkey = "Pubkey" + i.ToString()}); - peer.Setup(p => p.IsReady).Returns(true); - peer.Setup(p => p.TryAddKnownBlock(It.IsAny())) - .Returns(blockHash => knownBlockHashes.TryAdd(blockHash)); - peer.Setup(p => p.KnowsBlock(It.IsAny())) - .Returns(blockHash => knownBlockHashes.HasHash(blockHash)); - - peer.Setup(p => p.TryAddKnownTransaction(It.IsAny())) - .Returns(txHash => knownTransactionHashes.TryAdd(txHash)); - peer.Setup(p => p.KnowsTransaction(It.IsAny())) - .Returns(txHash => knownTransactionHashes.HasHash(txHash)); - SetupBroadcastCallbacks(peer); - - peerPool.TryAddPeer(peer.Object); - testContext.MockedPeers.Add(peer); - } + if (HasHash(hash)) + return false; + + _knownHashes.Add(hash); + + return true; } - private void SetupBroadcastCallbacks(Mock peerMock) + public bool HasHash(Hash hash) { - // set up the mock to execute the broadcast callbacks - - peerMock - .Setup(p => p.EnqueueBlock(It.IsAny(), It.IsAny>())) - .Callback>((block, action) => action.Invoke(null)); - - peerMock - .Setup(p => p.EnqueueAnnouncement(It.IsAny(), It.IsAny>())) - .Callback>((announce, action) => action.Invoke(null)); - - peerMock - .Setup(p => p.EnqueueTransaction(It.IsAny(), It.IsAny>())) - .Callback>((transaction, action) => action.Invoke(null)); + return _knownHashes.Contains(hash); } } +} - public class NetworkServicePropagationTestContext - { - public List> MockedPeers = new List>(); - - public Mock MockAElfNetworkServer = new Mock(); - } +public class NetworkServicePropagationTestContext +{ + public Mock MockAElfNetworkServer = new(); + public List> MockedPeers = new(); } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/NetworkTestConstants.cs b/test/AElf.OS.Core.Tests/Network/NetworkTestConstants.cs index 7437603ffe..30d09f5aac 100644 --- a/test/AElf.OS.Core.Tests/Network/NetworkTestConstants.cs +++ b/test/AElf.OS.Core.Tests/Network/NetworkTestConstants.cs @@ -1,22 +1,22 @@ -using System.Net; +namespace AElf.OS.Network; -namespace AElf.OS.Network +public class NetworkTestConstants { - public class NetworkTestConstants - { - public const string FakeIpEndpoint = "127.0.0.1:666"; - public const string FakeIpEndpoint2 = "127.0.0.1:1000"; - - public const string DialExceptionIpEndpoint = "127.0.0.1:1234"; - public const string HandshakeWithNetExceptionIp = "127.0.0.1:1235"; - public const string BadHandshakeIp = "127.0.0.1:1236"; - public const string HandshakeWithDataExceptionIp = "127.0.0.1:1237"; - - public const string GoodPeerEndpoint = "127.0.0.1:1335"; - - public const int DefaultChainId = 1; - - public const string FakePubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; - public const string FakePubkey2 = "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; - } + public const string FakeIpEndpoint = "127.0.0.1:666"; + public const string FakeIpEndpoint2 = "127.0.0.1:1000"; + + public const string DialExceptionIpEndpoint = "127.0.0.1:1234"; + public const string HandshakeWithNetExceptionIp = "127.0.0.1:1235"; + public const string BadHandshakeIp = "127.0.0.1:1236"; + public const string HandshakeWithDataExceptionIp = "127.0.0.1:1237"; + + public const string GoodPeerEndpoint = "127.0.0.1:1335"; + + public const int DefaultChainId = 1; + + public const string FakePubkey = + "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; + + public const string FakePubkey2 = + "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/OSCoreHandshakeTestModule.cs b/test/AElf.OS.Core.Tests/Network/OSCoreHandshakeTestModule.cs index 36fd096540..c380ef3d3f 100644 --- a/test/AElf.OS.Core.Tests/Network/OSCoreHandshakeTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/OSCoreHandshakeTestModule.cs @@ -6,26 +6,25 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreWithChainTestAElfModule))] +public class OSCoreHandshakeTestModule : AElfModule { - [DependsOn(typeof(OSCoreWithChainTestAElfModule))] - public class OSCoreHandshakeTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var authorizedKeyPair = CryptoHelper.GenerateKeyPair(); + + Configure(o => { - var authorizedKeyPair = CryptoHelper.GenerateKeyPair(); + // for convenience when testing self connection the local key-pair will be part of the authorized. + var accountService = context.Services.GetRequiredServiceLazy().Value; + var pubkey = AsyncHelper.RunSync(async () => (await accountService.GetPublicKeyAsync()).ToHex()); + + o.AuthorizedPeers = AuthorizedPeers.Authorized; + o.AuthorizedKeys = new List { authorizedKeyPair.PublicKey.ToHex(), pubkey }; + }); - Configure(o => - { - // for convenience when testing self connection the local key-pair will be part of the authorized. - var accountService = context.Services.GetRequiredServiceLazy().Value; - var pubkey = AsyncHelper.RunSync(async () => (await accountService.GetPublicKeyAsync()).ToHex()); - - o.AuthorizedPeers = AuthorizedPeers.Authorized; - o.AuthorizedKeys = new List {authorizedKeyPair.PublicKey.ToHex(), pubkey}; - }); - - context.Services.AddSingleton(new TestPeerKeyProvider { AuthorizedKey = authorizedKeyPair }); - } + context.Services.AddSingleton(new TestPeerKeyProvider { AuthorizedKey = authorizedKeyPair }); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/OSCoreSyncFlagTestModule.cs b/test/AElf.OS.Core.Tests/Network/OSCoreSyncFlagTestModule.cs index e438ddf504..eee681c986 100644 --- a/test/AElf.OS.Core.Tests/Network/OSCoreSyncFlagTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/OSCoreSyncFlagTestModule.cs @@ -5,28 +5,27 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreWithChainTestAElfModule))] +public class OSCoreSyncFlagTestModule : AElfModule { - [DependsOn(typeof(OSCoreWithChainTestAElfModule))] - public class OSCoreSyncFlagTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { o.InitialSyncOffset = 5; }); + + + context.Services.AddSingleton(o => { - Configure(o => { o.InitialSyncOffset = 5; }); + var peerList = new List(); + + var peerPoolMock = new Mock(); + peerPoolMock.Setup(p => p.GetPeers(It.IsAny())) + .Returns(peerList); + peerPoolMock.Setup(p => p.TryAddPeer(It.IsAny())) + .Callback(peer => peerList.Add(peer)); - - context.Services.AddSingleton(o => - { - var peerList = new List(); - - var peerPoolMock = new Mock(); - peerPoolMock.Setup(p => p.GetPeers(It.IsAny())) - .Returns(peerList); - peerPoolMock.Setup(p => p.TryAddPeer(It.IsAny())) - .Callback(peer => peerList.Add(peer)); - - return peerPoolMock.Object; - }); - } + return peerPoolMock.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/PeerDiscoveryTestModule.cs b/test/AElf.OS.Core.Tests/Network/PeerDiscoveryTestModule.cs index eb1b31b5e5..10da38ffb1 100644 --- a/test/AElf.OS.Core.Tests/Network/PeerDiscoveryTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/PeerDiscoveryTestModule.cs @@ -13,115 +13,114 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreTestAElfModule))] +public class PeerDiscoveryTestModule : AElfModule { - [DependsOn(typeof(OSCoreTestAElfModule))] - public class PeerDiscoveryTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(o => { - context.Services.AddSingleton(o => - { - var networkServer = new Mock(); + var networkServer = new Mock(); - networkServer.Setup(s => s.CheckEndpointAvailableAsync(It.IsAny())).Returns( - endpoint => - { - if (endpoint.Port == 8001) - return Task.FromResult(false); + networkServer.Setup(s => s.CheckEndpointAvailableAsync(It.IsAny())).Returns( + endpoint => + { + if (endpoint.Port == 8001) + return Task.FromResult(false); - return Task.FromResult(true); - }); + return Task.FromResult(true); + }); - return networkServer.Object; - }); - } + return networkServer.Object; + }); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var peerPool = context.ServiceProvider.GetRequiredService(); - var accountService = context.ServiceProvider.GetRequiredService(); - var pubkey = AsyncHelper.RunSync(accountService.GetPublicKeyAsync).ToHex(); + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var peerPool = context.ServiceProvider.GetRequiredService(); + var accountService = context.ServiceProvider.GetRequiredService(); + var pubkey = AsyncHelper.RunSync(accountService.GetPublicKeyAsync).ToHex(); - { - var peerWithNoNode = new Mock(); - peerWithNoNode.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "PeerWithNoNode", ConnectionTime = TimestampHelper.GetUtcNow()}); - peerWithNoNode.Setup(p => p.IsReady).Returns(true); - peerWithNoNode.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.88.100", 8801)); - peerWithNoNode.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList())); + { + var peerWithNoNode = new Mock(); + peerWithNoNode.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "PeerWithNoNode", ConnectionTime = TimestampHelper.GetUtcNow() }); + peerWithNoNode.Setup(p => p.IsReady).Returns(true); + peerWithNoNode.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.88.100", 8801)); + peerWithNoNode.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList())); - peerPool.TryAddPeer(peerWithNoNode.Object); - } + peerPool.TryAddPeer(peerWithNoNode.Object); + } - { - var peerWithUnavailableNode = new Mock(); - peerWithUnavailableNode.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "PeerWithUnavailableNode", ConnectionTime = TimestampHelper.GetUtcNow()}); - peerWithUnavailableNode.Setup(p => p.IsReady).Returns(true); - peerWithUnavailableNode.Setup(p => p.RemoteEndpoint) - .Returns(new AElfPeerEndpoint("192.168.88.100", 8802)); - peerWithUnavailableNode.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList + { + var peerWithUnavailableNode = new Mock(); + peerWithUnavailableNode.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "PeerWithUnavailableNode", ConnectionTime = TimestampHelper.GetUtcNow() }); + peerWithUnavailableNode.Setup(p => p.IsReady).Returns(true); + peerWithUnavailableNode.Setup(p => p.RemoteEndpoint) + .Returns(new AElfPeerEndpoint("192.168.88.100", 8802)); + peerWithUnavailableNode.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList + { + Nodes = { - Nodes = + new NodeInfo { - new NodeInfo - { - Endpoint = "192.168.100.100:8001", - Pubkey = ByteString.CopyFromUtf8("192.168.100.100:8001") - } + Endpoint = "192.168.100.100:8001", + Pubkey = ByteString.CopyFromUtf8("192.168.100.100:8001") } - })); + } + })); - peerPool.TryAddPeer(peerWithUnavailableNode.Object); - } + peerPool.TryAddPeer(peerWithUnavailableNode.Object); + } - { - var peerWittSamePubkeyNode = new Mock(); - peerWittSamePubkeyNode.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "PeerWithSamePubkeyNode", ConnectionTime = TimestampHelper.GetUtcNow()}); - peerWittSamePubkeyNode.Setup(p => p.IsReady).Returns(true); - peerWittSamePubkeyNode.Setup(p => p.RemoteEndpoint) - .Returns(new AElfPeerEndpoint("192.168.88.100", 8803)); - peerWittSamePubkeyNode.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList + { + var peerWittSamePubkeyNode = new Mock(); + peerWittSamePubkeyNode.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "PeerWithSamePubkeyNode", ConnectionTime = TimestampHelper.GetUtcNow() }); + peerWittSamePubkeyNode.Setup(p => p.IsReady).Returns(true); + peerWittSamePubkeyNode.Setup(p => p.RemoteEndpoint) + .Returns(new AElfPeerEndpoint("192.168.88.100", 8803)); + peerWittSamePubkeyNode.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList + { + Nodes = { - Nodes = + new NodeInfo { - new NodeInfo - { - Endpoint = "192.168.100.100:8002", - Pubkey = ByteStringHelper.FromHexString(pubkey) - } + Endpoint = "192.168.100.100:8002", + Pubkey = ByteStringHelper.FromHexString(pubkey) } - })); + } + })); - peerPool.TryAddPeer(peerWittSamePubkeyNode.Object); - } + peerPool.TryAddPeer(peerWittSamePubkeyNode.Object); + } - { - var peerWithNormalNode = new Mock(); - peerWithNormalNode.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = "PeerWithNormalNode", ConnectionTime = TimestampHelper.GetUtcNow()}); - peerWithNormalNode.Setup(p => p.IsReady).Returns(true); - peerWithNormalNode.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.88.100", 8804)); - peerWithNormalNode.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList + { + var peerWithNormalNode = new Mock(); + peerWithNormalNode.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = "PeerWithNormalNode", ConnectionTime = TimestampHelper.GetUtcNow() }); + peerWithNormalNode.Setup(p => p.IsReady).Returns(true); + peerWithNormalNode.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.88.100", 8804)); + peerWithNormalNode.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList + { + Nodes = { - Nodes = + new NodeInfo { - new NodeInfo - { - Endpoint = "192.168.100.100:8003", - Pubkey = ByteString.CopyFromUtf8("192.168.100.100:8003") - } + Endpoint = "192.168.100.100:8003", + Pubkey = ByteString.CopyFromUtf8("192.168.100.100:8003") } - })); + } + })); - peerPool.TryAddPeer(peerWithNormalNode.Object); - } + peerPool.TryAddPeer(peerWithNormalNode.Object); } } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/PeerInvalidTransactionTestModule.cs b/test/AElf.OS.Core.Tests/Network/PeerInvalidTransactionTestModule.cs index 164aa490c9..a239c72b10 100644 --- a/test/AElf.OS.Core.Tests/Network/PeerInvalidTransactionTestModule.cs +++ b/test/AElf.OS.Core.Tests/Network/PeerInvalidTransactionTestModule.cs @@ -9,47 +9,43 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +[DependsOn(typeof(OSCoreTestAElfModule))] +public class PeerInvalidTransactionTestModule : AElfModule { - [DependsOn(typeof(OSCoreTestAElfModule))] - public class PeerInvalidTransactionTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var peerPoolMock = new Mock(); + var peerList = new List { - var peerPoolMock = new Mock(); - var peerList = new List - { - MockPeer("192.168.1.100:6800", "Peer1"), - MockPeer("192.168.1.100:6801", "Peer2"), - MockPeer("192.168.100.100:6800", "Peer3") - }; + MockPeer("192.168.1.100:6800", "Peer1"), + MockPeer("192.168.1.100:6801", "Peer2"), + MockPeer("192.168.100.100:6800", "Peer3") + }; - peerPoolMock.Setup(p => p.GetPeers(It.IsAny())) - .Returns(includeFailing => peerList); - peerPoolMock.Setup(p => p.GetPeersByHost(It.IsAny())) - .Returns(host => { return peerList.Where(p => p.RemoteEndpoint.Host.Equals(host)).ToList(); }); - peerPoolMock.Setup(p => p.FindPeerByPublicKey(It.IsAny())) - .Returns(pubkey => peerList.First(p => p.Info.Pubkey.Equals(pubkey))); - - context.Services.AddSingleton(o => peerPoolMock.Object); - } + peerPoolMock.Setup(p => p.GetPeers(It.IsAny())) + .Returns(includeFailing => peerList); + peerPoolMock.Setup(p => p.GetPeersByHost(It.IsAny())) + .Returns(host => { return peerList.Where(p => p.RemoteEndpoint.Host.Equals(host)).ToList(); }); + peerPoolMock.Setup(p => p.FindPeerByPublicKey(It.IsAny())) + .Returns(pubkey => peerList.First(p => p.Info.Pubkey.Equals(pubkey))); - private IPeer MockPeer(string address, string pubkey) - { - AElfPeerEndpointHelper.TryParse(address, out var endpoint); - var peer = new Mock(); - var knowsTransactions = new HashSet(); - for (var i = 0; i < 10; i++) - { - knowsTransactions.Add(HashHelper.ComputeFrom("Tx" + i + pubkey)); - } + context.Services.AddSingleton(o => peerPoolMock.Object); + } + + private IPeer MockPeer(string address, string pubkey) + { + AElfPeerEndpointHelper.TryParse(address, out var endpoint); + var peer = new Mock(); + var knowsTransactions = new HashSet(); + for (var i = 0; i < 10; i++) knowsTransactions.Add(HashHelper.ComputeFrom("Tx" + i + pubkey)); - peer.Setup(p => p.KnowsTransaction(It.IsAny())) - .Returns(hash => knowsTransactions.Contains(hash)); - peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); - peer.Setup(p => p.Info).Returns(new PeerConnectionInfo {Pubkey = pubkey}); + peer.Setup(p => p.KnowsTransaction(It.IsAny())) + .Returns(hash => knowsTransactions.Contains(hash)); + peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); + peer.Setup(p => p.Info).Returns(new PeerConnectionInfo { Pubkey = pubkey }); - return peer.Object; - } + return peer.Object; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Protocol/BlockWithTransactionsTests.cs b/test/AElf.OS.Core.Tests/Network/Protocol/BlockWithTransactionsTests.cs index 11028d8fdf..52bfbe283b 100644 --- a/test/AElf.OS.Core.Tests/Network/Protocol/BlockWithTransactionsTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Protocol/BlockWithTransactionsTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -8,44 +7,40 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Protocol +namespace AElf.OS.Network.Protocol; + +public class BlockWithTransactionsTests : NetworkInfrastructureTestBase { - public class BlockWithTransactionsTests : NetworkInfrastructureTestBase + private readonly IBlockchainService _blockchainService; + private readonly KernelTestHelper _kernelTestHelper; + + public BlockWithTransactionsTests() { - private readonly IBlockchainService _blockchainService; - private readonly KernelTestHelper _kernelTestHelper; + _blockchainService = GetRequiredService(); + _kernelTestHelper = GetRequiredService(); + } - public BlockWithTransactionsTests() - { - _blockchainService = GetRequiredService(); - _kernelTestHelper = GetRequiredService(); - } + [Fact] + public async Task BlockWithTransactions_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var transactions = new List(); + for (var i = 0; i < 5; i++) transactions.Add(_kernelTestHelper.GenerateTransaction()); + + var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash, transactions); - [Fact] - public async Task BlockWithTransactions_Test() + var blockWithTransactions = new BlockWithTransactions { - var chain = await _blockchainService.GetChainAsync(); - var transactions = new List(); - for (var i = 0; i < 5; i++) - { - transactions.Add(_kernelTestHelper.GenerateTransaction()); - } + Header = block.Header, + Transactions = { transactions } + }; - var block = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash, transactions); - - var blockWithTransactions = new BlockWithTransactions - { - Header = block.Header, - Transactions = { transactions } - }; - - blockWithTransactions.FullTransactionList.ShouldBe(transactions); - blockWithTransactions.TransactionIds.ShouldBe(transactions.Select(o=>o.GetHash())); - blockWithTransactions.Height.ShouldBe(block.Height); - blockWithTransactions.Body.ShouldBe(new BlockBody - { - TransactionIds = {transactions.Select(tx => tx.GetHash()).ToList()} - }); - } + blockWithTransactions.FullTransactionList.ShouldBe(transactions); + blockWithTransactions.TransactionIds.ShouldBe(transactions.Select(o => o.GetHash())); + blockWithTransactions.Height.ShouldBe(block.Height); + blockWithTransactions.Body.ShouldBe(new BlockBody + { + TransactionIds = { transactions.Select(tx => tx.GetHash()).ToList() } + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/Protocol/HandshakeProviderTests.cs b/test/AElf.OS.Core.Tests/Network/Protocol/HandshakeProviderTests.cs index 3a30f8ad89..68df3649a7 100644 --- a/test/AElf.OS.Core.Tests/Network/Protocol/HandshakeProviderTests.cs +++ b/test/AElf.OS.Core.Tests/Network/Protocol/HandshakeProviderTests.cs @@ -1,90 +1,86 @@ using System.Threading.Tasks; -using AElf.ContractTestKit; using AElf.Cryptography; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; -using AElf.Sdk.CSharp; -using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.OS.Network.Protocol +namespace AElf.OS.Network.Protocol; + +public class HandshakeProviderTests : HandshakeTestBase { - public class HandshakeProviderTests : HandshakeTestBase + private readonly IBlockchainService _blockchainService; + private readonly IHandshakeProvider _handshakeProvider; + private readonly TestPeerKeyProvider _peerKeyProvider; + + public HandshakeProviderTests() { - private readonly IHandshakeProvider _handshakeProvider; - private readonly TestPeerKeyProvider _peerKeyProvider; - private readonly IBlockchainService _blockchainService; + _handshakeProvider = GetRequiredService(); + _blockchainService = GetRequiredService(); + _peerKeyProvider = GetRequiredService(); + } - public HandshakeProviderTests() - { - _handshakeProvider = GetRequiredService(); - _blockchainService = GetRequiredService(); - _peerKeyProvider = GetRequiredService(); - } - - public Handshake CreateHandshake(ECKeyPair initiatorPeer, int chainId = NetworkTestConstants.DefaultChainId) + public Handshake CreateHandshake(ECKeyPair initiatorPeer, int chainId = NetworkTestConstants.DefaultChainId) + { + var data = new HandshakeData { - var data = new HandshakeData - { - ChainId = _blockchainService.GetChainId(), - Version = KernelConstants.ProtocolVersion, - Pubkey = ByteString.CopyFrom(initiatorPeer.PublicKey), - Time = TimestampHelper.GetUtcNow() - }; - - var signature = CryptoHelper.SignWithPrivateKey(initiatorPeer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); - - return new Handshake { HandshakeData = data, Signature = ByteString.CopyFrom(signature) }; - } + ChainId = _blockchainService.GetChainId(), + Version = KernelConstants.ProtocolVersion, + Pubkey = ByteString.CopyFrom(initiatorPeer.PublicKey), + Time = TimestampHelper.GetUtcNow() + }; - [Fact] - public async Task ValidateHandshake_Test() - { - var remoteKeyPair = _peerKeyProvider.AuthorizedKey; + var signature = + CryptoHelper.SignWithPrivateKey(initiatorPeer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); + + return new Handshake { HandshakeData = data, Signature = ByteString.CopyFrom(signature) }; + } + + [Fact] + public async Task ValidateHandshake_Test() + { + var remoteKeyPair = _peerKeyProvider.AuthorizedKey; - var handshake = CreateHandshake(remoteKeyPair); - var validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.Ok); + var handshake = CreateHandshake(remoteKeyPair); + var validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.Ok); - handshake = CreateHandshake(remoteKeyPair); - var unauthorizedKeyPair = CryptoHelper.GenerateKeyPair(); - handshake.HandshakeData.Pubkey = ByteString.CopyFrom(unauthorizedKeyPair.PublicKey); - validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.Unauthorized); + handshake = CreateHandshake(remoteKeyPair); + var unauthorizedKeyPair = CryptoHelper.GenerateKeyPair(); + handshake.HandshakeData.Pubkey = ByteString.CopyFrom(unauthorizedKeyPair.PublicKey); + validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.Unauthorized); - handshake = CreateHandshake(remoteKeyPair); - handshake.HandshakeData.ChainId = 1234; - validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.InvalidChainId); + handshake = CreateHandshake(remoteKeyPair); + handshake.HandshakeData.ChainId = 1234; + validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.InvalidChainId); - handshake = CreateHandshake(remoteKeyPair); - handshake.HandshakeData.Version = 0; - validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.InvalidVersion); + handshake = CreateHandshake(remoteKeyPair); + handshake.HandshakeData.Version = 0; + validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.InvalidVersion); - handshake = CreateHandshake(remoteKeyPair); - handshake.HandshakeData.Time = - TimestampHelper.GetUtcNow().AddMilliseconds(-(NetworkConstants.HandshakeTimeout + 100)); - validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.HandshakeTimeout); + handshake = CreateHandshake(remoteKeyPair); + handshake.HandshakeData.Time = + TimestampHelper.GetUtcNow().AddMilliseconds(-(NetworkConstants.HandshakeTimeout + 100)); + validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.HandshakeTimeout); - handshake = CreateHandshake(remoteKeyPair); - var maliciousPeer = CryptoHelper.GenerateKeyPair(); - var signature = CryptoHelper.SignWithPrivateKey(maliciousPeer.PrivateKey, HashHelper - .ComputeFrom(handshake.HandshakeData) - .ToByteArray()); - handshake.Signature = ByteString.CopyFrom(signature); - validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); - validationResult.ShouldBe(HandshakeValidationResult.InvalidSignature); + handshake = CreateHandshake(remoteKeyPair); + var maliciousPeer = CryptoHelper.GenerateKeyPair(); + var signature = CryptoHelper.SignWithPrivateKey(maliciousPeer.PrivateKey, HashHelper + .ComputeFrom(handshake.HandshakeData) + .ToByteArray()); + handshake.Signature = ByteString.CopyFrom(signature); + validationResult = await _handshakeProvider.ValidateHandshakeAsync(handshake); + validationResult.ShouldBe(HandshakeValidationResult.InvalidSignature); - var localHandshake = await _handshakeProvider.GetHandshakeAsync(); - validationResult = await _handshakeProvider.ValidateHandshakeAsync(localHandshake); - validationResult.ShouldBe(HandshakeValidationResult.SelfConnection); - } + var localHandshake = await _handshakeProvider.GetHandshakeAsync(); + validationResult = await _handshakeProvider.ValidateHandshakeAsync(localHandshake); + validationResult.ShouldBe(HandshakeValidationResult.SelfConnection); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/Network/TestPeerKeyProvider.cs b/test/AElf.OS.Core.Tests/Network/TestPeerKeyProvider.cs index f11af3aa02..21ae53bf05 100644 --- a/test/AElf.OS.Core.Tests/Network/TestPeerKeyProvider.cs +++ b/test/AElf.OS.Core.Tests/Network/TestPeerKeyProvider.cs @@ -1,9 +1,8 @@ using AElf.Cryptography.ECDSA; -namespace AElf.OS.Network +namespace AElf.OS.Network; + +public class TestPeerKeyProvider { - public class TestPeerKeyProvider - { - public ECKeyPair AuthorizedKey { get; set; } - } + public ECKeyPair AuthorizedKey { get; set; } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/OSCoreTestAElfModule.cs b/test/AElf.OS.Core.Tests/OSCoreTestAElfModule.cs index bc5d88a7d8..84ae304d77 100644 --- a/test/AElf.OS.Core.Tests/OSCoreTestAElfModule.cs +++ b/test/AElf.OS.Core.Tests/OSCoreTestAElfModule.cs @@ -12,61 +12,57 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS +namespace AElf.OS; + +[DependsOn( + typeof(OSTestBaseAElfModule) +)] +public class OSCoreTestAElfModule : AElfModule { - [DependsOn( - typeof(OSTestBaseAElfModule) - )] - public class OSCoreTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => { o.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); + Configure(o => { o.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var nodeAccount = Address.FromPublicKey(ecKeyPair.PublicKey).ToBase58(); - var nodeAccountPassword = "123"; + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + var nodeAccount = Address.FromPublicKey(ecKeyPair.PublicKey).ToBase58(); + var nodeAccountPassword = "123"; - Configure(o => - { - o.NodeAccount = nodeAccount; - o.NodeAccountPassword = nodeAccountPassword; - }); + Configure(o => + { + o.NodeAccount = nodeAccount; + o.NodeAccountPassword = nodeAccountPassword; + }); - Configure(o => - { - var miners = new List(); - for (var i = 0; i < 3; i++) - { - miners.Add(CryptoHelper.GenerateKeyPair().PublicKey.ToHex()); - } + Configure(o => + { + var miners = new List(); + for (var i = 0; i < 3; i++) miners.Add(CryptoHelper.GenerateKeyPair().PublicKey.ToHex()); - o.InitialMinerList = miners; - o.MiningInterval = 4000; - o.PeriodSeconds = 604800; - o.MinerIncreaseInterval = 31536000; - }); + o.InitialMinerList = miners; + o.MiningInterval = 4000; + o.PeriodSeconds = 604800; + o.MinerIncreaseInterval = 31536000; + }); - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => - Task.FromResult(CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, data))); + context.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(a => a.SignAsync(It.IsAny())).Returns(data => + Task.FromResult(CryptoHelper.SignWithPrivateKey(ecKeyPair.PrivateKey, data))); + + mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(ecKeyPair.PublicKey); - mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(ecKeyPair.PublicKey); + return mockService.Object; + }); - return mockService.Object; - }); + context.Services.AddSingleton(o => Mock.Of()); - context.Services.AddSingleton(o => Mock.Of()); - - Configure(o=> - { - o.PeerInvalidTransactionLimit = 5; - o.PeerInvalidTransactionTimeout = 1000; - o.PeerDiscoveryMaxNodesToKeep = 5; - o.MaxPeers = 5; - }); - } + Configure(o => + { + o.PeerInvalidTransactionLimit = 5; + o.PeerInvalidTransactionTimeout = 1000; + o.PeerDiscoveryMaxNodesToKeep = 5; + o.MaxPeers = 5; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/OSCoreTestBase.cs b/test/AElf.OS.Core.Tests/OSCoreTestBase.cs index 17909bb8fe..447dbb0595 100644 --- a/test/AElf.OS.Core.Tests/OSCoreTestBase.cs +++ b/test/AElf.OS.Core.Tests/OSCoreTestBase.cs @@ -1,35 +1,28 @@ using AElf.OS.Network; using AElf.TestBase; -namespace AElf.OS +namespace AElf.OS; + +public class OSCoreNetworkServiceTestBase : AElfIntegratedTest { - public class OSCoreNetworkServiceTestBase : AElfIntegratedTest - { - - } +} - public class NetworkServicePropagationTestBase : AElfIntegratedTest - { - - } +public class NetworkServicePropagationTestBase : AElfIntegratedTest +{ +} - public class SyncFlagTestBase : AElfIntegratedTest - { - - } +public class SyncFlagTestBase : AElfIntegratedTest +{ +} - public class HandshakeTestBase : AElfIntegratedTest - { - - } +public class HandshakeTestBase : AElfIntegratedTest +{ +} - public class PeerInvalidTransactionTestBase : AElfIntegratedTest - { - - } - - public class PeerDiscoveryTestBase : AElfIntegratedTest - { - - } +public class PeerInvalidTransactionTestBase : AElfIntegratedTest +{ +} + +public class PeerDiscoveryTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.OS.Core.Tests/OSCoreWithChainTestAElfModule.cs b/test/AElf.OS.Core.Tests/OSCoreWithChainTestAElfModule.cs index 74dfea5468..7df4853d94 100644 --- a/test/AElf.OS.Core.Tests/OSCoreWithChainTestAElfModule.cs +++ b/test/AElf.OS.Core.Tests/OSCoreWithChainTestAElfModule.cs @@ -18,70 +18,71 @@ using Volo.Abp; using Volo.Abp.Modularity; using Volo.Abp.Threading; +using UnitTestContractZeroCodeProvider = AElf.Kernel.UnitTestContractZeroCodeProvider; -namespace AElf.OS +namespace AElf.OS; + +[DependsOn( + typeof(OSCoreTestAElfModule) +)] +public class OSCoreWithChainTestAElfModule : AElfModule { - [DependsOn( - typeof(OSCoreTestAElfModule) - )] - public class OSCoreWithChainTestAElfModule : AElfModule - { - private OSTestHelper _osTestHelper; + private OSTestHelper _osTestHelper; - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTransient(o => { - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(s => - s.GenerateSystemTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new List())); - return mockService.Object; - }); + var mockService = new Mock(); + mockService.Setup(s => + s.GenerateSystemTransactionsAsync(It.IsAny
(), It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(new List())); + return mockService.Object; + }); - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(s => - s.FillBlockExtraDataAsync(It.IsAny())).Returns(Task.CompletedTask); - return mockService.Object; - }); + context.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(s => + s.FillBlockExtraDataAsync(It.IsAny())).Returns(Task.CompletedTask); + return mockService.Object; + }); - context.Services.AddTransient(o => - { - var mockService = new Mock(); - mockService.Setup(s => - s.ValidateBlockBeforeAttachAsync(It.IsAny())).Returns(Task.FromResult(true)); - mockService.Setup(s => - s.ValidateBlockBeforeExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); - mockService.Setup(s => - s.ValidateBlockAfterExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); - return mockService.Object; - }); + context.Services.AddTransient(o => + { + var mockService = new Mock(); + mockService.Setup(s => + s.ValidateBlockBeforeAttachAsync(It.IsAny())).Returns(Task.FromResult(true)); + mockService.Setup(s => + s.ValidateBlockBeforeExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); + mockService.Setup(s => + s.ValidateBlockAfterExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); + return mockService.Object; + }); - context.Services.AddSingleton(o => Mock.Of()); - context.Services.AddSingleton(); + context.Services.AddSingleton(o => Mock.Of()); + context.Services.AddSingleton(); - context.Services.AddSingleton(provider => - { - var option = provider.GetService>(); - return new UnitTestCSharpSmartContractRunner( - option.Value.SdkDir); - }); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - context.Services - .AddSingleton(); - } - public override void OnApplicationInitialization(ApplicationInitializationContext context) + context.Services.AddSingleton(provider => { - _osTestHelper = context.ServiceProvider.GetService(); - AsyncHelper.RunSync(() => _osTestHelper.MockChainAsync()); - } + var option = provider.GetService>(); + return new UnitTestCSharpSmartContractRunner( + option.Value.SdkDir); + }); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + context.Services + .AddSingleton(); + } - public override void OnApplicationShutdown(ApplicationShutdownContext context) - { - AsyncHelper.RunSync(() => _osTestHelper.DisposeMock()); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + _osTestHelper = context.ServiceProvider.GetService(); + AsyncHelper.RunSync(() => _osTestHelper.MockChainAsync()); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + AsyncHelper.RunSync(() => _osTestHelper.DisposeMock()); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/AElf.OS.Network.Grpc.Tests.csproj b/test/AElf.OS.Network.Grpc.Tests/AElf.OS.Network.Grpc.Tests.csproj index 3750c0c002..26692ab16c 100644 --- a/test/AElf.OS.Network.Grpc.Tests/AElf.OS.Network.Grpc.Tests.csproj +++ b/test/AElf.OS.Network.Grpc.Tests/AElf.OS.Network.Grpc.Tests.csproj @@ -5,19 +5,19 @@ AElf.OS.Network.Grpc - - - - - - - - + + + + + + + + - - + + - + diff --git a/test/AElf.OS.Network.Grpc.Tests/BoundedExpirationCacheTests.cs b/test/AElf.OS.Network.Grpc.Tests/BoundedExpirationCacheTests.cs index c26a962ef3..5f8e3ca5f7 100644 --- a/test/AElf.OS.Network.Grpc.Tests/BoundedExpirationCacheTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/BoundedExpirationCacheTests.cs @@ -4,68 +4,64 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class BoundedExpirationCacheTests : GrpcNetworkTestBase { - public class BoundedExpirationCacheTests : GrpcNetworkTestBase + [Fact] + public void Test_Add_Existence() { - [Fact] - public void Test_Add_Existence() - { - var hash = HashHelper.ComputeFrom("hello_world"); - var cache = new BoundedExpirationCache(10, 10_000); - cache.HasHash(hash).ShouldBeFalse(); - cache.TryAdd(hash).ShouldBeTrue(); - cache.HasHash(hash).ShouldBeTrue(); - cache.TryAdd(hash).ShouldBeFalse(); - } + var hash = HashHelper.ComputeFrom("hello_world"); + var cache = new BoundedExpirationCache(10, 10_000); + cache.HasHash(hash).ShouldBeFalse(); + cache.TryAdd(hash).ShouldBeTrue(); + cache.HasHash(hash).ShouldBeTrue(); + cache.TryAdd(hash).ShouldBeFalse(); + } - [Fact] - public async Task Test_Expiration() - { - var hash = HashHelper.ComputeFrom("hello_world"); - var cache = new BoundedExpirationCache(10, 4); // 4ms timeout - cache.TryAdd(hash); - await Task.Delay(TimeSpan.FromSeconds(1)); + [Fact] + public async Task Test_Expiration() + { + var hash = HashHelper.ComputeFrom("hello_world"); + var cache = new BoundedExpirationCache(10, 4); // 4ms timeout + cache.TryAdd(hash); + await Task.Delay(TimeSpan.FromSeconds(1)); - cache.HasHash(hash, false).ShouldBeTrue(); + cache.HasHash(hash, false).ShouldBeTrue(); - cache.HasHash(hash).ShouldBeFalse(); - } + cache.HasHash(hash).ShouldBeFalse(); + } - [Fact] - public async Task Test_MultiItem_Expiration() + [Fact] + public async Task Test_MultiItem_Expiration() + { + var cacheCapacity = 10; + var timeout = 1_000; + var cache = new BoundedExpirationCache(cacheCapacity, timeout); + var hashStrings = new List(); + for (var i = 0; i < cacheCapacity; i++) { - int cacheCapacity = 10; - int timeout = 1_000; - var cache = new BoundedExpirationCache(cacheCapacity, timeout); - List hashStrings = new List(); - for (int i = 0; i < cacheCapacity; i++) - { - var current = $"hello_world_{i}"; - hashStrings.Add(current); - cache.TryAdd(HashHelper.ComputeFrom(current)).ShouldBeTrue(); - } - - await Task.Delay(TimeSpan.FromMilliseconds(timeout+500)); - - cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{cacheCapacity}")).ShouldBeTrue(); - - foreach (string hashString in hashStrings) - { - cache.HasHash(HashHelper.ComputeFrom(hashString)).ShouldBeFalse(); - } + var current = $"hello_world_{i}"; + hashStrings.Add(current); + cache.TryAdd(HashHelper.ComputeFrom(current)).ShouldBeTrue(); } - [Fact] - public void Test_Max_Capacity() - { - int cacheCapacity = 2; - BoundedExpirationCache cache = new BoundedExpirationCache(cacheCapacity, 10_000); + await Task.Delay(TimeSpan.FromMilliseconds(timeout + 500)); - for (int i = 0; i < cacheCapacity; i++) - cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{i}")).ShouldBeTrue(); + cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{cacheCapacity}")).ShouldBeTrue(); - cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{cacheCapacity}")).ShouldBeFalse(); - } + foreach (var hashString in hashStrings) cache.HasHash(HashHelper.ComputeFrom(hashString)).ShouldBeFalse(); + } + + [Fact] + public void Test_Max_Capacity() + { + var cacheCapacity = 2; + var cache = new BoundedExpirationCache(cacheCapacity, 10_000); + + for (var i = 0; i < cacheCapacity; i++) + cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{i}")).ShouldBeTrue(); + + cache.TryAdd(HashHelper.ComputeFrom($"hello_world_{cacheCapacity}")).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceBootNodeTests.cs b/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceBootNodeTests.cs index bda17561cc..ded7047242 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceBootNodeTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceBootNodeTests.cs @@ -3,32 +3,31 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class ConnectionServiceBootNodeTests : GrpcNetworkConnectionWithBootNodesTestBase { - public class ConnectionServiceBootNodeTests : GrpcNetworkConnectionWithBootNodesTestBase - { - private readonly IConnectionService _connectionService; - private readonly IReconnectionService _reconnectionService; + private readonly IConnectionService _connectionService; + private readonly IReconnectionService _reconnectionService; - public ConnectionServiceBootNodeTests() - { - _connectionService = GetRequiredService(); - _reconnectionService = GetRequiredService(); - } + public ConnectionServiceBootNodeTests() + { + _connectionService = GetRequiredService(); + _reconnectionService = GetRequiredService(); + } - [Fact] - public async Task TrySchedulePeerReconnection_IsInboundAndInBootNode_Test() - { - var peer = GrpcTestPeerHelper.CreateBasicPeer("127.0.0.1:2020", NetworkTestConstants.FakePubkey); - peer.Info.IsInbound = true; + [Fact] + public async Task TrySchedulePeerReconnection_IsInboundAndInBootNode_Test() + { + var peer = GrpcTestPeerHelper.CreateBasicPeer("127.0.0.1:2020", NetworkTestConstants.FakePubkey); + peer.Info.IsInbound = true; - var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); - result.ShouldBeTrue(); + var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); + result.ShouldBeTrue(); - peer.IsConnected.ShouldBeFalse(); - peer.IsShutdown.ShouldBeTrue(); + peer.IsConnected.ShouldBeFalse(); + peer.IsShutdown.ShouldBeTrue(); - _reconnectionService.GetReconnectingPeer("127.0.0.1:2020").ShouldNotBeNull(); - } + _reconnectionService.GetReconnectingPeer("127.0.0.1:2020").ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceTests.cs b/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceTests.cs index 5b4e434c14..d245bd303f 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Connection/ConnectionServiceTests.cs @@ -19,424 +19,423 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class ConnectionServiceTests : GrpcNetworkTestBase { - public class ConnectionServiceTests : GrpcNetworkTestBase + private readonly IBlackListedPeerProvider _blackListedPeerProvider; + private readonly IBlockchainService _blockchainService; + private readonly IConnectionService _connectionService; + private readonly ILocalEventBus _eventBus; + private readonly IHandshakeProvider _handshakeProvider; + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public ConnectionServiceTests() { - private readonly IConnectionService _connectionService; - private readonly IPeerPool _peerPool; - private readonly IBlackListedPeerProvider _blackListedPeerProvider; - private readonly ILocalEventBus _eventBus; - private readonly IBlockchainService _blockchainService; - private readonly IHandshakeProvider _handshakeProvider; - private readonly IReconnectionService _reconnectionService; - - public ConnectionServiceTests() - { - _connectionService = GetRequiredService(); - _peerPool = GetRequiredService(); - _blackListedPeerProvider = GetRequiredService(); - _eventBus = GetRequiredService(); - _blockchainService = GetRequiredService(); - _handshakeProvider = GetRequiredService(); - _reconnectionService = GetRequiredService(); - } - - [Fact] - public async Task Connect_DialPeerFailed_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.DialExceptionIpEndpoint, out var endpoint); - var result = await _connectionService.ConnectAsync(endpoint); - result.ShouldBeFalse(); - } - - [Fact] - public async Task Connect_PeerAlreadyInPoolAndIsValid_Test() - { - var peer = CreatePeerAndAddToPeerPool(); - var added = await _connectionService.ConnectAsync(peer.RemoteEndpoint); - - added.ShouldBeFalse(); - } - - [Fact] - public async Task Connect_PeerAlreadyInPoolAndIsInvalid_Test() - { - var peer = CreatePeerAndAddToPeerPool(NetworkTestConstants.GoodPeerEndpoint, NetworkTestConstants.FakePubkey2); - peer.IsConnected = false; - peer.Info.ConnectionTime = TimestampHelper.GetUtcNow() - .AddMilliseconds(-NetworkConstants.PeerConnectionTimeout - 1000); - - var added = await _connectionService.ConnectAsync(peer.RemoteEndpoint); - added.ShouldBeTrue(); - - var currentPeer = _peerPool.FindPeerByPublicKey(NetworkTestConstants.FakePubkey); - currentPeer.ShouldNotBeNull(); - } - - [Fact] - public async Task Connect_HostInBlackList_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); - _blackListedPeerProvider.AddHostToBlackList(endpoint.Host, 10); - - var added = await _connectionService.ConnectAsync(endpoint); - added.ShouldBeFalse(); - } - - [Fact] - public async Task Connect_OverIpLimit_Test() - { - AElfPeerEndpointHelper.TryParse("192.168.100.100", out var endpoint); - _peerPool.AddHandshakingPeer(endpoint.Host, "pubkey"); + _connectionService = GetRequiredService(); + _peerPool = GetRequiredService(); + _blackListedPeerProvider = GetRequiredService(); + _eventBus = GetRequiredService(); + _blockchainService = GetRequiredService(); + _handshakeProvider = GetRequiredService(); + _reconnectionService = GetRequiredService(); + } - var added = await _connectionService.ConnectAsync(endpoint); - added.ShouldBeFalse(); - } + [Fact] + public async Task Connect_DialPeerFailed_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.DialExceptionIpEndpoint, out var endpoint); + var result = await _connectionService.ConnectAsync(endpoint); + result.ShouldBeFalse(); + } - [Fact] - public async Task Connect_InboundPeerIsLater_Test() - { - var peer = CreatePeerAndAddToPeerPool(); - - peer.UpdateLastReceivedHandshake(new Handshake - { - HandshakeData = new HandshakeData - { - LastIrreversibleBlockHeight=1, - BestChainHash = HashHelper.ComputeFrom("BestChainHash"), - BestChainHeight =10, - Time = TimestampHelper.GetUtcNow().AddMinutes(1) - } - }); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - var added = await _connectionService.ConnectAsync(endpoint); - added.ShouldBeTrue(); - - var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldNotBeNull(); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); - currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldBeNull(); - } - - [Fact] - public async Task Connect_InboundPeerIsEarlier_Test() + [Fact] + public async Task Connect_PeerAlreadyInPoolAndIsValid_Test() + { + var peer = CreatePeerAndAddToPeerPool(); + var added = await _connectionService.ConnectAsync(peer.RemoteEndpoint); + + added.ShouldBeFalse(); + } + + [Fact] + public async Task Connect_PeerAlreadyInPoolAndIsInvalid_Test() + { + var peer = CreatePeerAndAddToPeerPool(NetworkTestConstants.GoodPeerEndpoint, NetworkTestConstants.FakePubkey2); + peer.IsConnected = false; + peer.Info.ConnectionTime = TimestampHelper.GetUtcNow() + .AddMilliseconds(-NetworkConstants.PeerConnectionTimeout - 1000); + + var added = await _connectionService.ConnectAsync(peer.RemoteEndpoint); + added.ShouldBeTrue(); + + var currentPeer = _peerPool.FindPeerByPublicKey(NetworkTestConstants.FakePubkey); + currentPeer.ShouldNotBeNull(); + } + + [Fact] + public async Task Connect_HostInBlackList_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); + _blackListedPeerProvider.AddHostToBlackList(endpoint.Host, 10); + + var added = await _connectionService.ConnectAsync(endpoint); + added.ShouldBeFalse(); + } + + [Fact] + public async Task Connect_OverIpLimit_Test() + { + AElfPeerEndpointHelper.TryParse("192.168.100.100", out var endpoint); + _peerPool.AddHandshakingPeer(endpoint.Host, "pubkey"); + + var added = await _connectionService.ConnectAsync(endpoint); + added.ShouldBeFalse(); + } + + [Fact] + public async Task Connect_InboundPeerIsLater_Test() + { + var peer = CreatePeerAndAddToPeerPool(); + + peer.UpdateLastReceivedHandshake(new Handshake { - var mockClient = new Mock(); - var confirmHandshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(new VoidReply()), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), - () => { }); - mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), - It.IsAny(), It.IsAny(), - CancellationToken.None)).Returns(confirmHandshakeCall); - - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint, - NetworkTestConstants.FakePubkey, mockClient.Object); - - peer.UpdateLastReceivedHandshake(new Handshake + HandshakeData = new HandshakeData { - HandshakeData = new HandshakeData - { - LastIrreversibleBlockHeight=1, - BestChainHash = HashHelper.ComputeFrom("BestChainHash"), - BestChainHeight =10, - Time = TimestampHelper.GetUtcNow().AddMinutes(-1) - } - }); - _peerPool.TryAddPeer(peer); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - var added = await _connectionService.ConnectAsync(endpoint); - added.ShouldBeTrue(); - - var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldBeNull(); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); - currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldNotBeNull(); - } - - [Fact] - public async Task Connect_ConfirmFailed_Test() + LastIrreversibleBlockHeight = 1, + BestChainHash = HashHelper.ComputeFrom("BestChainHash"), + BestChainHeight = 10, + Time = TimestampHelper.GetUtcNow().AddMinutes(1) + } + }); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + + var added = await _connectionService.ConnectAsync(endpoint); + added.ShouldBeTrue(); + + var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldNotBeNull(); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); + currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldBeNull(); + } + + [Fact] + public async Task Connect_InboundPeerIsEarlier_Test() + { + var mockClient = new Mock(); + var confirmHandshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(new VoidReply()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), + () => { }); + mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), + It.IsAny(), It.IsAny(), + CancellationToken.None)).Returns(confirmHandshakeCall); + + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint, + NetworkTestConstants.FakePubkey, mockClient.Object); + + peer.UpdateLastReceivedHandshake(new Handshake { - var mockClient = new Mock(); - mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), - It.IsAny(), It.IsAny(), - CancellationToken.None)).Throws(); - - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint, - NetworkTestConstants.FakePubkey, mockClient.Object); - - peer.UpdateLastReceivedHandshake(new Handshake + HandshakeData = new HandshakeData { - HandshakeData = new HandshakeData - { - LastIrreversibleBlockHeight=1, - BestChainHash = HashHelper.ComputeFrom("BestChainHash"), - BestChainHeight =10, - Time = TimestampHelper.GetUtcNow().AddMinutes(-1) - } - }); - _peerPool.TryAddPeer(peer); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - _connectionService.ConnectAsync(endpoint).ShouldThrow(); - - var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldBeNull(); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); - currentPeer = _peerPool.FindPeerByEndpoint(endpoint); - currentPeer.ShouldBeNull(); - } - - [Fact] - public async Task DialPeerAsync_GoodPeer_Test() + LastIrreversibleBlockHeight = 1, + BestChainHash = HashHelper.ComputeFrom("BestChainHash"), + BestChainHeight = 10, + Time = TimestampHelper.GetUtcNow().AddMinutes(-1) + } + }); + _peerPool.TryAddPeer(peer); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + + var added = await _connectionService.ConnectAsync(endpoint); + added.ShouldBeTrue(); + + var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldBeNull(); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); + currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldNotBeNull(); + } + + [Fact] + public async Task Connect_ConfirmFailed_Test() + { + var mockClient = new Mock(); + mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), + It.IsAny(), It.IsAny(), + CancellationToken.None)).Throws(); + + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint, + NetworkTestConstants.FakePubkey, mockClient.Object); + + peer.UpdateLastReceivedHandshake(new Handshake { - PeerConnectedEventData eventData = null; - _eventBus.Subscribe(e => + HandshakeData = new HandshakeData { - eventData = e; - return Task.CompletedTask; - }); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - var added = await _connectionService.ConnectAsync(endpoint); - added.ShouldBeTrue(); - - var peer = (GrpcPeer)_peerPool.FindPeerByEndpoint(endpoint); - peer.ShouldNotBeNull(); - peer.IsConnected.ShouldBeTrue(); - peer.SyncState.ShouldBe(SyncState.Syncing); - - eventData.ShouldNotBeNull(); - } - - [Fact] - public async Task DoHandshake_InvalidHandshake_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - var handshake = CreateHandshake(); - handshake.HandshakeData.ChainId = 100; - var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.ChainMismatch); - - handshake = CreateHandshake(); - handshake.HandshakeData.Version = 100; - result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.ProtocolMismatch); - - handshake = CreateHandshake(); - handshake.HandshakeData.Time = handshake.HandshakeData.Time - - TimestampHelper.DurationFromMilliseconds( - NetworkConstants.HandshakeTimeout + 1000); - result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.SignatureTimeout); - - handshake = CreateHandshake(); - handshake.HandshakeData.Pubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey); - result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.WrongSignature); - - handshake = await _handshakeProvider.GetHandshakeAsync(); - result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.ConnectionRefused); - } - - [Fact] - public async Task DoHandshake_AlreadyInHandshaking_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - var handshake = CreateHandshake(); - _peerPool.AddHandshakingPeer(endpoint.Host, handshake.HandshakeData.Pubkey.ToHex()); - - var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.ConnectionRefused); - - _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); - } - - [Fact] - public async Task DoHandshake_DialBackFailed_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); - var handshake = CreateHandshake(port: endpoint.Port); - - var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.InvalidConnection); - - _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); - } - - [Fact] - public async Task DoHandshake_AlreadyInPeerPool_Test() - { - var keyPair = CryptoHelper.GenerateKeyPair(); - var existPeer = CreatePeerAndAddToPeerPool(pubkey: keyPair.PublicKey.ToHex()); - - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - var handshake = CreateHandshake(keyPair, endpoint.Port); - - var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.RepeatedConnection); - } - - [Fact] - public async Task DoHandshake_Success_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - var handshake = CreateHandshake(port: endpoint.Port); - - var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); - result.Error.ShouldBe(HandshakeError.HandshakeOk); - - var peer = (GrpcPeer)_peerPool.FindPeerByEndpoint(endpoint); - peer.InboundSessionId.ShouldBe(result.Handshake.SessionId); - peer.LastSentHandshakeTime.ShouldBe(result.Handshake.HandshakeData.Time); - - _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); - } - - [Fact] - public async Task GetPeerByPubkey_Test() - { - var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); - _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBe(peer); - - await _connectionService.RemovePeerAsync(NetworkTestConstants.FakePubkey); - _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBeNull(); - } - - [Fact] - public async Task Disconnect_Test() - { - var peer1 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); - var peer2 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey2); - - _reconnectionService.SchedulePeerForReconnection(NetworkTestConstants.FakeIpEndpoint); - - await _connectionService.DisconnectAsync(peer1); - peer1.IsConnected.ShouldBeFalse(); - peer1.IsShutdown.ShouldBeTrue(); - - _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldBeNull(); - - _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBeNull(); - _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey2).ShouldNotBeNull(); - } - - [Fact] - public async Task DisconnectPeers_Test() - { - var peer1 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); - var peer2 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey2); - - await _connectionService.DisconnectPeersAsync(false); - peer1.IsConnected.ShouldBeFalse(); - peer1.IsShutdown.ShouldBeTrue(); - peer2.IsConnected.ShouldBeFalse(); - peer2.IsShutdown.ShouldBeTrue(); - } - - [Fact] - public async Task SchedulePeerReconnection_Test() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); - var result = await _connectionService.SchedulePeerReconnection(endpoint); - result.ShouldBeTrue(); - - _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldNotBeNull(); - } - - [Fact] - public async Task TrySchedulePeerReconnection_IsOutbound_Test() - { - var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); - peer.Info.IsInbound = false; + LastIrreversibleBlockHeight = 1, + BestChainHash = HashHelper.ComputeFrom("BestChainHash"), + BestChainHeight = 10, + Time = TimestampHelper.GetUtcNow().AddMinutes(-1) + } + }); + _peerPool.TryAddPeer(peer); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); - result.ShouldBeTrue(); + _connectionService.ConnectAsync(endpoint).ShouldThrow(); - peer.IsConnected.ShouldBeFalse(); - peer.IsShutdown.ShouldBeTrue(); + var currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldBeNull(); - _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldNotBeNull(); - } + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out endpoint); + currentPeer = _peerPool.FindPeerByEndpoint(endpoint); + currentPeer.ShouldBeNull(); + } - [Fact] - public async Task TrySchedulePeerReconnection_IsInboundAndNotInBootNode_Test() + [Fact] + public async Task DialPeerAsync_GoodPeer_Test() + { + PeerConnectedEventData eventData = null; + _eventBus.Subscribe(e => { - var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); - peer.Info.IsInbound = true; + eventData = e; + return Task.CompletedTask; + }); - var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); - result.ShouldBeFalse(); + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - peer.IsConnected.ShouldBeFalse(); - peer.IsShutdown.ShouldBeTrue(); + var added = await _connectionService.ConnectAsync(endpoint); + added.ShouldBeTrue(); - _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldBeNull(); - } + var peer = (GrpcPeer)_peerPool.FindPeerByEndpoint(endpoint); + peer.ShouldNotBeNull(); + peer.IsConnected.ShouldBeTrue(); + peer.SyncState.ShouldBe(SyncState.Syncing); - [Fact] - public void ConfirmHandshake_Test() - { - PeerConnectedEventData eventData = null; - _eventBus.Subscribe(e => - { - eventData = e; - return Task.CompletedTask; - }); - - _connectionService.ConfirmHandshake(NetworkTestConstants.FakePubkey); - eventData.ShouldBeNull(); - - var peer = CreatePeerAndAddToPeerPool(); - _connectionService.ConfirmHandshake(NetworkTestConstants.FakePubkey); - peer.IsConnected.ShouldBeTrue(); - peer.SyncState.ShouldBe(SyncState.Syncing); - - eventData.ShouldNotBeNull(); - } - - private Handshake CreateHandshake(ECKeyPair initiatorPeer = null, int port = 0) + eventData.ShouldNotBeNull(); + } + + [Fact] + public async Task DoHandshake_InvalidHandshake_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + + var handshake = CreateHandshake(); + handshake.HandshakeData.ChainId = 100; + var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.ChainMismatch); + + handshake = CreateHandshake(); + handshake.HandshakeData.Version = 100; + result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.ProtocolMismatch); + + handshake = CreateHandshake(); + handshake.HandshakeData.Time = handshake.HandshakeData.Time - + TimestampHelper.DurationFromMilliseconds( + NetworkConstants.HandshakeTimeout + 1000); + result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.SignatureTimeout); + + handshake = CreateHandshake(); + handshake.HandshakeData.Pubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey); + result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.WrongSignature); + + handshake = await _handshakeProvider.GetHandshakeAsync(); + result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.ConnectionRefused); + } + + [Fact] + public async Task DoHandshake_AlreadyInHandshaking_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + var handshake = CreateHandshake(); + _peerPool.AddHandshakingPeer(endpoint.Host, handshake.HandshakeData.Pubkey.ToHex()); + + var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.ConnectionRefused); + + _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); + } + + [Fact] + public async Task DoHandshake_DialBackFailed_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); + var handshake = CreateHandshake(port: endpoint.Port); + + var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.InvalidConnection); + + _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); + } + + [Fact] + public async Task DoHandshake_AlreadyInPeerPool_Test() + { + var keyPair = CryptoHelper.GenerateKeyPair(); + var existPeer = CreatePeerAndAddToPeerPool(pubkey: keyPair.PublicKey.ToHex()); + + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + var handshake = CreateHandshake(keyPair, endpoint.Port); + + var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.RepeatedConnection); + } + + [Fact] + public async Task DoHandshake_Success_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + var handshake = CreateHandshake(port: endpoint.Port); + + var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); + result.Error.ShouldBe(HandshakeError.HandshakeOk); + + var peer = (GrpcPeer)_peerPool.FindPeerByEndpoint(endpoint); + peer.InboundSessionId.ShouldBe(result.Handshake.SessionId); + peer.LastSentHandshakeTime.ShouldBe(result.Handshake.HandshakeData.Time); + + _peerPool.GetHandshakingPeers().ShouldNotContainKey(endpoint.Host); + } + + [Fact] + public async Task GetPeerByPubkey_Test() + { + var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); + _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBe(peer); + + await _connectionService.RemovePeerAsync(NetworkTestConstants.FakePubkey); + _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBeNull(); + } + + [Fact] + public async Task Disconnect_Test() + { + var peer1 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); + var peer2 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey2); + + _reconnectionService.SchedulePeerForReconnection(NetworkTestConstants.FakeIpEndpoint); + + await _connectionService.DisconnectAsync(peer1); + peer1.IsConnected.ShouldBeFalse(); + peer1.IsShutdown.ShouldBeTrue(); + + _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldBeNull(); + + _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey).ShouldBeNull(); + _connectionService.GetPeerByPubkey(NetworkTestConstants.FakePubkey2).ShouldNotBeNull(); + } + + [Fact] + public async Task DisconnectPeers_Test() + { + var peer1 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); + var peer2 = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey2); + + await _connectionService.DisconnectPeersAsync(false); + peer1.IsConnected.ShouldBeFalse(); + peer1.IsShutdown.ShouldBeTrue(); + peer2.IsConnected.ShouldBeFalse(); + peer2.IsShutdown.ShouldBeTrue(); + } + + [Fact] + public async Task SchedulePeerReconnection_Test() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var endpoint); + var result = await _connectionService.SchedulePeerReconnection(endpoint); + result.ShouldBeTrue(); + + _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldNotBeNull(); + } + + [Fact] + public async Task TrySchedulePeerReconnection_IsOutbound_Test() + { + var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); + peer.Info.IsInbound = false; + + var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); + result.ShouldBeTrue(); + + peer.IsConnected.ShouldBeFalse(); + peer.IsShutdown.ShouldBeTrue(); + + _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldNotBeNull(); + } + + [Fact] + public async Task TrySchedulePeerReconnection_IsInboundAndNotInBootNode_Test() + { + var peer = CreatePeerAndAddToPeerPool(pubkey: NetworkTestConstants.FakePubkey); + peer.Info.IsInbound = true; + + var result = await _connectionService.TrySchedulePeerReconnectionAsync(peer); + result.ShouldBeFalse(); + + peer.IsConnected.ShouldBeFalse(); + peer.IsShutdown.ShouldBeTrue(); + + _reconnectionService.GetReconnectingPeer(NetworkTestConstants.FakeIpEndpoint).ShouldBeNull(); + } + + [Fact] + public void ConfirmHandshake_Test() + { + PeerConnectedEventData eventData = null; + _eventBus.Subscribe(e => { - if (initiatorPeer == null) - initiatorPeer = CryptoHelper.GenerateKeyPair(); + eventData = e; + return Task.CompletedTask; + }); - var data = new HandshakeData - { - ChainId = _blockchainService.GetChainId(), - Version = KernelConstants.ProtocolVersion, - Pubkey = ByteString.CopyFrom(initiatorPeer.PublicKey), - Time = TimestampHelper.GetUtcNow(), - ListeningPort = port - }; + _connectionService.ConfirmHandshake(NetworkTestConstants.FakePubkey); + eventData.ShouldBeNull(); - var signature = - CryptoHelper.SignWithPrivateKey(initiatorPeer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); + var peer = CreatePeerAndAddToPeerPool(); + _connectionService.ConfirmHandshake(NetworkTestConstants.FakePubkey); + peer.IsConnected.ShouldBeTrue(); + peer.SyncState.ShouldBe(SyncState.Syncing); - return new Handshake {HandshakeData = data, Signature = ByteString.CopyFrom(signature)}; - } + eventData.ShouldNotBeNull(); + } + + private Handshake CreateHandshake(ECKeyPair initiatorPeer = null, int port = 0) + { + if (initiatorPeer == null) + initiatorPeer = CryptoHelper.GenerateKeyPair(); - private GrpcPeer CreatePeerAndAddToPeerPool(string ip = NetworkTestConstants.FakeIpEndpoint, - string pubkey = NetworkTestConstants.FakePubkey) + var data = new HandshakeData { - var peer = GrpcTestPeerHelper.CreateBasicPeer(ip, pubkey); - var added = _peerPool.TryAddPeer(peer); + ChainId = _blockchainService.GetChainId(), + Version = KernelConstants.ProtocolVersion, + Pubkey = ByteString.CopyFrom(initiatorPeer.PublicKey), + Time = TimestampHelper.GetUtcNow(), + ListeningPort = port + }; + + var signature = + CryptoHelper.SignWithPrivateKey(initiatorPeer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); + + return new Handshake { HandshakeData = data, Signature = ByteString.CopyFrom(signature) }; + } + + private GrpcPeer CreatePeerAndAddToPeerPool(string ip = NetworkTestConstants.FakeIpEndpoint, + string pubkey = NetworkTestConstants.FakePubkey) + { + var peer = GrpcTestPeerHelper.CreateBasicPeer(ip, pubkey); + var added = _peerPool.TryAddPeer(peer); - Assert.True(added); + Assert.True(added); - return peer; - } + return peer; } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerInvalidHandshakeTests.cs b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerInvalidHandshakeTests.cs index 10e4292abc..21aa36243a 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerInvalidHandshakeTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerInvalidHandshakeTests.cs @@ -1,27 +1,25 @@ using System.Threading.Tasks; -using AElf.OS.Network.Grpc; using AElf.OS.Network.Helpers; using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class PeerDialerInvalidHandshakeTests : PeerDialerInvalidHandshakeTestBase { - public class PeerDialerInvalidHandshakeTests : PeerDialerInvalidHandshakeTestBase + private readonly IPeerDialer _peerDialer; + + public PeerDialerInvalidHandshakeTests() { - private readonly IPeerDialer _peerDialer; + _peerDialer = GetRequiredService(); + } - public PeerDialerInvalidHandshakeTests() - { - _peerDialer = GetRequiredService(); - } + [Fact] + public async Task DialPeer_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); + var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - [Fact] - public async Task DialPeer_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); - var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - - grpcPeer.ShouldBeNull(); - } + grpcPeer.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerReplyErrorTests.cs b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerReplyErrorTests.cs index 50c745e537..93e638e214 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerReplyErrorTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerReplyErrorTests.cs @@ -1,27 +1,25 @@ using System.Threading.Tasks; -using AElf.OS.Network.Grpc; using AElf.OS.Network.Helpers; using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class PeerDialerReplyErrorTests : PeerDialerReplyErrorTestBase { - public class PeerDialerReplyErrorTests : PeerDialerReplyErrorTestBase + private readonly IPeerDialer _peerDialer; + + public PeerDialerReplyErrorTests() { - private readonly IPeerDialer _peerDialer; + _peerDialer = GetRequiredService(); + } - public PeerDialerReplyErrorTests() - { - _peerDialer = GetRequiredService(); - } + [Fact] + public async Task DialPeer_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); + var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - [Fact] - public async Task DialPeer_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); - var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - - grpcPeer.ShouldBeNull(); - } + grpcPeer.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerTests.cs b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerTests.cs index 02af13e345..05a9efdb3d 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Connection/PeerDialerTests.cs @@ -1,73 +1,71 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; -using AElf.OS.Network.Grpc; using AElf.OS.Network.Helpers; using AElf.OS.Network.Protocol; using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class PeerDialerTests : PeerDialerTestBase { - public class PeerDialerTests : PeerDialerTestBase + private readonly IBlockchainService _blockchainService; + private readonly IHandshakeProvider _handshakeProvider; + private readonly IPeerDialer _peerDialer; + + public PeerDialerTests() + { + _peerDialer = GetRequiredService(); + _blockchainService = GetRequiredService(); + _handshakeProvider = GetRequiredService(); + } + + [Fact] + public async Task DialPeer_Test() { - private readonly IPeerDialer _peerDialer; - private readonly IBlockchainService _blockchainService; - private readonly IHandshakeProvider _handshakeProvider; + AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); + var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - public PeerDialerTests() - { - _peerDialer = GetRequiredService(); - _blockchainService = GetRequiredService(); - _handshakeProvider = GetRequiredService(); - } + grpcPeer.ShouldNotBeNull(); + + grpcPeer.CurrentBlockHash.ShouldBe(HashHelper.ComputeFrom("BestChainHash")); + grpcPeer.CurrentBlockHeight.ShouldBe(10); + grpcPeer.LastKnownLibHeight.ShouldBe(1); + } + + [Fact] + public async Task DialPeer_InvalidEndpoint_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint); + var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - [Fact] - public async Task DialPeer_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); - var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - - grpcPeer.ShouldNotBeNull(); + grpcPeer.ShouldBeNull(); + } + + [Fact] + public async Task DialBackPeer_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); + var handshake = await _handshakeProvider.GetHandshakeAsync(); + + var grpcPeer = await _peerDialer.DialBackPeerAsync(endpoint, handshake); + + grpcPeer.ShouldNotBeNull(); + grpcPeer.CurrentBlockHash.ShouldBe(handshake.HandshakeData.BestChainHash); + grpcPeer.CurrentBlockHeight.ShouldBe(handshake.HandshakeData.BestChainHeight); + grpcPeer.LastKnownLibHeight.ShouldBe(handshake.HandshakeData.LastIrreversibleBlockHeight); + grpcPeer.Info.Pubkey.ShouldBe(handshake.HandshakeData.Pubkey.ToHex()); + grpcPeer.Info.ProtocolVersion.ShouldBe(handshake.HandshakeData.Version); + } + + [Fact] + public async Task DialBackPeer_InvalidEndpoint_Test() + { + AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint); + var handshake = await _handshakeProvider.GetHandshakeAsync(); - grpcPeer.CurrentBlockHash.ShouldBe(HashHelper.ComputeFrom("BestChainHash")); - grpcPeer.CurrentBlockHeight.ShouldBe(10); - grpcPeer.LastKnownLibHeight.ShouldBe(1); - } - - [Fact] - public async Task DialPeer_InvalidEndpoint_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint); - var grpcPeer = await _peerDialer.DialPeerAsync(endpoint); - - grpcPeer.ShouldBeNull(); - } + var grpcPeer = await _peerDialer.DialBackPeerAsync(endpoint, handshake); - [Fact] - public async Task DialBackPeer_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2000", out var endpoint); - var handshake = await _handshakeProvider.GetHandshakeAsync(); - - var grpcPeer = await _peerDialer.DialBackPeerAsync(endpoint, handshake); - - grpcPeer.ShouldNotBeNull(); - grpcPeer.CurrentBlockHash.ShouldBe(handshake.HandshakeData.BestChainHash); - grpcPeer.CurrentBlockHeight.ShouldBe(handshake.HandshakeData.BestChainHeight); - grpcPeer.LastKnownLibHeight.ShouldBe(handshake.HandshakeData.LastIrreversibleBlockHeight); - grpcPeer.Info.Pubkey.ShouldBe(handshake.HandshakeData.Pubkey.ToHex()); - grpcPeer.Info.ProtocolVersion.ShouldBe(handshake.HandshakeData.Version); - } - - [Fact] - public async Task DialBackPeer_InvalidEndpoint_Test() - { - AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint); - var handshake = await _handshakeProvider.GetHandshakeAsync(); - - var grpcPeer = await _peerDialer.DialBackPeerAsync(endpoint, handshake); - - grpcPeer.ShouldBeNull(); - } + grpcPeer.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Extensions/ClientInterceptorContextExtensionsTests.cs b/test/AElf.OS.Network.Grpc.Tests/Extensions/ClientInterceptorContextExtensionsTests.cs index 450af89b26..54b3e34742 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Extensions/ClientInterceptorContextExtensionsTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Extensions/ClientInterceptorContextExtensionsTests.cs @@ -3,33 +3,32 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc.Extensions +namespace AElf.OS.Network.Grpc.Extensions; + +public class ClientInterceptorContextExtensionsTests : GrpcNetworkTestBase { - public class ClientInterceptorContextExtensionsTests : GrpcNetworkTestBase + [Fact] + public void GetHeader_Test() { - [Fact] - public void GetHeader_Test() + var context = new ClientInterceptorContext(null, null, new CallOptions()); + context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); + + context = new ClientInterceptorContext(null, null, new CallOptions(new Metadata())); + context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); + + var data = new Metadata { - var context = new ClientInterceptorContext(null, null, new CallOptions()); - context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); - - context = new ClientInterceptorContext(null, null, new CallOptions(new Metadata())); - context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); - - Metadata data = new Metadata - { - { GrpcConstants.TimeoutMetadataKey, "TimeoutMetadata" }, - { GrpcConstants.RetryCountMetadataKey, "2" } - }; - context = new ClientInterceptorContext(null, null, new CallOptions(data)); - context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey).ShouldBe("TimeoutMetadata"); - context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBe("2"); - - context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey, true).ShouldBe("TimeoutMetadata"); - context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey, true).ShouldBe("2"); - - context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey).ShouldBeNull(); - context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); - } + { GrpcConstants.TimeoutMetadataKey, "TimeoutMetadata" }, + { GrpcConstants.RetryCountMetadataKey, "2" } + }; + context = new ClientInterceptorContext(null, null, new CallOptions(data)); + context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey).ShouldBe("TimeoutMetadata"); + context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBe("2"); + + context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey, true).ShouldBe("TimeoutMetadata"); + context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey, true).ShouldBe("2"); + + context.GetHeaderStringValue(GrpcConstants.TimeoutMetadataKey).ShouldBeNull(); + context.GetHeaderStringValue(GrpcConstants.RetryCountMetadataKey).ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkBaseTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkBaseTestModule.cs index e60e408577..4765c72ece 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkBaseTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkBaseTestModule.cs @@ -1,18 +1,17 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn(typeof(OSCoreTestAElfModule), typeof(GrpcNetworkModule))] +public class GrpcNetworkBaseTestModule : AElfModule { - [DependsOn(typeof(OSCoreTestAElfModule), typeof(GrpcNetworkModule))] - public class GrpcNetworkBaseTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o=> - { - o.ListeningPort = 2000; - o.MaxPeers = 2; - }); - } + o.ListeningPort = 2000; + o.MaxPeers = 2; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkConnectionWithBootNodesTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkConnectionWithBootNodesTestModule.cs index e042003a52..4caa9a2914 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkConnectionWithBootNodesTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkConnectionWithBootNodesTestModule.cs @@ -2,24 +2,23 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn(typeof(GrpcNetworkTestModule))] +public class GrpcNetworkConnectionWithBootNodesTestModule : AElfModule { - [DependsOn(typeof(GrpcNetworkTestModule))] - public class GrpcNetworkConnectionWithBootNodesTestModule: AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - Configure(o => + Configure(o => + { + o.ListeningPort = 2001; + o.MaxPeers = 2; + o.BootNodes = new List { - o.ListeningPort = 2001; - o.MaxPeers = 2; - o.BootNodes = new List - { - "127.0.0.1:2020" - }; - }); - } + "127.0.0.1:2020" + }; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerBootNodesTests.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerBootNodesTests.cs index 88848b9d7c..893c406ef8 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerBootNodesTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerBootNodesTests.cs @@ -3,45 +3,43 @@ using AElf.OS.Network.Application; using AElf.OS.Network.Events; using AElf.OS.Network.Infrastructure; -using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcNetworkServerBootNodesTests : GrpcNetworkWithBootNodesTestBase { - public class GrpcNetworkServerBootNodesTests : GrpcNetworkWithBootNodesTestBase - { - private readonly IAElfNetworkServer _networkServer; - private readonly ILocalEventBus _eventBus; - private readonly IReconnectionService _reconnectionService; + private readonly ILocalEventBus _eventBus; + private readonly IAElfNetworkServer _networkServer; + private readonly IReconnectionService _reconnectionService; - public GrpcNetworkServerBootNodesTests() - { - _networkServer = GetRequiredService(); - _eventBus = GetRequiredService(); - _reconnectionService = GetRequiredService(); - } + public GrpcNetworkServerBootNodesTests() + { + _networkServer = GetRequiredService(); + _eventBus = GetRequiredService(); + _reconnectionService = GetRequiredService(); + } - [Fact] - public async Task StartServer_Test() + [Fact] + public async Task StartServer_Test() + { + NetworkInitializedEvent received = null; + _eventBus.Subscribe(a => { - NetworkInitializedEvent received = null; - _eventBus.Subscribe(a => - { - received = a; - return Task.CompletedTask; - }); + received = a; + return Task.CompletedTask; + }); - await _networkServer.StartAsync(); + await _networkServer.StartAsync(); - received.ShouldNotBeNull(); + received.ShouldNotBeNull(); - var reconnections = _reconnectionService.GetPeersReadyForReconnection(null); - reconnections.Count.ShouldBe(1); - reconnections.First().Endpoint.ShouldBe("127.0.0.1:2018"); + var reconnections = _reconnectionService.GetPeersReadyForReconnection(null); + reconnections.Count.ShouldBe(1); + reconnections.First().Endpoint.ShouldBe("127.0.0.1:2018"); - await _networkServer.StopAsync(); - } + await _networkServer.StopAsync(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerTests.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerTests.cs index f62772e684..10c5e9d2f7 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkServerTests.cs @@ -8,120 +8,118 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcNetworkServerTests : GrpcNetworkTestBase { - public class GrpcNetworkServerTests : GrpcNetworkTestBase + private readonly ILocalEventBus _eventBus; + private readonly IAElfNetworkServer _networkServer; + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public GrpcNetworkServerTests() { - private readonly IAElfNetworkServer _networkServer; - private readonly ILocalEventBus _eventBus; - private readonly IPeerPool _peerPool; - private readonly IReconnectionService _reconnectionService; + _networkServer = GetRequiredService(); + _eventBus = GetRequiredService(); + _peerPool = GetRequiredService(); + _reconnectionService = GetRequiredService(); + } - public GrpcNetworkServerTests() - { - _networkServer = GetRequiredService(); - _eventBus = GetRequiredService(); - _peerPool = GetRequiredService(); - _reconnectionService = GetRequiredService(); - } - - private GrpcPeer AddPeerToPool(string ip = NetworkTestConstants.FakeIpEndpoint, - string pubkey = NetworkTestConstants.FakePubkey) - { - var peer = GrpcTestPeerHelper.CreateBasicPeer(ip, pubkey); - bool added = _peerPool.TryAddPeer(peer); - - Assert.True(added); + private GrpcPeer AddPeerToPool(string ip = NetworkTestConstants.FakeIpEndpoint, + string pubkey = NetworkTestConstants.FakePubkey) + { + var peer = GrpcTestPeerHelper.CreateBasicPeer(ip, pubkey); + var added = _peerPool.TryAddPeer(peer); - return peer; - } + Assert.True(added); - [Fact] - public async Task Start_Test() + return peer; + } + + [Fact] + public async Task Start_Test() + { + NetworkInitializedEvent eventData = null; + _eventBus.Subscribe(ed => { - NetworkInitializedEvent eventData = null; - _eventBus.Subscribe(ed => - { - eventData = ed; - return Task.CompletedTask; - }); + eventData = ed; + return Task.CompletedTask; + }); - await _networkServer.StartAsync(); - await _networkServer.StopAsync(); + await _networkServer.StartAsync(); + await _networkServer.StopAsync(); - eventData.ShouldNotBeNull(); - } + eventData.ShouldNotBeNull(); + } - [Fact] - public async Task Disconnect_Test() - { - await _networkServer.StartAsync(); - var peer = AddPeerToPool(); - peer.IsShutdown.ShouldBeFalse(); - await _networkServer.DisconnectAsync(peer); - peer.IsShutdown.ShouldBeTrue(); - - await _networkServer.StopAsync(); - } - - [Fact] - public async Task TrySchedulePeerReconnection_Test() - { - var peer = AddPeerToPool(); - var result = await _networkServer.TrySchedulePeerReconnectionAsync(peer); - result.ShouldBeTrue(); - - _reconnectionService.GetReconnectingPeer(peer.RemoteEndpoint.ToString()).ShouldNotBeNull(); - } - - [Fact] - public async Task DialPeerAsync_HostAlreadyInPool_ShouldReturnFalse() - { - var peer = AddPeerToPool(); - var added = await _networkServer.ConnectAsync(peer.RemoteEndpoint); - - added.ShouldBeFalse(); - } - - [Fact] - public async Task DialPeerAsync_GoodPeer_ShouldBeInPool() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); - - // two different hosts with the same pubkey. - var added = await _networkServer.ConnectAsync(endpoint); - - added.ShouldBeTrue(); - _peerPool.FindPeerByEndpoint(endpoint).ShouldNotBeNull(); - } - - - - [Fact] - public void DialPeerAsync_HandshakeNetProblem_ShouldThrowException() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.HandshakeWithNetExceptionIp, out var endpoint); - _networkServer.ConnectAsync(endpoint).ShouldThrow(); - - _peerPool.PeerCount.ShouldBe(0); - } - - [Fact] - public void DialPeerAsync_HandshakeDataProblem_ShouldThrowException() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.HandshakeWithDataExceptionIp, out var endpoint); - _networkServer.ConnectAsync(endpoint).ShouldThrow(); - - _peerPool.PeerCount.ShouldBe(0); - } - - [Fact] - public void DialPeerAsync_HandshakeError_ShouldThrowException() - { - AElfPeerEndpointHelper.TryParse(NetworkTestConstants.BadHandshakeIp, out var endpoint); - _networkServer.ConnectAsync(endpoint).ShouldThrow(); - - _peerPool.PeerCount.ShouldBe(0); - } + [Fact] + public async Task Disconnect_Test() + { + await _networkServer.StartAsync(); + var peer = AddPeerToPool(); + peer.IsShutdown.ShouldBeFalse(); + await _networkServer.DisconnectAsync(peer); + peer.IsShutdown.ShouldBeTrue(); + + await _networkServer.StopAsync(); + } + + [Fact] + public async Task TrySchedulePeerReconnection_Test() + { + var peer = AddPeerToPool(); + var result = await _networkServer.TrySchedulePeerReconnectionAsync(peer); + result.ShouldBeTrue(); + + _reconnectionService.GetReconnectingPeer(peer.RemoteEndpoint.ToString()).ShouldNotBeNull(); + } + + [Fact] + public async Task DialPeerAsync_HostAlreadyInPool_ShouldReturnFalse() + { + var peer = AddPeerToPool(); + var added = await _networkServer.ConnectAsync(peer.RemoteEndpoint); + + added.ShouldBeFalse(); + } + + [Fact] + public async Task DialPeerAsync_GoodPeer_ShouldBeInPool() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); + + // two different hosts with the same pubkey. + var added = await _networkServer.ConnectAsync(endpoint); + + added.ShouldBeTrue(); + _peerPool.FindPeerByEndpoint(endpoint).ShouldNotBeNull(); + } + + + [Fact] + public void DialPeerAsync_HandshakeNetProblem_ShouldThrowException() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.HandshakeWithNetExceptionIp, out var endpoint); + _networkServer.ConnectAsync(endpoint).ShouldThrow(); + + _peerPool.PeerCount.ShouldBe(0); + } + + [Fact] + public void DialPeerAsync_HandshakeDataProblem_ShouldThrowException() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.HandshakeWithDataExceptionIp, out var endpoint); + _networkServer.ConnectAsync(endpoint).ShouldThrow(); + + _peerPool.PeerCount.ShouldBe(0); + } + + [Fact] + public void DialPeerAsync_HandshakeError_ShouldThrowException() + { + AElfPeerEndpointHelper.TryParse(NetworkTestConstants.BadHandshakeIp, out var endpoint); + _networkServer.ConnectAsync(endpoint).ShouldThrow(); + + _peerPool.PeerCount.ShouldBe(0); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestBase.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestBase.cs index c2163d36ff..b7e2c34d47 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestBase.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestBase.cs @@ -6,60 +6,64 @@ using Xunit; [assembly: CollectionBehavior(DisableTestParallelization = true)] -namespace AElf.OS.Network.Grpc + +namespace AElf.OS.Network.Grpc; + +public class GrpcNetworkWithChainTestBase : AElfIntegratedTest { - public class GrpcNetworkWithChainTestBase : AElfIntegratedTest - { - } +} - public class GrpcNetworkTestBase : AElfIntegratedTest - { - } - - public class GrpcNetworkWithPeerTestBase : AElfIntegratedTest - { - } - - public class GrpcNetworkWithBootNodesTestBase : AElfIntegratedTest - { - } - - public class GrpcNetworkConnectionWithBootNodesTestBase : AElfIntegratedTest - { - } - - public class GrpcNetworkWithChainAndPeerTestBase : AElfIntegratedTest - { - } +public class GrpcNetworkTestBase : AElfIntegratedTest +{ +} - public class PeerDialerTestBase : AElfIntegratedTest - { - } - - public class PeerDialerInvalidHandshakeTestBase : AElfIntegratedTest +public class GrpcNetworkWithPeerTestBase : AElfIntegratedTest +{ +} + +public class GrpcNetworkWithBootNodesTestBase : AElfIntegratedTest +{ +} + +public class + GrpcNetworkConnectionWithBootNodesTestBase : AElfIntegratedTest +{ +} + +public class GrpcNetworkWithChainAndPeerTestBase : AElfIntegratedTest +{ +} + +public class PeerDialerTestBase : AElfIntegratedTest +{ +} + +public class PeerDialerInvalidHandshakeTestBase : AElfIntegratedTest +{ +} + +public class PeerDialerReplyErrorTestBase : AElfIntegratedTest +{ +} + +public class TestAsyncStreamReader : IAsyncStreamReader +{ + private readonly IEnumerator _enumerator; + + public TestAsyncStreamReader(IEnumerable data) { + _enumerator = data.GetEnumerator(); } - - public class PeerDialerReplyErrorTestBase : AElfIntegratedTest + + public Task MoveNext(CancellationToken cancellationToken) { + return Task.FromResult(_enumerator.MoveNext()); } - public class TestAsyncStreamReader : IAsyncStreamReader + public T Current => _enumerator.Current; + + public void Dispose() { - private IEnumerator _enumerator; - public TestAsyncStreamReader(IEnumerable data) - { - _enumerator = data.GetEnumerator(); - } - public void Dispose() - { - _enumerator.Dispose(); - } - public Task MoveNext(CancellationToken cancellationToken) - { - return Task.FromResult(_enumerator.MoveNext()); - } - - public T Current => _enumerator.Current; + _enumerator.Dispose(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestModule.cs index 916af8639c..21e6dab8d9 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkTestModule.cs @@ -8,236 +8,232 @@ using AElf.Kernel.Blockchain.Application; using AElf.Modularity; using AElf.OS.Network.Application; -using AElf.OS.Network.Grpc; -using AElf.OS.Network.Grpc.Helpers; +using AElf.OS.Network.Infrastructure; using AElf.OS.Network.Protocol; using AElf.Types; -using AElf.OS.Network.Infrastructure; using Grpc.Core; using Grpc.Core.Testing; using Microsoft.Extensions.DependencyInjection; using Moq; -using NSubstitute; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn(typeof(GrpcNetworkBaseTestModule))] +public class GrpcNetworkTestModule : AElfModule { - [DependsOn(typeof(GrpcNetworkBaseTestModule))] - public class GrpcNetworkTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o => + o.ListeningPort = 2001; + o.MaxPeers = 2; + }); + + context.Services.AddTransient(o => + { + var mockBlockchainService = new Mock(); + var keyPair = CryptoHelper.GenerateKeyPair(); + + mockBlockchainService.Setup(b => b.GetChainAsync()).ReturnsAsync(new Chain { - o.ListeningPort = 2001; - o.MaxPeers = 2; + Id = NetworkTestConstants.DefaultChainId }); - context.Services.AddTransient(o => - { - var mockBlockchainService = new Mock(); - var keyPair = CryptoHelper.GenerateKeyPair(); + mockBlockchainService.Setup(b => b.GetChainId()).Returns(NetworkTestConstants.DefaultChainId); - mockBlockchainService.Setup(b => b.GetChainAsync()).ReturnsAsync(new Chain + mockBlockchainService.Setup(b => b.GetBlockHeaderByHashAsync(It.IsAny())).ReturnsAsync( + NetworkTestHelper.CreateFakeBlockHeader(NetworkTestConstants.DefaultChainId, 1, keyPair)); + + return mockBlockchainService.Object; + }); + + context.Services.AddTransient(sp => + { + var mockDialer = new Mock(); + + mockDialer.Setup(d => + d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants.FakeIpEndpoint))) + .Returns(s => { - Id = NetworkTestConstants.DefaultChainId + var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.FakeIpEndpoint, + NetworkTestConstants.FakePubkey); + return Task.FromResult(peer); }); - mockBlockchainService.Setup(b => b.GetChainId()).Returns(NetworkTestConstants.DefaultChainId); + mockDialer.Setup(d => + d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants.FakeIpEndpoint2))) + .Returns(s => + { + var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.FakeIpEndpoint2, + NetworkTestConstants.FakePubkey); + return Task.FromResult(peer); + }); - mockBlockchainService.Setup(b => b.GetBlockHeaderByHashAsync(It.IsAny())).ReturnsAsync( - NetworkTestHelper.CreateFakeBlockHeader(NetworkTestConstants.DefaultChainId, 1, keyPair)); + mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants + .DialExceptionIpEndpoint))) + .Returns(Task.FromResult(null)); - return mockBlockchainService.Object; - }); + mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants.HandshakeWithNetExceptionIp))) + .Returns(s => + { + var mockClient = new Mock(); + mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), + It.IsAny(), CancellationToken.None)) + .Throws(new AggregateException()); - context.Services.AddTransient(sp => - { - var mockDialer = new Mock(); + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint2, + NetworkTestConstants.FakePubkey, + mockClient.Object); - mockDialer.Setup(d => - d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants.FakeIpEndpoint))) - .Returns(s => - { - var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.FakeIpEndpoint, - NetworkTestConstants.FakePubkey); - return Task.FromResult(peer); - }); + return Task.FromResult(peer); + }); - mockDialer.Setup(d => - d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants.FakeIpEndpoint2))) - .Returns(s => - { - var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.FakeIpEndpoint2, - NetworkTestConstants.FakePubkey); - return Task.FromResult(peer); - }); + // Incorrect handshake + mockDialer.Setup(d => + d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants.BadHandshakeIp))) + .Returns(s => + { + var handshakeReply = new HandshakeReply(); - mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants - .DialExceptionIpEndpoint))) - .Returns(Task.FromResult(null)); + var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), + () => { }); - mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants.HandshakeWithNetExceptionIp))) - .Returns(s => - { - var mockClient = new Mock(); - mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), - It.IsAny(), CancellationToken.None)) - .Throws(new AggregateException()); + var mockClient = new Mock(); + mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), + It.IsAny(), + CancellationToken.None)).Returns(handshakeCall); + mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), + It.IsAny(), It.IsAny(), + CancellationToken.None)).Throws(new AggregateException()); - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.FakeIpEndpoint2, - NetworkTestConstants.FakePubkey, - mockClient.Object); + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, + NetworkTestConstants.FakePubkey, mockClient.Object); - return Task.FromResult(peer); - }); + return Task.FromResult(peer); + }); - // Incorrect handshake - mockDialer.Setup(d => - d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants.BadHandshakeIp))) - .Returns((s) => - { - var handshakeReply = new HandshakeReply(); + // Incorrect handshake signature + mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants + .HandshakeWithDataExceptionIp))) + .Returns(async s => + { + var handshakeProvider = context.Services.GetServiceLazy().Value; + var handshake = await handshakeProvider.GetHandshakeAsync(); + handshake.HandshakeData.Time = null; + var handshakeReply = new HandshakeReply { Handshake = handshake }; - var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), - () => { }); + var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), + () => { }); - var mockClient = new Mock(); - mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), - It.IsAny(), - CancellationToken.None)).Returns(handshakeCall); - mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), - It.IsAny(), It.IsAny(), - CancellationToken.None)).Throws(new AggregateException()); + var mockClient = new Mock(); + mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), + It.IsAny(), + CancellationToken.None)).Returns(handshakeCall); - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, - NetworkTestConstants.FakePubkey, mockClient.Object); + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, + NetworkTestConstants.FakePubkey, mockClient.Object); - return Task.FromResult(peer); - }); + return peer; + }); - // Incorrect handshake signature - mockDialer.Setup(d => d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants - .HandshakeWithDataExceptionIp))) - .Returns(async (s) => - { - var handshakeProvider = context.Services.GetServiceLazy().Value; - var handshake = await handshakeProvider.GetHandshakeAsync(); - handshake.HandshakeData.Time = null; - var handshakeReply = new HandshakeReply {Handshake = handshake}; - - var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), - () => { }); - - var mockClient = new Mock(); - mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), - It.IsAny(), - CancellationToken.None)).Returns(handshakeCall); - - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, - NetworkTestConstants.FakePubkey, mockClient.Object); - - return peer; - }); - - // This peer will pass all checks with success. - mockDialer.Setup(d => - d.DialPeerAsync(It.Is(endPoint => - endPoint.ToString() == NetworkTestConstants.GoodPeerEndpoint))) - .Returns(s => + // This peer will pass all checks with success. + mockDialer.Setup(d => + d.DialPeerAsync(It.Is(endPoint => + endPoint.ToString() == NetworkTestConstants.GoodPeerEndpoint))) + .Returns(s => + { + var keyPair = CryptoHelper.GenerateKeyPair(); + var handshakeReply = new HandshakeReply { - var keyPair = CryptoHelper.GenerateKeyPair(); - var handshakeReply = new HandshakeReply - { - Handshake = NetworkTestHelper.CreateValidHandshake(keyPair, 10) - }; - var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), - () => { }); - var confirmHandshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(new VoidReply()), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), - () => { }); - - var mockClient = new Mock(); - mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), - It.IsAny(), - CancellationToken.None)).Returns(handshakeCall); - - mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), - It.IsAny(), It.IsAny(), - CancellationToken.None)).Returns(confirmHandshakeCall); - - var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, - NetworkTestConstants.FakePubkey, mockClient.Object); - peer.UpdateLastSentHandshake(handshakeReply.Handshake); - - return Task.FromResult(peer); - }); + Handshake = NetworkTestHelper.CreateValidHandshake(keyPair, 10) + }; + var handshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(handshakeReply), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), + () => { }); + var confirmHandshakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(new VoidReply()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), + () => { }); + + var mockClient = new Mock(); + mockClient.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny(), + It.IsAny(), + CancellationToken.None)).Returns(handshakeCall); + + mockClient.Setup(m => m.ConfirmHandshakeAsync(It.IsAny(), + It.IsAny(), It.IsAny(), + CancellationToken.None)).Returns(confirmHandshakeCall); + + var peer = GrpcTestPeerHelper.CreatePeerWithClient(NetworkTestConstants.GoodPeerEndpoint, + NetworkTestConstants.FakePubkey, mockClient.Object); + peer.UpdateLastSentHandshake(handshakeReply.Handshake); + + return Task.FromResult(peer); + }); - mockDialer.Setup(d => d.DialBackPeerAsync(It.IsAny(), It.IsAny())) - .Returns((endPoint, handshake) => + mockDialer.Setup(d => d.DialBackPeerAsync(It.IsAny(), It.IsAny())) + .Returns((endPoint, handshake) => + { + if (endPoint.ToString() == NetworkTestConstants.GoodPeerEndpoint) { - if (endPoint.ToString() == NetworkTestConstants.GoodPeerEndpoint) - { - var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.GoodPeerEndpoint, - NetworkTestConstants.FakePubkey); - return Task.FromResult(peer); - } + var peer = GrpcTestPeerHelper.CreateBasicPeer(NetworkTestConstants.GoodPeerEndpoint, + NetworkTestConstants.FakePubkey); + return Task.FromResult(peer); + } - return Task.FromResult(null); - }); + return Task.FromResult(null); + }); - return mockDialer.Object; - }); - } + return mockDialer.Object; + }); } +} - [DependsOn(typeof(GrpcNetworkTestModule))] - public class GrpcNetworkWithBootNodesTestModule : AElfModule +[DependsOn(typeof(GrpcNetworkTestModule))] +public class GrpcNetworkWithBootNodesTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - Configure(o => + Configure(o => + { + o.ListeningPort = 2001; + o.MaxPeers = 2; + o.BootNodes = new List { - o.ListeningPort = 2001; - o.MaxPeers = 2; - o.BootNodes = new List - { - "127.0.0.1:2018", - "127.0.0.1:2019", - "127.0.0.1:2020", - }; - }); + "127.0.0.1:2018", + "127.0.0.1:2019", + "127.0.0.1:2020" + }; + }); - services.AddTransient(provider => + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.ConnectAsync(It.IsAny())).Returns(endpoint => { - var mockService = new Mock(); - mockService.Setup(m => m.ConnectAsync(It.IsAny())).Returns(endpoint => - { - if (endpoint.Port == 2018) - return Task.FromResult(false); - return Task.FromResult(true); - }); - mockService.Setup(m => m.DisconnectAsync(It.IsAny(), It.IsAny())) - .Returns(Task.CompletedTask); + if (endpoint.Port == 2018) + return Task.FromResult(false); + return Task.FromResult(true); + }); + mockService.Setup(m => m.DisconnectAsync(It.IsAny(), It.IsAny())) + .Returns(Task.CompletedTask); - var reconnectionService = services.GetRequiredServiceLazy().Value; - mockService.Setup(m => m.SchedulePeerReconnection(It.IsAny())) - .Returns(endpoint => - Task.FromResult(reconnectionService.SchedulePeerForReconnection(endpoint.ToString()))); + var reconnectionService = services.GetRequiredServiceLazy().Value; + mockService.Setup(m => m.SchedulePeerReconnection(It.IsAny())) + .Returns(endpoint => + Task.FromResult(reconnectionService.SchedulePeerForReconnection(endpoint.ToString()))); - return mockService.Object; - }); - } + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainAndPeerTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainAndPeerTestModule.cs index 8aded57551..4f50ffbcaa 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainAndPeerTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainAndPeerTestModule.cs @@ -1,33 +1,23 @@ -using System; -using AElf.Kernel; using AElf.Modularity; -using AElf.OS.Network.Application; -using AElf.OS.Network.Grpc; -using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; -using AElf.OS.Network.Protocol.Types; -using Grpc.Core; using Microsoft.Extensions.DependencyInjection; -using Moq; -using QuickGraph; using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn( + typeof(GrpcNetworkWithChainTestModule), + typeof(GrpcNetworkWithPeerTestModule))] +public class GrpcNetworkWithChainAndPeerTestModule : AElfModule { - [DependsOn( - typeof(GrpcNetworkWithChainTestModule), - typeof(GrpcNetworkWithPeerTestModule))] - public class GrpcNetworkWithChainAndPeerTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var syncStateProvider = context.ServiceProvider.GetRequiredService(); - syncStateProvider.SetSyncTarget(-1); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var syncStateProvider = context.ServiceProvider.GetRequiredService(); + syncStateProvider.SetSyncTarget(-1); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainTestModule.cs index 6fd27a33ea..942305f47c 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithChainTestModule.cs @@ -1,33 +1,23 @@ -using System; -using AElf.Kernel; using AElf.Modularity; -using AElf.OS.Network.Application; -using AElf.OS.Network.Grpc; -using AElf.OS.Network.Helpers; using AElf.OS.Network.Infrastructure; -using AElf.OS.Network.Protocol.Types; -using Grpc.Core; using Microsoft.Extensions.DependencyInjection; -using Moq; -using QuickGraph; using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn( + typeof(OSCoreWithChainTestAElfModule), + typeof(GrpcNetworkBaseTestModule))] +public class GrpcNetworkWithChainTestModule : AElfModule { - [DependsOn( - typeof(OSCoreWithChainTestAElfModule), - typeof(GrpcNetworkBaseTestModule))] - public class GrpcNetworkWithChainTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var syncStateProvider = context.ServiceProvider.GetRequiredService(); - syncStateProvider.SetSyncTarget(-1); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var syncStateProvider = context.ServiceProvider.GetRequiredService(); + syncStateProvider.SetSyncTarget(-1); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithPeerTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithPeerTestModule.cs index cc9faf876b..bb0bc38eba 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithPeerTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcNetworkWithPeerTestModule.cs @@ -9,28 +9,28 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn(typeof(GrpcNetworkBaseTestModule))] +public class GrpcNetworkWithPeerTestModule : AElfModule { - [DependsOn(typeof(GrpcNetworkBaseTestModule))] - public class GrpcNetworkWithPeerTestModule : AElfModule + public override void OnApplicationInitialization(ApplicationInitializationContext context) { - public override void OnApplicationInitialization(ApplicationInitializationContext context) + var pool = context.ServiceProvider.GetRequiredService(); + var channel = new Channel(NetworkTestConstants.FakeIpEndpoint, ChannelCredentials.Insecure); + + var connectionInfo = new PeerConnectionInfo { - var pool = context.ServiceProvider.GetRequiredService(); - var channel = new Channel(NetworkTestConstants.FakeIpEndpoint, ChannelCredentials.Insecure); - - var connectionInfo = new PeerConnectionInfo - { - Pubkey = NetworkTestConstants.FakePubkey2, - ProtocolVersion = KernelConstants.ProtocolVersion, - ConnectionTime = TimestampHelper.GetUtcNow(), - IsInbound = true - }; - - if (!AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var peerEndpoint)) - throw new Exception($"Ip {NetworkTestConstants.FakeIpEndpoint} is invalid."); - - pool.TryAddPeer(new GrpcPeer(new GrpcClient(channel, new PeerService.PeerServiceClient(channel)), peerEndpoint, connectionInfo)); - } + Pubkey = NetworkTestConstants.FakePubkey2, + ProtocolVersion = KernelConstants.ProtocolVersion, + ConnectionTime = TimestampHelper.GetUtcNow(), + IsInbound = true + }; + + if (!AElfPeerEndpointHelper.TryParse(NetworkTestConstants.FakeIpEndpoint, out var peerEndpoint)) + throw new Exception($"Ip {NetworkTestConstants.FakeIpEndpoint} is invalid."); + + pool.TryAddPeer(new GrpcPeer(new GrpcClient(channel, new PeerService.PeerServiceClient(channel)), peerEndpoint, + connectionInfo)); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/GrpcPeerTests.cs b/test/AElf.OS.Network.Grpc.Tests/GrpcPeerTests.cs index c9c590d43b..856a51e97f 100644 --- a/test/AElf.OS.Network.Grpc.Tests/GrpcPeerTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/GrpcPeerTests.cs @@ -11,460 +11,458 @@ using Grpc.Core.Testing; using Moq; using Shouldly; -using Volo.Abp.Threading; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcPeerTests : GrpcNetworkWithChainTestBase { - public class GrpcPeerTests : GrpcNetworkWithChainTestBase + private readonly OSTestHelper _osTestHelper; + private readonly IPeerPool _pool; + + private readonly GrpcPeer _grpcPeer; + private readonly GrpcPeer _nonInterceptedPeer; + + public GrpcPeerTests() { - private readonly IPeerPool _pool; - private readonly OSTestHelper _osTestHelper; + _osTestHelper = GetRequiredService(); + _pool = GetRequiredService(); - private GrpcPeer _grpcPeer; - private GrpcPeer _nonInterceptedPeer; + _grpcPeer = GrpcTestPeerHelper.CreateNewPeer(); + _grpcPeer.IsConnected = true; + _nonInterceptedPeer = MockServiceClient("127.0.0.1:2000"); - public GrpcPeerTests() - { - _osTestHelper = GetRequiredService(); - _pool = GetRequiredService(); + _pool.TryAddPeer(_grpcPeer); + } - _grpcPeer = GrpcTestPeerHelper.CreateNewPeer(); - _grpcPeer.IsConnected = true; - _nonInterceptedPeer = MockServiceClient("127.0.0.1:2000"); + [Fact] + public void KnowsBlock_Test() + { + var hash = HashHelper.ComputeFrom("TestHash"); - _pool.TryAddPeer(_grpcPeer); - } + _grpcPeer.KnowsBlock(hash).ShouldBeFalse(); + _grpcPeer.TryAddKnownBlock(hash).ShouldBeTrue(); + _grpcPeer.KnowsBlock(hash).ShouldBeTrue(); + _grpcPeer.TryAddKnownBlock(hash).ShouldBeFalse(); + } + + [Fact] + public void KnowsTransaction_Test() + { + var hash = HashHelper.ComputeFrom("TransactionHash"); - [Fact] - public void KnowsBlock_Test() + _grpcPeer.KnowsTransaction(hash).ShouldBeFalse(); + _grpcPeer.TryAddKnownTransaction(hash).ShouldBeTrue(); + _grpcPeer.KnowsTransaction(hash).ShouldBeTrue(); + _grpcPeer.TryAddKnownTransaction(hash).ShouldBeFalse(); + } + + [Fact] + public void UpdateLastKnownLib_Test() + { + var libAnnouncement = new LibAnnouncement { - var hash = HashHelper.ComputeFrom("TestHash"); - - _grpcPeer.KnowsBlock(hash).ShouldBeFalse(); - _grpcPeer.TryAddKnownBlock(hash).ShouldBeTrue(); - _grpcPeer.KnowsBlock(hash).ShouldBeTrue(); - _grpcPeer.TryAddKnownBlock(hash).ShouldBeFalse(); - } - - [Fact] - public void KnowsTransaction_Test() + LibHeight = 100, + LibHash = HashHelper.ComputeFrom(100) + }; + _grpcPeer.UpdateLastKnownLib(libAnnouncement); + _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); + _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); + + libAnnouncement = new LibAnnouncement { - var hash = HashHelper.ComputeFrom("TransactionHash"); - - _grpcPeer.KnowsTransaction(hash).ShouldBeFalse(); - _grpcPeer.TryAddKnownTransaction(hash).ShouldBeTrue(); - _grpcPeer.KnowsTransaction(hash).ShouldBeTrue(); - _grpcPeer.TryAddKnownTransaction(hash).ShouldBeFalse(); - } + LibHeight = 101, + LibHash = HashHelper.ComputeFrom(101) + }; + _grpcPeer.UpdateLastKnownLib(libAnnouncement); + _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); + _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); + + var wrongLibAnnouncement = new LibAnnouncement + { + LibHeight = 90, + LibHash = HashHelper.ComputeFrom(90) + }; + _grpcPeer.UpdateLastKnownLib(wrongLibAnnouncement); + _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); + _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); + } + + [Fact] + public void EnqueueBlock_ShouldExecuteCallback_Test() + { + var executed = new AutoResetEvent(false); - [Fact] - public void UpdateLastKnownLib_Test() + NetworkException exception = null; + var called = false; + _nonInterceptedPeer.EnqueueBlock(new BlockWithTransactions(), ex => { - var libAnnouncement = new LibAnnouncement - { - LibHeight = 100, - LibHash = HashHelper.ComputeFrom(100) - }; - _grpcPeer.UpdateLastKnownLib(libAnnouncement); - _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); - _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); - - libAnnouncement = new LibAnnouncement - { - LibHeight = 101, - LibHash = HashHelper.ComputeFrom(101) - }; - _grpcPeer.UpdateLastKnownLib(libAnnouncement); - _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); - _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); - - var wrongLibAnnouncement = new LibAnnouncement - { - LibHeight = 90, - LibHash = HashHelper.ComputeFrom(90) - }; - _grpcPeer.UpdateLastKnownLib(wrongLibAnnouncement); - _grpcPeer.LastKnownLibHash.ShouldBe(libAnnouncement.LibHash); - _grpcPeer.LastKnownLibHeight.ShouldBe(libAnnouncement.LibHeight); - } + exception = ex; + called = true; + executed.Set(); + }); + + executed.WaitOne(); + exception.ShouldBeNull(); + called.ShouldBeTrue(); + } - [Fact] - public void EnqueueBlock_ShouldExecuteCallback_Test() + [Fact] + public void EnqueueTransaction_ShouldExecuteCallback_Test() + { + var executed = new AutoResetEvent(false); + + NetworkException exception = null; + var transaction = new Transaction(); + var called = false; + _nonInterceptedPeer.EnqueueTransaction(transaction, ex => { - AutoResetEvent executed = new AutoResetEvent(false); + exception = ex; + called = true; + executed.Set(); + }); + + executed.WaitOne(); + exception.ShouldBeNull(); + called.ShouldBeTrue(); + } - NetworkException exception = null; - bool called = false; - _nonInterceptedPeer.EnqueueBlock(new BlockWithTransactions(), ex => + [Fact] + public void EnqueueAnnouncement_ShouldExecuteCallback_Test() + { + var executed = new AutoResetEvent(false); + + NetworkException exception = null; + var called = false; + _nonInterceptedPeer.EnqueueAnnouncement(new BlockAnnouncement(), ex => + { + exception = ex; + called = true; + executed.Set(); + }); + + executed.WaitOne(); + exception.ShouldBeNull(); + called.ShouldBeTrue(); + } + + [Fact] + public void EnqueueLibAnnouncement_ShouldExecuteCallback_Test() + { + var executed = new AutoResetEvent(false); + + NetworkException exception = null; + var called = false; + _nonInterceptedPeer.EnqueueLibAnnouncement(new LibAnnouncement(), ex => + { + exception = ex; + called = true; + executed.Set(); + }); + + executed.WaitOne(); + exception.ShouldBeNull(); + called.ShouldBeTrue(); + } + + [Fact] + public void EnqueueAnnouncement_WithPeerNotReady_Test() + { + var executed = new AutoResetEvent(false); + + NetworkException exception = null; + _nonInterceptedPeer.IsConnected = false; + Should.Throw(() => + _nonInterceptedPeer.EnqueueAnnouncement(new BlockAnnouncement(), ex => { exception = ex; - called = true; executed.Set(); - }); + })); + } - executed.WaitOne(); - exception.ShouldBeNull(); - called.ShouldBeTrue(); - } + [Fact] + public void EnqueueBlock_WithPeerNotReady_Test() + { + var executed = new AutoResetEvent(false); - [Fact] - public void EnqueueTransaction_ShouldExecuteCallback_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + NetworkException exception = null; + _nonInterceptedPeer.IsConnected = false; - NetworkException exception = null; - var transaction = new Transaction(); - bool called = false; - _nonInterceptedPeer.EnqueueTransaction(transaction, ex => + Should.Throw(() => + _nonInterceptedPeer.EnqueueBlock(new BlockWithTransactions(), ex => { exception = ex; - called = true; executed.Set(); - }); + })); + } - executed.WaitOne(); - exception.ShouldBeNull(); - called.ShouldBeTrue(); - } + [Fact] + public void EnqueueTransaction_WithPeerNotReady_Test() + { + var executed = new AutoResetEvent(false); - [Fact] - public void EnqueueAnnouncement_ShouldExecuteCallback_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + NetworkException exception = null; + _nonInterceptedPeer.IsConnected = false; - NetworkException exception = null; - var called = false; - _nonInterceptedPeer.EnqueueAnnouncement(new BlockAnnouncement(), ex => + Should.Throw(() => + _nonInterceptedPeer.EnqueueTransaction(new Transaction(), ex => { exception = ex; - called = true; executed.Set(); - }); + })); + } - executed.WaitOne(); - exception.ShouldBeNull(); - called.ShouldBeTrue(); - } - - [Fact] - public void EnqueueLibAnnouncement_ShouldExecuteCallback_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + [Fact] + public void EnqueueLibAnnouncement_WithPeerNotReady_Test() + { + var executed = new AutoResetEvent(false); - NetworkException exception = null; - bool called = false; + NetworkException exception = null; + _nonInterceptedPeer.IsConnected = false; + + Should.Throw(() => _nonInterceptedPeer.EnqueueLibAnnouncement(new LibAnnouncement(), ex => { exception = ex; - called = true; executed.Set(); - }); + })); + } - executed.WaitOne(); - exception.ShouldBeNull(); - called.ShouldBeTrue(); - } + [Fact] + public async Task DisconnectAsync_Test() + { + _grpcPeer.IsReady.ShouldBeTrue(); + _grpcPeer.IsShutdown.ShouldBeFalse(); + _grpcPeer.IsConnected.ShouldBeTrue(); + _grpcPeer.IsInvalid.ShouldBeFalse(); - [Fact] - public void EnqueueAnnouncement_WithPeerNotReady_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); - - NetworkException exception = null; - _nonInterceptedPeer.IsConnected = false; - Should.Throw(() => - _nonInterceptedPeer.EnqueueAnnouncement(new BlockAnnouncement(), ex => - { - exception = ex; - executed.Set(); - })); - } - - [Fact] - public void EnqueueBlock_WithPeerNotReady_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + await _grpcPeer.DisconnectAsync(false); - NetworkException exception = null; - _nonInterceptedPeer.IsConnected = false; + _grpcPeer.IsShutdown.ShouldBeTrue(); + _grpcPeer.IsConnected.ShouldBeFalse(); + _grpcPeer.IsReady.ShouldBeFalse(); + _grpcPeer.IsInvalid.ShouldBeFalse(); + _grpcPeer.ConnectionStatus.ShouldBe("Shutdown"); - Should.Throw(()=> - _nonInterceptedPeer.EnqueueBlock(new BlockWithTransactions(), ex => - { - exception = ex; - executed.Set(); - })); - } - - [Fact] - public void EnqueueTransaction_WithPeerNotReady_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + _grpcPeer.Info.ConnectionTime = TimestampHelper.GetUtcNow().AddSeconds(-11); + _grpcPeer.IsInvalid.ShouldBeTrue(); + } - NetworkException exception = null; - _nonInterceptedPeer.IsConnected = false; + [Fact] + public async Task CheckHealth_Test() + { + var mockClient = new Mock(); + mockClient.Setup(c => + c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(new HealthCheckReply())); + var grpcPeer = CreatePeer(mockClient.Object); + await grpcPeer.CheckHealthAsync(); + } - Should.Throw(()=> - _nonInterceptedPeer.EnqueueTransaction(new Transaction(), ex => - { - exception = ex; - executed.Set(); - })); - } - - [Fact] - public void EnqueueLibAnnouncement_WithPeerNotReady_Test() - { - AutoResetEvent executed = new AutoResetEvent(false); + [Fact] + public async Task GetBlockByHash_Test() + { + var block = new BlockWithTransactions + { Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header }; + + var mockClient = new Mock(); + mockClient.Setup(c => + c.RequestBlockAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(new BlockReply { Block = block })); + var grpcPeer = CreatePeer(mockClient.Object); + + var result = await grpcPeer.GetBlockByHashAsync(block.GetHash()); + result.ShouldBe(block); + + var metrics = grpcPeer.GetRequestMetrics(); + metrics["GetBlock"].Count.ShouldBe(1); + metrics["GetBlock"][0].MethodName.ShouldContain("GetBlock"); + metrics["GetBlock"][0].Info.ShouldContain("Block request for"); + } + + [Fact] + public async Task GetBlocks_Test() + { + var block = new BlockWithTransactions + { Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header }; + var blockList = new BlockList(); + blockList.Blocks.Add(block); + + var mockClient = new Mock(); + mockClient.Setup(c => + c.RequestBlocksAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(blockList)); + var grpcPeer = CreatePeer(mockClient.Object); + + var result = await grpcPeer.GetBlocksAsync(block.Header.PreviousBlockHash, 1); + result.ShouldBe(blockList.Blocks); + + var metrics = grpcPeer.GetRequestMetrics(); + metrics["GetBlocks"].Count.ShouldBe(1); + metrics["GetBlocks"][0].MethodName.ShouldContain("GetBlocks"); + metrics["GetBlocks"][0].Info.ShouldContain("Get blocks for"); + } - NetworkException exception = null; - _nonInterceptedPeer.IsConnected = false; + [Fact] + public async Task GetNodes_Test() + { + var nodeList = new NodeList(); + nodeList.Nodes.Add(new NodeInfo { Endpoint = "127.0.0.1:123", Pubkey = ByteString.Empty }); + + var mockClient = new Mock(); + mockClient.Setup(c => + c.GetNodesAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(nodeList)); + var grpcPeer = CreatePeer(mockClient.Object); + + var result = await grpcPeer.GetNodesAsync(); + result.ShouldBe(nodeList); + } - Should.Throw(()=> - _nonInterceptedPeer.EnqueueLibAnnouncement(new LibAnnouncement(), ex => - { - exception = ex; - executed.Set(); - })); - } + [Fact] + public async Task RecordMetric_Test() + { + var block = new BlockWithTransactions + { Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header }; - [Fact] - public async Task DisconnectAsync_Test() + var mockClient = new Mock(); + mockClient.Setup(c => + c.RequestBlockAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(new BlockReply { Block = block })); + + var blockList = new BlockList(); + blockList.Blocks.Add(block); + + mockClient.Setup(c => + c.RequestBlocksAsync(It.IsAny(), It.IsAny(), null, + CancellationToken.None)) + .Returns(MockAsyncUnaryCall(blockList)); + var grpcPeer = CreatePeer(mockClient.Object); + + for (var i = 0; i < 101; i++) { - _grpcPeer.IsReady.ShouldBeTrue(); - _grpcPeer.IsShutdown.ShouldBeFalse(); - _grpcPeer.IsConnected.ShouldBeTrue(); - _grpcPeer.IsInvalid.ShouldBeFalse(); - - await _grpcPeer.DisconnectAsync(false); - - _grpcPeer.IsShutdown.ShouldBeTrue(); - _grpcPeer.IsConnected.ShouldBeFalse(); - _grpcPeer.IsReady.ShouldBeFalse(); - _grpcPeer.IsInvalid.ShouldBeFalse(); - _grpcPeer.ConnectionStatus.ShouldBe("Shutdown"); - - _grpcPeer.Info.ConnectionTime = TimestampHelper.GetUtcNow().AddSeconds(-11); - _grpcPeer.IsInvalid.ShouldBeTrue(); + await grpcPeer.GetBlockByHashAsync(block.GetHash()); + await grpcPeer.GetBlocksAsync(block.Header.PreviousBlockHash, 1); } - [Fact] - public async Task CheckHealth_Test() + var metrics = grpcPeer.GetRequestMetrics(); + metrics["GetBlocks"].Count.ShouldBe(100); + metrics["GetBlock"].Count.ShouldBe(100); + } + + [Fact] + public async Task HandleObjectDisposedException_Test() + { + var mockClient = new Mock(); + mockClient.Setup(c => + c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, CancellationToken.None)) + .Throws(new ObjectDisposedException("ObjectDisposedException")); + var grpcPeer = CreatePeer(mockClient.Object); + grpcPeer.CheckHealthAsync() + .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); + } + + [Fact] + public async Task HandleRpcException_Test() + { { var mockClient = new Mock(); mockClient.Setup(c => c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, CancellationToken.None)) - .Returns(MockAsyncUnaryCall(new HealthCheckReply())); + .Throws(new AggregateException(new RpcException(new Status(StatusCode.Cancelled, "")))); var grpcPeer = CreatePeer(mockClient.Object); - await grpcPeer.CheckHealthAsync(); + grpcPeer.CheckHealthAsync() + .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); } - [Fact] - public async Task GetBlockByHash_Test() { - var block = new BlockWithTransactions - {Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header}; - var mockClient = new Mock(); mockClient.Setup(c => - c.RequestBlockAsync(It.IsAny(), It.IsAny(), null, + c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, CancellationToken.None)) - .Returns(MockAsyncUnaryCall(new BlockReply {Block = block})); + .Throws(new AggregateException()); var grpcPeer = CreatePeer(mockClient.Object); - - var result = await grpcPeer.GetBlockByHashAsync(block.GetHash()); - result.ShouldBe(block); - - var metrics = grpcPeer.GetRequestMetrics(); - metrics["GetBlock"].Count.ShouldBe(1); - metrics["GetBlock"][0].MethodName.ShouldContain("GetBlock"); - metrics["GetBlock"][0].Info.ShouldContain("Block request for"); + + grpcPeer.CheckHealthAsync() + .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); } - - [Fact] - public async Task GetBlocks_Test() - { - var block = new BlockWithTransactions - {Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header}; - var blockList = new BlockList(); - blockList.Blocks.Add(block); + { var mockClient = new Mock(); mockClient.Setup(c => - c.RequestBlocksAsync(It.IsAny(), It.IsAny(), null, + c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, CancellationToken.None)) - .Returns(MockAsyncUnaryCall(blockList)); + .Throws(new AggregateException(new RpcException(new Status(StatusCode.Cancelled, "")))); var grpcPeer = CreatePeer(mockClient.Object); + await grpcPeer.DisconnectAsync(false); - var result = await grpcPeer.GetBlocksAsync(block.Header.PreviousBlockHash, 1); - result.ShouldBe(blockList.Blocks); - - var metrics = grpcPeer.GetRequestMetrics(); - metrics["GetBlocks"].Count.ShouldBe(1); - metrics["GetBlocks"][0].MethodName.ShouldContain("GetBlocks"); - metrics["GetBlocks"][0].Info.ShouldContain("Get blocks for"); + grpcPeer.CheckHealthAsync() + .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); } - - [Fact] - public async Task GetNodes_Test() - { - var nodeList = new NodeList(); - nodeList.Nodes.Add(new NodeInfo {Endpoint = "127.0.0.1:123", Pubkey = ByteString.Empty}); + } - var mockClient = new Mock(); - mockClient.Setup(c => - c.GetNodesAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Returns(MockAsyncUnaryCall(nodeList)); - var grpcPeer = CreatePeer(mockClient.Object); + private GrpcPeer CreatePeer(PeerService.PeerServiceClient client) + { + return GrpcTestPeerHelper.CreatePeerWithClient("127.0.0.1:2000", NetworkTestConstants.FakePubkey, client); + } - var result = await grpcPeer.GetNodesAsync(); - result.ShouldBe(nodeList); - } + private GrpcPeer MockServiceClient(string ipAddress) + { + var mockClient = new Mock(); + var testCompletionSource = Task.FromResult(new VoidReply()); - [Fact] - public async Task RecordMetric_Test() - { - var block = new BlockWithTransactions - {Header = _osTestHelper.GenerateBlock(HashHelper.ComputeFrom("PreBlockHash"), 100).Header}; + // setup mock announcement stream + var announcementStreamCall = MockStreamCall(testCompletionSource); + mockClient.Setup(m => m.AnnouncementBroadcastStream(It.IsAny(), null, CancellationToken.None)) + .Returns(announcementStreamCall); - var mockClient = new Mock(); - mockClient.Setup(c => - c.RequestBlockAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Returns(MockAsyncUnaryCall(new BlockReply {Block = block})); - - var blockList = new BlockList(); - blockList.Blocks.Add(block); + // setup mock transaction stream + var transactionStreamCall = MockStreamCall(testCompletionSource); + mockClient.Setup(m => m.TransactionBroadcastStream(It.IsAny(), null, CancellationToken.None)) + .Returns(transactionStreamCall); - mockClient.Setup(c => - c.RequestBlocksAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Returns(MockAsyncUnaryCall(blockList)); - var grpcPeer = CreatePeer(mockClient.Object); + // setup mock block stream + var blockStreamCall = MockStreamCall(testCompletionSource); + mockClient.Setup(m => m.BlockBroadcastStream(It.IsAny(), null, CancellationToken.None)) + .Returns(blockStreamCall); - for (var i = 0; i < 101; i++) - { - await grpcPeer.GetBlockByHashAsync(block.GetHash()); - await grpcPeer.GetBlocksAsync(block.Header.PreviousBlockHash, 1); - } + // setup mock lib stream + var libAnnouncementStreamCall = MockStreamCall(testCompletionSource); + mockClient.Setup(m => m.LibAnnouncementBroadcastStream(It.IsAny(), null, CancellationToken.None)) + .Returns(libAnnouncementStreamCall); - var metrics = grpcPeer.GetRequestMetrics(); - metrics["GetBlocks"].Count.ShouldBe(100); - metrics["GetBlock"].Count.ShouldBe(100); - } + // create peer + var grpcPeer = GrpcTestPeerHelper.CreatePeerWithClient(ipAddress, + NetworkTestConstants.FakePubkey, mockClient.Object); - [Fact] - public async Task HandleObjectDisposedException_Test() - { - var mockClient = new Mock(); - mockClient.Setup(c => - c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, CancellationToken.None)) - .Throws(new ObjectDisposedException("ObjectDisposedException")); - var grpcPeer = CreatePeer(mockClient.Object); - grpcPeer.CheckHealthAsync() - .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); - } - - [Fact] - public async Task HandleRpcException_Test() - { - { - var mockClient = new Mock(); - mockClient.Setup(c => - c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Throws(new AggregateException(new RpcException(new Status(StatusCode.Cancelled, "")))); - var grpcPeer = CreatePeer(mockClient.Object); - grpcPeer.CheckHealthAsync() - .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); - } + grpcPeer.IsConnected = true; - { - var mockClient = new Mock(); - mockClient.Setup(c => - c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Throws(new AggregateException()); - var grpcPeer = CreatePeer(mockClient.Object); - - grpcPeer.CheckHealthAsync() - .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); - } - - { - var mockClient = new Mock(); - mockClient.Setup(c => - c.CheckHealthAsync(It.IsAny(), It.IsAny(), null, - CancellationToken.None)) - .Throws(new AggregateException(new RpcException(new Status(StatusCode.Cancelled, "")))); - var grpcPeer = CreatePeer(mockClient.Object); - await grpcPeer.DisconnectAsync(false); - - grpcPeer.CheckHealthAsync() - .ShouldThrow().ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); - } - } + return grpcPeer; + } - private GrpcPeer CreatePeer(PeerService.PeerServiceClient client) - { - return GrpcTestPeerHelper.CreatePeerWithClient("127.0.0.1:2000", NetworkTestConstants.FakePubkey, client); - } + private AsyncClientStreamingCall MockStreamCall(Task replyTask) where TResp : new() + { + var mockRequestStream = new Mock>(); + mockRequestStream.Setup(m => m.WriteAsync(It.IsAny())) + .Returns(replyTask); - private GrpcPeer MockServiceClient(string ipAddress) - { - var mockClient = new Mock(); - var testCompletionSource = Task.FromResult(new VoidReply()); - - // setup mock announcement stream - var announcementStreamCall = MockStreamCall(testCompletionSource); - mockClient.Setup(m => m.AnnouncementBroadcastStream(It.IsAny(), null, CancellationToken.None)) - .Returns(announcementStreamCall); - - // setup mock transaction stream - var transactionStreamCall = MockStreamCall(testCompletionSource); - mockClient.Setup(m => m.TransactionBroadcastStream(It.IsAny(), null, CancellationToken.None)) - .Returns(transactionStreamCall); - - // setup mock block stream - var blockStreamCall = MockStreamCall(testCompletionSource); - mockClient.Setup(m => m.BlockBroadcastStream(It.IsAny(), null, CancellationToken.None)) - .Returns(blockStreamCall); - - // setup mock lib stream - var libAnnouncementStreamCall = MockStreamCall(testCompletionSource); - mockClient.Setup(m => m.LibAnnouncementBroadcastStream(It.IsAny(), null, CancellationToken.None)) - .Returns(libAnnouncementStreamCall); - - // create peer - var grpcPeer = GrpcTestPeerHelper.CreatePeerWithClient(ipAddress, - NetworkTestConstants.FakePubkey, mockClient.Object); - - grpcPeer.IsConnected = true; - - return grpcPeer; - } - - private AsyncClientStreamingCall MockStreamCall(Task replyTask) where TResp : new() - { - var mockRequestStream = new Mock>(); - mockRequestStream.Setup(m => m.WriteAsync(It.IsAny())) - .Returns(replyTask); - - var call = TestCalls.AsyncClientStreamingCall(mockRequestStream.Object, Task.FromResult(new TResp()), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); - - return call; - } - - private AsyncUnaryCall MockAsyncUnaryCall(TResponse reply) where TResponse : new() - { - var call = TestCalls.AsyncUnaryCall(Task.FromResult(reply), - Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + var call = TestCalls.AsyncClientStreamingCall(mockRequestStream.Object, Task.FromResult(new TResp()), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); - return call; - } + return call; + } + + private AsyncUnaryCall MockAsyncUnaryCall(TResponse reply) where TResponse : new() + { + var call = TestCalls.AsyncUnaryCall(Task.FromResult(reply), + Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + + return call; } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Helpers/GrpcTestPeerHelper.cs b/test/AElf.OS.Network.Grpc.Tests/Helpers/GrpcTestPeerHelper.cs index 81fc21b9e5..1d448f868d 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Helpers/GrpcTestPeerHelper.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Helpers/GrpcTestPeerHelper.cs @@ -1,67 +1,72 @@ using AElf.Kernel; -using AElf.OS.Network.Grpc; using AElf.OS.Network.Helpers; using AElf.OS.Network.Protocol.Types; using Grpc.Core; using Grpc.Core.Interceptors; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public static class GrpcTestPeerHelper { - public static class GrpcTestPeerHelper + private static Channel CreateMockChannel() { - private static Channel CreateMockChannel() => new Channel("127.0.0.1:9999", ChannelCredentials.Insecure); - - public static GrpcPeer CreateBasicPeer(string ip, string pubkey) - { - return CreatePeerWithInfo(ip, new PeerConnectionInfo { Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2}, ConnectionTime = TimestampHelper.GetUtcNow()}); - } + return new("127.0.0.1:9999", ChannelCredentials.Insecure); + } - public static GrpcPeer CreatePeerWithInfo(string ip, PeerConnectionInfo info) - { - AElfPeerEndpointHelper.TryParse(ip, out var endpoint); - var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), null), endpoint, info); - peer.InboundSessionId = new byte[] {0, 1, 2}; - return peer; - } + public static GrpcPeer CreateBasicPeer(string ip, string pubkey) + { + return CreatePeerWithInfo(ip, + new PeerConnectionInfo + { Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2 }, ConnectionTime = TimestampHelper.GetUtcNow() }); + } - public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client) - { - AElfPeerEndpointHelper.TryParse(ip, out var endpoint); - var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), client), endpoint, new PeerConnectionInfo { Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2} }); - peer.InboundSessionId = new byte[] {0, 1, 2}; - return peer; - } - - public static GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true, string publicKey = null) - { - var pubkey = publicKey ?? NetworkTestConstants.FakePubkey; - var channel = new Channel(ipAddress, ChannelCredentials.Insecure); - - PeerService.PeerServiceClient client; - - if(isValid) - client = new PeerService.PeerServiceClient(channel.Intercept(metadata => - { - metadata.Add(GrpcConstants.PubkeyMetadataKey, pubkey); - return metadata; - })); - else - client = new PeerService.PeerServiceClient(channel); - - var connectionInfo = new PeerConnectionInfo + public static GrpcPeer CreatePeerWithInfo(string ip, PeerConnectionInfo info) + { + AElfPeerEndpointHelper.TryParse(ip, out var endpoint); + var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), null), endpoint, info); + peer.InboundSessionId = new byte[] { 0, 1, 2 }; + return peer; + } + + public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client) + { + AElfPeerEndpointHelper.TryParse(ip, out var endpoint); + var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), client), endpoint, + new PeerConnectionInfo { Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2 } }); + peer.InboundSessionId = new byte[] { 0, 1, 2 }; + return peer; + } + + public static GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true, + string publicKey = null) + { + var pubkey = publicKey ?? NetworkTestConstants.FakePubkey; + var channel = new Channel(ipAddress, ChannelCredentials.Insecure); + + PeerService.PeerServiceClient client; + + if (isValid) + client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { - Pubkey = pubkey, - ProtocolVersion = KernelConstants.ProtocolVersion, - ConnectionTime = TimestampHelper.GetUtcNow(), - SessionId = new byte[] { 0, 1, 2}, - IsInbound = true - }; + metadata.Add(GrpcConstants.PubkeyMetadataKey, pubkey); + return metadata; + })); + else + client = new PeerService.PeerServiceClient(channel); + + var connectionInfo = new PeerConnectionInfo + { + Pubkey = pubkey, + ProtocolVersion = KernelConstants.ProtocolVersion, + ConnectionTime = TimestampHelper.GetUtcNow(), + SessionId = new byte[] { 0, 1, 2 }, + IsInbound = true + }; - AElfPeerEndpointHelper.TryParse(ipAddress, out var endpoint); - var peer = new GrpcPeer(new GrpcClient(channel, client), endpoint, connectionInfo); - peer.InboundSessionId = new byte[] {0, 1, 2}; + AElfPeerEndpointHelper.TryParse(ipAddress, out var endpoint); + var peer = new GrpcPeer(new GrpcClient(channel, client), endpoint, connectionInfo); + peer.InboundSessionId = new byte[] { 0, 1, 2 }; - return peer; - } + return peer; } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Helpers/MockServiceBuilder.cs b/test/AElf.OS.Network.Grpc.Tests/Helpers/MockServiceBuilder.cs index 8ac8999b66..8aa712c373 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Helpers/MockServiceBuilder.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Helpers/MockServiceBuilder.cs @@ -4,173 +4,153 @@ using Grpc.Core; using Grpc.Core.Utils; -namespace AElf.OS.Network.Grpc -{ - /// - /// Allows setting up a mock service in the client-server tests easily. - /// - public class MockServiceBuilder - { - public const string ServiceName = "tests.Test"; +namespace AElf.OS.Network.Grpc; - private readonly string _host; - private readonly IEnumerable _channelOptions; +/// +/// Allows setting up a mock service in the client-server tests easily. +/// +public class MockServiceBuilder +{ + public const string ServiceName = "tests.Test"; + private readonly IEnumerable _channelOptions; + private readonly Method _clientStreamingMethod; + private readonly Method _duplexStreamingMethod; - private readonly Method _unaryMethod; - private readonly Method _clientStreamingMethod; - private readonly Method _serverStreamingMethod; - private readonly Method _duplexStreamingMethod; + private readonly Method _serverStreamingMethod; - private UnaryServerMethod _unaryHandler; - private ClientStreamingServerMethod _clientStreamingHandler; - private ServerStreamingServerMethod _serverStreamingHandler; - private DuplexStreamingServerMethod _duplexStreamingHandler; + private readonly Method _unaryMethod; + private Channel _channel; - private Server _server; - private Channel _channel; + private Server _server; - public MockServiceBuilder(string host = null, Marshaller marshaller = null, IEnumerable channelOptions = null) + public MockServiceBuilder(string host = null, Marshaller marshaller = null, + IEnumerable channelOptions = null) + { + Host = host ?? "localhost"; + _channelOptions = channelOptions; + marshaller ??= Marshallers.StringMarshaller; + + _unaryMethod = new Method( + MethodType.Unary, + ServiceName, + "Unary", + marshaller, + marshaller); + + _clientStreamingMethod = new Method( + MethodType.ClientStreaming, + ServiceName, + "ClientStreaming", + marshaller, + marshaller); + + _serverStreamingMethod = new Method( + MethodType.ServerStreaming, + ServiceName, + "ServerStreaming", + marshaller, + marshaller); + + _duplexStreamingMethod = new Method( + MethodType.DuplexStreaming, + ServiceName, + "DuplexStreaming", + marshaller, + marshaller); + + ServiceDefinition = ServerServiceDefinition.CreateBuilder() + .AddMethod(_unaryMethod, (request, context) => UnaryHandler(request, context)) + .AddMethod(_clientStreamingMethod, + (requestStream, context) => ClientStreamingHandler(requestStream, context)) + .AddMethod(_serverStreamingMethod, + (request, responseStream, context) => ServerStreamingHandler(request, responseStream, context)) + .AddMethod(_duplexStreamingMethod, + (requestStream, responseStream, context) => + DuplexStreamingHandler(requestStream, responseStream, context)) + .Build(); + + var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); + + UnaryHandler = (request, context) => { - _host = host ?? "localhost"; - _channelOptions = channelOptions; - marshaller ??= Marshallers.StringMarshaller; - - _unaryMethod = new Method( - MethodType.Unary, - ServiceName, - "Unary", - marshaller, - marshaller); - - _clientStreamingMethod = new Method( - MethodType.ClientStreaming, - ServiceName, - "ClientStreaming", - marshaller, - marshaller); - - _serverStreamingMethod = new Method( - MethodType.ServerStreaming, - ServiceName, - "ServerStreaming", - marshaller, - marshaller); - - _duplexStreamingMethod = new Method( - MethodType.DuplexStreaming, - ServiceName, - "DuplexStreaming", - marshaller, - marshaller); - - ServiceDefinition = ServerServiceDefinition.CreateBuilder() - .AddMethod(_unaryMethod, (request, context) => _unaryHandler(request, context)) - .AddMethod(_clientStreamingMethod, (requestStream, context) => _clientStreamingHandler(requestStream, context)) - .AddMethod(_serverStreamingMethod, (request, responseStream, context) => _serverStreamingHandler(request, responseStream, context)) - .AddMethod(_duplexStreamingMethod, (requestStream, responseStream, context) => _duplexStreamingHandler(requestStream, responseStream, context)) - .Build(); - - var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); - - _unaryHandler = new UnaryServerMethod((request, context) => - { - context.Status = defaultStatus; - return Task.FromResult(""); - }); - - _clientStreamingHandler = new ClientStreamingServerMethod((requestStream, context) => - { - context.Status = defaultStatus; - return Task.FromResult(""); - }); - - _serverStreamingHandler = new ServerStreamingServerMethod((request, responseStream, context) => - { - context.Status = defaultStatus; - return TaskUtils.CompletedTask; - }); + context.Status = defaultStatus; + return Task.FromResult(""); + }; - _duplexStreamingHandler = new DuplexStreamingServerMethod((requestStream, responseStream, context) => - { - context.Status = defaultStatus; - return TaskUtils.CompletedTask; - }); - } - - /// - /// Returns the default server for this service and creates one if not yet created. - /// - public Server GetServer() - { - if (_server == null) - { - // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 - _server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) - { - Services = { ServiceDefinition }, - Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } - }; - } - return _server; - } - - /// - /// Returns the default channel for this service and creates one if not yet created. - /// - public Channel GetChannel() + ClientStreamingHandler = (requestStream, context) => { - if (_channel == null) - { - _channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, _channelOptions); - } - return _channel; - } + context.Status = defaultStatus; + return Task.FromResult(""); + }; - public CallInvocationDetails CreateUnaryCall(CallOptions options = default(CallOptions)) + ServerStreamingHandler = (request, responseStream, context) => { - return new CallInvocationDetails(_channel, _unaryMethod, options); - } + context.Status = defaultStatus; + return TaskUtils.CompletedTask; + }; - public CallInvocationDetails CreateClientStreamingCall(CallOptions options = default(CallOptions)) + DuplexStreamingHandler = (requestStream, responseStream, context) => { - return new CallInvocationDetails(_channel, _clientStreamingMethod, options); - } + context.Status = defaultStatus; + return TaskUtils.CompletedTask; + }; + } - public CallInvocationDetails CreateServerStreamingCall(CallOptions options = default(CallOptions)) - { - return new CallInvocationDetails(_channel, _serverStreamingMethod, options); - } + public string Host { get; } - public CallInvocationDetails CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) - { - return new CallInvocationDetails(_channel, _duplexStreamingMethod, options); - } + public ServerServiceDefinition ServiceDefinition { get; set; } - public string Host => _host; - public ServerServiceDefinition ServiceDefinition { get; set; } - - public UnaryServerMethod UnaryHandler - { - get { return this._unaryHandler; } - set { _unaryHandler = value; } - } + public UnaryServerMethod UnaryHandler { get; set; } - public ClientStreamingServerMethod ClientStreamingHandler - { - get { return this._clientStreamingHandler; } - set { _clientStreamingHandler = value; } - } + public ClientStreamingServerMethod ClientStreamingHandler { get; set; } - public ServerStreamingServerMethod ServerStreamingHandler - { - get { return this._serverStreamingHandler; } - set { _serverStreamingHandler = value; } - } + public ServerStreamingServerMethod ServerStreamingHandler { get; set; } - public DuplexStreamingServerMethod DuplexStreamingHandler - { - get { return this._duplexStreamingHandler; } - set { _duplexStreamingHandler = value; } - } + public DuplexStreamingServerMethod DuplexStreamingHandler { get; set; } + + /// + /// Returns the default server for this service and creates one if not yet created. + /// + public Server GetServer() + { + if (_server == null) + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + _server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { ServiceDefinition }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + return _server; + } + + /// + /// Returns the default channel for this service and creates one if not yet created. + /// + public Channel GetChannel() + { + if (_channel == null) + _channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, + _channelOptions); + return _channel; + } + + public CallInvocationDetails CreateUnaryCall(CallOptions options = default) + { + return new CallInvocationDetails(_channel, _unaryMethod, options); + } + + public CallInvocationDetails CreateClientStreamingCall(CallOptions options = default) + { + return new CallInvocationDetails(_channel, _clientStreamingMethod, options); + } + + public CallInvocationDetails CreateServerStreamingCall(CallOptions options = default) + { + return new CallInvocationDetails(_channel, _serverStreamingMethod, options); + } + + public CallInvocationDetails CreateDuplexStreamingCall(CallOptions options = default) + { + return new CallInvocationDetails(_channel, _duplexStreamingMethod, options); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Helpers/NetworkTestHelper.cs b/test/AElf.OS.Network.Grpc.Tests/Helpers/NetworkTestHelper.cs index 409c1afd74..a8e8cd0ca4 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Helpers/NetworkTestHelper.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Helpers/NetworkTestHelper.cs @@ -4,43 +4,44 @@ using AElf.Types; using Google.Protobuf; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public static class NetworkTestHelper { - public static class NetworkTestHelper + public static Handshake CreateValidHandshake(ECKeyPair producer, long bestChainHeight, + int chainId = NetworkTestConstants.DefaultChainId, int port = 0) { - public static Handshake CreateValidHandshake(ECKeyPair producer, long bestChainHeight, int chainId = NetworkTestConstants.DefaultChainId, int port = 0) + var data = new HandshakeData { - var data = new HandshakeData - { - ChainId = chainId, - Version = KernelConstants.ProtocolVersion, - ListeningPort = port, - Pubkey = ByteString.CopyFrom(producer.PublicKey), - BestChainHash = HashHelper.ComputeFrom("BestChainHash"), - BestChainHeight = bestChainHeight, - LastIrreversibleBlockHash = HashHelper.ComputeFrom("LastIrreversibleBlockHash"), - LastIrreversibleBlockHeight = 1, - Time = TimestampHelper.GetUtcNow() - }; - - var signature = CryptoHelper.SignWithPrivateKey(producer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); - - return new Handshake { HandshakeData = data, Signature = ByteString.CopyFrom(signature) }; - } + ChainId = chainId, + Version = KernelConstants.ProtocolVersion, + ListeningPort = port, + Pubkey = ByteString.CopyFrom(producer.PublicKey), + BestChainHash = HashHelper.ComputeFrom("BestChainHash"), + BestChainHeight = bestChainHeight, + LastIrreversibleBlockHash = HashHelper.ComputeFrom("LastIrreversibleBlockHash"), + LastIrreversibleBlockHeight = 1, + Time = TimestampHelper.GetUtcNow() + }; + + var signature = + CryptoHelper.SignWithPrivateKey(producer.PrivateKey, HashHelper.ComputeFrom(data).ToByteArray()); - public static BlockHeader CreateFakeBlockHeader(int chainId, long height, ECKeyPair producer) + return new Handshake { HandshakeData = data, Signature = ByteString.CopyFrom(signature) }; + } + + public static BlockHeader CreateFakeBlockHeader(int chainId, long height, ECKeyPair producer) + { + return new BlockHeader { - return new BlockHeader - { - ChainId = chainId, - Height = height, - PreviousBlockHash = HashHelper.ComputeFrom(new byte[]{1, 2, 3}), - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfTransactions = Hash.Empty, - MerkleTreeRootOfWorldState = Hash.Empty, - MerkleTreeRootOfTransactionStatus = Hash.Empty, - SignerPubkey = ByteString.CopyFrom(producer.PublicKey) - }; - } + ChainId = chainId, + Height = height, + PreviousBlockHash = HashHelper.ComputeFrom(new byte[] { 1, 2, 3 }), + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfTransactions = Hash.Empty, + MerkleTreeRootOfWorldState = Hash.Empty, + MerkleTreeRootOfTransactionStatus = Hash.Empty, + SignerPubkey = ByteString.CopyFrom(producer.PublicKey) + }; } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Interceptors/AuthInterceptorTests.cs b/test/AElf.OS.Network.Grpc.Tests/Interceptors/AuthInterceptorTests.cs index 8d25f8e695..c578e81c5e 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Interceptors/AuthInterceptorTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Interceptors/AuthInterceptorTests.cs @@ -8,220 +8,220 @@ using Xunit; using Xunit.Sdk; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class AuthInterceptorTests : GrpcNetworkWithPeerTestBase { - public class AuthInterceptorTests : GrpcNetworkWithPeerTestBase + private readonly AuthInterceptor _authInterceptor; + private readonly IPeerPool _peerPool; + private Channel _channel; + + private Server _server; + + public AuthInterceptorTests() + { + _peerPool = GetRequiredService(); + _authInterceptor = GetRequiredService(); + } + + [Theory] + [InlineData("Ping")] + [InlineData("DoHandshake")] + public async Task UnaryServerHandler_NoAuth_Test(string methodName) { - private readonly IPeerPool _peerPool; - private readonly AuthInterceptor _authInterceptor; + var helper = new MockServiceBuilder(); + var unaryHandler = new UnaryServerMethod((request, context) => Task.FromResult("ok")); + var method = new Method( + MethodType.Unary, + nameof(PeerService), + methodName, + Marshallers.StringMarshaller, + Marshallers.StringMarshaller); + var serverServiceDefinition = ServerServiceDefinition.CreateBuilder() + .AddMethod(method, (request, context) => unaryHandler(request, context)).Build() + .Intercept(_authInterceptor); + helper.ServiceDefinition = serverServiceDefinition; + _server = helper.GetServer(); + _server.Start(); + + _channel = helper.GetChannel(); + + var result = await Calls.AsyncUnaryCall(new CallInvocationDetails(_channel, method, default), + ""); + result.ShouldBe("ok"); + } - private Server _server; - private Channel _channel; + [Fact] + public async Task UnaryServerHandler_Auth_Failed() + { + var helper = new MockServiceBuilder(); + helper.UnaryHandler = (request, context) => Task.FromResult("ok"); - public AuthInterceptorTests() - { - _peerPool = GetRequiredService(); - _authInterceptor = GetRequiredService(); - } + helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); - [Theory] - [InlineData("Ping")] - [InlineData("DoHandshake")] - public async Task UnaryServerHandler_NoAuth_Test(string methodName) - { - var helper = new MockServiceBuilder(); - var unaryHandler = new UnaryServerMethod((request, context) => Task.FromResult("ok")); - var method = new Method( - MethodType.Unary, - nameof(PeerService), - methodName, - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - var serverServiceDefinition = ServerServiceDefinition.CreateBuilder() - .AddMethod(method, (request, context) => unaryHandler(request, context)).Build() - .Intercept(_authInterceptor); - helper.ServiceDefinition = serverServiceDefinition; - _server = helper.GetServer(); - _server.Start(); - - _channel = helper.GetChannel(); - - var result = await Calls.AsyncUnaryCall(new CallInvocationDetails(_channel, method, default), - ""); - result.ShouldBe("ok"); - } + await ShouldBeCancelRpcExceptionAsync(async () => + await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "")); - [Fact] - public async Task UnaryServerHandler_Auth_Failed() + var method = new Method(MethodType.Unary, MockServiceBuilder.ServiceName, "Unary", + Marshallers.StringMarshaller, Marshallers.StringMarshaller); + + var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); + ((GrpcPeer)peer).InboundSessionId = new byte[] { 1, 2, 3 }; + var callInvoker = helper.GetChannel().Intercept(metadata => { - var helper = new MockServiceBuilder(); - helper.UnaryHandler = new UnaryServerMethod((request, context) => Task.FromResult("ok")); - - helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); - - await ShouldBeCancelRpcExceptionAsync(async () => - await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "")); - - var method = new Method(MethodType.Unary, MockServiceBuilder.ServiceName, "Unary", - Marshallers.StringMarshaller, Marshallers.StringMarshaller); - - var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); - ((GrpcPeer) peer).InboundSessionId = new byte[] {1, 2, 3}; - var callInvoker = helper.GetChannel().Intercept(metadata => - { - metadata = new Metadata - { - { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey} - }; - return metadata; - }); - - await ShouldBeCancelRpcExceptionAsync(async () => - await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); - - callInvoker = helper.GetChannel().Intercept(metadata => + metadata = new Metadata { - metadata = new Metadata - { - { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey}, - { GrpcConstants.SessionIdMetadataKey, new byte[] {4, 5, 6 }} - }; - return metadata; - }); - - await ShouldBeCancelRpcExceptionAsync(async () => - await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); - - ((GrpcPeer) peer).InboundSessionId = null; - await ShouldBeCancelRpcExceptionAsync(async () => - await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); - } - - [Fact] - public async Task UnaryServerHandler_Auth_Success() + { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey } + }; + return metadata; + }); + + await ShouldBeCancelRpcExceptionAsync(async () => + await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); + + callInvoker = helper.GetChannel().Intercept(metadata => { - var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); - ((GrpcPeer) peer).InboundSessionId = new byte[] {1, 2, 3}; - - var helper = new MockServiceBuilder(); - helper.UnaryHandler = new UnaryServerMethod((request, context) => + metadata = new Metadata { - context.GetPeerInfo().ShouldBe(peer.ToString()); - return Task.FromResult("ok"); - }); + { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey }, + { GrpcConstants.SessionIdMetadataKey, new byte[] { 4, 5, 6 } } + }; + return metadata; + }); + + await ShouldBeCancelRpcExceptionAsync(async () => + await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); + + ((GrpcPeer)peer).InboundSessionId = null; + await ShouldBeCancelRpcExceptionAsync(async () => + await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), "")); + } - helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); + [Fact] + public async Task UnaryServerHandler_Auth_Success() + { + var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); + ((GrpcPeer)peer).InboundSessionId = new byte[] { 1, 2, 3 }; - var method = new Method(MethodType.Unary, MockServiceBuilder.ServiceName, "Unary", - Marshallers.StringMarshaller, Marshallers.StringMarshaller); + var helper = new MockServiceBuilder(); + helper.UnaryHandler = (request, context) => + { + context.GetPeerInfo().ShouldBe(peer.ToString()); + return Task.FromResult("ok"); + }; - var callInvoker = helper.GetChannel().Intercept(metadata => - { - metadata = new Metadata - { - { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey}, - { GrpcConstants.SessionIdMetadataKey, new byte[] {1, 2, 3}} - }; - return metadata; - }); - - var result = await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), ""); - result.ShouldBe("ok"); - } - - [Fact] - public async Task ClientStreamingServerHandler_Auth_Failed() + helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); + + var method = new Method(MethodType.Unary, MockServiceBuilder.ServiceName, "Unary", + Marshallers.StringMarshaller, Marshallers.StringMarshaller); + + var callInvoker = helper.GetChannel().Intercept(metadata => { - var helper = new MockServiceBuilder(); - helper.ClientStreamingHandler = new ClientStreamingServerMethod((request, context) => Task.FromResult("ok")); - - helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); - - await ShouldBeCancelRpcExceptionAsync(async () => - await Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()).ResponseAsync); - - var method = new Method(MethodType.ClientStreaming, MockServiceBuilder.ServiceName, "ClientStreaming", - Marshallers.StringMarshaller, Marshallers.StringMarshaller); - - var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); - ((GrpcPeer) peer).InboundSessionId = new byte[] {1, 2, 3}; - var callInvoker = helper.GetChannel().Intercept(metadata => + metadata = new Metadata { - metadata = new Metadata - { - { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey}, - { GrpcConstants.SessionIdMetadataKey, new byte[] {4, 5, 6}} - }; - return metadata; - }); - - await ShouldBeCancelRpcExceptionAsync(async () => - await callInvoker.AsyncClientStreamingCall(method, "localhost", new CallOptions()).ResponseAsync); - } + { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey }, + { GrpcConstants.SessionIdMetadataKey, new byte[] { 1, 2, 3 } } + }; + return metadata; + }); + + var result = await callInvoker.AsyncUnaryCall(method, "localhost", new CallOptions(), ""); + result.ShouldBe("ok"); + } - [Fact] - public async Task ClientStreamingServerHandler_Auth_Success() - { - var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); - ((GrpcPeer) peer).InboundSessionId = new byte[] {1, 2, 3}; + [Fact] + public async Task ClientStreamingServerHandler_Auth_Failed() + { + var helper = new MockServiceBuilder(); + helper.ClientStreamingHandler = (request, context) => Task.FromResult("ok"); - var helper = new MockServiceBuilder(); - helper.ClientStreamingHandler = new ClientStreamingServerMethod((request, context) => - { - context.GetPeerInfo().ShouldBe(peer.ToString()); - return Task.FromResult("ok"); - }); + helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); - helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); + await ShouldBeCancelRpcExceptionAsync(async () => + await Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()).ResponseAsync); - var method = new Method(MethodType.ClientStreaming, MockServiceBuilder.ServiceName, - "ClientStreaming", - Marshallers.StringMarshaller, Marshallers.StringMarshaller); + var method = new Method(MethodType.ClientStreaming, MockServiceBuilder.ServiceName, + "ClientStreaming", + Marshallers.StringMarshaller, Marshallers.StringMarshaller); - var callInvoker = helper.GetChannel().Intercept(metadata => + var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); + ((GrpcPeer)peer).InboundSessionId = new byte[] { 1, 2, 3 }; + var callInvoker = helper.GetChannel().Intercept(metadata => + { + metadata = new Metadata { - metadata = new Metadata - { - {GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey}, - {GrpcConstants.SessionIdMetadataKey, new byte[] {1, 2, 3}} - }; - return metadata; - }); - - var result = await callInvoker.AsyncClientStreamingCall(method, "localhost", new CallOptions()).ResponseAsync; - result.ShouldBe("ok"); - } + { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey }, + { GrpcConstants.SessionIdMetadataKey, new byte[] { 4, 5, 6 } } + }; + return metadata; + }); + + await ShouldBeCancelRpcExceptionAsync(async () => + await callInvoker.AsyncClientStreamingCall(method, "localhost", new CallOptions()).ResponseAsync); + } + + [Fact] + public async Task ClientStreamingServerHandler_Auth_Success() + { + var peer = _peerPool.GetPeersByHost("127.0.0.1").First(); + ((GrpcPeer)peer).InboundSessionId = new byte[] { 1, 2, 3 }; - private async Task ShouldBeCancelRpcExceptionAsync(Func func) + var helper = new MockServiceBuilder(); + helper.ClientStreamingHandler = (request, context) => { - try - { - await func(); - throw new XunitException("Should throw RpcException, but execute successfully."); - } - catch (RpcException e) + context.GetPeerInfo().ShouldBe(peer.ToString()); + return Task.FromResult("ok"); + }; + + helper.ServiceDefinition = helper.ServiceDefinition.Intercept(_authInterceptor); + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); + + var method = new Method(MethodType.ClientStreaming, MockServiceBuilder.ServiceName, + "ClientStreaming", + Marshallers.StringMarshaller, Marshallers.StringMarshaller); + + var callInvoker = helper.GetChannel().Intercept(metadata => + { + metadata = new Metadata { - e.Status.StatusCode.ShouldBe(StatusCode.Cancelled); - } - } + { GrpcConstants.PubkeyMetadataKey, peer.Info.Pubkey }, + { GrpcConstants.SessionIdMetadataKey, new byte[] { 1, 2, 3 } } + }; + return metadata; + }); + + var result = await callInvoker.AsyncClientStreamingCall(method, "localhost", new CallOptions()).ResponseAsync; + result.ShouldBe("ok"); + } - public override void Dispose() + private async Task ShouldBeCancelRpcExceptionAsync(Func func) + { + try { - base.Dispose(); - _channel.ShutdownAsync().Wait(); - _server.ShutdownAsync().Wait(); + await func(); + throw new XunitException("Should throw RpcException, but execute successfully."); } + catch (RpcException e) + { + e.Status.StatusCode.ShouldBe(StatusCode.Cancelled); + } + } + + public override void Dispose() + { + base.Dispose(); + _channel.ShutdownAsync().Wait(); + _server.ShutdownAsync().Wait(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Interceptors/RetryInterceptorTest.cs b/test/AElf.OS.Network.Grpc.Tests/Interceptors/RetryInterceptorTest.cs index 9c371d4830..5f6ca5414a 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Interceptors/RetryInterceptorTest.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Interceptors/RetryInterceptorTest.cs @@ -5,127 +5,129 @@ using Shouldly; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class RetryInterceptorTest : GrpcNetworkWithPeerTestBase { - public class RetryInterceptorTest : GrpcNetworkWithPeerTestBase + private Channel _channel; + private Server _server; + + [Fact] + public async Task RetryDoesNotExceedSuccess() { - private Server _server; - private Channel _channel; - - [Fact] - public async Task RetryDoesNotExceedSuccess() - { - var helper = new MockServiceBuilder("localhost"); - int callCount = 0; - helper.UnaryHandler = new UnaryServerMethod((request, context) => - { - callCount++; - - if (callCount == 1) - context.Status = new Status(StatusCode.Cancelled, ""); - - return Task.FromResult("ok"); - }); - - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); - - var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); - - var metadata = new Metadata {{ GrpcConstants.RetryCountMetadataKey, "5"}}; - - await callInvoker.AsyncUnaryCall(new Method(MethodType.Unary, - MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), - "localhost", new CallOptions().WithHeaders(metadata), ""); - - Assert.Equal(2, callCount); - } - - [Fact] - public async Task RetryHeaderDecidesRetryCount() + var helper = new MockServiceBuilder("localhost"); + var callCount = 0; + helper.UnaryHandler = (request, context) => { - var helper = new MockServiceBuilder("localhost"); - int callCount = 0; - helper.UnaryHandler = new UnaryServerMethod((request, context) => - { - callCount++; + callCount++; + + if (callCount == 1) context.Status = new Status(StatusCode.Cancelled, ""); - return Task.FromResult("ok"); - }); - - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); - - var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); - - var metadata = new Metadata {{ GrpcConstants.RetryCountMetadataKey, "0"}}; - - await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall(new Method(MethodType.Unary, - MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), - "localhost", new CallOptions().WithHeaders(metadata), "")); - - Assert.Equal(1, callCount); - - callCount = 0; - var oneRetryMetadata = new Metadata {{ GrpcConstants.RetryCountMetadataKey, "1"}}; - - await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall(new Method(MethodType.Unary, - MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), - "localhost", new CallOptions().WithHeaders(oneRetryMetadata), "")); - - Assert.Equal(2, callCount); - - callCount = 0; - - await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall(new Method(MethodType.Unary, - MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), - "localhost", new CallOptions(), "")); - - Assert.Equal(2, callCount); - } - - [Fact] - public async Task Retry_Timeout_Test() + + return Task.FromResult("ok"); + }; + + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); + + var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); + + var metadata = new Metadata { { GrpcConstants.RetryCountMetadataKey, "5" } }; + + await callInvoker.AsyncUnaryCall(new Method(MethodType.Unary, + MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), + "localhost", new CallOptions().WithHeaders(metadata), ""); + + Assert.Equal(2, callCount); + } + + [Fact] + public async Task RetryHeaderDecidesRetryCount() + { + var helper = new MockServiceBuilder("localhost"); + var callCount = 0; + helper.UnaryHandler = (request, context) => { - var helper = new MockServiceBuilder("localhost"); - int callCount = 0; - helper.UnaryHandler = new UnaryServerMethod((request, context) => - { - callCount++; - - Task.Delay(1000).Wait(); - - return Task.FromResult("ok"); - }); - - _server = helper.GetServer(); - _server.Start(); - _channel = helper.GetChannel(); - - var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); - - var metadata = new Metadata {{ GrpcConstants.RetryCountMetadataKey, "1"}}; - - var exception = await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall( - new Method(MethodType.Unary, - MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, - Marshallers.StringMarshaller), - "localhost", new CallOptions().WithHeaders(metadata), "")); - - var rpcException = exception.InnerExceptions[0] as RpcException; - rpcException.ShouldNotBeNull(); - rpcException.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); - - Assert.Equal(2, callCount); - } - - public override void Dispose() + callCount++; + context.Status = new Status(StatusCode.Cancelled, ""); + return Task.FromResult("ok"); + }; + + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); + + var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); + + var metadata = new Metadata { { GrpcConstants.RetryCountMetadataKey, "0" } }; + + await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall( + new Method(MethodType.Unary, + MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), + "localhost", new CallOptions().WithHeaders(metadata), "")); + + Assert.Equal(1, callCount); + + callCount = 0; + var oneRetryMetadata = new Metadata { { GrpcConstants.RetryCountMetadataKey, "1" } }; + + await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall( + new Method(MethodType.Unary, + MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), + "localhost", new CallOptions().WithHeaders(oneRetryMetadata), "")); + + Assert.Equal(2, callCount); + + callCount = 0; + + await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall( + new Method(MethodType.Unary, + MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), + "localhost", new CallOptions(), "")); + + Assert.Equal(2, callCount); + } + + [Fact] + public async Task Retry_Timeout_Test() + { + var helper = new MockServiceBuilder("localhost"); + var callCount = 0; + helper.UnaryHandler = (request, context) => { - base.Dispose(); - _channel.ShutdownAsync().Wait(); - _server.ShutdownAsync().Wait(); - } + callCount++; + + Task.Delay(1000).Wait(); + + return Task.FromResult("ok"); + }; + + _server = helper.GetServer(); + _server.Start(); + _channel = helper.GetChannel(); + + var callInvoker = helper.GetChannel().Intercept(new RetryInterceptor()); + + var metadata = new Metadata { { GrpcConstants.RetryCountMetadataKey, "1" } }; + + var exception = await Assert.ThrowsAsync(async () => await callInvoker.AsyncUnaryCall( + new Method(MethodType.Unary, + MockServiceBuilder.ServiceName, "Unary", Marshallers.StringMarshaller, + Marshallers.StringMarshaller), + "localhost", new CallOptions().WithHeaders(metadata), "")); + + var rpcException = exception.InnerExceptions[0] as RpcException; + rpcException.ShouldNotBeNull(); + rpcException.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); + + Assert.Equal(2, callCount); + } + + public override void Dispose() + { + base.Dispose(); + _channel.ShutdownAsync().Wait(); + _server.ShutdownAsync().Wait(); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/PeerDialerTestModule.cs b/test/AElf.OS.Network.Grpc.Tests/PeerDialerTestModule.cs index bdd6525857..537a66ec90 100644 --- a/test/AElf.OS.Network.Grpc.Tests/PeerDialerTestModule.cs +++ b/test/AElf.OS.Network.Grpc.Tests/PeerDialerTestModule.cs @@ -2,90 +2,86 @@ using System.Threading.Tasks; using AElf.Cryptography; using AElf.Modularity; -using AElf.OS.Network.Grpc; -using AElf.OS.Network.Protocol; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -using Volo.Abp.Threading; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +[DependsOn( + typeof(GrpcNetworkWithChainTestModule))] +public class PeerDialerTestModule : AElfModule { - [DependsOn( - typeof(GrpcNetworkWithChainTestModule))] - public class PeerDialerTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + + services.AddTransient(provider => { - var services = context.Services; + var mockService = new Mock(); + mockService.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny())) + .Returns((pe, hsk) => + { + var handshake = NetworkTestHelper.CreateValidHandshake(CryptoHelper.GenerateKeyPair(), 10, + hsk.HandshakeData.ChainId); - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny())) - .Returns((pe, hsk) => + var handShakeReply = Task.FromResult(new HandshakeReply { - var handshake = NetworkTestHelper.CreateValidHandshake(CryptoHelper.GenerateKeyPair(), 10, hsk.HandshakeData.ChainId); - - var handShakeReply = Task.FromResult(new HandshakeReply - { - Error = HandshakeError.HandshakeOk, - Handshake = handshake - }); - return handShakeReply; + Error = HandshakeError.HandshakeOk, + Handshake = handshake }); + return handShakeReply; + }); - return mockService.Object; - }); - - } + return mockService.Object; + }); } +} - [DependsOn( - typeof(GrpcNetworkWithChainTestModule))] - public class PeerDialerInvalidHandshakeTestModule : AElfModule +[DependsOn( + typeof(GrpcNetworkWithChainTestModule))] +public class PeerDialerInvalidHandshakeTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m=>m.DoHandshakeAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new HandshakeReply + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(new HandshakeReply + { + Error = HandshakeError.HandshakeOk, + Handshake = new Handshake { - Error = HandshakeError.HandshakeOk, - Handshake = new Handshake - { - HandshakeData = new HandshakeData() - } - })); + HandshakeData = new HandshakeData() + } + })); - return mockService.Object; - }); - } + return mockService.Object; + }); } - - [DependsOn( - typeof(GrpcNetworkWithChainTestModule))] - public class PeerDialerReplyErrorTestModule : AElfModule +} + +[DependsOn( + typeof(GrpcNetworkWithChainTestModule))] +public class PeerDialerReplyErrorTestModule : AElfModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - var services = context.Services; + var services = context.Services; - services.AddTransient(provider => - { - var mockService = new Mock(); - mockService.Setup(m=>m.DoHandshakeAsync(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(new HandshakeReply - { - Error = HandshakeError.ChainMismatch - })); + services.AddTransient(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.DoHandshakeAsync(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(new HandshakeReply + { + Error = HandshakeError.ChainMismatch + })); - return mockService.Object; - }); - } + return mockService.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Network.Grpc.Tests/Service/GrpcServerServiceTests.cs b/test/AElf.OS.Network.Grpc.Tests/Service/GrpcServerServiceTests.cs index 474e4b5245..1ec3ff4930 100644 --- a/test/AElf.OS.Network.Grpc.Tests/Service/GrpcServerServiceTests.cs +++ b/test/AElf.OS.Network.Grpc.Tests/Service/GrpcServerServiceTests.cs @@ -11,691 +11,702 @@ using AElf.OS.Network.Domain; using AElf.OS.Network.Events; using AElf.OS.Network.Infrastructure; -using AElf.OS.Network.Protocol; using AElf.Types; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Testing; using Grpc.Core.Utils; -using Moq; using Shouldly; using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Network.Grpc +namespace AElf.OS.Network.Grpc; + +public class GrpcServerServiceTests : GrpcNetworkWithChainAndPeerTestBase { - public class GrpcServerServiceTests : GrpcNetworkWithChainAndPeerTestBase - { - private readonly IAElfNetworkServer _networkServer; - private readonly IBlockchainService _blockchainService; - private readonly IPeerPool _peerPool; - private readonly ILocalEventBus _eventBus; - private readonly INodeManager _nodeManager; - private readonly OSTestHelper _osTestHelper; - private readonly INodeSyncStateProvider _syncStateProvider; - - private readonly GrpcServerService _serverService; - - public GrpcServerServiceTests() - { - _networkServer = GetRequiredService(); - _serverService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _peerPool = GetRequiredService(); - _eventBus = GetRequiredService(); - _nodeManager = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _syncStateProvider = GetRequiredService(); - } + private readonly IBlockchainService _blockchainService; + private readonly ILocalEventBus _eventBus; + private readonly IAElfNetworkServer _networkServer; + private readonly INodeManager _nodeManager; + private readonly OSTestHelper _osTestHelper; + private readonly IPeerPool _peerPool; - private ServerCallContext BuildServerCallContext(Metadata metadata = null, string address = null) - { - return TestServerCallContext.Create("mock", null, TimestampHelper.GetUtcNow().AddHours(1).ToDateTime(), metadata ?? new Metadata(), CancellationToken.None, - address ?? "ipv4:127.0.0.1:5555", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), writeOptions => { }); - } + private readonly GrpcServerService _serverService; + private readonly INodeSyncStateProvider _syncStateProvider; - #region Handshake - - [Fact] - public async Task DoHandshake_Test() - { - var context = BuildServerCallContext(null, "ipv4:127.0.0.1:7878"); - var peerKeyPair = CryptoHelper.GenerateKeyPair(); - var handshake = NetworkTestHelper.CreateValidHandshake(peerKeyPair, 10, ChainHelper.ConvertBase58ToChainId("AELF"), 2000); - var request = new HandshakeRequest {Handshake = handshake}; - var result = await _serverService.DoHandshake(request, context); - result.Error.ShouldBe(HandshakeError.HandshakeOk); - } + public GrpcServerServiceTests() + { + _networkServer = GetRequiredService(); + _serverService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _peerPool = GetRequiredService(); + _eventBus = GetRequiredService(); + _nodeManager = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _syncStateProvider = GetRequiredService(); + } - [Fact] - public async Task DoHandshake_InvalidPeer_Test() - { - var context = BuildServerCallContext(null, "ipv4:127.0.0.1:a"); - var peerKeyPair = CryptoHelper.GenerateKeyPair(); - var handshake = NetworkTestHelper.CreateValidHandshake(peerKeyPair, 10, ChainHelper.ConvertBase58ToChainId("AELF"), 2000); - var request = new HandshakeRequest {Handshake = handshake}; - var result = await _serverService.DoHandshake(request, context); - result.Error.ShouldBe(HandshakeError.InvalidConnection); - } + private ServerCallContext BuildServerCallContext(Metadata metadata = null, string address = null) + { + return TestServerCallContext.Create("mock", null, TimestampHelper.GetUtcNow().AddHours(1).ToDateTime(), + metadata ?? new Metadata(), CancellationToken.None, + address ?? "ipv4:127.0.0.1:5555", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), + writeOptions => { }); + } - [Fact] - public async Task ConfirmHandshake_Test() - { - PeerConnectedEventData received = null; - _eventBus.Subscribe(t => - { - received = t; - return Task.CompletedTask; - }); - var request = new ConfirmHandshakeRequest(); - var context = BuildServerCallContext(null, "ipv4:127.0.0.1:7878"); - - await _serverService.ConfirmHandshake(request, context); - received.ShouldBe(null); - - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - context = BuildServerCallContext(metadata, "ipv4:127.0.0.1:7878"); - await _serverService.ConfirmHandshake(request, context); - received.ShouldNotBeNull(); - } - - #endregion - - #region Boradcast - - [Fact] - public async Task BlockBroadcastStream_UnknownPeer_Test() - { - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" }}; - - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); - - var requestStream = new TestAsyncStreamReader(new List { block }); - await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)) - .ShouldThrowAsync(); - } - - [Fact] - public async Task BlockBroadcastStream_RepeatedBlock_Test() - { - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); - - var requestStream = new TestAsyncStreamReader(new List { block }); - await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); - - requestStream = new TestAsyncStreamReader(new List { block }); - await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - received.Count.ShouldBe(0); - } - - [Fact] - public async Task BlockBroadcastStream_Test() - { - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); - - var peer = _peerPool.GetPeers(true).First(); - peer.SyncState.ShouldNotBe(SyncState.Finished); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); - - var requestStream = new TestAsyncStreamReader(new List { block }); - await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - peer.TryAddKnownBlock(block.GetHash()).ShouldBeFalse(); - received.Count.ShouldBe(1); - peer.SyncState.ShouldBe(SyncState.Finished); - } + [Fact] + public async Task Disconnect_ShouldRemovePeer_Test() + { + await _serverService.Disconnect(new DisconnectReason(), + BuildServerCallContext(new Metadata + { { GrpcConstants.PubkeyMetadataKey, NetworkTestConstants.FakePubkey2 } })); + Assert.Empty(_peerPool.GetPeers(true)); + } - [Fact] - public async Task BlockBroadcastStream_Stream_Test() - { - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); + [Fact] + public async Task GetNodes_Test() + { + var context = BuildServerCallContext(); + var result = await _serverService.GetNodes(null, context); + result.ShouldBe(new NodeList()); + + var node = new NodeInfo + { + Endpoint = "127.0.0.1:2001", + Pubkey = ByteString.CopyFromUtf8("pubkey1") + }; + await _nodeManager.AddNodeAsync(node); + var request = new NodesRequest + { + MaxCount = 1 + }; + result = await _serverService.GetNodes(request, context); + result.Nodes.Count.ShouldBe(1); + result.Nodes[0].ShouldBe(node); + } - var blocks = new List(); - blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, (await _osTestHelper.GenerateTransferTransactions(1)).ToList())); - blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block2"), 2, (await _osTestHelper.GenerateTransferTransactions(2)).ToList())); - blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block3"), 3, (await _osTestHelper.GenerateTransferTransactions(3)).ToList())); - - var context = BuildServerCallContext(); - var requestStream = new TestAsyncStreamReader(blocks.ToArray()); - - context.RequestHeaders.Add(new Metadata.Entry(GrpcConstants.PubkeyMetadataKey, NetworkTestConstants.FakePubkey2)); - await _serverService.BlockBroadcastStream(requestStream, context); - received.Count.ShouldBe(3); - } - - [Fact] - public async Task AnnouncementBroadcastStream_UnknownPeer_Test() + [Fact] + public async Task Ping_Test() + { + var pingResult = await _serverService.Ping(new PingRequest(), BuildServerCallContext()); + pingResult.ShouldBe(new PongReply()); + } + + [Fact] + public async Task CheckHealth_Test() + { + var pingResult = await _serverService.CheckHealth(new HealthCheckRequest(), BuildServerCallContext()); + pingResult.ShouldBe(new HealthCheckReply()); + } + + #region Handshake + + [Fact] + public async Task DoHandshake_Test() + { + var context = BuildServerCallContext(null, "ipv4:127.0.0.1:7878"); + var peerKeyPair = CryptoHelper.GenerateKeyPair(); + var handshake = + NetworkTestHelper.CreateValidHandshake(peerKeyPair, 10, ChainHelper.ConvertBase58ToChainId("AELF"), 2000); + var request = new HandshakeRequest { Handshake = handshake }; + var result = await _serverService.DoHandshake(request, context); + result.Error.ShouldBe(HandshakeError.HandshakeOk); + } + + [Fact] + public async Task DoHandshake_InvalidPeer_Test() + { + var context = BuildServerCallContext(null, "ipv4:127.0.0.1:a"); + var peerKeyPair = CryptoHelper.GenerateKeyPair(); + var handshake = + NetworkTestHelper.CreateValidHandshake(peerKeyPair, 10, ChainHelper.ConvertBase58ToChainId("AELF"), 2000); + var request = new HandshakeRequest { Handshake = handshake }; + var result = await _serverService.DoHandshake(request, context); + result.Error.ShouldBe(HandshakeError.InvalidConnection); + } + + [Fact] + public async Task ConfirmHandshake_Test() + { + PeerConnectedEventData received = null; + _eventBus.Subscribe(t => + { + received = t; + return Task.CompletedTask; + }); + var request = new ConfirmHandshakeRequest(); + var context = BuildServerCallContext(null, "ipv4:127.0.0.1:7878"); + + await _serverService.ConfirmHandshake(request, context); + received.ShouldBe(null); + + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + context = BuildServerCallContext(metadata, "ipv4:127.0.0.1:7878"); + await _serverService.ConfirmHandshake(request, context); + received.ShouldNotBeNull(); + } + + #endregion + + #region Boradcast + + [Fact] + public async Task BlockBroadcastStream_UnknownPeer_Test() + { + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" } }; + + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { block }); + await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)) + .ShouldThrowAsync(); + } + + [Fact] + public async Task BlockBroadcastStream_RepeatedBlock_Test() + { + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { block }); + await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + var received = new List(); + _eventBus.Subscribe(a => { - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" }}; + received.Add(a); + return Task.CompletedTask; + }); - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + requestStream = new TestAsyncStreamReader(new List { block }); + await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); - var requestStream = new TestAsyncStreamReader(new List - { - new BlockAnnouncement - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - } - }); - - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)) - .ShouldThrowAsync(); - } - - [Fact] - public async Task AnnouncementBroadcastStream_RepeatedBlock_Test() + received.Count.ShouldBe(0); + } + + [Fact] + public async Task BlockBroadcastStream_Test() + { + var received = new List(); + _eventBus.Subscribe(a => { - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; + received.Add(a); + return Task.CompletedTask; + }); - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + var peer = _peerPool.GetPeers(true).First(); + peer.SyncState.ShouldNotBe(SyncState.Finished); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; - var requestStream = new TestAsyncStreamReader(new List - { - new BlockAnnouncement - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - } - }); - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); - - requestStream = new TestAsyncStreamReader(new List - { - new BlockAnnouncement - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - } - }); - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - received.Count.ShouldBe(0); - } - - [Fact] - public async Task AnnouncementBroadcastStream_Test() + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { block }); + await _serverService.BlockBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + peer.TryAddKnownBlock(block.GetHash()).ShouldBeFalse(); + received.Count.ShouldBe(1); + peer.SyncState.ShouldBe(SyncState.Finished); + } + + [Fact] + public async Task BlockBroadcastStream_Stream_Test() + { + var received = new List(); + _eventBus.Subscribe(a => + { + received.Add(a); + return Task.CompletedTask; + }); + + var blocks = new List(); + blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList())); + blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block2"), 2, + (await _osTestHelper.GenerateTransferTransactions(2)).ToList())); + blocks.Add(_osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block3"), 3, + (await _osTestHelper.GenerateTransferTransactions(3)).ToList())); + + var context = BuildServerCallContext(); + var requestStream = new TestAsyncStreamReader(blocks.ToArray()); + + context.RequestHeaders.Add( + new Metadata.Entry(GrpcConstants.PubkeyMetadataKey, NetworkTestConstants.FakePubkey2)); + await _serverService.BlockBroadcastStream(requestStream, context); + received.Count.ShouldBe(3); + } + + [Fact] + public async Task AnnouncementBroadcastStream_UnknownPeer_Test() + { + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" } }; + + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { - var received = new List(); - _eventBus.Subscribe(a => + new() { - received.Add(a); - return Task.CompletedTask; - }); - - var peer = _peerPool.GetPeers(true).First(); - peer.SyncState.ShouldNotBe(SyncState.Finished); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, - (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); - - var requestStream = new TestAsyncStreamReader(new List {null}); - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - received.Count.ShouldBe(0); - peer.SyncState.ShouldNotBe(SyncState.Finished); - - requestStream = new TestAsyncStreamReader(new List - { - new BlockAnnouncement() - }); - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - received.Count.ShouldBe(0); - peer.SyncState.ShouldNotBe(SyncState.Finished); - - requestStream = new TestAsyncStreamReader(new List - { - new BlockAnnouncement - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - } - }); - await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - peer.TryAddKnownBlock(block.GetHash()).ShouldBeFalse(); - received.Count.ShouldBe(1); - peer.SyncState.ShouldBe(SyncState.Finished); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + } + }); - [Fact] - public async Task AnnouncementBroadcastStream_Stream_Test() + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)) + .ShouldThrowAsync(); + } + + [Fact] + public async Task AnnouncementBroadcastStream_RepeatedBlock_Test() + { + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { - var received = new List(); - _eventBus.Subscribe(a => + new() { - received.Add(a); - return Task.CompletedTask; - }); - - var announcements = new List(); - for (var i = 0; i < 5; i++) - { - announcements.Add(new BlockAnnouncement - { - BlockHash = HashHelper.ComputeFrom($"block-{i}"), - BlockHeight = 10 + i - }); + BlockHash = block.GetHash(), + BlockHeight = block.Height } - - var pubkey = _peerPool.GetPeers(true).First().Info.Pubkey; - var metadata = new Metadata { - { - GrpcConstants.PubkeyMetadataKey, pubkey - }}; - - var context = BuildServerCallContext(metadata); - var requestStream = new TestAsyncStreamReader(announcements.ToArray()); - - - await _serverService.AnnouncementBroadcastStream(requestStream, context); - received.Count.ShouldBe(5); - } - - [Fact] - public async Task TransactionBroadcastStream_UnknownPeer_Test() + }); + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + var received = new List(); + _eventBus.Subscribe(a => { - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" }}; + received.Add(a); + return Task.CompletedTask; + }); - var transaction = await _osTestHelper.GenerateTransferTransaction(); - - var requestStream = new TestAsyncStreamReader(new List { transaction }); - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)) - .ShouldThrowAsync(); - } - - [Fact] - public async Task TransactionBroadcastStream_RepeatedTransaction_Test() + requestStream = new TestAsyncStreamReader(new List { - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var transaction = await _osTestHelper.GenerateTransferTransaction(); - - var requestStream = new TestAsyncStreamReader(new List { transaction }); - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - var received = new List(); - _eventBus.Subscribe(a => + new() { - received.Add(a); - return Task.CompletedTask; - }); - - requestStream = new TestAsyncStreamReader(new List { transaction }); - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - received.Count.ShouldBe(0); - } - - [Fact] - public async Task TransactionBroadcastStream_TransactionIsTooHigh_Test() + BlockHash = block.GetHash(), + BlockHeight = block.Height + } + }); + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + received.Count.ShouldBe(0); + } + + [Fact] + public async Task AnnouncementBroadcastStream_Test() + { + var received = new List(); + _eventBus.Subscribe(a => { - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); - - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var chain = await _blockchainService.GetChainAsync(); - - var transaction = await _osTestHelper.GenerateTransferTransaction(); - transaction.RefBlockNumber = chain.LongestChainHeight + NetworkConstants.DefaultInitialSyncOffset + 1; - - var requestStream = new TestAsyncStreamReader(new List { transaction }); - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - peer.TryAddKnownBlock(transaction.GetHash()).ShouldBeTrue(); - received.Count.ShouldBe(0); - } - - [Fact] - public async Task TransactionBroadcastStream_Test() + received.Add(a); + return Task.CompletedTask; + }); + + var peer = _peerPool.GetPeers(true).First(); + peer.SyncState.ShouldNotBe(SyncState.Finished); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("block1"), 1, + (await _osTestHelper.GenerateTransferTransactions(1)).ToList()); + + var requestStream = new TestAsyncStreamReader(new List { null }); + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); + received.Count.ShouldBe(0); + peer.SyncState.ShouldNotBe(SyncState.Finished); + + requestStream = new TestAsyncStreamReader(new List { - var received = new List(); - _eventBus.Subscribe(a => - { - received.Add(a); - return Task.CompletedTask; - }); - - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var transaction = await _osTestHelper.GenerateTransferTransaction(); - - var requestStream = new TestAsyncStreamReader(new List { transaction }); - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - peer.TryAddKnownTransaction(transaction.GetHash()).ShouldBeFalse(); - received.Count.ShouldBe(1); - } + new() + }); + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); + received.Count.ShouldBe(0); + peer.SyncState.ShouldNotBe(SyncState.Finished); - [Fact] - public async Task TransactionBroadcastStream_Stream_Test() + requestStream = new TestAsyncStreamReader(new List { - var received = new List(); - _eventBus.Subscribe(t => + new() { - received.Add(t); - return Task.CompletedTask; - }); - - var peer = _peerPool.GetPeers(true).First(); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var transactions = await _osTestHelper.GenerateTransferTransactions(3); - var requestStream = new TestAsyncStreamReader(transactions.ToArray()); - - await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); - - received.Count.ShouldBe(3); - } - - [Fact] - public async Task LibAnnouncementBroadcastStream_UnknownPeer_Test() - { - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" }}; + BlockHash = block.GetHash(), + BlockHeight = block.Height + } + }); + await _serverService.AnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)); - var transaction = await _osTestHelper.GenerateTransferTransaction(); + peer.TryAddKnownBlock(block.GetHash()).ShouldBeFalse(); + received.Count.ShouldBe(1); + peer.SyncState.ShouldBe(SyncState.Finished); + } - var requestStream = new TestAsyncStreamReader(new List - { - new LibAnnouncement - { - LibHeight = 100, - LibHash = HashHelper.ComputeFrom("LibHash") - } - }); - await _serverService.LibAnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)) - .ShouldThrowAsync(); - } - - [Fact] - public async Task LibAnnouncementBroadcastStream_Test() + [Fact] + public async Task AnnouncementBroadcastStream_Stream_Test() + { + var received = new List(); + _eventBus.Subscribe(a => { - var libHeight = 100; - var libHash = HashHelper.ComputeFrom("LibHash"); - var peer = _peerPool.GetPeers(true).First(); - peer.SyncState.ShouldNotBe(SyncState.Finished); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - var context = BuildServerCallContext(metadata); - - var lastLibHeight = peer.LastKnownLibHeight; - var lastLibHash = peer.LastKnownLibHash; - var requestStream = new TestAsyncStreamReader(new List - { - null - }); - await _serverService.LibAnnouncementBroadcastStream(requestStream, context); - peer.SyncState.ShouldNotBe(SyncState.Finished); - peer.LastKnownLibHash.ShouldBe(lastLibHash); - peer.LastKnownLibHeight.ShouldBe(lastLibHeight); - - requestStream = new TestAsyncStreamReader(new List - { - new LibAnnouncement() - }); - await _serverService.LibAnnouncementBroadcastStream(requestStream, context); - peer.SyncState.ShouldNotBe(SyncState.Finished); - peer.LastKnownLibHash.ShouldBe(lastLibHash); - peer.LastKnownLibHeight.ShouldBe(lastLibHeight); + received.Add(a); + return Task.CompletedTask; + }); - requestStream = new TestAsyncStreamReader(new List + var announcements = new List(); + for (var i = 0; i < 5; i++) + announcements.Add(new BlockAnnouncement { - new LibAnnouncement - { - LibHeight = libHeight, - LibHash = libHash - } + BlockHash = HashHelper.ComputeFrom($"block-{i}"), + BlockHeight = 10 + i }); - await _serverService.LibAnnouncementBroadcastStream(requestStream, context); - - peer.SyncState.ShouldBe(SyncState.Finished); - peer.LastKnownLibHash.ShouldBe(libHash); - peer.LastKnownLibHeight.ShouldBe(libHeight); - } - [Fact] - public async Task LibAnnouncementBroadcastStream_Stream_Test() + var pubkey = _peerPool.GetPeers(true).First().Info.Pubkey; + var metadata = new Metadata { - long libHeight = 0; - var libHash = Hash.Empty; - var libAnnouncements = new List(); - for (var i = 0; i <= 3; i++) { - libHeight = 100 + i; - libHash = HashHelper.ComputeFrom(libHeight); - - libAnnouncements.Add(new LibAnnouncement - { - LibHeight = libHeight, - LibHash = libHash - }); + GrpcConstants.PubkeyMetadataKey, pubkey } - var peer = _peerPool.GetPeers(true).First(); - peer.SyncState.ShouldNotBe(SyncState.Finished); - var pubkey = peer.Info.Pubkey; - var metadata = new Metadata {{ GrpcConstants.PubkeyMetadataKey, pubkey }}; - - var requestStream = new TestAsyncStreamReader(libAnnouncements); - var context = BuildServerCallContext(metadata); - await _serverService.LibAnnouncementBroadcastStream(requestStream, context); - - peer.SyncState.ShouldBe(SyncState.Finished); - peer.LastKnownLibHash.ShouldBe(libHash); - peer.LastKnownLibHeight.ShouldBe(libHeight); - } - - #endregion - - #region RequestBlock - - [Fact] - public async Task RequestBlock_SyncStateIsNotFinished_Test() - { - _syncStateProvider.SetSyncTarget(0); - - var peer = _peerPool.GetPeers(true).First(); - var pubKey = peer.Info.Pubkey; - Metadata metadata = new Metadata {{GrpcConstants.PubkeyMetadataKey, pubKey}}; - var context = BuildServerCallContext(metadata); - var chain = await _blockchainService.GetChainAsync(); - var reply = await _serverService.RequestBlock(new BlockRequest { Hash = chain.LongestChainHash }, context); - - Assert.NotNull(reply); - Assert.Null(reply.Block); - } + }; - [Fact] - public async Task RequestBlock_Test() - { - var peer = _peerPool.GetPeers(true).First(); - var pubKey = peer.Info.Pubkey; - Metadata metadata = new Metadata {{GrpcConstants.PubkeyMetadataKey, pubKey}}; - var context = BuildServerCallContext(metadata); - var chain = await _blockchainService.GetChainAsync(); - var reply = await _serverService.RequestBlock(new BlockRequest { Hash = chain.LongestChainHash }, context); - - Assert.NotNull(reply.Block); - Assert.True(reply.Block.GetHash() == chain.LongestChainHash); - - peer.TryAddKnownBlock(chain.LongestChainHash).ShouldBeFalse(); - } + var context = BuildServerCallContext(metadata); + var requestStream = new TestAsyncStreamReader(announcements.ToArray()); - [Fact] - public async Task RequestBlock_NotExistBlock_ReturnsEmpty() - { - var reply = await _serverService.RequestBlock(new BlockRequest {Hash = HashHelper.ComputeFrom("NotExist")}, - BuildServerCallContext()); - Assert.NotNull(reply); - Assert.Null(reply.Block); - } + await _serverService.AnnouncementBroadcastStream(requestStream, context); + received.Count.ShouldBe(5); + } - [Fact] - public async Task RequestBlock_NoHash_ReturnsEmpty() - { - var reply = await _serverService.RequestBlock(null, BuildServerCallContext()); - Assert.Null(reply.Block); - - reply = await _serverService.RequestBlock(new BlockRequest(), BuildServerCallContext()); - Assert.Null(reply.Block); - } + [Fact] + public async Task TransactionBroadcastStream_UnknownPeer_Test() + { + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" } }; + + var transaction = await _osTestHelper.GenerateTransferTransaction(); - #endregion RequestBlock + var requestStream = new TestAsyncStreamReader(new List { transaction }); + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)) + .ShouldThrowAsync(); + } - #region RequestBlocks + [Fact] + public async Task TransactionBroadcastStream_RepeatedTransaction_Test() + { + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; - [Fact] - public async Task RequestBlocks_Test() + var transaction = await _osTestHelper.GenerateTransferTransaction(); + + var requestStream = new TestAsyncStreamReader(new List { transaction }); + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + var received = new List(); + _eventBus.Subscribe(a => { - var reqBlockContext = BuildServerCallContext(); - var chain = await _blockchainService.GetChainAsync(); - var reply = await _serverService.RequestBlocks(new BlocksRequest { PreviousBlockHash = chain.GenesisBlockHash, Count = 5 }, reqBlockContext); - - Assert.True(reply.Blocks.Count == 5); - reply.Blocks.First().Header.PreviousBlockHash.ShouldBe(chain.GenesisBlockHash); - - } - - [Fact] - public async Task RequestBlocks_SyncStateIsNotFinished_Test() + received.Add(a); + return Task.CompletedTask; + }); + + requestStream = new TestAsyncStreamReader(new List { transaction }); + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + received.Count.ShouldBe(0); + } + + [Fact] + public async Task TransactionBroadcastStream_TransactionIsTooHigh_Test() + { + var received = new List(); + _eventBus.Subscribe(a => { - _syncStateProvider.SetSyncTarget(0); - - var reqBlockContext = BuildServerCallContext(); - var chain = await _blockchainService.GetChainAsync(); - var reply = await _serverService.RequestBlocks(new BlocksRequest { PreviousBlockHash = chain.GenesisBlockHash, Count = 5 }, reqBlockContext); - - Assert.Empty(reply.Blocks); - } - - [Fact] - public async Task RequestBlocks_NotExist_ReturnsEmpty() + received.Add(a); + return Task.CompletedTask; + }); + + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var chain = await _blockchainService.GetChainAsync(); + + var transaction = await _osTestHelper.GenerateTransferTransaction(); + transaction.RefBlockNumber = chain.LongestChainHeight + NetworkConstants.DefaultInitialSyncOffset + 1; + + var requestStream = new TestAsyncStreamReader(new List { transaction }); + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + peer.TryAddKnownBlock(transaction.GetHash()).ShouldBeTrue(); + received.Count.ShouldBe(0); + } + + [Fact] + public async Task TransactionBroadcastStream_Test() + { + var received = new List(); + _eventBus.Subscribe(a => { - var reply = await _serverService.RequestBlocks(new BlocksRequest { PreviousBlockHash = HashHelper.ComputeFrom("NotExist"), Count = 5 }, BuildServerCallContext()); - Assert.Empty(reply.Blocks); - } - - [Fact] - public async Task RequestBlocks_NoHash_ReturnsEmpty() + received.Add(a); + return Task.CompletedTask; + }); + + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var transaction = await _osTestHelper.GenerateTransferTransaction(); + + var requestStream = new TestAsyncStreamReader(new List { transaction }); + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + peer.TryAddKnownTransaction(transaction.GetHash()).ShouldBeFalse(); + received.Count.ShouldBe(1); + } + + [Fact] + public async Task TransactionBroadcastStream_Stream_Test() + { + var received = new List(); + _eventBus.Subscribe(t => { - var reply = await _serverService.RequestBlocks(null, BuildServerCallContext()); - Assert.Empty(reply.Blocks); - - reply = await _serverService.RequestBlocks(new BlocksRequest(), BuildServerCallContext()); - Assert.Empty(reply.Blocks); - } + received.Add(t); + return Task.CompletedTask; + }); + + var peer = _peerPool.GetPeers(true).First(); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var transactions = await _osTestHelper.GenerateTransferTransactions(3); + var requestStream = new TestAsyncStreamReader(transactions.ToArray()); + + await _serverService.TransactionBroadcastStream(requestStream, BuildServerCallContext(metadata)); + + received.Count.ShouldBe(3); + } + + [Fact] + public async Task LibAnnouncementBroadcastStream_UnknownPeer_Test() + { + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, "UnknownPeerPubkey" } }; + + var transaction = await _osTestHelper.GenerateTransferTransaction(); - [Fact] - public async Task RequestBlocks_MoreThenLimit_ReturnsEmpty() + var requestStream = new TestAsyncStreamReader(new List { - var serverCallContext = BuildServerCallContext(); - var chain = await _blockchainService.GetChainAsync(); - var reply = await _serverService.RequestBlocks(new BlocksRequest + new() { - PreviousBlockHash = chain.GenesisBlockHash, - Count = GrpcConstants.MaxSendBlockCountLimit + 1 - }, serverCallContext); + LibHeight = 100, + LibHash = HashHelper.ComputeFrom("LibHash") + } + }); + await _serverService.LibAnnouncementBroadcastStream(requestStream, BuildServerCallContext(metadata)) + .ShouldThrowAsync(); + } - Assert.True(reply.Blocks.Count == 0); - } + [Fact] + public async Task LibAnnouncementBroadcastStream_Test() + { + var libHeight = 100; + var libHash = HashHelper.ComputeFrom("LibHash"); + var peer = _peerPool.GetPeers(true).First(); + peer.SyncState.ShouldNotBe(SyncState.Finished); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + var context = BuildServerCallContext(metadata); + + var lastLibHeight = peer.LastKnownLibHeight; + var lastLibHash = peer.LastKnownLibHash; + var requestStream = new TestAsyncStreamReader(new List + { + null + }); + await _serverService.LibAnnouncementBroadcastStream(requestStream, context); + peer.SyncState.ShouldNotBe(SyncState.Finished); + peer.LastKnownLibHash.ShouldBe(lastLibHash); + peer.LastKnownLibHeight.ShouldBe(lastLibHeight); + + requestStream = new TestAsyncStreamReader(new List + { + new() + }); + await _serverService.LibAnnouncementBroadcastStream(requestStream, context); + peer.SyncState.ShouldNotBe(SyncState.Finished); + peer.LastKnownLibHash.ShouldBe(lastLibHash); + peer.LastKnownLibHeight.ShouldBe(lastLibHeight); + + requestStream = new TestAsyncStreamReader(new List + { + new() + { + LibHeight = libHeight, + LibHash = libHash + } + }); + await _serverService.LibAnnouncementBroadcastStream(requestStream, context); - #endregion RequestBlocks - - [Fact] - public async Task Disconnect_ShouldRemovePeer_Test() - { - await _serverService.Disconnect(new DisconnectReason(), BuildServerCallContext(new Metadata {{ GrpcConstants.PubkeyMetadataKey, NetworkTestConstants.FakePubkey2}})); - Assert.Empty(_peerPool.GetPeers(true)); - } - - [Fact] - public async Task GetNodes_Test() + peer.SyncState.ShouldBe(SyncState.Finished); + peer.LastKnownLibHash.ShouldBe(libHash); + peer.LastKnownLibHeight.ShouldBe(libHeight); + } + + [Fact] + public async Task LibAnnouncementBroadcastStream_Stream_Test() + { + long libHeight = 0; + var libHash = Hash.Empty; + var libAnnouncements = new List(); + for (var i = 0; i <= 3; i++) { - var context = BuildServerCallContext(); - var result = await _serverService.GetNodes(null, context); - result.ShouldBe(new NodeList()); + libHeight = 100 + i; + libHash = HashHelper.ComputeFrom(libHeight); - var node = new NodeInfo - { - Endpoint = "127.0.0.1:2001", - Pubkey = ByteString.CopyFromUtf8("pubkey1") - }; - await _nodeManager.AddNodeAsync(node); - var request = new NodesRequest + libAnnouncements.Add(new LibAnnouncement { - MaxCount = 1 - }; - result = await _serverService.GetNodes(request, context); - result.Nodes.Count.ShouldBe(1); - result.Nodes[0].ShouldBe(node); + LibHeight = libHeight, + LibHash = libHash + }); } - [Fact] - public async Task Ping_Test() - { - var pingResult = await _serverService.Ping(new PingRequest(), BuildServerCallContext()); - pingResult.ShouldBe(new PongReply()); - } - - [Fact] - public async Task CheckHealth_Test() + var peer = _peerPool.GetPeers(true).First(); + peer.SyncState.ShouldNotBe(SyncState.Finished); + var pubkey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubkey } }; + + var requestStream = new TestAsyncStreamReader(libAnnouncements); + var context = BuildServerCallContext(metadata); + await _serverService.LibAnnouncementBroadcastStream(requestStream, context); + + peer.SyncState.ShouldBe(SyncState.Finished); + peer.LastKnownLibHash.ShouldBe(libHash); + peer.LastKnownLibHeight.ShouldBe(libHeight); + } + + #endregion + + #region RequestBlock + + [Fact] + public async Task RequestBlock_SyncStateIsNotFinished_Test() + { + _syncStateProvider.SetSyncTarget(0); + + var peer = _peerPool.GetPeers(true).First(); + var pubKey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubKey } }; + var context = BuildServerCallContext(metadata); + var chain = await _blockchainService.GetChainAsync(); + var reply = await _serverService.RequestBlock(new BlockRequest { Hash = chain.LongestChainHash }, context); + + Assert.NotNull(reply); + Assert.Null(reply.Block); + } + + [Fact] + public async Task RequestBlock_Test() + { + var peer = _peerPool.GetPeers(true).First(); + var pubKey = peer.Info.Pubkey; + var metadata = new Metadata { { GrpcConstants.PubkeyMetadataKey, pubKey } }; + var context = BuildServerCallContext(metadata); + var chain = await _blockchainService.GetChainAsync(); + var reply = await _serverService.RequestBlock(new BlockRequest { Hash = chain.LongestChainHash }, context); + + Assert.NotNull(reply.Block); + Assert.True(reply.Block.GetHash() == chain.LongestChainHash); + + peer.TryAddKnownBlock(chain.LongestChainHash).ShouldBeFalse(); + } + + [Fact] + public async Task RequestBlock_NotExistBlock_ReturnsEmpty() + { + var reply = await _serverService.RequestBlock(new BlockRequest { Hash = HashHelper.ComputeFrom("NotExist") }, + BuildServerCallContext()); + + Assert.NotNull(reply); + Assert.Null(reply.Block); + } + + [Fact] + public async Task RequestBlock_NoHash_ReturnsEmpty() + { + var reply = await _serverService.RequestBlock(null, BuildServerCallContext()); + Assert.Null(reply.Block); + + reply = await _serverService.RequestBlock(new BlockRequest(), BuildServerCallContext()); + Assert.Null(reply.Block); + } + + #endregion RequestBlock + + #region RequestBlocks + + [Fact] + public async Task RequestBlocks_Test() + { + var reqBlockContext = BuildServerCallContext(); + var chain = await _blockchainService.GetChainAsync(); + var reply = await _serverService.RequestBlocks( + new BlocksRequest { PreviousBlockHash = chain.GenesisBlockHash, Count = 5 }, reqBlockContext); + + Assert.True(reply.Blocks.Count == 5); + reply.Blocks.First().Header.PreviousBlockHash.ShouldBe(chain.GenesisBlockHash); + } + + [Fact] + public async Task RequestBlocks_SyncStateIsNotFinished_Test() + { + _syncStateProvider.SetSyncTarget(0); + + var reqBlockContext = BuildServerCallContext(); + var chain = await _blockchainService.GetChainAsync(); + var reply = await _serverService.RequestBlocks( + new BlocksRequest { PreviousBlockHash = chain.GenesisBlockHash, Count = 5 }, reqBlockContext); + + Assert.Empty(reply.Blocks); + } + + [Fact] + public async Task RequestBlocks_NotExist_ReturnsEmpty() + { + var reply = await _serverService.RequestBlocks( + new BlocksRequest { PreviousBlockHash = HashHelper.ComputeFrom("NotExist"), Count = 5 }, + BuildServerCallContext()); + Assert.Empty(reply.Blocks); + } + + [Fact] + public async Task RequestBlocks_NoHash_ReturnsEmpty() + { + var reply = await _serverService.RequestBlocks(null, BuildServerCallContext()); + Assert.Empty(reply.Blocks); + + reply = await _serverService.RequestBlocks(new BlocksRequest(), BuildServerCallContext()); + Assert.Empty(reply.Blocks); + } + + [Fact] + public async Task RequestBlocks_MoreThenLimit_ReturnsEmpty() + { + var serverCallContext = BuildServerCallContext(); + var chain = await _blockchainService.GetChainAsync(); + var reply = await _serverService.RequestBlocks(new BlocksRequest { - var pingResult = await _serverService.CheckHealth(new HealthCheckRequest(), BuildServerCallContext()); - pingResult.ShouldBe(new HealthCheckReply()); - } + PreviousBlockHash = chain.GenesisBlockHash, + Count = GrpcConstants.MaxSendBlockCountLimit + 1 + }, serverCallContext); + + Assert.True(reply.Blocks.Count == 0); } + + #endregion RequestBlocks } \ No newline at end of file diff --git a/test/AElf.OS.TestBase/AElf.OS.TestBase.csproj b/test/AElf.OS.TestBase/AElf.OS.TestBase.csproj index d422bbe95e..e857f288b0 100644 --- a/test/AElf.OS.TestBase/AElf.OS.TestBase.csproj +++ b/test/AElf.OS.TestBase/AElf.OS.TestBase.csproj @@ -5,18 +5,18 @@ false - - - - - - - - + + + + + + + + - - + + diff --git a/test/AElf.OS.TestBase/MockTxHub.cs b/test/AElf.OS.TestBase/MockTxHub.cs index 0776577767..c7f5d3314d 100644 --- a/test/AElf.OS.TestBase/MockTxHub.cs +++ b/test/AElf.OS.TestBase/MockTxHub.cs @@ -8,97 +8,89 @@ using AElf.Kernel.TransactionPool.Infrastructure; using AElf.Types; -namespace AElf.OS +namespace AElf.OS; + +public class MockTxHub : ITxHub { - public class MockTxHub : ITxHub - { - private readonly ITransactionManager _transactionManager; - private readonly IBlockchainService _blockchainService; + private readonly Dictionary _allTransactions = new(); - private readonly Dictionary _allTransactions = - new Dictionary(); + private readonly IBlockchainService _blockchainService; + private readonly ITransactionManager _transactionManager; + private Hash _bestChainHash = Hash.Empty; - private long _bestChainHeight = AElfConstants.GenesisBlockHeight - 1; - private Hash _bestChainHash = Hash.Empty; + private long _bestChainHeight = AElfConstants.GenesisBlockHeight - 1; - public MockTxHub(ITransactionManager transactionManager, IBlockchainService blockchainService) - { - _transactionManager = transactionManager; - _blockchainService = blockchainService; - } + public MockTxHub(ITransactionManager transactionManager, IBlockchainService blockchainService) + { + _transactionManager = transactionManager; + _blockchainService = blockchainService; + } - public Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount = 0) + public Task GetExecutableTransactionSetAsync(Hash blockHash, int transactionCount = 0) + { + return Task.FromResult(new ExecutableTransactionSet { - return Task.FromResult(new ExecutableTransactionSet - { - PreviousBlockHash = _bestChainHash, - PreviousBlockHeight = _bestChainHeight, - Transactions = _allTransactions.Values.ToList() - }); - } + PreviousBlockHash = _bestChainHash, + PreviousBlockHeight = _bestChainHeight, + Transactions = _allTransactions.Values.ToList() + }); + } - public async Task AddTransactionsAsync(IEnumerable transactions) + public async Task AddTransactionsAsync(IEnumerable transactions) + { + var txs = transactions.ToList(); + foreach (var transaction in txs) { - var txs = transactions.ToList(); - foreach (var transaction in txs) - { - if (_allTransactions.ContainsKey(transaction.GetHash())) - continue; - _allTransactions.Add(transaction.GetHash(), transaction); - } - - await _transactionManager.AddTransactionsAsync(txs); + if (_allTransactions.ContainsKey(transaction.GetHash())) + continue; + _allTransactions.Add(transaction.GetHash(), transaction); } - public Task CleanByTransactionIdsAsync(IEnumerable transactionIds) - { - CleanTransactions(transactionIds); - - return Task.CompletedTask; - } + await _transactionManager.AddTransactionsAsync(txs); + } - public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) - { - _bestChainHeight = bestChainHeight; - _bestChainHash = bestChainHash; - await Task.CompletedTask; - } + public Task CleanByTransactionIdsAsync(IEnumerable transactionIds) + { + CleanTransactions(transactionIds); - public async Task CleanByHeightAsync(long height) - { - await Task.CompletedTask; - } + return Task.CompletedTask; + } - public async Task GetQueuedTransactionAsync(Hash transactionId) - { - if (!_allTransactions.TryGetValue(transactionId, out var transaction)) - { - return null; - } - - var queuedTransaction = await Task.FromResult(new QueuedTransaction - { - TransactionId = transactionId, - Transaction = transaction - }); - - return queuedTransaction; - } + public async Task UpdateTransactionPoolByBestChainAsync(Hash bestChainHash, long bestChainHeight) + { + _bestChainHeight = bestChainHeight; + _bestChainHash = bestChainHash; + await Task.CompletedTask; + } + + public async Task CleanByHeightAsync(long height) + { + await Task.CompletedTask; + } + + public async Task GetQueuedTransactionAsync(Hash transactionId) + { + if (!_allTransactions.TryGetValue(transactionId, out var transaction)) return null; - public Task GetTransactionPoolStatusAsync() + var queuedTransaction = await Task.FromResult(new QueuedTransaction { - return Task.FromResult(new TransactionPoolStatus - { - AllTransactionCount = _allTransactions.Count, - }); - } + TransactionId = transactionId, + Transaction = transaction + }); - private void CleanTransactions(IEnumerable transactionIds) + return queuedTransaction; + } + + public Task GetTransactionPoolStatusAsync() + { + return Task.FromResult(new TransactionPoolStatus { - foreach (var transactionId in transactionIds) - { - _allTransactions.Remove(transactionId, out _); - } - } + AllTransactionCount = _allTransactions.Count + }); + } + + private void CleanTransactions(IEnumerable transactionIds) + { + foreach (var transactionId in transactionIds) _allTransactions.Remove(transactionId, out _); } } \ No newline at end of file diff --git a/test/AElf.OS.TestBase/OSTestBaseAElfModule.cs b/test/AElf.OS.TestBase/OSTestBaseAElfModule.cs index 3c39c732ce..eda8c9b2a9 100644 --- a/test/AElf.OS.TestBase/OSTestBaseAElfModule.cs +++ b/test/AElf.OS.TestBase/OSTestBaseAElfModule.cs @@ -5,19 +5,18 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; -namespace AElf.OS +namespace AElf.OS; + +[DependsOn( + typeof(CoreOSAElfModule), + typeof(AEDPoSAElfModule), + typeof(CSharpRuntimeAElfModule), + typeof(KernelTestAElfModule) +)] +public class OSTestBaseAElfModule : AElfModule { - [DependsOn( - typeof(CoreOSAElfModule), - typeof(AEDPoSAElfModule), - typeof(CSharpRuntimeAElfModule), - typeof(KernelTestAElfModule) - )] - public class OSTestBaseAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); } } \ No newline at end of file diff --git a/test/AElf.OS.TestBase/OSTestHelper.cs b/test/AElf.OS.TestBase/OSTestHelper.cs index 67b3be9695..a2f430808f 100644 --- a/test/AElf.OS.TestBase/OSTestHelper.cs +++ b/test/AElf.OS.TestBase/OSTestHelper.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; @@ -12,7 +11,6 @@ using AElf.Kernel; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Events; using AElf.Kernel.Blockchain.Infrastructure; using AElf.Kernel.Consensus; using AElf.Kernel.Miner.Application; @@ -23,492 +21,500 @@ using AElf.OS.Network; using AElf.OS.Node.Application; using AElf.OS.Node.Domain; +using AElf.Standards.ACS0; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Options; using Volo.Abp.Threading; -namespace AElf.OS +namespace AElf.OS; + +public class OSTestHelper { - public class OSTestHelper + private readonly IAccountService _accountService; + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + + private readonly ChainOptions _chainOptions; + private readonly IMinerService _minerService; + + private readonly IOsBlockchainNodeContextService _osBlockchainNodeContextService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IStaticChainInformationProvider _staticChainInformationProvider; + private readonly ITransactionPoolService _transactionPoolService; + private readonly ITransactionResultService _transactionResultService; + + public readonly long TokenTotalSupply = 100_0000_0000_0000_0000L; + + private OsBlockchainNodeContext _blockchainNodeCtxt; + private IReadOnlyDictionary _codes; + + public OSTestHelper(IOsBlockchainNodeContextService osBlockchainNodeContextService, + IAccountService accountService, + IMinerService minerService, + IBlockchainService blockchainService, + ISmartContractAddressService smartContractAddressService, + IBlockAttachService blockAttachService, + IStaticChainInformationProvider staticChainInformationProvider, + ITransactionResultService transactionResultService, + IOptionsSnapshot chainOptions, + ITransactionPoolService transactionPoolService) { - private IReadOnlyDictionary _codes; - - public readonly long TokenTotalSupply = 100_0000_0000_0000_0000L; - public long MockChainTokenAmount { get; private set; } - public IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - public byte[] ConsensusContractCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; - public byte[] ElectionContractCode => Codes.Single(kv => kv.Key.Contains("Election")).Value; - public byte[] TokenContractCode => - Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("MultiToken")).Value; - - private readonly ChainOptions _chainOptions; - - private readonly IOsBlockchainNodeContextService _osBlockchainNodeContextService; - private readonly IAccountService _accountService; - private readonly IMinerService _minerService; - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITransactionPoolService _transactionPoolService; - private readonly IStaticChainInformationProvider _staticChainInformationProvider; - private readonly IBlockAttachService _blockAttachService; - private readonly ITransactionResultService _transactionResultService; - - private OsBlockchainNodeContext _blockchainNodeCtxt; - - /// - /// 12 Blocks: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - /// - public List BestBranchBlockList { get; set; } - - /// - /// 5 Blocks: q -> r -> s -> t -> u - /// - public List ForkBranchBlockList { get; set; } - - /// - /// 5 Blocks: v -> w -> x -> y -> z - /// - public List NotLinkedBlockList { get; set; } - - public OSTestHelper(IOsBlockchainNodeContextService osBlockchainNodeContextService, - IAccountService accountService, - IMinerService minerService, - IBlockchainService blockchainService, - ISmartContractAddressService smartContractAddressService, - IBlockAttachService blockAttachService, - IStaticChainInformationProvider staticChainInformationProvider, - ITransactionResultService transactionResultService, - IOptionsSnapshot chainOptions, - ITransactionPoolService transactionPoolService) - { - _chainOptions = chainOptions.Value; - _osBlockchainNodeContextService = osBlockchainNodeContextService; - _accountService = accountService; - _minerService = minerService; - _blockchainService = blockchainService; - _smartContractAddressService = smartContractAddressService; - _blockAttachService = blockAttachService; - _staticChainInformationProvider = staticChainInformationProvider; - _transactionResultService = transactionResultService; - _transactionPoolService = transactionPoolService; - - BestBranchBlockList = new List(); - ForkBranchBlockList = new List(); - NotLinkedBlockList = new List(); - } + _chainOptions = chainOptions.Value; + _osBlockchainNodeContextService = osBlockchainNodeContextService; + _accountService = accountService; + _minerService = minerService; + _blockchainService = blockchainService; + _smartContractAddressService = smartContractAddressService; + _blockAttachService = blockAttachService; + _staticChainInformationProvider = staticChainInformationProvider; + _transactionResultService = transactionResultService; + _transactionPoolService = transactionPoolService; + + BestBranchBlockList = new List(); + ForkBranchBlockList = new List(); + NotLinkedBlockList = new List(); + } + + public long MockChainTokenAmount { get; private set; } + + public IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); + + public byte[] ConsensusContractCode => Codes.Single(kv => kv.Key.Contains("Consensus.AEDPoS")).Value; + public byte[] ElectionContractCode => Codes.Single(kv => kv.Key.Contains("Election")).Value; + + public byte[] TokenContractCode => + Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("MultiToken")).Value; + + /// + /// 12 Blocks: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + /// + public List BestBranchBlockList { get; set; } + + /// + /// 5 Blocks: q -> r -> s -> t -> u + /// + public List ForkBranchBlockList { get; set; } + + /// + /// 5 Blocks: v -> w -> x -> y -> z + /// + public List NotLinkedBlockList { get; set; } + + /// + /// Mock a chain with a best branch, and some fork branches + /// + /// + /// Mock Chain + /// BestChainHeight: 11 + /// LIB height: 5 + /// Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 + /// Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k + /// Fork Branch: (e)-> q -> r -> s -> t -> u + /// Unlinked Branch: v -> w -> x -> y -> z + /// + public async Task MockChainAsync() + { + await StartNodeAsync(); + var chain = await _blockchainService.GetChainAsync(); - /// - /// Mock a chain with a best branch, and some fork branches - /// - /// - /// Mock Chain - /// BestChainHeight: 11 - /// LIB height: 5 - /// - /// Height: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 - /// Best Branch: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k - /// Fork Branch: (e)-> q -> r -> s -> t -> u - /// Unlinked Branch: v -> w -> x -> y -> z - /// - public async Task MockChainAsync() + if (chain.BestChainHeight == 1) { - await StartNodeAsync(); - var chain = await _blockchainService.GetChainAsync(); + var genesisBlock = await _blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); + BestBranchBlockList.Add(genesisBlock); - if (chain.BestChainHeight == 1) - { - var genesisBlock = await _blockchainService.GetBlockByHashAsync(chain.GenesisBlockHash); - BestBranchBlockList.Add(genesisBlock); + BestBranchBlockList.AddRange(await AddBestBranch()); - BestBranchBlockList.AddRange(await AddBestBranch()); + ForkBranchBlockList = + await AddForkBranch(BestBranchBlockList[4].GetHash(), BestBranchBlockList[4].Height); - ForkBranchBlockList = - await AddForkBranch(BestBranchBlockList[4].GetHash(), BestBranchBlockList[4].Height); + NotLinkedBlockList = await AddForkBranch(HashHelper.ComputeFrom("UnlinkBlock"), 9); - NotLinkedBlockList = await AddForkBranch(HashHelper.ComputeFrom("UnlinkBlock"), 9); + // Set lib + chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, BestBranchBlockList[4].Height, + BestBranchBlockList[4].GetHash()); + } - // Set lib - chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, BestBranchBlockList[4].Height, - BestBranchBlockList[4].GetHash()); - } + await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, + chain.BestChainHeight); + } - await _transactionPoolService.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, - chain.BestChainHeight); - } + public async Task DisposeMock() + { + await StopNode(); + } - public async Task DisposeMock() - { - await StopNode(); - } + public async Task GenerateTransferTransaction() + { + var newUserKeyPair = CryptoHelper.GenerateKeyPair(); + var accountAddress = await _accountService.GetAccountAsync(); - public async Task GenerateTransferTransaction() + var transaction = GenerateTransaction(accountAddress, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.Transfer), + new TransferInput { To = Address.FromPublicKey(newUserKeyPair.PublicKey), Amount = 10, Symbol = "ELF" }); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + return transaction; + } + + public async Task<(List, List)> PrepareTokenForParallel(int count, long tokenAmount = 10) + { + var transactions = new List(); + var keyPairs = new List(); + + var accountAddress = await _accountService.GetAccountAsync(); + for (var i = 0; i < count; i++) { var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - var accountAddress = await _accountService.GetAccountAsync(); - var transaction = GenerateTransaction(accountAddress, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), nameof(TokenContractContainer.TokenContractStub.Transfer), - new TransferInput {To = Address.FromPublicKey(newUserKeyPair.PublicKey), Amount = 10, Symbol = "ELF"}); + new TransferInput + { To = Address.FromPublicKey(newUserKeyPair.PublicKey), Amount = tokenAmount, Symbol = "ELF" }); var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); transaction.Signature = ByteString.CopyFrom(signature); - return transaction; + transactions.Add(transaction); + keyPairs.Add(newUserKeyPair); } - public async Task<(List, List)> PrepareTokenForParallel(int count, long tokenAmount = 10) + return (transactions, keyPairs); + } + + public async Task> GenerateTransactionsWithoutConflictAsync(List keyPairs, + int count = 1) + { + var transactions = new List(); + foreach (var keyPair in keyPairs) { - var transactions = new List(); - var keyPairs = new List(); - - var accountAddress = await _accountService.GetAccountAsync(); + var from = Address.FromPublicKey(keyPair.PublicKey); for (var i = 0; i < count; i++) { - var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - var transaction = GenerateTransaction(accountAddress, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), + var to = CryptoHelper.GenerateKeyPair(); + var transaction = GenerateTransaction(from, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), nameof(TokenContractContainer.TokenContractStub.Transfer), - new TransferInput {To = Address.FromPublicKey(newUserKeyPair.PublicKey), Amount = tokenAmount, Symbol = "ELF"}); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + new TransferInput { To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF" }); + var signature = + CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); transaction.Signature = ByteString.CopyFrom(signature); transactions.Add(transaction); - keyPairs.Add(newUserKeyPair); } - - return (transactions, keyPairs); } - public async Task> GenerateTransactionsWithoutConflictAsync(List keyPairs, int count = 1) - { - var transactions = new List(); - foreach (var keyPair in keyPairs) - { - var from = Address.FromPublicKey(keyPair.PublicKey); - for (var i = 0; i < count; i++) - { - var to = CryptoHelper.GenerateKeyPair(); - var transaction = GenerateTransaction(from, - await _smartContractAddressService.GetAddressByContractNameAsync( await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.Transfer), - new TransferInput {To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF"}); - var signature = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactions.Add(transaction); - } - } + return transactions; + } - return transactions; - } - - public async Task> GenerateApproveTransactions(List keyPairs, int count = 1) + public async Task> GenerateApproveTransactions(List keyPairs, int count = 1) + { + var transactions = new List(); + var spender = await _accountService.GetAccountAsync(); + foreach (var keyPair in keyPairs) { - var transactions = new List(); - var spender = await _accountService.GetAccountAsync(); - foreach (var keyPair in keyPairs) - { - var from = Address.FromPublicKey(keyPair.PublicKey); - var transaction = GenerateTransaction(from, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.Approve), - new ApproveInput {Spender = spender, Amount = count, Symbol = "ELF"}); - var signature = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactions.Add(transaction); - } + var from = Address.FromPublicKey(keyPair.PublicKey); + var transaction = GenerateTransaction(from, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.Approve), + new ApproveInput { Spender = spender, Amount = count, Symbol = "ELF" }); + var signature = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); - return transactions; + transactions.Add(transaction); } - - public async Task> GenerateTransferFromTransactionsWithoutConflict(List keyPairs, int count = 1) - { - var transactions = new List(); - var address = await _accountService.GetAccountAsync(); - foreach (var keyPair in keyPairs) - { - var from = Address.FromPublicKey(keyPair.PublicKey); - for (var i = 0; i < count; i++) - { - var to = CryptoHelper.GenerateKeyPair(); - var transaction = GenerateTransaction(address, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.TransferFrom), - new TransferFromInput - {From = from, To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF"}); - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactions.Add(transaction); - } - } - return transactions; - } - - public async Task> GenerateTransferTransactions(int count) + return transactions; + } + + public async Task> GenerateTransferFromTransactionsWithoutConflict(List keyPairs, + int count = 1) + { + var transactions = new List(); + var address = await _accountService.GetAccountAsync(); + foreach (var keyPair in keyPairs) { - var transactions = new List(); + var from = Address.FromPublicKey(keyPair.PublicKey); for (var i = 0; i < count; i++) { - var transaction = await GenerateTransferTransaction(); + var to = CryptoHelper.GenerateKeyPair(); + var transaction = GenerateTransaction(address, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.TransferFrom), + new TransferFromInput + { From = from, To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF" }); + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + transactions.Add(transaction); } - - return transactions; } - public Transaction GenerateTransaction(Address from, Address to, string methodName, IMessage input) - { - var chain = _blockchainService.GetChainAsync().Result; - var transaction = new Transaction - { - From = from, - To = to, - MethodName = methodName, - Params = input.ToByteString(), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash), - }; - - return transaction; - } + return transactions; + } - public async Task BroadcastTransactions(IEnumerable transactions) + public async Task> GenerateTransferTransactions(int count) + { + var transactions = new List(); + for (var i = 0; i < count; i++) { - await _transactionPoolService.AddTransactionsAsync(transactions); + var transaction = await GenerateTransferTransaction(); + transactions.Add(transaction); } - public async Task MinedOneBlock(Hash previousBlockHash = null, long previousBlockHeight = 0) + return transactions; + } + + public Transaction GenerateTransaction(Address from, Address to, string methodName, IMessage input) + { + var chain = _blockchainService.GetChainAsync().Result; + var transaction = new Transaction { - if (previousBlockHash == null || previousBlockHeight == 0) - { - var chain = await _blockchainService.GetChainAsync(); - previousBlockHash = chain.BestChainHash; - previousBlockHeight = chain.BestChainHeight; - } + From = from, + To = to, + MethodName = methodName, + Params = input.ToByteString(), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + + return transaction; + } - var block = (await _minerService.MineAsync(previousBlockHash, previousBlockHeight, - TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000))).Block; + public async Task BroadcastTransactions(IEnumerable transactions) + { + await _transactionPoolService.AddTransactionsAsync(transactions); + } - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - return block; + public async Task MinedOneBlock(Hash previousBlockHash = null, long previousBlockHeight = 0) + { + if (previousBlockHash == null || previousBlockHeight == 0) + { + var chain = await _blockchainService.GetChainAsync(); + previousBlockHash = chain.BestChainHash; + previousBlockHeight = chain.BestChainHeight; } - public virtual Block GenerateBlock(Hash preBlockHash, long preBlockHeight, IEnumerable transactions = null) - { - var block = new Block - { - Header = new BlockHeader - { - ChainId = _staticChainInformationProvider.ChainId, - Height = preBlockHeight + 1, - PreviousBlockHash = preBlockHash, - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfTransactions = Hash.Empty, - MerkleTreeRootOfWorldState = Hash.Empty, - MerkleTreeRootOfTransactionStatus = Hash.Empty, - SignerPubkey = ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)) - }, - Body = new BlockBody() - }; - if (transactions != null) - { - foreach (var transaction in transactions) - { - block.AddTransaction(transaction); - } + var block = (await _minerService.MineAsync(previousBlockHash, previousBlockHeight, + TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000))).Block; - block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); - } + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); - return block; - } + return block; + } - public BlockWithTransactions GenerateBlockWithTransactions(Hash preBlockHash, long preBlockHeight, - IEnumerable transactions = null) + public virtual Block GenerateBlock(Hash preBlockHash, long preBlockHeight, + IEnumerable transactions = null) + { + var block = new Block { - var block = GenerateBlock(preBlockHash, preBlockHeight, transactions); - var blockWithTransactions = new BlockWithTransactions + Header = new BlockHeader { - Header = block.Header - }; - if (transactions != null) - { - blockWithTransactions.Transactions.AddRange(transactions); - } + ChainId = _staticChainInformationProvider.ChainId, + Height = preBlockHeight + 1, + PreviousBlockHash = preBlockHash, + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfTransactions = Hash.Empty, + MerkleTreeRootOfWorldState = Hash.Empty, + MerkleTreeRootOfTransactionStatus = Hash.Empty, + SignerPubkey = ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)) + }, + Body = new BlockBody() + }; + if (transactions != null) + { + foreach (var transaction in transactions) block.AddTransaction(transaction); - return blockWithTransactions; + block.Header.MerkleTreeRootOfTransactions = block.Body.CalculateMerkleTreeRoot(); } - public async Task
DeployContract() + return block; + } + + public BlockWithTransactions GenerateBlockWithTransactions(Hash preBlockHash, long preBlockHeight, + IEnumerable transactions = null) + { + var block = GenerateBlock(preBlockHash, preBlockHeight, transactions); + var blockWithTransactions = new BlockWithTransactions { - var basicContractZero = _smartContractAddressService.GetZeroSmartContractAddress(); - var accountAddress = await _accountService.GetAccountAsync(); - - var transaction = GenerateTransaction(accountAddress, basicContractZero, - nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.DeploySmartContract), new ContractDeploymentInput() - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(T).Assembly.Location)) - }); + Header = block.Header + }; + if (transactions != null) blockWithTransactions.Transactions.AddRange(transactions); - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); + return blockWithTransactions; + } - await BroadcastTransactions(new List {transaction}); - await MinedOneBlock(); + public async Task
DeployContract() + { + var basicContractZero = _smartContractAddressService.GetZeroSmartContractAddress(); + var accountAddress = await _accountService.GetAccountAsync(); - var txResult = await _transactionResultService.GetTransactionResultAsync(transaction.GetHash()); + var transaction = GenerateTransaction(accountAddress, basicContractZero, + nameof(BasicContractZeroImplContainer.BasicContractZeroImplBase.DeploySmartContract), + new ContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(T).Assembly.Location)) + }); - return Address.Parser.ParseFrom(txResult.ReturnValue); - } + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); - public async Task GetTransactionResultsAsync(Hash transactionId) - { - var res = await _transactionResultService.GetTransactionResultAsync(transactionId); - return res; - } - - public async Task GetChainContextAsync() + await BroadcastTransactions(new List { transaction }); + await MinedOneBlock(); + + var txResult = await _transactionResultService.GetTransactionResultAsync(transaction.GetHash()); + + return Address.Parser.ParseFrom(txResult.ReturnValue); + } + + public async Task GetTransactionResultsAsync(Hash transactionId) + { + var res = await _transactionResultService.GetTransactionResultAsync(transactionId); + return res; + } + + public async Task GetChainContextAsync() + { + var chain = await _blockchainService.GetChainAsync(); + return new ChainContext { - var chain = await _blockchainService.GetChainAsync(); - return new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }; - } + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }; + } - #region private methods + #region private methods - private async Task StartNodeAsync() + private async Task StartNodeAsync() + { + var dto = new OsBlockchainNodeContextStartDto { - var dto = new OsBlockchainNodeContextStartDto - { - ZeroSmartContract = typeof(BasicContractZero), - ChainId = _chainOptions.ChainId - }; + ZeroSmartContract = typeof(BasicContractZero), + ChainId = _chainOptions.ChainId + }; - dto.SmartContractRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; - var consensusContractDto = new GenesisSmartContractDto - { - Code = ConsensusContractCode, - SystemSmartContractName = ConsensusSmartContractAddressNameProvider.Name, - ContractInitializationMethodCallList = new List() - }; - dto.InitializationSmartContracts.Add(consensusContractDto); + dto.SmartContractRunnerCategory = KernelConstants.CodeCoverageRunnerCategory; + var consensusContractDto = new GenesisSmartContractDto + { + Code = ConsensusContractCode, + SystemSmartContractName = ConsensusSmartContractAddressNameProvider.Name, + ContractInitializationMethodCallList = new List() + }; + dto.InitializationSmartContracts.Add(consensusContractDto); - var tokenContractDto = new GenesisSmartContractDto - { - Code = TokenContractCode, - SystemSmartContractName = TokenSmartContractAddressNameProvider.Name, - ContractInitializationMethodCallList = new List() - }; - var ownAddress = await _accountService.GetAccountAsync(); - tokenContractDto - .AddGenesisTransactionMethodCall(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Create), Params = new CreateInput - { - Symbol = "ELF", - TokenName = "ELF_Token", - TotalSupply = TokenTotalSupply, - Decimals = 2, - Issuer = ownAddress, - IsBurnable = true - }.ToByteString() - }); - - tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall - { - MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), - Params = - new SetPrimaryTokenSymbolInput {Symbol = "ELF"}.ToByteString() - }); - tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + var tokenContractDto = new GenesisSmartContractDto + { + Code = TokenContractCode, + SystemSmartContractName = TokenSmartContractAddressNameProvider.Name, + ContractInitializationMethodCallList = new List() + }; + var ownAddress = await _accountService.GetAccountAsync(); + tokenContractDto + .AddGenesisTransactionMethodCall(new ContractInitializationMethodCall { - MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), Params = new IssueInput + MethodName = nameof(TokenContractContainer.TokenContractStub.Create), Params = new CreateInput { Symbol = "ELF", - Amount = TokenTotalSupply, - To = ownAddress, - Memo = "Issue" + TokenName = "ELF_Token", + TotalSupply = TokenTotalSupply, + Decimals = 2, + Issuer = ownAddress, + IsBurnable = true }.ToByteString() }); - tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.SetPrimaryTokenSymbol), + Params = + new SetPrimaryTokenSymbolInput { Symbol = "ELF" }.ToByteString() + }); + tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), Params = new IssueInput { - MethodName = nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), - Params = new Empty().ToByteString() - }); - dto.InitializationSmartContracts.Add(tokenContractDto); + Symbol = "ELF", + Amount = TokenTotalSupply, + To = ownAddress, + Memo = "Issue" + }.ToByteString() + }); + + tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.InitialCoefficients), + Params = new Empty().ToByteString() + }); + dto.InitializationSmartContracts.Add(tokenContractDto); - - var electionContractDto = new GenesisSmartContractDto - { - Code = ElectionContractCode, - SystemSmartContractName = ElectionSmartContractAddressNameProvider.Name, - ContractInitializationMethodCallList = new List() - }; - dto.InitializationSmartContracts.Add(electionContractDto); - _blockchainNodeCtxt = await _osBlockchainNodeContextService.StartAsync(dto); - } + var electionContractDto = new GenesisSmartContractDto + { + Code = ElectionContractCode, + SystemSmartContractName = ElectionSmartContractAddressNameProvider.Name, + ContractInitializationMethodCallList = new List() + }; + dto.InitializationSmartContracts.Add(electionContractDto); + + _blockchainNodeCtxt = await _osBlockchainNodeContextService.StartAsync(dto); + } - private async Task StopNode() + private async Task StopNode() + { + await _osBlockchainNodeContextService.StopAsync(_blockchainNodeCtxt); + } + + private async Task> AddBestBranch() + { + var bestBranchBlockList = new List(); + + for (var i = 0; i < 10; i++) { - await _osBlockchainNodeContextService.StopAsync(_blockchainNodeCtxt); + var chain = await _blockchainService.GetChainAsync(); + var transaction = await GenerateTransferTransaction(); + await BroadcastTransactions(new List { transaction }); + var block = await MinedOneBlock(chain.BestChainHash, chain.BestChainHeight); + var transactionResult = await _transactionResultService.GetTransactionResultAsync(transaction.GetHash()); + var relatedLog = transactionResult.Logs.FirstOrDefault(l => l.Name == nameof(TransactionFeeCharged)); + var fee = relatedLog == null ? 0 : TransactionFeeCharged.Parser.ParseFrom(relatedLog.NonIndexed).Amount; + MockChainTokenAmount += fee + TransferInput.Parser.ParseFrom(transaction.Params).Amount; + bestBranchBlockList.Add(block); } - private async Task> AddBestBranch() - { - var bestBranchBlockList = new List(); + return bestBranchBlockList; + } - for (var i = 0; i < 10; i++) - { - var chain = await _blockchainService.GetChainAsync(); - var transaction = await GenerateTransferTransaction(); - await BroadcastTransactions(new List {transaction}); - var block = await MinedOneBlock(chain.BestChainHash, chain.BestChainHeight); - var transactionResult = await _transactionResultService.GetTransactionResultAsync(transaction.GetHash()); - var relatedLog = transactionResult.Logs.FirstOrDefault(l => l.Name == nameof(TransactionFeeCharged)); - var fee = relatedLog == null ? 0 : TransactionFeeCharged.Parser.ParseFrom(relatedLog.NonIndexed).Amount; - MockChainTokenAmount += fee + TransferInput.Parser.ParseFrom(transaction.Params).Amount; - bestBranchBlockList.Add(block); - } + private async Task> AddForkBranch(Hash previousHash, long previousHeight) + { + var forkBranchBlockList = new List(); - return bestBranchBlockList; - } - - private async Task> AddForkBranch(Hash previousHash, long previousHeight) + for (var i = 0; i < 5; i++) { - var forkBranchBlockList = new List(); - - for (var i = 0; i < 5; i++) - { // var transaction = await GenerateTransferTransaction(); // await BroadcastTransactions(new List {transaction}); - var block = await MinedOneBlock(previousHash,previousHeight); - - forkBranchBlockList.Add(block); + var block = await MinedOneBlock(previousHash, previousHeight); - previousHeight++; - previousHash = block.GetHash(); - } + forkBranchBlockList.Add(block); - return forkBranchBlockList; + previousHeight++; + previousHash = block.GetHash(); } - - #endregion + + return forkBranchBlockList; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.OS.TestBase/TestingSmartContractExecutiveService.cs b/test/AElf.OS.TestBase/TestingSmartContractExecutiveService.cs index a68f06fbc2..2655ea6d55 100644 --- a/test/AElf.OS.TestBase/TestingSmartContractExecutiveService.cs +++ b/test/AElf.OS.TestBase/TestingSmartContractExecutiveService.cs @@ -1,27 +1,24 @@ -using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.SmartContract.Infrastructure; -namespace AElf.OS +namespace AElf.OS; + +public class TestingSmartContractExecutiveService : SmartContractExecutiveService { - public class TestingSmartContractExecutiveService : SmartContractExecutiveService + public TestingSmartContractExecutiveService( + IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, + ISmartContractRunnerContainer smartContractRunnerContainer, + IHostSmartContractBridgeContextService hostSmartContractBridgeContextService, + ISmartContractRegistrationProvider smartContractRegistrationProvider, + ISmartContractExecutiveProvider smartContractExecutiveProvider, + ITransactionContextFactory transactionContextFactory) + : base(defaultContractZeroCodeProvider, + smartContractRunnerContainer, + hostSmartContractBridgeContextService, + smartContractRegistrationProvider, + smartContractExecutiveProvider, + transactionContextFactory + ) { - public TestingSmartContractExecutiveService( - IDefaultContractZeroCodeProvider defaultContractZeroCodeProvider, - ISmartContractRunnerContainer smartContractRunnerContainer, - IHostSmartContractBridgeContextService hostSmartContractBridgeContextService, - ISmartContractRegistrationProvider smartContractRegistrationProvider, - ISmartContractExecutiveProvider smartContractExecutiveProvider, - ITransactionContextFactory transactionContextFactory) - : base(defaultContractZeroCodeProvider, - smartContractRunnerContainer, - hostSmartContractBridgeContextService, - smartContractRegistrationProvider, - smartContractExecutiveProvider, - transactionContextFactory - ) - { - } } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/AElf.OS.Tests.csproj b/test/AElf.OS.Tests/AElf.OS.Tests.csproj index 39b5107935..e3020e0740 100644 --- a/test/AElf.OS.Tests/AElf.OS.Tests.csproj +++ b/test/AElf.OS.Tests/AElf.OS.Tests.csproj @@ -5,19 +5,19 @@ false - - - - - - - + + + + + + + - - - + + + - + \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/AccountServiceTestAElfModule.cs b/test/AElf.OS.Tests/Account/AccountServiceTestAElfModule.cs index b46155d00d..dbc05ded6d 100644 --- a/test/AElf.OS.Tests/Account/AccountServiceTestAElfModule.cs +++ b/test/AElf.OS.Tests/Account/AccountServiceTestAElfModule.cs @@ -2,15 +2,15 @@ using AElf.Modularity; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; +using AccountService = AElf.OS.Account.Application.AccountService; -namespace AElf.OS.Account +namespace AElf.OS.Account; + +[DependsOn(typeof(OSTestAElfModule))] +public class AccountServiceTestAElfModule : AElfModule { - [DependsOn(typeof(OSTestAElfModule))] - public class AccountServiceTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddTransient(); - } + context.Services.AddTransient(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs index bba0d7fc83..399bdd6064 100644 --- a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs @@ -8,97 +8,95 @@ using Shouldly; using Xunit; -namespace AElf.OS.Account.Application +namespace AElf.OS.Account.Application; + +public class AccountServiceTests : AccountServiceTestBase { - public class AccountServiceTests : AccountServiceTestBase - { - private readonly AccountOptions _accountOptions; - private readonly IAccountService _accountService; + private readonly AccountOptions _accountOptions; + private readonly IAccountService _accountService; - public AccountServiceTests() - { - _accountOptions = GetRequiredService>().Value; - _accountService = GetRequiredService(); - } + public AccountServiceTests() + { + _accountOptions = GetRequiredService>().Value; + _accountService = GetRequiredService(); + } - [Fact] - public async Task GetPublicKeyTest() - { - var publicKey = await _accountService.GetPublicKeyAsync(); + [Fact] + public async Task GetPublicKeyTest() + { + var publicKey = await _accountService.GetPublicKeyAsync(); - Assert.Equal(Address.FromPublicKey(publicKey).ToBase58(), _accountOptions.NodeAccount); + Assert.Equal(Address.FromPublicKey(publicKey).ToBase58(), _accountOptions.NodeAccount); - // Test unlock account - publicKey = await _accountService.GetPublicKeyAsync(); - Assert.Equal(Address.FromPublicKey(publicKey).ToBase58(), _accountOptions.NodeAccount); - } + // Test unlock account + publicKey = await _accountService.GetPublicKeyAsync(); + Assert.Equal(Address.FromPublicKey(publicKey).ToBase58(), _accountOptions.NodeAccount); + } - [Fact] - public async Task GetAccountTest() - { - var account = await _accountService.GetAccountAsync(); + [Fact] + public async Task GetAccountTest() + { + var account = await _accountService.GetAccountAsync(); - Assert.Equal(account.ToBase58(), _accountOptions.NodeAccount); - } + Assert.Equal(account.ToBase58(), _accountOptions.NodeAccount); + } - [Fact] - public async Task SignAndVerifyPassTest() - { - var data = HashHelper.ComputeFrom("test").ToByteArray(); + [Fact] + public async Task SignAndVerifyPassTest() + { + var data = HashHelper.ComputeFrom("test").ToByteArray(); - var signature = await _accountService.SignAsync(data); - var publicKey = await _accountService.GetPublicKeyAsync(); + var signature = await _accountService.SignAsync(data); + var publicKey = await _accountService.GetPublicKeyAsync(); - var recoverResult = CryptoHelper.RecoverPublicKey(signature, data, out var recoverPublicKey); - var verifyResult = recoverResult && publicKey.BytesEqual(recoverPublicKey); + var recoverResult = CryptoHelper.RecoverPublicKey(signature, data, out var recoverPublicKey); + var verifyResult = recoverResult && publicKey.BytesEqual(recoverPublicKey); - Assert.True(verifyResult); - } + Assert.True(verifyResult); + } - [Fact] - public async Task SignAndVerifyNotPassTest() - { - var data1 = HashHelper.ComputeFrom("test1").ToByteArray(); - var data2 = HashHelper.ComputeFrom("test2").ToByteArray(); + [Fact] + public async Task SignAndVerifyNotPassTest() + { + var data1 = HashHelper.ComputeFrom("test1").ToByteArray(); + var data2 = HashHelper.ComputeFrom("test2").ToByteArray(); - var signature = await _accountService.SignAsync(data1); - var publicKey = await _accountService.GetPublicKeyAsync(); + var signature = await _accountService.SignAsync(data1); + var publicKey = await _accountService.GetPublicKeyAsync(); - var recoverResult = CryptoHelper.RecoverPublicKey(signature, data2, out var recoverPublicKey); - var verifyResult = recoverResult && publicKey.BytesEqual(recoverPublicKey); + var recoverResult = CryptoHelper.RecoverPublicKey(signature, data2, out var recoverPublicKey); + var verifyResult = recoverResult && publicKey.BytesEqual(recoverPublicKey); - Assert.False(verifyResult); - } + Assert.False(verifyResult); + } - [Fact] - public async Task EncryptAndDecryptMessage() + [Fact] + public async Task EncryptAndDecryptMessage() + { + var stringValue = new StringValue { - var stringValue = new StringValue - { - Value = "EncryptAndDecryptMessage" - }; - var pubicKey = await _accountService.GetPublicKeyAsync(); - var plainMessage = stringValue.ToByteArray(); - - var encryptMessage = await _accountService.EncryptMessageAsync(pubicKey, plainMessage); + Value = "EncryptAndDecryptMessage" + }; + var pubicKey = await _accountService.GetPublicKeyAsync(); + var plainMessage = stringValue.ToByteArray(); - var decryptMessage = await _accountService.DecryptMessageAsync(pubicKey, encryptMessage); + var encryptMessage = await _accountService.EncryptMessageAsync(pubicKey, plainMessage); - decryptMessage.ShouldBe(plainMessage); - } + var decryptMessage = await _accountService.DecryptMessageAsync(pubicKey, encryptMessage); - [Fact] - public async Task GetAccountAsync_WithOptionEmpty() - { - _accountOptions.NodeAccount = string.Empty; - // Test create key pair - var account = await _accountService.GetAccountAsync(); - account.ShouldNotBeNull(); - - // Test read key pair - account = await _accountService.GetAccountAsync(); - account.ShouldNotBeNull(); - } + decryptMessage.ShouldBe(plainMessage); + } + [Fact] + public async Task GetAccountAsync_WithOptionEmpty() + { + _accountOptions.NodeAccount = string.Empty; + // Test create key pair + var account = await _accountService.GetAccountAsync(); + account.ShouldNotBeNull(); + + // Test read key pair + account = await _accountService.GetAccountAsync(); + account.ShouldNotBeNull(); } -} +} \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/Infrastructure/AElfKeyStoreTests.cs b/test/AElf.OS.Tests/Account/Infrastructure/AElfKeyStoreTests.cs index 1b9e5558de..b782d1e7ef 100644 --- a/test/AElf.OS.Tests/Account/Infrastructure/AElfKeyStoreTests.cs +++ b/test/AElf.OS.Tests/Account/Infrastructure/AElfKeyStoreTests.cs @@ -1,6 +1,4 @@ -using System; -using System.IO; -using System.Threading; +using System.IO; using System.Threading.Tasks; using AElf.Cryptography.Exceptions; using AElf.Kernel; @@ -9,113 +7,112 @@ using Shouldly; using Xunit; -namespace AElf.OS.Account.Infrastructure +namespace AElf.OS.Account.Infrastructure; + +public class AElfKeyStoreTests : KeyStoreTestBase { - public class AElfKeyStoreTests : KeyStoreTestBase + private readonly AElfKeyStore _keyStore; + private readonly INodeEnvironmentService _nodeEnvironmentService; + + public AElfKeyStoreTests() + { + _keyStore = GetRequiredService(); + _nodeEnvironmentService = GetRequiredService(); + } + + [Fact] + public async Task Account_Create_And_Open() + { + var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); + keyPair.ShouldNotBe(null); + var list = await _keyStore.GetAccountsAsync(); + list.Count.ShouldBeGreaterThanOrEqualTo(1); + list.ShouldContain(Address.FromPublicKey(keyPair.PublicKey).ToBase58()); + + var address = Address.FromPublicKey(keyPair.PublicKey); + var addString = address.ToBase58(); + address.ShouldNotBe(null); + + //Open account + var errResult = await _keyStore.UnlockAccountAsync(addString, "12"); + errResult.ShouldBe(AccountError.WrongPassword); + + errResult = await _keyStore.UnlockAccountAsync(addString, "123"); + errResult.ShouldBe(AccountError.None); + + errResult = await _keyStore.UnlockAccountAsync(addString, "123"); + errResult.ShouldBe(AccountError.AccountAlreadyUnlocked); + + errResult = await _keyStore.UnlockAccountAsync(addString, "123"); + errResult.ShouldBe(AccountError.AccountAlreadyUnlocked); + } + + [Fact] + public async Task Account_Create_And_Read() + { + await Should.ThrowAsync(() => _keyStore.ReadKeyPairAsync("file", "123")); + + //Create + var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); + keyPair.ShouldNotBe(null); + var address = Address.FromPublicKey(keyPair.PublicKey); + var publicKey = keyPair.PublicKey.ToHex(); + var addString = address.ToBase58(); + + //Read + await Should.ThrowAsync(() => + _keyStore.ReadKeyPairAsync(addString + "_fake", "123")); + + await Should.ThrowAsync(() => + _keyStore.ReadKeyPairAsync(addString, "WrongPassword")); + + var keyPair1 = await _keyStore.ReadKeyPairAsync(addString, "123"); + var address1 = Address.FromPublicKey(keyPair1.PublicKey); + var publicKey1 = keyPair1.PublicKey.ToHex(); + + keyPair.PrivateKey.ShouldBe(keyPair1.PrivateKey); + + publicKey.ShouldBe(publicKey1); + address.ShouldBe(address1); + } + + [Fact] + public async Task Open_NotExist_Account() + { + var address = SampleAddress.AddressList[0]; + var addString = address.ToBase58(); + var keyPair = _keyStore.GetAccountKeyPair(addString); + keyPair.ShouldBeNull(); + + var errResult = await _keyStore.UnlockAccountAsync(addString, "123"); + errResult.ShouldBe(AccountError.AccountFileNotFound); + } + + [Fact] + public async Task GetAccountKeyPair_Test() + { + var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); + var address = Address.FromPublicKey(keyPair.PublicKey).ToBase58(); + + var result = _keyStore.GetAccountKeyPair(address); + result.ShouldBeNull(); + + await _keyStore.UnlockAccountAsync(address, "123"); + result = _keyStore.GetAccountKeyPair(address); + result.ShouldNotBeNull(); + result.PublicKey.ShouldBe(keyPair.PublicKey); + } + + public override void Dispose() + { + base.Dispose(); + DeleteTestFolder(); + } + + private void DeleteTestFolder() { - private readonly AElfKeyStore _keyStore; - private readonly INodeEnvironmentService _nodeEnvironmentService; - - public AElfKeyStoreTests() - { - _keyStore = GetRequiredService(); - _nodeEnvironmentService = GetRequiredService(); - } - - [Fact] - public async Task Account_Create_And_Open() - { - var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); - keyPair.ShouldNotBe(null); - var list = await _keyStore.GetAccountsAsync(); - list.Count.ShouldBeGreaterThanOrEqualTo(1); - list.ShouldContain(Address.FromPublicKey(keyPair.PublicKey).ToBase58()); - - var address = Address.FromPublicKey(keyPair.PublicKey); - var addString = address.ToBase58(); - address.ShouldNotBe(null); - - //Open account - var errResult = await _keyStore.UnlockAccountAsync(addString, "12"); - errResult.ShouldBe(AccountError.WrongPassword); - - errResult = await _keyStore.UnlockAccountAsync(addString, "123"); - errResult.ShouldBe(AccountError.None); - - errResult = await _keyStore.UnlockAccountAsync(addString, "123"); - errResult.ShouldBe(AccountError.AccountAlreadyUnlocked); - - errResult = await _keyStore.UnlockAccountAsync(addString, "123"); - errResult.ShouldBe(AccountError.AccountAlreadyUnlocked); - } - - [Fact] - public async Task Account_Create_And_Read() - { - await Should.ThrowAsync(() => _keyStore.ReadKeyPairAsync("file", "123")); - - //Create - var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); - keyPair.ShouldNotBe(null); - var address = Address.FromPublicKey(keyPair.PublicKey); - var publicKey = keyPair.PublicKey.ToHex(); - var addString = address.ToBase58(); - - //Read - await Should.ThrowAsync(() => - _keyStore.ReadKeyPairAsync(addString + "_fake", "123")); - - await Should.ThrowAsync(() => - _keyStore.ReadKeyPairAsync(addString, "WrongPassword")); - - var keyPair1 = await _keyStore.ReadKeyPairAsync(addString, "123"); - var address1 = Address.FromPublicKey(keyPair1.PublicKey); - var publicKey1 = keyPair1.PublicKey.ToHex(); - - keyPair.PrivateKey.ShouldBe(keyPair1.PrivateKey); - - publicKey.ShouldBe(publicKey1); - address.ShouldBe(address1); - } - - [Fact] - public async Task Open_NotExist_Account() - { - var address = SampleAddress.AddressList[0]; - var addString = address.ToBase58(); - var keyPair = _keyStore.GetAccountKeyPair(addString); - keyPair.ShouldBeNull(); - - var errResult = await _keyStore.UnlockAccountAsync(addString, "123"); - errResult.ShouldBe(AccountError.AccountFileNotFound); - } - - [Fact] - public async Task GetAccountKeyPair_Test() - { - var keyPair = await _keyStore.CreateAccountKeyPairAsync("123"); - var address = Address.FromPublicKey(keyPair.PublicKey).ToBase58(); - - var result = _keyStore.GetAccountKeyPair(address); - result.ShouldBeNull(); - - await _keyStore.UnlockAccountAsync(address, "123"); - result = _keyStore.GetAccountKeyPair(address); - result.ShouldNotBeNull(); - result.PublicKey.ShouldBe(keyPair.PublicKey); - } - - public override void Dispose() - { - base.Dispose(); - DeleteTestFolder(); - } - - private void DeleteTestFolder() - { - var path = Path.Combine(_nodeEnvironmentService.GetAppDataPath(), "keys"); - if (Directory.Exists(path)) - Directory.Delete(path, true); - } + var path = Path.Combine(_nodeEnvironmentService.GetAppDataPath(), "keys"); + if (Directory.Exists(path)) + Directory.Delete(path, true); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/KeyStoreTestAElfModule.cs b/test/AElf.OS.Tests/Account/KeyStoreTestAElfModule.cs index 3d6a00ec7d..98e83de0b1 100644 --- a/test/AElf.OS.Tests/Account/KeyStoreTestAElfModule.cs +++ b/test/AElf.OS.Tests/Account/KeyStoreTestAElfModule.cs @@ -8,31 +8,30 @@ using Volo.Abp; using Volo.Abp.Modularity; -namespace AElf.OS.Account +namespace AElf.OS.Account; + +[DependsOn( + typeof(OSTestAElfModule) +)] +public class KeyStoreTestAElfModule : AElfModule { - [DependsOn( - typeof(OSTestAElfModule) - )] - public class KeyStoreTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(o => { - context.Services.AddSingleton(o => - { - var service = new Mock(); + var service = new Mock(); - service.Setup(s => s.GetAppDataPath()) - .Returns(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "aelftest")); + service.Setup(s => s.GetAppDataPath()) + .Returns(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "aelftest")); - return service.Object; - }); + return service.Object; + }); - context.Services.AddSingleton(); - } + context.Services.AddSingleton(); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceAbnormalPeerTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceAbnormalPeerTests.cs index da8a09166d..7311ed8300 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceAbnormalPeerTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceAbnormalPeerTests.cs @@ -2,100 +2,98 @@ using AElf.OS.BlockSync.Dto; using AElf.OS.BlockSync.Infrastructure; using AElf.OS.Network.Application; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockDownloadServiceAbnormalPeerTests : BlockSyncAbnormalPeerTestBase { - public class BlockDownloadServiceAbnormalPeerTests : BlockSyncAbnormalPeerTestBase + private readonly IBlockDownloadService _blockDownloadService; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly INetworkService _networkService; + + public BlockDownloadServiceAbnormalPeerTests() { - private readonly IBlockDownloadService _blockDownloadService; - private readonly INetworkService _networkService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - - public BlockDownloadServiceAbnormalPeerTests() - { - _blockDownloadService = GetRequiredService(); - _networkService = GetRequiredService(); - _blockSyncStateProvider = GetRequiredService(); - } + _blockDownloadService = GetRequiredService(); + _networkService = GetRequiredService(); + _blockSyncStateProvider = GetRequiredService(); + } + + [Fact] + public async Task DownloadBlock_NotLinkedBlocks() + { + var notLinkedBlockPubkey = "NotLinkedBlockPubkey"; - [Fact] - public async Task DownloadBlock_NotLinkedBlocks() + var abnormalPeer = _networkService.GetPeerByPubkey(notLinkedBlockPubkey); + abnormalPeer.ShouldNotBeNull(); + + var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var notLinkedBlockPubkey = "NotLinkedBlockPubkey"; - - var abnormalPeer = _networkService.GetPeerByPubkey(notLinkedBlockPubkey); - abnormalPeer.ShouldNotBeNull(); - - var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - PreviousBlockHeight = 100, - BatchRequestBlockCount = 5, - MaxBlockDownloadCount = 5, - SuggestedPeerPubkey = notLinkedBlockPubkey, - UseSuggestedPeer = true - }); - result.Success.ShouldBeFalse(); - - abnormalPeer = _networkService.GetPeerByPubkey(notLinkedBlockPubkey); - abnormalPeer.ShouldBeNull(); - } - - [Fact] - public async Task DownloadBlock_WrongLibHash() + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + PreviousBlockHeight = 100, + BatchRequestBlockCount = 5, + MaxBlockDownloadCount = 5, + SuggestedPeerPubkey = notLinkedBlockPubkey, + UseSuggestedPeer = true + }); + result.Success.ShouldBeFalse(); + + abnormalPeer = _networkService.GetPeerByPubkey(notLinkedBlockPubkey); + abnormalPeer.ShouldBeNull(); + } + + [Fact] + public async Task DownloadBlock_WrongLibHash() + { + var wrongLIBPubkey = "WrongLIBPubkey"; + + _blockSyncStateProvider.LastRequestPeerPubkey = wrongLIBPubkey; + + var abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); + abnormalPeer.ShouldNotBeNull(); + + var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var wrongLIBPubkey = "WrongLIBPubkey"; - - _blockSyncStateProvider.LastRequestPeerPubkey = wrongLIBPubkey; - - var abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); - abnormalPeer.ShouldNotBeNull(); - - var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - PreviousBlockHeight = 100, - BatchRequestBlockCount = 5, - MaxBlockDownloadCount = 5, - SuggestedPeerPubkey = "GoodPeerPubkey0", - UseSuggestedPeer = false - }); - - result.Success.ShouldBeTrue(); - result.DownloadBlockCount.ShouldBe(0); - - abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); - abnormalPeer.ShouldBeNull(); - } - - [Fact] - public async Task DownloadBlock_WrongLibHash_NotEnoughPeer() + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + PreviousBlockHeight = 100, + BatchRequestBlockCount = 5, + MaxBlockDownloadCount = 5, + SuggestedPeerPubkey = "GoodPeerPubkey0", + UseSuggestedPeer = false + }); + + result.Success.ShouldBeTrue(); + result.DownloadBlockCount.ShouldBe(0); + + abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); + abnormalPeer.ShouldBeNull(); + } + + [Fact] + public async Task DownloadBlock_WrongLibHash_NotEnoughPeer() + { + var wrongLIBPubkey = "WrongLIBPubkey"; + + _blockSyncStateProvider.LastRequestPeerPubkey = wrongLIBPubkey; + + var abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); + abnormalPeer.ShouldNotBeNull(); + + var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var wrongLIBPubkey = "WrongLIBPubkey"; - - _blockSyncStateProvider.LastRequestPeerPubkey = wrongLIBPubkey; - - var abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); - abnormalPeer.ShouldNotBeNull(); - - var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - PreviousBlockHeight = 155, - BatchRequestBlockCount = 5, - MaxBlockDownloadCount = 5, - SuggestedPeerPubkey = "GoodPeerPubkey14", - UseSuggestedPeer = false - }); - - result.Success.ShouldBeTrue(); - result.DownloadBlockCount.ShouldBe(0); - - abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); - abnormalPeer.ShouldNotBeNull(); - } + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + PreviousBlockHeight = 155, + BatchRequestBlockCount = 5, + MaxBlockDownloadCount = 5, + SuggestedPeerPubkey = "GoodPeerPubkey14", + UseSuggestedPeer = false + }); + + result.Success.ShouldBeTrue(); + result.DownloadBlockCount.ShouldBe(0); + + abnormalPeer = _networkService.GetPeerByPubkey(wrongLIBPubkey); + abnormalPeer.ShouldNotBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceRetryTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceRetryTests.cs index 274f131446..302ce5193a 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceRetryTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceRetryTests.cs @@ -1,70 +1,65 @@ using System.Threading.Tasks; using AElf.OS.BlockSync.Dto; using AElf.OS.Network.Application; -using AElf.OS.Network.Infrastructure; using AElf.Types; using Moq; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockDownloadServiceRetryTests : BlockSyncRetryTestBase { - public class BlockDownloadServiceRetryTests : BlockSyncRetryTestBase + private readonly IBlockDownloadService _blockDownloadService; + private readonly BlockSyncRetryTestContext _blockSyncRetryTestContext; + private readonly INetworkService _networkService; + + public BlockDownloadServiceRetryTests() { - private readonly IBlockDownloadService _blockDownloadService; - private readonly BlockSyncRetryTestContext _blockSyncRetryTestContext; - private readonly INetworkService _networkService; + _blockDownloadService = GetRequiredService(); + _blockSyncRetryTestContext = GetRequiredService(); + _networkService = GetRequiredService(); + } - public BlockDownloadServiceRetryTests() + [Fact] + public async Task DownloadBlocks_Retry_Test() + { + var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - _blockDownloadService = GetRequiredService(); - _blockSyncRetryTestContext = GetRequiredService(); - _networkService = GetRequiredService(); - } + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + PreviousBlockHeight = 100, + BatchRequestBlockCount = 5, + MaxBlockDownloadCount = 5, + SuggestedPeerPubkey = "PeerPubkey0", + UseSuggestedPeer = false + }); - [Fact] - public async Task DownloadBlocks_Retry_Test() - { - var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - PreviousBlockHeight = 100, - BatchRequestBlockCount = 5, - MaxBlockDownloadCount = 5, - SuggestedPeerPubkey = "PeerPubkey0", - UseSuggestedPeer = false - }); + result.Success.ShouldBeFalse(); + result.DownloadBlockCount.ShouldBe(0); + + _blockSyncRetryTestContext.MockedNetworkService.Verify( + s => s.GetBlocksAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + } - result.Success.ShouldBeFalse(); - result.DownloadBlockCount.ShouldBe(0); + [Fact] + public async Task DownloadBlocks_Retry_OnlyOnePeer_Test() + { + foreach (var peer in _networkService.GetPeers(false)) peer.SyncState = SyncState.Syncing; - _blockSyncRetryTestContext.MockedNetworkService.Verify( - s => s.GetBlocksAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); - } - - [Fact] - public async Task DownloadBlocks_Retry_OnlyOnePeer_Test() + var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - foreach (var peer in _networkService.GetPeers(false)) - { - peer.SyncState = SyncState.Syncing; - } - - var result = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - PreviousBlockHeight = 100, - BatchRequestBlockCount = 5, - MaxBlockDownloadCount = 5, - SuggestedPeerPubkey = "PeerPubkey0", - UseSuggestedPeer = false - }); + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + PreviousBlockHeight = 100, + BatchRequestBlockCount = 5, + MaxBlockDownloadCount = 5, + SuggestedPeerPubkey = "PeerPubkey0", + UseSuggestedPeer = false + }); - result.Success.ShouldBeFalse(); - result.DownloadBlockCount.ShouldBe(0); + result.Success.ShouldBeFalse(); + result.DownloadBlockCount.ShouldBe(0); - _blockSyncRetryTestContext.MockedNetworkService.Verify( - s => s.GetBlocksAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); - } + _blockSyncRetryTestContext.MockedNetworkService.Verify( + s => s.GetBlocksAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceTests.cs index 005da27f67..d7138eb3ae 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockDownloadServiceTests.cs @@ -4,183 +4,180 @@ using AElf.Kernel.Blockchain.Application; using AElf.OS.BlockSync.Dto; using AElf.OS.BlockSync.Infrastructure; -using AElf.Types; using Microsoft.Extensions.Options; -using NuGet.Frameworks; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockDownloadServiceTests : BlockSyncTestBase { - public class BlockDownloadServiceTests : BlockSyncTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadService _blockDownloadService; + private readonly BlockSyncOptions _blockSyncOptions; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + + public BlockDownloadServiceTests() { - private readonly IBlockDownloadService _blockDownloadService; - private readonly IBlockchainService _blockchainService; - private readonly BlockSyncOptions _blockSyncOptions; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; + _blockDownloadService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockSyncOptions = GetRequiredService>().Value; + _blockSyncStateProvider = GetRequiredService(); + } - public BlockDownloadServiceTests() - { - _blockDownloadService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockSyncOptions = GetRequiredService>().Value; - _blockSyncStateProvider = GetRequiredService(); - } - - [Fact] - public async Task DownloadBlocks_Success() - { - var chain = await _blockchainService.GetChainAsync(); - - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount - }); - - downloadResult.DownloadBlockCount.ShouldBe(20); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(31); - } - - [Fact] - public async Task DownloadBlocks_UseSuggestedPeer() - { - var chain = await _blockchainService.GetChainAsync(); - - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - UseSuggestedPeer = true - }); - - downloadResult.DownloadBlockCount.ShouldBe(20); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(31); - } - - [Fact] - public async Task DownloadBlocks_NetworkException() - { - var chain = await _blockchainService.GetChainAsync(); - - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - SuggestedPeerPubkey = "NetworkException", - UseSuggestedPeer = true - }); - - downloadResult.Success.ShouldBeFalse(); - downloadResult.DownloadBlockCount.ShouldBe(0); - } - - [Fact] - public async Task DownloadBlocks_MoreThanLimit() + [Fact] + public async Task DownloadBlocks_Success() + { + var chain = await _blockchainService.GetChainAsync(); + + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("MoreThanLimit"), - PreviousBlockHeight = 62, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount - }); - - downloadResult.DownloadBlockCount.ShouldBe(0); - - var chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(11); - } - - [Fact] - public async Task DownloadBlocks_NoBlockReturn() + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount + }); + + downloadResult.DownloadBlockCount.ShouldBe(20); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(31); + } + + [Fact] + public async Task DownloadBlocks_UseSuggestedPeer() + { + var chain = await _blockchainService.GetChainAsync(); + + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = HashHelper.ComputeFrom("NoBlockReturn"), - PreviousBlockHeight = 15, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount - }); - - downloadResult.DownloadBlockCount.ShouldBe(0); - - var chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(11); - } - - [Fact] - public async Task DownloadBlocks_RemovedPeer() + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, + UseSuggestedPeer = true + }); + + downloadResult.DownloadBlockCount.ShouldBe(20); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(31); + } + + [Fact] + public async Task DownloadBlocks_NetworkException() + { + var chain = await _blockchainService.GetChainAsync(); + + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var chain = await _blockchainService.GetChainAsync(); - - var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto - { - PreviousBlockHash = chain.BestChainHash, - PreviousBlockHeight = chain.BestChainHeight, - BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, - MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, - SuggestedPeerPubkey = "RemovedPeer", - UseSuggestedPeer = true - }); - - downloadResult.Success.ShouldBeFalse(); - downloadResult.DownloadBlockCount.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(11); - } - - [Fact] - public void ValidateQueueAvailabilityBeforeDownload_Test() + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, + SuggestedPeerPubkey = "NetworkException", + UseSuggestedPeer = true + }); + + downloadResult.Success.ShouldBeFalse(); + downloadResult.DownloadBlockCount.ShouldBe(0); + } + + [Fact] + public async Task DownloadBlocks_MoreThanLimit() + { + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachBlockAgeLimit - 1000)); - _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeFalse(); - - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit - 1000)); - _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeFalse(); - } - - [Fact] - public void RemoveDownloadJobTargetState_Test() + PreviousBlockHash = HashHelper.ComputeFrom("MoreThanLimit"), + PreviousBlockHeight = 62, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount + }); + + downloadResult.DownloadBlockCount.ShouldBe(0); + + var chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(11); + } + + [Fact] + public async Task DownloadBlocks_NoBlockReturn() + { + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var targetHash = HashHelper.ComputeFrom("TargetHash"); - _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, true); - - _blockDownloadService.RemoveDownloadJobTargetState(null); - _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeTrue(); - - _blockDownloadService.RemoveDownloadJobTargetState(targetHash); - _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeFalse(); - } - - [Fact] - public void IsNotReachedDownloadTarget_Test() + PreviousBlockHash = HashHelper.ComputeFrom("NoBlockReturn"), + PreviousBlockHeight = 15, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount + }); + + downloadResult.DownloadBlockCount.ShouldBe(0); + + var chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(11); + } + + [Fact] + public async Task DownloadBlocks_RemovedPeer() + { + var chain = await _blockchainService.GetChainAsync(); + + var downloadResult = await _blockDownloadService.DownloadBlocksAsync(new DownloadBlockDto { - var targetHash = HashHelper.ComputeFrom("TargetHash"); - _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeFalse(); - - _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, false); - _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeTrue(); - - _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, true); - _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeFalse(); - } + PreviousBlockHash = chain.BestChainHash, + PreviousBlockHeight = chain.BestChainHeight, + BatchRequestBlockCount = _blockSyncOptions.MaxBatchRequestBlockCount, + MaxBlockDownloadCount = _blockSyncOptions.MaxBlockDownloadCount, + SuggestedPeerPubkey = "RemovedPeer", + UseSuggestedPeer = true + }); + + downloadResult.Success.ShouldBeFalse(); + downloadResult.DownloadBlockCount.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(11); + } + + [Fact] + public void ValidateQueueAvailabilityBeforeDownload_Test() + { + _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachBlockAgeLimit - 1000)); + _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeFalse(); + + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit - 1000)); + _blockDownloadService.ValidateQueueAvailabilityBeforeDownload().ShouldBeFalse(); + } + + [Fact] + public void RemoveDownloadJobTargetState_Test() + { + var targetHash = HashHelper.ComputeFrom("TargetHash"); + _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, true); + + _blockDownloadService.RemoveDownloadJobTargetState(null); + _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeTrue(); + + _blockDownloadService.RemoveDownloadJobTargetState(targetHash); + _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out _).ShouldBeFalse(); + } + + [Fact] + public void IsNotReachedDownloadTarget_Test() + { + var targetHash = HashHelper.ComputeFrom("TargetHash"); + _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeFalse(); + + _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, false); + _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeTrue(); + + _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, true); + _blockDownloadService.IsNotReachedDownloadTarget(targetHash).ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceAbnormalPeerTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceAbnormalPeerTests.cs index 743d1a962d..f3a352e1d6 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceAbnormalPeerTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceAbnormalPeerTests.cs @@ -1,36 +1,35 @@ using System.Threading.Tasks; using AElf.OS.Network.Application; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockFetchServiceAbnormalPeerTests : BlockSyncAbnormalPeerTestBase { - public class BlockFetchServiceAbnormalPeerTests : BlockSyncAbnormalPeerTestBase + private readonly IBlockFetchService _blockFetchService; + private readonly INetworkService _networkService; + + public BlockFetchServiceAbnormalPeerTests() + { + _blockFetchService = GetRequiredService(); + _networkService = GetRequiredService(); + } + + [Fact] + public async Task FetchBlock_ReturnInvalidBlock() { - private readonly IBlockFetchService _blockFetchService; - private readonly INetworkService _networkService; + var abnormalPeerPubkey = "AbnormalPeerPubkey"; - public BlockFetchServiceAbnormalPeerTests() - { - _blockFetchService = GetRequiredService(); - _networkService = GetRequiredService(); - } + var abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); + abnormalPeer.ShouldNotBeNull(); - [Fact] - public async Task FetchBlock_ReturnInvalidBlock() - { - var abnormalPeerPubkey = "AbnormalPeerPubkey"; - - var abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); - abnormalPeer.ShouldNotBeNull(); - - var result = - await _blockFetchService.FetchBlockAsync(HashHelper.ComputeFrom("AnnounceBlockHash"), 100, abnormalPeerPubkey); - result.ShouldBeFalse(); + var result = + await _blockFetchService.FetchBlockAsync(HashHelper.ComputeFrom("AnnounceBlockHash"), 100, + abnormalPeerPubkey); + result.ShouldBeFalse(); - abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); - abnormalPeer.ShouldBeNull(); - } + abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); + abnormalPeer.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceTests.cs index 05912ba177..ea9d892868 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockFetchServiceTests.cs @@ -5,53 +5,52 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockFetchServiceTests : BlockSyncTestBase { - public class BlockFetchServiceTests : BlockSyncTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockFetchService _blockFetchService; + private readonly INetworkService _networkService; + + public BlockFetchServiceTests() + { + _blockFetchService = GetRequiredService(); + _networkService = GetRequiredService(); + _blockchainService = GetRequiredService(); + } + + [Fact] + public async Task FetchBlock_Success() { - private readonly IBlockFetchService _blockFetchService; - private readonly INetworkService _networkService; - private readonly IBlockchainService _blockchainService; - - public BlockFetchServiceTests() - { - _blockFetchService = GetRequiredService(); - _networkService = GetRequiredService(); - _blockchainService = GetRequiredService(); - } - - [Fact] - public async Task FetchBlock_Success() - { - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - - var fetchResult = await _blockFetchService.FetchBlockAsync(peerBlock.GetHash(), peerBlock.Height, null); - - fetchResult.ShouldBeTrue(); - - block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.GetHash().ShouldBe(peerBlock.GetHash()); - } - - [Fact] - public async Task FetchBlock_AlreadyExist_Success() - { - var chain = await _blockchainService.GetChainAsync(); - var fetchResult = await _blockFetchService.FetchBlockAsync(chain.BestChainHash, chain.BestChainHeight, null); - - fetchResult.ShouldBeTrue(); - } - - [Fact] - public async Task FetchBlock_ReturnNull_Failure() - { - var fetchResult = await _blockFetchService.FetchBlockAsync(Hash.Empty, 0, null); - - fetchResult.ShouldBeFalse(); - } + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); + + var fetchResult = await _blockFetchService.FetchBlockAsync(peerBlock.GetHash(), peerBlock.Height, null); + + fetchResult.ShouldBeTrue(); + + block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.GetHash().ShouldBe(peerBlock.GetHash()); + } + + [Fact] + public async Task FetchBlock_AlreadyExist_Success() + { + var chain = await _blockchainService.GetChainAsync(); + var fetchResult = await _blockFetchService.FetchBlockAsync(chain.BestChainHash, chain.BestChainHeight, null); + + fetchResult.ShouldBeTrue(); + } + + [Fact] + public async Task FetchBlock_ReturnNull_Failure() + { + var fetchResult = await _blockFetchService.FetchBlockAsync(Hash.Empty, 0, null); + + fetchResult.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceAbnormalPeerTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceAbnormalPeerTests.cs index b56bfd2d92..c26a0b59fc 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceAbnormalPeerTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceAbnormalPeerTests.cs @@ -1,37 +1,35 @@ using System.Threading.Tasks; using AElf.OS.Network.Application; -using AElf.Types; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncAttachServiceAbnormalPeerTests : BlockSyncAttachBlockAbnormalPeerTestBase { - public class BlockSyncAttachServiceAbnormalPeerTests : BlockSyncAttachBlockAbnormalPeerTestBase + private readonly IBlockSyncAttachService _blockSyncAttachService; + private readonly INetworkService _networkService; + private readonly OSTestHelper _osTestHelper; + + public BlockSyncAttachServiceAbnormalPeerTests() + { + _blockSyncAttachService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _networkService = GetRequiredService(); + } + + [Fact] + public async Task Attach_InvalidBlock() { - private readonly IBlockSyncAttachService _blockSyncAttachService; - private readonly OSTestHelper _osTestHelper; - private readonly INetworkService _networkService; - - public BlockSyncAttachServiceAbnormalPeerTests() - { - _blockSyncAttachService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _networkService = GetRequiredService(); - } + var abnormalPeerPubkey = "AbnormalPeerPubkey"; + var badBlock = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), 10000); + + var abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); + abnormalPeer.ShouldNotBeNull(); - [Fact] - public async Task Attach_InvalidBlock() - { - var abnormalPeerPubkey = "AbnormalPeerPubkey"; - var badBlock = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), 10000); - - var abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); - abnormalPeer.ShouldNotBeNull(); + await _blockSyncAttachService.AttachBlockWithTransactionsAsync(badBlock, abnormalPeerPubkey); - await _blockSyncAttachService.AttachBlockWithTransactionsAsync(badBlock, abnormalPeerPubkey); - - abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); - abnormalPeer.ShouldBeNull(); - } + abnormalPeer = _networkService.GetPeerByPubkey(abnormalPeerPubkey); + abnormalPeer.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceTests.cs index c8e0af9578..0c43e463b9 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncAttachServiceTests.cs @@ -2,54 +2,52 @@ using System.Threading.Tasks; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContractExecution.Application; -using AElf.OS.Helpers; using AElf.OS.Network; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncAttachServiceTests : BlockSyncTestBase { - public class BlockSyncAttachServiceTests : BlockSyncTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockSyncAttachService _blockSyncAttachService; + private readonly OSTestHelper _osTestHelper; + + public BlockSyncAttachServiceTests() + { + _blockSyncAttachService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + } + + [Fact] + public async Task AttachBlockWithTransactions_Test() { - private readonly IBlockSyncAttachService _blockSyncAttachService; - private readonly IBlockchainService _blockchainService; - private readonly IBlockExecutingService _blockExecutingService; - private readonly OSTestHelper _osTestHelper; - - public BlockSyncAttachServiceTests() - { - _blockSyncAttachService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - } - - [Fact] - public async Task AttachBlockWithTransactions_Test() - { - var chain = await _blockchainService.GetChainAsync(); - var transactions = await _osTestHelper.GenerateTransferTransactions(2); - var block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - var executedBlock = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - var blockWithTransactions = new BlockWithTransactions - {Header = executedBlock.Header, Transactions = {transactions}}; - - var attachFinished = false; - - await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, "pubkey", - () => - { - attachFinished = true; - return Task.CompletedTask; - }); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(blockWithTransactions.GetHash()); - chain.BestChainHeight.ShouldBe(blockWithTransactions.Height); - attachFinished.ShouldBeTrue(); - - var txs = await _blockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash())); - txs.Count.ShouldBe(2); - } + var chain = await _blockchainService.GetChainAsync(); + var transactions = await _osTestHelper.GenerateTransferTransactions(2); + var block = _osTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + var executedBlock = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + var blockWithTransactions = new BlockWithTransactions + { Header = executedBlock.Header, Transactions = { transactions } }; + + var attachFinished = false; + + await _blockSyncAttachService.AttachBlockWithTransactionsAsync(blockWithTransactions, "pubkey", + () => + { + attachFinished = true; + return Task.CompletedTask; + }); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(blockWithTransactions.GetHash()); + chain.BestChainHeight.ShouldBe(blockWithTransactions.Height); + attachFinished.ShouldBeTrue(); + + var txs = await _blockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash())); + txs.Count.ShouldBe(2); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncQueueServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncQueueServiceTests.cs index a7fc8365d3..e7c3836db9 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncQueueServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncQueueServiceTests.cs @@ -6,88 +6,87 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncQueueServiceTests : BlockSyncTestBase { - public class BlockSyncQueueServiceTests : BlockSyncTestBase + private readonly IBlockSyncQueueService _blockSyncQueueService; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + + public BlockSyncQueueServiceTests() { - private readonly IBlockSyncQueueService _blockSyncQueueService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; + _blockSyncQueueService = GetRequiredService(); + _blockSyncStateProvider = GetRequiredService(); + } - public BlockSyncQueueServiceTests() + [Fact] + public void ValidateQueueAvailability_Test() + { { - _blockSyncQueueService = GetRequiredService(); - _blockSyncStateProvider = GetRequiredService(); + var result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); + result.ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, + TimestampHelper.GetUtcNow()); + result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); + result.ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-BlockSyncConstants.BlockSyncFetchBlockAgeLimit - 1000)); + result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); + result.ShouldBeFalse(); } - [Fact] - public void ValidateQueueAvailability_Test() { - { - var result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, - TimestampHelper.GetUtcNow()); - result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-BlockSyncConstants.BlockSyncFetchBlockAgeLimit - 1000)); - result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockFetchQueueName); - result.ShouldBeFalse(); - } - - { - var result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow()); - result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachBlockAgeLimit - 1000)); - result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); - result.ShouldBeFalse(); - } - - { - var result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, - TimestampHelper.GetUtcNow()); - result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); - result.ShouldBeTrue(); - - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit - 1000)); - result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); - result.ShouldBeFalse(); - } - - Assert.Throws(() => - _blockSyncQueueService.ValidateQueueAvailability("InvalidQueueName")); + var result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); + result.ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow()); + result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); + result.ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachBlockAgeLimit - 1000)); + result = _blockSyncQueueService.ValidateQueueAvailability(OSConstants.BlockSyncAttachQueueName); + result.ShouldBeFalse(); } - [Fact] - public void Enqueue_Test() { - var result = false; - - _blockSyncQueueService.Enqueue(() => - { - result = true; - return Task.CompletedTask; - }, OSConstants.BlockFetchQueueName); - + var result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); result.ShouldBeTrue(); - - _blockSyncStateProvider.GetEnqueueTime(OSConstants.BlockFetchQueueName).ShouldBeNull(); + + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, + TimestampHelper.GetUtcNow()); + result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); + result.ShouldBeTrue(); + + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit - 1000)); + result = _blockSyncQueueService.ValidateQueueAvailability(KernelConstants.UpdateChainQueueName); + result.ShouldBeFalse(); } + + Assert.Throws(() => + _blockSyncQueueService.ValidateQueueAvailability("InvalidQueueName")); + } + + [Fact] + public void Enqueue_Test() + { + var result = false; + + _blockSyncQueueService.Enqueue(() => + { + result = true; + return Task.CompletedTask; + }, OSConstants.BlockFetchQueueName); + + result.ShouldBeTrue(); + + _blockSyncStateProvider.GetEnqueueTime(OSConstants.BlockFetchQueueName).ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncServiceTests.cs index 8b0e70a4e9..cf2a02c60e 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncServiceTests.cs @@ -6,182 +6,84 @@ using AElf.OS.BlockSync.Dto; using AElf.OS.BlockSync.Infrastructure; using AElf.OS.Network.Application; -using AElf.Sdk.CSharp; using AElf.Types; using Shouldly; -using Virgil.Crypto; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncServiceTests : BlockSyncTestBase { - public class BlockSyncServiceTests : BlockSyncTestBase + private readonly IAnnouncementCacheProvider _announcementCacheProvider; + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + private readonly IBlockSyncService _blockSyncService; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly INetworkService _networkService; + private readonly OSTestHelper _osTestHelper; + + public BlockSyncServiceTests() { - private readonly IBlockSyncService _blockSyncService; - private readonly IBlockchainService _blockchainService; - private readonly INetworkService _networkService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - private readonly IBlockDownloadJobStore _blockDownloadJobStore; - private readonly IAnnouncementCacheProvider _announcementCacheProvider; - private readonly OSTestHelper _osTestHelper; - - public BlockSyncServiceTests() - { - _blockSyncService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _networkService = GetRequiredService(); - _blockSyncStateProvider = GetRequiredService(); - _blockDownloadJobStore = GetRequiredService(); - _announcementCacheProvider = GetRequiredService(); - _osTestHelper = GetRequiredService(); - } - - [Fact] - public async Task SyncByAnnounce_Success() - { - var chain = await _blockchainService.GetChainAsync(); - var resp = await _networkService.GetBlocksAsync(chain.BestChainHash, 30, null); - var peerBlocks = resp.Payload; - - var block = peerBlocks[0]; - var peerBlockHash = block.GetHash(); - var peerBlockHeight = block.Height; - { - // Sync one block to best chain - // BestChainHeight: 12 - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlockHash, - SyncBlockHeight = peerBlockHeight, - BatchRequestBlockCount = 5 - }); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(12); - chain.BestChainHash.ShouldBe(peerBlocks[0].GetHash()); - } - - { - // Handle the same announcement again - // BestChainHeight: 12 - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlockHash, - SyncBlockHeight = peerBlockHeight, - BatchRequestBlockCount = 5 - }); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(peerBlocks[0].GetHash()); - chain.BestChainHeight.ShouldBe(12); - } - - { - // Mined one block, and fork - await _osTestHelper.MinedOneBlock(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(13); - } + _blockSyncService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _networkService = GetRequiredService(); + _blockSyncStateProvider = GetRequiredService(); + _blockDownloadJobStore = GetRequiredService(); + _announcementCacheProvider = GetRequiredService(); + _osTestHelper = GetRequiredService(); + } - { - // Receive a higher fork block, sync from the lib - // BestChainHeight: 31 - block = peerBlocks.Last(); - peerBlockHash = block.GetHash(); - peerBlockHeight = block.Height; - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlockHash, - SyncBlockHeight = peerBlockHeight, - BatchRequestBlockCount = 5 - }); - - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.TargetBlockHeight.ShouldBe(peerBlockHeight); - jobInfo.TargetBlockHash.ShouldBe(peerBlockHash); - } - } + [Fact] + public async Task SyncByAnnounce_Success() + { + var chain = await _blockchainService.GetChainAsync(); + var resp = await _networkService.GetBlocksAsync(chain.BestChainHash, 30); + var peerBlocks = resp.Payload; - [Fact] - public async Task SyncByAnnounce_LessThenFetchLimit_Success() + var block = peerBlocks[0]; + var peerBlockHash = block.GetHash(); + var peerBlockHeight = block.Height; { - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - - var chain = await _blockchainService.GetChainAsync(); + // Sync one block to best chain + // BestChainHeight: 12 await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = peerBlock.Height, + SyncBlockHash = peerBlockHash, + SyncBlockHeight = peerBlockHeight, BatchRequestBlockCount = 5 }); - - block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.GetHash().ShouldBe(peerBlock.GetHash()); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(peerBlock.GetHash()); - chain.BestChainHeight.ShouldBe(peerBlock.Height); + chain.BestChainHeight.ShouldBe(12); + chain.BestChainHash.ShouldBe(peerBlocks[0].GetHash()); } - - [Fact] - public async Task SyncByAnnounce_FetchQueueIsBusy() - { - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, TimestampHelper.GetUtcNow() - .AddMilliseconds(-(BlockSyncConstants.BlockSyncFetchBlockAgeLimit + 100))); + { + // Handle the same announcement again + // BestChainHeight: 12 await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = peerBlock.Height, + SyncBlockHash = peerBlockHash, + SyncBlockHeight = peerBlockHeight, BatchRequestBlockCount = 5 }); - - block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); + chain.BestChainHash.ShouldBe(peerBlocks[0].GetHash()); + chain.BestChainHeight.ShouldBe(12); } - - [Fact] - public async Task SyncByAnnounce_LessThenFetchLimit_FetchReturnFalse() - { - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = Hash.Empty, - SyncBlockHeight = 12, - BatchRequestBlockCount = 5 - }); + { + // Mined one block, and fork + await _osTestHelper.MinedOneBlock(); chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); + chain.BestChainHeight.ShouldBe(13); } - [Fact] - public async Task SyncByAnnounce_MoreThenFetchLimit_Success() { - var chain = await _blockchainService.GetChainAsync(); - - var peerBlockHash = HashHelper.ComputeFrom("PeerBlock"); - var peerBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset +1; - + // Receive a higher fork block, sync from the lib + // BestChainHeight: 31 + block = peerBlocks.Last(); + peerBlockHash = block.GetHash(); + peerBlockHeight = block.Height; await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { SyncBlockHash = peerBlockHash, @@ -193,169 +95,264 @@ public async Task SyncByAnnounce_MoreThenFetchLimit_Success() jobInfo.TargetBlockHeight.ShouldBe(peerBlockHeight); jobInfo.TargetBlockHash.ShouldBe(peerBlockHash); } + } + + [Fact] + public async Task SyncByAnnounce_LessThenFetchLimit_Success() + { + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); - [Fact] - public async Task SyncByAnnounce_Fetch_AttachAndExecuteQueueIsBusy() + var chain = await _blockchainService.GetChainAsync(); + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, - TimestampHelper.GetUtcNow() - .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100))); + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = peerBlock.Height, + BatchRequestBlockCount = 5 + }); - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; + block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.GetHash().ShouldBe(peerBlock.GetHash()); - var chain = await _blockchainService.GetChainAsync(); - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, - BatchRequestBlockCount = 5 - }); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(peerBlock.GetHash()); + chain.BestChainHeight.ShouldBe(peerBlock.Height); + } - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - } + [Fact] + public async Task SyncByAnnounce_FetchQueueIsBusy() + { + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); + + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockFetchQueueName, TimestampHelper.GetUtcNow() + .AddMilliseconds(-(BlockSyncConstants.BlockSyncFetchBlockAgeLimit + 100))); + + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto + { + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = peerBlock.Height, + BatchRequestBlockCount = 5 + }); + + block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + } + + [Fact] + public async Task SyncByAnnounce_LessThenFetchLimit_FetchReturnFalse() + { + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto + { + SyncBlockHash = Hash.Empty, + SyncBlockHeight = 12, + BatchRequestBlockCount = 5 + }); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + } + + [Fact] + public async Task SyncByAnnounce_MoreThenFetchLimit_Success() + { + var chain = await _blockchainService.GetChainAsync(); - [Fact] - public async Task SyncByAnnounce_Download_AttachAndExecuteQueueIsBusy() + var peerBlockHash = HashHelper.ComputeFrom("PeerBlock"); + var peerBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset + 1; + + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, - TimestampHelper.GetUtcNow() + SyncBlockHash = peerBlockHash, + SyncBlockHeight = peerBlockHeight, + BatchRequestBlockCount = 5 + }); + + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.TargetBlockHeight.ShouldBe(peerBlockHeight); + jobInfo.TargetBlockHash.ShouldBe(peerBlockHash); + } + + [Fact] + public async Task SyncByAnnounce_Fetch_AttachAndExecuteQueueIsBusy() + { + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, + TimestampHelper.GetUtcNow() .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100))); - - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset +1 , - BatchRequestBlockCount = 5 - }); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - } - - [Fact] - public async Task SyncByAnnounce_Fetch_AttachQueueIsBusy() + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var chain = await _blockchainService.GetChainAsync(); + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, + BatchRequestBlockCount = 5 + }); - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); + } - var chain = await _blockchainService.GetChainAsync(); - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, - BatchRequestBlockCount = 5 - }); + [Fact] + public async Task SyncByAnnounce_Download_AttachAndExecuteQueueIsBusy() + { + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, + TimestampHelper.GetUtcNow() + .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100))); - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); - } - - [Fact] - public async Task SyncByAnnounce_Download_AttachQueueIsBusy() + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset + 1, + BatchRequestBlockCount = 5 + }); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + } - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; + [Fact] + public async Task SyncByAnnounce_Fetch_AttachQueueIsBusy() + { + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset +1, - BatchRequestBlockCount = 5 - }); + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - } - - [Fact] - public async Task SyncByAnnounce_RetryByNextSender() + var chain = await _blockchainService.GetChainAsync(); + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto + { + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, + BatchRequestBlockCount = 5 + }); + + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); + } + + [Fact] + public async Task SyncByAnnounce_Download_AttachQueueIsBusy() + { + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); + + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); - - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset + 1, + BatchRequestBlockCount = 5 + }); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + } - _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(peerBlock.GetHash(), peerBlock.Height, - "NextPeerPubkey"); + [Fact] + public async Task SyncByAnnounce_RetryByNextSender() + { + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); - var chain = await _blockchainService.GetChainAsync(); - await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto - { - SyncBlockHash = peerBlock.GetHash(), - SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, - BatchRequestBlockCount = 5 - }); + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; - _announcementCacheProvider.TryGetAnnouncementNextSender(peerBlock.GetHash(), out var nextPeerPubkey); - nextPeerPubkey.ShouldBeNull(); - } + _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(peerBlock.GetHash(), peerBlock.Height, + "NextPeerPubkey"); - [Fact] - public async Task SyncByBlock_Success() + var chain = await _blockchainService.GetChainAsync(); + await _blockSyncService.SyncByAnnouncementAsync(chain, new SyncAnnouncementDto { - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; + SyncBlockHash = peerBlock.GetHash(), + SyncBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset, + BatchRequestBlockCount = 5 + }); - var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.ShouldBeNull(); + _announcementCacheProvider.TryGetAnnouncementNextSender(peerBlock.GetHash(), out var nextPeerPubkey); + nextPeerPubkey.ShouldBeNull(); + } - var chain = await _blockchainService.GetChainAsync(); - await _blockSyncService.SyncByBlockAsync(chain, new SyncBlockDto - { - BlockWithTransactions = peerBlock, - BatchRequestBlockCount = 5 - }); + [Fact] + public async Task SyncByBlock_Success() + { + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; - block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); - block.GetHash().ShouldBe(peerBlock.GetHash()); + var block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.ShouldBeNull(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(peerBlock.GetHash()); - chain.BestChainHeight.ShouldBe(peerBlock.Height); - } - - [Fact] - public async Task SyncByBlock_MoreThenFetchLimit_Success() + var chain = await _blockchainService.GetChainAsync(); + await _blockSyncService.SyncByBlockAsync(chain, new SyncBlockDto { - var chain = await _blockchainService.GetChainAsync(); + BlockWithTransactions = peerBlock, + BatchRequestBlockCount = 5 + }); - var peerBlockHash = HashHelper.ComputeFrom("PeerBlock"); - var peerBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset +1; + block = await _blockchainService.GetBlockByHashAsync(peerBlock.GetHash()); + block.GetHash().ShouldBe(peerBlock.GetHash()); - var block = _osTestHelper.GenerateBlockWithTransactions(peerBlockHash, peerBlockHeight); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(peerBlock.GetHash()); + chain.BestChainHeight.ShouldBe(peerBlock.Height); + } - await _blockSyncService.SyncByBlockAsync(chain, - new SyncBlockDto - { - BlockWithTransactions = block, BatchRequestBlockCount = 10, - SuggestedPeerPubkey = "SuggestedPeerPubkey" - }); + [Fact] + public async Task SyncByBlock_MoreThenFetchLimit_Success() + { + var chain = await _blockchainService.GetChainAsync(); - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.TargetBlockHeight.ShouldBe(block.Height); - jobInfo.TargetBlockHash.ShouldBe(block.GetHash()); - } + var peerBlockHash = HashHelper.ComputeFrom("PeerBlock"); + var peerBlockHeight = chain.LongestChainHeight + BlockSyncConstants.BlockSyncModeHeightOffset + 1; + + var block = _osTestHelper.GenerateBlockWithTransactions(peerBlockHash, peerBlockHeight); + + await _blockSyncService.SyncByBlockAsync(chain, + new SyncBlockDto + { + BlockWithTransactions = block, BatchRequestBlockCount = 10, + SuggestedPeerPubkey = "SuggestedPeerPubkey" + }); + + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.TargetBlockHeight.ShouldBe(block.Height); + jobInfo.TargetBlockHash.ShouldBe(block.GetHash()); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceInvalidBlockTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceInvalidBlockTests.cs index 9ffff13c60..930f597252 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceInvalidBlockTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceInvalidBlockTests.cs @@ -2,25 +2,24 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncValidationServiceInvalidBlockTests : BlockSyncAttachBlockAbnormalPeerTestBase { - public class BlockSyncValidationServiceInvalidBlockTests : BlockSyncAttachBlockAbnormalPeerTestBase - { - private readonly IBlockSyncValidationService _blockSyncValidationService; - private readonly OSTestHelper _osTestHelper; + private readonly IBlockSyncValidationService _blockSyncValidationService; + private readonly OSTestHelper _osTestHelper; - public BlockSyncValidationServiceInvalidBlockTests() - { - _blockSyncValidationService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - } + public BlockSyncValidationServiceInvalidBlockTests() + { + _blockSyncValidationService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + } - [Fact] - public async Task ValidateBlockBeforeAttach_InvalidBlock_ReturnFalse() - { - var invalidBlock = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), 10000); - var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(invalidBlock); - result.ShouldBeFalse(); - } + [Fact] + public async Task ValidateBlockBeforeAttach_InvalidBlock_ReturnFalse() + { + var invalidBlock = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), 10000); + var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(invalidBlock); + result.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceTests.cs b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceTests.cs index 0e2e09007c..7ddba066ab 100644 --- a/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Application/BlockSyncValidationServiceTests.cs @@ -1,176 +1,172 @@ -using System; using System.Threading.Tasks; using AElf.Cryptography; -using AElf.Kernel; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; -using AElf.OS.BlockSync.Infrastructure; using AElf.OS.Network; -using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Application +namespace AElf.OS.BlockSync.Application; + +public class BlockSyncValidationServiceTests : BlockSyncTestBase { - public class BlockSyncValidationServiceTests : BlockSyncTestBase + private readonly IAccountService _accountService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockSyncValidationService _blockSyncValidationService; + private readonly OSTestHelper _osTestHelper; + + public BlockSyncValidationServiceTests() { - private readonly IBlockSyncValidationService _blockSyncValidationService; - private readonly IBlockchainService _blockchainService; - private readonly IAccountService _accountService; - private readonly OSTestHelper _osTestHelper; + _blockSyncValidationService = GetRequiredService(); + _blockchainService = GetRequiredService(); + _accountService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + } - public BlockSyncValidationServiceTests() - { - _blockSyncValidationService = GetRequiredService(); - _blockchainService = GetRequiredService(); - _accountService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - } - - [Fact] - public async Task ValidateAnnouncement_Success() + [Fact] + public async Task ValidateAnnouncement_Success() + { + var chain = await _blockchainService.GetChainAsync(); + + var blockAnnouncement = new BlockAnnouncement { - var chain = await _blockchainService.GetChainAsync(); + BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), + BlockHeight = chain.LastIrreversibleBlockHeight + 1 + }; - var blockAnnouncement = new BlockAnnouncement - { - BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), - BlockHeight = chain.LastIrreversibleBlockHeight + 1 - }; + var validateResult = + await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, + GetEncodedPubKeyString()); - var validateResult = - await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, - GetEncodedPubKeyString()); + validateResult.ShouldBeTrue(); + } - validateResult.ShouldBeTrue(); - } + [Fact] + public async Task ValidateAnnouncement_AlreadySynchronized() + { + var chain = await _blockchainService.GetChainAsync(); - [Fact] - public async Task ValidateAnnouncement_AlreadySynchronized() + var blockAnnouncement = new BlockAnnouncement { - var chain = await _blockchainService.GetChainAsync(); - - var blockAnnouncement = new BlockAnnouncement - { - BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), - BlockHeight = chain.LastIrreversibleBlockHeight + 1 - }; - - var validateResult = - await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, - GetEncodedPubKeyString()); - validateResult.ShouldBeTrue(); - - validateResult = - await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, - GetEncodedPubKeyString()); - validateResult.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateAnnouncement_LessThenLIBHeight() + BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), + BlockHeight = chain.LastIrreversibleBlockHeight + 1 + }; + + var validateResult = + await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, + GetEncodedPubKeyString()); + validateResult.ShouldBeTrue(); + + validateResult = + await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, + GetEncodedPubKeyString()); + validateResult.ShouldBeFalse(); + } + + [Fact] + public async Task ValidateAnnouncement_LessThenLIBHeight() + { + var chain = await _blockchainService.GetChainAsync(); + + var blockAnnouncement = new BlockAnnouncement { - var chain = await _blockchainService.GetChainAsync(); + BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), + BlockHeight = chain.LastIrreversibleBlockHeight + }; - var blockAnnouncement = new BlockAnnouncement - { - BlockHash = HashHelper.ComputeFrom("SyncBlockHash"), - BlockHeight = chain.LastIrreversibleBlockHeight - }; + var validateResult = + await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, + GetEncodedPubKeyString()); - var validateResult = - await _blockSyncValidationService.ValidateAnnouncementBeforeSyncAsync(chain, blockAnnouncement, - GetEncodedPubKeyString()); + validateResult.ShouldBeFalse(); + } - validateResult.ShouldBeFalse(); - } + [Fact] + public async Task ValidateBlock_Success() + { + var chain = await _blockchainService.GetChainAsync(); - [Fact] - public async Task ValidateBlock_Success() - { - var chain = await _blockchainService.GetChainAsync(); + var block = _osTestHelper.GenerateBlockWithTransactions(chain.LastIrreversibleBlockHash, + chain.LastIrreversibleBlockHeight); + var pubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); - var block = _osTestHelper.GenerateBlockWithTransactions(chain.LastIrreversibleBlockHash, - chain.LastIrreversibleBlockHeight); - var pubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); + var validateResult = await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, pubkey); - var validateResult = await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, pubkey); + validateResult.ShouldBeTrue(); + } - validateResult.ShouldBeTrue(); - } - - [Fact] - public async Task ValidateBlock_LessThenLIBHeight() - { - var chain = await _blockchainService.GetChainAsync(); + [Fact] + public async Task ValidateBlock_LessThenLIBHeight() + { + var chain = await _blockchainService.GetChainAsync(); - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("SyncBlockHash"), - chain.LastIrreversibleBlockHeight - 1); - var pubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("SyncBlockHash"), + chain.LastIrreversibleBlockHeight - 1); + var pubkey = (await _accountService.GetPublicKeyAsync()).ToHex(); - var validateResult = await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, pubkey); + var validateResult = await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, pubkey); - validateResult.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateBlock_IncorrectSender() - { - var chain = await _blockchainService.GetChainAsync(); + validateResult.ShouldBeFalse(); + } - var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("SyncBlockHash"), - chain.LastIrreversibleBlockHeight + 1); + [Fact] + public async Task ValidateBlock_IncorrectSender() + { + var chain = await _blockchainService.GetChainAsync(); - var validateResult = await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, GetEncodedPubKeyString()); + var block = _osTestHelper.GenerateBlockWithTransactions(HashHelper.ComputeFrom("SyncBlockHash"), + chain.LastIrreversibleBlockHeight + 1); - validateResult.ShouldBeFalse(); - } + var validateResult = + await _blockSyncValidationService.ValidateBlockBeforeSyncAsync(chain, block, GetEncodedPubKeyString()); - [Fact] - public async Task ValidateBlockBeforeAttach_Success() - { - var chain = await _blockchainService.GetChainAsync(); - var transactions = await _osTestHelper.GenerateTransferTransactions(3); - var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, - transactions); + validateResult.ShouldBeFalse(); + } - var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); - result.ShouldBeTrue(); - } + [Fact] + public async Task ValidateBlockBeforeAttach_Success() + { + var chain = await _blockchainService.GetChainAsync(); + var transactions = await _osTestHelper.GenerateTransferTransactions(3); + var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, + transactions); - [Fact] - public async Task ValidateBlockBeforeAttach_InvalidTransaction_ReturnFalse() - { - var chain = await _blockchainService.GetChainAsync(); - var transaction = await _osTestHelper.GenerateTransferTransaction(); - transaction.Signature = ByteString.Empty; - var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, - new []{transaction}); - - var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); - result.ShouldBeFalse(); - } - - [Fact] - public async Task ValidateBlockBeforeAttach_ExpiredTransaction_ReturnFalse() - { - var chain = await _blockchainService.GetChainAsync(); - var transaction = await _osTestHelper.GenerateTransferTransaction(); - transaction.RefBlockNumber = chain.BestChainHeight + 1; - var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, - new []{transaction}); - - var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); - result.ShouldBeFalse(); - } - - private string GetEncodedPubKeyString() - { - var pk = CryptoHelper.GenerateKeyPair().PublicKey; - var address = Address.FromPublicKey(pk); - return address.ToBase58(); - } + var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); + result.ShouldBeTrue(); + } + + [Fact] + public async Task ValidateBlockBeforeAttach_InvalidTransaction_ReturnFalse() + { + var chain = await _blockchainService.GetChainAsync(); + var transaction = await _osTestHelper.GenerateTransferTransaction(); + transaction.Signature = ByteString.Empty; + var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, + new[] { transaction }); + + var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); + result.ShouldBeFalse(); + } + + [Fact] + public async Task ValidateBlockBeforeAttach_ExpiredTransaction_ReturnFalse() + { + var chain = await _blockchainService.GetChainAsync(); + var transaction = await _osTestHelper.GenerateTransferTransaction(); + transaction.RefBlockNumber = chain.BestChainHeight + 1; + var block = _osTestHelper.GenerateBlockWithTransactions(chain.BestChainHash, chain.BestChainHeight, + new[] { transaction }); + + var result = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(block); + result.ShouldBeFalse(); + } + + private string GetEncodedPubKeyString() + { + var pk = CryptoHelper.GenerateKeyPair().PublicKey; + var address = Address.FromPublicKey(pk); + return address.ToBase58(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockDownloadWorkerTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockDownloadWorkerTestAElfModule.cs index df0ef7e4eb..3e44f362d9 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockDownloadWorkerTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockDownloadWorkerTestAElfModule.cs @@ -1,18 +1,17 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestAElfModule))] +public class BlockDownloadWorkerTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestAElfModule))] - public class BlockDownloadWorkerTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + Configure(o => { - Configure(o => - { - o.MaxBlockDownloadCount = 3; - o.MaxBatchRequestBlockCount = 3; - }); - } + o.MaxBlockDownloadCount = 3; + o.MaxBatchRequestBlockCount = 3; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncAbnormalPeerTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncAbnormalPeerTestAElfModule.cs index 9ea3cfb540..d36de27ec5 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncAbnormalPeerTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncAbnormalPeerTestAElfModule.cs @@ -10,107 +10,102 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestBaseAElfModule))] +public class BlockSyncAbnormalPeerTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestBaseAElfModule))] - public class BlockSyncAbnormalPeerTestAElfModule : AElfModule + private readonly Dictionary _peers = new(); + + public override void ConfigureServices(ServiceConfigurationContext context) { - private readonly Dictionary _peers = new Dictionary(); + _peers.Add("AbnormalPeerPubkey", new PeerInfo()); + _peers.Add("NotLinkedBlockPubkey", new PeerInfo()); + _peers.Add("WrongLIBPubkey", new PeerInfo + { + Pubkey = "WrongLIBPubkey", + SyncState = SyncState.Finished, + LastKnownLibHeight = 110 + }); - public override void ConfigureServices(ServiceConfigurationContext context) + for (var i = 0; i < 15; i++) { - _peers.Add("AbnormalPeerPubkey", new PeerInfo()); - _peers.Add("NotLinkedBlockPubkey", new PeerInfo()); - _peers.Add("WrongLIBPubkey", new PeerInfo + var pubkey = "GoodPeerPubkey" + i; + _peers.Add(pubkey, new PeerInfo { - Pubkey = "WrongLIBPubkey", + Pubkey = pubkey, SyncState = SyncState.Finished, - LastKnownLibHeight = 110 + LastKnownLibHeight = 150 + i }); + } - for (int i = 0; i < 15; i++) - { - var pubkey = "GoodPeerPubkey" + i; - _peers.Add(pubkey, new PeerInfo + var osTestHelper = context.Services.GetServiceLazy(); + + context.Services.AddSingleton(o => + { + var networkServiceMock = new Mock(); + networkServiceMock + .Setup(p => p.GetBlockByHashAsync(It.IsAny(), It.IsAny())) + .Returns((hash, peerPubkey) => { - Pubkey = pubkey, - SyncState = SyncState.Finished, - LastKnownLibHeight = 150 + i - }); - } + BlockWithTransactions result = null; + if (peerPubkey == "AbnormalPeerPubkey") + result = osTestHelper.Value.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), + 1000); - var osTestHelper = context.Services.GetServiceLazy(); - - context.Services.AddSingleton(o => - { - var networkServiceMock = new Mock(); - networkServiceMock - .Setup(p => p.GetBlockByHashAsync(It.IsAny(), It.IsAny())) - .Returns((hash, peerPubkey) => - { - BlockWithTransactions result = null; - if (peerPubkey == "AbnormalPeerPubkey") - { - result = osTestHelper.Value.GenerateBlockWithTransactions(HashHelper.ComputeFrom("BadBlock"), - 1000); - } + return Task.FromResult(new Response(result)); + }); - return Task.FromResult(new Response(result)); - }); + networkServiceMock + .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((previousBlockHash, count, peerPubKey) => + { + var result = new List(); + var hash = previousBlockHash; - networkServiceMock - .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((previousBlockHash, count, peerPubKey) => + if (peerPubKey == "NotLinkedBlockPubkey") { - var result = new List(); - var hash = previousBlockHash; - - if (peerPubKey == "NotLinkedBlockPubkey") + for (var i = 0; i < count - 1; i++) { - for (var i = 0; i < count-1; i++) - { - var block = osTestHelper.Value.GenerateBlockWithTransactions(hash, 100 + i); - hash = block.Header.PreviousBlockHash; - - result.Add(block); - } - - var notLinkedBlock = - osTestHelper.Value.GenerateBlockWithTransactions(HashHelper.ComputeFrom("NotLinkedBlock"), - 100); - result.Add(notLinkedBlock); + var block = osTestHelper.Value.GenerateBlockWithTransactions(hash, 100 + i); + hash = block.Header.PreviousBlockHash; + + result.Add(block); } - if (hash == HashHelper.ComputeFrom("GoodBlockHash")) + var notLinkedBlock = + osTestHelper.Value.GenerateBlockWithTransactions(HashHelper.ComputeFrom("NotLinkedBlock"), + 100); + result.Add(notLinkedBlock); + } + + if (hash == HashHelper.ComputeFrom("GoodBlockHash")) + for (var i = 0; i < count; i++) { - for (var i = 0; i < count; i++) - { - var block = osTestHelper.Value.GenerateBlockWithTransactions(hash, 100 + i); - hash = block.Header.PreviousBlockHash; + var block = osTestHelper.Value.GenerateBlockWithTransactions(hash, 100 + i); + hash = block.Header.PreviousBlockHash; - result.Add(block); - } + result.Add(block); } - return Task.FromResult(new Response>(result)); - }); + return Task.FromResult(new Response>(result)); + }); - networkServiceMock.Setup(p => p.RemovePeerByPubkeyAsync(It.IsAny(), It.IsAny())) - .Returns( - (peerPubkey,removalSeconds) => - { - _peers.Remove(peerPubkey); - return Task.FromResult(true); - }); + networkServiceMock.Setup(p => p.RemovePeerByPubkeyAsync(It.IsAny(), It.IsAny())) + .Returns( + (peerPubkey, removalSeconds) => + { + _peers.Remove(peerPubkey); + return Task.FromResult(true); + }); - networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) - .Returns((peerPubKey) => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); + networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) + .Returns(peerPubKey => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); - networkServiceMock.Setup(p => p.GetPeers(It.IsAny())).Returns(_peers.Values.ToList()); + networkServiceMock.Setup(p => p.GetPeers(It.IsAny())).Returns(_peers.Values.ToList()); - return networkServiceMock.Object; - }); - } + return networkServiceMock.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncAttachBlockAbnormalPeerTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncAttachBlockAbnormalPeerTestAElfModule.cs index 8dc9d5851b..03656f3c18 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncAttachBlockAbnormalPeerTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncAttachBlockAbnormalPeerTestAElfModule.cs @@ -5,61 +5,57 @@ using AElf.Modularity; using AElf.OS.Network.Application; using AElf.OS.Network.Types; -using AElf.Types; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestBaseAElfModule))] +public class BlockSyncAttachBlockAbnormalPeerTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestBaseAElfModule))] - public class BlockSyncAttachBlockAbnormalPeerTestAElfModule : AElfModule + private readonly Dictionary _peers = new(); + + public override void ConfigureServices(ServiceConfigurationContext context) { - private readonly Dictionary _peers = new Dictionary(); + _peers.Add("AbnormalPeerPubkey", new PeerInfo()); - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(o => { - _peers.Add("AbnormalPeerPubkey", new PeerInfo()); - - context.Services.AddSingleton(o => - { - var networkServiceMock = new Mock(); - - networkServiceMock.Setup(p => p.RemovePeerByPubkeyAsync(It.IsAny(),It.IsAny())) - .Returns( - (peerPubkey, removalSeconds) => - { - _peers.Remove(peerPubkey); - return Task.FromResult(true); - }); - - networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) - .Returns((peerPubKey) => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); - - return networkServiceMock.Object; - }); - - context.Services.AddTransient(o => - { - var blockValidationServiceMock = new Mock(); + var networkServiceMock = new Mock(); - blockValidationServiceMock.Setup(p => p.ValidateBlockBeforeAttachAsync(It.IsAny())) - .Returns(block => + networkServiceMock.Setup(p => p.RemovePeerByPubkeyAsync(It.IsAny(), It.IsAny())) + .Returns( + (peerPubkey, removalSeconds) => { - if (block.Header.PreviousBlockHash.Equals(HashHelper.ComputeFrom("BadBlock"))) - { - return Task.FromResult(false); - } - + _peers.Remove(peerPubkey); return Task.FromResult(true); }); - blockValidationServiceMock.Setup(s => - s.ValidateBlockBeforeExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); - blockValidationServiceMock.Setup(s => - s.ValidateBlockAfterExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); - return blockValidationServiceMock.Object; - }); - } + networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) + .Returns(peerPubKey => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); + + return networkServiceMock.Object; + }); + + context.Services.AddTransient(o => + { + var blockValidationServiceMock = new Mock(); + + blockValidationServiceMock.Setup(p => p.ValidateBlockBeforeAttachAsync(It.IsAny())) + .Returns(block => + { + if (block.Header.PreviousBlockHash.Equals(HashHelper.ComputeFrom("BadBlock"))) + return Task.FromResult(false); + + return Task.FromResult(true); + }); + blockValidationServiceMock.Setup(s => + s.ValidateBlockBeforeExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); + blockValidationServiceMock.Setup(s => + s.ValidateBlockAfterExecuteAsync(It.IsAny())).Returns(Task.FromResult(true)); + + return blockValidationServiceMock.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncForkedTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncForkedTestAElfModule.cs index 70c4fe3a00..589af9f66d 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncForkedTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncForkedTestAElfModule.cs @@ -3,7 +3,6 @@ using System.Threading; using System.Threading.Tasks; using AElf.Kernel; -using AElf.Kernel.Blockchain.Application; using AElf.Kernel.SmartContractExecution.Application; using AElf.Modularity; using AElf.OS.Network; @@ -16,71 +15,68 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestBaseAElfModule))] +public class BlockSyncForkedTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestBaseAElfModule))] - public class BlockSyncForkedTestAElfModule : AElfModule - { - private readonly Dictionary _peerBlockList = new Dictionary(); + private readonly Dictionary _peerBlockList = new(); - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(o => { - context.Services.AddSingleton(o => - { - var networkServiceMock = new Mock(); - networkServiceMock - .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((previousBlockHash, count, peerPubKey) => - { - var result = new List(); + var networkServiceMock = new Mock(); + networkServiceMock + .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((previousBlockHash, count, peerPubKey) => + { + var result = new List(); - var hash = previousBlockHash; + var hash = previousBlockHash; - while (result.Count < count && _peerBlockList.TryGetValue(hash, out var block)) - { - result.Add(new BlockWithTransactions {Header = block.Header}); + while (result.Count < count && _peerBlockList.TryGetValue(hash, out var block)) + { + result.Add(new BlockWithTransactions { Header = block.Header }); - hash = block.GetHash(); - } + hash = block.GetHash(); + } - return Task.FromResult(new Response>(result)); - }); + return Task.FromResult(new Response>(result)); + }); - networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())).Returns(new PeerInfo()); + networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())).Returns(new PeerInfo()); - return networkServiceMock.Object; - }); - } + return networkServiceMock.Object; + }); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var exec = context.ServiceProvider.GetRequiredService(); - var osTestHelper = context.ServiceProvider.GetService(); + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var exec = context.ServiceProvider.GetRequiredService(); + var osTestHelper = context.ServiceProvider.GetService(); - var previousBlockHash = osTestHelper.ForkBranchBlockList.Last().GetHash(); - var height = osTestHelper.ForkBranchBlockList.Last().Height; + var previousBlockHash = osTestHelper.ForkBranchBlockList.Last().GetHash(); + var height = osTestHelper.ForkBranchBlockList.Last().Height; - foreach (var block in osTestHelper.ForkBranchBlockList) - { - _peerBlockList.Add(block.Header.PreviousBlockHash, block); - } + foreach (var block in osTestHelper.ForkBranchBlockList) + _peerBlockList.Add(block.Header.PreviousBlockHash, block); - var forkBranchHeight = height; + var forkBranchHeight = height; - for (var i = forkBranchHeight; i < forkBranchHeight + 20; i++) - { - var block = osTestHelper.GenerateBlock(previousBlockHash, height); + for (var i = forkBranchHeight; i < forkBranchHeight + 20; i++) + { + var block = osTestHelper.GenerateBlock(previousBlockHash, height); - // no choice need to execute the block to finalize it. - var newBlock = AsyncHelper.RunSync(() => exec.ExecuteBlockAsync(block.Header, new List(), - new List(), CancellationToken.None)).Block; + // no choice need to execute the block to finalize it. + var newBlock = AsyncHelper.RunSync(() => exec.ExecuteBlockAsync(block.Header, new List(), + new List(), CancellationToken.None)).Block; - previousBlockHash = newBlock.GetHash(); - height++; + previousBlockHash = newBlock.GetHash(); + height++; - _peerBlockList.Add(newBlock.Header.PreviousBlockHash, newBlock); - } + _peerBlockList.Add(newBlock.Header.PreviousBlockHash, newBlock); } } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncRetryTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncRetryTestAElfModule.cs index c62d80cbcc..06e5d57d9f 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncRetryTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncRetryTestAElfModule.cs @@ -10,52 +10,51 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestBaseAElfModule))] +public class BlockSyncRetryTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestBaseAElfModule))] - public class BlockSyncRetryTestAElfModule : AElfModule - { - private readonly Dictionary _peers = new Dictionary(); + private readonly Dictionary _peers = new(); - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) + { + for (var i = 0; i < 15; i++) { - for (int i = 0; i < 15; i++) - { - var pubkey = "PeerPubkey" + i; - _peers.Add(pubkey, new PeerInfo - { - Pubkey = pubkey, - SyncState = SyncState.Finished, - LastKnownLibHeight = 150 + i - }); - } - - var testContext = new BlockSyncRetryTestContext(); - context.Services.AddSingleton(testContext); - - context.Services.AddSingleton(o => + var pubkey = "PeerPubkey" + i; + _peers.Add(pubkey, new PeerInfo { - var networkServiceMock = new Mock(); + Pubkey = pubkey, + SyncState = SyncState.Finished, + LastKnownLibHeight = 150 + i + }); + } - networkServiceMock - .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((previousBlockHash, count, peerPubKey) => - Task.FromResult(new Response>())); + var testContext = new BlockSyncRetryTestContext(); + context.Services.AddSingleton(testContext); - networkServiceMock.Setup(p => p.GetPeers(It.IsAny())).Returns(_peers.Values.ToList()); + context.Services.AddSingleton(o => + { + var networkServiceMock = new Mock(); - networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) - .Returns((peerPubKey) => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); - - testContext.MockedNetworkService = networkServiceMock; - return networkServiceMock.Object; - }); - } - } - - public class BlockSyncRetryTestContext - { - public Mock MockedNetworkService { get; set; } + networkServiceMock + .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((previousBlockHash, count, peerPubKey) => + Task.FromResult(new Response>())); + + networkServiceMock.Setup(p => p.GetPeers(It.IsAny())).Returns(_peers.Values.ToList()); + + networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())) + .Returns(peerPubKey => _peers.ContainsKey(peerPubKey) ? _peers[peerPubKey] : null); + + testContext.MockedNetworkService = networkServiceMock; + return networkServiceMock.Object; + }); } +} + +public class BlockSyncRetryTestContext +{ + public Mock MockedNetworkService { get; set; } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncTestAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncTestAElfModule.cs index 2e085967cc..b9aead1d99 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncTestAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncTestAElfModule.cs @@ -17,106 +17,100 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(BlockSyncTestBaseAElfModule))] +public class BlockSyncTestAElfModule : AElfModule { - [DependsOn(typeof(BlockSyncTestBaseAElfModule))] - public class BlockSyncTestAElfModule : AElfModule - { - private readonly Dictionary _peerBlockList = new Dictionary(); + private readonly Dictionary _peerBlockList = new(); - public override void ConfigureServices(ServiceConfigurationContext context) + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(o => { - context.Services.AddSingleton(o => - { - var networkServiceMock = new Mock(); - networkServiceMock - .Setup(p => p.GetBlockByHashAsync(It.IsAny(), It.IsAny())) - .Returns((hash, peer) => + var networkServiceMock = new Mock(); + networkServiceMock + .Setup(p => p.GetBlockByHashAsync(It.IsAny(), It.IsAny())) + .Returns((hash, peer) => + { + BlockWithTransactions result = null; + if (hash != Hash.Empty) { - BlockWithTransactions result = null; - if (hash != Hash.Empty) - { - var blockchainService = context.Services.GetServiceLazy().Value; - var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); - result = new BlockWithTransactions {Header = _peerBlockList[chain.BestChainHash].Header}; - } - - return Task.FromResult(new Response(result)); - }); - - networkServiceMock - .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), - It.IsAny())) - .Returns((previousBlockHash, count, peerPubkey) => - { - var result = new List(); + var blockchainService = context.Services.GetServiceLazy().Value; + var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); + result = new BlockWithTransactions { Header = _peerBlockList[chain.BestChainHash].Header }; + } - if (peerPubkey == "AbnormalPeer") - throw new Exception("Get blocks failed."); - - if (peerPubkey == "NetworkException") - return Task.FromResult(new Response>()); + return Task.FromResult(new Response(result)); + }); - var hash = previousBlockHash; + networkServiceMock + .Setup(p => p.GetBlocksAsync(It.IsAny(), It.IsAny(), + It.IsAny())) + .Returns((previousBlockHash, count, peerPubkey) => + { + var result = new List(); - while (result.Count < count && _peerBlockList.TryGetValue(hash, out var block)) - { - result.Add(new BlockWithTransactions {Header = block.Header}); + if (peerPubkey == "AbnormalPeer") + throw new Exception("Get blocks failed."); - hash = block.GetHash(); - } + if (peerPubkey == "NetworkException") + return Task.FromResult(new Response>()); - return Task.FromResult(new Response>(result)); - }); + var hash = previousBlockHash; - networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())).Returns( - (peerPubkey) => + while (result.Count < count && _peerBlockList.TryGetValue(hash, out var block)) { - if (peerPubkey == "RemovedPeer") - { - return null; - } + result.Add(new BlockWithTransactions { Header = block.Header }); - return new PeerInfo(); - }); + hash = block.GetHash(); + } - return networkServiceMock.Object; - }); + return Task.FromResult(new Response>(result)); + }); - context.Services.AddSingleton(); - } + networkServiceMock.Setup(p => p.GetPeerByPubkey(It.IsAny())).Returns( + peerPubkey => + { + if (peerPubkey == "RemovedPeer") return null; - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var blockchainService = context.ServiceProvider.GetRequiredService(); - var exec = context.ServiceProvider.GetRequiredService(); - var osTestHelper = context.ServiceProvider.GetService(); + return new PeerInfo(); + }); - var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); - var previousBlockHash = chain.BestChainHash; - var height = chain.BestChainHeight; + return networkServiceMock.Object; + }); - foreach (var block in osTestHelper.BestBranchBlockList) - { - _peerBlockList.Add(block.Header.PreviousBlockHash, block); - } + context.Services.AddSingleton(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var blockchainService = context.ServiceProvider.GetRequiredService(); + var exec = context.ServiceProvider.GetRequiredService(); + var osTestHelper = context.ServiceProvider.GetService(); - var bestBranchHeight = height; + var chain = AsyncHelper.RunSync(() => blockchainService.GetChainAsync()); + var previousBlockHash = chain.BestChainHash; + var height = chain.BestChainHeight; - for (var i = bestBranchHeight; i < bestBranchHeight + 20; i++) - { - var block = osTestHelper.GenerateBlock(previousBlockHash, height); + foreach (var block in osTestHelper.BestBranchBlockList) + _peerBlockList.Add(block.Header.PreviousBlockHash, block); + + var bestBranchHeight = height; + + for (var i = bestBranchHeight; i < bestBranchHeight + 20; i++) + { + var block = osTestHelper.GenerateBlock(previousBlockHash, height); - // no choice need to execute the block to finalize it. - var newBlock = AsyncHelper.RunSync(() => exec.ExecuteBlockAsync(block.Header, new List(), - new List(), CancellationToken.None)) - .Block; + // no choice need to execute the block to finalize it. + var newBlock = AsyncHelper.RunSync(() => exec.ExecuteBlockAsync(block.Header, new List(), + new List(), CancellationToken.None)) + .Block; - previousBlockHash = newBlock.GetHash(); - height++; + previousBlockHash = newBlock.GetHash(); + height++; - _peerBlockList.Add(newBlock.Header.PreviousBlockHash, newBlock); - } + _peerBlockList.Add(newBlock.Header.PreviousBlockHash, newBlock); } } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/BlockSyncTestBaseAElfModule.cs b/test/AElf.OS.Tests/BlockSync/BlockSyncTestBaseAElfModule.cs index 341e84f496..d70cfaa61e 100644 --- a/test/AElf.OS.Tests/BlockSync/BlockSyncTestBaseAElfModule.cs +++ b/test/AElf.OS.Tests/BlockSync/BlockSyncTestBaseAElfModule.cs @@ -6,25 +6,22 @@ using Volo.Abp.BackgroundWorkers; using Volo.Abp.Modularity; -namespace AElf.OS.BlockSync +namespace AElf.OS.BlockSync; + +[DependsOn(typeof(OSTestAElfModule))] +public class BlockSyncTestBaseAElfModule : AElfModule { - [DependsOn(typeof(OSTestAElfModule))] - public class BlockSyncTestBaseAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddTransient(o => { - context.Services.AddTransient(o => - { - var taskQueue = new Mock(); - taskQueue.Setup(t => t.Enqueue(It.IsAny>())).Callback>(async task => - { - await task(); - }); + var taskQueue = new Mock(); + taskQueue.Setup(t => t.Enqueue(It.IsAny>())) + .Callback>(async task => { await task(); }); + + return taskQueue.Object; + }); - return taskQueue.Object; - }); - - Configure(o => { o.IsEnabled = false; }); - } + Configure(o => { o.IsEnabled = false; }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Domain/BlockDownloadJobManagerTests.cs b/test/AElf.OS.Tests/BlockSync/Domain/BlockDownloadJobManagerTests.cs index 5d025965fe..327dad4f7d 100644 --- a/test/AElf.OS.Tests/BlockSync/Domain/BlockDownloadJobManagerTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Domain/BlockDownloadJobManagerTests.cs @@ -3,49 +3,48 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Domain +namespace AElf.OS.BlockSync.Domain; + +public class BlockDownloadJobManagerTests : BlockSyncTestBase { - public class BlockDownloadJobManagerTests : BlockSyncTestBase + private readonly IBlockDownloadJobManager _blockDownloadJobManager; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + + public BlockDownloadJobManagerTests() { - private readonly IBlockDownloadJobManager _blockDownloadJobManager; - private readonly IBlockDownloadJobStore _blockDownloadJobStore; + _blockDownloadJobManager = GetRequiredService(); + _blockDownloadJobStore = GetRequiredService(); + } - public BlockDownloadJobManagerTests() - { - _blockDownloadJobManager = GetRequiredService(); - _blockDownloadJobStore = GetRequiredService(); - } + [Fact] + public async Task Enqueue_Test() + { + var syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash"); + var syncBlockHeight = 100; + var batchRequestBlockCount = 10; + var suggestedPeerPubkey = "SuggestedPeerPubkey"; - [Fact] - public async Task Enqueue_Test() - { - var syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash"); - var syncBlockHeight = 100; - var batchRequestBlockCount = 10; - var suggestedPeerPubkey = "SuggestedPeerPubkey"; + var jobId = await _blockDownloadJobManager.EnqueueAsync(syncBlockHash, syncBlockHeight, + batchRequestBlockCount, suggestedPeerPubkey); + jobId.ShouldNotBeNull(); - var jobId = await _blockDownloadJobManager.EnqueueAsync(syncBlockHash, syncBlockHeight, - batchRequestBlockCount, suggestedPeerPubkey); - jobId.ShouldNotBeNull(); + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.TargetBlockHash.ShouldBe(syncBlockHash); + jobInfo.TargetBlockHeight.ShouldBe(syncBlockHeight); + jobInfo.BatchRequestBlockCount.ShouldBe(batchRequestBlockCount); + jobInfo.SuggestedPeerPubkey.ShouldBe(suggestedPeerPubkey); - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.TargetBlockHash.ShouldBe(syncBlockHash); - jobInfo.TargetBlockHeight.ShouldBe(syncBlockHeight); - jobInfo.BatchRequestBlockCount.ShouldBe(batchRequestBlockCount); - jobInfo.SuggestedPeerPubkey.ShouldBe(suggestedPeerPubkey); - - for (int i = 0; i < 99; i++) - { - syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash" + i); - jobId = await _blockDownloadJobManager.EnqueueAsync(syncBlockHash, syncBlockHeight, - batchRequestBlockCount, suggestedPeerPubkey); - jobId.ShouldNotBeNull(); - } - - syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash100" ); + for (var i = 0; i < 99; i++) + { + syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash" + i); jobId = await _blockDownloadJobManager.EnqueueAsync(syncBlockHash, syncBlockHeight, batchRequestBlockCount, suggestedPeerPubkey); - jobId.ShouldBeNull(); + jobId.ShouldNotBeNull(); } + + syncBlockHash = HashHelper.ComputeFrom("SyncBlockHash100"); + jobId = await _blockDownloadJobManager.EnqueueAsync(syncBlockHash, syncBlockHeight, + batchRequestBlockCount, suggestedPeerPubkey); + jobId.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Infrastructure/AnnouncementCacheProviderTests.cs b/test/AElf.OS.Tests/BlockSync/Infrastructure/AnnouncementCacheProviderTests.cs index 1f773e3751..b42a04503c 100644 --- a/test/AElf.OS.Tests/BlockSync/Infrastructure/AnnouncementCacheProviderTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Infrastructure/AnnouncementCacheProviderTests.cs @@ -1,78 +1,77 @@ -using System; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class AnnouncementCacheProviderTests : BlockSyncTestBase { - public class AnnouncementCacheProviderTests : BlockSyncTestBase + private readonly IAnnouncementCacheProvider _announcementCacheProvider; + + public AnnouncementCacheProviderTests() { - private readonly IAnnouncementCacheProvider _announcementCacheProvider; - - public AnnouncementCacheProviderTests() - { - _announcementCacheProvider = GetRequiredService(); - } - - [Fact] - public void AnnouncementCache_Test() + _announcementCacheProvider = GetRequiredService(); + } + + [Fact] + public void AnnouncementCache_Test() + { + var blockHash = HashHelper.ComputeFrom("BlockHash"); + var blockHeight = 0; + var pubkey = "Pubkey"; + var addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, pubkey); + addResult.ShouldBeTrue(); + + var getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out var senderPubKey); + getResult.ShouldBeTrue(); + senderPubKey.ShouldBe(pubkey); + + getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out senderPubKey); + getResult.ShouldBeFalse(); + senderPubKey.ShouldBeNull(); + + for (var i = 0; i < 101; i++) { - var blockHash = HashHelper.ComputeFrom("BlockHash"); - var blockHeight = 0; - var pubkey = "Pubkey"; - var addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, pubkey); + var hash = HashHelper.ComputeFrom("BlockHash" + i); + addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(hash, blockHeight, pubkey); addResult.ShouldBeTrue(); - - var getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out var senderPubKey); - getResult.ShouldBeTrue(); - senderPubKey.ShouldBe(pubkey); - - getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out senderPubKey); - getResult.ShouldBeFalse(); - senderPubKey.ShouldBeNull(); - - for (var i = 0; i < 101; i++) - { - var hash = HashHelper.ComputeFrom("BlockHash" + i); - addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(hash, blockHeight, pubkey); - addResult.ShouldBeTrue(); - } - - getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(HashHelper.ComputeFrom("BlockHash" + 0), out senderPubKey); - getResult.ShouldBeFalse(); - senderPubKey.ShouldBeNull(); } - [Fact] - public void AnnouncementCache_SameBlockHash_Test() + getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(HashHelper.ComputeFrom("BlockHash" + 0), + out senderPubKey); + getResult.ShouldBeFalse(); + senderPubKey.ShouldBeNull(); + } + + [Fact] + public void AnnouncementCache_SameBlockHash_Test() + { + var blockHash = HashHelper.ComputeFrom("Hash"); + var blockHeight = 10; + var pubkey = "Pubkey"; + + var addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, pubkey); + addResult.ShouldBeTrue(); + + for (var i = 0; i < 10; i++) { - var blockHash = HashHelper.ComputeFrom("Hash"); - var blockHeight = 10; - var pubkey = "Pubkey"; + addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, + pubkey + i); + addResult.ShouldBeFalse(); + } - var addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, pubkey); - addResult.ShouldBeTrue(); - - for (int i = 0; i < 10; i++) - { - addResult = _announcementCacheProvider.TryAddOrUpdateAnnouncementCache(blockHash, blockHeight, - pubkey + i); - addResult.ShouldBeFalse(); - } - - var getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out var senderPubKey); - getResult.ShouldBeTrue(); - senderPubKey.ShouldBe(pubkey); - - for (int i = 0; i < 10; i++) - { - getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out senderPubKey); - getResult.ShouldBeTrue(); - senderPubKey.ShouldBe(pubkey + i); - } - + var getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out var senderPubKey); + getResult.ShouldBeTrue(); + senderPubKey.ShouldBe(pubkey); + + for (var i = 0; i < 10; i++) + { getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out senderPubKey); - getResult.ShouldBeFalse(); - senderPubKey.ShouldBeNull(); + getResult.ShouldBeTrue(); + senderPubKey.ShouldBe(pubkey + i); } + + getResult = _announcementCacheProvider.TryGetAnnouncementNextSender(blockHash, out senderPubKey); + getResult.ShouldBeFalse(); + senderPubKey.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Infrastructure/BlockSyncStateProviderTests.cs b/test/AElf.OS.Tests/BlockSync/Infrastructure/BlockSyncStateProviderTests.cs index 8603656082..87837a56fc 100644 --- a/test/AElf.OS.Tests/BlockSync/Infrastructure/BlockSyncStateProviderTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Infrastructure/BlockSyncStateProviderTests.cs @@ -2,53 +2,52 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class BlockSyncStateProviderTests : BlockSyncTestBase { - public class BlockSyncStateProviderTests : BlockSyncTestBase + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + + public BlockSyncStateProviderTests() + { + _blockSyncStateProvider = GetRequiredService(); + } + + [Fact] + public void EnqueueTime_Test() { - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - - public BlockSyncStateProviderTests() - { - _blockSyncStateProvider = GetRequiredService(); - } - - [Fact] - public void EnqueueTime_Test() - { - var testQueueName = "TestQueue"; - var testEnqueueTime = TimestampHelper.GetUtcNow(); - - var enqueueTime = _blockSyncStateProvider.GetEnqueueTime(testQueueName); - enqueueTime.ShouldBeNull(); - - _blockSyncStateProvider.SetEnqueueTime(testQueueName, testEnqueueTime); - - enqueueTime = _blockSyncStateProvider.GetEnqueueTime(testQueueName); - enqueueTime.ShouldBe(testEnqueueTime); - } - - [Fact] - public void DownloadJobTargetState_Test() - { - var targetHash = HashHelper.ComputeFrom("TargetHash"); - var result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false); - result.ShouldBeFalse(); - - _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, false); - result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out var value); - result.ShouldBeTrue(); - value.ShouldBeFalse(); - - result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false); - result.ShouldBeFalse(); - - result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, true); - result.ShouldBeTrue(); - - _blockSyncStateProvider.TryRemoveDownloadJobTargetState(targetHash); - result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out value); - result.ShouldBeFalse(); - } + var testQueueName = "TestQueue"; + var testEnqueueTime = TimestampHelper.GetUtcNow(); + + var enqueueTime = _blockSyncStateProvider.GetEnqueueTime(testQueueName); + enqueueTime.ShouldBeNull(); + + _blockSyncStateProvider.SetEnqueueTime(testQueueName, testEnqueueTime); + + enqueueTime = _blockSyncStateProvider.GetEnqueueTime(testQueueName); + enqueueTime.ShouldBe(testEnqueueTime); + } + + [Fact] + public void DownloadJobTargetState_Test() + { + var targetHash = HashHelper.ComputeFrom("TargetHash"); + var result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false); + result.ShouldBeFalse(); + + _blockSyncStateProvider.SetDownloadJobTargetState(targetHash, false); + result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out var value); + result.ShouldBeTrue(); + value.ShouldBeFalse(); + + result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, false); + result.ShouldBeFalse(); + + result = _blockSyncStateProvider.TryUpdateDownloadJobTargetState(targetHash, true); + result.ShouldBeTrue(); + + _blockSyncStateProvider.TryRemoveDownloadJobTargetState(targetHash); + result = _blockSyncStateProvider.TryGetDownloadJobTargetState(targetHash, out value); + result.ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Infrastructure/InMemoryBlockDownloadJobStoreTests.cs b/test/AElf.OS.Tests/BlockSync/Infrastructure/InMemoryBlockDownloadJobStoreTests.cs index b400e6ca23..f1cfcbfb39 100644 --- a/test/AElf.OS.Tests/BlockSync/Infrastructure/InMemoryBlockDownloadJobStoreTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Infrastructure/InMemoryBlockDownloadJobStoreTests.cs @@ -4,89 +4,88 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Infrastructure +namespace AElf.OS.BlockSync.Infrastructure; + +public class InMemoryBlockDownloadJobStoreTests : BlockSyncTestBase { - public class InMemoryBlockDownloadJobStoreTests : BlockSyncTestBase + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + + public InMemoryBlockDownloadJobStoreTests() { - private readonly IBlockDownloadJobStore _blockDownloadJobStore; + _blockDownloadJobStore = GetRequiredService(); + } - public InMemoryBlockDownloadJobStoreTests() + [Fact] + public async Task Add_Test() + { + for (var i = 0; i < 100; i++) { - _blockDownloadJobStore = GetRequiredService(); - } + var job = CreateBlockDownloadJob(i.ToString()); - [Fact] - public async Task Add_Test() - { - for (int i = 0; i < 100; i++) - { - var job = CreateBlockDownloadJob(i.ToString()); - - var addResult = await _blockDownloadJobStore.AddAsync(job); - addResult.ShouldBeTrue(); - } - - var moreThanLimitResult = await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("10")); - moreThanLimitResult.ShouldBeFalse(); + var addResult = await _blockDownloadJobStore.AddAsync(job); + addResult.ShouldBeTrue(); } - [Fact] - public async Task GetFirstWaitingJob_Test() - { - var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - job.ShouldBeNull(); - - await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); - await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("2")); - await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("3")); - - job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - job.JobId.ShouldBe("1"); - } + var moreThanLimitResult = await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("10")); + moreThanLimitResult.ShouldBeFalse(); + } - [Fact] - public async Task Update_Test() - { - var currentTargetBlockHash = HashHelper.ComputeFrom("CurrentTargetBlockHash"); - var currentTargetBlockHeight = 10; - var deadline = TimestampHelper.GetUtcNow(); - - await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); - - var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - job.CurrentTargetBlockHash = currentTargetBlockHash; - job.CurrentTargetBlockHeight = currentTargetBlockHeight; - job.IsFinished = true; - job.Deadline = deadline; - - await _blockDownloadJobStore.UpdateAsync(job); - - job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - job.CurrentTargetBlockHash.ShouldBe(currentTargetBlockHash); - job.CurrentTargetBlockHeight.ShouldBe(currentTargetBlockHeight); - job.IsFinished.ShouldBeTrue(); - job.Deadline.ShouldBe(deadline); - } + [Fact] + public async Task GetFirstWaitingJob_Test() + { + var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + job.ShouldBeNull(); - [Fact] - public async Task Remove_Test() - { - await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); - await _blockDownloadJobStore.RemoveAsync("1"); - var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - job.ShouldBeNull(); - } + await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); + await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("2")); + await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("3")); - private BlockDownloadJobInfo CreateBlockDownloadJob(string jobId) + job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + job.JobId.ShouldBe("1"); + } + + [Fact] + public async Task Update_Test() + { + var currentTargetBlockHash = HashHelper.ComputeFrom("CurrentTargetBlockHash"); + var currentTargetBlockHeight = 10; + var deadline = TimestampHelper.GetUtcNow(); + + await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); + + var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + job.CurrentTargetBlockHash = currentTargetBlockHash; + job.CurrentTargetBlockHeight = currentTargetBlockHeight; + job.IsFinished = true; + job.Deadline = deadline; + + await _blockDownloadJobStore.UpdateAsync(job); + + job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + job.CurrentTargetBlockHash.ShouldBe(currentTargetBlockHash); + job.CurrentTargetBlockHeight.ShouldBe(currentTargetBlockHeight); + job.IsFinished.ShouldBeTrue(); + job.Deadline.ShouldBe(deadline); + } + + [Fact] + public async Task Remove_Test() + { + await _blockDownloadJobStore.AddAsync(CreateBlockDownloadJob("1")); + await _blockDownloadJobStore.RemoveAsync("1"); + var job = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + job.ShouldBeNull(); + } + + private BlockDownloadJobInfo CreateBlockDownloadJob(string jobId) + { + return new BlockDownloadJobInfo { - return new BlockDownloadJobInfo - { - JobId = jobId, - BatchRequestBlockCount = 10, - TargetBlockHash = HashHelper.ComputeFrom("TargetBlockHash"), - TargetBlockHeight = 100, - SuggestedPeerPubkey = "SuggestedPeerPubkey" - }; - } + JobId = jobId, + BatchRequestBlockCount = 10, + TargetBlockHash = HashHelper.ComputeFrom("TargetBlockHash"), + TargetBlockHeight = 100, + SuggestedPeerPubkey = "SuggestedPeerPubkey" + }; } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerForkedTests.cs b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerForkedTests.cs index 9c943de28a..94bdc6dca5 100644 --- a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerForkedTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerForkedTests.cs @@ -8,76 +8,75 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Worker +namespace AElf.OS.BlockSync.Worker; + +public class BlockDownloadWorkerForkedTests : BlockSyncForkedTestBase { - public class BlockDownloadWorkerForkedTests : BlockSyncForkedTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadJobManager _blockDownloadJobManager; + private readonly BlockDownloadWorker _blockDownloadWorker; + private readonly INetworkService _networkService; + + public BlockDownloadWorkerForkedTests() { - private readonly BlockDownloadWorker _blockDownloadWorker; - private readonly IBlockDownloadJobManager _blockDownloadJobManager; - private readonly IBlockchainService _blockchainService; - private readonly INetworkService _networkService; + _blockDownloadWorker = GetRequiredService(); + _blockDownloadJobManager = GetRequiredService(); + _blockchainService = GetRequiredService(); + _networkService = GetRequiredService(); + } - public BlockDownloadWorkerForkedTests() - { - _blockDownloadWorker = GetRequiredService(); - _blockDownloadJobManager = GetRequiredService(); - _blockchainService = GetRequiredService(); - _networkService = GetRequiredService(); - } + [Fact] + public async Task ProcessDownloadJob_Success() + { + var chain = await _blockchainService.GetChainAsync(); + var originalBestChainHash = chain.BestChainHash; + var originalBestChainHeight = chain.BestChainHeight; + var response = await _networkService.GetBlocksAsync(chain.LastIrreversibleBlockHash, 30); + var peerBlocks = response.Payload; - [Fact] - public async Task ProcessDownloadJob_Success() - { - var chain = await _blockchainService.GetChainAsync(); - var originalBestChainHash = chain.BestChainHash; - var originalBestChainHeight = chain.BestChainHeight; - var response = await _networkService.GetBlocksAsync(chain.LastIrreversibleBlockHash, 30, null); - var peerBlocks = response.Payload; - - var peerBlock = peerBlocks.Last(); + var peerBlock = peerBlocks.Last(); - await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, 5, null); + await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, 5, null); - await _blockDownloadWorker.ProcessDownloadJobAsync(); + await _blockDownloadWorker.ProcessDownloadJobAsync(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(30); - chain.BestChainHash.ShouldBe(peerBlock.GetHash()); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(30); + chain.BestChainHash.ShouldBe(peerBlock.GetHash()); - var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(originalBestChainHeight); - block.GetHash().ShouldNotBe(originalBestChainHash); - } - - [Fact] - public async Task ProcessDownloadJob_SyncFromLongestChain_Success() - { - var chain = await _blockchainService.GetChainAsync(); - var originalBestChainHash = chain.BestChainHash; - var originalBestChainHeight = chain.BestChainHeight; - var response = await _networkService.GetBlocksAsync(chain.LastIrreversibleBlockHash, 30, null); - var peerBlocks = response.Payload; + var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(originalBestChainHeight); + block.GetHash().ShouldNotBe(originalBestChainHash); + } - foreach (var peerBlockWithTransaction in peerBlocks) - { - chain = await _blockchainService.GetChainAsync(); - var peerBlock = peerBlockWithTransaction.ToBlock(); - await _blockchainService.AddBlockAsync(peerBlock); - var result = await _blockchainService.AttachBlockToChainAsync(chain, peerBlock); - if (result == BlockAttachOperationStatus.LongestChainFound) - break; - } + [Fact] + public async Task ProcessDownloadJob_SyncFromLongestChain_Success() + { + var chain = await _blockchainService.GetChainAsync(); + var originalBestChainHash = chain.BestChainHash; + var originalBestChainHeight = chain.BestChainHeight; + var response = await _networkService.GetBlocksAsync(chain.LastIrreversibleBlockHash, 30); + var peerBlocks = response.Payload; - var lastPeerBlock = peerBlocks.Last(); - await _blockDownloadJobManager.EnqueueAsync(lastPeerBlock.GetHash(), lastPeerBlock.Height, 5, null); + foreach (var peerBlockWithTransaction in peerBlocks) + { + chain = await _blockchainService.GetChainAsync(); + var peerBlock = peerBlockWithTransaction.ToBlock(); + await _blockchainService.AddBlockAsync(peerBlock); + var result = await _blockchainService.AttachBlockToChainAsync(chain, peerBlock); + if (result == BlockAttachOperationStatus.LongestChainFound) + break; + } - await _blockDownloadWorker.ProcessDownloadJobAsync(); + var lastPeerBlock = peerBlocks.Last(); + await _blockDownloadJobManager.EnqueueAsync(lastPeerBlock.GetHash(), lastPeerBlock.Height, 5, null); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(30); - chain.BestChainHash.ShouldBe(lastPeerBlock.GetHash()); + await _blockDownloadWorker.ProcessDownloadJobAsync(); - var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(originalBestChainHeight); - block.GetHash().ShouldNotBe(originalBestChainHash); - } + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(30); + chain.BestChainHash.ShouldBe(lastPeerBlock.GetHash()); + + var block = await _blockchainService.GetBlockByHeightInBestChainBranchAsync(originalBestChainHeight); + block.GetHash().ShouldNotBe(originalBestChainHash); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerManyJobTests.cs b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerManyJobTests.cs index 0e3f970046..bd6a31a6f0 100644 --- a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerManyJobTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerManyJobTests.cs @@ -9,102 +9,96 @@ using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Worker +namespace AElf.OS.BlockSync.Worker; + +public class BlockDownloadWorkerManyJobTests : BlockSyncManyJobsTestBase { - public class BlockDownloadWorkerManyJobTests : BlockSyncManyJobsTestBase - { - private readonly BlockDownloadWorker _blockDownloadWorker; - private readonly IBlockDownloadJobStore _blockDownloadJobStore; - private readonly IBlockDownloadJobManager _blockDownloadJobManager; - private readonly IBlockchainService _blockchainService; - private readonly INetworkService _networkService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - private readonly BlockSyncOptions _blockSyncOptions; + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadJobManager _blockDownloadJobManager; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + private readonly BlockDownloadWorker _blockDownloadWorker; + private readonly BlockSyncOptions _blockSyncOptions; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly INetworkService _networkService; - public BlockDownloadWorkerManyJobTests() - { - _blockDownloadWorker = GetRequiredService(); - _blockDownloadJobStore = GetRequiredService(); - _blockDownloadJobManager = GetRequiredService(); - _blockchainService = GetRequiredService(); - _networkService = GetRequiredService(); - _blockSyncStateProvider = GetRequiredService(); - _blockSyncOptions = GetRequiredService>().Value; - } + public BlockDownloadWorkerManyJobTests() + { + _blockDownloadWorker = GetRequiredService(); + _blockDownloadJobStore = GetRequiredService(); + _blockDownloadJobManager = GetRequiredService(); + _blockchainService = GetRequiredService(); + _networkService = GetRequiredService(); + _blockSyncStateProvider = GetRequiredService(); + _blockSyncOptions = GetRequiredService>().Value; + } - [Fact] - public async Task ProcessDownloadJob_ManyJob() - { - var chain = await _blockchainService.GetChainAsync(); - var response = await _networkService.GetBlocksAsync(chain.BestChainHash, 30, null); - var peerBlocks = response.Payload; + [Fact] + public async Task ProcessDownloadJob_ManyJob() + { + var chain = await _blockchainService.GetChainAsync(); + var response = await _networkService.GetBlocksAsync(chain.BestChainHash, 30); + var peerBlocks = response.Payload; - // Enqueue download job, from height 25 to 31 - for (int i = 13; i < 19; i++) - { - await _blockDownloadJobManager.EnqueueAsync(peerBlocks[i].GetHash(), peerBlocks[i].Height, - _blockSyncOptions.MaxBatchRequestBlockCount, null); - } + // Enqueue download job, from height 25 to 31 + for (var i = 13; i < 19; i++) + await _blockDownloadJobManager.EnqueueAsync(peerBlocks[i].GetHash(), peerBlocks[i].Height, + _blockSyncOptions.MaxBatchRequestBlockCount, null); - { - // Worker run once - // Execute job(TargetBlockHeight: 25) - // BestChainHeight should be 14 - await RunWorkerAsync(1, peerBlocks); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(peerBlocks[2].Height); - chain.BestChainHash.ShouldBe(peerBlocks[2].GetHash()); + { + // Worker run once + // Execute job(TargetBlockHeight: 25) + // BestChainHeight should be 14 + await RunWorkerAsync(1, peerBlocks); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(peerBlocks[2].Height); + chain.BestChainHash.ShouldBe(peerBlocks[2].GetHash()); - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.TargetBlockHeight.ShouldBe(peerBlocks[13].Height); - jobInfo.TargetBlockHash.ShouldBe(peerBlocks[13].GetHash()); - } + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.TargetBlockHeight.ShouldBe(peerBlocks[13].Height); + jobInfo.TargetBlockHash.ShouldBe(peerBlocks[13].GetHash()); + } - { - // Worker run 6 times - // Execute job(TargetBlockHeight: 25) - // BestChainHeight should be 31 - await RunWorkerAsync(6, peerBlocks); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(peerBlocks[19].Height); - chain.BestChainHash.ShouldBe(peerBlocks[19].GetHash()); + { + // Worker run 6 times + // Execute job(TargetBlockHeight: 25) + // BestChainHeight should be 31 + await RunWorkerAsync(6, peerBlocks); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(peerBlocks[19].Height); + chain.BestChainHash.ShouldBe(peerBlocks[19].GetHash()); - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.TargetBlockHeight.ShouldBe(peerBlocks[13].Height); - jobInfo.TargetBlockHash.ShouldBe(peerBlocks[13].GetHash()); - } + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.TargetBlockHeight.ShouldBe(peerBlocks[13].Height); + jobInfo.TargetBlockHash.ShouldBe(peerBlocks[13].GetHash()); + } - { - // Worker run once - // Execute job(TargetBlockHeight: 25): Just drop the job - // Execute job(TargetBlockHeight: 26): Just drop the job - // Execute job(TargetBlockHeight: 27): Just drop the job - // Execute job(TargetBlockHeight: 28): Just drop the job - // Execute job(TargetBlockHeight: 29): Just drop the job - // Execute job(TargetBlockHeight: 30): Just drop the job - // Execute job(TargetBlockHeight: 31): Just drop the job - // BestChainHeight should be 31 - await RunWorkerAsync(1, peerBlocks); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(peerBlocks[19].Height); - chain.BestChainHash.ShouldBe(peerBlocks[19].GetHash()); + { + // Worker run once + // Execute job(TargetBlockHeight: 25): Just drop the job + // Execute job(TargetBlockHeight: 26): Just drop the job + // Execute job(TargetBlockHeight: 27): Just drop the job + // Execute job(TargetBlockHeight: 28): Just drop the job + // Execute job(TargetBlockHeight: 29): Just drop the job + // Execute job(TargetBlockHeight: 30): Just drop the job + // Execute job(TargetBlockHeight: 31): Just drop the job + // BestChainHeight should be 31 + await RunWorkerAsync(1, peerBlocks); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(peerBlocks[19].Height); + chain.BestChainHash.ShouldBe(peerBlocks[19].GetHash()); - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.ShouldBeNull(); - } + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.ShouldBeNull(); } + } - private async Task RunWorkerAsync(int times, List peerBlocks) + private async Task RunWorkerAsync(int times, List peerBlocks) + { + for (var i = 0; i < times; i++) { - for (int i = 0; i < times; i++) - { - foreach (var block in peerBlocks) - { - _blockSyncStateProvider.TryRemoveDownloadJobTargetState(block.GetHash()); - } + foreach (var block in peerBlocks) _blockSyncStateProvider.TryRemoveDownloadJobTargetState(block.GetHash()); - await _blockDownloadWorker.ProcessDownloadJobAsync(); - } + await _blockDownloadWorker.ProcessDownloadJobAsync(); } } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerTests.cs b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerTests.cs index 38650a02fc..58dcc728cd 100644 --- a/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerTests.cs +++ b/test/AElf.OS.Tests/BlockSync/Worker/BlockDownloadWorkerTests.cs @@ -6,172 +6,168 @@ using AElf.OS.BlockSync.Domain; using AElf.OS.BlockSync.Infrastructure; using AElf.OS.Network.Application; -using AElf.Sdk.CSharp; -using AElf.Types; using Microsoft.Extensions.Options; using Shouldly; using Xunit; -namespace AElf.OS.BlockSync.Worker +namespace AElf.OS.BlockSync.Worker; + +public class BlockDownloadWorkerTests : BlockSyncTestBase { - public class BlockDownloadWorkerTests : BlockSyncTestBase + private readonly IBlockchainService _blockchainService; + private readonly IBlockDownloadJobManager _blockDownloadJobManager; + private readonly IBlockDownloadJobStore _blockDownloadJobStore; + private readonly BlockDownloadWorker _blockDownloadWorker; + private readonly BlockSyncOptions _blockSyncOptions; + private readonly IBlockSyncStateProvider _blockSyncStateProvider; + private readonly INetworkService _networkService; + private readonly OSTestHelper _osTestHelper; + + public BlockDownloadWorkerTests() + { + _blockDownloadWorker = GetRequiredService(); + _blockDownloadJobStore = GetRequiredService(); + _blockDownloadJobManager = GetRequiredService(); + _blockchainService = GetRequiredService(); + _networkService = GetRequiredService(); + _blockSyncStateProvider = GetRequiredService(); + _blockSyncOptions = GetRequiredService>().Value; + _osTestHelper = GetRequiredService(); + } + + [Fact] + public async Task ProcessDownloadJob_Success() + { + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + + var jobId = await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, + _blockSyncOptions.MaxBatchRequestBlockCount, + null); + + await _blockDownloadWorker.ProcessDownloadJobAsync(); + + var chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(31); + + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.JobId.ShouldBe(jobId); + _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out var state).ShouldBeTrue(); + state.ShouldBeFalse(); + + _blockSyncStateProvider.SetDownloadJobTargetState(chain.BestChainHash, true); + + await _blockDownloadWorker.ProcessDownloadJobAsync(); + + jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.ShouldBeNull(); + _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out state).ShouldBeFalse(); + } + + [Fact] + public async Task ProcessDownloadJob_CannotGetBlocks() + { + await _blockDownloadJobManager.EnqueueAsync(HashHelper.ComputeFrom("PeerBlock"), 30, + _blockSyncOptions.MaxBatchRequestBlockCount, + null); + + var block = await _osTestHelper.MinedOneBlock(); + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, block.GetHash()); + + await _blockDownloadWorker.ProcessDownloadJobAsync(); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHeight.ShouldBe(block.Height); + + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.ShouldBeNull(); + } + + [Fact] + public async Task ProcessDownloadJob_ThrowException() + { + await _blockDownloadJobManager.EnqueueAsync(HashHelper.ComputeFrom("PeerBlock"), 30, + _blockSyncOptions.MaxBatchRequestBlockCount, + "AbnormalPeer"); + + _blockDownloadWorker.ProcessDownloadJobAsync().ShouldThrow(); + + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.ShouldBeNull(); + } + + [Fact] + public async Task ProcessDownloadJob_ValidateFailed() + { + var chain = await _blockchainService.GetChainAsync(); + var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock")); + var peerBlock = response.Payload; + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + // no job + await _blockDownloadWorker.ProcessDownloadJobAsync(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + + await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, + _blockSyncOptions.MaxBatchRequestBlockCount, null); + + // attach queue is too busy + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, + TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); + await _blockDownloadWorker.ProcessDownloadJobAsync(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, null); + + // update queue is too busy + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, TimestampHelper.GetUtcNow() + .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100))); + await _blockDownloadWorker.ProcessDownloadJobAsync(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + + // not reached the download target and less then deadline + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.CurrentTargetBlockHash = jobInfo.TargetBlockHash; + jobInfo.CurrentTargetBlockHeight = jobInfo.TargetBlockHeight; + jobInfo.Deadline = TimestampHelper.GetUtcNow().AddSeconds(4); + _blockSyncStateProvider.SetDownloadJobTargetState(jobInfo.TargetBlockHash, false); + + _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, null); + _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, null); + + await _blockDownloadWorker.ProcessDownloadJobAsync(); + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + } + + [Fact] + public async Task ProcessDownloadJob_InvalidJob() { - private readonly BlockDownloadWorker _blockDownloadWorker; - private readonly IBlockDownloadJobStore _blockDownloadJobStore; - private readonly IBlockDownloadJobManager _blockDownloadJobManager; - private readonly IBlockchainService _blockchainService; - private readonly INetworkService _networkService; - private readonly IBlockSyncStateProvider _blockSyncStateProvider; - private readonly BlockSyncOptions _blockSyncOptions; - private readonly OSTestHelper _osTestHelper; - - public BlockDownloadWorkerTests() - { - _blockDownloadWorker = GetRequiredService(); - _blockDownloadJobStore = GetRequiredService(); - _blockDownloadJobManager = GetRequiredService(); - _blockchainService = GetRequiredService(); - _networkService = GetRequiredService(); - _blockSyncStateProvider = GetRequiredService(); - _blockSyncOptions = GetRequiredService>().Value; - _osTestHelper = GetRequiredService(); - } - - [Fact] - public async Task ProcessDownloadJob_Success() - { - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - - var jobId = await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, - _blockSyncOptions.MaxBatchRequestBlockCount, - null); - - await _blockDownloadWorker.ProcessDownloadJobAsync(); - - var chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(31); - - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.JobId.ShouldBe(jobId); - _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out var state).ShouldBeTrue(); - state.ShouldBeFalse(); - - _blockSyncStateProvider.SetDownloadJobTargetState(chain.BestChainHash, true); - - await _blockDownloadWorker.ProcessDownloadJobAsync(); - - jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.ShouldBeNull(); - _blockSyncStateProvider.TryGetDownloadJobTargetState(chain.BestChainHash, out state).ShouldBeFalse(); - } - - [Fact] - public async Task ProcessDownloadJob_CannotGetBlocks() - { - await _blockDownloadJobManager.EnqueueAsync(HashHelper.ComputeFrom("PeerBlock"), 30, - _blockSyncOptions.MaxBatchRequestBlockCount, - null); - - var block = await _osTestHelper.MinedOneBlock(); - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, block.Height, block.GetHash()); - - await _blockDownloadWorker.ProcessDownloadJobAsync(); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHeight.ShouldBe(block.Height); - - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.ShouldBeNull(); - } - - [Fact] - public async Task ProcessDownloadJob_ThrowException() - { - await _blockDownloadJobManager.EnqueueAsync(HashHelper.ComputeFrom("PeerBlock"), 30, - _blockSyncOptions.MaxBatchRequestBlockCount, - "AbnormalPeer"); - - _blockDownloadWorker.ProcessDownloadJobAsync().ShouldThrow(); - - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.ShouldBeNull(); - } - - [Fact] - public async Task ProcessDownloadJob_ValidateFailed() - { - var chain = await _blockchainService.GetChainAsync(); - var response = await _networkService.GetBlockByHashAsync(HashHelper.ComputeFrom("PeerBlock"), null); - var peerBlock = response.Payload; - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - // no job - await _blockDownloadWorker.ProcessDownloadJobAsync(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - - await _blockDownloadJobManager.EnqueueAsync(peerBlock.GetHash(), peerBlock.Height, - _blockSyncOptions.MaxBatchRequestBlockCount, null); - - // attach queue is too busy - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, - TimestampHelper.GetUtcNow().AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachBlockAgeLimit + 100))); - await _blockDownloadWorker.ProcessDownloadJobAsync(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, null); - - // update queue is too busy - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, TimestampHelper.GetUtcNow() - .AddMilliseconds(-(BlockSyncConstants.BlockSyncAttachAndExecuteBlockAgeLimit + 100))); - await _blockDownloadWorker.ProcessDownloadJobAsync(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - - // not reached the download target and less then deadline - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.CurrentTargetBlockHash = jobInfo.TargetBlockHash; - jobInfo.CurrentTargetBlockHeight = jobInfo.TargetBlockHeight; - jobInfo.Deadline = TimestampHelper.GetUtcNow().AddSeconds(4); - _blockSyncStateProvider.SetDownloadJobTargetState(jobInfo.TargetBlockHash, false); - - _blockSyncStateProvider.SetEnqueueTime(OSConstants.BlockSyncAttachQueueName, null); - _blockSyncStateProvider.SetEnqueueTime(KernelConstants.UpdateChainQueueName, null); - - await _blockDownloadWorker.ProcessDownloadJobAsync(); - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - } - - [Fact] - public async Task ProcessDownloadJob_InvalidJob() - { - var chain = await _blockchainService.GetChainAsync(); - var bestChainHash = chain.BestChainHash; - var bestChainHeight = chain.BestChainHeight; - - await _blockDownloadJobManager.EnqueueAsync(bestChainHash, bestChainHeight, - _blockSyncOptions.MaxBatchRequestBlockCount, null); - await _blockDownloadJobManager.EnqueueAsync(bestChainHash, bestChainHeight - 1, - _blockSyncOptions.MaxBatchRequestBlockCount, null); - - await _blockDownloadWorker.ProcessDownloadJobAsync(); - - chain = await _blockchainService.GetChainAsync(); - chain.BestChainHash.ShouldBe(bestChainHash); - chain.BestChainHeight.ShouldBe(bestChainHeight); - - var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); - jobInfo.ShouldBeNull(); - } + var chain = await _blockchainService.GetChainAsync(); + var bestChainHash = chain.BestChainHash; + var bestChainHeight = chain.BestChainHeight; + + await _blockDownloadJobManager.EnqueueAsync(bestChainHash, bestChainHeight, + _blockSyncOptions.MaxBatchRequestBlockCount, null); + await _blockDownloadJobManager.EnqueueAsync(bestChainHash, bestChainHeight - 1, + _blockSyncOptions.MaxBatchRequestBlockCount, null); + + await _blockDownloadWorker.ProcessDownloadJobAsync(); + + chain = await _blockchainService.GetChainAsync(); + chain.BestChainHash.ShouldBe(bestChainHash); + chain.BestChainHeight.ShouldBe(bestChainHeight); + var jobInfo = await _blockDownloadJobStore.GetFirstWaitingJobAsync(); + jobInfo.ShouldBeNull(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Handlers/AbnormalPeerEventHandlerTests.cs b/test/AElf.OS.Tests/Handlers/AbnormalPeerEventHandlerTests.cs index 7799695e99..598e06d546 100644 --- a/test/AElf.OS.Tests/Handlers/AbnormalPeerEventHandlerTests.cs +++ b/test/AElf.OS.Tests/Handlers/AbnormalPeerEventHandlerTests.cs @@ -4,33 +4,32 @@ using Shouldly; using Xunit; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class AbnormalPeerEventHandlerTests : AbnormalPeerEventHandlerTestBase { - public class AbnormalPeerEventHandlerTests : AbnormalPeerEventHandlerTestBase + private readonly AbnormalPeerEventHandler _AbnormalPeerEventHandler; + private readonly IBlackListedPeerProvider _blackListedPeerProvider; + + public AbnormalPeerEventHandlerTests() + { + _AbnormalPeerEventHandler = GetRequiredService(); + _blackListedPeerProvider = GetRequiredService(); + } + + [Fact] + public async Task HandleEvent_Test() { - private readonly AbnormalPeerEventHandler _AbnormalPeerEventHandler; - private readonly IBlackListedPeerProvider _blackListedPeerProvider; + var peerHost = "192.168.100.200"; + _blackListedPeerProvider.IsIpBlackListed(peerHost).ShouldBeFalse(); - public AbnormalPeerEventHandlerTests() + await _AbnormalPeerEventHandler.HandleEventAsync(new AbnormalPeerFoundEventData { - _AbnormalPeerEventHandler = GetRequiredService(); - _blackListedPeerProvider = GetRequiredService(); - } + BlockHash = HashHelper.ComputeFrom("Hash"), + BlockHeight = 100, + PeerPubkey = "NormalPeer" + }); - [Fact] - public async Task HandleEvent_Test() - { - var peerHost = "192.168.100.200"; - _blackListedPeerProvider.IsIpBlackListed(peerHost).ShouldBeFalse(); - - await _AbnormalPeerEventHandler.HandleEventAsync(new AbnormalPeerFoundEventData - { - BlockHash = HashHelper.ComputeFrom("Hash"), - BlockHeight = 100, - PeerPubkey = "NormalPeer" - }); - - _blackListedPeerProvider.IsIpBlackListed(peerHost).ShouldBeTrue(); - } + _blackListedPeerProvider.IsIpBlackListed(peerHost).ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Handlers/NetworkInitializedEventHandlerTests.cs b/test/AElf.OS.Tests/Handlers/NetworkInitializedEventHandlerTests.cs index 410d4393c5..d92ecae5a9 100644 --- a/test/AElf.OS.Tests/Handlers/NetworkInitializedEventHandlerTests.cs +++ b/test/AElf.OS.Tests/Handlers/NetworkInitializedEventHandlerTests.cs @@ -4,24 +4,23 @@ using Shouldly; using Xunit; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class NetworkInitializedEventHandlerTests : OSTestBase { - public class NetworkInitializedEventHandlerTests : OSTestBase - { - private readonly NetworkInitializedEventHandler _networkInitializedEventHandler; - private readonly INodeSyncStateProvider _syncStateProvider; + private readonly NetworkInitializedEventHandler _networkInitializedEventHandler; + private readonly INodeSyncStateProvider _syncStateProvider; - public NetworkInitializedEventHandlerTests() - { - _networkInitializedEventHandler = GetRequiredService(); - _syncStateProvider = GetRequiredService(); - } + public NetworkInitializedEventHandlerTests() + { + _networkInitializedEventHandler = GetRequiredService(); + _syncStateProvider = GetRequiredService(); + } - [Fact] - public async Task HandleEvent_Test() - { - await _networkInitializedEventHandler.HandleEventAsync(new NetworkInitializedEvent()); - _syncStateProvider.SyncTarget.ShouldBe(-1); - } + [Fact] + public async Task HandleEvent_Test() + { + await _networkInitializedEventHandler.HandleEventAsync(new NetworkInitializedEvent()); + _syncStateProvider.SyncTarget.ShouldBe(-1); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Handlers/OSHandlerTestAElfModule.cs b/test/AElf.OS.Tests/Handlers/OSHandlerTestAElfModule.cs index 6e43f12992..f4a2e1c91b 100644 --- a/test/AElf.OS.Tests/Handlers/OSHandlerTestAElfModule.cs +++ b/test/AElf.OS.Tests/Handlers/OSHandlerTestAElfModule.cs @@ -2,13 +2,11 @@ using AElf.OS.Network; using Volo.Abp.Modularity; -namespace AElf.OS.Handlers -{ - [DependsOn( - typeof(NetworkServiceTestModule), - typeof(OSTestAElfModule))] - public class AbnormalPeerEventHandlerTestAElfModule : AElfModule - { +namespace AElf.OS.Handlers; - } +[DependsOn( + typeof(NetworkServiceTestModule), + typeof(OSTestAElfModule))] +public class AbnormalPeerEventHandlerTestAElfModule : AElfModule +{ } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Handlers/PeerConnectedEventHandlerTests.cs b/test/AElf.OS.Tests/Handlers/PeerConnectedEventHandlerTests.cs index 8368e6cf18..db5f7ec407 100644 --- a/test/AElf.OS.Tests/Handlers/PeerConnectedEventHandlerTests.cs +++ b/test/AElf.OS.Tests/Handlers/PeerConnectedEventHandlerTests.cs @@ -2,53 +2,51 @@ using AElf.OS.Network; using AElf.OS.Network.Application; using AElf.OS.Network.Events; -using AElf.Types; using Google.Protobuf; using Shouldly; using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.OS.Handlers +namespace AElf.OS.Handlers; + +public class PeerConnectedEventHandlerTests : OSTestBase { - public class PeerConnectedEventHandlerTests : OSTestBase + private readonly ILocalEventBus _eventBus; + private readonly PeerConnectedEventHandler _peerConnectedEventHandler; + private readonly IPeerDiscoveryService _peerDiscoveryService; + + public PeerConnectedEventHandlerTests() { - private readonly PeerConnectedEventHandler _peerConnectedEventHandler; - private readonly ILocalEventBus _eventBus; - private readonly IPeerDiscoveryService _peerDiscoveryService; + _peerConnectedEventHandler = GetRequiredService(); + _eventBus = GetRequiredService(); + _peerDiscoveryService = GetRequiredService(); + } - public PeerConnectedEventHandlerTests() - { - _peerConnectedEventHandler = GetRequiredService(); - _eventBus = GetRequiredService(); - _peerDiscoveryService = GetRequiredService(); - } + [Fact] + public async Task HandleEvent_Test() + { + var eventData = new PeerConnectedEventData + ( + new NodeInfo { Endpoint = "127.0.0.1:1234", Pubkey = ByteString.CopyFromUtf8("Pubkey") }, + HashHelper.ComputeFrom("BestChainHash"), + 100 + ); - [Fact] - public async Task HandleEvent_Test() + AnnouncementReceivedEventData announcementEventData = null; + _eventBus.Subscribe(d => { - var eventData = new PeerConnectedEventData - ( - new NodeInfo{Endpoint = "127.0.0.1:1234",Pubkey = ByteString.CopyFromUtf8("Pubkey")}, - HashHelper.ComputeFrom("BestChainHash"), - 100 - ); - - AnnouncementReceivedEventData announcementEventData = null; - _eventBus.Subscribe(d => - { - announcementEventData = d; - return Task.CompletedTask; - }); - - await _peerConnectedEventHandler.HandleEventAsync(eventData); - - var nodes = await _peerDiscoveryService.GetNodesAsync(1); - nodes.Nodes[0].ShouldBe(eventData.NodeInfo); - - announcementEventData.ShouldNotBeNull(); - announcementEventData.Announce.BlockHash.ShouldBe(eventData.BestChainHash); - announcementEventData.Announce.BlockHeight.ShouldBe(eventData.BestChainHeight); - announcementEventData.SenderPubKey.ShouldBe(eventData.NodeInfo.Pubkey.ToHex()); - } + announcementEventData = d; + return Task.CompletedTask; + }); + + await _peerConnectedEventHandler.HandleEventAsync(eventData); + + var nodes = await _peerDiscoveryService.GetNodesAsync(1); + nodes.Nodes[0].ShouldBe(eventData.NodeInfo); + + announcementEventData.ShouldNotBeNull(); + announcementEventData.Announce.BlockHash.ShouldBe(eventData.BestChainHash); + announcementEventData.Announce.BlockHeight.ShouldBe(eventData.BestChainHeight); + announcementEventData.SenderPubKey.ShouldBe(eventData.NodeInfo.Pubkey.ToHex()); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/OSTestAElfModule.cs b/test/AElf.OS.Tests/OSTestAElfModule.cs index 440e8d2bcd..d02941b202 100644 --- a/test/AElf.OS.Tests/OSTestAElfModule.cs +++ b/test/AElf.OS.Tests/OSTestAElfModule.cs @@ -4,68 +4,67 @@ using AElf.Cryptography.ECDSA; using AElf.Kernel; using AElf.Kernel.Account.Application; -using AElf.Kernel.SmartContract; using AElf.Modularity; using AElf.OS.Account.Infrastructure; using AElf.Types; using Microsoft.Extensions.DependencyInjection; using Moq; -using Org.BouncyCastle.Crypto; using Volo.Abp; using Volo.Abp.BackgroundWorkers; using Volo.Abp.Modularity; -namespace AElf.OS +namespace AElf.OS; + +[DependsOn( + typeof(OSAElfModule), + typeof(OSCoreWithChainTestAElfModule) +)] +// ReSharper disable once InconsistentNaming +public class OSTestAElfModule : AElfModule { - [DependsOn( - typeof(OSAElfModule), - typeof(OSCoreWithChainTestAElfModule) - )] - // ReSharper disable once InconsistentNaming - public class OSTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(o => { o.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); + Configure(o => { o.ChainId = ChainHelper.ConvertBase58ToChainId("AELF"); }); - var ecKeyPair = CryptoHelper.GenerateKeyPair(); - var nodeAccount = Address.FromPublicKey(ecKeyPair.PublicKey).ToBase58(); - var nodeAccountPassword = "123"; + var ecKeyPair = CryptoHelper.GenerateKeyPair(); + var nodeAccount = Address.FromPublicKey(ecKeyPair.PublicKey).ToBase58(); + var nodeAccountPassword = "123"; - Configure(o => - { - o.NodeAccount = nodeAccount; - o.NodeAccountPassword = nodeAccountPassword; - }); + Configure(o => + { + o.NodeAccount = nodeAccount; + o.NodeAccountPassword = nodeAccountPassword; + }); - context.Services.AddSingleton(o => - { - var keyStore = new Mock(); - ECKeyPair keyPair = null; + context.Services.AddSingleton(o => + { + var keyStore = new Mock(); + ECKeyPair keyPair = null; - keyStore.Setup(k => k.GetAccountKeyPair(It.IsAny())).Returns(() => keyPair); - - keyStore.Setup(k => k.GetAccountsAsync()).Returns(Task.FromResult(new List())); - - keyStore.Setup(k => k.CreateAccountKeyPairAsync(It.IsAny())) - .Returns(Task.FromResult(CryptoHelper.FromPrivateKey(ByteArrayHelper.HexStringToByteArray("5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f")))); + keyStore.Setup(k => k.GetAccountKeyPair(It.IsAny())).Returns(() => keyPair); - keyStore.Setup(k => k.UnlockAccountAsync(It.IsAny(), It.IsAny())).Returns(() => - { - keyPair = ecKeyPair; - return Task.FromResult(AccountError.None); - }); + keyStore.Setup(k => k.GetAccountsAsync()).Returns(Task.FromResult(new List())); - return keyStore.Object; + keyStore.Setup(k => k.CreateAccountKeyPairAsync(It.IsAny())) + .Returns(Task.FromResult(CryptoHelper.FromPrivateKey( + ByteArrayHelper.HexStringToByteArray( + "5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f")))); + + keyStore.Setup(k => k.UnlockAccountAsync(It.IsAny(), It.IsAny())).Returns(() => + { + keyPair = ecKeyPair; + return Task.FromResult(AccountError.None); }); - context.Services.AddTransient(); - - Configure(o => { o.IsEnabled = false; }); - } + return keyStore.Object; + }); - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - } + context.Services.AddTransient(); + + Configure(o => { o.IsEnabled = false; }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/OSTestBase.cs b/test/AElf.OS.Tests/OSTestBase.cs index 881588485e..c2c2ca7a1f 100644 --- a/test/AElf.OS.Tests/OSTestBase.cs +++ b/test/AElf.OS.Tests/OSTestBase.cs @@ -4,60 +4,54 @@ using AElf.OS.Worker; using AElf.TestBase; -namespace AElf.OS -{ - // ReSharper disable once InconsistentNaming - public class OSTestBase : AElfIntegratedTest - { - - } - - public class BlockSyncTestBase : AElfIntegratedTest - { - - } - - public class BlockSyncForkedTestBase : AElfIntegratedTest - { - - } - - public class AccountServiceTestBase : AElfIntegratedTest - { - - } - - public class KeyStoreTestBase : AElfIntegratedTest - { - - } - - public class BlockSyncManyJobsTestBase : AElfIntegratedTest - { - - } - - public class BlockSyncAbnormalPeerTestBase : AElfIntegratedTest - { - } - - public class BlockSyncAttachBlockAbnormalPeerTestBase : AElfIntegratedTest - { - } - - public class BlockSyncRetryTestBase : AElfIntegratedTest - { - } - - public class PeerDiscoveryWorkerTestBase : AElfIntegratedTest - { - } - - public class PeerReconnectionTestBase : AElfIntegratedTest - { - } - - public class AbnormalPeerEventHandlerTestBase : AElfIntegratedTest - { - } +namespace AElf.OS; + +// ReSharper disable once InconsistentNaming +public class OSTestBase : AElfIntegratedTest +{ +} + +public class BlockSyncTestBase : AElfIntegratedTest +{ +} + +public class BlockSyncForkedTestBase : AElfIntegratedTest +{ +} + +public class AccountServiceTestBase : AElfIntegratedTest +{ +} + +public class KeyStoreTestBase : AElfIntegratedTest +{ +} + +public class BlockSyncManyJobsTestBase : AElfIntegratedTest +{ +} + +public class BlockSyncAbnormalPeerTestBase : AElfIntegratedTest +{ +} + +public class + BlockSyncAttachBlockAbnormalPeerTestBase : AElfIntegratedTest +{ +} + +public class BlockSyncRetryTestBase : AElfIntegratedTest +{ +} + +public class PeerDiscoveryWorkerTestBase : AElfIntegratedTest +{ +} + +public class PeerReconnectionTestBase : AElfIntegratedTest +{ +} + +public class AbnormalPeerEventHandlerTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTestModule.cs b/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTestModule.cs index 286b251af2..7a464c6c0a 100644 --- a/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTestModule.cs +++ b/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTestModule.cs @@ -9,43 +9,42 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +[DependsOn(typeof(OSTestAElfModule), + typeof(PeerDiscoveryTestModule))] +public class PeerDiscoveryWorkerTestModule : AElfModule { - [DependsOn(typeof(OSTestAElfModule), - typeof(PeerDiscoveryTestModule))] - public class PeerDiscoveryWorkerTestModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var peerPool = context.Services.GetRequiredServiceLazy(); + context.Services.AddSingleton(o => { - var peerPool = context.Services.GetRequiredServiceLazy(); - context.Services.AddSingleton(o => - { - var networkServer = new Mock(); + var networkServer = new Mock(); - networkServer.Setup(s => s.CheckEndpointAvailableAsync(It.IsAny())).Returns( - endpoint => - { - if (endpoint.Port == 8001) - return Task.FromResult(false); + networkServer.Setup(s => s.CheckEndpointAvailableAsync(It.IsAny())).Returns( + endpoint => + { + if (endpoint.Port == 8001) + return Task.FromResult(false); - return Task.FromResult(true); - }); + return Task.FromResult(true); + }); - networkServer.Setup(s => s.ConnectAsync(It.IsAny())).Returns( - endpoint => - { - var peer = new Mock(); - peer.Setup(p => p.IsReady).Returns(true); - peer.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = endpoint.ToString(), ConnectionTime = TimestampHelper.GetUtcNow()}); - peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); + networkServer.Setup(s => s.ConnectAsync(It.IsAny())).Returns( + endpoint => + { + var peer = new Mock(); + peer.Setup(p => p.IsReady).Returns(true); + peer.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = endpoint.ToString(), ConnectionTime = TimestampHelper.GetUtcNow() }); + peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); - peerPool.Value.TryAddPeer(peer.Object); - return Task.FromResult(true); - }); + peerPool.Value.TryAddPeer(peer.Object); + return Task.FromResult(true); + }); - return networkServer.Object; - }); - } + return networkServer.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTests.cs b/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTests.cs index aa326e51ee..4a9d239018 100644 --- a/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTests.cs +++ b/test/AElf.OS.Tests/Worker/PeerDiscoveryWorkerTests.cs @@ -11,125 +11,124 @@ using Shouldly; using Xunit; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +public class PeerDiscoveryWorkerTests : PeerDiscoveryWorkerTestBase { - public class PeerDiscoveryWorkerTests : PeerDiscoveryWorkerTestBase + private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + private readonly IPeerDiscoveryService _peerDiscoveryService; + private readonly PeerDiscoveryWorker _peerDiscoveryWorker; + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public PeerDiscoveryWorkerTests() { - private readonly PeerDiscoveryWorker _peerDiscoveryWorker; - private readonly IPeerPool _peerPool; - private readonly IPeerDiscoveryService _peerDiscoveryService; - private readonly IReconnectionService _reconnectionService; - private readonly IPeerDiscoveryJobProcessor _peerDiscoveryJobProcessor; + _peerDiscoveryWorker = GetRequiredService(); + _peerPool = GetRequiredService(); + _peerDiscoveryService = GetRequiredService(); + _reconnectionService = GetRequiredService(); + _peerDiscoveryJobProcessor = GetRequiredService(); + } - public PeerDiscoveryWorkerTests() - { - _peerDiscoveryWorker = GetRequiredService(); - _peerPool = GetRequiredService(); - _peerDiscoveryService = GetRequiredService(); - _reconnectionService = GetRequiredService(); - _peerDiscoveryJobProcessor = GetRequiredService(); - } - - [Fact] - public async Task ProcessPeerDiscoveryJob_Test() - { - var node1 = new NodeInfo - { - Endpoint = "192.168.100.1:8001", - Pubkey = ByteString.CopyFromUtf8("node1") - }; - await _peerDiscoveryService.AddNodeAsync(node1); - - await RunDiscoveryWorkerAsync(); - - var endpointString = "192.168.100.100:8003"; - var nodeList = await _peerDiscoveryService.GetNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(1); - nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); - nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); - - AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); - var peer = _peerPool.FindPeerByEndpoint(aelEndpoint); - peer.ShouldNotBeNull(); - } - - [Fact] - public async Task ProcessPeerDiscoveryJob_PeerPoolIsFull_Test() - { - var endpoint = new AElfPeerEndpoint("192.168.100.1", 8000); - var peer = new Mock(); - peer.Setup(p => p.IsReady).Returns(true); - peer.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = endpoint.ToString(), ConnectionTime = TimestampHelper.GetUtcNow()}); - peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); - - _peerPool.TryAddPeer(peer.Object); - - await RunDiscoveryWorkerAsync(); - - var endpointString = "192.168.100.100:8003"; - var nodeList = await _peerDiscoveryService.GetNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(1); - nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); - nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); - - AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); - var result = _peerPool.FindPeerByEndpoint(aelEndpoint); - result.ShouldBeNull(); - } - - [Fact] - public async Task ProcessPeerDiscoveryJob_ReconnectingPeer_Test() - { - var endpointString = "192.168.100.100:8003"; - _reconnectionService.SchedulePeerForReconnection(endpointString); - - await RunDiscoveryWorkerAsync(); - - var nodeList = await _peerDiscoveryService.GetNodesAsync(10); - nodeList.Nodes.Count.ShouldBe(1); - nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); - nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); - - AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); - var result = _peerPool.FindPeerByEndpoint(aelEndpoint); - result.ShouldBeNull(); - } - - [Fact] - public async Task ProcessPeerDiscoveryJob_PeerIsInPeerPool_Test() + [Fact] + public async Task ProcessPeerDiscoveryJob_Test() + { + var node1 = new NodeInfo { - var pubkey = ByteString.CopyFromUtf8("SamePubkey"); - - var mockPeer = new Mock(); - mockPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo - {Pubkey = pubkey.ToHex(), ConnectionTime = TimestampHelper.GetUtcNow()}); - mockPeer.Setup(p => p.IsReady).Returns(true); - mockPeer.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.99.99", 8801)); - mockPeer.Setup(m => m.GetNodesAsync(It.IsAny())) - .Returns(Task.FromResult(new NodeList())); - - _peerPool.TryAddPeer(mockPeer.Object); - - var node = new NodeInfo - { - Endpoint = "192.168.99.100:8002", - Pubkey = pubkey - }; - await _peerDiscoveryService.AddNodeAsync(node); - - await RunDiscoveryWorkerAsync(); - - var peer = _peerPool.FindPeerByPublicKey(node.Pubkey.ToHex()); - peer.RemoteEndpoint.Host.ShouldBe("192.168.99.99"); - peer.RemoteEndpoint.Port.ShouldBe(8801); - } - - private async Task RunDiscoveryWorkerAsync() + Endpoint = "192.168.100.1:8001", + Pubkey = ByteString.CopyFromUtf8("node1") + }; + await _peerDiscoveryService.AddNodeAsync(node1); + + await RunDiscoveryWorkerAsync(); + + var endpointString = "192.168.100.100:8003"; + var nodeList = await _peerDiscoveryService.GetNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(1); + nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); + nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); + + AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); + var peer = _peerPool.FindPeerByEndpoint(aelEndpoint); + peer.ShouldNotBeNull(); + } + + [Fact] + public async Task ProcessPeerDiscoveryJob_PeerPoolIsFull_Test() + { + var endpoint = new AElfPeerEndpoint("192.168.100.1", 8000); + var peer = new Mock(); + peer.Setup(p => p.IsReady).Returns(true); + peer.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = endpoint.ToString(), ConnectionTime = TimestampHelper.GetUtcNow() }); + peer.Setup(p => p.RemoteEndpoint).Returns(endpoint); + + _peerPool.TryAddPeer(peer.Object); + + await RunDiscoveryWorkerAsync(); + + var endpointString = "192.168.100.100:8003"; + var nodeList = await _peerDiscoveryService.GetNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(1); + nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); + nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); + + AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); + var result = _peerPool.FindPeerByEndpoint(aelEndpoint); + result.ShouldBeNull(); + } + + [Fact] + public async Task ProcessPeerDiscoveryJob_ReconnectingPeer_Test() + { + var endpointString = "192.168.100.100:8003"; + _reconnectionService.SchedulePeerForReconnection(endpointString); + + await RunDiscoveryWorkerAsync(); + + var nodeList = await _peerDiscoveryService.GetNodesAsync(10); + nodeList.Nodes.Count.ShouldBe(1); + nodeList.Nodes[0].Endpoint.ShouldBe(endpointString); + nodeList.Nodes[0].Pubkey.ShouldBe(ByteString.CopyFromUtf8(endpointString)); + + AElfPeerEndpointHelper.TryParse(endpointString, out var aelEndpoint); + var result = _peerPool.FindPeerByEndpoint(aelEndpoint); + result.ShouldBeNull(); + } + + [Fact] + public async Task ProcessPeerDiscoveryJob_PeerIsInPeerPool_Test() + { + var pubkey = ByteString.CopyFromUtf8("SamePubkey"); + + var mockPeer = new Mock(); + mockPeer.Setup(p => p.Info).Returns(new PeerConnectionInfo + { Pubkey = pubkey.ToHex(), ConnectionTime = TimestampHelper.GetUtcNow() }); + mockPeer.Setup(p => p.IsReady).Returns(true); + mockPeer.Setup(p => p.RemoteEndpoint).Returns(new AElfPeerEndpoint("192.168.99.99", 8801)); + mockPeer.Setup(m => m.GetNodesAsync(It.IsAny())) + .Returns(Task.FromResult(new NodeList())); + + _peerPool.TryAddPeer(mockPeer.Object); + + var node = new NodeInfo { - await _peerDiscoveryWorker.ProcessPeerDiscoveryJobAsync(); - await _peerDiscoveryJobProcessor.CompleteAsync(); - await _peerDiscoveryWorker.ProcessPeerDiscoveryJobAsync(); - } + Endpoint = "192.168.99.100:8002", + Pubkey = pubkey + }; + await _peerDiscoveryService.AddNodeAsync(node); + + await RunDiscoveryWorkerAsync(); + + var peer = _peerPool.FindPeerByPublicKey(node.Pubkey.ToHex()); + peer.RemoteEndpoint.Host.ShouldBe("192.168.99.99"); + peer.RemoteEndpoint.Port.ShouldBe(8801); + } + + private async Task RunDiscoveryWorkerAsync() + { + await _peerDiscoveryWorker.ProcessPeerDiscoveryJobAsync(); + await _peerDiscoveryJobProcessor.CompleteAsync(); + await _peerDiscoveryWorker.ProcessPeerDiscoveryJobAsync(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Worker/PeerReconnectionTestAElfModule.cs b/test/AElf.OS.Tests/Worker/PeerReconnectionTestAElfModule.cs index cd71258c28..4d6005194d 100644 --- a/test/AElf.OS.Tests/Worker/PeerReconnectionTestAElfModule.cs +++ b/test/AElf.OS.Tests/Worker/PeerReconnectionTestAElfModule.cs @@ -1,28 +1,26 @@ using System.Net; using System.Threading.Tasks; using AElf.Modularity; -using AElf.OS.Network.Grpc; using AElf.OS.Network.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Moq; using Volo.Abp.Modularity; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +[DependsOn(typeof(OSTestAElfModule))] +public class PeerReconnectionTestAElfModule : AElfModule { - [DependsOn(typeof(OSTestAElfModule))] - public class PeerReconnectionTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.AddSingleton(o => { - context.Services.AddSingleton(o => - { - var service = new Mock(); + var service = new Mock(); - service.Setup(s => s.ConnectAsync(It.IsAny())) - .Returns(endpoint => Task.FromResult(endpoint.Port == 8001)); + service.Setup(s => s.ConnectAsync(It.IsAny())) + .Returns(endpoint => Task.FromResult(endpoint.Port == 8001)); - return service.Object; - }); - } + return service.Object; + }); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Worker/PeerReconnectionWorkerTests.cs b/test/AElf.OS.Tests/Worker/PeerReconnectionWorkerTests.cs index fd98505797..0694b953c9 100644 --- a/test/AElf.OS.Tests/Worker/PeerReconnectionWorkerTests.cs +++ b/test/AElf.OS.Tests/Worker/PeerReconnectionWorkerTests.cs @@ -11,145 +11,144 @@ using Shouldly; using Xunit; -namespace AElf.OS.Worker +namespace AElf.OS.Worker; + +public class PeerReconnectionWorkerTests : PeerReconnectionTestBase { - public class PeerReconnectionWorkerTests : PeerReconnectionTestBase + private readonly NetworkOptions _networkOptions; + private readonly IPeerPool _peerPool; + private readonly IPeerReconnectionStateProvider _peerReconnectionStateProvider; + private readonly PeerReconnectionWorker _peerReconnectionWorker; + + public PeerReconnectionWorkerTests() { - private readonly PeerReconnectionWorker _peerReconnectionWorker; - private readonly IPeerReconnectionStateProvider _peerReconnectionStateProvider; - private readonly IPeerPool _peerPool; - private readonly NetworkOptions _networkOptions; - - public PeerReconnectionWorkerTests() - { - _peerReconnectionWorker = GetRequiredService(); - _peerReconnectionStateProvider = GetRequiredService(); - _peerPool = GetRequiredService(); - _networkOptions = GetRequiredService>().Value; - } - - [Fact] - public async Task DoReconnectionJob_NoReconnection_Test() - { - var peer1 = CreatePeer("Peer1", "127.0.0.1:8001",true); - _peerPool.TryAddPeer(peer1); - var peer2 = CreatePeer("Peer2", "127.0.0.1:8002",false); - _peerPool.TryAddPeer(peer2); - - await _peerReconnectionWorker.DoReconnectionJobAsync(); - - _peerPool.FindPeerByPublicKey(peer1.Info.Pubkey).ShouldBeNull(); - _peerPool.FindPeerByPublicKey(peer2.Info.Pubkey).ShouldNotBeNull(); - } - - [Fact] - public async Task DoReconnectionJob_InvalidEndpoint_Test() - { - var invalidEndpoint = "127.0.0.1:abc"; - _peerReconnectionStateProvider.AddReconnectingPeer(invalidEndpoint, new ReconnectingPeer - { - Endpoint = invalidEndpoint, - RetryCount = 1, - NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), - DisconnectionTime = TimestampHelper.GetUtcNow() - }); - - await _peerReconnectionWorker.DoReconnectionJobAsync(); - - _peerReconnectionStateProvider.GetReconnectingPeer(invalidEndpoint).ShouldBeNull(); - } - - [Fact] - public async Task DoReconnectionJob_AlreadyInPeerPool_Test() + _peerReconnectionWorker = GetRequiredService(); + _peerReconnectionStateProvider = GetRequiredService(); + _peerPool = GetRequiredService(); + _networkOptions = GetRequiredService>().Value; + } + + [Fact] + public async Task DoReconnectionJob_NoReconnection_Test() + { + var peer1 = CreatePeer("Peer1", "127.0.0.1:8001", true); + _peerPool.TryAddPeer(peer1); + var peer2 = CreatePeer("Peer2", "127.0.0.1:8002"); + _peerPool.TryAddPeer(peer2); + + await _peerReconnectionWorker.DoReconnectionJobAsync(); + + _peerPool.FindPeerByPublicKey(peer1.Info.Pubkey).ShouldBeNull(); + _peerPool.FindPeerByPublicKey(peer2.Info.Pubkey).ShouldNotBeNull(); + } + + [Fact] + public async Task DoReconnectionJob_InvalidEndpoint_Test() + { + var invalidEndpoint = "127.0.0.1:abc"; + _peerReconnectionStateProvider.AddReconnectingPeer(invalidEndpoint, new ReconnectingPeer { - var endpoint = "127.0.0.1:123"; - var peer = CreatePeer("pubkey", endpoint); - _peerPool.TryAddPeer(peer); - - _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer - { - Endpoint = endpoint, - RetryCount = 1, - NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), - DisconnectionTime = TimestampHelper.GetUtcNow() - }); - - await _peerReconnectionWorker.DoReconnectionJobAsync(); - - _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); - } - - [Fact] - public async Task DoReconnectionJob_ReconnectSuccess_Test() + Endpoint = invalidEndpoint, + RetryCount = 1, + NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), + DisconnectionTime = TimestampHelper.GetUtcNow() + }); + + await _peerReconnectionWorker.DoReconnectionJobAsync(); + + _peerReconnectionStateProvider.GetReconnectingPeer(invalidEndpoint).ShouldBeNull(); + } + + [Fact] + public async Task DoReconnectionJob_AlreadyInPeerPool_Test() + { + var endpoint = "127.0.0.1:123"; + var peer = CreatePeer("pubkey", endpoint); + _peerPool.TryAddPeer(peer); + + _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer { - var endpoint = "127.0.0.1:8001"; - - _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer - { - Endpoint = endpoint, - RetryCount = 1, - NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), - DisconnectionTime = TimestampHelper.GetUtcNow() - }); - - await _peerReconnectionWorker.DoReconnectionJobAsync(); - - _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); - } - - [Fact] - public async Task DoReconnectionJob_ReconnectFailed_Test() + Endpoint = endpoint, + RetryCount = 1, + NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), + DisconnectionTime = TimestampHelper.GetUtcNow() + }); + + await _peerReconnectionWorker.DoReconnectionJobAsync(); + + _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); + } + + [Fact] + public async Task DoReconnectionJob_ReconnectSuccess_Test() + { + var endpoint = "127.0.0.1:8001"; + + _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer { - var endpoint = "127.0.0.1:8002"; - - var now = TimestampHelper.GetUtcNow(); - var nextAttemptTime = TimestampHelper.GetUtcNow().AddMinutes(-10); - _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer - { - Endpoint = endpoint, - RetryCount = 1, - NextAttempt = nextAttemptTime, - DisconnectionTime = TimestampHelper.GetUtcNow() - }); - - await _peerReconnectionWorker.DoReconnectionJobAsync(); - - var reconnection = _peerReconnectionStateProvider.GetReconnectingPeer(endpoint); - - var timeExtension = _networkOptions.PeerReconnectionPeriod * (int)Math.Pow(2, reconnection.RetryCount); - reconnection.NextAttempt.ShouldBeGreaterThan(now.AddMilliseconds(timeExtension)); - } - - [Fact] - public async Task DoReconnectionJob_ReconnectFailedAndExceedMaxTime_Test() + Endpoint = endpoint, + RetryCount = 1, + NextAttempt = TimestampHelper.GetUtcNow().AddMinutes(-10), + DisconnectionTime = TimestampHelper.GetUtcNow() + }); + + await _peerReconnectionWorker.DoReconnectionJobAsync(); + + _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); + } + + [Fact] + public async Task DoReconnectionJob_ReconnectFailed_Test() + { + var endpoint = "127.0.0.1:8002"; + + var now = TimestampHelper.GetUtcNow(); + var nextAttemptTime = TimestampHelper.GetUtcNow().AddMinutes(-10); + _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer { - var endpoint = "127.0.0.1:8002"; + Endpoint = endpoint, + RetryCount = 1, + NextAttempt = nextAttemptTime, + DisconnectionTime = TimestampHelper.GetUtcNow() + }); + + await _peerReconnectionWorker.DoReconnectionJobAsync(); + + var reconnection = _peerReconnectionStateProvider.GetReconnectingPeer(endpoint); + + var timeExtension = _networkOptions.PeerReconnectionPeriod * (int)Math.Pow(2, reconnection.RetryCount); + reconnection.NextAttempt.ShouldBeGreaterThan(now.AddMilliseconds(timeExtension)); + } - var nextAttemptTime = TimestampHelper.GetUtcNow().AddMinutes(-10); - _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer - { - Endpoint = endpoint, - RetryCount = 10, - NextAttempt = nextAttemptTime, - DisconnectionTime = TimestampHelper.GetUtcNow().AddDays(-1) - }); + [Fact] + public async Task DoReconnectionJob_ReconnectFailedAndExceedMaxTime_Test() + { + var endpoint = "127.0.0.1:8002"; - await _peerReconnectionWorker.DoReconnectionJobAsync(); + var nextAttemptTime = TimestampHelper.GetUtcNow().AddMinutes(-10); + _peerReconnectionStateProvider.AddReconnectingPeer(endpoint, new ReconnectingPeer + { + Endpoint = endpoint, + RetryCount = 10, + NextAttempt = nextAttemptTime, + DisconnectionTime = TimestampHelper.GetUtcNow().AddDays(-1) + }); - _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); - } + await _peerReconnectionWorker.DoReconnectionJobAsync(); - private IPeer CreatePeer(string pubkey, string endpoint, bool isInvalid = false) + _peerReconnectionStateProvider.GetReconnectingPeer(endpoint).ShouldBeNull(); + } + + private IPeer CreatePeer(string pubkey, string endpoint, bool isInvalid = false) + { + AElfPeerEndpointHelper.TryParse(endpoint, out var aelfEndpoint); + var peer = new Mock(); + peer.Setup(p => p.IsInvalid).Returns(isInvalid); + peer.Setup(p => p.Info).Returns(new PeerConnectionInfo { - AElfPeerEndpointHelper.TryParse(endpoint, out var aelfEndpoint); - var peer = new Mock(); - peer.Setup(p => p.IsInvalid).Returns(isInvalid); - peer.Setup(p => p.Info).Returns(new PeerConnectionInfo - { - Pubkey = pubkey, - }); - peer.Setup(p => p.RemoteEndpoint).Returns(aelfEndpoint); - return peer.Object; - } + Pubkey = pubkey + }); + peer.Setup(p => p.RemoteEndpoint).Returns(aelfEndpoint); + return peer.Object; } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/AElf.Parallel.Tests.csproj b/test/AElf.Parallel.Tests/AElf.Parallel.Tests.csproj index 4535aea526..20107bbfc3 100644 --- a/test/AElf.Parallel.Tests/AElf.Parallel.Tests.csproj +++ b/test/AElf.Parallel.Tests/AElf.Parallel.Tests.csproj @@ -6,17 +6,17 @@ 0436 - - - - - - - + + + + + + + - - + + diff --git a/test/AElf.Parallel.Tests/DeleteDataFromStateDbPostExecutionPlugin.cs b/test/AElf.Parallel.Tests/DeleteDataFromStateDbPostExecutionPlugin.cs index 1374b5f75e..e9cd1c66ab 100644 --- a/test/AElf.Parallel.Tests/DeleteDataFromStateDbPostExecutionPlugin.cs +++ b/test/AElf.Parallel.Tests/DeleteDataFromStateDbPostExecutionPlugin.cs @@ -3,142 +3,165 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicFunctionWithParallel; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Application; using AElf.Types; using Google.Protobuf; using Google.Protobuf.Reflection; using Volo.Abp.DependencyInjection; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +public class DeleteDataFromStateDbPostExecutionPlugin : IPostExecutionPlugin, ISingletonDependency { - public class DeleteDataFromStateDbPostExecutionPlugin : IPostExecutionPlugin, ISingletonDependency + private readonly IHostSmartContractBridgeContextService _contextService; + + public DeleteDataFromStateDbPostExecutionPlugin(IHostSmartContractBridgeContextService contextService) { - private readonly IHostSmartContractBridgeContextService _contextService; + _contextService = contextService; + } - public DeleteDataFromStateDbPostExecutionPlugin(IHostSmartContractBridgeContextService contextService) - { - _contextService = contextService; - } - - public Task> GetPostTransactionsAsync(IReadOnlyList descriptors, ITransactionContext transactionContext) + public Task> GetPostTransactionsAsync(IReadOnlyList descriptors, + ITransactionContext transactionContext) + { + if (!descriptors.Any(service => service.File.Name == "test_basic_function_with_parallel_contract.proto")) + return Task.FromResult(new List().AsEnumerable()); + + if (transactionContext.Transaction.To == ParallelTestHelper.BasicFunctionWithParallelContractAddress && + !transactionContext.Transaction.MethodName.EndsWith("Plugin")) + return Task.FromResult(new List().AsEnumerable()); + + var context = _contextService.Create(); + context.TransactionContext = transactionContext; + + var transactions = new List(); + switch (transactionContext.Transaction.MethodName) { - if (!descriptors.Any(service => service.File.Name == "test_basic_function_with_parallel_contract.proto")) + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromInlineWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueWithPlugin): { - return Task.FromResult(new List().AsEnumerable()); + var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction + { + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput + { + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; } - if (transactionContext.Transaction.To == ParallelTestHelper.BasicFunctionWithParallelContractAddress && - !transactionContext.Transaction.MethodName.EndsWith("Plugin")) + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin): { - return Task.FromResult(new List().AsEnumerable()); + var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction + { + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = input.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; } - var context = _contextService.Create(); - context.TransactionContext = transactionContext; - - var transactions = new List(); - switch (transactionContext.Transaction.MethodName) + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedParallelWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithFailedInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPrePluginAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin): { - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromInlineWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueWithPlugin): + var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; + } - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin): - { - var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction - { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = input.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } - - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedParallelWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithFailedInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPrePluginAndPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin): - { - var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction - { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } - - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePluginAndFailedPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePluginAndFailedPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin): + { + var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailed), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailed), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; } - - return Task.FromResult(transactions.AsEnumerable()); - } + + return Task.FromResult(transactions.AsEnumerable()); } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/DeleteDataFromStateDbPreExecutionAcsPlugin.cs b/test/AElf.Parallel.Tests/DeleteDataFromStateDbPreExecutionAcsPlugin.cs index 7eb9d785a2..f6ce270783 100644 --- a/test/AElf.Parallel.Tests/DeleteDataFromStateDbPreExecutionAcsPlugin.cs +++ b/test/AElf.Parallel.Tests/DeleteDataFromStateDbPreExecutionAcsPlugin.cs @@ -3,147 +3,171 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.TestContract.BasicFunctionWithParallel; -using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Application; using AElf.Types; using Google.Protobuf; using Google.Protobuf.Reflection; using Volo.Abp.DependencyInjection; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +public class DeleteDataFromStateDbPreExecutionPlugin : IPreExecutionPlugin, ISingletonDependency { - public class DeleteDataFromStateDbPreExecutionPlugin : IPreExecutionPlugin, ISingletonDependency + private readonly IHostSmartContractBridgeContextService _contextService; + + public DeleteDataFromStateDbPreExecutionPlugin(IHostSmartContractBridgeContextService contextService) { - private readonly IHostSmartContractBridgeContextService _contextService; + _contextService = contextService; + } - public DeleteDataFromStateDbPreExecutionPlugin(IHostSmartContractBridgeContextService contextService) - { - _contextService = contextService; - } - - public Task> GetPreTransactionsAsync(IReadOnlyList descriptors, ITransactionContext transactionContext) - { - if (!descriptors.Any(service => service.File.Name == "test_basic_function_with_parallel_contract.proto")) - { - return Task.FromResult(new List().AsEnumerable()); - } - - if (transactionContext.Transaction.To == ParallelTestHelper.BasicFunctionWithParallelContractAddress && - !transactionContext.Transaction.MethodName.EndsWith("Plugin")) - { - return Task.FromResult(new List().AsEnumerable()); - } - - var context = _contextService.Create(); - context.TransactionContext = transactionContext; - - var transactions = new List(); + public Task> GetPreTransactionsAsync(IReadOnlyList descriptors, + ITransactionContext transactionContext) + { + if (!descriptors.Any(service => service.File.Name == "test_basic_function_with_parallel_contract.proto")) + return Task.FromResult(new List().AsEnumerable()); + + if (transactionContext.Transaction.To == ParallelTestHelper.BasicFunctionWithParallelContractAddress && + !transactionContext.Transaction.MethodName.EndsWith("Plugin")) + return Task.FromResult(new List().AsEnumerable()); + + var context = _contextService.Create(); + context.TransactionContext = transactionContext; - switch (transactionContext.Transaction.MethodName) + var transactions = new List(); + + switch (transactionContext.Transaction.MethodName) + { + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromInlineWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin): { - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromInlineWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin): + var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; + } - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPrePlugin): + { + var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = RemoveValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction - { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = input.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedParallelWithInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithFailedInlineAndPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePluginAndFailedPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin): + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = input.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; + } + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedParallelWithInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithFailedInlineAndPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePluginAndFailedPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin): + { + var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValue), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; + } - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPrePlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPrePluginAndPostPlugin): - case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPrePlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPrePluginAndPostPlugin): + case nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin): + { + var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); + transactions.Add(new Transaction { - var input = IncreaseValueInput.Parser.ParseFrom(transactionContext.Transaction.Params); - transactions.Add(new Transaction + From = transactionContext.Transaction.From, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new IncreaseValueInput { - From = transactionContext.Transaction.From, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new IncreaseValueInput - { - Key = input.Key, - Memo = Guid.NewGuid().ToString() - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailed), - RefBlockNumber = transactionContext.BlockHeight - 1, - RefBlockPrefix = - BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) - }); - break; - } + Key = input.Key, + Memo = Guid.NewGuid().ToString() + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailed), + RefBlockNumber = transactionContext.BlockHeight - 1, + RefBlockPrefix = + BlockHelper.GetRefBlockPrefix(transactionContext.PreviousBlockHash) + }); + break; } - - return Task.FromResult(transactions.AsEnumerable()); - } - - public bool IsStopExecuting(ByteString txReturnValue, out string executionInformation) - { - executionInformation = string.Empty; - return false; } + + return Task.FromResult(transactions.AsEnumerable()); + } + + public bool IsStopExecuting(ByteString txReturnValue, out string executionInformation) + { + executionInformation = string.Empty; + return false; } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/DeleteDataFromStateDbTest.cs b/test/AElf.Parallel.Tests/DeleteDataFromStateDbTest.cs index b07d776331..2e2c018dc8 100644 --- a/test/AElf.Parallel.Tests/DeleteDataFromStateDbTest.cs +++ b/test/AElf.Parallel.Tests/DeleteDataFromStateDbTest.cs @@ -20,1164 +20,1164 @@ using Shouldly; using Xunit; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +//TODO: rewrite this class, too many repeated codes +public sealed class DeleteDataFromStateDbTest : AElfIntegratedTest { - //TODO: rewrite this class, too many repeated codes - public sealed class DeleteDataFromStateDbTest : AElfIntegratedTest + private readonly IAccountService _accountService; + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; + private readonly ParallelTestHelper _parallelTestHelper; + private readonly ITransactionGrouper _transactionGrouper; + private readonly ITransactionResultManager _transactionResultManager; + private readonly IStateStore _versionedStates; + + public DeleteDataFromStateDbTest() { - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionResultManager _transactionResultManager; - private readonly IBlockAttachService _blockAttachService; - private readonly IAccountService _accountService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly IStateStore _versionedStates; - private readonly IBlockchainStateService _blockchainStateService; - private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; - private readonly ITransactionGrouper _transactionGrouper; - private readonly ParallelTestHelper _parallelTestHelper; - - public DeleteDataFromStateDbTest() - { - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _transactionResultManager = GetRequiredService(); - _blockAttachService = GetRequiredService(); - _accountService = GetRequiredService(); - _versionedStates = GetRequiredService>(); - _blockchainStateService = GetRequiredService(); - _nonparallelContractCodeProvider = GetRequiredService(); - _transactionGrouper = GetRequiredService(); - _parallelTestHelper = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - } + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _transactionResultManager = GetRequiredService(); + _blockAttachService = GetRequiredService(); + _accountService = GetRequiredService(); + _versionedStates = GetRequiredService>(); + _blockchainStateService = GetRequiredService(); + _nonparallelContractCodeProvider = GetRequiredService(); + _transactionGrouper = GetRequiredService(); + _parallelTestHelper = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + } + + [Fact] + public async Task Set_Value() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - [Fact] - public async Task Set_Value() + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Key = key, + Memo = Guid.NewGuid().ToString() + }; - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), + increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), + otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValue), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var otherMessageValue = new MessageValue + { + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + [Fact] + public async Task Set_Value_With_Inline() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var messageValue = new MessageValue - { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_Inline() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + const string key = "TestKey"; + const string otherKey = "OtherKey"; - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInline), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInline), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var messageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_PrePlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + var transactions = new List(); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInline), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInline), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - var messageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + var otherMessageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPostPlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPostPlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + [Fact] + public async Task Set_Value_With_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + const string key = "TestKey"; + const string otherKey = "OtherKey"; - var messageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_Inline_And_PrePlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactions = new List(); - var messageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_Inline_And_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPostPlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPostPlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var otherMessageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } - var messageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_Plugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + [Fact] + public async Task Set_Value_With_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + const string otherKey = "OtherKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var messageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 3, - StringValue = "3" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_With_Inline_And_Plugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var transactions = new List(); + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - //NonParallel System Transaction - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var transactions = new List(); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; - var messageValue = new MessageValue - { - Int64Value = 4, - StringValue = "4" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue - { - Int64Value = 4, - StringValue = "4" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_Parallel_With_Inline_And_Plugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPostPlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPostPlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_With_Inline_And_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_With_Inline_And_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPostPlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPostPlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_With_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 3, + StringValue = "3" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_With_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + //NonParallel System Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 4, + StringValue = "4" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 4, + StringValue = "4" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_Parallel_With_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transactions = new List(); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 4, + StringValue = "4" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var otherMessageValue = new MessageValue + { + Int64Value = 4, + StringValue = "4" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } + + [Fact] + public async Task Set_Value_In_Blocks() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + const string otherKey = "OtherKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var increaseValueInput = new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }; + + var otherKeyInput = new IncreaseValueInput + { + Key = otherKey, + Memo = Guid.NewGuid().ToString() + }; + + MessageValue messageValue; + MessageValue otherMessageValue; + + //First block + { + var systemTransactions = new List(); var transactions = new List(); - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput + //NonParallel System Transaction { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); + var systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(systemTransaction); + + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), otherKeyInput); + systemTransactions.Add(systemTransaction); + } + + //Parallel System Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(systemTransaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(systemTransaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); + systemTransactions.Add(systemTransaction); + } + + var groupedSystemTransactions = await _transactionGrouper.GroupAsync(new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, systemTransactions); + groupedSystemTransactions.Parallelizables.Count.ShouldBe(2); + groupedSystemTransactions.Parallelizables[0].Count.ShouldBe(2); + groupedSystemTransactions.Parallelizables[1].Count.ShouldBe(1); + groupedSystemTransactions.NonParallelizables.Count.ShouldBe(2); + + //NonParallel Normal Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + } + + //Parallel Normal Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + transactions.Add(transaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + transactions.Add(transaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + } + + var groupedNormalTransactions = await _transactionGrouper.GroupAsync(new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, transactions); + groupedNormalTransactions.Parallelizables.Count.ShouldBe(2); + groupedNormalTransactions.Parallelizables[0].Count.ShouldBe(2); + groupedNormalTransactions.Parallelizables[1].Count.ShouldBe(1); + groupedNormalTransactions.NonParallelizables.Count.ShouldBe(3); + + var allTransactions = systemTransactions.Concat(transactions).ToList(); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, transactions, + CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(allTransactions); await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); + + var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); + nonparallelContractCode.ShouldBeNull(); - var messageValue = new MessageValue + messageValue = new MessageValue { - Int64Value = 4, - StringValue = "4" + Int64Value = 28, + StringValue = "28" }; value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var otherMessageValue = new MessageValue + + otherMessageValue = new MessageValue { - Int64Value = 4, - StringValue = "4" + Int64Value = 16, + StringValue = "16" }; value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Set_Value_In_Blocks() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - const string key = "TestKey"; - const string otherKey = "OtherKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, otherKey, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - var increaseValueInput = new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }; - - var otherKeyInput = new IncreaseValueInput - { - Key = otherKey, - Memo = Guid.NewGuid().ToString() - }; - - MessageValue messageValue; - MessageValue otherMessageValue; - //First block - { - var systemTransactions = new List(); - var transactions = new List(); - - //NonParallel System Transaction - { - var systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(systemTransaction); - - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), otherKeyInput); - systemTransactions.Add(systemTransaction); - } - - //Parallel System Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(systemTransaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(systemTransaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); - systemTransactions.Add(systemTransaction); - } - - var groupedSystemTransactions = await _transactionGrouper.GroupAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, systemTransactions); - groupedSystemTransactions.Parallelizables.Count.ShouldBe(2); - groupedSystemTransactions.Parallelizables[0].Count.ShouldBe(2); - groupedSystemTransactions.Parallelizables[1].Count.ShouldBe(1); - groupedSystemTransactions.NonParallelizables.Count.ShouldBe(2); - - //NonParallel Normal Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - } - - //Parallel Normal Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - transactions.Add(transaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - transactions.Add(transaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - } - - var groupedNormalTransactions = await _transactionGrouper.GroupAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, transactions); - groupedNormalTransactions.Parallelizables.Count.ShouldBe(2); - groupedNormalTransactions.Parallelizables[0].Count.ShouldBe(2); - groupedNormalTransactions.Parallelizables[1].Count.ShouldBe(1); - groupedNormalTransactions.NonParallelizables.Count.ShouldBe(3); - - var allTransactions = systemTransactions.Concat(transactions).ToList(); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, transactions, - CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(allTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); - - var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); - nonparallelContractCode.ShouldBeNull(); - - messageValue = new MessageValue - { - Int64Value = 28, - StringValue = "28" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - otherMessageValue = new MessageValue - { - Int64Value = 16, - StringValue = "16" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); - } - - { - chain = await _blockchainService.GetChainAsync(); - var systemTransactions = new List(); - var transactions = new List(); - - //NonParallel System Transaction - { - var systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(systemTransaction); - - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), otherKeyInput); - systemTransactions.Add(systemTransaction); - } - - - //Parallel System Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(systemTransaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(systemTransaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - systemTransaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); - systemTransactions.Add(systemTransaction); - } - - var groupedSystemTransactions = await _transactionGrouper.GroupAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, systemTransactions); - groupedSystemTransactions.Parallelizables.Count.ShouldBe(2); - groupedSystemTransactions.Parallelizables[0].Count.ShouldBe(2); - groupedSystemTransactions.Parallelizables[1].Count.ShouldBe(1); - groupedSystemTransactions.NonParallelizables.Count.ShouldBe(2); - - //NonParallel Normal Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - transactions.Add(transaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - } - - //Parallel Normal Transaction - { - increaseValueInput.Memo = Guid.NewGuid().ToString(); - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - transactions.Add(transaction); - - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - transactions.Add(transaction); - - otherKeyInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); - transactions.Add(transaction); - } - - var groupedNormalTransactions = await _transactionGrouper.GroupAsync(new ChainContext - { - BlockHash = chain.BestChainHash, - BlockHeight = chain.BestChainHeight - }, transactions); - groupedNormalTransactions.Parallelizables.Count.ShouldBe(2); - groupedNormalTransactions.Parallelizables[0].Count.ShouldBe(2); - groupedNormalTransactions.Parallelizables[1].Count.ShouldBe(1); - groupedNormalTransactions.NonParallelizables.Count.ShouldBe(3); - - var allTransactions = systemTransactions.Concat(transactions).ToList(); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, transactions, - CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(allTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); - - var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - ParallelTestHelper.BasicFunctionWithParallelContractAddress); - nonparallelContractCode.ShouldBeNull(); - - messageValue = new MessageValue - { - Int64Value = 56, - StringValue = "56" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); + } - otherMessageValue = new MessageValue - { - Int64Value = 32, - StringValue = "32" - }; - value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); - CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + { + chain = await _blockchainService.GetChainAsync(); + var systemTransactions = new List(); + var transactions = new List(); - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(0); + //NonParallel System Transaction + { + var systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(systemTransaction); + + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), otherKeyInput); + systemTransactions.Add(systemTransaction); } - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, - messageValue.StringValue, messageValue); - await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, - otherMessageValue.StringValue, otherMessageValue); - } - - [Fact] - public async Task Remove_Not_Exist_Key() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + //Parallel System Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(systemTransaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(systemTransaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + systemTransaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); + systemTransactions.Add(systemTransaction); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var groupedSystemTransactions = await _transactionGrouper.GroupAsync(new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, systemTransactions); + groupedSystemTransactions.Parallelizables.Count.ShouldBe(2); + groupedSystemTransactions.Parallelizables[0].Count.ShouldBe(2); + groupedSystemTransactions.Parallelizables[1].Count.ShouldBe(1); + groupedSystemTransactions.NonParallelizables.Count.ShouldBe(2); + + //NonParallel Normal Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + transactions.Add(transaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + } - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValue), new RemoveValueInput - { - Key = key - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); + //Parallel Normal Transaction + { + increaseValueInput.Memo = Guid.NewGuid().ToString(); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + transactions.Add(transaction); + + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + transactions.Add(transaction); + + otherKeyInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), otherKeyInput); + transactions.Add(transaction); + } + + var groupedNormalTransactions = await _transactionGrouper.GroupAsync(new ChainContext + { + BlockHash = chain.BestChainHash, + BlockHeight = chain.BestChainHeight + }, transactions); + groupedNormalTransactions.Parallelizables.Count.ShouldBe(2); + groupedNormalTransactions.Parallelizables[0].Count.ShouldBe(2); + groupedNormalTransactions.Parallelizables[1].Count.ShouldBe(1); + groupedNormalTransactions.NonParallelizables.Count.ShouldBe(3); + + var allTransactions = systemTransactions.Concat(transactions).ToList(); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, transactions, + CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(allTransactions); await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); + + var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + ParallelTestHelper.BasicFunctionWithParallelContractAddress); + nonparallelContractCode.ShouldBeNull(); + + messageValue = new MessageValue + { + Int64Value = 56, + StringValue = "56" + }; value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + otherMessageValue = new MessageValue + { + Int64Value = 32, + StringValue = "32" + }; + value = await GetValueAsync(accountAddress, otherKey, block.GetHash(), block.Height); + CheckValue(value, otherMessageValue.StringValue, otherMessageValue.Int64Value, otherMessageValue); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(3); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(0); } - [Fact] - public async Task Remove_After_Set_Key() - { - const string key = "TestKey"; - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveAfterSetValue), new RemoveAfterSetValueInput - { - Key = key, - Int64Value = 10, - StringValue = "test", - MessageValue = new MessageValue - { - Int64Value = 20, - StringValue = "MessageTest", - } - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, + messageValue.StringValue, messageValue); + await CheckValueInVersionStateAsync(otherKey, otherMessageValue.Int64Value, + otherMessageValue.StringValue, otherMessageValue); + } - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(3); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } + [Fact] + public async Task Remove_Not_Exist_Key() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValue), + new RemoveValueInput + { + Key = key + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(3); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - [Fact] - public async Task Set_After_Remove_Key() - { - const string key = "TestKey"; - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Remove_After_Set_Key() + { + const string key = "TestKey"; + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var setValueInput = new SetValueInput + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveAfterSetValue), new RemoveAfterSetValueInput { Key = key, Int64Value = 10, @@ -1185,1842 +1185,1983 @@ public async Task Set_After_Remove_Key() MessageValue = new MessageValue { Int64Value = 20, - StringValue = "MessageTest", + StringValue = "MessageTest" } - }; - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.SetValue), setValueInput); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, setValueInput.StringValue, setValueInput.Int64Value, - setValueInput.MessageValue); - - var setAfterRemoveValueInput = new SetAfterRemoveValueInput + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(3); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } + + [Fact] + public async Task Set_After_Remove_Key() + { + const string key = "TestKey"; + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var setValueInput = new SetValueInput + { + Key = key, + Int64Value = 10, + StringValue = "test", + MessageValue = new MessageValue { - Key = key, Int64Value = 20, - StringValue = "test2", - MessageValue = new MessageValue - { - Int64Value = 10, - StringValue = "MessageTest2", - } - }; - transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.SetAfterRemoveValue), setAfterRemoveValueInput); - transactions = new List {transaction}; - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, setAfterRemoveValueInput.StringValue, - setAfterRemoveValueInput.Int64Value, setAfterRemoveValueInput.MessageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, - setAfterRemoveValueInput.Int64Value, setAfterRemoveValueInput.StringValue, - setAfterRemoveValueInput.MessageValue); - } - - [Fact] - public async Task Complex_ChangeAndDelete_Key() + StringValue = "MessageTest" + } + }; + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.SetValue), + setValueInput); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, setValueInput.StringValue, setValueInput.Int64Value, + setValueInput.MessageValue); + + var setAfterRemoveValueInput = new SetAfterRemoveValueInput { - const string key = "TestKey"; - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + Key = key, + Int64Value = 20, + StringValue = "test2", + MessageValue = new MessageValue + { + Int64Value = 10, + StringValue = "MessageTest2" + } + }; + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .SetAfterRemoveValue), setAfterRemoveValueInput); + transactions = new List { transaction }; + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, setAfterRemoveValueInput.StringValue, + setAfterRemoveValueInput.Int64Value, setAfterRemoveValueInput.MessageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, + setAfterRemoveValueInput.Int64Value, setAfterRemoveValueInput.StringValue, + setAfterRemoveValueInput.MessageValue); + } + + [Fact] + public async Task Complex_ChangeAndDelete_Key() + { + const string key = "TestKey"; + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - //ComplexChangeWithDeleteValue1 - var complexChangeInput = new SetValueInput + //ComplexChangeWithDeleteValue1 + var complexChangeInput = new SetValueInput + { + Key = key, + Int64Value = 100, + StringValue = "test1", + MessageValue = new MessageValue { - Key = key, Int64Value = 100, - StringValue = "test1", - MessageValue = new MessageValue - { - Int64Value = 100, - StringValue = "test1" - } - }; - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.ComplexChangeWithDeleteValue1), complexChangeInput); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, complexChangeInput.StringValue, complexChangeInput.Int64Value, - null); - - //ComplexChangeWithDeleteValue2 - complexChangeInput = new SetValueInput + StringValue = "test1" + } + }; + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .ComplexChangeWithDeleteValue1), complexChangeInput); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, complexChangeInput.StringValue, complexChangeInput.Int64Value, + null); + + //ComplexChangeWithDeleteValue2 + complexChangeInput = new SetValueInput + { + Key = key, + Int64Value = 100, + StringValue = "test2", + MessageValue = new MessageValue { - Key = key, Int64Value = 100, - StringValue = "test2", - MessageValue = new MessageValue - { - Int64Value = 100, - StringValue = "test2" - } - }; - transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.ComplexChangeWithDeleteValue2), complexChangeInput); - transactions = new List {transaction}; - block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, complexChangeInput.StringValue, 0, - complexChangeInput.MessageValue); - - //ComplexChangeWithDeleteValue3 - complexChangeInput = new SetValueInput + StringValue = "test2" + } + }; + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .ComplexChangeWithDeleteValue2), complexChangeInput); + transactions = new List { transaction }; + block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, complexChangeInput.StringValue, 0, + complexChangeInput.MessageValue); + + //ComplexChangeWithDeleteValue3 + complexChangeInput = new SetValueInput + { + Key = key, + Int64Value = 100, + StringValue = "test3", + MessageValue = new MessageValue { - Key = key, Int64Value = 100, - StringValue = "test3", - MessageValue = new MessageValue - { - Int64Value = 100, - StringValue = "test3" - } - }; - transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.ComplexChangeWithDeleteValue3), complexChangeInput); - transactions = new List {transaction}; - block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, "", complexChangeInput.Int64Value, - null); - } + StringValue = "test3" + } + }; + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .ComplexChangeWithDeleteValue3), complexChangeInput); + transactions = new List { transaction }; + block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, "", complexChangeInput.Int64Value, + null); + } + + [Fact] + public async Task Remove_Value_From_PrePlugin() + { + await Set_Value(); - [Fact] - public async Task Remove_Value_From_PrePlugin() + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + + const string key = "TestKey"; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPrePlugin), new RemoveValueInput + { + Key = key + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue { - await Set_Value(); - - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); + Int64Value = 3, + StringValue = "3" + }; - const string key = "TestKey"; + var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPrePlugin), new RemoveValueInput - { - Key = key - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var messageValue = new MessageValue + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } + + [Fact] + public async Task Remove_Value_With_Plugin() + { + await Set_Value(); + + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + + const string key = "TestKey"; + + var transactions = new List(); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueWithPlugin), new RemoveValueInput { - Int64Value = 3, - StringValue = "3" - }; - - var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } + Key = key + }); + transactions.Add(transaction); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); - [Fact] - public async Task Remove_Value_With_Plugin() + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue { - await Set_Value(); - - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); + Int64Value = 2, + StringValue = "2" + }; - const string key = "TestKey"; - - var transactions = new List(); - - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueWithPlugin), new RemoveValueInput - { - Key = key - }); - transactions.Add(transaction); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } + + [Fact] + public async Task Remove_Value_From_Inline_With_Plugin() + { + await Set_Value(); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var messageValue = new MessageValue + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + + const string key = "TestKey"; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromInlineWithPlugin), new RemoveValueInput { - Int64Value = 2, - StringValue = "2" - }; - - var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + Key = key + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 1, + StringValue = "1" + }; + + var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } + + [Fact] + public async Task Remove_Value_From_PostPlugin() + { + await Set_Value(); + + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + + const string key = "TestKey"; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), new RemoveValueInput + { + Key = key + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(3); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } + + [Fact] + public async Task Remove_Value_In_Blocks() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + var keys = new[] + { "TestKeyOne", "TestKeyTwo", "TestKeyThree", "TestKeyFour", "TestKeyFive", "TestKeySix", "TestKeySeven" }; + + var value = await GetValueAsync(accountAddress, keys[0], chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, keys[1], chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var tasks = keys.Select(key => GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + })); + var transactions = await Task.WhenAll(tasks); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions.ToList())).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); + + var messageValue = new MessageValue + { + Int64Value = 4, + StringValue = "4" + }; + foreach (var key in keys) + { + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); } - - [Fact] - public async Task Remove_Value_From_Inline_With_Plugin() + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + + //First Block { - await Set_Value(); - - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); + var systemTransactions = new List(); + var normalTransactions = new List(); + + //System Transaction + { + var increaseValueInput = new IncreaseValueInput + { + Key = keys[0], + Memo = Guid.NewGuid().ToString() + }; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); - const string key = "TestKey"; + var removeValueInput = new RemoveValueInput + { + Key = keys[0], + Memo = Guid.NewGuid().ToString() + }; + + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[1]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[2]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[3]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[4]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(transaction); + + removeValueInput.Key = keys[3]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + + removeValueInput.Key = keys[4]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + } - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromInlineWithPlugin), new RemoveValueInput + //Normal Transaction + { + var removeValueInput = new RemoveValueInput { - Key = key - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); + Key = keys[2], + Memo = Guid.NewGuid().ToString() + }; + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + removeValueInput.Key = keys[5]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + removeValueInput.Key = keys[6]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + var increaseValueInput = new IncreaseValueInput + { + Key = keys[5], + Memo = Guid.NewGuid().ToString() + }; + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); + normalTransactions.Add(transaction); + + increaseValueInput.Key = keys[6]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); + normalTransactions.Add(transaction); + } + + var allTransactions = systemTransactions.Concat(normalTransactions).ToList(); + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + normalTransactions, + CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(systemTransactions); await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var messageValue = new MessageValue + transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); + + value = await GetValueAsync(accountAddress, keys[0], block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var newMessageValue = new MessageValue { - Int64Value = 1, - StringValue = "1" + Int64Value = 8, + StringValue = "8" }; - - var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + value = await GetValueAsync(accountAddress, keys[1], block.GetHash(), block.Height); + CheckValue(value, newMessageValue.StringValue, newMessageValue.Int64Value, newMessageValue); + + value = await GetValueAsync(accountAddress, keys[2], block.GetHash(), block.Height); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, keys[3], block.GetHash(), block.Height); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, keys[4], block.GetHash(), block.Height); CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - + + value = await GetValueAsync(accountAddress, keys[5], block.GetHash(), block.Height); + CheckValueNotExisted(value); + + value = await GetValueAsync(accountAddress, keys[6], block.GetHash(), block.Height); + CheckValueNotExisted(value); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + blockStateSet.Changes.Count.ShouldBe(6); + blockStateSet.Deletes.Count.ShouldBe(15); } - - [Fact] - public async Task Remove_Value_From_PostPlugin() + + //Second Block { - await Set_Value(); - - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); + var systemTransactions = new List(); + var normalTransactions = new List(); + + //System Transaction + { + var increaseValueInput = new IncreaseValueInput + { + Key = keys[0], + Memo = Guid.NewGuid().ToString() + }; - const string key = "TestKey"; + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), new RemoveValueInput + var removeValueInput = new RemoveValueInput { - Key = key - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + Key = keys[0], + Memo = Guid.NewGuid().ToString() + }; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(3); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[1]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[2]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[3]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(transaction); + + increaseValueInput.Key = keys[4]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPlugin), + increaseValueInput); + systemTransactions.Add(transaction); + + removeValueInput.Key = keys[3]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + + removeValueInput.Key = keys[4]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin), removeValueInput); + systemTransactions.Add(transaction); + } - [Fact] - public async Task Remove_Value_In_Blocks() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + //Normal Transaction + { + var removeValueInput = new RemoveValueInput + { + Key = keys[2], + Memo = Guid.NewGuid().ToString() + }; - var keys = new[] {"TestKeyOne", "TestKeyTwo", "TestKeyThree", "TestKeyFour", "TestKeyFive", "TestKeySix", "TestKeySeven"}; - - var value = await GetValueAsync(accountAddress, keys[0], chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[1], chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + removeValueInput = new RemoveValueInput + { + Key = keys[1], + Memo = Guid.NewGuid().ToString() + }; - var tasks = keys.Select(key => GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), new IncreaseValueInput - { - Key = key, + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueParallelFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + removeValueInput.Key = keys[5]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + removeValueInput.Key = keys[6]; + removeValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .RemoveValueFromPostPlugin), removeValueInput); + normalTransactions.Add(transaction); + + var increaseValueInput = new IncreaseValueInput + { + Key = keys[5], Memo = Guid.NewGuid().ToString() - })); - var transactions = await Task.WhenAll(tasks); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions.ToList())).Block; - await _blockchainService.AddTransactionsAsync(transactions); + }; + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); + normalTransactions.Add(transaction); + + increaseValueInput.Key = keys[6]; + increaseValueInput.Memo = Guid.NewGuid().ToString(); + transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); + normalTransactions.Add(transaction); + } + + var allTransactions = systemTransactions.Concat(normalTransactions).ToList(); + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + normalTransactions, + CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(systemTransactions); await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.ShouldAllBe(t=>t.Status == TransactionResultStatus.Mined); - - var messageValue = new MessageValue - { - Int64Value = 4, - StringValue = "4" - }; - foreach (var key in keys) - { - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - } - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); - //First Block - { - var systemTransactions = new List(); - var normalTransactions = new List(); + value = await GetValueAsync(accountAddress, keys[0], block.GetHash(), block.Height); + CheckValueNotExisted(value); - //System Transaction - { - var increaseValueInput = new IncreaseValueInput - { - Key = keys[0], - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - var removeValueInput = new RemoveValueInput - { - Key = keys[0], - Memo = Guid.NewGuid().ToString() - }; - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[1]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[2]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[3]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[4]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(transaction); - - removeValueInput.Key = keys[3]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - - removeValueInput.Key = keys[4]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - } + value = await GetValueAsync(accountAddress, keys[1], block.GetHash(), block.Height); + CheckValueNotExisted(value); - //Normal Transaction - { - var removeValueInput = new RemoveValueInput - { - Key = keys[2], - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - removeValueInput.Key = keys[5]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - removeValueInput.Key = keys[6]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - var increaseValueInput = new IncreaseValueInput - { - Key = keys[5], - Memo = Guid.NewGuid().ToString() - }; - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); - normalTransactions.Add(transaction); - - increaseValueInput.Key = keys[6]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); - normalTransactions.Add(transaction); - } + value = await GetValueAsync(accountAddress, keys[2], block.GetHash(), block.Height); + CheckValueNotExisted(value); - var allTransactions = systemTransactions.Concat(normalTransactions).ToList(); - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - normalTransactions, - CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(systemTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + value = await GetValueAsync(accountAddress, keys[3], block.GetHash(), block.Height); + CheckValueNotExisted(value); - transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); + value = await GetValueAsync(accountAddress, keys[4], block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - value = await GetValueAsync(accountAddress, keys[0], block.GetHash(), block.Height); - CheckValueNotExisted(value); + value = await GetValueAsync(accountAddress, keys[5], block.GetHash(), block.Height); + CheckValueNotExisted(value); - var newMessageValue = new MessageValue - { - Int64Value = 8, - StringValue = "8" - }; - value = await GetValueAsync(accountAddress, keys[1], block.GetHash(), block.Height); - CheckValue(value, newMessageValue.StringValue, newMessageValue.Int64Value, newMessageValue); + value = await GetValueAsync(accountAddress, keys[6], block.GetHash(), block.Height); + CheckValueNotExisted(value); - value = await GetValueAsync(accountAddress, keys[2], block.GetHash(), block.Height); - CheckValueNotExisted(value); + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(18); + } - value = await GetValueAsync(accountAddress, keys[3], block.GetHash(), block.Height); - CheckValueNotExisted(value); + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(keys[0]); + await CheckValueNotExistedInVersionStateAsync(keys[1]); + await CheckValueNotExistedInVersionStateAsync(keys[2]); + await CheckValueNotExistedInVersionStateAsync(keys[3]); + await CheckValueNotExistedInVersionStateAsync(keys[5]); + await CheckValueNotExistedInVersionStateAsync(keys[6]); + await CheckValueInVersionStateAsync(keys[4], messageValue.Int64Value, + messageValue.StringValue, messageValue); + } - value = await GetValueAsync(accountAddress, keys[4], block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + [Fact] + public async Task Increase_Value_Failed() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - value = await GetValueAsync(accountAddress, keys[5], block.GetHash(), block.Height); - CheckValueNotExisted(value); + const string key = "TestKey"; - value = await GetValueAsync(accountAddress, keys[6], block.GetHash(), block.Height); - CheckValueNotExisted(value); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(6); - blockStateSet.Deletes.Count.ShouldBe(15); - } - - //Second Block + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailed), new IncreaseValueInput { - var systemTransactions = new List(); - var normalTransactions = new List(); - - //System Transaction - { - var increaseValueInput = new IncreaseValueInput - { - Key = keys[0], - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - var removeValueInput = new RemoveValueInput - { - Key = keys[0], - Memo = Guid.NewGuid().ToString() - }; - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[1]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[2]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[3]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(transaction); - - increaseValueInput.Key = keys[4]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPlugin), - increaseValueInput); - systemTransactions.Add(transaction); - - removeValueInput.Key = keys[3]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - - removeValueInput.Key = keys[4]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin), removeValueInput); - systemTransactions.Add(transaction); - } + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - //Normal Transaction - { - var removeValueInput = new RemoveValueInput - { - Key = keys[2], - Memo = Guid.NewGuid().ToString() - }; - - var transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - removeValueInput = new RemoveValueInput - { - Key = keys[1], - Memo = Guid.NewGuid().ToString() - }; - - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueParallelFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - removeValueInput.Key = keys[5]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - removeValueInput.Key = keys[6]; - removeValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.RemoveValueFromPostPlugin), removeValueInput); - normalTransactions.Add(transaction); - - var increaseValueInput = new IncreaseValueInput - { - Key = keys[5], - Memo = Guid.NewGuid().ToString() - }; - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); - normalTransactions.Add(transaction); - - increaseValueInput.Key = keys[6]; - increaseValueInput.Memo = Guid.NewGuid().ToString(); - transaction = await GenerateTransactionAsync(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithInlineAndPlugin), increaseValueInput); - normalTransactions.Add(transaction); - } + [Fact] + public async Task Increase_Value_Parallel_Failed() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var allTransactions = systemTransactions.Concat(normalTransactions).ToList(); - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - normalTransactions, - CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(systemTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.ShouldAllBe(t => t.Status == TransactionResultStatus.Mined); - - value = await GetValueAsync(accountAddress, keys[0], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[1], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[2], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[3], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[4], block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - value = await GetValueAsync(accountAddress, keys[5], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - value = await GetValueAsync(accountAddress, keys[6], block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(18); - } + const string key = "TestKey"; - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(keys[0]); - await CheckValueNotExistedInVersionStateAsync(keys[1]); - await CheckValueNotExistedInVersionStateAsync(keys[2]); - await CheckValueNotExistedInVersionStateAsync(keys[3]); - await CheckValueNotExistedInVersionStateAsync(keys[5]); - await CheckValueNotExistedInVersionStateAsync(keys[6]); - await CheckValueInVersionStateAsync(keys[4], messageValue.Int64Value, - messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelFailed), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailed), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + [Fact] + public async Task Increase_Value_Failed_With_Inline() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_Parallel_Failed() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + const string key = "TestKey"; - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelFailed), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInline), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } + [Fact] + public async Task Increase_Value_With_Failed_Inline() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - [Fact] - public async Task Increase_Value_Failed_With_Inline() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + const string key = "TestKey"; - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInline), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInline), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_Failed_Inline() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + [Fact] + public async Task Increase_Value_Failed_With_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + const string key = "TestKey"; - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInline), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_Failed_With_PrePlugin() + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPrePlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_With_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPrePlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPostPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed_With_PostPlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_With_Inline_And_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPrePlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed_With_Inline_And_PrePlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_With_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPrePlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed_With_Plugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_With_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue - { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - [Fact] - public async Task Increase_Value_Failed_With_Inline_And_Plugin() + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_Parallel_With_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedParallelWithInlineAndPlugin), new IncreaseValueInput { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed_Parallel_With_Inline_And_Plugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Failed_Inline_And_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedParallelWithInlineAndPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPrePlugin), new IncreaseValueInput { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_With_Failed_Inline_And_PrePlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Failed_Inline_And_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPrePlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPostPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_With_Failed_Inline_And_PostPlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Failed_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedInlineAndPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_With_Failed_Inline_And_Plugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } + + [Fact] + public async Task Increase_Value_Parallel_With_Failed_Inline_And_Plugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + const string key = "TestKey"; - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedInlineAndPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueParallelWithFailedInlineAndPlugin), new IncreaseValueInput { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Parallel_With_Failed_Inline_And_Plugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 2, + StringValue = "2" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_Failed_With_Inline_And_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueParallelWithFailedInlineAndPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueFailedWithInlineAndPostPlugin), new IncreaseValueInput { - Int64Value = 2, - StringValue = "2" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_Failed_With_Inline_And_PostPlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Failed_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueFailedWithInlineAndPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPrePlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_With_Failed_PrePlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Inline_And_Failed_PrePlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPrePlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - [Fact] - public async Task Increase_Value_With_Inline_And_Failed_PrePlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPrePlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Failed_PrePlugin_And_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPrePlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_Failed_PrePlugin_And_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPrePluginAndPostPlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPrePluginAndPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + [Fact] + public async Task Increase_Value_With_Inline_And_Failed_PrePlugin_And_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_Inline_And_Failed_PrePlugin_And_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + const string key = "TestKey"; - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPrePluginAndPostPlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_Failed_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + [Fact] + public async Task Increase_Value_With_Failed_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + const string key = "TestKey"; - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithFailedPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_Inline_And_Failed_PostPlugin() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithFailedPostPlugin), new IncreaseValueInput + { + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Inline_And_Failed_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndFailedPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); + + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndFailedPostPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValueNotExisted(value); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(0); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueNotExistedInVersionStateAsync(key); - } - - [Fact] - public async Task Increase_Value_With_PrePlugin_And_Failed_PostPlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValueNotExisted(value); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(0); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueNotExistedInVersionStateAsync(key); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_PrePlugin_And_Failed_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithPrePluginAndFailedPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; + + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithPrePluginAndFailedPostPlugin), new IncreaseValueInput { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - [Fact] - public async Task Increase_Value_With_Inline_And_PrePlugin_And_Failed_PostPlugin() + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - const string key = "TestKey"; - - var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); - CheckValueNotExisted(value); + [Fact] + public async Task Increase_Value_With_Inline_And_PrePlugin_And_Failed_PostPlugin() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); - var transaction = await GenerateTransactionAsync(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin), new IncreaseValueInput - { - Key = key, - Memo = Guid.NewGuid().ToString() - }); - var transactions = new List {transaction}; - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - await _blockchainService.AddTransactionsAsync(transactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); + const string key = "TestKey"; - var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - var messageValue = new MessageValue - { - Int64Value = 1, - StringValue = "1" - }; - value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); - CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBe(3); - blockStateSet.Deletes.Count.ShouldBe(0); - - chain = await _blockchainService.GetChainAsync(); - await SetIrreversibleBlockAsync(chain); - await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); - } - - #region private - private async Task GenerateTransactionAsync(Address from,Address to,string methodName,IMessage input) - { - var transaction = _parallelTestHelper.GenerateTransaction(from, to, methodName, input); - var transactionHash = transaction.GetHash(); - var signature = await _accountService.SignAsync(transactionHash.ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - var transactions = new List {transaction}; - await _parallelTestHelper.BroadcastTransactions(transactions); - return transaction; - } + var value = await GetValueAsync(accountAddress, key, chain.BestChainHash, chain.BestChainHeight); + CheckValueNotExisted(value); - private async Task GetValueAsync(Address from,string key,Hash blockHash,long blockHeight) - { - var byteString = await _parallelTestHelper.ExecuteReadOnlyAsync(new Transaction + var transaction = await GenerateTransactionAsync(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseValueWithInlineAndPrePluginAndFailedPostPlugin), new IncreaseValueInput { - From = from, - To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Params = new GetValueInput - { - Key = key - }.ToByteString(), - MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub.GetValue), + Key = key, + Memo = Guid.NewGuid().ToString() + }); + var transactions = new List { transaction }; + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + await _blockchainService.AddTransactionsAsync(transactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = await GetTransactionResultAsync(transaction.GetHash(), block.Header); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + var messageValue = new MessageValue + { + Int64Value = 1, + StringValue = "1" + }; + value = await GetValueAsync(accountAddress, key, block.GetHash(), block.Height); + CheckValue(value, messageValue.StringValue, messageValue.Int64Value, messageValue); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBe(3); + blockStateSet.Deletes.Count.ShouldBe(0); + + chain = await _blockchainService.GetChainAsync(); + await SetIrreversibleBlockAsync(chain); + await CheckValueInVersionStateAsync(key, messageValue.Int64Value, messageValue.StringValue, messageValue); + } - }, blockHash, blockHeight); - return GetValueOutput.Parser.ParseFrom(byteString); - } + #region private - private async Task SetIrreversibleBlockAsync(Chain chain) + private async Task GenerateTransactionAsync(Address from, Address to, string methodName, + IMessage input) + { + var transaction = _parallelTestHelper.GenerateTransaction(from, to, methodName, input); + var transactionHash = transaction.GetHash(); + var signature = await _accountService.SignAsync(transactionHash.ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + var transactions = new List { transaction }; + await _parallelTestHelper.BroadcastTransactions(transactions); + return transaction; + } + + private async Task GetValueAsync(Address from, string key, Hash blockHash, long blockHeight) + { + var byteString = await _parallelTestHelper.ExecuteReadOnlyAsync(new Transaction { - await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); - await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); - } + From = from, + To = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Params = new GetValueInput + { + Key = key + }.ToByteString(), + MethodName = nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .GetValue) + }, blockHash, blockHeight); + return GetValueOutput.Parser.ParseFrom(byteString); + } + + private async Task SetIrreversibleBlockAsync(Chain chain) + { + await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); + await _blockchainStateService.MergeBlockStateAsync(chain.BestChainHeight, chain.BestChainHash); + } + + private void CheckValueNotExisted(GetValueOutput output) + { + output.StringValue.ShouldBeEmpty(); + output.Int64Value.ShouldBe(0); + output.MessageValue.ShouldBeNull(); + } - private void CheckValueNotExisted(GetValueOutput output) + private async Task CheckValueNotExistedInVersionStateAsync(string key) + { + var state = await _versionedStates.GetAsync(new ScopedStatePath { - output.StringValue.ShouldBeEmpty(); - output.Int64Value.ShouldBe(0); - output.MessageValue.ShouldBeNull(); - } + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath + { + Parts = { "BoolValueMap", key } + } + }.ToStateKey()); + state.ShouldBeNull(); - private async Task CheckValueNotExistedInVersionStateAsync(string key) + state = await _versionedStates.GetAsync(new ScopedStatePath { - var state = await _versionedStates.GetAsync(new ScopedStatePath() + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"BoolValueMap", key} - } - }.ToStateKey()); - state.ShouldBeNull(); - - state = await _versionedStates.GetAsync(new ScopedStatePath() + Parts = { "LongValueMap", key } + } + }.ToStateKey()); + state.ShouldBeNull(); + + state = await _versionedStates.GetAsync(new ScopedStatePath + { + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"LongValueMap", key} - } - }.ToStateKey()); - state.ShouldBeNull(); - - state = await _versionedStates.GetAsync(new ScopedStatePath() + Parts = { "StringValueMap", key } + } + }.ToStateKey()); + state.ShouldBeNull(); + + state = await _versionedStates.GetAsync(new ScopedStatePath + { + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"StringValueMap", key} - } - }.ToStateKey()); - state.ShouldBeNull(); - - state = await _versionedStates.GetAsync(new ScopedStatePath() + Parts = { "MessageValueMap", key } + } + }.ToStateKey()); + state.ShouldBeNull(); + } + + private async Task CheckValueInVersionStateAsync(string key, long longValue, string stringValue, + MessageValue messageValue) + { + var state = await _versionedStates.GetAsync(new ScopedStatePath + { + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"MessageValueMap", key} - } - }.ToStateKey()); - state.ShouldBeNull(); - } - - private async Task CheckValueInVersionStateAsync(string key,long longValue,string stringValue,MessageValue messageValue) + Parts = { "LongValueMap", key } + } + }.ToStateKey()); + SerializationHelper.Deserialize(state.Value.ToByteArray()) + .ShouldBe(longValue); + + state = await _versionedStates.GetAsync(new ScopedStatePath { - var state = await _versionedStates.GetAsync(new ScopedStatePath() + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"LongValueMap", key} - } - }.ToStateKey()); - SerializationHelper.Deserialize(state.Value.ToByteArray()) - .ShouldBe(longValue); - - state = await _versionedStates.GetAsync(new ScopedStatePath() - { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"StringValueMap", key} - } - }.ToStateKey()); - SerializationHelper.Deserialize(state.Value.ToByteArray()) - .ShouldBe(stringValue); - - state = await _versionedStates.GetAsync(new ScopedStatePath() - { - Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, - Path = new StatePath - { - Parts = {"MessageValueMap", key} - } - }.ToStateKey()); - SerializationHelper.Deserialize(state.Value.ToByteArray()) - .ShouldBe(messageValue); - } + Parts = { "StringValueMap", key } + } + }.ToStateKey()); + SerializationHelper.Deserialize(state.Value.ToByteArray()) + .ShouldBe(stringValue); - private void CheckValue(GetValueOutput output,string stringValue,long longValue,MessageValue messageValue) + state = await _versionedStates.GetAsync(new ScopedStatePath { - output.StringValue.ShouldBe(stringValue); - output.Int64Value.ShouldBe(longValue); - output.MessageValue.ShouldBe(messageValue); - } - - private async Task GetTransactionResultAsync(Hash transactionId,BlockHeader blockHeader) + Address = ParallelTestHelper.BasicFunctionWithParallelContractAddress, + Path = new StatePath + { + Parts = { "MessageValueMap", key } + } + }.ToStateKey()); + SerializationHelper.Deserialize(state.Value.ToByteArray()) + .ShouldBe(messageValue); + } + + private void CheckValue(GetValueOutput output, string stringValue, long longValue, MessageValue messageValue) + { + output.StringValue.ShouldBe(stringValue); + output.Int64Value.ShouldBe(longValue); + output.MessageValue.ShouldBe(messageValue); + } + + private async Task GetTransactionResultAsync(Hash transactionId, BlockHeader blockHeader) + { + var transactionResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, + blockHeader.GetHash()); + if (transactionResult != null) return transactionResult; + return await _transactionResultManager.GetTransactionResultAsync(transactionId, + blockHeader.GetDisambiguatingHash()); + } + + private async Task> GetTransactionResultsAsync(List transactionIds, + BlockHeader blockHeader) + { + var transactionResults = new List(); + foreach (var transactionId in transactionIds) { var transactionResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, blockHeader.GetHash()); - if (transactionResult != null) return transactionResult; - return await _transactionResultManager.GetTransactionResultAsync(transactionId, + if (transactionResult != null) transactionResults.Add(transactionResult); + transactionResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, blockHeader.GetDisambiguatingHash()); + if (transactionResult != null) transactionResults.Add(transactionResult); } - private async Task> GetTransactionResultsAsync(List transactionIds,BlockHeader blockHeader) - { - var transactionResults = new List(); - foreach (var transactionId in transactionIds) - { - var transactionResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, - blockHeader.GetHash()); - if (transactionResult != null) transactionResults.Add(transactionResult); - transactionResult = await _transactionResultManager.GetTransactionResultAsync(transactionId, - blockHeader.GetDisambiguatingHash()); - if(transactionResult != null) transactionResults.Add(transactionResult); - } - - return transactionResults; - } - #endregion + return transactionResults; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/ParallelTestAElfModule.cs b/test/AElf.Parallel.Tests/ParallelTestAElfModule.cs index a538f45bdf..f02beed36e 100644 --- a/test/AElf.Parallel.Tests/ParallelTestAElfModule.cs +++ b/test/AElf.Parallel.Tests/ParallelTestAElfModule.cs @@ -1,46 +1,41 @@ -using AElf.Kernel.SmartContract.Application; using System.Collections.Generic; using AElf.Kernel; -using AElf.Kernel.FeeCalculation; -using AElf.Kernel.FeeCalculation.Application; -using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; using AElf.Kernel.SmartContract.Parallel; using AElf.Kernel.SmartContract.Parallel.Application; using AElf.Modularity; using AElf.OS; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp; using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +[DependsOn( + typeof(OSCoreWithChainTestAElfModule), + typeof(ParallelExecutionModule), + typeof(ExecutionPluginForMethodFeeModule) +)] +public class ParallelTestAElfModule : AElfModule { - [DependsOn( - typeof(OSCoreWithChainTestAElfModule), - typeof(ParallelExecutionModule), - typeof(ExecutionPluginForMethodFeeModule) - )] - public class ParallelTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - base.ConfigureServices(context); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - // context.Services.AddSingleton(); - } + base.ConfigureServices(context); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + // context.Services.AddSingleton(); + } - public override void PostConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(s=>s.ImplementationType == typeof(NewIrreversibleBlockFoundEventHandler)); - } + public override void PostConfigureServices(ServiceConfigurationContext context) + { + context.Services.RemoveAll(s => s.ImplementationType == typeof(NewIrreversibleBlockFoundEventHandler)); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var parallelTestHelper = context.ServiceProvider.GetService(); - AsyncHelper.RunSync(() => parallelTestHelper.DeployBasicFunctionWithParallelContract()); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var parallelTestHelper = context.ServiceProvider.GetService(); + AsyncHelper.RunSync(() => parallelTestHelper.DeployBasicFunctionWithParallelContract()); } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/ParallelTestHelper.cs b/test/AElf.Parallel.Tests/ParallelTestHelper.cs index 7e4dcac6a9..e2b523791f 100644 --- a/test/AElf.Parallel.Tests/ParallelTestHelper.cs +++ b/test/AElf.Parallel.Tests/ParallelTestHelper.cs @@ -24,214 +24,219 @@ using Microsoft.Extensions.Options; using Volo.Abp.Threading; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +public class ParallelTestHelper : OSTestHelper { - public class ParallelTestHelper : OSTestHelper + private readonly IAccountService _accountService; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly IStaticChainInformationProvider _staticChainInformationProvider; + private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; + public readonly string PrimaryTokenSymbol = "ELF"; + private IReadOnlyDictionary _codes; + + public ParallelTestHelper(IOsBlockchainNodeContextService osBlockchainNodeContextService, + IAccountService accountService, + IMinerService minerService, + IBlockchainService blockchainService, + ISmartContractAddressService smartContractAddressService, + IBlockAttachService blockAttachService, + IStaticChainInformationProvider staticChainInformationProvider, + ITransactionResultService transactionResultService, + IOptionsSnapshot chainOptions, + ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, + ITransactionPoolService transactionPoolService + ) : base(osBlockchainNodeContextService, accountService, + minerService, blockchainService, smartContractAddressService, blockAttachService, + staticChainInformationProvider, transactionResultService, chainOptions, transactionPoolService) { - private IReadOnlyDictionary _codes; - private readonly IStaticChainInformationProvider _staticChainInformationProvider; - private readonly IAccountService _accountService; - private readonly ITransactionReadOnlyExecutionService _transactionReadOnlyExecutionService; - private readonly ISmartContractAddressService _smartContractAddressService; - - public new IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - - public byte[] BasicFunctionWithParallelContractCode => - Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("BasicFunctionWithParallel")).Value; - - public static Address BasicFunctionWithParallelContractAddress { get; private set; } - public readonly string PrimaryTokenSymbol = "ELF"; - - public ParallelTestHelper(IOsBlockchainNodeContextService osBlockchainNodeContextService, - IAccountService accountService, - IMinerService minerService, - IBlockchainService blockchainService, - ISmartContractAddressService smartContractAddressService, - IBlockAttachService blockAttachService, - IStaticChainInformationProvider staticChainInformationProvider, - ITransactionResultService transactionResultService, - IOptionsSnapshot chainOptions, - ITransactionReadOnlyExecutionService transactionReadOnlyExecutionService, - ITransactionPoolService transactionPoolService - ) : base(osBlockchainNodeContextService, accountService, - minerService, blockchainService, smartContractAddressService, blockAttachService, - staticChainInformationProvider, transactionResultService, chainOptions,transactionPoolService) - { - _accountService = accountService; - _staticChainInformationProvider = staticChainInformationProvider; - _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; - _smartContractAddressService = smartContractAddressService; + _accountService = accountService; + _staticChainInformationProvider = staticChainInformationProvider; + _transactionReadOnlyExecutionService = transactionReadOnlyExecutionService; + _smartContractAddressService = smartContractAddressService; + } - } + public new IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - public override Block GenerateBlock(Hash preBlockHash, long preBlockHeight, IEnumerable transactions = null) + public byte[] BasicFunctionWithParallelContractCode => + Codes.Single(kv => kv.Key.Split(",").First().Trim().EndsWith("BasicFunctionWithParallel")).Value; + + public static Address BasicFunctionWithParallelContractAddress { get; private set; } + + public override Block GenerateBlock(Hash preBlockHash, long preBlockHeight, + IEnumerable transactions = null) + { + var block = new Block { - var block = new Block + Header = new BlockHeader { - Header = new BlockHeader - { - ChainId = _staticChainInformationProvider.ChainId, - Height = preBlockHeight + 1, - PreviousBlockHash = preBlockHash, - Time = TimestampHelper.GetUtcNow(), - SignerPubkey = ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)) - }, - Body = new BlockBody() - }; - if (transactions != null) - { - foreach (var transaction in transactions) - { - block.AddTransaction(transaction); - } - } + ChainId = _staticChainInformationProvider.ChainId, + Height = preBlockHeight + 1, + PreviousBlockHash = preBlockHash, + Time = TimestampHelper.GetUtcNow(), + SignerPubkey = ByteString.CopyFrom(AsyncHelper.RunSync(_accountService.GetPublicKeyAsync)) + }, + Body = new BlockBody() + }; + if (transactions != null) + foreach (var transaction in transactions) + block.AddTransaction(transaction); + + return block; + } - return block; - } + public async Task DeployBasicFunctionWithParallelContract() + { + BasicFunctionWithParallelContractAddress = await DeployContract(); + } - public async Task DeployBasicFunctionWithParallelContract() - { - BasicFunctionWithParallelContractAddress = await DeployContract(); - } - - public List GenerateBasicFunctionWithParallelTransactions(List groupUsers, int transactionCount) - { - var transactions = new List(); + public List GenerateBasicFunctionWithParallelTransactions(List groupUsers, + int transactionCount) + { + var transactions = new List(); - var groupCount = groupUsers.Count; - for (var i = 0; i < groupCount; i++) + var groupCount = groupUsers.Count; + for (var i = 0; i < groupCount; i++) + { + var keyPair = groupUsers[i]; + var from = Address.FromPublicKey(keyPair.PublicKey); + var count = transactionCount / groupCount; + for (var j = 0; j < count; j++) { - var keyPair = groupUsers[i]; - var from = Address.FromPublicKey(keyPair.PublicKey); - var count = transactionCount / groupCount; - for (var j = 0; j < count; j++) - { - var address = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey); - var transaction = GenerateTransaction(from, - BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub - .IncreaseWinMoney), - new IncreaseWinMoneyInput {First = from, Second = address}); - var signature = - CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactions.Add(transaction); - } + var address = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey); + var transaction = GenerateTransaction(from, + BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContractContainer.BasicFunctionWithParallelContractStub + .IncreaseWinMoney), + new IncreaseWinMoneyInput { First = from, Second = address }); + var signature = + CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + transactions.Add(transaction); } - - return transactions; } - - public async Task> GenerateTransferFromTransactionsWithoutConflictWithMultiSenderAsync(List keyPairs, int count = 1) + + return transactions; + } + + public async Task> GenerateTransferFromTransactionsWithoutConflictWithMultiSenderAsync( + List keyPairs, int count = 1) + { + var transactions = new List(); + foreach (var keyPair in keyPairs) { - var transactions = new List(); - foreach (var keyPair in keyPairs) + var from = Address.FromPublicKey(keyPair.PublicKey); + for (var i = 0; i < count; i++) { - var from = Address.FromPublicKey(keyPair.PublicKey); - for (var i = 0; i < count; i++) - { - var to = CryptoHelper.GenerateKeyPair(); - var transaction = GenerateTransaction(from, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.TransferFrom), - new TransferFromInput - {From = from, To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF"}); - var signature = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactions.Add(transaction); - } + var to = CryptoHelper.GenerateKeyPair(); + var transaction = GenerateTransaction(from, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.TransferFrom), + new TransferFromInput + { From = from, To = Address.FromPublicKey(to.PublicKey), Amount = 1, Symbol = "ELF" }); + var signature = + CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + transactions.Add(transaction); } - - return transactions; } - public async Task ExecuteReadOnlyAsync(Transaction transaction, Hash blockHash,long blockHeight) - { - var transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext - { - BlockHash = blockHash, - BlockHeight = blockHeight - }, - transaction, - DateTime.UtcNow.ToTimestamp()); - - return transactionTrace.ReturnValue; - } + return transactions; + } - public async Task QueryBalanceAsync(Address address,string symbol,Hash blockHash,long blockHeight) - { - var accountAddress = await _accountService.GetAccountAsync(); - var transaction = GenerateTransaction(accountAddress, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.GetBalance), - new GetBalanceInput {Owner = address, Symbol = symbol}); - var returnValue = await ExecuteReadOnlyAsync(transaction, blockHash, blockHeight); - return GetBalanceOutput.Parser.ParseFrom(returnValue).Balance; - } + public async Task ExecuteReadOnlyAsync(Transaction transaction, Hash blockHash, long blockHeight) + { + var transactionTrace = await _transactionReadOnlyExecutionService.ExecuteAsync(new ChainContext + { + BlockHash = blockHash, + BlockHeight = blockHeight + }, + transaction, + DateTime.UtcNow.ToTimestamp()); - public async Task CreateAndIssueTokenAsync(string symbol,Address issueAddress) - { - var ownAddress = await _accountService.GetAccountAsync(); - var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var createTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Create), - new CreateInput - { - Symbol = symbol, - TokenName = $"{symbol}_Token", - TotalSupply = TokenTotalSupply, - Decimals = 2, - Issuer = ownAddress, - IsBurnable = true - }); - var signature = await _accountService.SignAsync(createTokenTransaction.GetHash().ToByteArray()); - createTokenTransaction.Signature = ByteString.CopyFrom(signature); - await BroadcastTransactions(new List {createTokenTransaction}); - await MinedOneBlock(); - - var issueTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput - { - Symbol = symbol, - Amount = TokenTotalSupply, - To = issueAddress, - Memo = "Issue" - }); - signature = await _accountService.SignAsync(issueTokenTransaction.GetHash().ToByteArray()); - issueTokenTransaction.Signature = ByteString.CopyFrom(signature); - await BroadcastTransactions(new List {issueTokenTransaction}); - await MinedOneBlock(); - } - - public async Task GenerateTransferTransactionAsync(ECKeyPair fromKeyPair, Address to ,string symbol, long amount) - { - var transaction = GenerateTransaction(Address.FromPublicKey(fromKeyPair.PublicKey), - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.Transfer), - new TransferInput {To = to, Amount = amount, Symbol = symbol}); + return transactionTrace.ReturnValue; + } - var signature = - CryptoHelper.SignWithPrivateKey(fromKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); + public async Task QueryBalanceAsync(Address address, string symbol, Hash blockHash, long blockHeight) + { + var accountAddress = await _accountService.GetAccountAsync(); + var transaction = GenerateTransaction(accountAddress, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.GetBalance), + new GetBalanceInput { Owner = address, Symbol = symbol }); + var returnValue = await ExecuteReadOnlyAsync(transaction, blockHash, blockHeight); + return GetBalanceOutput.Parser.ParseFrom(returnValue).Balance; + } - return transaction; - } - - public async Task GenerateTransferTransaction(Address to ,string symbol, long amount) - { - var fromAddress = await _accountService.GetAccountAsync(); - var transaction = GenerateTransaction(fromAddress, - await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.Transfer), - new TransferInput {To = to, Amount = amount, Symbol = symbol}); + public async Task CreateAndIssueTokenAsync(string symbol, Address issueAddress) + { + var ownAddress = await _accountService.GetAccountAsync(); + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var createTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Create), + new CreateInput + { + Symbol = symbol, + TokenName = $"{symbol}_Token", + TotalSupply = TokenTotalSupply, + Decimals = 2, + Issuer = ownAddress, + IsBurnable = true + }); + var signature = await _accountService.SignAsync(createTokenTransaction.GetHash().ToByteArray()); + createTokenTransaction.Signature = ByteString.CopyFrom(signature); + await BroadcastTransactions(new List { createTokenTransaction }); + await MinedOneBlock(); + + var issueTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput + { + Symbol = symbol, + Amount = TokenTotalSupply, + To = issueAddress, + Memo = "Issue" + }); + signature = await _accountService.SignAsync(issueTokenTransaction.GetHash().ToByteArray()); + issueTokenTransaction.Signature = ByteString.CopyFrom(signature); + await BroadcastTransactions(new List { issueTokenTransaction }); + await MinedOneBlock(); + } - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); + public async Task GenerateTransferTransactionAsync(ECKeyPair fromKeyPair, Address to, string symbol, + long amount) + { + var transaction = GenerateTransaction(Address.FromPublicKey(fromKeyPair.PublicKey), + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.Transfer), + new TransferInput { To = to, Amount = amount, Symbol = symbol }); - return transaction; - } + var signature = + CryptoHelper.SignWithPrivateKey(fromKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + return transaction; + } + + public async Task GenerateTransferTransaction(Address to, string symbol, long amount) + { + var fromAddress = await _accountService.GetAccountAsync(); + var transaction = GenerateTransaction(fromAddress, + await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.Transfer), + new TransferInput { To = to, Amount = amount, Symbol = symbol }); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + return transaction; } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/ParallelTestWithoutFeeAElfModule.cs b/test/AElf.Parallel.Tests/ParallelTestWithoutFeeAElfModule.cs index 73618a6637..97ca109e18 100644 --- a/test/AElf.Parallel.Tests/ParallelTestWithoutFeeAElfModule.cs +++ b/test/AElf.Parallel.Tests/ParallelTestWithoutFeeAElfModule.cs @@ -1,7 +1,6 @@ -using AElf.Kernel.SmartContract.Application; using System.Collections.Generic; using AElf.Kernel; -using AElf.Kernel.SmartContract; +using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.Parallel; using AElf.Kernel.SmartContract.Parallel.Application; using AElf.Modularity; @@ -12,32 +11,31 @@ using Volo.Abp.Modularity; using Volo.Abp.Threading; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +[DependsOn( + typeof(OSCoreWithChainTestAElfModule), + typeof(ParallelExecutionModule) +)] +public class ParallelTestWithoutFeeAElfModule : AElfModule { - [DependsOn( - typeof(OSCoreWithChainTestAElfModule), - typeof(ParallelExecutionModule) - )] - public class ParallelTestWithoutFeeAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - base.ConfigureServices(context); - context.Services.AddSingleton(); - context.Services.RemoveAll(); - context.Services.AddSingleton(); - context.Services.AddSingleton(); - } + base.ConfigureServices(context); + context.Services.AddSingleton(); + context.Services.RemoveAll(); + context.Services.AddSingleton(); + context.Services.AddSingleton(); + } - public override void PostConfigureServices(ServiceConfigurationContext context) - { - context.Services.RemoveAll(s=>s.ImplementationType == typeof(NewIrreversibleBlockFoundEventHandler)); - } + public override void PostConfigureServices(ServiceConfigurationContext context) + { + context.Services.RemoveAll(s => s.ImplementationType == typeof(NewIrreversibleBlockFoundEventHandler)); + } - public override void OnApplicationInitialization(ApplicationInitializationContext context) - { - var parallelTestHelper = context.ServiceProvider.GetService(); - AsyncHelper.RunSync(() => parallelTestHelper.DeployBasicFunctionWithParallelContract()); - } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var parallelTestHelper = context.ServiceProvider.GetService(); + AsyncHelper.RunSync(() => parallelTestHelper.DeployBasicFunctionWithParallelContract()); } } \ No newline at end of file diff --git a/test/AElf.Parallel.Tests/ParallelTests.cs b/test/AElf.Parallel.Tests/ParallelTests.cs index 8f926a0d0c..b0dbbd5e5a 100644 --- a/test/AElf.Parallel.Tests/ParallelTests.cs +++ b/test/AElf.Parallel.Tests/ParallelTests.cs @@ -25,554 +25,565 @@ using Volo.Abp.EventBus.Local; using Xunit; -namespace AElf.Parallel.Tests +namespace AElf.Parallel.Tests; + +public sealed class ParallelTests : AElfIntegratedTest { - public sealed class ParallelTests : AElfIntegratedTest + private readonly IAccountService _accountService; + private readonly IBlockAttachService _blockAttachService; + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateManager _blockchainStateManager; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockExecutingService _blockExecutingService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly ITransactionGrouper _grouper; + private readonly ILocalEventBus _localEventBus; + private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; + private readonly ParallelTestHelper _parallelTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionResultManager _transactionResultManager; + private readonly ITxHub _txHub; + private readonly IStateStore _versionedStates; + + private readonly int _groupCount = 10; + private readonly int _transactionCount = 20; + + public ParallelTests() + { + _blockchainService = GetRequiredService(); + _blockExecutingService = GetRequiredService(); + _transactionResultManager = GetRequiredService(); + _grouper = GetRequiredService(); + _blockchainStateService = GetRequiredService(); + _txHub = GetRequiredService(); + _blockAttachService = GetRequiredService(); + _accountService = GetRequiredService(); + _parallelTestHelper = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _blockchainStateManager = GetRequiredService(); + _versionedStates = GetRequiredService>(); + _nonparallelContractCodeProvider = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _localEventBus = GetRequiredService(); + } + + [Fact] + public async Task TokenTransferParallelTest() { - private readonly IBlockExecutingService _blockExecutingService; - private readonly IBlockchainService _blockchainService; - private readonly ITransactionResultManager _transactionResultManager; - private readonly ITransactionGrouper _grouper; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockchainStateManager _blockchainStateManager; - private readonly ITxHub _txHub; - private readonly IBlockAttachService _blockAttachService; - private readonly IAccountService _accountService; - private readonly ParallelTestHelper _parallelTestHelper; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly IStateStore _versionedStates; - private readonly INonparallelContractCodeProvider _nonparallelContractCodeProvider; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly ILocalEventBus _localEventBus; - - private int _groupCount = 10; - private int _transactionCount = 20; - - public ParallelTests() + var chain = await _blockchainService.GetChainAsync(); + var tokenAmount = _transactionCount / _groupCount; + var (prepareTransactions, keyPairs) = + await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000000000); + await _parallelTestHelper.BroadcastTransactions(prepareTransactions); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + prepareTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions)).Block; + + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + var cancellableTransactions = + await _parallelTestHelper.GenerateTransactionsWithoutConflictAsync(keyPairs, tokenAmount); + var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); + await _parallelTestHelper.BroadcastTransactions(allTransaction); + + var groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + cancellableTransactions, CancellationToken.None)).Block; + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var chainContext = new ChainContext { - _blockchainService = GetRequiredService(); - _blockExecutingService = GetRequiredService(); - _transactionResultManager = GetRequiredService(); - _grouper = GetRequiredService(); - _blockchainStateService = GetRequiredService(); - _txHub = GetRequiredService(); - _blockAttachService = GetRequiredService(); - _accountService = GetRequiredService(); - _parallelTestHelper = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _blockchainStateManager = GetRequiredService(); - _versionedStates = GetRequiredService>(); - _nonparallelContractCodeProvider = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _localEventBus = GetRequiredService(); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + var nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, + tokenContractAddress); + nonparallelContractCode.ShouldBeNull(); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block.TransactionIds.Count().ShouldBe(allTransaction.Count); + } - [Fact] - public async Task TokenTransferParallelTest() + [Fact] + public async Task TokenTransferFromParallelTest() + { + var chain = await _blockchainService.GetChainAsync(); + var tokenAmount = _transactionCount / _groupCount; + var (prepareTransactions, keyPairs) = + await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000000000); + await _parallelTestHelper.BroadcastTransactions(prepareTransactions); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, + prepareTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions)).Block; + + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactions = await _parallelTestHelper.GenerateApproveTransactions(keyPairs, 1000000000); + await _parallelTestHelper.BroadcastTransactions(transactions); + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + var cancellableTransactions = + await _parallelTestHelper.GenerateTransferFromTransactionsWithoutConflict(keyPairs, tokenAmount); + await _parallelTestHelper.BroadcastTransactions(systemTransactions.Concat(cancellableTransactions)); + + var groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, + systemTransactions.Concat(cancellableTransactions)); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + cancellableTransactions, CancellationToken.None)).Block; + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var chainContext = new ChainContext { - var chain = await _blockchainService.GetChainAsync(); - var tokenAmount = _transactionCount / _groupCount; - var (prepareTransactions, keyPairs) = - await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000000000); - await _parallelTestHelper.BroadcastTransactions(prepareTransactions); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - prepareTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions)).Block; - - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - var cancellableTransactions = - await _parallelTestHelper.GenerateTransactionsWithoutConflictAsync(keyPairs, tokenAmount); - var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); - await _parallelTestHelper.BroadcastTransactions(allTransaction); - - var groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - cancellableTransactions, CancellationToken.None)).Block; - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var chainContext = new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }; - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName); - var nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, - tokenContractAddress); - nonparallelContractCode.ShouldBeNull(); - - groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block.TransactionIds.Count().ShouldBe(allTransaction.Count); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + var nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, tokenContractAddress); + nonparallelContractCode.ShouldBeNull(); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block.TransactionIds.Count().ShouldBe(systemTransactions.Count + cancellableTransactions.Count); + + systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + cancellableTransactions = + await _parallelTestHelper.GenerateTransferFromTransactionsWithoutConflictWithMultiSenderAsync(keyPairs, + tokenAmount); + await _parallelTestHelper.BroadcastTransactions(systemTransactions.Concat(cancellableTransactions)); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, + systemTransactions.Concat(cancellableTransactions)); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + cancellableTransactions, CancellationToken.None)).Block; + + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + tokenContractAddress); + nonparallelContractCode.ShouldBeNull(); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block.TransactionIds.Count().ShouldBe(systemTransactions.Count + cancellableTransactions.Count); + } + + [Fact] + public async Task TransferTwoSymbolParallelTest() + { + var symbol = "TELF"; + var keyPair = CryptoHelper.GenerateKeyPair(); + var address = Address.FromPublicKey(keyPair.PublicKey); + await _parallelTestHelper.CreateAndIssueTokenAsync(symbol, address); + + var transactionList = new List(); + var accountAddress = await _accountService.GetAccountAsync(); + + var transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(address, + _parallelTestHelper.PrimaryTokenSymbol, + 100_00000000); + transactionList.Add(transferTransaction); + await _parallelTestHelper.BroadcastTransactions(transactionList); + var block = await _parallelTestHelper.MinedOneBlock(); + + var nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, transferTransaction.To); + nonparallelContractCode.ShouldBeNull(); + + transactionList.Clear(); + transferTransaction = + await _parallelTestHelper.GenerateTransferTransactionAsync(keyPair, accountAddress, symbol, 10); + transactionList.Add(transferTransaction); + transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(address, + _parallelTestHelper.PrimaryTokenSymbol, 10); + transactionList.Add(transferTransaction); + await _parallelTestHelper.BroadcastTransactions(transactionList); + + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactionList); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactionList)).Block; + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.Count.ShouldBe(2); + transactionResults.Count(t => t.Status == TransactionResultStatus.Mined).ShouldBe(2); + + nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, transferTransaction.To); + nonparallelContractCode.ShouldBeNull(); + } - [Fact] - public async Task TokenTransferFromParallelTest() + [Fact] + public async Task WrongParallelTest() + { + var chain = await _blockchainService.GetChainAsync(); + await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); + + //prepare token for tx verify + var (tokenTransactions, groupUsers) = + await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000_00000000); + await _parallelTestHelper.BroadcastTransactions(tokenTransactions); + var prepareBlock = + _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, tokenTransactions); + prepareBlock = + (await _blockExecutingService.ExecuteBlockAsync(prepareBlock.Header, + tokenTransactions)).Block; + await _blockchainService.AddBlockAsync(prepareBlock); + await _blockAttachService.AttachBlockAsync(prepareBlock); + + chain = await _blockchainService.GetChainAsync(); + + var transactions = + _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount); + var transferTransaction = await _parallelTestHelper.GenerateTransferTransaction( + Address.FromPublicKey(groupUsers[1].PublicKey) + , "ELF", 10); + transactions.Add(transferTransaction); + await _parallelTestHelper.BroadcastTransactions(transactions); + + var otherTransactions = + _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount); + var otherTransferTransaction = await _parallelTestHelper.GenerateTransferTransaction( + Address.FromPublicKey(groupUsers[2].PublicKey) + , "ELF", 10); + otherTransactions.Add(otherTransferTransaction); + await _parallelTestHelper.BroadcastTransactions(otherTransactions); + + var transferTransactions = await _parallelTestHelper.GenerateTransferTransactions(16); + await _parallelTestHelper.BroadcastTransactions(transferTransactions); + + var poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount; + poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count); + + var groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight }, + transactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + for (var i = 0; i < transactions.Count; i++) + transactions[i].GetHash().ShouldBe(groupedTransactions.Parallelizables[i][0].GetHash()); + + var otherGroupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight }, + otherTransactions); + otherGroupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1); + otherGroupedTransactions.NonParallelizables.Count.ShouldBe(0); + + var groupedTransferTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight }, + transferTransactions); + groupedTransferTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count); + groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0); + + _localEventBus.Subscribe(e => { - var chain = await _blockchainService.GetChainAsync(); - var tokenAmount = _transactionCount / _groupCount; - var (prepareTransactions, keyPairs) = - await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000000000); - await _parallelTestHelper.BroadcastTransactions(prepareTransactions); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, - prepareTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions)).Block; - - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var transactions = await _parallelTestHelper.GenerateApproveTransactions(keyPairs, 1000000000); - await _parallelTestHelper.BroadcastTransactions(transactions); - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - var cancellableTransactions = - await _parallelTestHelper.GenerateTransferFromTransactionsWithoutConflict(keyPairs, tokenAmount); - await _parallelTestHelper.BroadcastTransactions(systemTransactions.Concat(cancellableTransactions)); - - var groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, - systemTransactions.Concat(cancellableTransactions)); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - cancellableTransactions, CancellationToken.None)).Block; - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var chainContext = new ChainContext + e.ConflictingSets.Count.ShouldBe(_groupCount + 1); + e.ExistingSets.Count.ShouldBe(_groupCount); + return Task.CompletedTask; + }); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; + block.TransactionIds.Count().ShouldBe(_transactionCount + 1); + + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + transactionResults.Count(t => t.Status == TransactionResultStatus.Mined).ShouldBe(_groupCount); + transactionResults.Count(t => t.Status == TransactionResultStatus.Conflict).ShouldBe(_groupCount + 1); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + var accountAddress = await _accountService.GetAccountAsync(); + + var chainContext = new ChainContext + { + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + var nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, + tokenContractAddress); + nonparallelContractCode.ShouldBeNull(); + + foreach (var transaction in transactions) + { + if (transaction.To == tokenContractAddress) continue; + var param = IncreaseWinMoneyInput.Parser.ParseFrom(transaction.Params); + var input = new QueryTwoUserWinMoneyInput { - BlockHash = block.GetHash(), - BlockHeight = block.Height + First = param.First, + Second = param.Second }; - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName); - var nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, tokenContractAddress); - nonparallelContractCode.ShouldBeNull(); - - groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block.TransactionIds.Count().ShouldBe(systemTransactions.Count + cancellableTransactions.Count); - - systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - cancellableTransactions = - await _parallelTestHelper.GenerateTransferFromTransactionsWithoutConflictWithMultiSenderAsync(keyPairs, - tokenAmount); - await _parallelTestHelper.BroadcastTransactions(systemTransactions.Concat(cancellableTransactions)); - - groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, - systemTransactions.Concat(cancellableTransactions)); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - cancellableTransactions, CancellationToken.None)).Block; - - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - tokenContractAddress); - nonparallelContractCode.ShouldBeNull(); - - groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block.TransactionIds.Count().ShouldBe(systemTransactions.Count + cancellableTransactions.Count); - } - - [Fact] - public async Task TransferTwoSymbolParallelTest() - { - var symbol = "TELF"; - var keyPair = CryptoHelper.GenerateKeyPair(); - var address = Address.FromPublicKey(keyPair.PublicKey); - await _parallelTestHelper.CreateAndIssueTokenAsync(symbol, address); - - var transactionList = new List(); - var accountAddress = await _accountService.GetAccountAsync(); - - var transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(address, _parallelTestHelper.PrimaryTokenSymbol, - 100_00000000); - transactionList.Add(transferTransaction); - await _parallelTestHelper.BroadcastTransactions(transactionList); - var block = await _parallelTestHelper.MinedOneBlock(); - - var nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, transferTransaction.To); - nonparallelContractCode.ShouldBeNull(); - - transactionList.Clear(); - transferTransaction = await _parallelTestHelper.GenerateTransferTransactionAsync(keyPair, accountAddress, symbol, 10); - transactionList.Add(transferTransaction); - transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(address, - _parallelTestHelper.PrimaryTokenSymbol, 10); - transactionList.Add(transferTransaction); - await _parallelTestHelper.BroadcastTransactions(transactionList); - - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, transactionList); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactionList)).Block; - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(),block.Header); - transactionResults.Count.ShouldBe(2); - transactionResults.Count(t => t.Status == TransactionResultStatus.Mined).ShouldBe(2); - - nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, transferTransaction.To); - nonparallelContractCode.ShouldBeNull(); + var queryTransaction = _parallelTestHelper.GenerateTransaction(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, + nameof(BasicFunctionWithParallelContract.QueryTwoUserWinMoney), input); + var byteString = + await _parallelTestHelper.ExecuteReadOnlyAsync(queryTransaction, block.GetHash(), block.Height); + var output = TwoUserMoneyOut.Parser.ParseFrom(byteString); + output.FirstInt64Value.ShouldBe(1); + var result = transactionResults.First(t => t.TransactionId == transaction.GetHash()); + if (result.Status == TransactionResultStatus.Mined) + output.SecondInt64Value.ShouldBe(1); + else if (result.Status == TransactionResultStatus.Conflict) output.SecondInt64Value.ShouldBe(0); } - [Fact] - public async Task WrongParallelTest() - { - var chain = await _blockchainService.GetChainAsync(); - await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash); - - //prepare token for tx verify - var (tokenTransactions, groupUsers) = - await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000_00000000); - await _parallelTestHelper.BroadcastTransactions(tokenTransactions); - var prepareBlock = - _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, tokenTransactions); - prepareBlock = - (await _blockExecutingService.ExecuteBlockAsync(prepareBlock.Header, - tokenTransactions)).Block; - await _blockchainService.AddBlockAsync(prepareBlock); - await _blockAttachService.AttachBlockAsync(prepareBlock); - - chain = await _blockchainService.GetChainAsync(); - - var transactions = - _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount); - var transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(Address.FromPublicKey(groupUsers[1].PublicKey) - , "ELF", 10); - transactions.Add(transferTransaction); - await _parallelTestHelper.BroadcastTransactions(transactions); - - var otherTransactions = _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount); - var otherTransferTransaction = await _parallelTestHelper.GenerateTransferTransaction(Address.FromPublicKey(groupUsers[2].PublicKey) - , "ELF", 10); - otherTransactions.Add(otherTransferTransaction); - await _parallelTestHelper.BroadcastTransactions(otherTransactions); - - var transferTransactions = await _parallelTestHelper.GenerateTransferTransactions(16); - await _parallelTestHelper.BroadcastTransactions(transferTransactions); - - var poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount; - poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count); - - var groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight}, - transactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - for (var i = 0; i < transactions.Count; i++) - { - transactions[i].GetHash().ShouldBe(groupedTransactions.Parallelizables[i][0].GetHash()); - } - - var otherGroupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight}, - otherTransactions); - otherGroupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1); - otherGroupedTransactions.NonParallelizables.Count.ShouldBe(0); - - var groupedTransferTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight}, - transferTransactions); - groupedTransferTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count); - groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0); - - _localEventBus.Subscribe(e => - { - e.ConflictingSets.Count.ShouldBe(_groupCount + 1); - e.ExistingSets.Count.ShouldBe(_groupCount); - return Task.CompletedTask; - }); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block; - block.TransactionIds.Count().ShouldBe(_transactionCount + 1); - - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - transactionResults.Count(t=>t.Status == TransactionResultStatus.Mined).ShouldBe(_groupCount); - transactionResults.Count(t => t.Status == TransactionResultStatus.Conflict).ShouldBe(_groupCount + 1); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - var accountAddress = await _accountService.GetAccountAsync(); - - var chainContext = new ChainContext + nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height - }; - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName); - var nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, - tokenContractAddress); - nonparallelContractCode.ShouldBeNull(); - - foreach (var transaction in transactions) - { - if(transaction.To == tokenContractAddress) continue; - var param = IncreaseWinMoneyInput.Parser.ParseFrom(transaction.Params); - var input = new QueryTwoUserWinMoneyInput - { - First = param.First, - Second = param.Second - }; - var queryTransaction = _parallelTestHelper.GenerateTransaction(accountAddress, - ParallelTestHelper.BasicFunctionWithParallelContractAddress, - nameof(BasicFunctionWithParallelContract.QueryTwoUserWinMoney), input); - var byteString = await _parallelTestHelper.ExecuteReadOnlyAsync(queryTransaction, block.GetHash(), block.Height); - var output = TwoUserMoneyOut.Parser.ParseFrom(byteString); - output.FirstInt64Value.ShouldBe(1); - var result = transactionResults.First(t => t.TransactionId == transaction.GetHash()); - if (result.Status ==TransactionResultStatus.Mined) - { - output.SecondInt64Value.ShouldBe(1); - } - else if (result.Status == TransactionResultStatus.Conflict) - { - output.SecondInt64Value.ShouldBe(0); - } - } - - nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); - nonparallelContractCode.CodeHash.ShouldBe(HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode)); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.Changes.Count.ShouldBeGreaterThan(0); - var blockExecutedData = blockStateSet.BlockExecutedData.First(); - var versionedState = await _versionedStates.GetAsync(blockExecutedData.Key); - versionedState.ShouldBeNull(); - - await _blockchainStateService.MergeBlockStateAsync(block.Height, block.GetHash()); - blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - blockStateSet.ShouldBeNull(); - - nonparallelContractCode = - await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext - { - BlockHash = block.GetHash(), - BlockHeight = block.Height - }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); - nonparallelContractCode.CodeHash.ShouldBe(HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode)); - - versionedState = await _versionedStates.GetAsync(blockExecutedData.Key); - versionedState.Key.ShouldBe(blockExecutedData.Key); - versionedState.Value.ShouldBe(blockExecutedData.Value); - - groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - transactions); - - groupedTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress); - groupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount); - - otherGroupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - otherTransactions); - otherGroupedTransactions.Parallelizables.Count.ShouldBe(1); - otherGroupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress); - otherGroupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount); - - groupedTransferTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight}, - transferTransactions); - groupedTransferTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count); - groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0); - - poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount; - - poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count - block.TransactionIds.Count()); - } - - [Fact] - public async Task Parallel_TransactionWithoutContract() - { - var chain = await _blockchainService.GetChainAsync(); - var tokenAmount = _transactionCount / _groupCount; - var accountAddress = await _accountService.GetAccountAsync(); - - var (prepareTransactions, keyPairs) = await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 100000000); - - var transactionWithoutContract = _parallelTestHelper.GenerateTransaction(accountAddress, - SampleAddress.AddressList[0], "Transfer", new Empty()); - var transactionHash = transactionWithoutContract.GetHash(); - var signature = await _accountService.SignAsync(transactionHash.ToByteArray()); - transactionWithoutContract.Signature = ByteString.CopyFrom(signature); - prepareTransactions.Add(transactionWithoutContract); - - var cancellableTransaction = _parallelTestHelper.GenerateTransaction(accountAddress, ParallelTestHelper.BasicFunctionWithParallelContractAddress, "QueryWinMoney", - new Empty()); - signature = await _accountService.SignAsync(cancellableTransaction.GetHash().ToByteArray()); - cancellableTransaction.Signature = ByteString.CopyFrom(signature); - var cancellableTransactions = new List {cancellableTransaction}; - var allTransactions = prepareTransactions.Concat(cancellableTransactions).ToList(); - - await _parallelTestHelper.BroadcastTransactions(allTransactions); - - var groupedTransactions = await _grouper.GroupAsync( - new ChainContext {BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight}, - prepareTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(1); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - groupedTransactions.TransactionsWithoutContract.Count.ShouldBe(1); - var transaction = groupedTransactions.TransactionsWithoutContract[0]; - transaction.GetHash().ShouldBe(transactionHash); - - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions, - cancellableTransactions, CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(allTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var transactionResult = - await _transactionResultManager.GetTransactionResultAsync(transactionHash, - block.Header.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Invalid contract address"); - - var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - cancellableTransactions = await _parallelTestHelper.GenerateTransactionsWithoutConflictAsync(keyPairs, tokenAmount); - - transactionWithoutContract = _parallelTestHelper.GenerateTransaction(accountAddress, - SampleAddress.AddressList[0], "Transfer", new Empty()); - transactionHash = transactionWithoutContract.GetHash(); - signature = await _accountService.SignAsync(transactionHash.ToByteArray()); - transactionWithoutContract.Signature = ByteString.CopyFrom(signature); - cancellableTransactions.Add(transactionWithoutContract); - - var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); - await _parallelTestHelper.BroadcastTransactions(allTransaction); - - groupedTransactions = await _grouper.GroupAsync(new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - groupedTransactions.TransactionsWithoutContract.Count.ShouldBe(1); - transaction = groupedTransactions.TransactionsWithoutContract[0]; - transaction.GetHash().ShouldBe(transactionHash); - - block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - cancellableTransactions, CancellationToken.None)).Block; - await _blockchainService.AddTransactionsAsync(allTransactions); - await _blockchainService.AddBlockAsync(block); - await _blockAttachService.AttachBlockAsync(block); - - var chainContext = new ChainContext + }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); + nonparallelContractCode.CodeHash.ShouldBe( + HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode)); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.Changes.Count.ShouldBeGreaterThan(0); + var blockExecutedData = blockStateSet.BlockExecutedData.First(); + var versionedState = await _versionedStates.GetAsync(blockExecutedData.Key); + versionedState.ShouldBeNull(); + + await _blockchainStateService.MergeBlockStateAsync(block.Height, block.GetHash()); + blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + blockStateSet.ShouldBeNull(); + + nonparallelContractCode = + await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height - }; - var tokenContractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName); - var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( - chainContext, tokenContractAddress); - nonparallelContractCode.ShouldBeNull(); - - groupedTransactions = await _grouper.GroupAsync(new ChainContext {BlockHash = block.GetHash(), BlockHeight = block.Height}, - cancellableTransactions); - groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); - groupedTransactions.NonParallelizables.Count.ShouldBe(0); - - block.TransactionIds.Count().ShouldBe(allTransaction.Count); - block.TransactionIds.ShouldContain(transactionHash); - - transactionResult = - await _transactionResultManager.GetTransactionResultAsync(transactionHash, - block.Header.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.Error.ShouldContain("Invalid contract address"); - } + }, ParallelTestHelper.BasicFunctionWithParallelContractAddress); + nonparallelContractCode.CodeHash.ShouldBe( + HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode)); + + versionedState = await _versionedStates.GetAsync(blockExecutedData.Key); + versionedState.Key.ShouldBe(blockExecutedData.Key); + versionedState.Value.ShouldBe(blockExecutedData.Value); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + transactions); + + groupedTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress); + groupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount); + + otherGroupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + otherTransactions); + otherGroupedTransactions.Parallelizables.Count.ShouldBe(1); + otherGroupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress); + otherGroupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount); + + groupedTransferTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight }, + transferTransactions); + groupedTransferTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count); + groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0); + + poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount; + + poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count - block.TransactionIds.Count()); + } - [Fact] - public async Task Use_Same_Resource_Key_With_SystemTransaction_Test() + [Fact] + public async Task Parallel_TransactionWithoutContract() + { + var chain = await _blockchainService.GetChainAsync(); + var tokenAmount = _transactionCount / _groupCount; + var accountAddress = await _accountService.GetAccountAsync(); + + var (prepareTransactions, keyPairs) = await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 100000000); + + var transactionWithoutContract = _parallelTestHelper.GenerateTransaction(accountAddress, + SampleAddress.AddressList[0], "Transfer", new Empty()); + var transactionHash = transactionWithoutContract.GetHash(); + var signature = await _accountService.SignAsync(transactionHash.ToByteArray()); + transactionWithoutContract.Signature = ByteString.CopyFrom(signature); + prepareTransactions.Add(transactionWithoutContract); + + var cancellableTransaction = _parallelTestHelper.GenerateTransaction(accountAddress, + ParallelTestHelper.BasicFunctionWithParallelContractAddress, "QueryWinMoney", + new Empty()); + signature = await _accountService.SignAsync(cancellableTransaction.GetHash().ToByteArray()); + cancellableTransaction.Signature = ByteString.CopyFrom(signature); + var cancellableTransactions = new List { cancellableTransaction }; + var allTransactions = prepareTransactions.Concat(cancellableTransactions).ToList(); + + await _parallelTestHelper.BroadcastTransactions(allTransactions); + + var groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight }, + prepareTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(1); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + groupedTransactions.TransactionsWithoutContract.Count.ShouldBe(1); + var transaction = groupedTransactions.TransactionsWithoutContract[0]; + transaction.GetHash().ShouldBe(transactionHash); + + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions, + cancellableTransactions, CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(allTransactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var transactionResult = + await _transactionResultManager.GetTransactionResultAsync(transactionHash, + block.Header.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Invalid contract address"); + + var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + cancellableTransactions = + await _parallelTestHelper.GenerateTransactionsWithoutConflictAsync(keyPairs, tokenAmount); + + transactionWithoutContract = _parallelTestHelper.GenerateTransaction(accountAddress, + SampleAddress.AddressList[0], "Transfer", new Empty()); + transactionHash = transactionWithoutContract.GetHash(); + signature = await _accountService.SignAsync(transactionHash.ToByteArray()); + transactionWithoutContract.Signature = ByteString.CopyFrom(signature); + cancellableTransactions.Add(transactionWithoutContract); + + var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); + await _parallelTestHelper.BroadcastTransactions(allTransaction); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + groupedTransactions.TransactionsWithoutContract.Count.ShouldBe(1); + transaction = groupedTransactions.TransactionsWithoutContract[0]; + transaction.GetHash().ShouldBe(transactionHash); + + block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + cancellableTransactions, CancellationToken.None)).Block; + await _blockchainService.AddTransactionsAsync(allTransactions); + await _blockchainService.AddBlockAsync(block); + await _blockAttachService.AttachBlockAsync(block); + + var chainContext = new ChainContext { - var chain = await _blockchainService.GetChainAsync(); - var accountAddress = await _accountService.GetAccountAsync(); - var startBalance = await _parallelTestHelper.QueryBalanceAsync(accountAddress, "ELF", chain.BestChainHash, - chain.BestChainHeight); - var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - var cancellableTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); - var allTransactions = systemTransactions.Concat(cancellableTransactions).ToList(); - await _parallelTestHelper.BroadcastTransactions(allTransactions); - var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, allTransactions); - block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, - cancellableTransactions, CancellationToken.None)).Block; - - var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); - var totalFee = transactionResults - .Select(transactionResult => - transactionResult.Logs.Single(l => l.Name == nameof(TransactionFeeCharged))) - .Select(relatedLog => TransactionFeeCharged.Parser.ParseFrom(relatedLog.NonIndexed)) - .Where(chargedEvent => chargedEvent.Symbol == "ELF").Sum(chargedEvent => chargedEvent.Amount); - var amount = allTransactions.Sum(t => TransferInput.Parser.ParseFrom(t.Params).Amount); - var endBalance = - await _parallelTestHelper.QueryBalanceAsync(accountAddress, "ELF", block.GetHash(), block.Height); - (startBalance - endBalance).ShouldBe(amount + totalFee); - } + BlockHash = block.GetHash(), + BlockHeight = block.Height + }; + var tokenContractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, + TokenSmartContractAddressNameProvider.StringName); + var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync( + chainContext, tokenContractAddress); + nonparallelContractCode.ShouldBeNull(); + + groupedTransactions = await _grouper.GroupAsync( + new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, + cancellableTransactions); + groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); + groupedTransactions.NonParallelizables.Count.ShouldBe(0); + + block.TransactionIds.Count().ShouldBe(allTransaction.Count); + block.TransactionIds.ShouldContain(transactionHash); + + transactionResult = + await _transactionResultManager.GetTransactionResultAsync(transactionHash, + block.Header.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + transactionResult.Error.ShouldContain("Invalid contract address"); + } - private async Task> GetTransactionResultsAsync(List transactionIds,BlockHeader blockHeader) - { - var transactionResults = new List(); - foreach (var transactionId in transactionIds) - { - var result = await _transactionResultManager.GetTransactionResultAsync(transactionId, blockHeader.GetDisambiguatingHash()); - if(result != null) transactionResults.Add(result); - } + [Fact] + public async Task Use_Same_Resource_Key_With_SystemTransaction_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var accountAddress = await _accountService.GetAccountAsync(); + var startBalance = await _parallelTestHelper.QueryBalanceAsync(accountAddress, "ELF", chain.BestChainHash, + chain.BestChainHeight); + var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + var cancellableTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); + var allTransactions = systemTransactions.Concat(cancellableTransactions).ToList(); + await _parallelTestHelper.BroadcastTransactions(allTransactions); + var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, allTransactions); + block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, + cancellableTransactions, CancellationToken.None)).Block; + + var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header); + var totalFee = transactionResults + .Select(transactionResult => + transactionResult.Logs.Single(l => l.Name == nameof(TransactionFeeCharged))) + .Select(relatedLog => TransactionFeeCharged.Parser.ParseFrom(relatedLog.NonIndexed)) + .Where(chargedEvent => chargedEvent.Symbol == "ELF").Sum(chargedEvent => chargedEvent.Amount); + var amount = allTransactions.Sum(t => TransferInput.Parser.ParseFrom(t.Params).Amount); + var endBalance = + await _parallelTestHelper.QueryBalanceAsync(accountAddress, "ELF", block.GetHash(), block.Height); + (startBalance - endBalance).ShouldBe(amount + totalFee); + } - return transactionResults; + private async Task> GetTransactionResultsAsync(List transactionIds, + BlockHeader blockHeader) + { + var transactionResults = new List(); + foreach (var transactionId in transactionIds) + { + var result = + await _transactionResultManager.GetTransactionResultAsync(transactionId, + blockHeader.GetDisambiguatingHash()); + if (result != null) transactionResults.Add(result); } + + return transactionResults; } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Core.Tests/AElf.Runtime.CSharp.Core.Tests.csproj b/test/AElf.Runtime.CSharp.Core.Tests/AElf.Runtime.CSharp.Core.Tests.csproj index 6eaf151081..4708e9b795 100644 --- a/test/AElf.Runtime.CSharp.Core.Tests/AElf.Runtime.CSharp.Core.Tests.csproj +++ b/test/AElf.Runtime.CSharp.Core.Tests/AElf.Runtime.CSharp.Core.Tests.csproj @@ -5,18 +5,18 @@ false - - - - - - + + + + + + - - - - + + + + diff --git a/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestAElfModule.cs b/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestAElfModule.cs index b990681d81..f37cb4cf60 100644 --- a/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestAElfModule.cs +++ b/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestAElfModule.cs @@ -1,13 +1,11 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Runtime.CSharp.Core +namespace AElf.Runtime.CSharp.Core; + +public class CSharpRuntimeCoreTestAElfModule : AElfModule { - public class CSharpRuntimeCoreTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - - } } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestBase.cs b/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestBase.cs index c42b65992b..2d7d71eca1 100644 --- a/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestBase.cs +++ b/test/AElf.Runtime.CSharp.Core.Tests/CSharpRuntimeCoreTestBase.cs @@ -1,9 +1,7 @@ using AElf.TestBase; -namespace AElf.Runtime.CSharp.Core -{ - public class CSharpRuntimeCoreTestBase : AElfIntegratedTest - { +namespace AElf.Runtime.CSharp.Core; - } +public class CSharpRuntimeCoreTestBase : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Core.Tests/ContractCodeLoadContextTests.cs b/test/AElf.Runtime.CSharp.Core.Tests/ContractCodeLoadContextTests.cs index d2b900690d..53b5156374 100644 --- a/test/AElf.Runtime.CSharp.Core.Tests/ContractCodeLoadContextTests.cs +++ b/test/AElf.Runtime.CSharp.Core.Tests/ContractCodeLoadContextTests.cs @@ -5,35 +5,34 @@ using Shouldly; using Xunit; -namespace AElf.Runtime.CSharp.Core +namespace AElf.Runtime.CSharp.Core; + +public class ContractCodeLoadContextTests : CSharpRuntimeCoreTestBase { - public class ContractCodeLoadContextTests : CSharpRuntimeCoreTestBase + [Fact] + public void Load_Test() { - [Fact] - public void Load_Test() - { - var sdkDir = Path.GetDirectoryName(typeof(SdkStreamManager).Assembly.Location); - var sdkStreamManager = new SdkStreamManager(sdkDir); - var loader = new ContractCodeLoadContext(sdkStreamManager); - - var code = File.ReadAllBytes(typeof(TestContract).Assembly.Location); - using (var stream = new MemoryStream(code)) - { - var assembly = loader.LoadFromStream(stream); - Activator.CreateInstance(assembly.GetType("AElf.Runtime.CSharp.Tests.TestContract.TestContract")); + var sdkDir = Path.GetDirectoryName(typeof(SdkStreamManager).Assembly.Location); + var sdkStreamManager = new SdkStreamManager(sdkDir); + var loader = new ContractCodeLoadContext(sdkStreamManager); - assembly.FullName.ShouldBe( - "AElf.Runtime.CSharp.Tests.TestContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); + var code = File.ReadAllBytes(typeof(TestContract).Assembly.Location); + using (var stream = new MemoryStream(code)) + { + var assembly = loader.LoadFromStream(stream); + Activator.CreateInstance(assembly.GetType("AElf.Runtime.CSharp.Tests.TestContract.TestContract")); - loader.Assemblies.Count().ShouldBe(2); - loader.Assemblies.ShouldContain(a => - a.FullName == - "AElf.Runtime.CSharp.Tests.TestContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); - loader.Assemblies.ShouldContain(a => - a.FullName == "AElf.Sdk.CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); - } + assembly.FullName.ShouldBe( + "AElf.Runtime.CSharp.Tests.TestContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); - loader.Unload(); + loader.Assemblies.Count().ShouldBe(2); + loader.Assemblies.ShouldContain(a => + a.FullName == + "AElf.Runtime.CSharp.Tests.TestContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); + loader.Assemblies.ShouldContain(a => + a.FullName == "AElf.Sdk.CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); } + + loader.Unload(); } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Core.Tests/SdkStreamManagerTests.cs b/test/AElf.Runtime.CSharp.Core.Tests/SdkStreamManagerTests.cs index 5268098d17..70ed2db522 100644 --- a/test/AElf.Runtime.CSharp.Core.Tests/SdkStreamManagerTests.cs +++ b/test/AElf.Runtime.CSharp.Core.Tests/SdkStreamManagerTests.cs @@ -1,68 +1,64 @@ -using System; using System.IO; using System.Reflection; using System.Runtime.Loader; using Shouldly; using Xunit; -namespace AElf.Runtime.CSharp.Core +namespace AElf.Runtime.CSharp.Core; + +public class SdkStreamManagerTests : CSharpRuntimeCoreTestBase { - public class SdkStreamManagerTests : CSharpRuntimeCoreTestBase + [Fact] + public void GetStream_SdkPathExist_Test() { - - [Fact] - public void GetStream_SdkPathExist_Test() - { - var sdkDir = Path.GetDirectoryName(typeof(SdkStreamManager).Assembly.Location); - var sdkStreamManager = new SdkStreamManager(sdkDir); - var assemblyName = new AssemblyName("AElf.Runtime.CSharp.Core"); - - using (var stream = sdkStreamManager.GetStream(assemblyName)) - { - CheckGetStreamResult(stream); - } + var sdkDir = Path.GetDirectoryName(typeof(SdkStreamManager).Assembly.Location); + var sdkStreamManager = new SdkStreamManager(sdkDir); + var assemblyName = new AssemblyName("AElf.Runtime.CSharp.Core"); - // Get stream from cache - using (var stream = sdkStreamManager.GetStream(assemblyName)) - { - CheckGetStreamResult(stream); - } - } - - [Fact] - public void GetStream_SdkPathNotExist_Test() + using (var stream = sdkStreamManager.GetStream(assemblyName)) { - var sdkStreamManager = new SdkStreamManager("/NotExist/"); - var assemblyName = new AssemblyName("AElf.Runtime.CSharp.Core"); - - using (var stream = sdkStreamManager.GetStream(assemblyName)) - { - CheckGetStreamResult(stream); - } + CheckGetStreamResult(stream); + } - // Get stream from cache - using (var stream = sdkStreamManager.GetStream(assemblyName)) - { - CheckGetStreamResult(stream); - } + // Get stream from cache + using (var stream = sdkStreamManager.GetStream(assemblyName)) + { + CheckGetStreamResult(stream); } + } + + [Fact] + public void GetStream_SdkPathNotExist_Test() + { + var sdkStreamManager = new SdkStreamManager("/NotExist/"); + var assemblyName = new AssemblyName("AElf.Runtime.CSharp.Core"); - [Fact] - public void ExceptionTest() + using (var stream = sdkStreamManager.GetStream(assemblyName)) { - var message = "message"; - Should.Throw(() => throw new InvalidMethodNameException()); - Should.Throw(() => throw new InvalidMethodNameException(message)); - Should.Throw(() => throw new RuntimeException()); - Should.Throw(() => throw new RuntimeException(message)); - + CheckGetStreamResult(stream); } - private void CheckGetStreamResult(Stream stream) + // Get stream from cache + using (var stream = sdkStreamManager.GetStream(assemblyName)) { - var loader = new AssemblyLoadContext(null); - var assembly = loader.LoadFromStream(stream); - assembly.FullName.ShouldBe("AElf.Runtime.CSharp.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); + CheckGetStreamResult(stream); } } + + [Fact] + public void ExceptionTest() + { + var message = "message"; + Should.Throw(() => throw new InvalidMethodNameException()); + Should.Throw(() => throw new InvalidMethodNameException(message)); + Should.Throw(() => throw new RuntimeException()); + Should.Throw(() => throw new RuntimeException(message)); + } + + private void CheckGetStreamResult(Stream stream) + { + var loader = new AssemblyLoadContext(null); + var assembly = loader.LoadFromStream(stream); + assembly.FullName.ShouldBe("AElf.Runtime.CSharp.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); + } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/AElf.Runtime.CSharp.Tests.BadContract.csproj b/test/AElf.Runtime.CSharp.Tests.BadContract/AElf.Runtime.CSharp.Tests.BadContract.csproj index 6ee7efed25..f38e72b499 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/AElf.Runtime.CSharp.Tests.BadContract.csproj +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/AElf.Runtime.CSharp.Tests.BadContract.csproj @@ -8,8 +8,8 @@ true - - + + diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/BadCases.cs b/test/AElf.Runtime.CSharp.Tests.BadContract/BadCases.cs index 6f423fafee..c32a634a04 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/BadCases.cs +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/BadCases.cs @@ -1,60 +1,53 @@ using System; using System.Collections.ObjectModel; -using System.Linq; using Google.Protobuf.Reflection; -namespace AElf.Runtime.CSharp.Tests.BadContract +namespace AElf.Runtime.CSharp.Tests.BadContract; + +public class BadCase1 { - public class BadCase1 + public static FileDescriptor Descriptor { get; private set; } + + public void SetFileDescriptor() { - public static FileDescriptor Descriptor - { - get { return descriptor; } - } + Descriptor = null; + } +} - private static FileDescriptor descriptor; +public class BadCase2 +{ + public static int Number = 1; + public int I; +} - public void SetFileDescriptor() - { - descriptor = null; - } - } +public class BadCase3 +{ + public static readonly BadCase2 field; +} - public class BadCase2 - { - public int I; - public static int Number = 1; - } +// Similar to Linq generated class but with instance field I, should not be allowed +public class BadCase4 +{ + public static readonly BadCase4 field; - public class BadCase3 - { - public static readonly BadCase2 field; - } - - // Similar to Linq generated class but with instance field I, should not be allowed - public class BadCase4 - { - public static readonly BadCase4 field; + public int I; +} - public int I; - } +public static class BadCase5 +{ + private static readonly ReadOnlyCollection collection; - public static class BadCase5 + static BadCase5() { - static readonly ReadOnlyCollection collection; - - static BadCase5() - { - collection = Array.AsReadOnly(new[] { new BadCase3() }); - } + collection = Array.AsReadOnly(new[] { new BadCase3() }); } +} - public class BadCase6 +public class BadCase6 +{ + public BadCase6() { - public BadCase6() - { - var array = new int[0][]; // multi dim array - int length = array.Length; - } + var array = new int[0][]; // multi dim array + var length = array.Length; } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/BadContract.cs b/test/AElf.Runtime.CSharp.Tests.BadContract/BadContract.cs index 1fdc214298..3d75521d68 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/BadContract.cs +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/BadContract.cs @@ -1,204 +1,195 @@ using System; -using System.Collections.Generic; using System.IO; -using AElf.Sdk.CSharp; using Google.Protobuf; using Google.Protobuf.Reflection; using Google.Protobuf.WellKnownTypes; -namespace AElf.Runtime.CSharp.Tests.BadContract +namespace AElf.Runtime.CSharp.Tests.BadContract; + +public class BadContract : BadContractContainer.BadContractBase { - public class BadContract : BadContractContainer.BadContractBase + private static BadCase1 staticNotAllowedTypeField; + private static int staticAllowedTypeField; + private int i = 1; + + public override Empty UpdateDoubleState(DoubleInput input) { - int i = 1; - private static BadCase1 staticNotAllowedTypeField; - private static int staticAllowedTypeField; - - public override Empty UpdateDoubleState(DoubleInput input) - { - State.Double.Value = input.DoubleValue; + State.Double.Value = input.DoubleValue; - return new Empty(); - } + return new Empty(); + } - public override Empty UpdateFloatState(FloatInput input) - { - State.Float.Value = input.FloatValue; - - return new Empty(); - } + public override Empty UpdateFloatState(FloatInput input) + { + State.Float.Value = input.FloatValue; - public override RandomOutput UpdateStateWithRandom(Empty input) - { - var random = new Random().Next(); - - State.CurrentRandom.Value = random; - - return new RandomOutput() - { - RandomValue = random - }; - } + return new Empty(); + } + + public override RandomOutput UpdateStateWithRandom(Empty input) + { + var random = new Random().Next(); + + State.CurrentRandom.Value = random; - public override DateTimeOutput UpdateStateWithCurrentTime(Empty input) + return new RandomOutput { - var current = DateTime.Now; + RandomValue = random + }; + } - State.CurrentTime.Value = current; + public override DateTimeOutput UpdateStateWithCurrentTime(Empty input) + { + var current = DateTime.Now; - State.CurrentTimeUtc.Value = DateTime.UtcNow; + State.CurrentTime.Value = current; - State.CurrentTimeToday.Value = DateTime.Today; + State.CurrentTimeUtc.Value = DateTime.UtcNow; - return new DateTimeOutput() - { - DateTimeValue = Timestamp.FromDateTime(current) - }; - } + State.CurrentTimeToday.Value = DateTime.Today; - public override Empty WriteFileToNode(FileInfoInput input) + return new DateTimeOutput { - using (var writer = new StreamWriter(input.FilePath)) - { - writer.Write(input.FileContent); - } - - return new Empty(); - } + DateTimeValue = Timestamp.FromDateTime(current) + }; + } - public override Empty InitLargeArray(Empty input) + public override Empty WriteFileToNode(FileInfoInput input) + { + using (var writer = new StreamWriter(input.FilePath)) { - var arr = new int[1024 * 1024 * 1024]; // + writer.Write(input.FileContent); + } - for (var i = 0; i < arr.Length; i++) - { - arr[i] = int.MaxValue; - } + return new Empty(); + } - return new Empty(); - } + public override Empty InitLargeArray(Empty input) + { + var arr = new int[1024 * 1024 * 1024]; // - public override Empty InitLargeStringDynamic(InitLargeStringDynamicInput input) - { - var str = new String('A', input.StringSizeValue); + for (var i = 0; i < arr.Length; i++) arr[i] = int.MaxValue; - return new Empty(); - } + return new Empty(); + } - public override Empty TestCallToNestedClass(Empty input) - { - State.CurrentTime.Value = NestedClass.UseDeniedMemberInNestedClass(); + public override Empty InitLargeStringDynamic(InitLargeStringDynamicInput input) + { + var str = new string('A', input.StringSizeValue); - return new Empty(); - } - - public override Empty TestCallToSeparateClass(Empty input) - { - State.CurrentTime.Value = SeparateClass.UseDeniedMemberInSeparateClass(); - - return new Empty(); - } + return new Empty(); + } - public override Empty TestInfiniteLoop(Int32Value input) - { - int i = 0; - while (i++ < input.Value) - { - } - - ExecutionObserverProxy.SetObserver(null); - return new Empty(); - } + public override Empty TestCallToNestedClass(Empty input) + { + State.CurrentTime.Value = NestedClass.UseDeniedMemberInNestedClass(); - public override Empty TestInfiniteLoopInSeparateClass(Empty input) - { - SeparateClass.UseInfiniteLoopInSeparateClass(); - return new Empty(); - } + return new Empty(); + } - public override Empty TestInfiniteRecursiveCall(Empty input) - { - InfiniteRecursiveCall(); - return new Empty(); - } - - private void InfiniteRecursiveCall(string text = "") - { - text += "TEST"; - InfiniteRecursiveCall(text); - } + public override Empty TestCallToSeparateClass(Empty input) + { + State.CurrentTime.Value = SeparateClass.UseDeniedMemberInSeparateClass(); - public override Empty TestInfiniteRecursiveCallInSeparateClass(Empty input) - { - SeparateClass.UseInfiniteRecursiveCallInSeparateClass(); - return new Empty(); - } + return new Empty(); + } - private class NestedClass + public override Empty TestInfiniteLoop(Int32Value input) + { + var i = 0; + while (i++ < input.Value) { - public static DateTime UseDeniedMemberInNestedClass() - { - return DateTime.Now; - } } - public override Int32Value TestGetHashCodeCall(Empty input) - { - return new Int32Value() - { - Value = new IMessageInheritedClass().GetHashCode() - }; - } + ExecutionObserverProxy.SetObserver(null); + return new Empty(); } - - public class SeparateClass + + public override Empty TestInfiniteLoopInSeparateClass(Empty input) { - public static DateTime UseDeniedMemberInSeparateClass() - { - return DateTime.Now; - } + SeparateClass.UseInfiniteLoopInSeparateClass(); + return new Empty(); + } - public static void UseInfiniteLoopInSeparateClass() - { - int i = 0; - for (; true;) - { - i++; - } - } + public override Empty TestInfiniteRecursiveCall(Empty input) + { + InfiniteRecursiveCall(); + return new Empty(); + } - public static void UseInfiniteRecursiveCallInSeparateClass(string text = "") - { - text += "TEST"; - UseInfiniteRecursiveCallInSeparateClass(text); - } + private void InfiniteRecursiveCall(string text = "") + { + text += "TEST"; + InfiniteRecursiveCall(text); } - public class IMessageInheritedClass : IMessage + public override Empty TestInfiniteRecursiveCallInSeparateClass(Empty input) { - public int Test { get; set; } + SeparateClass.UseInfiniteRecursiveCallInSeparateClass(); + return new Empty(); + } - public override int GetHashCode() + public override Int32Value TestGetHashCodeCall(Empty input) + { + return new Int32Value { - Test = base.GetHashCode(); - return 0; - } + Value = new IMessageInheritedClass().GetHashCode() + }; + } - public void MergeFrom(CodedInputStream input) + private class NestedClass + { + public static DateTime UseDeniedMemberInNestedClass() { - throw new NotImplementedException(); + return DateTime.Now; } + } +} - public void WriteTo(CodedOutputStream output) - { - throw new NotImplementedException(); - } +public class SeparateClass +{ + public static DateTime UseDeniedMemberInSeparateClass() + { + return DateTime.Now; + } - public int CalculateSize() - { - throw new NotImplementedException(); - } + public static void UseInfiniteLoopInSeparateClass() + { + var i = 0; + for (;;) i++; + } - public MessageDescriptor Descriptor { get; } + public static void UseInfiniteRecursiveCallInSeparateClass(string text = "") + { + text += "TEST"; + UseInfiniteRecursiveCallInSeparateClass(text); } } + +public class IMessageInheritedClass : IMessage +{ + public int Test { get; set; } + + public void MergeFrom(CodedInputStream input) + { + throw new NotImplementedException(); + } + + public void WriteTo(CodedOutputStream output) + { + throw new NotImplementedException(); + } + + public int CalculateSize() + { + throw new NotImplementedException(); + } + + public MessageDescriptor Descriptor { get; } + + public override int GetHashCode() + { + Test = base.GetHashCode(); + return 0; + } +} \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/BadContractState.cs b/test/AElf.Runtime.CSharp.Tests.BadContract/BadContractState.cs index 2c3d87472d..848ee99103 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/BadContractState.cs +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/BadContractState.cs @@ -1,22 +1,20 @@ using System; using AElf.Sdk.CSharp.State; -namespace AElf.Runtime.CSharp.Tests.BadContract -{ - public class BadContractState : ContractState - { - public SingletonState Double; +namespace AElf.Runtime.CSharp.Tests.BadContract; - public SingletonState Float; +public class BadContractState : ContractState +{ + public SingletonState CurrentRandom; - public SingletonState CurrentTime; + public SingletonState CurrentTime; - public SingletonState CurrentTimeUtc; + public SingletonState CurrentTimeToday; - public SingletonState CurrentTimeToday; + public SingletonState CurrentTimeUtc; + public SingletonState Double; - public SingletonState CurrentRandom; + public SingletonState Float; - public int i; - } -} + public int i; +} \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/BadReferences.cs b/test/AElf.Runtime.CSharp.Tests.BadContract/BadReferences.cs index e43337dd49..f2443eab59 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/BadReferences.cs +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/BadReferences.cs @@ -1,45 +1,41 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; using System.Text; using AElf.Cryptography.SecretSharing; using AElf.Kernel.Blockchain.Domain; -namespace AElf.Runtime.CSharp.Tests.BadContract +namespace AElf.Runtime.CSharp.Tests.BadContract; + +public class BadReferences { - public class BadReferences + private int[] _ints = new int[long.MaxValue]; + + private object[] _objects = new object[6]; + + private string[] _strings = new string[40 * 1024 / 128 + 1]; + private ChainManager ChainManager { get; set; } //assembly denied + private Random[] RandomArray { get; set; } //array with namespace denied type + + private List AllowedListField // namespace allowed + { + get; + } + + private List DeniedListField // namespace allowed + { + get; + } + + private Assembly AssemblyField { get; set; } // namespace denied + + private AssemblyCompanyAttribute AssemblyCompanyAttribute { get; set; } // namespace denied, type allowed + private object EncodingObject { get; } = Encoding.UTF8; // type denied, member allowed + private int ThreadId { get; } = Environment.CurrentManagedThreadId; // type denied, member allowed + private DateTime DateTime { get; } = DateTime.Today; // type allowed, member denied + + private void TestSecretSharing() { - private ChainManager ChainManager { get; set; } //assembly denied - private Random[] RandomArray { get; set; } //array with namespace denied type - - private List AllowedListField // namespace allowed - { - get; - } - - private List DeniedListField // namespace allowed - { - get; - } - - private Assembly AssemblyField { get; set; } // namespace denied - - private AssemblyCompanyAttribute AssemblyCompanyAttribute { get; set; } // namespace denied, type allowed - private Object EncodingObject { get; } = Encoding.UTF8; // type denied, member allowed - private int ThreadId { get; } = Environment.CurrentManagedThreadId; // type denied, member allowed - private DateTime DateTime { get; } = DateTime.Today; // type allowed, member denied - - private string[] _strings = new string[(40 * 1024) / 128 + 1]; - - private object[] _objects = new object[6]; - - private int[] _ints = new int[long.MaxValue]; - - private void TestSecretSharing() - { - SecretSharingHelper.DecodeSecret(new List(), new List(), 2); - } + SecretSharingHelper.DecodeSecret(new List(), new List(), 2); } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.BadContract/FakeExecutionObserverProxy.cs b/test/AElf.Runtime.CSharp.Tests.BadContract/FakeExecutionObserverProxy.cs index 5e872cd91e..189a766cad 100644 --- a/test/AElf.Runtime.CSharp.Tests.BadContract/FakeExecutionObserverProxy.cs +++ b/test/AElf.Runtime.CSharp.Tests.BadContract/FakeExecutionObserverProxy.cs @@ -1,24 +1,23 @@ using AElf.Kernel.SmartContract; -namespace AElf.Runtime.CSharp.Tests.BadContract +namespace AElf.Runtime.CSharp.Tests.BadContract; + +public static class ExecutionObserverProxy { - public static class ExecutionObserverProxy - { - private static IExecutionObserver _observer; + private static IExecutionObserver _observer; - public static void SetObserver(IExecutionObserver observer) - { - _observer = observer; - } + public static void SetObserver(IExecutionObserver observer) + { + _observer = observer; + } - public static void BranchCount() - { - _observer.BranchCount(); - } + public static void BranchCount() + { + _observer.BranchCount(); + } - public static void CallCount() - { - _observer.CallCount(); - } + public static void CallCount() + { + _observer.CallCount(); } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.TestContract/AElf.Runtime.CSharp.Tests.TestContract.csproj b/test/AElf.Runtime.CSharp.Tests.TestContract/AElf.Runtime.CSharp.Tests.TestContract.csproj index ab81be0969..6faf712389 100644 --- a/test/AElf.Runtime.CSharp.Tests.TestContract/AElf.Runtime.CSharp.Tests.TestContract.csproj +++ b/test/AElf.Runtime.CSharp.Tests.TestContract/AElf.Runtime.CSharp.Tests.TestContract.csproj @@ -6,7 +6,7 @@ false - + diff --git a/test/AElf.Runtime.CSharp.Tests.TestContract/TestContract.cs b/test/AElf.Runtime.CSharp.Tests.TestContract/TestContract.cs index 0acaa2293d..fbdaf79743 100644 --- a/test/AElf.Runtime.CSharp.Tests.TestContract/TestContract.cs +++ b/test/AElf.Runtime.CSharp.Tests.TestContract/TestContract.cs @@ -1,210 +1,201 @@ -using System; using AElf.CSharp.Core; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; -namespace AElf.Runtime.CSharp.Tests.TestContract +namespace AElf.Runtime.CSharp.Tests.TestContract; + +public class TestContract : TestContractContainer.TestContractBase { - public class TestContract : TestContractContainer.TestContractBase + public static int i; + + public override BoolOutput TestBoolState(BoolInput input) { - public static int i; - - public override BoolOutput TestBoolState(BoolInput input) - { - State.BoolInfo.Value = input.BoolValue; - return new BoolOutput() - { - BoolValue = State.BoolInfo.Value - }; - } - - public override Int32Output TestInt32State(Int32Input input) + State.BoolInfo.Value = input.BoolValue; + return new BoolOutput { - State.Int32Info.Value = State.Int32Info.Value.Sub(input.Int32Value); - return new Int32Output() - { - Int32Value = State.Int32Info.Value - }; - } + BoolValue = State.BoolInfo.Value + }; + } - public override UInt32Output TestUInt32State(UInt32Input input) + public override Int32Output TestInt32State(Int32Input input) + { + State.Int32Info.Value = State.Int32Info.Value.Sub(input.Int32Value); + return new Int32Output { - State.UInt32Info.Value = State.UInt32Info.Value.Add(input.UInt32Value); - return new UInt32Output() - { - UInt32Value = State.UInt32Info.Value - }; - } + Int32Value = State.Int32Info.Value + }; + } - public override Int64Output TestInt64State(Int64Input input) + public override UInt32Output TestUInt32State(UInt32Input input) + { + State.UInt32Info.Value = State.UInt32Info.Value.Add(input.UInt32Value); + return new UInt32Output { - State.Int64Info.Value = State.Int64Info.Value.Sub(input.Int64Value); - return new Int64Output() - { - Int64Value = State.Int64Info.Value - }; - } + UInt32Value = State.UInt32Info.Value + }; + } - public override UInt64Output TestUInt64State(UInt64Input input) + public override Int64Output TestInt64State(Int64Input input) + { + State.Int64Info.Value = State.Int64Info.Value.Sub(input.Int64Value); + return new Int64Output { - State.UInt64Info.Value = State.UInt64Info.Value.Add(input.UInt64Value); - return new UInt64Output() - { - UInt64Value = State.UInt64Info.Value - }; - } + Int64Value = State.Int64Info.Value + }; + } - public override StringOutput TestStringState(StringInput input) + public override UInt64Output TestUInt64State(UInt64Input input) + { + State.UInt64Info.Value = State.UInt64Info.Value.Add(input.UInt64Value); + return new UInt64Output { - if (string.IsNullOrEmpty(State.StringInfo.Value)) - State.StringInfo.Value = string.Empty; - - State.StringInfo.Value = State.StringInfo.Value + input.StringValue; - return new StringOutput() - { - StringValue = State.StringInfo.Value - }; - } + UInt64Value = State.UInt64Info.Value + }; + } + + public override StringOutput TestStringState(StringInput input) + { + if (string.IsNullOrEmpty(State.StringInfo.Value)) + State.StringInfo.Value = string.Empty; - public override BytesOutput TestBytesState(BytesInput input) + State.StringInfo.Value = State.StringInfo.Value + input.StringValue; + return new StringOutput { - State.BytesInfo.Value = input.BytesValue.ToByteArray(); - return new BytesOutput() - { - BytesValue = ByteString.CopyFrom(State.BytesInfo.Value) - }; - } + StringValue = State.StringInfo.Value + }; + } - public override ProtobufOutput TestProtobufState(ProtobufInput input) + public override BytesOutput TestBytesState(BytesInput input) + { + State.BytesInfo.Value = input.BytesValue.ToByteArray(); + return new BytesOutput { - State.ProtoInfo.Value = input.ProtobufValue; + BytesValue = ByteString.CopyFrom(State.BytesInfo.Value) + }; + } - return new ProtobufOutput() - { - ProtobufValue = State.ProtoInfo.Value - }; - } + public override ProtobufOutput TestProtobufState(ProtobufInput input) + { + State.ProtoInfo.Value = input.ProtobufValue; - public override Complex1Output TestComplex1State(Complex1Input input) + return new ProtobufOutput { - State.BoolInfo.Value = input.BoolValue; - State.Int32Info.Value = input.Int32Value; - - return new Complex1Output() - { - BoolValue = State.BoolInfo.Value, - Int32Value = State.Int32Info.Value - }; - } + ProtobufValue = State.ProtoInfo.Value + }; + } + + public override Complex1Output TestComplex1State(Complex1Input input) + { + State.BoolInfo.Value = input.BoolValue; + State.Int32Info.Value = input.Int32Value; - public override Complex2Output TestComplex2State(Complex2Input input) + return new Complex1Output { - State.BoolInfo.Value = input.BoolData.BoolValue; - State.Int32Info.Value = input.Int32Data.Int32Value; - - return new Complex2Output() - { - BoolData = new BoolOutput() {BoolValue = State.BoolInfo.Value}, - Int32Data = new Int32Output() {Int32Value = State.Int32Info.Value} - }; - } + BoolValue = State.BoolInfo.Value, + Int32Value = State.Int32Info.Value + }; + } + + public override Complex2Output TestComplex2State(Complex2Input input) + { + State.BoolInfo.Value = input.BoolData.BoolValue; + State.Int32Info.Value = input.Int32Data.Int32Value; - public override ProtobufListOutput TestMappedState(ProtobufInput input) + return new Complex2Output { - var protobufMessage = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; - if (protobufMessage == null) - { - State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = - new ProtobufMessage() - { - BoolValue = true, - Int64Value = input.ProtobufValue.Int64Value, - StringValue = input.ProtobufValue.StringValue - }; - } - else - { - State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue].Int64Value = - input.ProtobufValue.Int64Value; - } - - return new ProtobufListOutput - { - Collection = {input.ProtobufValue} - }; - } + BoolData = new BoolOutput { BoolValue = State.BoolInfo.Value }, + Int32Data = new Int32Output { Int32Value = State.Int32Info.Value } + }; + } - public override TradeMessage TestMapped1State(Complex3Input input) + public override ProtobufListOutput TestMappedState(ProtobufInput input) + { + var protobufMessage = State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue]; + if (protobufMessage == null) + State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue] = + new ProtobufMessage + { + BoolValue = true, + Int64Value = input.ProtobufValue.Int64Value, + StringValue = input.ProtobufValue.StringValue + }; + else + State.Complex3Info[input.ProtobufValue.Int64Value][input.ProtobufValue.StringValue].Int64Value = + input.ProtobufValue.Int64Value; + + return new ProtobufListOutput + { + Collection = { input.ProtobufValue } + }; + } + + public override TradeMessage TestMapped1State(Complex3Input input) + { + var tradeMessage = State.Complex4Info[input.From][input.PairA][input.To][input.PairB]; + if (tradeMessage == null) { - var tradeMessage = State.Complex4Info[input.From][input.PairA][input.To][input.PairB]; - if (tradeMessage == null) - { - State.Complex4Info[input.From][input.PairA][input.To][input.PairB] = input.TradeDetails; + State.Complex4Info[input.From][input.PairA][input.To][input.PairB] = input.TradeDetails; - return input.TradeDetails; - } + return input.TradeDetails; + } - tradeMessage.FromAmount += input.TradeDetails.FromAmount; - tradeMessage.ToAmount += input.TradeDetails.ToAmount; + tradeMessage.FromAmount += input.TradeDetails.FromAmount; + tradeMessage.ToAmount += input.TradeDetails.ToAmount; - State.Complex4Info[input.From][input.PairA][input.To][input.PairB] = tradeMessage; + State.Complex4Info[input.From][input.PairA][input.To][input.PairB] = tradeMessage; - return tradeMessage; - } + return tradeMessage; + } - public override BoolOutput TestReadonlyState(BoolInput input) - { - State.ReadonlyBool.Value = input.BoolValue; - return new BoolOutput {BoolValue = State.ReadonlyBool.Value}; - } + public override BoolOutput TestReadonlyState(BoolInput input) + { + State.ReadonlyBool.Value = input.BoolValue; + return new BoolOutput { BoolValue = State.ReadonlyBool.Value }; + } - public override StringOutput TestArrayIterateForeach(Empty input) - { - // Iterating array via foreach loop causes unchecked arithmetic opcodes - // This is to be used for contract policy tests + public override StringOutput TestArrayIterateForeach(Empty input) + { + // Iterating array via foreach loop causes unchecked arithmetic opcodes + // This is to be used for contract policy tests - var words = new[] {"TEST", "FOREACH", "LOOP"}; - var merged = ""; + var words = new[] { "TEST", "FOREACH", "LOOP" }; + var merged = ""; - foreach (var word in words) - { - merged += $" {word}"; - } + foreach (var word in words) merged += $" {word}"; - return new StringOutput {StringValue = merged}; - } + return new StringOutput { StringValue = merged }; + } - public override Int32Output TestViewMethod(Empty input) + public override Int32Output TestViewMethod(Empty input) + { + return new Int32Output { - return new Int32Output() - { - Int32Value = State.Int32Info.Value + 1 - }; - } + Int32Value = State.Int32Info.Value + 1 + }; + } - // for test cases - public bool TestStateType(int i) - { - State.ReadonlyBool.Value = false; - State.ProtoInfo.Value = new ProtobufMessage(); - State.Int32Info.Value = Int32.MaxValue; - State.MappedState[1] = new Address(); - State.MappedInt64State[1] = i + 1; - State.StringInfo.Value = "test"; - return State.BoolInfo.Value; - } + // for test cases + public bool TestStateType(int i) + { + State.ReadonlyBool.Value = false; + State.ProtoInfo.Value = new ProtobufMessage(); + State.Int32Info.Value = int.MaxValue; + State.MappedState[1] = new Address(); + State.MappedInt64State[1] = i + 1; + State.StringInfo.Value = "test"; + return State.BoolInfo.Value; + } + + public class TestNestClass + { + public const int j = 1; + public static int k; - public class TestNestClass + public void TestState() { - public static int k; - public const int j = 1; - - public void TestState() - { - var state =new TestContractState(); - state.ProtoInfo.Value = new ProtobufMessage(); - } + var state = new TestContractState(); + state.ProtoInfo.Value = new ProtobufMessage(); } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests.TestContract/TestContractState.cs b/test/AElf.Runtime.CSharp.Tests.TestContract/TestContractState.cs index c16b2ec496..33b28fd642 100644 --- a/test/AElf.Runtime.CSharp.Tests.TestContract/TestContractState.cs +++ b/test/AElf.Runtime.CSharp.Tests.TestContract/TestContractState.cs @@ -1,28 +1,27 @@ using AElf.Sdk.CSharp.State; using AElf.Types; -namespace AElf.Runtime.CSharp.Tests.TestContract +namespace AElf.Runtime.CSharp.Tests.TestContract; + +public class TestContractState : ContractState { - public class TestContractState : ContractState - { - private static BoolState boolState; - private static readonly BoolState boolState2; - public BoolState BoolInfo { get; set; } - public Int32State Int32Info { get; set; } - public UInt32State UInt32Info { get; set; } - public Int64State Int64Info { get; set; } - public UInt64State UInt64Info { get; set; } - public StringState StringInfo { get; set; } - public BytesState BytesInfo { get; set; } - public ProtobufState ProtoInfo { get; set; } - - public MappedState Complex3Info { get; set; } - public MappedState Complex4Info { get; set; } + private static BoolState boolState; + private static readonly BoolState boolState2; + public BoolState BoolInfo { get; set; } + public Int32State Int32Info { get; set; } + public UInt32State UInt32Info { get; set; } + public Int64State Int64Info { get; set; } + public UInt64State UInt64Info { get; set; } + public StringState StringInfo { get; set; } + public BytesState BytesInfo { get; set; } + public ProtobufState ProtoInfo { get; set; } + + public MappedState Complex3Info { get; set; } + public MappedState Complex4Info { get; set; } + + public ReadonlyState ReadonlyBool { get; set; } + + public MappedState MappedState { get; set; } - public ReadonlyState ReadonlyBool { get; set; } - - public MappedState MappedState { get; set; } - - public MappedState MappedInt64State { get; set; } - } + public MappedState MappedInt64State { get; set; } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/AElf.Runtime.CSharp.Tests.csproj b/test/AElf.Runtime.CSharp.Tests/AElf.Runtime.CSharp.Tests.csproj index c970f82d42..838592acc5 100644 --- a/test/AElf.Runtime.CSharp.Tests/AElf.Runtime.CSharp.Tests.csproj +++ b/test/AElf.Runtime.CSharp.Tests/AElf.Runtime.CSharp.Tests.csproj @@ -5,35 +5,35 @@ false - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestAElfModule.cs b/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestAElfModule.cs index b2ad867250..e1dc387e83 100644 --- a/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestAElfModule.cs +++ b/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestAElfModule.cs @@ -3,17 +3,16 @@ using AElf.Modularity; using Volo.Abp.Modularity; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +[DependsOn( + typeof(CSharpRuntimeAElfModule), + typeof(SmartContractTestAElfModule), + typeof(CSharpCodeOpsAElfModule) +)] +public class CSharpRuntimeTestAElfModule : AElfModule { - [DependsOn( - typeof(CSharpRuntimeAElfModule), - typeof(SmartContractTestAElfModule), - typeof(CSharpCodeOpsAElfModule) - )] - public class CSharpRuntimeTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - } } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestBase.cs b/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestBase.cs index f5b25d79d8..f3a6540a50 100644 --- a/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestBase.cs +++ b/test/AElf.Runtime.CSharp.Tests/CSharpRuntimeTestBase.cs @@ -1,8 +1,7 @@ using AElf.TestBase; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class CSharpRuntimeTestBase : AElfIntegratedTest { - public class CSharpRuntimeTestBase : AElfIntegratedTest - { - } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/ExecutiveTests.cs b/test/AElf.Runtime.CSharp.Tests/ExecutiveTests.cs index e33b94f3bb..239ad6cee2 100644 --- a/test/AElf.Runtime.CSharp.Tests/ExecutiveTests.cs +++ b/test/AElf.Runtime.CSharp.Tests/ExecutiveTests.cs @@ -13,201 +13,196 @@ using Shouldly; using Xunit; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class ExecutiveTests : CSharpRuntimeTestBase { - public class ExecutiveTests : CSharpRuntimeTestBase + private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; + private readonly IContractPatcher _patcher; + + public ExecutiveTests() { - private readonly IHostSmartContractBridgeContextService _hostSmartContractBridgeContextService; - private readonly IContractPatcher _patcher; + _hostSmartContractBridgeContextService = GetRequiredService(); + _patcher = GetRequiredService(); + } - public ExecutiveTests() - { - _hostSmartContractBridgeContextService = GetRequiredService(); - _patcher = GetRequiredService(); - } + [Fact] + public async Task Apply_ExceededMaxCallDepth_Test() + { + var executive = CreateExecutive(); - [Fact] - public async Task Apply_ExceededMaxCallDepth_Test() - { - var executive = CreateExecutive(); - - var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - - var transactionContext = CreateTransactionContext(); - transactionContext.CallDepth = 16; - - await executive.ApplyAsync(transactionContext); - - hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); - transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.ExceededMaxCallDepth); - transactionContext.Trace.Error.ShouldContain("ExceededMaxCallDepth"); - } - - [Fact] - public async Task Apply_MethodNotExist_Test() - { - var executive = CreateExecutive(); + var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); + var transactionContext = CreateTransactionContext(); + transactionContext.CallDepth = 16; - var transactionContext = CreateTransactionContext(); - transactionContext.Transaction.MethodName = "NotExist"; + await executive.ApplyAsync(transactionContext); - await executive.ApplyAsync(transactionContext); - hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); - transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.SystemError); - transactionContext.Trace.Error.ShouldContain("Failed to find handler for NotExist"); - } + hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); + transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.ExceededMaxCallDepth); + transactionContext.Trace.Error.ShouldContain("ExceededMaxCallDepth"); + } - [Fact] - public async Task Apply_Success_Test() - { - var executive = CreateExecutive(); - - var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - var transactionContext = CreateTransactionContext(); - - await executive.ApplyAsync(transactionContext); - - hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); - transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); - transactionContext.Trace.Error.ShouldBeNullOrEmpty(); - transactionContext.Trace.ReturnValue.ShouldBe((new Int32Output {Int32Value = -5}).ToByteString()); - transactionContext.Trace.StateSet.Reads.Count.ShouldBe(1); - transactionContext.Trace.StateSet.Writes.Count.ShouldBe(1); - } - - [Fact] - public async Task Apply_ViewMethod_Test() - { - var executive = CreateExecutive(); - - var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - var transactionContext = CreateTransactionContext(); - transactionContext.Transaction.MethodName = "TestViewMethod"; - transactionContext.Transaction.Params = ByteString.Empty; - - await executive.ApplyAsync(transactionContext); - - hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); - transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); - transactionContext.Trace.Error.ShouldBeNullOrEmpty(); - transactionContext.Trace.ReturnValue.ShouldBe((new Int32Output {Int32Value = 1}).ToByteString()); - transactionContext.Trace.StateSet.Reads.Count.ShouldBe(0); - } - - [Fact] - public async Task Apply_ExecutionObserver_Test() - { - var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); - var code = _patcher.Patch(contractCode, false); - var assembly = Assembly.Load(code); - var executive = new Executive(assembly) - { - }; - - var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); - executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - var transactionContext = CreateTransactionContext(); - - await executive.ApplyAsync(transactionContext); - - hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); - transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); - transactionContext.Trace.Error.ShouldBeNullOrEmpty(); - transactionContext.Trace.ReturnValue.ShouldBe((new Int32Output {Int32Value = -5}).ToByteString()); - transactionContext.Trace.StateSet.Reads.Count.ShouldBe(1); - transactionContext.Trace.StateSet.Writes.Count.ShouldBe(1); - } - - [Fact] - public void GetJsonStringOfParameters_Test() - { - var executive = CreateExecutive(); - var json = executive.GetJsonStringOfParameters("NotExist", new Int32Input{Int32Value = 5}.ToByteArray()); - json.ShouldBeEmpty(); - - json = executive.GetJsonStringOfParameters("TestInt32State", new Int32Input{Int32Value = 5}.ToByteArray()); - json.ShouldBe("{ \"int32Value\": 5 }"); - } - - [Fact] - public void Descriptors_Test() - { - var executive = CreateExecutive(); - executive.Descriptors.Count.ShouldBe(1); - executive.Descriptors[0].File.Name.ShouldBe("test_contract.proto"); - executive.Descriptors[0].FullName.ShouldBe("TestContract"); - } - - [Fact] - public void GetFileDescriptors_Test() - { - var executive = CreateExecutive(); - var fileDescriptors = executive.GetFileDescriptors(); - - var descriptors = fileDescriptors.ToList(); - descriptors.Count.ShouldBe(5); - descriptors.ShouldContain(f => f.Name == "google/protobuf/descriptor.proto"); - descriptors.ShouldContain(f => f.Name == "google/protobuf/empty.proto"); - descriptors.ShouldContain(f => f.Name == "google/protobuf/timestamp.proto"); - descriptors.ShouldContain(f => f.Name == "aelf/options.proto"); - descriptors.ShouldContain(f => f.Name == "test_contract.proto"); - - var set = new FileDescriptorSet(); - set.File.AddRange(descriptors.Select(x => x.SerializedData)); - - var fileDescriptorSet = executive.GetFileDescriptorSet(); - fileDescriptorSet.ShouldBe(set.ToByteArray()); - } - - [Fact] - public void IsView_Test() - { - var executive = CreateExecutive(); + [Fact] + public async Task Apply_MethodNotExist_Test() + { + var executive = CreateExecutive(); - Assert.Throws(() => executive.IsView("NotExist")); - executive.IsView("TestViewMethod").ShouldBeTrue(); - executive.IsView("TestBoolState").ShouldBeFalse(); - } + var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); - private Executive CreateExecutive() - { - var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); - var assembly = Assembly.Load(contractCode); - var executive = new Executive(assembly) - { - }; - return executive; - } + var transactionContext = CreateTransactionContext(); + transactionContext.Transaction.MethodName = "NotExist"; + + await executive.ApplyAsync(transactionContext); + hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); + transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.SystemError); + transactionContext.Trace.Error.ShouldContain("Failed to find handler for NotExist"); + } - private TransactionContext CreateTransactionContext() + [Fact] + public async Task Apply_Success_Test() + { + var executive = CreateExecutive(); + + var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); + var transactionContext = CreateTransactionContext(); + + await executive.ApplyAsync(transactionContext); + + hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); + transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + transactionContext.Trace.Error.ShouldBeNullOrEmpty(); + transactionContext.Trace.ReturnValue.ShouldBe(new Int32Output { Int32Value = -5 }.ToByteString()); + transactionContext.Trace.StateSet.Reads.Count.ShouldBe(1); + transactionContext.Trace.StateSet.Writes.Count.ShouldBe(1); + } + + [Fact] + public async Task Apply_ViewMethod_Test() + { + var executive = CreateExecutive(); + + var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); + var transactionContext = CreateTransactionContext(); + transactionContext.Transaction.MethodName = "TestViewMethod"; + transactionContext.Transaction.Params = ByteString.Empty; + + await executive.ApplyAsync(transactionContext); + + hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); + transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + transactionContext.Trace.Error.ShouldBeNullOrEmpty(); + transactionContext.Trace.ReturnValue.ShouldBe(new Int32Output { Int32Value = 1 }.ToByteString()); + transactionContext.Trace.StateSet.Reads.Count.ShouldBe(0); + } + + [Fact] + public async Task Apply_ExecutionObserver_Test() + { + var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); + var code = _patcher.Patch(contractCode, false); + var assembly = Assembly.Load(code); + var executive = new Executive(assembly); + + var hostSmartContractBridgeContext = _hostSmartContractBridgeContextService.Create(); + executive.SetHostSmartContractBridgeContext(_hostSmartContractBridgeContextService.Create()); + var transactionContext = CreateTransactionContext(); + + await executive.ApplyAsync(transactionContext); + + hostSmartContractBridgeContext.TransactionContext.ShouldBeNull(); + transactionContext.Trace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); + transactionContext.Trace.Error.ShouldBeNullOrEmpty(); + transactionContext.Trace.ReturnValue.ShouldBe(new Int32Output { Int32Value = -5 }.ToByteString()); + transactionContext.Trace.StateSet.Reads.Count.ShouldBe(1); + transactionContext.Trace.StateSet.Writes.Count.ShouldBe(1); + } + + [Fact] + public void GetJsonStringOfParameters_Test() + { + var executive = CreateExecutive(); + var json = executive.GetJsonStringOfParameters("NotExist", new Int32Input { Int32Value = 5 }.ToByteArray()); + json.ShouldBeEmpty(); + + json = executive.GetJsonStringOfParameters("TestInt32State", new Int32Input { Int32Value = 5 }.ToByteArray()); + json.ShouldBe("{ \"int32Value\": 5 }"); + } + + [Fact] + public void Descriptors_Test() + { + var executive = CreateExecutive(); + executive.Descriptors.Count.ShouldBe(1); + executive.Descriptors[0].File.Name.ShouldBe("test_contract.proto"); + executive.Descriptors[0].FullName.ShouldBe("TestContract"); + } + + [Fact] + public void GetFileDescriptors_Test() + { + var executive = CreateExecutive(); + var fileDescriptors = executive.GetFileDescriptors(); + + var descriptors = fileDescriptors.ToList(); + descriptors.Count.ShouldBe(5); + descriptors.ShouldContain(f => f.Name == "google/protobuf/descriptor.proto"); + descriptors.ShouldContain(f => f.Name == "google/protobuf/empty.proto"); + descriptors.ShouldContain(f => f.Name == "google/protobuf/timestamp.proto"); + descriptors.ShouldContain(f => f.Name == "aelf/options.proto"); + descriptors.ShouldContain(f => f.Name == "test_contract.proto"); + + var set = new FileDescriptorSet(); + set.File.AddRange(descriptors.Select(x => x.SerializedData)); + + var fileDescriptorSet = executive.GetFileDescriptorSet(); + fileDescriptorSet.ShouldBe(set.ToByteArray()); + } + + [Fact] + public void IsView_Test() + { + var executive = CreateExecutive(); + + Assert.Throws(() => executive.IsView("NotExist")); + executive.IsView("TestViewMethod").ShouldBeTrue(); + executive.IsView("TestBoolState").ShouldBeFalse(); + } + + private Executive CreateExecutive() + { + var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); + var assembly = Assembly.Load(contractCode); + var executive = new Executive(assembly); + return executive; + } + + private TransactionContext CreateTransactionContext() + { + return new TransactionContext { - return new TransactionContext + Transaction = new Transaction + { + From = SampleAddress.AddressList[0], + To = SampleAddress.AddressList[1], + MethodName = "TestInt32State", + Params = new Int32Input { Int32Value = 5 }.ToByteString() + }, + Trace = new TransactionTrace(), + ExecutionObserverThreshold = new ExecutionObserverThreshold { - Transaction = new Transaction - { - From = SampleAddress.AddressList[0], - To = SampleAddress.AddressList[1], - MethodName = "TestInt32State", - Params = (new Int32Input{Int32Value = 5}).ToByteString() - }, - Trace = new TransactionTrace(), - ExecutionObserverThreshold = new ExecutionObserverThreshold - { - ExecutionBranchThreshold = -1, - ExecutionCallThreshold = -1 - }, - CallDepth = 1, - MaxCallDepth = 15, - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - BlockHeight = 1, - CurrentBlockTime = TimestampHelper.GetUtcNow() - }; - } + ExecutionBranchThreshold = -1, + ExecutionCallThreshold = -1 + }, + CallDepth = 1, + MaxCallDepth = 15, + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + BlockHeight = 1, + CurrentBlockTime = TimestampHelper.GetUtcNow() + }; } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/ServerCallHandlerTests.cs b/test/AElf.Runtime.CSharp.Tests/ServerCallHandlerTests.cs index 950ca394b4..fff655c849 100644 --- a/test/AElf.Runtime.CSharp.Tests/ServerCallHandlerTests.cs +++ b/test/AElf.Runtime.CSharp.Tests/ServerCallHandlerTests.cs @@ -5,122 +5,121 @@ using Shouldly; using Xunit; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public class ServerCallHandlerTests : CSharpRuntimeTestBase { - public class ServerCallHandlerTests : CSharpRuntimeTestBase + [Fact] + public void Method_Type_Test() { - [Fact] - public void Method_Type_Test() - { - var callHandler = CreateServerCallHandler(); - var isView = callHandler.IsView(); - isView.ShouldBeFalse(); - - callHandler = CreateServerCallHandler(true); - isView = callHandler.IsView(); - isView.ShouldBeTrue(); - } - - [Fact] - public void Execute_Test() + var callHandler = CreateServerCallHandler(); + var isView = callHandler.IsView(); + isView.ShouldBeFalse(); + + callHandler = CreateServerCallHandler(true); + isView = callHandler.IsView(); + isView.ShouldBeTrue(); + } + + [Fact] + public void Execute_Test() + { + var callHandler = CreateServerCallHandler(); + var input = new StringInput { - var callHandler = CreateServerCallHandler(); - var input = new StringInput - { - StringValue = "test" - }; - var inputArray = input.ToByteArray(); - var result = callHandler.Execute(inputArray); - result.ShouldNotBeNull(); + StringValue = "test" + }; + var inputArray = input.ToByteArray(); + var result = callHandler.Execute(inputArray); + result.ShouldNotBeNull(); - var objectInfo = callHandler.ReturnBytesToObject(result); - var outValue = (StringOutput) objectInfo; - outValue.StringValue.ShouldBe("test"); - } + var objectInfo = callHandler.ReturnBytesToObject(result); + var outValue = (StringOutput)objectInfo; + outValue.StringValue.ShouldBe("test"); + } - [Fact] - public void InputBytesToObject_Test() + [Fact] + public void InputBytesToObject_Test() + { + var callHandler = CreateServerCallHandler(); + var input = new StringInput { - var callHandler = CreateServerCallHandler(); - var input = new StringInput - { - StringValue = "test1" - }; - var objInfo = callHandler.InputBytesToObject(input.ToByteArray()); - objInfo.ShouldNotBeNull(); + StringValue = "test1" + }; + var objInfo = callHandler.InputBytesToObject(input.ToByteArray()); + objInfo.ShouldNotBeNull(); - var input1 = (StringInput) objInfo; - input1.ShouldBe(input); - } + var input1 = (StringInput)objInfo; + input1.ShouldBe(input); + } - [Fact] - public void InputBytesToString_Test() + [Fact] + public void InputBytesToString_Test() + { + var callHandler = CreateServerCallHandler(); + var input = new StringInput { - var callHandler = CreateServerCallHandler(); - var input = new StringInput - { - StringValue = "test1" - }; - var objString = callHandler.InputBytesToString(input.ToByteArray()); - objString.ShouldBe("{ \"stringValue\": \"test1\" }"); - } + StringValue = "test1" + }; + var objString = callHandler.InputBytesToString(input.ToByteArray()); + objString.ShouldBe("{ \"stringValue\": \"test1\" }"); + } - [Fact] - public void ReturnBytesToObject_Test() + [Fact] + public void ReturnBytesToObject_Test() + { + var callHandler = CreateServerCallHandler(); + var output = new StringOutput { - var callHandler = CreateServerCallHandler(); - var output = new StringOutput - { - StringValue = "test-out" - }; - var objInfo = callHandler.ReturnBytesToObject(output.ToByteArray()); - objInfo.ShouldNotBeNull(); + StringValue = "test-out" + }; + var objInfo = callHandler.ReturnBytesToObject(output.ToByteArray()); + objInfo.ShouldNotBeNull(); - var output1 = (StringOutput) objInfo; - output1.ShouldBe(output); - } + var output1 = (StringOutput)objInfo; + output1.ShouldBe(output); + } - [Fact] - public void ReturnBytesToString_Test() + [Fact] + public void ReturnBytesToString_Test() + { + var callHandler = CreateServerCallHandler(); + var output = new StringOutput { - var callHandler = CreateServerCallHandler(); - var output = new StringOutput() - { - StringValue = "test-out" - }; - var objString = callHandler.ReturnBytesToString(output.ToByteArray()); - objString.ShouldBe("{ \"stringValue\": \"test-out\" }"); - } + StringValue = "test-out" + }; + var objString = callHandler.ReturnBytesToString(output.ToByteArray()); + objString.ShouldBe("{ \"stringValue\": \"test-out\" }"); + } - private IServerCallHandler CreateServerCallHandler(bool isView = false) - { - var method = CreateMethod(isView); - var handler = CreateHandler(); - return ServerCalls.UnaryCall(method, handler); - } + private IServerCallHandler CreateServerCallHandler(bool isView = false) + { + var method = CreateMethod(isView); + var handler = CreateHandler(); + return ServerCalls.UnaryCall(method, handler); + } - private Method CreateMethod(bool isView) - { - Func serializer = input => input.ToByteArray(); - Func deserializer = input => StringInput.Parser.ParseFrom(input); + private Method CreateMethod(bool isView) + { + Func serializer = input => input.ToByteArray(); + Func deserializer = input => StringInput.Parser.ParseFrom(input); - Func serializer1 = input => input.ToByteArray(); - Func deserializer1 = input => StringOutput.Parser.ParseFrom(input); + Func serializer1 = input => input.ToByteArray(); + Func deserializer1 = input => StringOutput.Parser.ParseFrom(input); - return new Method(isView ? MethodType.View : MethodType.Action, - nameof(TestContract), nameof(TestContract.TestStringState), - new Marshaller(serializer, deserializer), - new Marshaller(serializer1, deserializer1)); - } + return new Method(isView ? MethodType.View : MethodType.Action, + nameof(TestContract), nameof(TestContract.TestStringState), + new Marshaller(serializer, deserializer), + new Marshaller(serializer1, deserializer1)); + } - private UnaryServerMethod CreateHandler() - { - UnaryServerMethod handler = - input => new StringOutput - { - StringValue = input.StringValue - }; - return handler; - } + private UnaryServerMethod CreateHandler() + { + UnaryServerMethod handler = + input => new StringOutput + { + StringValue = input.StringValue + }; + return handler; } } \ No newline at end of file diff --git a/test/AElf.Runtime.CSharp.Tests/SmartContractRunnerTests.cs b/test/AElf.Runtime.CSharp.Tests/SmartContractRunnerTests.cs index 50b227ec3b..bdcc84719c 100644 --- a/test/AElf.Runtime.CSharp.Tests/SmartContractRunnerTests.cs +++ b/test/AElf.Runtime.CSharp.Tests/SmartContractRunnerTests.cs @@ -6,30 +6,29 @@ using Shouldly; using Xunit; -namespace AElf.Runtime.CSharp +namespace AElf.Runtime.CSharp; + +public sealed class SmartContractRunnerTests : CSharpRuntimeTestBase { - public sealed class SmartContractRunnerTests: CSharpRuntimeTestBase + [Fact] + public async Task Run_Test() { - [Fact] - public async Task Run_Test() + var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); + var smartContractRegistration = new SmartContractRegistration { - var contractCode = File.ReadAllBytes(typeof(TestContract).Assembly.Location); - var smartContractRegistration = new SmartContractRegistration() - { - Code = ByteString.CopyFrom(contractCode), - CodeHash = HashHelper.ComputeFrom(contractCode), - IsSystemContract = true - }; - - var sdkDir = Path.GetDirectoryName(typeof(CSharpSmartContractRunner).Assembly.Location); - var smartContractRunner = new CSharpSmartContractRunner(sdkDir); - - var executive = await smartContractRunner.RunAsync(smartContractRegistration); - executive.ShouldNotBe(null); - executive.ContractHash.ShouldBe(smartContractRegistration.CodeHash); - executive.ContractVersion.ShouldBe("1.0.0.0"); - - smartContractRunner.ContractVersion.ShouldBe("1.0.0.0"); - } + Code = ByteString.CopyFrom(contractCode), + CodeHash = HashHelper.ComputeFrom(contractCode), + IsSystemContract = true + }; + + var sdkDir = Path.GetDirectoryName(typeof(CSharpSmartContractRunner).Assembly.Location); + var smartContractRunner = new CSharpSmartContractRunner(sdkDir); + + var executive = await smartContractRunner.RunAsync(smartContractRegistration); + executive.ShouldNotBe(null); + executive.ContractHash.ShouldBe(smartContractRegistration.CodeHash); + executive.ContractVersion.ShouldBe("1.0.0.0"); + + smartContractRunner.ContractVersion.ShouldBe("1.0.0.0"); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContractState.cs b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContractState.cs index 5acb12d22a..3ea610899c 100644 --- a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContractState.cs +++ b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContractState.cs @@ -1,39 +1,38 @@ -using AElf.Standards.ACS0; using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS0; using AElf.Types; -namespace AElf.Sdk.CSharp.Tests.TestContract +namespace AElf.Sdk.CSharp.Tests.TestContract; + +public class TokenInfoState : StructuredState +{ + public StringState Symbol { get; set; } + public StringState TokenName { get; set; } + public UInt64State TotalSupply { get; set; } + public UInt32State Decimals { get; set; } +} + +public class BalanceMappedState : MappedState +{ +} + +public class AllowanceMappedState : MappedState { - public class TokenInfoState : StructuredState - { - public StringState Symbol { get; set; } - public StringState TokenName { get; set; } - public UInt64State TotalSupply { get; set; } - public UInt32State Decimals { get; set; } - } - - public class BalanceMappedState : MappedState - { - } - - public class AllowanceMappedState : MappedState - { - } - - public class MethodFeesMappedState : MappedState - { - } - - public class TokenContractState : ContractState - { - public MethodFeesMappedState TransactionFees { get; set; } - public BoolState Initialized { get; set; } - public TokenInfoState TokenInfo { get; set; } - public BalanceMappedState Balances { get; set; } - public AllowanceMappedState Allowances { get; set; } - - public ReadonlyState NativeTokenSymbol { get; set; } - - internal ACS0Container.ACS0ReferenceState ZeroContract { get; set; } - } +} + +public class MethodFeesMappedState : MappedState +{ +} + +public class TokenContractState : ContractState +{ + public MethodFeesMappedState TransactionFees { get; set; } + public BoolState Initialized { get; set; } + public TokenInfoState TokenInfo { get; set; } + public BalanceMappedState Balances { get; set; } + public AllowanceMappedState Allowances { get; set; } + + public ReadonlyState NativeTokenSymbol { get; set; } + + internal ACS0Container.ACS0ReferenceState ZeroContract { get; set; } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Actions.cs b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Actions.cs index 330581de8a..d017012666 100644 --- a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Actions.cs +++ b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Actions.cs @@ -2,77 +2,76 @@ using AElf.CSharp.Core; using AElf.Types; -namespace AElf.Sdk.CSharp.Tests.TestContract +namespace AElf.Sdk.CSharp.Tests.TestContract; + +public partial class TokenContract : CSharpSmartContract { - public partial class TokenContract : CSharpSmartContract + public void Initialize(string symbol, string tokenName, ulong totalSupply, uint decimals) { - public void Initialize(string symbol, string tokenName, ulong totalSupply, uint decimals) - { - Assert(!State.Initialized.Value, "Already initialized."); - - // Set token info - State.TokenInfo.Symbol.Value = symbol; - State.TokenInfo.TokenName.Value = tokenName; - State.TokenInfo.TotalSupply.Value = totalSupply; - State.TokenInfo.Decimals.Value = decimals; + Assert(!State.Initialized.Value, "Already initialized."); - State.NativeTokenSymbol.Value = symbol; + // Set token info + State.TokenInfo.Symbol.Value = symbol; + State.TokenInfo.TokenName.Value = tokenName; + State.TokenInfo.TotalSupply.Value = totalSupply; + State.TokenInfo.Decimals.Value = decimals; - // Assign total supply to owner - State.Balances[Context.Sender] = totalSupply; + State.NativeTokenSymbol.Value = symbol; - // Set initialized flag - State.Initialized.Value = true; - } + // Assign total supply to owner + State.Balances[Context.Sender] = totalSupply; - public void ResetNativeTokenSymbol(string symbol) - { - State.NativeTokenSymbol.Value = symbol; - } + // Set initialized flag + State.Initialized.Value = true; + } - public void Transfer(Address to, ulong amount) - { - var from = Context.Sender; - DoTransfer(from, to, amount); - } + public void ResetNativeTokenSymbol(string symbol) + { + State.NativeTokenSymbol.Value = symbol; + } - public void TransferFrom(Address from, Address to, ulong amount) - { - var allowance = State.Allowances[from][Context.Sender]; - Assert(allowance >= amount, "Insufficient allowance."); + public void Transfer(Address to, ulong amount) + { + var from = Context.Sender; + DoTransfer(from, to, amount); + } + + public void TransferFrom(Address from, Address to, ulong amount) + { + var allowance = State.Allowances[from][Context.Sender]; + Assert(allowance >= amount, "Insufficient allowance."); - DoTransfer(from, to, amount); - State.Allowances[from][Context.Sender] = allowance.Sub(amount); - } + DoTransfer(from, to, amount); + State.Allowances[from][Context.Sender] = allowance.Sub(amount); + } - public void Approve(Address spender, ulong amount) - { - State.Allowances[Context.Sender][spender] = State.Allowances[Context.Sender][spender].Add(amount); - } + public void Approve(Address spender, ulong amount) + { + State.Allowances[Context.Sender][spender] = State.Allowances[Context.Sender][spender].Add(amount); + } - public void UnApprove(Address spender, ulong amount) - { - var oldAllowance = State.Allowances[Context.Sender][spender]; - var amountOrAll = Math.Min(amount, oldAllowance); - State.Allowances[Context.Sender][spender] = oldAllowance.Sub(amountOrAll); - } + public void UnApprove(Address spender, ulong amount) + { + var oldAllowance = State.Allowances[Context.Sender][spender]; + var amountOrAll = Math.Min(amount, oldAllowance); + State.Allowances[Context.Sender][spender] = oldAllowance.Sub(amountOrAll); + } - public void Burn(ulong amount) - { - var existingBalance = State.Balances[Context.Sender]; - Assert(existingBalance >= amount, "Burner doesn't own enough balance."); - State.Balances[Context.Sender] = existingBalance.Sub(amount); - State.TokenInfo.TotalSupply.Value = State.TokenInfo.TotalSupply.Value.Sub(amount); - } + public void Burn(ulong amount) + { + var existingBalance = State.Balances[Context.Sender]; + Assert(existingBalance >= amount, "Burner doesn't own enough balance."); + State.Balances[Context.Sender] = existingBalance.Sub(amount); + State.TokenInfo.TotalSupply.Value = State.TokenInfo.TotalSupply.Value.Sub(amount); + } - public ulong GetMethodFee(string methodName) - { - return State.TransactionFees[methodName]; - } + public ulong GetMethodFee(string methodName) + { + return State.TransactionFees[methodName]; + } - public void SetMethodFee(string methodName, ulong fee) - { - State.TransactionFees[methodName] = fee; - } + public void SetMethodFee(string methodName, ulong fee) + { + State.TransactionFees[methodName] = fee; } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Helper.cs b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Helper.cs index f188ed5ee8..80a77f99b9 100644 --- a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Helper.cs +++ b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Helper.cs @@ -1,17 +1,16 @@ using AElf.CSharp.Core; using AElf.Types; -namespace AElf.Sdk.CSharp.Tests.TestContract +namespace AElf.Sdk.CSharp.Tests.TestContract; + +public partial class TokenContract { - public partial class TokenContract + private void DoTransfer(Address from, Address to, ulong amount) { - private void DoTransfer(Address from, Address to, ulong amount) - { - var balanceOfSender = State.Balances[from]; - Assert(balanceOfSender >= amount, $"Insufficient balance. Current balance: {balanceOfSender}"); - var balanceOfReceiver = State.Balances[to]; - State.Balances[from] = balanceOfSender.Sub(amount); - State.Balances[to] = balanceOfReceiver.Add(amount); - } + var balanceOfSender = State.Balances[from]; + Assert(balanceOfSender >= amount, $"Insufficient balance. Current balance: {balanceOfSender}"); + var balanceOfReceiver = State.Balances[to]; + State.Balances[from] = balanceOfSender.Sub(amount); + State.Balances[to] = balanceOfReceiver.Add(amount); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Views.cs b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Views.cs index 8e764417ab..3339cb2593 100644 --- a/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Views.cs +++ b/test/AElf.Sdk.CSharp.Tests.TestContract/TokenContract_Views.cs @@ -1,63 +1,62 @@ using System.Linq; using AElf.Types; -namespace AElf.Sdk.CSharp.Tests.TestContract +namespace AElf.Sdk.CSharp.Tests.TestContract; + +public partial class TokenContract { - public partial class TokenContract - { - [View] - public string Symbol() - { - return State.TokenInfo.Symbol.Value; - } - - [View] - public string TokenName() - { - return State.TokenInfo.TokenName.Value; - } - - [View] - public ulong TotalSupply() - { - return State.TokenInfo.TotalSupply.Value; - } - - [View] - public uint Decimals() - { - return State.TokenInfo.Decimals.Value; - } - - [View] - public ulong BalanceOf(Address owner) - { - return State.Balances[owner]; - } - - [View] - public ulong Allowance(Address owner, Address spender) - { - return State.Allowances[owner][spender]; - } - - - [View] - public Hash GetVirtualAddressHash(int n) - { - return - HashHelper.ComputeFrom(Context.Sender.Value.Concat(n.ToBytes()).ToArray().ComputeHash()); - } - - [View] - public Address GetVirtualAddress(int n) - { - return Context.ConvertVirtualAddressToContractAddress(GetVirtualAddressHash(n)); - } - - public string NativeTokenSymbol() - { - return State.NativeTokenSymbol.Value; - } + [View] + public string Symbol() + { + return State.TokenInfo.Symbol.Value; + } + + [View] + public string TokenName() + { + return State.TokenInfo.TokenName.Value; + } + + [View] + public ulong TotalSupply() + { + return State.TokenInfo.TotalSupply.Value; + } + + [View] + public uint Decimals() + { + return State.TokenInfo.Decimals.Value; + } + + [View] + public ulong BalanceOf(Address owner) + { + return State.Balances[owner]; + } + + [View] + public ulong Allowance(Address owner, Address spender) + { + return State.Allowances[owner][spender]; + } + + + [View] + public Hash GetVirtualAddressHash(int n) + { + return + HashHelper.ComputeFrom(Context.Sender.Value.Concat(n.ToBytes()).ToArray().ComputeHash()); + } + + [View] + public Address GetVirtualAddress(int n) + { + return Context.ConvertVirtualAddressToContractAddress(GetVirtualAddressHash(n)); + } + + public string NativeTokenSymbol() + { + return State.NativeTokenSymbol.Value; } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/AElf.Sdk.CSharp.Tests.csproj b/test/AElf.Sdk.CSharp.Tests/AElf.Sdk.CSharp.Tests.csproj index 5a12610492..d61ee9c5c9 100644 --- a/test/AElf.Sdk.CSharp.Tests/AElf.Sdk.CSharp.Tests.csproj +++ b/test/AElf.Sdk.CSharp.Tests/AElf.Sdk.CSharp.Tests.csproj @@ -4,21 +4,21 @@ false - - - - - - - + + + + + + + - - - - - - - + + + + + + + \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/AElfStringTests.cs b/test/AElf.Sdk.CSharp.Tests/AElfStringTests.cs index f141e49c50..b779008ce4 100644 --- a/test/AElf.Sdk.CSharp.Tests/AElfStringTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/AElfStringTests.cs @@ -2,43 +2,43 @@ using Shouldly; using Xunit; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class AElfStringTests { - public class AElfStringTests + [Fact] + public void Concat_ArrayString_Test() { - [Fact] - public void Concat_ArrayString_Test() - { - var array = new[] {"test1", "test2", "test3", "test4"}; - var concatResult = AElfString.Concat(array); - var emptyInfo = string.Empty; - concatResult.ShouldBe(string.Join(emptyInfo, array)); - } + var array = new[] { "test1", "test2", "test3", "test4" }; + var concatResult = AElfString.Concat(array); + var emptyInfo = string.Empty; + concatResult.ShouldBe(string.Join(emptyInfo, array)); + } + + [Fact] + public void Concat_ArrayObj_Test() + { + var info = new object[] { 1, 2, 3, 4 }; + var concatResult = AElfString.Concat(info); + concatResult.ShouldBe("1234"); + } - [Fact] - public void Concat_ArrayObj_Test() - { - var info = new object[] {1, 2, 3, 4}; - var concatResult = AElfString.Concat(info); - concatResult.ShouldBe("1234"); - } + [Fact] + public void Concat_StringParameters_Test() + { + var info1 = "test1"; + var info2 = "test2"; + var info3 = "test3"; + var info4 = "test4"; - [Fact] - public void Concat_StringParameters_Test() - { - var info1 = "test1"; - var info2 = "test2"; - var info3 = "test3"; - var info4 = "test4"; + var result1 = AElfString.Concat(info1, info2); + result1.ShouldBe("test1test2"); - var result1 = AElfString.Concat(info1, info2); - result1.ShouldBe("test1test2"); + var result2 = AElfString.Concat(info1, info2, info3); + result2.ShouldBe("test1test2test3"); - var result2 = AElfString.Concat(info1, info2, info3); - result2.ShouldBe("test1test2test3"); - - var result3 = AElfString.Concat(info1, info2, info3,info4); - result3.ShouldBe("test1test2test3test4"); + var result3 = AElfString.Concat(info1, info2, info3, info4); + result3.ShouldBe("test1test2test3test4"); #if !DEBUG var result4 = result3; @@ -48,33 +48,32 @@ public void Concat_StringParameters_Test() } Assert.Throws(() => { AElfString.Concat(result4, result1);}); #endif - } + } - [Fact] - public void Concat_ObjectParameters_Test() - { - object info1 = 24; - object info2 = "test"; - object info3 = Hash.Empty; - object info4 = new[] {2, 4, 6}; + [Fact] + public void Concat_ObjectParameters_Test() + { + object info1 = 24; + object info2 = "test"; + object info3 = Hash.Empty; + object info4 = new[] { 2, 4, 6 }; - var result1 = AElfString.Concat(info1, info2); - result1.ShouldBe("24test"); + var result1 = AElfString.Concat(info1, info2); + result1.ShouldBe("24test"); - var result2 = AElfString.Concat(info1, info2, info3); - result2.ShouldBe("24test" + info3); + var result2 = AElfString.Concat(info1, info2, info3); + result2.ShouldBe("24test" + info3); - var result3 = AElfString.Concat(info1, info2, info3, info4); - result3.ShouldBe("24test" + info3 + info4); - } + var result3 = AElfString.Concat(info1, info2, info3, info4); + result3.ShouldBe("24test" + info3 + info4); + } - [Fact] - public void StringExtensions_Test() - { - var str1 = "test1"; - var str2 = "test2"; - str1.Append(str2).ShouldBe("test1test2"); - str1.AppendLine(str2).ShouldBe("test1\ntest2"); - } + [Fact] + public void StringExtensions_Test() + { + var str1 = "test1"; + var str2 = "test2"; + str1.Append(str2).ShouldBe("test1test2"); + str1.AppendLine(str2).ShouldBe("test1\ntest2"); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/CSharpSmartContractContextTests.cs b/test/AElf.Sdk.CSharp.Tests/CSharpSmartContractContextTests.cs index 00aafd5948..4e0f98d97a 100644 --- a/test/AElf.Sdk.CSharp.Tests/CSharpSmartContractContextTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/CSharpSmartContractContextTests.cs @@ -1,53 +1,52 @@ +using AElf.Cryptography; using AElf.Kernel; using AElf.Kernel.SmartContract; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; using CustomContract = AElf.Runtime.CSharp.Tests.TestContract; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class CSharpSmartContractContextTests : SdkCSharpTestBase { - public class CSharpSmartContractContextTests : SdkCSharpTestBase + [Fact] + public void Verify_Transaction_Origin_SetValue() { - [Fact] - public void Verify_Transaction_Origin_SetValue() + var bridgeContext = GetRequiredService().Create(); + var origin = SampleAddress.AddressList[0]; + bridgeContext.TransactionContext = new TransactionContext { - var bridgeContext = GetRequiredService().Create(); - var origin = SampleAddress.AddressList[0]; - bridgeContext.TransactionContext = new TransactionContext + Origin = origin, + Transaction = new Transaction { - Origin = origin, - Transaction = new Transaction() - { - From = SampleAddress.AddressList[1], - To = SampleAddress.AddressList[2] - } - }; - var contractContext = new CSharpSmartContractContext(bridgeContext); - contractContext.Origin.ShouldBe(origin); - contractContext.Origin.ShouldNotBe(bridgeContext.TransactionContext.Transaction.From); - } + From = SampleAddress.AddressList[1], + To = SampleAddress.AddressList[2] + } + }; + var contractContext = new CSharpSmartContractContext(bridgeContext); + contractContext.Origin.ShouldBe(origin); + contractContext.Origin.ShouldNotBe(bridgeContext.TransactionContext.Transaction.From); + } - [Fact] - public void Transaction_VerifySignature_Test() + [Fact] + public void Transaction_VerifySignature_Test() + { + var keyPair = CryptoHelper.GenerateKeyPair(); + var transaction = new Transaction { - var keyPair = Cryptography.CryptoHelper.GenerateKeyPair(); - var transaction = new Transaction - { - From = Address.FromPublicKey(keyPair.PublicKey), - To = SampleAddress.AddressList[2], - MethodName = "Test", - RefBlockNumber = 100 - }; - var signature = Cryptography.CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - var bridgeContext = GetRequiredService().Create(); - var result = bridgeContext.VerifySignature(transaction); - result.ShouldBeTrue(); - } + From = Address.FromPublicKey(keyPair.PublicKey), + To = SampleAddress.AddressList[2], + MethodName = "Test", + RefBlockNumber = 100 + }; + var signature = CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + var bridgeContext = GetRequiredService().Create(); + var result = bridgeContext.VerifySignature(transaction); + result.ShouldBeTrue(); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/ContractTest.cs b/test/AElf.Sdk.CSharp.Tests/ContractTest.cs index 5b8aa4ad42..c8b6e901c9 100644 --- a/test/AElf.Sdk.CSharp.Tests/ContractTest.cs +++ b/test/AElf.Sdk.CSharp.Tests/ContractTest.cs @@ -1,216 +1,211 @@ using System; using AElf.Kernel; using AElf.Kernel.SmartContract.Application; -using Xunit; -using Shouldly; using AElf.Sdk.CSharp.Tests.TestContract; using AElf.Types; +using Shouldly; +using Xunit; + +namespace AElf.Sdk.CSharp.Tests; -namespace AElf.Sdk.CSharp.Tests +public sealed class ContractTest : SdkCSharpTestBase { - public sealed class ContractTest : SdkCSharpTestBase + public ContractTest() { - private TokenContract Contract { get; } = new TokenContract(); + BridgeContext.TransactionContext = TransactionContext; + Contract.InternalInitialize(BridgeContext); + } - - public ContractTest() - { - BridgeContext.TransactionContext = TransactionContext; - Contract.InternalInitialize(BridgeContext); - } + private TokenContract Contract { get; } = new(); - private void Init_Test() - { - Contract.Initialize("ELF", "elf test token", 1000000, 9); - Contract.Symbol().ShouldBe("ELF"); - Contract.TokenName().ShouldBe("elf test token"); - Contract.TotalSupply().ShouldBe(1000000UL); - Contract.Decimals().ShouldBe(9U); - var balance = Contract.BalanceOf(AddressList[1]); - balance.ShouldBe(1000000UL); - } - - [Fact] - public void Init_Again_Test() - { - Init_Test(); - Should.Throw(() => { Contract.Initialize("ELF", "elf test token again", 1000000, 0); }); - } + private void Init_Test() + { + Contract.Initialize("ELF", "elf test token", 1000000, 9); + Contract.Symbol().ShouldBe("ELF"); + Contract.TokenName().ShouldBe("elf test token"); + Contract.TotalSupply().ShouldBe(1000000UL); + Contract.Decimals().ShouldBe(9U); + var balance = Contract.BalanceOf(AddressList[1]); + balance.ShouldBe(1000000UL); + } - [Fact] - public void Transfer_With_Enough_Token() - { - Init_Test(); - Contract.Transfer(AddressList[2], 100UL); - var balance = Contract.BalanceOf(AddressList[2]); + [Fact] + public void Init_Again_Test() + { + Init_Test(); + Should.Throw(() => { Contract.Initialize("ELF", "elf test token again", 1000000, 0); }); + } - balance.ShouldBe(100UL); - } + [Fact] + public void Transfer_With_Enough_Token() + { + Init_Test(); + Contract.Transfer(AddressList[2], 100UL); + var balance = Contract.BalanceOf(AddressList[2]); - [Fact] - public void Transfer_Without_Enough_Token() - { - Init_Test(); - Contract.Transfer(AddressList[2], 100UL); + balance.ShouldBe(100UL); + } - SwitchOwner(AddressList[2]); - Should.Throw(() => { Contract.Transfer(AddressList[3], 200UL); }); - } + [Fact] + public void Transfer_Without_Enough_Token() + { + Init_Test(); + Contract.Transfer(AddressList[2], 100UL); - [Fact] - public void Transfer_To_Null_User_Test() - { - Init_Test(); - Should.Throw(() => { Contract.Transfer(null, 100UL); }); - } + SwitchOwner(AddressList[2]); + Should.Throw(() => { Contract.Transfer(AddressList[3], 200UL); }); + } - [Fact] - public void Approve_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 1000UL); - var allowance = Contract.Allowance(AddressList[1], AddressList[2]); - allowance.ShouldBe(1000UL); - } - - [Fact] - public void UnApprove_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 1000UL); - Contract.UnApprove(AddressList[2], 500UL); - var allowance = Contract.Allowance(AddressList[1], AddressList[2]); - allowance.ShouldBe(500UL); - } - - [Fact] - public void UnApprove_Available_Token_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 500UL); - Contract.UnApprove(AddressList[2], 1000UL); - var allowance = Contract.Allowance(AddressList[1], AddressList[2]); - allowance.ShouldBe(0UL); - } - - [Fact] - public void TransferFrom_Available_Token_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 500UL); - SwitchOwner(AddressList[2]); - Contract.TransferFrom(AddressList[1], AddressList[2], 500UL); - var balance1 = Contract.BalanceOf(AddressList[1]); - var balance2 = Contract.BalanceOf(AddressList[2]); - balance1.ShouldBe(Contract.TotalSupply() - 500UL); - balance2.ShouldBe(500UL); - } - - [Fact] - public void TransferFrom_Over_Token_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 500UL); - SwitchOwner(AddressList[2]); - Should.Throw(() => { Contract.TransferFrom(AddressList[1], AddressList[2], 1000UL); }); - } - - [Fact] - public void TransferFrom_MultipleTimes_Available_Token_Test() - { - Init_Test(); - Contract.Approve(AddressList[2], 1000UL); - SwitchOwner(AddressList[2]); - Contract.TransferFrom(AddressList[1], AddressList[2], 300UL); - Contract.TransferFrom(AddressList[1], AddressList[2], 500UL); - var balance2 = Contract.BalanceOf(AddressList[2]); - balance2.ShouldBe(800UL); - } - - [Fact] - public void Burn_Test() - { - Init_Test(); - Contract.Burn(1000UL); - - var balance = Contract.BalanceOf(AddressList[1]); - Contract.TotalSupply().ShouldBe(999000UL); - balance.ShouldBe(999000UL); - - //over token - Should.Throw(() => - { - Contract.Burn(100000000UL); - }); - } - - [Fact] - public void SetMethodFee_Test() - { - Init_Test(); - var fee = Contract.GetMethodFee("Transfer"); - fee.ShouldBe(0UL); + [Fact] + public void Transfer_To_Null_User_Test() + { + Init_Test(); + Should.Throw(() => { Contract.Transfer(null, 100UL); }); + } - Contract.SetMethodFee("Transfer", 10UL); - var fee1 = Contract.GetMethodFee("Transfer"); - fee1.ShouldBe(10UL); + [Fact] + public void Approve_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 1000UL); + var allowance = Contract.Allowance(AddressList[1], AddressList[2]); + allowance.ShouldBe(1000UL); + } - Contract.SetMethodFee("Transfer", 20UL); - var fee2 = Contract.GetMethodFee("Transfer"); - fee2.ShouldBe(20UL); - } + [Fact] + public void UnApprove_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 1000UL); + Contract.UnApprove(AddressList[2], 500UL); + var allowance = Contract.Allowance(AddressList[1], AddressList[2]); + allowance.ShouldBe(500UL); + } - [Fact] - public void GetVirtualAddressHash_Test() - { - var hash = Contract.GetVirtualAddressHash(10); - hash.ShouldNotBeNull(); - - var hash1 = Contract.GetVirtualAddressHash(10); - hash1.ShouldBe(hash); - - var hash2 = Contract.GetVirtualAddressHash(100); - hash2.ShouldNotBe(hash); - } - - - [Fact] - public void GetVirtualAddress_Test() + [Fact] + public void UnApprove_Available_Token_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 500UL); + Contract.UnApprove(AddressList[2], 1000UL); + var allowance = Contract.Allowance(AddressList[1], AddressList[2]); + allowance.ShouldBe(0UL); + } + + [Fact] + public void TransferFrom_Available_Token_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 500UL); + SwitchOwner(AddressList[2]); + Contract.TransferFrom(AddressList[1], AddressList[2], 500UL); + var balance1 = Contract.BalanceOf(AddressList[1]); + var balance2 = Contract.BalanceOf(AddressList[2]); + balance1.ShouldBe(Contract.TotalSupply() - 500UL); + balance2.ShouldBe(500UL); + } + + [Fact] + public void TransferFrom_Over_Token_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 500UL); + SwitchOwner(AddressList[2]); + Should.Throw(() => { Contract.TransferFrom(AddressList[1], AddressList[2], 1000UL); }); + } + + [Fact] + public void TransferFrom_MultipleTimes_Available_Token_Test() + { + Init_Test(); + Contract.Approve(AddressList[2], 1000UL); + SwitchOwner(AddressList[2]); + Contract.TransferFrom(AddressList[1], AddressList[2], 300UL); + Contract.TransferFrom(AddressList[1], AddressList[2], 500UL); + var balance2 = Contract.BalanceOf(AddressList[2]); + balance2.ShouldBe(800UL); + } + + [Fact] + public void Burn_Test() + { + Init_Test(); + Contract.Burn(1000UL); + + var balance = Contract.BalanceOf(AddressList[1]); + Contract.TotalSupply().ShouldBe(999000UL); + balance.ShouldBe(999000UL); + + //over token + Should.Throw(() => { Contract.Burn(100000000UL); }); + } + + [Fact] + public void SetMethodFee_Test() + { + Init_Test(); + var fee = Contract.GetMethodFee("Transfer"); + fee.ShouldBe(0UL); + + Contract.SetMethodFee("Transfer", 10UL); + var fee1 = Contract.GetMethodFee("Transfer"); + fee1.ShouldBe(10UL); + + Contract.SetMethodFee("Transfer", 20UL); + var fee2 = Contract.GetMethodFee("Transfer"); + fee2.ShouldBe(20UL); + } + + [Fact] + public void GetVirtualAddressHash_Test() + { + var hash = Contract.GetVirtualAddressHash(10); + hash.ShouldNotBeNull(); + + var hash1 = Contract.GetVirtualAddressHash(10); + hash1.ShouldBe(hash); + + var hash2 = Contract.GetVirtualAddressHash(100); + hash2.ShouldNotBe(hash); + } + + + [Fact] + public void GetVirtualAddress_Test() + { + var address = Contract.GetVirtualAddress(10); + address.Value.ShouldNotBeNull(); + + var address1 = Contract.GetVirtualAddress(10); + address1.ShouldBe(address); + + var address2 = Contract.GetVirtualAddress(100); + address2.ShouldNotBe(address); + } + + [Fact] + public void CannotResetNativeTokenSymbol_Test() + { + const string newSymbol = "TEST"; + Init_Test(); + Contract.ResetNativeTokenSymbol(newSymbol); + Contract.NativeTokenSymbol().ShouldNotBe(newSymbol); + } + + private void SwitchOwner(Address address) + { + var transactionContextFactory = GetRequiredService(); + var transactionContext = transactionContextFactory.Create(new Transaction { - var address = Contract.GetVirtualAddress(10); - address.Value.ShouldNotBeNull(); - - var address1 = Contract.GetVirtualAddress(10); - address1.ShouldBe(address); - - var address2 = Contract.GetVirtualAddress(100); - address2.ShouldNotBe(address); - } - - [Fact] - public void CannotResetNativeTokenSymbol_Test() + From = address, + To = AddressList[0], + MethodName = "Test" + }, new ChainContext { - const string newSymbol = "TEST"; - Init_Test(); - Contract.ResetNativeTokenSymbol(newSymbol); - Contract.NativeTokenSymbol().ShouldNotBe(newSymbol); - } + BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + BlockHeight = 1 + }); - private void SwitchOwner(Address address) - { - var transactionContextFactory = GetRequiredService(); - var transactionContext = transactionContextFactory.Create(new Transaction - { - From = address, - To = AddressList[0], - MethodName = "Test" - }, new ChainContext - { - BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - BlockHeight = 1 - }); - - BridgeContext.TransactionContext = transactionContext; - } + BridgeContext.TransactionContext = transactionContext; } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/ExecutionObserverTests.cs b/test/AElf.Sdk.CSharp.Tests/ExecutionObserverTests.cs index 1a650aa3cd..3a0a7fe224 100644 --- a/test/AElf.Sdk.CSharp.Tests/ExecutionObserverTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/ExecutionObserverTests.cs @@ -1,46 +1,45 @@ using Shouldly; using Xunit; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class ExecutionObserverTests { - public class ExecutionObserverTests + [Fact] + public void CallCount_Test() { - [Fact] - public void CallCount_Test() + var observer = new ExecutionObserver(-1, 5); + observer.GetCallCount().ShouldBe(0); + observer.CallCount(); + observer.GetCallCount().ShouldBe(1); + + observer = new ExecutionObserver(5, 5); + + for (var i = 0; i < 5; i++) { - var observer = new ExecutionObserver(-1, 5); - observer.GetCallCount().ShouldBe(0); observer.CallCount(); - observer.GetCallCount().ShouldBe(1); + observer.GetCallCount().ShouldBe(i + 1); + } - observer = new ExecutionObserver(5, 5); - - for (int i = 0; i < 5; i++) - { - observer.CallCount(); - observer.GetCallCount().ShouldBe(i + 1); - } + Assert.Throws(() => observer.CallCount()); + } - Assert.Throws(() => observer.CallCount()); - } - - [Fact] - public void BranchCount_Test() - { - var observer = new ExecutionObserver(5, -1); - observer.GetBranchCount().ShouldBe(0); - observer.BranchCount(); - observer.GetBranchCount().ShouldBe(1); + [Fact] + public void BranchCount_Test() + { + var observer = new ExecutionObserver(5, -1); + observer.GetBranchCount().ShouldBe(0); + observer.BranchCount(); + observer.GetBranchCount().ShouldBe(1); - observer = new ExecutionObserver(5, 5); - - for (int i = 0; i < 5; i++) - { - observer.BranchCount(); - observer.GetBranchCount().ShouldBe(i + 1); - } + observer = new ExecutionObserver(5, 5); - Assert.Throws(() => observer.BranchCount()); + for (var i = 0; i < 5; i++) + { + observer.BranchCount(); + observer.GetBranchCount().ShouldBe(i + 1); } + + Assert.Throws(() => observer.BranchCount()); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/MockStates.cs b/test/AElf.Sdk.CSharp.Tests/MockStates.cs index aa7b0bca60..bb53da58dd 100644 --- a/test/AElf.Sdk.CSharp.Tests/MockStates.cs +++ b/test/AElf.Sdk.CSharp.Tests/MockStates.cs @@ -3,38 +3,37 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class MockStructuredState : StructuredState +{ + public StringState StringState { get; set; } +} + +public class ElfTokenContractReference : ContractReferenceState { - public class MockStructuredState : StructuredState - { - public StringState StringState { get; set; } - } + public Action Action0 { get; set; } + public Action Action1 { get; set; } + public Action Action2 { get; set; } - public class ElfTokenContractReference : ContractReferenceState - { - public Action Action0 { get; set; } - public Action Action1 { get; set; } - public Action Action2 { get; set; } - - public int NotAction { get; set; } - public Func Func1 { get; set; } - public Func Func2 { get; set; } - public Func Func3 { get; set; } - - internal MethodReference MethodReference { get; set; } - } + public int NotAction { get; set; } + public Func Func1 { get; set; } + public Func Func2 { get; set; } + public Func Func3 { get; set; } - public class MockContractState : ContractState - { - public BoolState BoolState { get; set; } - public Int32State Int32State { get; set; } - public UInt32State UInt32State { get; set; } - public Int64State Int64State { get; set; } - public UInt64State UInt64State { get; set; } - public StringState StringState { get; set; } - public BytesState BytesState { get; set; } - public MockStructuredState StructuredState { get; set; } - public MappedState MappedState { get; set; } - public ElfTokenContractReference ElfToken { get; set; } - } + internal MethodReference MethodReference { get; set; } +} + +public class MockContractState : ContractState +{ + public BoolState BoolState { get; set; } + public Int32State Int32State { get; set; } + public UInt32State UInt32State { get; set; } + public Int64State Int64State { get; set; } + public UInt64State UInt64State { get; set; } + public StringState StringState { get; set; } + public BytesState BytesState { get; set; } + public MockStructuredState StructuredState { get; set; } + public MappedState MappedState { get; set; } + public ElfTokenContractReference ElfToken { get; set; } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/SafeMathTests.cs b/test/AElf.Sdk.CSharp.Tests/SafeMathTests.cs index 1d75b85a51..65ccf1afd6 100644 --- a/test/AElf.Sdk.CSharp.Tests/SafeMathTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/SafeMathTests.cs @@ -1,70 +1,68 @@ using System; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -using Xunit; using Shouldly; +using Xunit; + +namespace AElf.Sdk.CSharp.Tests; -namespace AElf.Sdk.CSharp.Tests +public class SafeMathTests { - public class SafeMathTests + [Fact] + public void Int_And_UInt_Test() { - [Fact] - public void Int_And_UInt_Test() - { - 5.Mul(6).ShouldBe(30); - (-5).Mul(6).ShouldBe(-30); - Should.Throw(() => { 5.Mul(int.MaxValue); }); - Should.Throw(() => { (-5).Mul(int.MaxValue); }); + 5.Mul(6).ShouldBe(30); + (-5).Mul(6).ShouldBe(-30); + Should.Throw(() => { 5.Mul(int.MaxValue); }); + Should.Throw(() => { (-5).Mul(int.MaxValue); }); - 10.Div(2).ShouldBe(5); - 10.Div(-2).ShouldBe(-5); - Should.Throw(() => { 5.Div(0); }); - Should.Throw(() => { (-5).Div(0); }); + 10.Div(2).ShouldBe(5); + 10.Div(-2).ShouldBe(-5); + Should.Throw(() => { 5.Div(0); }); + Should.Throw(() => { (-5).Div(0); }); - 10.Sub(5).ShouldBe(5); - 10.Sub(-5).ShouldBe(15); - Should.Throw(() => { int.MaxValue.Sub(-5); }); - Should.Throw(() => { uint.MinValue.Sub(5); }); + 10.Sub(5).ShouldBe(5); + 10.Sub(-5).ShouldBe(15); + Should.Throw(() => { int.MaxValue.Sub(-5); }); + Should.Throw(() => { uint.MinValue.Sub(5); }); - 10.Add(5).ShouldBe(15); - 10.Add(-5).ShouldBe(5); - Should.Throw(() => { int.MaxValue.Add(8); }); - Should.Throw(() => { uint.MaxValue.Add(8); }); + 10.Add(5).ShouldBe(15); + 10.Add(-5).ShouldBe(5); + Should.Throw(() => { int.MaxValue.Add(8); }); + Should.Throw(() => { uint.MaxValue.Add(8); }); - uint number1 = 30; - uint number2 = 10; - number1.Mul(number2).ShouldBe(300u); - Should.Throw(() => { number1.Mul(uint.MaxValue); }); + uint number1 = 30; + uint number2 = 10; + number1.Mul(number2).ShouldBe(300u); + Should.Throw(() => { number1.Mul(uint.MaxValue); }); - number1.Div(number2).ShouldBe(3u); - Should.Throw(() =>{ number1.Div(0u); }); - } + number1.Div(number2).ShouldBe(3u); + Should.Throw(() => { number1.Div(0u); }); + } - [Fact] - public void Int64_And_UInt64_Test() - { - ulong number1 = 6; - long number2 = 6; + [Fact] + public void Int64_And_UInt64_Test() + { + ulong number1 = 6; + long number2 = 6; - number1.Mul(6).ShouldBe(36UL); - number2.Mul(6).ShouldBe(36L); - Should.Throw(() => { number1.Div(0); }); - Should.Throw(() => { number2.Div(0); }); + number1.Mul(6).ShouldBe(36UL); + number2.Mul(6).ShouldBe(36L); + Should.Throw(() => { number1.Div(0); }); + Should.Throw(() => { number2.Div(0); }); - number1.Div(2).ShouldBe(3UL); - number2.Div(-2).ShouldBe(-3L); - Should.Throw(() => { 5.Div(0); }); - Should.Throw(() => { (-5).Div(0); }); + number1.Div(2).ShouldBe(3UL); + number2.Div(-2).ShouldBe(-3L); + Should.Throw(() => { 5.Div(0); }); + Should.Throw(() => { (-5).Div(0); }); - number1.Sub(5).ShouldBe(1UL); - number2.Sub(5).ShouldBe(1L); - Should.Throw(() => { long.MaxValue.Sub(-5); }); - Should.Throw(() => { ulong.MinValue.Sub(5); }); + number1.Sub(5).ShouldBe(1UL); + number2.Sub(5).ShouldBe(1L); + Should.Throw(() => { long.MaxValue.Sub(-5); }); + Should.Throw(() => { ulong.MinValue.Sub(5); }); - number1.Add(5).ShouldBe(11UL); - number2.Add(5).ShouldBe(11L); - Should.Throw(() => { long.MaxValue.Add(8); }); - Should.Throw(() => { ulong.MaxValue.Add(8); }); - } + number1.Add(5).ShouldBe(11UL); + number2.Add(5).ShouldBe(11L); + Should.Throw(() => { long.MaxValue.Add(8); }); + Should.Throw(() => { ulong.MaxValue.Add(8); }); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/SdkCSharpTestBase.cs b/test/AElf.Sdk.CSharp.Tests/SdkCSharpTestBase.cs index 597d31d531..69dd9993a9 100644 --- a/test/AElf.Sdk.CSharp.Tests/SdkCSharpTestBase.cs +++ b/test/AElf.Sdk.CSharp.Tests/SdkCSharpTestBase.cs @@ -6,32 +6,30 @@ using AElf.TestBase; using AElf.Types; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class SdkCSharpTestBase : AElfIntegratedTest { - public class SdkCSharpTestBase:AElfIntegratedTest + protected SdkCSharpTestBase() { - protected SdkCSharpTestBase() - { - StateProvider = GetRequiredService().CreateStateProvider(); - BridgeContext = GetRequiredService().Create(); - - var transactionContextFactory = GetRequiredService(); - TransactionContext = transactionContextFactory.Create(new Transaction - { - From = AddressList[1], - To = AddressList[0], - MethodName = "Test" - }, new ChainContext - { - BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - BlockHeight = 1 - }); - } - - private IStateProvider StateProvider { get; } - protected IHostSmartContractBridgeContext BridgeContext { get; } - protected ITransactionContext TransactionContext { get; } - protected List
AddressList { get; } = SampleAddress.AddressList.ToList(); + StateProvider = GetRequiredService().CreateStateProvider(); + BridgeContext = GetRequiredService().Create(); + var transactionContextFactory = GetRequiredService(); + TransactionContext = transactionContextFactory.Create(new Transaction + { + From = AddressList[1], + To = AddressList[0], + MethodName = "Test" + }, new ChainContext + { + BlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + BlockHeight = 1 + }); } + + private IStateProvider StateProvider { get; } + protected IHostSmartContractBridgeContext BridgeContext { get; } + protected ITransactionContext TransactionContext { get; } + protected List
AddressList { get; } = SampleAddress.AddressList.ToList(); } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/SerializationHelperTests.cs b/test/AElf.Sdk.CSharp.Tests/SerializationHelperTests.cs index 44324935f6..76c793f14c 100644 --- a/test/AElf.Sdk.CSharp.Tests/SerializationHelperTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/SerializationHelperTests.cs @@ -1,146 +1,144 @@ using System; using AElf.Kernel; -using AElf.Sdk.CSharp.State; using AElf.Types; using Google.Protobuf; using Shouldly; using Xunit; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class SerializationHelperTests { - public class SerializationHelperTests + [Fact] + public void Serialization_Bool_Test() { - [Fact] - public void Serialization_Bool_Test() - { - var boolValue = true; - var byteArray = SerializationHelper.Serialize(boolValue); - var serializeValue = SerializationHelper.Deserialize(byteArray); - boolValue.ShouldBe(serializeValue); + var boolValue = true; + var byteArray = SerializationHelper.Serialize(boolValue); + var serializeValue = SerializationHelper.Deserialize(byteArray); + boolValue.ShouldBe(serializeValue); - var boolValue1 = false; - var byteArray1 = SerializationHelper.Serialize(boolValue1); - var serializeValue1 = SerializationHelper.Deserialize(byteArray1); - boolValue1.ShouldBe(serializeValue1); - } + var boolValue1 = false; + var byteArray1 = SerializationHelper.Serialize(boolValue1); + var serializeValue1 = SerializationHelper.Deserialize(byteArray1); + boolValue1.ShouldBe(serializeValue1); + } - [Fact] - public void Serialization_Int_Test() - { - var intValue = new Random().Next(); - var byteArray = SerializationHelper.Serialize(intValue); - var serializeValue = SerializationHelper.Deserialize(byteArray); - intValue.ShouldBe(serializeValue); - } + [Fact] + public void Serialization_Int_Test() + { + var intValue = new Random().Next(); + var byteArray = SerializationHelper.Serialize(intValue); + var serializeValue = SerializationHelper.Deserialize(byteArray); + intValue.ShouldBe(serializeValue); + } - [Fact] - public void Serialization_UInt_Test() - { - var uintValue = Convert.ToUInt32(new Random().Next()); - var byteArray = SerializationHelper.Serialize(uintValue); - var serializeValue = SerializationHelper.Deserialize(byteArray); - uintValue.ShouldBe(serializeValue); - } + [Fact] + public void Serialization_UInt_Test() + { + var uintValue = Convert.ToUInt32(new Random().Next()); + var byteArray = SerializationHelper.Serialize(uintValue); + var serializeValue = SerializationHelper.Deserialize(byteArray); + uintValue.ShouldBe(serializeValue); + } - [Fact] - public void Serialization_Long_Test() + [Fact] + public void Serialization_Long_Test() + { + var longArray = new[] { long.MinValue, -10054, -100, -50, 0, 50, 100, 10005, long.MaxValue }; + foreach (var longValue in longArray) { - var longArray = new[] {long.MinValue, -10054, -100, -50, 0, 50, 100, 10005, long.MaxValue}; - foreach (var longValue in longArray) - { - var byteArray = SerializationHelper.Serialize(longValue); - var serializeValue = SerializationHelper.Deserialize(byteArray); - longValue.ShouldBe(serializeValue); - } + var byteArray = SerializationHelper.Serialize(longValue); + var serializeValue = SerializationHelper.Deserialize(byteArray); + longValue.ShouldBe(serializeValue); } + } - [Fact] - public void Serialization_ULong_Test() + [Fact] + public void Serialization_ULong_Test() + { + var ulongArray = new ulong[] { ulong.MinValue, 50, 100, 1004, ulong.MaxValue }; + foreach (var longValue in ulongArray) { - var ulongArray = new ulong[] { ulong.MinValue, 50, 100, 1004, ulong.MaxValue }; - foreach (var longValue in ulongArray) - { - var byteArray = SerializationHelper.Serialize(longValue); - var serializeValue = SerializationHelper.Deserialize(byteArray); - longValue.ShouldBe(serializeValue); - } + var byteArray = SerializationHelper.Serialize(longValue); + var serializeValue = SerializationHelper.Deserialize(byteArray); + longValue.ShouldBe(serializeValue); } + } - [Fact] - public void Serialization_UnSupported_Type() - { - //Serialize - var byteString = ByteString.CopyFromUtf8("ByteString shold not supported."); - Should.Throw(() => SerializationHelper.Serialize(byteString)); + [Fact] + public void Serialization_UnSupported_Type() + { + //Serialize + var byteString = ByteString.CopyFromUtf8("ByteString shold not supported."); + Should.Throw(() => SerializationHelper.Serialize(byteString)); - //Deserialize - var byteArray = byteString.ToByteArray(); - Should.Throw(() => SerializationHelper.Deserialize(byteArray)); - } + //Deserialize + var byteArray = byteString.ToByteArray(); + Should.Throw(() => SerializationHelper.Deserialize(byteArray)); + } - [Fact] - public void Serialization_ByteArray_Test() - { - //Hash test - var hash = HashHelper.ComputeFrom("hash"); - var hashArray = SerializationHelper.Serialize(hash); - var hash1 = SerializationHelper.Deserialize(hashArray); - hash.ShouldBe(hash1); + [Fact] + public void Serialization_ByteArray_Test() + { + //Hash test + var hash = HashHelper.ComputeFrom("hash"); + var hashArray = SerializationHelper.Serialize(hash); + var hash1 = SerializationHelper.Deserialize(hashArray); + hash.ShouldBe(hash1); - //Address test - var address = SampleAddress.AddressList[0]; - var addressArray = SerializationHelper.Serialize(address); - var address1 = SerializationHelper.Deserialize
(addressArray); - address.ShouldBe(address1); + //Address test + var address = SampleAddress.AddressList[0]; + var addressArray = SerializationHelper.Serialize(address); + var address1 = SerializationHelper.Deserialize
(addressArray); + address.ShouldBe(address1); - //Transaction test - var transaction = new Transaction - { - From = SampleAddress.AddressList[1], - To = SampleAddress.AddressList[2], - Params = ByteString.CopyFromUtf8("test"), - MethodName = "TestMethod", - RefBlockNumber = 1, - RefBlockPrefix = ByteString.Empty - }; - var transactionArray = SerializationHelper.Serialize(transaction); - var transaction1 = SerializationHelper.Deserialize(transactionArray); - transaction.ShouldBe(transaction1); + //Transaction test + var transaction = new Transaction + { + From = SampleAddress.AddressList[1], + To = SampleAddress.AddressList[2], + Params = ByteString.CopyFromUtf8("test"), + MethodName = "TestMethod", + RefBlockNumber = 1, + RefBlockPrefix = ByteString.Empty + }; + var transactionArray = SerializationHelper.Serialize(transaction); + var transaction1 = SerializationHelper.Deserialize(transactionArray); + transaction.ShouldBe(transaction1); - //Block header test - var header = new BlockHeader - { - ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - Height = AElfConstants.GenesisBlockHeight, - Bloom = ByteString.CopyFromUtf8("bloom"), - PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), - MerkleTreeRootOfTransactions = HashHelper.ComputeFrom("MerkleTreeRootOfTransactions"), - MerkleTreeRootOfWorldState = HashHelper.ComputeFrom("MerkleTreeRootOfWorldState"), - Time = TimestampHelper.GetUtcNow(), - MerkleTreeRootOfTransactionStatus = HashHelper.ComputeFrom("MerkleTreeRootOfTransactionStatus") - }; - var headerArray = SerializationHelper.Serialize(header); - var header1 = SerializationHelper.Deserialize(headerArray); - header.ShouldBe(header1); + //Block header test + var header = new BlockHeader + { + ChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + Height = AElfConstants.GenesisBlockHeight, + Bloom = ByteString.CopyFromUtf8("bloom"), + PreviousBlockHash = HashHelper.ComputeFrom("PreviousBlockHash"), + MerkleTreeRootOfTransactions = HashHelper.ComputeFrom("MerkleTreeRootOfTransactions"), + MerkleTreeRootOfWorldState = HashHelper.ComputeFrom("MerkleTreeRootOfWorldState"), + Time = TimestampHelper.GetUtcNow(), + MerkleTreeRootOfTransactionStatus = HashHelper.ComputeFrom("MerkleTreeRootOfTransactionStatus") + }; + var headerArray = SerializationHelper.Serialize(header); + var header1 = SerializationHelper.Deserialize(headerArray); + header.ShouldBe(header1); - //Block body test - var body = new BlockBody - { - TransactionIds = { transaction.GetHash() } - }; - var bodyArray = SerializationHelper.Serialize(body); - var body1 = SerializationHelper.Deserialize(bodyArray); - body.ShouldBe(body1); + //Block body test + var body = new BlockBody + { + TransactionIds = { transaction.GetHash() } + }; + var bodyArray = SerializationHelper.Serialize(body); + var body1 = SerializationHelper.Deserialize(bodyArray); + body.ShouldBe(body1); - //Block test - var block = new Block - { - Body = body, - Header = header, - }; - var blockArray = SerializationHelper.Serialize(block); - var block1 = SerializationHelper.Deserialize(blockArray); - block.ShouldBe(block1); - } + //Block test + var block = new Block + { + Body = body, + Header = header + }; + var blockArray = SerializationHelper.Serialize(block); + var block1 = SerializationHelper.Deserialize(blockArray); + block.ShouldBe(block1); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/StateTest.cs b/test/AElf.Sdk.CSharp.Tests/StateTest.cs index f3eb6748d5..9247e7d6a2 100644 --- a/test/AElf.Sdk.CSharp.Tests/StateTest.cs +++ b/test/AElf.Sdk.CSharp.Tests/StateTest.cs @@ -2,365 +2,345 @@ using System.Collections.Generic; using System.Linq; using AElf.Kernel; -using AElf.Sdk.CSharp.State; using AElf.Kernel.SmartContract; +using AElf.Sdk.CSharp.State; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Moq; using Shouldly; using Xunit; -using Type = System.Type; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class StateTest { - public class StateTest + internal T GetValue() { - internal T GetValue() - { - if (typeof(T) == typeof(bool)) - { - return (T) (object) true; - } - - if (typeof(T) == typeof(int)) - { - return (T) (object) (int) -12345; - } - - if (typeof(T) == typeof(uint)) - { - return (T) (object) (uint) 12345U; - } - - if (typeof(T) == typeof(long)) - { - return (T) (object) (long) -678910L; - } - - if (typeof(T) == typeof(ulong)) - { - return (T) (object) (ulong) 678910UL; - } - - if (typeof(T) == typeof(byte[])) - { - return (T) (object) ByteArrayHelper.HexStringToByteArray("302010"); - } - - if (typeof(T) == typeof(string)) - { - return (T) (object) "aelf"; - } - - if (typeof(T) == typeof(Address)) - { - return (T) (object) SampleAddress.AddressList[0]; - } - - throw new Exception("Not supported type."); - } - - private void SetValues(MockContractState state) - { - state.BoolState.Value = GetValue(); - state.Int32State.Value = GetValue(); - state.UInt32State.Value = GetValue(); - state.Int64State.Value = GetValue(); - state.UInt64State.Value = GetValue(); - state.StringState.Value = GetValue(); - state.BytesState.Value = GetValue(); - state.StructuredState.StringState.Value = GetValue(); - state.MappedState[GetValue
()][GetValue
()] = GetValue(); - } - - private void AssertDefault(MockContractState state) + if (typeof(T) == typeof(bool)) return (T)(object)true; + + if (typeof(T) == typeof(int)) return (T)(object)-12345; + + if (typeof(T) == typeof(uint)) return (T)(object)12345U; + + if (typeof(T) == typeof(long)) return (T)(object)-678910L; + + if (typeof(T) == typeof(ulong)) return (T)(object)678910UL; + + if (typeof(T) == typeof(byte[])) return (T)(object)ByteArrayHelper.HexStringToByteArray("302010"); + + if (typeof(T) == typeof(string)) return (T)(object)"aelf"; + + if (typeof(T) == typeof(Address)) return (T)(object)SampleAddress.AddressList[0]; + + throw new Exception("Not supported type."); + } + + private void SetValues(MockContractState state) + { + state.BoolState.Value = GetValue(); + state.Int32State.Value = GetValue(); + state.UInt32State.Value = GetValue(); + state.Int64State.Value = GetValue(); + state.UInt64State.Value = GetValue(); + state.StringState.Value = GetValue(); + state.BytesState.Value = GetValue(); + state.StructuredState.StringState.Value = GetValue(); + state.MappedState[GetValue
()][GetValue
()] = GetValue(); + } + + private void AssertDefault(MockContractState state) + { + Assert.False(state.BoolState.Value); + Assert.Equal(0, state.Int32State.Value); + Assert.Equal(0U, state.UInt32State.Value); + Assert.Equal(0, state.Int64State.Value); + Assert.Equal(0U, state.UInt64State.Value); + Assert.Equal("", state.StringState.Value); + Assert.Null(state.BytesState.Value); + Assert.Equal("", state.StructuredState.StringState.Value); + Assert.Equal("", state.MappedState[GetValue
()][GetValue
()]); + } + + private void AssertValues(MockContractState state) + { + Assert.Equal(GetValue(), state.BoolState.Value); + Assert.Equal(GetValue(), state.Int32State.Value); + Assert.Equal(GetValue(), state.UInt32State.Value); + Assert.Equal(GetValue(), state.Int64State.Value); + Assert.Equal(GetValue(), state.UInt64State.Value); + Assert.Equal(GetValue(), state.StringState.Value); + Assert.Equal(GetValue(), state.BytesState.Value); + Assert.Equal(GetValue(), state.StructuredState.StringState.Value); + Assert.Equal(GetValue(), state.MappedState[GetValue
()][GetValue
()]); + } + + [Fact] + public void State_Test() + { + var path = new StatePath(); + path.Parts.Add("dummy_address"); + var mockProvider = new Mock(); + var mockContext = new Mock(); + mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); + mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); + + var state = new MockContractState { - Assert.False(state.BoolState.Value); - Assert.Equal(0, state.Int32State.Value); - Assert.Equal(0U, state.UInt32State.Value); - Assert.Equal(0, state.Int64State.Value); - Assert.Equal(0U, state.UInt64State.Value); - Assert.Equal("", state.StringState.Value); - Assert.Null(state.BytesState.Value); - Assert.Equal("", state.StructuredState.StringState.Value); - Assert.Equal("", state.MappedState[GetValue
()][GetValue
()]); - } - - private void AssertValues(MockContractState state) + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + + // Initial default value + AssertDefault(state); + + // Set values + SetValues(state); + AssertValues(state); + + // Get changes + var changes = state.GetChanges(); + changes.Reads.Count.ShouldBeGreaterThan(0); + changes.Writes.Count.ShouldBeGreaterThan(0); + + state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]] = "test"; + state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] = "test2"; + state.MappedState[SampleAddress.AddressList[3]][SampleAddress.AddressList[4]] = "test3"; + state.MappedState[SampleAddress.AddressList[0]].Remove(SampleAddress.AddressList[1]); + state.MappedState[SampleAddress.AddressList[3]].Remove(SampleAddress.AddressList[4]); + state.MappedState[SampleAddress.AddressList[0]].Remove(SampleAddress.AddressList[4]); + state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBe("test2"); + state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]].ShouldBeNull(); + state.MappedState[SampleAddress.AddressList[0]].Set(SampleAddress.AddressList[5], "test5"); + state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[5]].ShouldBe("test5"); + var stateName = nameof(state.MappedState); + changes = state.GetChanges(); + changes.Deletes.Count.ShouldBe(3); + var key = string.Join("/", + SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, + SampleAddress.AddressList[0].ToString(), SampleAddress.AddressList[1].ToString() + ); + changes.Deletes.TryGetValue(key, out _).ShouldBeTrue(); + key = string.Join(",", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, + SampleAddress.AddressList[1].ToString(), SampleAddress.AddressList[2].ToString()); + changes.Deletes.TryGetValue(key, out _).ShouldBeFalse(); + key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, + SampleAddress.AddressList[3].ToString(), SampleAddress.AddressList[4].ToString()); + changes.Deletes.TryGetValue(key, out _).ShouldBeTrue(); + + key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, + SampleAddress.AddressList[4].ToString(), SampleAddress.AddressList[5].ToString()); + changes.Deletes.TryGetValue(key, out _).ShouldBeFalse(); + key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, + SampleAddress.AddressList[0].ToString(), SampleAddress.AddressList[4].ToString()); + changes.Deletes.TryGetValue(key, out _).ShouldBeTrue(); + changes.Reads.Count.ShouldBeGreaterThanOrEqualTo(changes.Deletes.Count + changes.Writes.Count); + + state.MappedState.OnContextSet(); + state.MappedState.Context.ShouldBe(state.MappedState[SampleAddress.AddressList[1]].Context); + + state.MappedState[SampleAddress.AddressList[1]].Clear(); + state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBe(string.Empty); + // Clear values + state.Clear(); + AssertDefault(state); + } + + [Fact] + public void MappedState_Test() + { + var path = new StatePath(); + path.Parts.Add("dummy_address"); + var mockProvider = new Mock(); + var mockContext = new Mock(); + mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); + mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); + + var state = new MappedState { - Assert.Equal(GetValue(), state.BoolState.Value); - Assert.Equal(GetValue(), state.Int32State.Value); - Assert.Equal(GetValue(), state.UInt32State.Value); - Assert.Equal(GetValue(), state.Int64State.Value); - Assert.Equal(GetValue(), state.UInt64State.Value); - Assert.Equal(GetValue(), state.StringState.Value); - Assert.Equal(GetValue(), state.BytesState.Value); - Assert.Equal(GetValue(), state.StructuredState.StringState.Value); - Assert.Equal(GetValue(), state.MappedState[GetValue
()][GetValue
()]); - } - - [Fact] - public void State_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] + .ShouldBe(string.Empty); + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] = "test"; + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] + .ShouldBe("test"); + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]].Remove(SampleAddress.AddressList[2]); + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBeNull(); + + state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[3]] = "test2"; + state.OnContextSet(); + state.Context.ShouldBe(state[SampleAddress.AddressList[0]].Context); + + var changes = state.GetChanges(); + changes.Deletes.Count.ShouldBe(1); + changes.Writes.Count.ShouldBe(1); + changes.Reads.Count.ShouldBe(changes.Deletes.Count + changes.Writes.Count); + + state.Clear(); + state.GetChanges().ShouldBe(new TransactionExecutingStateSet()); + + + var mapState = new MappedState { - var path = new StatePath(); - path.Parts.Add("dummy_address"); - var mockProvider = new Mock(); - var mockContext = new Mock(); - mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); - mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); - - var state = new MockContractState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - - // Initial default value - AssertDefault(state); - - // Set values - SetValues(state); - AssertValues(state); - - // Get changes - var changes = state.GetChanges(); - changes.Reads.Count.ShouldBeGreaterThan(0); - changes.Writes.Count.ShouldBeGreaterThan(0); - - state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]] = "test"; - state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] = "test2"; - state.MappedState[SampleAddress.AddressList[3]][SampleAddress.AddressList[4]] = "test3"; - state.MappedState[SampleAddress.AddressList[0]].Remove(SampleAddress.AddressList[1]); - state.MappedState[SampleAddress.AddressList[3]].Remove(SampleAddress.AddressList[4]); - state.MappedState[SampleAddress.AddressList[0]].Remove(SampleAddress.AddressList[4]); - state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBe("test2"); - state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]].ShouldBeNull(); - state.MappedState[SampleAddress.AddressList[0]].Set(SampleAddress.AddressList[5],"test5"); - state.MappedState[SampleAddress.AddressList[0]][SampleAddress.AddressList[5]].ShouldBe("test5"); - var stateName = nameof(state.MappedState); - changes = state.GetChanges(); - changes.Deletes.Count.ShouldBe(3); - var key = string.Join("/", - SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, - SampleAddress.AddressList[0].ToString(), SampleAddress.AddressList[1].ToString() - ); - changes.Deletes.TryGetValue(key,out _).ShouldBeTrue(); - key = string.Join(",", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, - SampleAddress.AddressList[1].ToString(), SampleAddress.AddressList[2].ToString()); - changes.Deletes.TryGetValue(key,out _).ShouldBeFalse(); - key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, - SampleAddress.AddressList[3].ToString(), SampleAddress.AddressList[4].ToString()); - changes.Deletes.TryGetValue(key,out _).ShouldBeTrue(); - - key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, - SampleAddress.AddressList[4].ToString(), SampleAddress.AddressList[5].ToString()); - changes.Deletes.TryGetValue(key,out _).ShouldBeFalse(); - key = string.Join("/", SampleAddress.AddressList[0].ToBase58(), "dummy_address", stateName, - SampleAddress.AddressList[0].ToString(), SampleAddress.AddressList[4].ToString()); - changes.Deletes.TryGetValue(key,out _).ShouldBeTrue(); - changes.Reads.Count.ShouldBeGreaterThanOrEqualTo(changes.Deletes.Count+ changes.Writes.Count); - - state.MappedState.OnContextSet(); - state.MappedState.Context.ShouldBe(state.MappedState[SampleAddress.AddressList[1]].Context); - - state.MappedState[SampleAddress.AddressList[1]].Clear(); - state.MappedState[SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBe(string.Empty); - // Clear values - state.Clear(); - AssertDefault(state); - } - - [Fact] - public void MappedState_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][ + SampleAddress.AddressList[3]] + .ShouldBe(string.Empty); + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][ + SampleAddress.AddressList[3]] = "test"; + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][ + SampleAddress.AddressList[3]] + .ShouldBe("test"); + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] + .Remove(SampleAddress.AddressList[3]); + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][ + SampleAddress.AddressList[3]].ShouldBeNull(); + + mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][ + SampleAddress.AddressList[4]] = "test2"; + mapState.OnContextSet(); + mapState.Context.ShouldBe(mapState[SampleAddress.AddressList[0]].Context); + + changes = mapState.GetChanges(); + changes.Deletes.Count.ShouldBe(1); + changes.Writes.Count.ShouldBe(1); + changes.Reads.Count.ShouldBe(changes.Deletes.Count + changes.Writes.Count); + + mapState.Clear(); + mapState.GetChanges().ShouldBe(new TransactionExecutingStateSet()); + } + + [Fact] + public void GetSubStatePath_Test() + { + var stateName = "Balances"; + var state = new MappedState(); + state.Path = new StatePath(); + state.Path.Parts.Add(stateName); + var key = "ELF"; + var statePath = state.GetSubStatePath(key); + statePath.Parts.Count.ShouldBe(2); + statePath.Parts[0].ShouldBe(stateName); + statePath.Parts[1].ShouldBe(key); + } + + + [Fact] + public void MethodReferenceExtensions_Test() + { + typeof(MethodReference).IsMethodReference().ShouldBeTrue(); + typeof(Dictionary).IsMethodReference().ShouldBeFalse(); + typeof(string).IsMethodReference().ShouldBeFalse(); + } + + [Fact] + public void ReadOnlyState_Test() + { + var path = new StatePath(); + path.Parts.Add("dummy_address"); + var mockProvider = new Mock(); + var mockContext = new Mock(); + mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); + mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); + var readOnlyState = new ReadonlyState { - var path = new StatePath(); - path.Parts.Add("dummy_address"); - var mockProvider = new Mock(); - var mockContext = new Mock(); - mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); - mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); - - var state = new MappedState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] - .ShouldBe(string.Empty); - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] = "test"; - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]] - .ShouldBe("test"); - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]].Remove(SampleAddress.AddressList[2]); - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].ShouldBeNull(); - - state[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[3]] = "test2"; - state.OnContextSet(); - state.Context.ShouldBe(state[SampleAddress.AddressList[0]].Context); - - var changes = state.GetChanges(); - changes.Deletes.Count.ShouldBe(1); - changes.Writes.Count.ShouldBe(1); - changes.Reads.Count.ShouldBe(changes.Deletes.Count + changes.Writes.Count); - - state.Clear(); - state.GetChanges().ShouldBe(new TransactionExecutingStateSet()); - - - var mapState = new MappedState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][SampleAddress.AddressList[3]] - .ShouldBe(string.Empty); - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][SampleAddress.AddressList[3]] = "test"; - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][SampleAddress.AddressList[3]] - .ShouldBe("test"); - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]].Remove(SampleAddress.AddressList[3]); - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][SampleAddress.AddressList[3]].ShouldBeNull(); - - mapState[SampleAddress.AddressList[0]][SampleAddress.AddressList[1]][SampleAddress.AddressList[2]][SampleAddress.AddressList[4]] = "test2"; - mapState.OnContextSet(); - mapState.Context.ShouldBe(mapState[SampleAddress.AddressList[0]].Context); - - changes = mapState.GetChanges(); - changes.Deletes.Count.ShouldBe(1); - changes.Writes.Count.ShouldBe(1); - changes.Reads.Count.ShouldBe(changes.Deletes.Count + changes.Writes.Count); - - mapState.Clear(); - mapState.GetChanges().ShouldBe(new TransactionExecutingStateSet()); - } - - [Fact] - public void GetSubStatePath_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + readOnlyState.Value.ShouldBe(default); + var intValue = 100; + var otherIntValue = 200; + readOnlyState.Value = intValue; + readOnlyState.Value.ShouldBe(intValue); + readOnlyState.Value = otherIntValue; + readOnlyState.Value.ShouldBe(intValue); + + var changes = readOnlyState.GetChanges(); + changes.Writes.Count.ShouldBe(1); + readOnlyState.Clear(); + readOnlyState.Loaded.ShouldBeFalse(); + readOnlyState.GetChanges().Writes.Count.ShouldBe(0); + + var otherReadOnlyState = new ReadonlyState { - var stateName = "Balances"; - var state = new MappedState(); - state.Path = new StatePath(); - state.Path.Parts.Add(stateName); - var key = "ELF"; - var statePath = state.GetSubStatePath(key); - statePath.Parts.Count.ShouldBe(2); - statePath.Parts[0].ShouldBe(stateName); - statePath.Parts[1].ShouldBe(key); - } - - - [Fact] - public void MethodReferenceExtensions_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object), + Value = intValue + }; + otherReadOnlyState.Value.ShouldBe(intValue); + + var stringReadOnlyState = new ReadonlyState { - typeof(MethodReference).IsMethodReference().ShouldBeTrue(); - typeof(Dictionary).IsMethodReference().ShouldBeFalse(); - typeof(string).IsMethodReference().ShouldBeFalse(); - } + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + var stringValue = "test"; + stringReadOnlyState.Value = stringValue; + stringReadOnlyState.Value.ShouldBe(string.Empty); + } - [Fact] - public void ReadOnlyState_Test() + [Fact] + public void SingletonState_Test() + { + var path = new StatePath(); + path.Parts.Add("dummy_address"); + var mockProvider = new Mock(); + var mockContext = new Mock(); + mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); + mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); + var singletonState = new SingletonState { - var path = new StatePath(); - path.Parts.Add("dummy_address"); - var mockProvider = new Mock(); - var mockContext = new Mock(); - mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); - mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); - var readOnlyState = new ReadonlyState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - readOnlyState.Value.ShouldBe(default); - var intValue = 100; - var otherIntValue = 200; - readOnlyState.Value = intValue; - readOnlyState.Value.ShouldBe(intValue); - readOnlyState.Value = otherIntValue; - readOnlyState.Value.ShouldBe(intValue); - - var changes = readOnlyState.GetChanges(); - changes.Writes.Count.ShouldBe(1); - readOnlyState.Clear(); - readOnlyState.Loaded.ShouldBeFalse(); - readOnlyState.GetChanges().Writes.Count.ShouldBe(0); - - var otherReadOnlyState = new ReadonlyState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object), - Value = intValue - }; - otherReadOnlyState.Value.ShouldBe(intValue); - - var stringReadOnlyState = new ReadonlyState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - var stringValue = "test"; - stringReadOnlyState.Value = stringValue; - stringReadOnlyState.Value.ShouldBe(string.Empty); - } - - [Fact] - public void SingletonState_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object) + }; + singletonState.Value.ShouldBe(default); + var intValue = 100; + singletonState.Value = intValue; + singletonState.Value.ShouldBe(intValue); + + singletonState.Modified.ShouldBeTrue(); + var changes = singletonState.GetChanges(); + changes.Writes.Count.ShouldBe(1); + singletonState.Clear(); + singletonState.Loaded.ShouldBeFalse(); + singletonState.Modified.ShouldBeFalse(); + singletonState.Value.ShouldBe(default); + singletonState.GetChanges().Writes.Count.ShouldBe(0); + + var otherReadOnlyState = new ReadonlyState { - var path = new StatePath(); - path.Parts.Add("dummy_address"); - var mockProvider = new Mock(); - var mockContext = new Mock(); - mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); - mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); - var singletonState = new SingletonState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object) - }; - singletonState.Value.ShouldBe(default); - var intValue = 100; - singletonState.Value = intValue; - singletonState.Value.ShouldBe(intValue); - - singletonState.Modified.ShouldBeTrue(); - var changes = singletonState.GetChanges(); - changes.Writes.Count.ShouldBe(1); - singletonState.Clear(); - singletonState.Loaded.ShouldBeFalse(); - singletonState.Modified.ShouldBeFalse(); - singletonState.Value.ShouldBe(default); - singletonState.GetChanges().Writes.Count.ShouldBe(0); - - var otherReadOnlyState = new ReadonlyState - { - Path = path, - Context = new CSharpSmartContractContext(mockContext.Object), - Value = intValue - }; - otherReadOnlyState.Value.ShouldBe(intValue); - } - - [Fact] - public void StateBase_Test() + Path = path, + Context = new CSharpSmartContractContext(mockContext.Object), + Value = intValue + }; + otherReadOnlyState.Value.ShouldBe(intValue); + } + + [Fact] + public void StateBase_Test() + { + var part = "test"; + var mockProvider = new Mock(); + var mockContext = new Mock(); + mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); + mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); + var stateBase = new StateBase(); + stateBase.Path = new StatePath { - var part = "test"; - var mockProvider = new Mock(); - var mockContext = new Mock(); - mockContext.SetupGet(o => o.StateProvider).Returns(mockProvider.Object); - mockContext.SetupGet(o => o.Self).Returns(SampleAddress.AddressList[0]); - var stateBase = new StateBase(); - stateBase.Path = new StatePath - { - Parts = {part} - }; - stateBase.Path.Parts.Single().ShouldBe(part); - var context = new CSharpSmartContractContext(mockContext.Object); - stateBase.Context = context; - stateBase.Context.ShouldBe(context); - stateBase.Provider.ShouldBe(mockProvider.Object); - stateBase.Clear(); - var transactionExecutingStateSet = new TransactionExecutingStateSet(); - stateBase.GetChanges().ShouldBe(transactionExecutingStateSet); - } + Parts = { part } + }; + stateBase.Path.Parts.Single().ShouldBe(part); + var context = new CSharpSmartContractContext(mockContext.Object); + stateBase.Context = context; + stateBase.Context.ShouldBe(context); + stateBase.Provider.ShouldBe(mockProvider.Object); + stateBase.Clear(); + var transactionExecutingStateSet = new TransactionExecutingStateSet(); + stateBase.GetChanges().ShouldBe(transactionExecutingStateSet); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/TestContractTests.cs b/test/AElf.Sdk.CSharp.Tests/TestContractTests.cs index 0e23f90ec1..f3da50a936 100644 --- a/test/AElf.Sdk.CSharp.Tests/TestContractTests.cs +++ b/test/AElf.Sdk.CSharp.Tests/TestContractTests.cs @@ -4,268 +4,268 @@ using Xunit; using CustomContract = AElf.Runtime.CSharp.Tests.TestContract; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +public class TestContractTests : SdkCSharpTestBase { - public class TestContractTests : SdkCSharpTestBase + private readonly CustomContract.TestContract Contract = new(); + + public TestContractTests() { - private CustomContract.TestContract Contract = new CustomContract.TestContract(); + BridgeContext.TransactionContext = TransactionContext; + Contract.InternalInitialize(BridgeContext); + } - public TestContractTests() + [Fact] + public void TestBoolState() + { + var input = new CustomContract.BoolInput { - BridgeContext.TransactionContext = TransactionContext; - Contract.InternalInitialize(BridgeContext); - } + BoolValue = true + }; - [Fact] - public void TestBoolState() - { - var input = new CustomContract.BoolInput - { - BoolValue = true - }; - - var output = Contract.TestBoolState(input); - output.BoolValue.ShouldBeTrue(); - - input.BoolValue = false; - output = Contract.TestBoolState(input); - output.BoolValue.ShouldBeFalse(); - } - - [Fact] - public void TestInt32State() - { - var input = new CustomContract.Int32Input - { - Int32Value = 36 - }; - var output = Contract.TestInt32State(input); - output.Int32Value.ShouldBe(-36); - - input.Int32Value = -100; - output = Contract.TestInt32State(input); - output.Int32Value.ShouldBe(64); - } - - [Fact] - public void UInt32Output() + var output = Contract.TestBoolState(input); + output.BoolValue.ShouldBeTrue(); + + input.BoolValue = false; + output = Contract.TestBoolState(input); + output.BoolValue.ShouldBeFalse(); + } + + [Fact] + public void TestInt32State() + { + var input = new CustomContract.Int32Input { - var input = new CustomContract.UInt32Input - { - UInt32Value = 24 - }; - var output = Contract.TestUInt32State(input); - output.UInt32Value.ShouldBe(24u); - - input.UInt32Value = 100; - output = Contract.TestUInt32State(input); - output.UInt32Value.ShouldBe(124u); - } - - [Fact] - public void TestInt64State() + Int32Value = 36 + }; + var output = Contract.TestInt32State(input); + output.Int32Value.ShouldBe(-36); + + input.Int32Value = -100; + output = Contract.TestInt32State(input); + output.Int32Value.ShouldBe(64); + } + + [Fact] + public void UInt32Output() + { + var input = new CustomContract.UInt32Input { - var input = new CustomContract.Int64Input - { - Int64Value = 36 - }; - var output = Contract.TestInt64State(input); - output.Int64Value.ShouldBe(-36); - - input.Int64Value = -100; - output = Contract.TestInt64State(input); - output.Int64Value.ShouldBe(64); - } - - [Fact] - public void TestUInt64State() + UInt32Value = 24 + }; + var output = Contract.TestUInt32State(input); + output.UInt32Value.ShouldBe(24u); + + input.UInt32Value = 100; + output = Contract.TestUInt32State(input); + output.UInt32Value.ShouldBe(124u); + } + + [Fact] + public void TestInt64State() + { + var input = new CustomContract.Int64Input { - var input = new CustomContract.UInt64Input - { - UInt64Value = 24 - }; - var output = Contract.TestUInt64State(input); - output.UInt64Value.ShouldBe(24ul); - - input.UInt64Value = 100; - output = Contract.TestUInt64State(input); - output.UInt64Value.ShouldBe(124ul); - } - - [Fact] - public void TestStringState() + Int64Value = 36 + }; + var output = Contract.TestInt64State(input); + output.Int64Value.ShouldBe(-36); + + input.Int64Value = -100; + output = Contract.TestInt64State(input); + output.Int64Value.ShouldBe(64); + } + + [Fact] + public void TestUInt64State() + { + var input = new CustomContract.UInt64Input { - var input = new CustomContract.StringInput - { - StringValue = "hello" - }; - var output = Contract.TestStringState(input); - output.StringValue.ShouldBe("hello"); - - input.StringValue = " elf"; - output = Contract.TestStringState(input); - output.StringValue.ShouldBe("hello elf"); - } - - [Fact] - public void TestBytesState() + UInt64Value = 24 + }; + var output = Contract.TestUInt64State(input); + output.UInt64Value.ShouldBe(24ul); + + input.UInt64Value = 100; + output = Contract.TestUInt64State(input); + output.UInt64Value.ShouldBe(124ul); + } + + [Fact] + public void TestStringState() + { + var input = new CustomContract.StringInput { - var input = new CustomContract.BytesInput - { - BytesValue = SampleAddress.AddressList[0].ToByteString() - }; + StringValue = "hello" + }; + var output = Contract.TestStringState(input); + output.StringValue.ShouldBe("hello"); - var output = Contract.TestBytesState(input); - output.BytesValue.ShouldBe(input.BytesValue); - } + input.StringValue = " elf"; + output = Contract.TestStringState(input); + output.StringValue.ShouldBe("hello elf"); + } - [Fact] - public void TestProtobufState() + [Fact] + public void TestBytesState() + { + var input = new CustomContract.BytesInput { - var input = new CustomContract.ProtobufInput - { - ProtobufValue = new CustomContract.ProtobufMessage - { - BoolValue = true, - Int64Value = 128, - StringValue = "test" - } - }; - - var output = Contract.TestProtobufState(input); - output.ProtobufValue.BoolValue.ShouldBeTrue(); - output.ProtobufValue.Int64Value.ShouldBe(128); - output.ProtobufValue.StringValue.ShouldBe("test"); - } - - [Fact] - public void TestComplex1State() + BytesValue = SampleAddress.AddressList[0].ToByteString() + }; + + var output = Contract.TestBytesState(input); + output.BytesValue.ShouldBe(input.BytesValue); + } + + [Fact] + public void TestProtobufState() + { + var input = new CustomContract.ProtobufInput { - var input = new CustomContract.Complex1Input + ProtobufValue = new CustomContract.ProtobufMessage { BoolValue = true, - Int32Value = 120 - }; - var output = Contract.TestComplex1State(input); - output.BoolValue.ShouldBe(true); - output.Int32Value.ShouldBe(120); - } - - [Fact] - public void TestComplex2State() + Int64Value = 128, + StringValue = "test" + } + }; + + var output = Contract.TestProtobufState(input); + output.ProtobufValue.BoolValue.ShouldBeTrue(); + output.ProtobufValue.Int64Value.ShouldBe(128); + output.ProtobufValue.StringValue.ShouldBe("test"); + } + + [Fact] + public void TestComplex1State() + { + var input = new CustomContract.Complex1Input { - var input = new CustomContract.Complex2Input - { - BoolData = new CustomContract.BoolInput(){ BoolValue = true }, - Int32Data = new CustomContract.Int32Input() { Int32Value = 12 } - }; - var output = Contract.TestComplex2State(input); - output.BoolData.BoolValue.ShouldBeTrue(); - output.Int32Data.Int32Value.ShouldBe(12); - } - - [Fact] - public void TestMappedState() + BoolValue = true, + Int32Value = 120 + }; + var output = Contract.TestComplex1State(input); + output.BoolValue.ShouldBe(true); + output.Int32Value.ShouldBe(120); + } + + [Fact] + public void TestComplex2State() + { + var input = new CustomContract.Complex2Input { - var input = new CustomContract.ProtobufInput - { - ProtobufValue = new CustomContract.ProtobufMessage - { - BoolValue = false, - Int64Value = 100, - StringValue = "test" - } - }; - - var output = Contract.TestMappedState(input); - output.Collection.Count.ShouldBe(1); - output.Collection[0].BoolValue.ShouldBeFalse(); - output.Collection[0].Int64Value.ShouldBe(100); - output.Collection[0].StringValue.ShouldBe("test"); - - input.ProtobufValue.Int64Value = 200; - output = Contract.TestMappedState(input); - output.Collection[0].Int64Value.ShouldBe(200); - } - - [Fact] - public void TestMapped1State() + BoolData = new CustomContract.BoolInput { BoolValue = true }, + Int32Data = new CustomContract.Int32Input { Int32Value = 12 } + }; + var output = Contract.TestComplex2State(input); + output.BoolData.BoolValue.ShouldBeTrue(); + output.Int32Data.Int32Value.ShouldBe(12); + } + + [Fact] + public void TestMappedState() + { + var input = new CustomContract.ProtobufInput { - var input = new CustomContract.Complex3Input + ProtobufValue = new CustomContract.ProtobufMessage { - From = "A", - PairA = "USD", - To = "B", - PairB = "RMB", - TradeDetails = new CustomContract.TradeMessage - { - FromAmount = 100, - ToAmount = 620 - } - }; - - var tradeMessage = Contract.TestMapped1State(input); - tradeMessage.FromAmount.ShouldBe(100); - tradeMessage.ToAmount.ShouldBe(620); - - tradeMessage = Contract.TestMapped1State(input); - tradeMessage.FromAmount.ShouldBe(200); - tradeMessage.ToAmount.ShouldBe(1240); - - input = new CustomContract.Complex3Input - { - From = "A", - PairA = "EUR", - To = "B", - PairB = "RMB", - TradeDetails = new CustomContract.TradeMessage - { - FromAmount = 100, - ToAmount = 758 - } - }; - tradeMessage = Contract.TestMapped1State(input); - tradeMessage.FromAmount.ShouldBe(100); - tradeMessage.ToAmount.ShouldBe(758); - } - - [Fact] - public void TestReadonlyState() + BoolValue = false, + Int64Value = 100, + StringValue = "test" + } + }; + + var output = Contract.TestMappedState(input); + output.Collection.Count.ShouldBe(1); + output.Collection[0].BoolValue.ShouldBeFalse(); + output.Collection[0].Int64Value.ShouldBe(100); + output.Collection[0].StringValue.ShouldBe("test"); + + input.ProtobufValue.Int64Value = 200; + output = Contract.TestMappedState(input); + output.Collection[0].Int64Value.ShouldBe(200); + } + + [Fact] + public void TestMapped1State() + { + var input = new CustomContract.Complex3Input { - var firstInput = new CustomContract.BoolInput + From = "A", + PairA = "USD", + To = "B", + PairB = "RMB", + TradeDetails = new CustomContract.TradeMessage { - BoolValue = true - }; + FromAmount = 100, + ToAmount = 620 + } + }; + + var tradeMessage = Contract.TestMapped1State(input); + tradeMessage.FromAmount.ShouldBe(100); + tradeMessage.ToAmount.ShouldBe(620); - var firstOutput = Contract.TestReadonlyState(firstInput); - firstOutput.BoolValue.ShouldBeTrue(); + tradeMessage = Contract.TestMapped1State(input); + tradeMessage.FromAmount.ShouldBe(200); + tradeMessage.ToAmount.ShouldBe(1240); - var secondInput = new CustomContract.BoolInput + input = new CustomContract.Complex3Input + { + From = "A", + PairA = "EUR", + To = "B", + PairB = "RMB", + TradeDetails = new CustomContract.TradeMessage { - BoolValue = false - }; + FromAmount = 100, + ToAmount = 758 + } + }; + tradeMessage = Contract.TestMapped1State(input); + tradeMessage.FromAmount.ShouldBe(100); + tradeMessage.ToAmount.ShouldBe(758); + } + + [Fact] + public void TestReadonlyState() + { + var firstInput = new CustomContract.BoolInput + { + BoolValue = true + }; - var secondOutput = Contract.TestReadonlyState(secondInput); - // Still true - secondOutput.BoolValue.ShouldBeTrue(); - } + var firstOutput = Contract.TestReadonlyState(firstInput); + firstOutput.BoolValue.ShouldBeTrue(); - [Fact] - public void SendVirtualInline_Test() + var secondInput = new CustomContract.BoolInput { - BridgeContext.SendVirtualInline(HashHelper.ComputeFrom("hash"), SampleAddress.AddressList[0], "TestMethod", new CustomContract.StringInput + BoolValue = false + }; + + var secondOutput = Contract.TestReadonlyState(secondInput); + // Still true + secondOutput.BoolValue.ShouldBeTrue(); + } + + [Fact] + public void SendVirtualInline_Test() + { + BridgeContext.SendVirtualInline(HashHelper.ComputeFrom("hash"), SampleAddress.AddressList[0], "TestMethod", + new CustomContract.StringInput { StringValue = "test send virtual inline" }); - } + } - [Fact] - public void SendInline_Test() + [Fact] + public void SendInline_Test() + { + BridgeContext.SendInline(SampleAddress.AddressList[0], "TestMethod", new CustomContract.StringInput { - BridgeContext.SendInline(SampleAddress.AddressList[0], "TestMethod", new CustomContract.StringInput - { - StringValue = "test send inline" - }); - } + StringValue = "test send inline" + }); } } \ No newline at end of file diff --git a/test/AElf.Sdk.CSharp.Tests/TestSdkCSharpAElfModule.cs b/test/AElf.Sdk.CSharp.Tests/TestSdkCSharpAElfModule.cs index 318d6db6d3..1055045c64 100644 --- a/test/AElf.Sdk.CSharp.Tests/TestSdkCSharpAElfModule.cs +++ b/test/AElf.Sdk.CSharp.Tests/TestSdkCSharpAElfModule.cs @@ -9,29 +9,28 @@ using Moq; using Volo.Abp.Modularity; -namespace AElf.Sdk.CSharp.Tests +namespace AElf.Sdk.CSharp.Tests; + +[DependsOn( + typeof(SmartContractAElfModule), + typeof(TestBaseKernelAElfModule))] +public class TestSdkCSharpAElfModule : AElfModule { - [DependsOn( - typeof(SmartContractAElfModule), - typeof(TestBaseKernelAElfModule))] - public class TestSdkCSharpAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + var services = context.Services; + + services.AddTransient(p => { - var services = context.Services; - - services.AddTransient(p => - { - var mockExecutive = new Mock(); - - var mockSmartContractRunner = new Mock(); - mockSmartContractRunner.SetupGet(m => m.Category).Returns(0); - mockSmartContractRunner.Setup(m => m.RunAsync(It.IsAny())) - .Returns(Task.FromResult(mockExecutive.Object)); - return mockSmartContractRunner.Object; - }); - - services.AddSingleton(p => Mock.Of()); - } + var mockExecutive = new Mock(); + + var mockSmartContractRunner = new Mock(); + mockSmartContractRunner.SetupGet(m => m.Category).Returns(0); + mockSmartContractRunner.Setup(m => m.RunAsync(It.IsAny())) + .Returns(Task.FromResult(mockExecutive.Object)); + return mockSmartContractRunner.Object; + }); + + services.AddSingleton(p => Mock.Of()); } } \ No newline at end of file diff --git a/test/AElf.TestBase/AElf.TestBase.csproj b/test/AElf.TestBase/AElf.TestBase.csproj index f314ad28b8..70dd10dc71 100644 --- a/test/AElf.TestBase/AElf.TestBase.csproj +++ b/test/AElf.TestBase/AElf.TestBase.csproj @@ -4,17 +4,17 @@ false - + - - - - - - - - - + + + + + + + + + diff --git a/test/AElf.TestBase/AElfIntegratedTest.cs b/test/AElf.TestBase/AElfIntegratedTest.cs index 2bb1cad6cb..34340e1573 100644 --- a/test/AElf.TestBase/AElfIntegratedTest.cs +++ b/test/AElf.TestBase/AElfIntegratedTest.cs @@ -1,27 +1,25 @@ using MartinCostello.Logging.XUnit; using Volo.Abp; -using Volo.Abp.Testing; using Volo.Abp.Modularity; +using Volo.Abp.Testing; using Xunit.Abstractions; -namespace AElf.TestBase +namespace AElf.TestBase; + +public class AElfIntegratedTest : AbpIntegratedTest + where TModule : IAbpModule { - public class AElfIntegratedTest : AbpIntegratedTest - where TModule : IAbpModule + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) { - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } - - - protected void SetTestOutputHelper(ITestOutputHelper testOutputHelper) - { - GetRequiredService().OutputHelper = testOutputHelper; - } + options.UseAutofac(); } - public class AElfIntegratedTest : AElfIntegratedTest + protected void SetTestOutputHelper(ITestOutputHelper testOutputHelper) { + GetRequiredService().OutputHelper = testOutputHelper; } +} + +public class AElfIntegratedTest : AElfIntegratedTest +{ } \ No newline at end of file diff --git a/test/AElf.TestBase/GlobalUsings.cs b/test/AElf.TestBase/GlobalUsings.cs new file mode 100644 index 0000000000..8c927eb747 --- /dev/null +++ b/test/AElf.TestBase/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/test/AElf.TestBase/IgnoreOnCIFact.cs b/test/AElf.TestBase/IgnoreOnCIFact.cs index c22c9c9421..850c3d4db0 100644 --- a/test/AElf.TestBase/IgnoreOnCIFact.cs +++ b/test/AElf.TestBase/IgnoreOnCIFact.cs @@ -1,19 +1,16 @@ using System; -using Xunit; -namespace AElf.TestBase +namespace AElf.TestBase; + +public sealed class IgnoreOnCIFact : FactAttribute { - public sealed class IgnoreOnCIFact : FactAttribute + public IgnoreOnCIFact() { - public IgnoreOnCIFact() - { - if (IsOnCI()) - { - Skip = "Ignore on CI running to save execution time."; - } - } + if (IsOnCI()) Skip = "Ignore on CI running to save execution time."; + } - private static bool IsOnCI() - => Environment.GetEnvironmentVariable("CI_TEST") != null; + private static bool IsOnCI() + { + return Environment.GetEnvironmentVariable("CI_TEST") != null; } } \ No newline at end of file diff --git a/test/AElf.TestBase/TestBaseAElfModule.cs b/test/AElf.TestBase/TestBaseAElfModule.cs index 22c7dc6e7a..c8d6783b8d 100644 --- a/test/AElf.TestBase/TestBaseAElfModule.cs +++ b/test/AElf.TestBase/TestBaseAElfModule.cs @@ -6,28 +6,23 @@ using Volo.Abp.Modularity; using Xunit.Abstractions; -namespace AElf.TestBase +namespace AElf.TestBase; + +[DependsOn( + typeof(AbpTestBaseModule))] +public class TestBaseAElfModule : AElfModule { - [DependsOn( - typeof(AbpTestBaseModule))] - public class TestBaseAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) - { - ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); + ITestOutputHelperAccessor testOutputHelperAccessor = new TestOutputHelperAccessor(); - context.Services.AddSingleton(testOutputHelperAccessor); + context.Services.AddSingleton(testOutputHelperAccessor); - context.Services.AddLogging(o => - { - o.AddXUnit(testOutputHelperAccessor); - - }); - } + context.Services.AddLogging(o => { o.AddXUnit(testOutputHelperAccessor); }); } +} - public class TestOutputHelperAccessor : ITestOutputHelperAccessor - { - public ITestOutputHelper OutputHelper { get; set; } - } +public class TestOutputHelperAccessor : ITestOutputHelperAccessor +{ + public ITestOutputHelper OutputHelper { get; set; } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/AElf.Types.Tests.csproj b/test/AElf.Types.Tests/AElf.Types.Tests.csproj index 42c3216fff..87d7c659a6 100644 --- a/test/AElf.Types.Tests/AElf.Types.Tests.csproj +++ b/test/AElf.Types.Tests/AElf.Types.Tests.csproj @@ -4,14 +4,14 @@ false - - - - - - + + + + + + - + \ No newline at end of file diff --git a/test/AElf.Types.Tests/AddressTest.cs b/test/AElf.Types.Tests/AddressTest.cs index a7ccf35833..8d268739ec 100644 --- a/test/AElf.Types.Tests/AddressTest.cs +++ b/test/AElf.Types.Tests/AddressTest.cs @@ -1,114 +1,111 @@ -using System.Linq; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +using System; +using System.Linq; using AElf.Cryptography; using Shouldly; using Xunit; -namespace AElf.Types.Tests +namespace AElf.Types.Tests; + +public class AddressTest { - public class AddressTest + [Fact] + public void Generate_Address() + { + //Generate default + var address1 = Address.FromBase58("2DZER7qHVwv3PUMFsHuQaQbE4wDFsCRzJsxLwYEk8rgM3HVn1S"); + var address2 = Address.FromBase58("xFqJD9R33mQBQPr1hCFUZMayXFQ577j34MPyUdXzbPpAYufG2"); + address1.ShouldNotBeSameAs(address2); + + //Generate from String + var address3 = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); + address3.ShouldNotBe(null); + + //Generate from byte + var bytes = Enumerable.Repeat((byte)0xEF, 32).ToArray(); + var address4 = Address.FromBytes(bytes); + address4.ShouldNotBe(null); + + bytes = Enumerable.Repeat((byte)32, 20).ToArray(); + Should.Throw(() => { Address.FromBytes(bytes); }); + + //Generate from public key + var pk = CryptoHelper.GenerateKeyPair().PublicKey; + var address5 = Address.FromPublicKey(pk); + address5.ShouldNotBe(null); + address5.ToByteArray().Length.ShouldBe(32); + } + + [Fact] + public void Get_Address_Info() { - [Fact] - public void Generate_Address() - { - //Generate default - var address1 = Address.FromBase58("2DZER7qHVwv3PUMFsHuQaQbE4wDFsCRzJsxLwYEk8rgM3HVn1S"); - var address2 = Address.FromBase58("xFqJD9R33mQBQPr1hCFUZMayXFQ577j34MPyUdXzbPpAYufG2"); - address1.ShouldNotBeSameAs(address2); - - //Generate from String - var address3 = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); - address3.ShouldNotBe(null); - - //Generate from byte - var bytes = Enumerable.Repeat((byte) 0xEF, 32).ToArray(); - var address4 = Address.FromBytes(bytes); - address4.ShouldNotBe(null); - - bytes = Enumerable.Repeat((byte) 32, 20).ToArray(); - Should.Throw(() => { Address.FromBytes(bytes); }); - - //Generate from public key - var pk = CryptoHelper.GenerateKeyPair().PublicKey; - var address5 = Address.FromPublicKey(pk); - address5.ShouldNotBe(null); - address5.ToByteArray().Length.ShouldBe(32); - } - - [Fact] - public void Get_Address_Info() - { - var pk = CryptoHelper.GenerateKeyPair().PublicKey; - var address = Address.FromPublicKey(pk); - var addressString = address.ToBase58(); - addressString.ShouldNotBe(string.Empty); - } - - [Fact] - public void Compare_Address() - { - var address1 = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); - var address2 = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); - address1.CompareTo(address2).ShouldNotBe(0); - Should.Throw(() => { address1.CompareTo(null); }); - - (address1 < null).ShouldBeFalse(); - (null < address2).ShouldBeTrue(); - (address1 > address2).ShouldBe(address1.CompareTo(address2) > 0); - - Address addressA = null; - Address addressB = null; - var value = addressA > addressB; - value.ShouldBeFalse(); - } - - [Fact] - public void Parse_Address_FromString() - { - string addStr = "ddnF1dEsp51QbASCqQKPZ7vs2zXxUxyu5BuGRKFQAsT9JKrra"; - var address = Address.FromBase58(addStr); - address.ShouldNotBe(null); - var addStr1 = address.ToBase58(); - addStr1.ShouldBe(addStr); - - addStr = "345678icdfvbghnjmkdfvgbhtn"; - Should.Throw(() => { address = Address.FromBase58(addStr); }); - } - - [Fact] - public void Chain_Address() - { - var address = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); - var chainId = 0; - var chainAddress1 = new ChainAddress(address, chainId); - - string str = chainAddress1.GetFormatted("ELF", chainAddress1.ChainId); - var chainAddress2 = ChainAddress.Parse(str, "ELF"); - chainAddress1.Address.ShouldBe(chainAddress2.Address); - chainAddress1.ChainId.ShouldBe(chainAddress2.ChainId); - - var strError = chainAddress1.ToString(); - Should.Throw(() => { chainAddress2 = ChainAddress.Parse(strError, "ELF"); }); - } - - [Fact] - public void Verify_Address() - { - var address = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); - var formattedAddress = address.ToBase58(); - AddressHelper.VerifyFormattedAddress(formattedAddress).ShouldBeTrue(); - - AddressHelper.VerifyFormattedAddress(formattedAddress + "ER").ShouldBeFalse(); - AddressHelper.VerifyFormattedAddress("AE" + formattedAddress).ShouldBeFalse(); - - var formattedAddressCharArray = formattedAddress.ToCharArray(); - formattedAddressCharArray[4] = 'F'; - AddressHelper.VerifyFormattedAddress(new string(formattedAddressCharArray)).ShouldBeFalse(); - - AddressHelper.VerifyFormattedAddress("").ShouldBeFalse(); - AddressHelper.VerifyFormattedAddress("I0I0").ShouldBeFalse(); - } + var pk = CryptoHelper.GenerateKeyPair().PublicKey; + var address = Address.FromPublicKey(pk); + var addressString = address.ToBase58(); + addressString.ShouldNotBe(string.Empty); + } + + [Fact] + public void Compare_Address() + { + var address1 = Address.FromBase58("z1NVbziJbekvcza3Zr4Gt4eAvoPBZThB68LHRQftrVFwjtGVM"); + var address2 = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); + address1.CompareTo(address2).ShouldNotBe(0); + Should.Throw(() => { address1.CompareTo(null); }); + + (address1 < null).ShouldBeFalse(); + (null < address2).ShouldBeTrue(); + (address1 > address2).ShouldBe(address1.CompareTo(address2) > 0); + + Address addressA = null; + Address addressB = null; + var value = addressA > addressB; + value.ShouldBeFalse(); + } + + [Fact] + public void Parse_Address_FromString() + { + var addStr = "ddnF1dEsp51QbASCqQKPZ7vs2zXxUxyu5BuGRKFQAsT9JKrra"; + var address = Address.FromBase58(addStr); + address.ShouldNotBe(null); + var addStr1 = address.ToBase58(); + addStr1.ShouldBe(addStr); + + addStr = "345678icdfvbghnjmkdfvgbhtn"; + Should.Throw(() => { address = Address.FromBase58(addStr); }); + } + + [Fact] + public void Chain_Address() + { + var address = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); + var chainId = 0; + var chainAddress1 = new ChainAddress(address, chainId); + + var str = chainAddress1.GetFormatted("ELF", chainAddress1.ChainId); + var chainAddress2 = ChainAddress.Parse(str, "ELF"); + chainAddress1.Address.ShouldBe(chainAddress2.Address); + chainAddress1.ChainId.ShouldBe(chainAddress2.ChainId); + + var strError = chainAddress1.ToString(); + Should.Throw(() => { chainAddress2 = ChainAddress.Parse(strError, "ELF"); }); + } + + [Fact] + public void Verify_Address() + { + var address = Address.FromBase58("nGmKp2ekysABSZAzVfXDrmaTNTaSSrfNmDhuaz7RUj5RTCYqy"); + var formattedAddress = address.ToBase58(); + AddressHelper.VerifyFormattedAddress(formattedAddress).ShouldBeTrue(); + + AddressHelper.VerifyFormattedAddress(formattedAddress + "ER").ShouldBeFalse(); + AddressHelper.VerifyFormattedAddress("AE" + formattedAddress).ShouldBeFalse(); + + var formattedAddressCharArray = formattedAddress.ToCharArray(); + formattedAddressCharArray[4] = 'F'; + AddressHelper.VerifyFormattedAddress(new string(formattedAddressCharArray)).ShouldBeFalse(); + + AddressHelper.VerifyFormattedAddress("").ShouldBeFalse(); + AddressHelper.VerifyFormattedAddress("I0I0").ShouldBeFalse(); } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Base58Tests.cs b/test/AElf.Types.Tests/Base58Tests.cs index 0d698b3725..2d6a8465ad 100644 --- a/test/AElf.Types.Tests/Base58Tests.cs +++ b/test/AElf.Types.Tests/Base58Tests.cs @@ -1,80 +1,77 @@ using System; -using Xunit; using Google.Protobuf; using Shouldly; +using Xunit; + +namespace AElf.Types.Tests; -namespace AElf.Types.Tests +public class Base58Tests { - public class Base58Tests + [Fact] + public void Encode_And_Decode_Hash() { - [Fact] - public void Encode_And_Decode_Hash() - { - var hash = HashHelper.ComputeFrom("hash"); - var data = hash.ToByteArray(); + var hash = HashHelper.ComputeFrom("hash"); + var data = hash.ToByteArray(); - var enCode = Base58CheckEncoding.Encode(data); - enCode.ShouldNotBe(string.Empty); - var deCode = Base58CheckEncoding.Decode(enCode); - deCode.ShouldBe(data); - } + var enCode = Base58CheckEncoding.Encode(data); + enCode.ShouldNotBe(string.Empty); + var deCode = Base58CheckEncoding.Decode(enCode); + deCode.ShouldBe(data); + } + + [Fact] + public void Encode_And_Decode_Address() + { + var address = Address.FromBase58("xFqJD9R33mQBQPr1hCFUZMayXFQ577j34MPyUdXzbPpAYufG2"); + var data = address.ToByteArray(); - [Fact] - public void Encode_And_Decode_Address() - { - var address = Address.FromBase58("xFqJD9R33mQBQPr1hCFUZMayXFQ577j34MPyUdXzbPpAYufG2"); - var data = address.ToByteArray(); + var enCode = Base58CheckEncoding.Encode(data); + enCode.ShouldNotBe(string.Empty); + var deCode = Base58CheckEncoding.Decode(enCode); + deCode.ShouldBe(data); - var enCode = Base58CheckEncoding.Encode(data); - enCode.ShouldNotBe(string.Empty); - var deCode = Base58CheckEncoding.Decode(enCode); - deCode.ShouldBe(data); + var deCode1 = Base58CheckEncoding.DecodePlain(enCode); + deCode1.ShouldNotBe(data); + } - var deCode1 = Base58CheckEncoding.DecodePlain(enCode); - deCode1.ShouldNotBe(data); - } + [Fact] + public void EncodePlain_And_DecodePlain_Hash() + { + var hash = HashHelper.ComputeFrom("hash"); + var data = hash.ToByteArray(); + var bytes = new byte[] { 0 }; - [Fact] - public void EncodePlain_And_DecodePlain_Hash() - { - var hash = HashHelper.ComputeFrom("hash"); - var data = hash.ToByteArray(); - var bytes = new byte[]{0}; + var enCode = Base58CheckEncoding.EncodePlain(data); + enCode.ShouldNotBe(string.Empty); + var deCode = Base58CheckEncoding.DecodePlain(enCode); + deCode.ShouldBe(data); - var enCode = Base58CheckEncoding.EncodePlain(data); - enCode.ShouldNotBe(string.Empty); - var deCode = Base58CheckEncoding.DecodePlain(enCode); - deCode.ShouldBe(data); - - Base58CheckEncoding.EncodePlain(bytes).ShouldBe("1"); - Should.Throw(() => { - Base58CheckEncoding.DecodePlain(bytes.ToString()); - }); + Base58CheckEncoding.EncodePlain(bytes).ShouldBe("1"); + Should.Throw(() => { Base58CheckEncoding.DecodePlain(bytes.ToString()); }); - Should.Throw(() => { Base58CheckEncoding.Decode(enCode); }); - } + Should.Throw(() => { Base58CheckEncoding.Decode(enCode); }); + } - [Fact] - public void EncodePlain_And_DecodePlain_Address() - { - var address = Address.FromBase58("2DZER7qHVwv3PUMFsHuQaQbE4wDFsCRzJsxLwYEk8rgM3HVn1S"); - var data = address.ToByteArray(); + [Fact] + public void EncodePlain_And_DecodePlain_Address() + { + var address = Address.FromBase58("2DZER7qHVwv3PUMFsHuQaQbE4wDFsCRzJsxLwYEk8rgM3HVn1S"); + var data = address.ToByteArray(); - var enCode = Base58CheckEncoding.EncodePlain(data); - enCode.ShouldNotBe(string.Empty); - var deCode = Base58CheckEncoding.DecodePlain(enCode); - deCode.ShouldBe(data); - } + var enCode = Base58CheckEncoding.EncodePlain(data); + enCode.ShouldNotBe(string.Empty); + var deCode = Base58CheckEncoding.DecodePlain(enCode); + deCode.ShouldBe(data); + } - [Fact] - public void EncodePlan_And_DecodePlain_ByteString() - { - var bs = ByteString.CopyFromUtf8("test byte string"); - var encodeMessage = Base58CheckEncoding.EncodePlain(bs); + [Fact] + public void EncodePlan_And_DecodePlain_ByteString() + { + var bs = ByteString.CopyFromUtf8("test byte string"); + var encodeMessage = Base58CheckEncoding.EncodePlain(bs); - var decodeMessage = Base58CheckEncoding.DecodePlain(encodeMessage); - var bs1 = ByteString.CopyFrom(decodeMessage); - bs.ShouldBe(bs1); - } + var decodeMessage = Base58CheckEncoding.DecodePlain(encodeMessage); + var bs1 = ByteString.CopyFrom(decodeMessage); + bs.ShouldBe(bs1); } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/BinaryMerkleTestTest.cs b/test/AElf.Types.Tests/BinaryMerkleTestTest.cs index 265172b907..38d46f0d98 100644 --- a/test/AElf.Types.Tests/BinaryMerkleTestTest.cs +++ b/test/AElf.Types.Tests/BinaryMerkleTestTest.cs @@ -3,441 +3,430 @@ using System.Linq; using Xunit; -namespace AElf.Types.Tests +namespace AElf.Types.Tests; + +public class BinaryMerkleTestTest { - public class BinaryMerkleTestTest + private Hash GetHashFromStrings(params string[] strings) { - private Hash GetHashFromStrings(params string[] strings) - { - return BinaryMerkleTree.FromLeafNodes(strings.Select(HashHelper.ComputeFrom).ToList()).Root; - } + return BinaryMerkleTree.FromLeafNodes(strings.Select(HashHelper.ComputeFrom).ToList()).Root; + } - private Hash GetHashFromHexString(params string[] strings) - { - var hash = Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(strings[0])); - foreach (var s in strings.Skip(1)) - { - hash = HashHelper.ComputeFrom(hash.ToByteArray().Concat(ByteArrayHelper.HexStringToByteArray(s)).ToArray()); - } + private Hash GetHashFromHexString(params string[] strings) + { + var hash = Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(strings[0])); + foreach (var s in strings.Skip(1)) + hash = HashHelper.ComputeFrom(hash.ToByteArray().Concat(ByteArrayHelper.HexStringToByteArray(s)).ToArray()); - return hash; - } + return hash; + } - /// - /// Add node(s) and compute root hash - /// - [Fact] - public void SingleNodeTest() - { - string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - var tree = BinaryMerkleTree.FromLeafNodes(new[] {CreateLeafFromHex(hex)}); + /// + /// Add node(s) and compute root hash + /// + [Fact] + public void SingleNodeTest() + { + var hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + var tree = BinaryMerkleTree.FromLeafNodes(new[] { CreateLeafFromHex(hex) }); - //See if the hash of merkle tree is equal to the element’s hash. - var root = tree.Root; - var expected = GetHashFromHexString(hex, hex); - Assert.Equal(expected, root); - } + //See if the hash of merkle tree is equal to the element’s hash. + var root = tree.Root; + var expected = GetHashFromHexString(hex, hex); + Assert.Equal(expected, root); + } - [Fact] - public void MerkleProofTest() - { - string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - var leaf = CreateLeafFromHex(hex); - var tree = BinaryMerkleTree.FromLeafNodes(new[] {leaf}); - - //See if the hash of merkle tree is equal to the element’s hash. - var root = tree.Root; - var path = tree.GenerateMerklePath(0); - var calculatedRoot = path.ComputeRootWithLeafNode(leaf); - Assert.Equal(root, calculatedRoot); - } + [Fact] + public void MerkleProofTest() + { + var hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + var leaf = CreateLeafFromHex(hex); + var tree = BinaryMerkleTree.FromLeafNodes(new[] { leaf }); + + //See if the hash of merkle tree is equal to the element’s hash. + var root = tree.Root; + var path = tree.GenerateMerklePath(0); + var calculatedRoot = path.ComputeRootWithLeafNode(leaf); + Assert.Equal(root, calculatedRoot); + } - [Fact] - public void MerkleProofTest_MultiTwoLeaves() - { - string hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - var leaf1 = CreateLeafFromHex(hex1); + [Fact] + public void MerkleProofTest_MultiTwoLeaves() + { + var hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + var leaf1 = CreateLeafFromHex(hex1); - string hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; - var leaf2 = CreateLeafFromHex(hex2); + var hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; + var leaf2 = CreateLeafFromHex(hex2); - var tree = BinaryMerkleTree.FromLeafNodes(new[] {leaf1, leaf2}); + var tree = BinaryMerkleTree.FromLeafNodes(new[] { leaf1, leaf2 }); - //See if the hash of merkle tree is equal to the element’s hash. - var root = tree.Root; - var path = tree.GenerateMerklePath(0); - var calculatedRoot = path.ComputeRootWithLeafNode(leaf1); - Assert.Equal(root, calculatedRoot); - } + //See if the hash of merkle tree is equal to the element’s hash. + var root = tree.Root; + var path = tree.GenerateMerklePath(0); + var calculatedRoot = path.ComputeRootWithLeafNode(leaf1); + Assert.Equal(root, calculatedRoot); + } - [Fact] - public void MerkleProofTest_MultiThreeLeaves() - { - string hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - var leaf1 = CreateLeafFromHex(hex1); + [Fact] + public void MerkleProofTest_MultiThreeLeaves() + { + var hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + var leaf1 = CreateLeafFromHex(hex1); - string hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; - var leaf2 = CreateLeafFromHex(hex2); + var hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; + var leaf2 = CreateLeafFromHex(hex2); - string hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; - var leaf3 = CreateLeafFromHex(hex3); - var tree = BinaryMerkleTree.FromLeafNodes(new[] {leaf1, leaf2, leaf3}); + var hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; + var leaf3 = CreateLeafFromHex(hex3); + var tree = BinaryMerkleTree.FromLeafNodes(new[] { leaf1, leaf2, leaf3 }); - var root = tree.Root; - var path = tree.GenerateMerklePath(2); - var calculatedRoot = path.ComputeRootWithLeafNode(leaf3); - Assert.Equal(root, calculatedRoot); - } + var root = tree.Root; + var path = tree.GenerateMerklePath(2); + var calculatedRoot = path.ComputeRootWithLeafNode(leaf3); + Assert.Equal(root, calculatedRoot); + } - [Fact] - public void MerkleProofTest_MultiLeaves() - { - string hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - var hash1 = CreateLeafFromHex(hex1); + [Fact] + public void MerkleProofTest_MultiLeaves() + { + var hex1 = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + var hash1 = CreateLeafFromHex(hex1); - string hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; - var hash2 = CreateLeafFromHex(hex2); + var hex2 = "a28bf94d0491a234d1e99abc62ed344eb55bb11aeecacc35c1b75bfa85c8983f"; + var hash2 = CreateLeafFromHex(hex2); - string hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; - var hash3 = CreateLeafFromHex(hex3); + var hex3 = "bf6ae8809d017f07b27ad1620839c6503666fb55f7fe7ac70881e8864ce5a3ff"; + var hash3 = CreateLeafFromHex(hex3); - string hex4 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; - var hash4 = CreateLeafFromHex(hex4); + var hex4 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; + var hash4 = CreateLeafFromHex(hex4); - string hex5 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; - var hash5 = CreateLeafFromHex(hex5); - var tree = BinaryMerkleTree.FromLeafNodes(new[] {hash1, hash2, hash3, hash4, hash5}); + var hex5 = "bac4adcf8066921237320cdcddb721f5ba5d34065b9c54fe7f9893d8dfe52f17"; + var hash5 = CreateLeafFromHex(hex5); + var tree = BinaryMerkleTree.FromLeafNodes(new[] { hash1, hash2, hash3, hash4, hash5 }); - //See if the hash of merkle tree is equal to the element’s hash. - var root = tree.Root; - var path = tree.GenerateMerklePath(4); - var calculatedRoot = path.ComputeRootWithLeafNode(hash5); - //Assert.Contains(hash3, path.Path); - Assert.Equal(root, calculatedRoot); - } + //See if the hash of merkle tree is equal to the element’s hash. + var root = tree.Root; + var path = tree.GenerateMerklePath(4); + var calculatedRoot = path.ComputeRootWithLeafNode(hash5); + //Assert.Contains(hash3, path.Path); + Assert.Equal(root, calculatedRoot); + } - [Fact] - public void MultiNodesTest() - { - var tree1 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] {"a", "e"})); - - //See if the hash of merkle tree is equal to the element’s hash. - var root1 = tree1.Root; - Assert.Equal(GetHashFromStrings("a", "e"), root1); - - var tree2 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] {"a", "e", "l"})); - var root2 = tree2.Root; - Hash right = GetHashFromStrings("l", "l"); - Assert.Equal(HashHelper.ConcatAndCompute(root1, right), root2); - - var tree3 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] {"a", "e", "l", "f"})); - var root3 = tree3.Root; - Hash right2 = GetHashFromStrings("l", "f"); - Assert.Equal(HashHelper.ConcatAndCompute(root1, right2), root3); - - var tree4 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] {"a", "e", "l", "f", "a"})); - var root4 = tree4.Root; - Hash l2 = GetHashFromStrings("a", "a"); - Hash l3 = HashHelper.ConcatAndCompute(l2, l2); - Assert.Equal(HashHelper.ConcatAndCompute(root3, l3), root4); - } + [Fact] + public void MultiNodesTest() + { + var tree1 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e" })); + + //See if the hash of merkle tree is equal to the element’s hash. + var root1 = tree1.Root; + Assert.Equal(GetHashFromStrings("a", "e"), root1); + + var tree2 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l" })); + var root2 = tree2.Root; + var right = GetHashFromStrings("l", "l"); + Assert.Equal(HashHelper.ConcatAndCompute(root1, right), root2); + + var tree3 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l", "f" })); + var root3 = tree3.Root; + var right2 = GetHashFromStrings("l", "f"); + Assert.Equal(HashHelper.ConcatAndCompute(root1, right2), root3); + + var tree4 = BinaryMerkleTree.FromLeafNodes(CreateLeaves(new[] { "a", "e", "l", "f", "a" })); + var root4 = tree4.Root; + var l2 = GetHashFromStrings("a", "a"); + var l3 = HashHelper.ConcatAndCompute(l2, l2); + Assert.Equal(HashHelper.ConcatAndCompute(root3, l3), root4); + } - [Fact] - public void MerklePathTest1LeafNode() - { - var hashes = CreateLeaves(new[] {"a"}); - var tree = BinaryMerkleTree.FromLeafNodes(hashes); - - // test invalid index - Assert.Throws(() => tree.GenerateMerklePath(1)); - - // test 1st "a" - var path = tree.GenerateMerklePath(0); - Assert.NotNull(path); - Assert.True(1 == path.MerklePathNodes.Count); - var realPath = GenerateMerklePath(new[] {1}, tree.Nodes); - Assert.Equal(realPath, path); - } + [Fact] + public void MerklePathTest1LeafNode() + { + var hashes = CreateLeaves(new[] { "a" }); + var tree = BinaryMerkleTree.FromLeafNodes(hashes); + + // test invalid index + Assert.Throws(() => tree.GenerateMerklePath(1)); + + // test 1st "a" + var path = tree.GenerateMerklePath(0); + Assert.NotNull(path); + Assert.True(1 == path.MerklePathNodes.Count); + var realPath = GenerateMerklePath(new[] { 1 }, tree.Nodes); + Assert.Equal(realPath, path); + } - [Fact] - public void MerklePathTest2LeafNodes() - { - var hashes = CreateLeaves(new[] {"a", "e"}); - var tree = BinaryMerkleTree.FromLeafNodes(hashes); - // test invalid index - Assert.Throws(() => tree.GenerateMerklePath(2)); - - // test "a" - var path = tree.GenerateMerklePath(0); - Assert.NotNull(path); - Assert.True(1 == path.MerklePathNodes.Count); - var realPath1 = GenerateMerklePath(new[] {1}, tree.Nodes); - Assert.Equal(realPath1, path); - - // test "e" - path = tree.GenerateMerklePath(1); - Assert.NotNull(path); - Assert.True(1 == path.MerklePathNodes.Count); - var realPath2 = GenerateMerklePath(new[] {0}, tree.Nodes); - Assert.Equal(realPath2, path); - } + [Fact] + public void MerklePathTest2LeafNodes() + { + var hashes = CreateLeaves(new[] { "a", "e" }); + var tree = BinaryMerkleTree.FromLeafNodes(hashes); + // test invalid index + Assert.Throws(() => tree.GenerateMerklePath(2)); + + // test "a" + var path = tree.GenerateMerklePath(0); + Assert.NotNull(path); + Assert.True(1 == path.MerklePathNodes.Count); + var realPath1 = GenerateMerklePath(new[] { 1 }, tree.Nodes); + Assert.Equal(realPath1, path); + + // test "e" + path = tree.GenerateMerklePath(1); + Assert.NotNull(path); + Assert.True(1 == path.MerklePathNodes.Count); + var realPath2 = GenerateMerklePath(new[] { 0 }, tree.Nodes); + Assert.Equal(realPath2, path); + } - [Fact] - public void MerklePathTest5LeafNodes() - { - var hashes = CreateLeaves(new[] {"a", "e", "l", "f", "a"}); - var tree = BinaryMerkleTree.FromLeafNodes(hashes); - var root = tree.Root; - - // test 1st "a" - var path1 = tree.GenerateMerklePath(0); - Assert.NotNull(path1); - Assert.Equal(3, path1.MerklePathNodes.Count); - var realPath1 = GenerateMerklePath(new[] {1, 7, 11}, tree.Nodes); - Assert.Equal(realPath1, path1); - var actualRoot1 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("a"), path1); - Assert.Equal(root, actualRoot1); - - // test 1st "e" - var path2 = tree.GenerateMerklePath(1); - Assert.NotNull(path2); - Assert.Equal(3, path2.MerklePathNodes.Count); - var realPath2 = GenerateMerklePath(new[] {0, 7, 11}, tree.Nodes); - - Assert.Equal(realPath2, path2); - var actualRoot2 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("e"), path2); - Assert.Equal(root, actualRoot2); - - // test 1st "l" - var path3 = tree.GenerateMerklePath(2); - Assert.NotNull(path3); - Assert.Equal(3, path3.MerklePathNodes.Count); - var realPath3 = GenerateMerklePath(new[] {3, 6, 11}, tree.Nodes); - Assert.Equal(realPath3, path3); - var actualRoot3 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("l"), path3); - Assert.Equal(root, actualRoot3); - - // test "f" - var path4 = tree.GenerateMerklePath(3); - Assert.NotNull(path4); - Assert.Equal(3, path4.MerklePathNodes.Count); - var realPath4 = GenerateMerklePath(new[] {2, 6, 11}, tree.Nodes); - Assert.Equal(realPath4, path4); - var actualRoot4 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("f"), path4); - Assert.Equal(root, actualRoot4); - - // test 2nd "a" - var path5 = tree.GenerateMerklePath(4); - Assert.NotNull(path5); - Assert.Equal(3, path5.MerklePathNodes.Count); - var realPath5 = GenerateMerklePath(new[] {5, 9, 10}, tree.Nodes); - Assert.Equal(realPath5, path5); - var actualRoot5 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("a"), path5); - Assert.Equal(root, actualRoot5); - - // test invalid index - Assert.Throws(() => tree.GenerateMerklePath(5)); - } + [Fact] + public void MerklePathTest5LeafNodes() + { + var hashes = CreateLeaves(new[] { "a", "e", "l", "f", "a" }); + var tree = BinaryMerkleTree.FromLeafNodes(hashes); + var root = tree.Root; + + // test 1st "a" + var path1 = tree.GenerateMerklePath(0); + Assert.NotNull(path1); + Assert.Equal(3, path1.MerklePathNodes.Count); + var realPath1 = GenerateMerklePath(new[] { 1, 7, 11 }, tree.Nodes); + Assert.Equal(realPath1, path1); + var actualRoot1 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("a"), path1); + Assert.Equal(root, actualRoot1); + + // test 1st "e" + var path2 = tree.GenerateMerklePath(1); + Assert.NotNull(path2); + Assert.Equal(3, path2.MerklePathNodes.Count); + var realPath2 = GenerateMerklePath(new[] { 0, 7, 11 }, tree.Nodes); + + Assert.Equal(realPath2, path2); + var actualRoot2 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("e"), path2); + Assert.Equal(root, actualRoot2); + + // test 1st "l" + var path3 = tree.GenerateMerklePath(2); + Assert.NotNull(path3); + Assert.Equal(3, path3.MerklePathNodes.Count); + var realPath3 = GenerateMerklePath(new[] { 3, 6, 11 }, tree.Nodes); + Assert.Equal(realPath3, path3); + var actualRoot3 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("l"), path3); + Assert.Equal(root, actualRoot3); + + // test "f" + var path4 = tree.GenerateMerklePath(3); + Assert.NotNull(path4); + Assert.Equal(3, path4.MerklePathNodes.Count); + var realPath4 = GenerateMerklePath(new[] { 2, 6, 11 }, tree.Nodes); + Assert.Equal(realPath4, path4); + var actualRoot4 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("f"), path4); + Assert.Equal(root, actualRoot4); + + // test 2nd "a" + var path5 = tree.GenerateMerklePath(4); + Assert.NotNull(path5); + Assert.Equal(3, path5.MerklePathNodes.Count); + var realPath5 = GenerateMerklePath(new[] { 5, 9, 10 }, tree.Nodes); + Assert.Equal(realPath5, path5); + var actualRoot5 = ComputeRootWithMerklePathAndLeaf(HashHelper.ComputeFrom("a"), path5); + Assert.Equal(root, actualRoot5); + + // test invalid index + Assert.Throws(() => tree.GenerateMerklePath(5)); + } - [Theory] - [InlineData(16, 0)] - [InlineData(16, 15)] - [InlineData(9, 8)] - public void MerklePathTest(int leafCount, int index) - { - var hashes = CreateLeaves(leafCount); - var tree = BinaryMerkleTree.FromLeafNodes(hashes.ToArray()); - var root = tree.Root; - var path = tree.GenerateMerklePath(index); - var calculatedRoot = path.ComputeRootWithLeafNode(hashes[index]); - Assert.Equal(root, calculatedRoot); - } + [Theory] + [InlineData(16, 0)] + [InlineData(16, 15)] + [InlineData(9, 8)] + public void MerklePathTest(int leafCount, int index) + { + var hashes = CreateLeaves(leafCount); + var tree = BinaryMerkleTree.FromLeafNodes(hashes.ToArray()); + var root = tree.Root; + var path = tree.GenerateMerklePath(index); + var calculatedRoot = path.ComputeRootWithLeafNode(hashes[index]); + Assert.Equal(root, calculatedRoot); + } - [Theory] - [InlineData(4, 7)] - [InlineData(5, 13)] - [InlineData(6, 13)] - [InlineData(7, 15)] - [InlineData(9, 23)] - public void MerkleNodesCountTest(int leafCount, int expectCount) - { - var hashes = CreateLeaves(leafCount); - var tree = BinaryMerkleTree.FromLeafNodes(hashes); - var nodesCount = tree.Nodes.Count; - Assert.Equal(expectCount, nodesCount); - } + [Theory] + [InlineData(4, 7)] + [InlineData(5, 13)] + [InlineData(6, 13)] + [InlineData(7, 15)] + [InlineData(9, 23)] + public void MerkleNodesCountTest(int leafCount, int expectCount) + { + var hashes = CreateLeaves(leafCount); + var tree = BinaryMerkleTree.FromLeafNodes(hashes); + var nodesCount = tree.Nodes.Count; + Assert.Equal(expectCount, nodesCount); + } - [Fact] - public void TestMerklePathFromEth() + [Fact] + public void TestMerklePathFromEth() + { + var expectedRoot = + Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x90ae927b3312b71e5ea7c8644a9d6f4e6107bf6c0e06df094c94be16d8023c52")); { - var expectedRoot = + var hex = + "0x324144584c63794b4d47477252653961474337584d584543763863787a33546f73317a36504a4853667958677553615662350000000000000000000000000000000000000000000000001111d67bb1bb0000"; + var expectedHash = Hash.LoadFromByteArray( ByteArrayHelper.HexStringToByteArray( - "0x90ae927b3312b71e5ea7c8644a9d6f4e6107bf6c0e06df094c94be16d8023c52")); + "0xa80afe5c85c3e9b09e8c74070d5d8d4de60780968d78e7b031e939e7335b6916")); + var actualHash = HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(hex)); + Assert.Equal(expectedHash, actualHash); + + var merklePath = new MerklePath { - var hex = - "0x324144584c63794b4d47477252653961474337584d584543763863787a33546f73317a36504a4853667958677553615662350000000000000000000000000000000000000000000000001111d67bb1bb0000"; - var expectedHash = - Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0xa80afe5c85c3e9b09e8c74070d5d8d4de60780968d78e7b031e939e7335b6916")); - var actualHash = HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(hex)); - Assert.Equal(expectedHash, actualHash); - - var merklePath = new MerklePath + MerklePathNodes = { - MerklePathNodes = + new MerklePathNode + { + IsLeftChildNode = true, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x739c9a33d81d44b3c6b511c326337c12d9f557fdc3c9476ab33f5d064785a47e")) + }, + new MerklePathNode + { + IsLeftChildNode = true, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x8487ce95823a23aac06a040828761818b2d491fb6603c5d3284b3c9c73764c87")) + }, + new MerklePathNode { - new MerklePathNode - { - IsLeftChildNode = true, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x739c9a33d81d44b3c6b511c326337c12d9f557fdc3c9476ab33f5d064785a47e")) - }, - new MerklePathNode - { - IsLeftChildNode = true, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x8487ce95823a23aac06a040828761818b2d491fb6603c5d3284b3c9c73764c87")) - }, - new MerklePathNode - { - IsLeftChildNode = true, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x7c8e76b0b80181c5154d138078d15aafd3e980858b8eb9076a3cae3fcdec76be")) - } + IsLeftChildNode = true, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x7c8e76b0b80181c5154d138078d15aafd3e980858b8eb9076a3cae3fcdec76be")) } - }; + } + }; + + var actualRoot = merklePath.ComputeRootWithLeafNode(actualHash); + Assert.Equal(expectedRoot, actualRoot); + } - var actualRoot = merklePath.ComputeRootWithLeafNode(actualHash); - Assert.Equal(expectedRoot, actualRoot); - } + { + var hex = + "0x536b4d476a766941417339626e59767636634b636166626866367462524751474b393357674b765a6f436f5335616d4d4b00000000000000000000000000000000000000000000000302379bf2ca2e0000"; + var expectedHash = + Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0xdbd4b01cea12038a3b0c3ce4900c64635b96a1ee2331625fbe473d6c1e816548")); + var actualHash = HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(hex)); + Assert.Equal(expectedHash, actualHash); + var merklePath = new MerklePath { - var hex = - "0x536b4d476a766941417339626e59767636634b636166626866367462524751474b393357674b765a6f436f5335616d4d4b00000000000000000000000000000000000000000000000302379bf2ca2e0000"; - var expectedHash = - Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0xdbd4b01cea12038a3b0c3ce4900c64635b96a1ee2331625fbe473d6c1e816548")); - var actualHash = HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(hex)); - Assert.Equal(expectedHash, actualHash); - - var merklePath = new MerklePath + MerklePathNodes = { - MerklePathNodes = + new MerklePathNode { - new MerklePathNode - { - IsLeftChildNode = false, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x12e2fc90c9b2c6887bf9633bf4872db4bb8cfe18619b0900dad49286abb81248")) - }, - new MerklePathNode - { - IsLeftChildNode = false, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x56ac8fe5cfe48c5ddf5d40f9a8ed5e504929935b677376cae35b8c326a97d34b")) - }, - new MerklePathNode - { - IsLeftChildNode = true, - Hash = Hash.LoadFromByteArray( - ByteArrayHelper.HexStringToByteArray( - "0x7c8e76b0b80181c5154d138078d15aafd3e980858b8eb9076a3cae3fcdec76be")) - } + IsLeftChildNode = false, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x12e2fc90c9b2c6887bf9633bf4872db4bb8cfe18619b0900dad49286abb81248")) + }, + new MerklePathNode + { + IsLeftChildNode = false, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x56ac8fe5cfe48c5ddf5d40f9a8ed5e504929935b677376cae35b8c326a97d34b")) + }, + new MerklePathNode + { + IsLeftChildNode = true, + Hash = Hash.LoadFromByteArray( + ByteArrayHelper.HexStringToByteArray( + "0x7c8e76b0b80181c5154d138078d15aafd3e980858b8eb9076a3cae3fcdec76be")) } - }; + } + }; - var actualRoot = merklePath.ComputeRootWithLeafNode(actualHash); - Assert.Equal(expectedRoot, actualRoot); - } + var actualRoot = merklePath.ComputeRootWithLeafNode(actualHash); + Assert.Equal(expectedRoot, actualRoot); } + } - [Theory] - [InlineData("SkMGjviAAs9bnYvv6cKcafbhf6tbRGQGK93WgKvZoCoS5amMK", "75900000000000000000", - "96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47", - "0x0eb4305ab57ea86f1f2940cc32c86f5870c5463e0e9c57c6ead6a38cbb2ded90")] - [InlineData("2ADXLcyKMGGrRe9aGC7XMXECv8cxz3Tos1z6PJHSfyXguSaVb5", "5500000000000000000", - "d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946", - "0xd4998a64d00f9b9178337fcebcb193494ceefc7b2ee68031a5060ef407d7ae2d")] - public void CalculateHashTest(string address, string amount, string uid, string result) - { - var hashFromString = HashHelper.ComputeFrom(address); + [Theory] + [InlineData("SkMGjviAAs9bnYvv6cKcafbhf6tbRGQGK93WgKvZoCoS5amMK", "75900000000000000000", + "96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47", + "0x0eb4305ab57ea86f1f2940cc32c86f5870c5463e0e9c57c6ead6a38cbb2ded90")] + [InlineData("2ADXLcyKMGGrRe9aGC7XMXECv8cxz3Tos1z6PJHSfyXguSaVb5", "5500000000000000000", + "d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946", + "0xd4998a64d00f9b9178337fcebcb193494ceefc7b2ee68031a5060ef407d7ae2d")] + public void CalculateHashTest(string address, string amount, string uid, string result) + { + var hashFromString = HashHelper.ComputeFrom(address); - var parsedResult = decimal.Parse(amount); - var originTokenSizeInByte = 32; - var preHolderSize = originTokenSizeInByte - 16; - var bytesFromDecimal = decimal.GetBits(parsedResult).Reverse().ToArray(); + var parsedResult = decimal.Parse(amount); + var originTokenSizeInByte = 32; + var preHolderSize = originTokenSizeInByte - 16; + var bytesFromDecimal = decimal.GetBits(parsedResult).Reverse().ToArray(); - if (preHolderSize < 0) - bytesFromDecimal = bytesFromDecimal.TakeLast(originTokenSizeInByte).ToArray(); + if (preHolderSize < 0) + bytesFromDecimal = bytesFromDecimal.TakeLast(originTokenSizeInByte).ToArray(); - var amountBytes = new List(); - bytesFromDecimal.Aggregate(amountBytes, (cur, i) => - { - while (cur.Count < preHolderSize) - { - cur.Add(new byte()); - } - - cur.AddRange(i.ToBytes()); - return cur; - }); - var hashFromAmount = HashHelper.ComputeFrom(amountBytes.ToArray()); - var hashFromUid = Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(uid)); - var hash = HashHelper.ConcatAndCompute(hashFromAmount, hashFromString, hashFromUid); - Assert.True(hash == Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(result))); - } + var amountBytes = new List(); + bytesFromDecimal.Aggregate(amountBytes, (cur, i) => + { + while (cur.Count < preHolderSize) cur.Add(new byte()); + + cur.AddRange(i.ToBytes()); + return cur; + }); + var hashFromAmount = HashHelper.ComputeFrom(amountBytes.ToArray()); + var hashFromUid = Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(uid)); + var hash = HashHelper.ConcatAndCompute(hashFromAmount, hashFromString, hashFromUid); + Assert.True(hash == Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(result))); + } - #region Some useful methods + #region Some useful methods - private List CreateLeaves(IEnumerable buffers) - { - return buffers.Select(HashHelper.ComputeFrom).ToList(); - } + private List CreateLeaves(IEnumerable buffers) + { + return buffers.Select(HashHelper.ComputeFrom).ToList(); + } - private List CreateLeaves(int i) - { - List res = new List(); - for (int j = 0; j < i; j++) - { - res.Add(HashHelper.ComputeFrom(j.ToString())); - } + private List CreateLeaves(int i) + { + var res = new List(); + for (var j = 0; j < i; j++) res.Add(HashHelper.ComputeFrom(j.ToString())); - return res; - } + return res; + } - private Hash CreateLeafFromHex(string hex) - { - return Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(hex)); - } + private Hash CreateLeafFromHex(string hex) + { + return Hash.LoadFromByteArray(ByteArrayHelper.HexStringToByteArray(hex)); + } - private Hash ComputeRootWithMerklePathAndLeaf(Hash leaf, MerklePath path) - { - return path.ComputeRootWithLeafNode(leaf); - } + private Hash ComputeRootWithMerklePathAndLeaf(Hash leaf, MerklePath path) + { + return path.ComputeRootWithLeafNode(leaf); + } - private MerklePath GenerateMerklePath(IList index, IList hashes) - { - var merklePath = new MerklePath(); - foreach (var i in index) + private MerklePath GenerateMerklePath(IList index, IList hashes) + { + var merklePath = new MerklePath(); + foreach (var i in index) + merklePath.MerklePathNodes.Add(new MerklePathNode { - merklePath.MerklePathNodes.Add(new MerklePathNode - { - Hash = hashes[i], - IsLeftChildNode = i % 2 == 0 - }); - } - - return merklePath; - } + Hash = hashes[i], + IsLeftChildNode = i % 2 == 0 + }); - #endregion + return merklePath; } + + #endregion } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Extensions/ExtensionTests.cs b/test/AElf.Types.Tests/Extensions/ExtensionTests.cs index 15e6b4af09..c938b0c648 100644 --- a/test/AElf.Types.Tests/Extensions/ExtensionTests.cs +++ b/test/AElf.Types.Tests/Extensions/ExtensionTests.cs @@ -2,244 +2,261 @@ using System.Linq; using System.Text; using AElf.Cryptography; -using Xunit; using Google.Protobuf; using Shouldly; +using Xunit; + +namespace AElf.Types.Tests.Extensions; -namespace AElf.Types.Tests.Extensions +public class ExtensionTests { - public class ExtensionTests + [Fact] + public void Number_Extensions_Methods_Test() { - [Fact] - public void Number_Extensions_Methods_Test() - { - //ulong - var uNumber = (ulong)10; - var byteArray = uNumber.ToBytes(); - byteArray.ShouldNotBe(null); - - //int - var iNumber = 10; - var byteArray1 = iNumber.ToBytes(); - byteArray1.ShouldNotBe(null); - - //hash - var hash = HashHelper.ComputeFrom(iNumber); - hash.ShouldNotBe(null); - } + //ulong + var uNumber = (ulong)10; + var byteArray = uNumber.ToBytes(); + byteArray.ShouldNotBe(null); - [Fact] - public void Byte_Extensions_ToPlainBase58_Test() - { - var emptyByteString = ByteString.Empty; - emptyByteString.ToPlainBase58().ShouldBe(string.Empty); - - var byteString = ByteString.CopyFromUtf8("5ta1yvi2dFEs4V7YLPgwkbnn816xVUvwWyTHPHcfxMVLrLB"); - byteString.ToPlainBase58().ShouldBe("SmUQnCq4Ffvy8UeR9EEV9DhNVcNaLhGpqFTDZfzdebANJAgngqe8RfT1sqPPqJQ9"); - - var bytes = new byte[] {0, 0, 0}; - byteString = ByteString.CopyFrom(bytes); - byteString.ToPlainBase58().ShouldBe("111"); - } - [Fact] - public void ByteStringExtension_toHex_Test() - { - var hash=HashHelper.ComputeFrom("hash"); - var result= hash.Value.ToHex(true); - result.ShouldNotBe(null); - result.IndexOf("0x").ShouldBe(0); - - var result1= hash.Value.ToHex(); - result1.ShouldNotBe(null); - result1.IndexOf("0x").ShouldBe(-1); - } + //int + var iNumber = 10; + var byteArray1 = iNumber.ToBytes(); + byteArray1.ShouldNotBe(null); - [Fact] - public void ByteStringExtension_IsNullOrEmpty_Test() - { - var byteString1 = ByteString.CopyFrom(new byte[] { }); - var result= byteString1.IsNullOrEmpty(); - result.ShouldBe(true); - - var hash=HashHelper.ComputeFrom("hash"); - var result1= hash.Value.IsNullOrEmpty(); - result1.ShouldBe(false); - } + //hash + var hash = HashHelper.ComputeFrom(iNumber); + hash.ShouldNotBe(null); + } - [Fact] - public void ByteExtensions_ToHex_Test() - { - var hash=HashHelper.ComputeFrom("hash"); - var result = hash.ToByteArray().ToHex(true); - result.ShouldNotBe(null); - result.IndexOf("0x").ShouldBe(0); - - var result1 = hash.ToByteArray().ToHex(false); - result1.ShouldNotBe(null); - result1.IndexOf("0x").ShouldBe(-1); - } + [Fact] + public void Byte_Extensions_ToPlainBase58_Test() + { + var emptyByteString = ByteString.Empty; + emptyByteString.ToPlainBase58().ShouldBe(string.Empty); - [Fact] - public void ByteExtensions_Find_Test() - { - var bytes1 = new byte[] {5, 2, 1, 8,9,0,5,2,0}; - var bytes2 = new byte[] {4, 1}; - var bytes3 = new byte[] {5, 7}; - var bytes4 = new byte[] {2, 3}; - var bytes5 = new byte[] {5, 2, 0}; - var result2 = bytes1.Find(bytes2); - result2.ShouldBe(-1); - var result3 = bytes1.Find(bytes3); - result3.ShouldBe(-1); - var result4 = bytes1.Find(bytes4); - result4.ShouldBe(-1); - var result5 = bytes1.Find(bytes5); - result5.ShouldBe(6); - } - [Fact] - public void IMessageExtensions_ToBytesValue_Test() - { - var message=new Transaction(); - var result= message.ToBytesValue(); - result.Value.ShouldBeEmpty(); - } - [Fact] - public void StringExtensions_GetBytes_Test() - { - BlockHelper.GetRefBlockPrefix(Hash.Empty); - var string1 = "string"; - var result= string1.GetBytes(); - var expected = Encoding.UTF8.GetBytes(string1); - result.ShouldBe(expected); - } + var byteString = ByteString.CopyFromUtf8("5ta1yvi2dFEs4V7YLPgwkbnn816xVUvwWyTHPHcfxMVLrLB"); + byteString.ToPlainBase58().ShouldBe("SmUQnCq4Ffvy8UeR9EEV9DhNVcNaLhGpqFTDZfzdebANJAgngqe8RfT1sqPPqJQ9"); + + var bytes = new byte[] { 0, 0, 0 }; + byteString = ByteString.CopyFrom(bytes); + byteString.ToPlainBase58().ShouldBe("111"); + } + + [Fact] + public void ByteStringExtension_toHex_Test() + { + var hash = HashHelper.ComputeFrom("hash"); + var result = hash.Value.ToHex(true); + result.ShouldNotBe(null); + result.IndexOf("0x").ShouldBe(0); + + var result1 = hash.Value.ToHex(); + result1.ShouldNotBe(null); + result1.IndexOf("0x").ShouldBe(-1); + } + + [Fact] + public void ByteStringExtension_IsNullOrEmpty_Test() + { + var byteString1 = ByteString.CopyFrom(); + var result = byteString1.IsNullOrEmpty(); + result.ShouldBe(true); + + var hash = HashHelper.ComputeFrom("hash"); + var result1 = hash.Value.IsNullOrEmpty(); + result1.ShouldBe(false); + } + + [Fact] + public void ByteExtensions_ToHex_Test() + { + var hash = HashHelper.ComputeFrom("hash"); + var result = hash.ToByteArray().ToHex(true); + result.ShouldNotBe(null); + result.IndexOf("0x").ShouldBe(0); + + var result1 = hash.ToByteArray().ToHex(); + result1.ShouldNotBe(null); + result1.IndexOf("0x").ShouldBe(-1); + } + + [Fact] + public void ByteExtensions_Find_Test() + { + var bytes1 = new byte[] { 5, 2, 1, 8, 9, 0, 5, 2, 0 }; + var bytes2 = new byte[] { 4, 1 }; + var bytes3 = new byte[] { 5, 7 }; + var bytes4 = new byte[] { 2, 3 }; + var bytes5 = new byte[] { 5, 2, 0 }; + var result2 = bytes1.Find(bytes2); + result2.ShouldBe(-1); + var result3 = bytes1.Find(bytes3); + result3.ShouldBe(-1); + var result4 = bytes1.Find(bytes4); + result4.ShouldBe(-1); + var result5 = bytes1.Find(bytes5); + result5.ShouldBe(6); + } + + [Fact] + public void IMessageExtensions_ToBytesValue_Test() + { + var message = new Transaction(); + var result = message.ToBytesValue(); + result.Value.ShouldBeEmpty(); + } + + [Fact] + public void StringExtensions_GetBytes_Test() + { + BlockHelper.GetRefBlockPrefix(Hash.Empty); + var string1 = "string"; + var result = string1.GetBytes(); + var expected = Encoding.UTF8.GetBytes(string1); + result.ShouldBe(expected); + } - [Fact] - public void MerklePathExtensions_ComputeRootWithLeafNode_Test() + [Fact] + public void MerklePathExtensions_ComputeRootWithLeafNode_Test() + { + // left node { - // left node + var merkleLeftNode = new MerklePathNode { - var merkleLeftNode = new MerklePathNode - { - Hash = HashHelper.ComputeFrom("node1"), - IsLeftChildNode = true - }; - - var nodePath = new MerklePath - { - MerklePathNodes = { merkleLeftNode } - }; - - var hash = HashHelper.ComputeFrom("new"); - - var calculateHash = nodePath.ComputeRootWithLeafNode(hash); - var targetHash = HashHelper.ConcatAndCompute(merkleLeftNode.Hash, hash); - calculateHash.ShouldBe(targetHash); - } - - // right node + Hash = HashHelper.ComputeFrom("node1"), + IsLeftChildNode = true + }; + + var nodePath = new MerklePath { - var merkleLeftNode = new MerklePathNode - { - Hash = HashHelper.ComputeFrom("node1"), - IsLeftChildNode = false - }; - - var nodePath = new MerklePath - { - MerklePathNodes = { merkleLeftNode } - }; - - var hash = HashHelper.ComputeFrom("new"); - - var calculateHash = nodePath.ComputeRootWithLeafNode(hash); - var targetHash = HashHelper.ConcatAndCompute(hash, merkleLeftNode.Hash); - calculateHash.ShouldBe(targetHash); - } - } + MerklePathNodes = { merkleLeftNode } + }; - [Fact] - public void NumericExtensions_ToBytes_For_long() - { - long number = -2; - var bigEndianBytes = number.ToBytes(true); - ((int)bigEndianBytes.Last()).ShouldBe(254); - var numberFromBigEndianBytes = BitConverter.ToInt64(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); - numberFromBigEndianBytes.ShouldBe(number); - - var littleEndianBytes = number.ToBytes(false); - ((int)littleEndianBytes.Last()).ShouldBe(255); - numberFromBigEndianBytes = BitConverter.ToInt64(BitConverter.IsLittleEndian ? littleEndianBytes: littleEndianBytes.Reverse().ToArray()); - numberFromBigEndianBytes.ShouldBe(number); - } - - [Fact] - public void NumericExtensions_ToBytes_For_ulong() - { - ulong number = ulong.MaxValue - 1; - var bigEndianBytes = number.ToBytes(true); - ((int)bigEndianBytes.Last()).ShouldBe(254); - var numberFromBigEndianBytes = BitConverter.ToUInt64(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); - numberFromBigEndianBytes.ShouldBe(number); - - var littleEndianBytes = number.ToBytes(false); - ((int)littleEndianBytes.Last()).ShouldBe(255); - numberFromBigEndianBytes = BitConverter.ToUInt64(BitConverter.IsLittleEndian ? littleEndianBytes: littleEndianBytes.Reverse().ToArray()); - numberFromBigEndianBytes.ShouldBe(number); - } - - [Fact] - public void NumericExtensions_ToBytes_For_int() - { - int number = -2; - var bigEndianBytes = number.ToBytes(true); - ((int)bigEndianBytes.Last()).ShouldBe(254); - var numberFromBigEndianBytes = BitConverter.ToInt32(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); - numberFromBigEndianBytes.ShouldBe(number); - - var littleEndianBytes = number.ToBytes(false); - ((int)littleEndianBytes.Last()).ShouldBe(255); - numberFromBigEndianBytes = BitConverter.ToInt32(BitConverter.IsLittleEndian ? littleEndianBytes: littleEndianBytes.Reverse().ToArray()); - numberFromBigEndianBytes.ShouldBe(number); - } - - [Fact] - public void NumericExtensions_ToBytes_For_uint() - { - uint number = uint.MaxValue - 1; - var bigEndianBytes = number.ToBytes(true); - ((int)bigEndianBytes.Last()).ShouldBe(254); - var numberFromBigEndianBytes = BitConverter.ToUInt32(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); - numberFromBigEndianBytes.ShouldBe(number); - - var littleEndianBytes = number.ToBytes(false); - ((int)littleEndianBytes.Last()).ShouldBe(255); - numberFromBigEndianBytes = BitConverter.ToUInt32(BitConverter.IsLittleEndian ? littleEndianBytes: littleEndianBytes.Reverse().ToArray()); - numberFromBigEndianBytes.ShouldBe(number); + var hash = HashHelper.ComputeFrom("new"); + + var calculateHash = nodePath.ComputeRootWithLeafNode(hash); + var targetHash = HashHelper.ConcatAndCompute(merkleLeftNode.Hash, hash); + calculateHash.ShouldBe(targetHash); } - [Fact] - public void StateKeyExtensions_ToStateKey_Test() + // right node { - var statePath = new StatePath + var merkleLeftNode = new MerklePathNode { - Parts = { "1", "2", "3"} + Hash = HashHelper.ComputeFrom("node1"), + IsLeftChildNode = false }; - - var privateKey = ByteArrayHelper.HexStringToByteArray("5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f"); - var keyPair = CryptoHelper.FromPrivateKey(privateKey); - var address = Address.FromPublicKey(keyPair.PublicKey); - var addressBase58String = address.ToBase58(); - var targetKeyString = string.Join("/", new[] {addressBase58String}.Concat(statePath.Parts)); - var stateKey1 = statePath.ToStateKey(address); - var scopedStatePath = new ScopedStatePath + + var nodePath = new MerklePath { - Path = statePath, - Address = address + MerklePathNodes = { merkleLeftNode } }; - var stateKey2 = scopedStatePath.ToStateKey(); - - stateKey1.ShouldBe(targetKeyString); - stateKey2.ShouldBe(stateKey1); + + var hash = HashHelper.ComputeFrom("new"); + + var calculateHash = nodePath.ComputeRootWithLeafNode(hash); + var targetHash = HashHelper.ConcatAndCompute(hash, merkleLeftNode.Hash); + calculateHash.ShouldBe(targetHash); } } + + [Fact] + public void NumericExtensions_ToBytes_For_long() + { + long number = -2; + var bigEndianBytes = number.ToBytes(); + ((int)bigEndianBytes.Last()).ShouldBe(254); + var numberFromBigEndianBytes = + BitConverter.ToInt64(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); + numberFromBigEndianBytes.ShouldBe(number); + + var littleEndianBytes = number.ToBytes(false); + ((int)littleEndianBytes.Last()).ShouldBe(255); + numberFromBigEndianBytes = + BitConverter.ToInt64( + BitConverter.IsLittleEndian ? littleEndianBytes : littleEndianBytes.Reverse().ToArray()); + numberFromBigEndianBytes.ShouldBe(number); + } + + [Fact] + public void NumericExtensions_ToBytes_For_ulong() + { + var number = ulong.MaxValue - 1; + var bigEndianBytes = number.ToBytes(); + ((int)bigEndianBytes.Last()).ShouldBe(254); + var numberFromBigEndianBytes = + BitConverter.ToUInt64(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); + numberFromBigEndianBytes.ShouldBe(number); + + var littleEndianBytes = number.ToBytes(false); + ((int)littleEndianBytes.Last()).ShouldBe(255); + numberFromBigEndianBytes = + BitConverter.ToUInt64(BitConverter.IsLittleEndian + ? littleEndianBytes + : littleEndianBytes.Reverse().ToArray()); + numberFromBigEndianBytes.ShouldBe(number); + } + + [Fact] + public void NumericExtensions_ToBytes_For_int() + { + var number = -2; + var bigEndianBytes = number.ToBytes(); + ((int)bigEndianBytes.Last()).ShouldBe(254); + var numberFromBigEndianBytes = + BitConverter.ToInt32(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); + numberFromBigEndianBytes.ShouldBe(number); + + var littleEndianBytes = number.ToBytes(false); + ((int)littleEndianBytes.Last()).ShouldBe(255); + numberFromBigEndianBytes = + BitConverter.ToInt32( + BitConverter.IsLittleEndian ? littleEndianBytes : littleEndianBytes.Reverse().ToArray()); + numberFromBigEndianBytes.ShouldBe(number); + } + + [Fact] + public void NumericExtensions_ToBytes_For_uint() + { + var number = uint.MaxValue - 1; + var bigEndianBytes = number.ToBytes(); + ((int)bigEndianBytes.Last()).ShouldBe(254); + var numberFromBigEndianBytes = + BitConverter.ToUInt32(BitConverter.IsLittleEndian ? bigEndianBytes.Reverse().ToArray() : bigEndianBytes); + numberFromBigEndianBytes.ShouldBe(number); + + var littleEndianBytes = number.ToBytes(false); + ((int)littleEndianBytes.Last()).ShouldBe(255); + numberFromBigEndianBytes = + BitConverter.ToUInt32(BitConverter.IsLittleEndian + ? littleEndianBytes + : littleEndianBytes.Reverse().ToArray()); + numberFromBigEndianBytes.ShouldBe(number); + } + + [Fact] + public void StateKeyExtensions_ToStateKey_Test() + { + var statePath = new StatePath + { + Parts = { "1", "2", "3" } + }; + + var privateKey = + ByteArrayHelper.HexStringToByteArray("5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f"); + var keyPair = CryptoHelper.FromPrivateKey(privateKey); + var address = Address.FromPublicKey(keyPair.PublicKey); + var addressBase58String = address.ToBase58(); + var targetKeyString = string.Join("/", new[] { addressBase58String }.Concat(statePath.Parts)); + var stateKey1 = statePath.ToStateKey(address); + var scopedStatePath = new ScopedStatePath + { + Path = statePath, + Address = address + }; + var stateKey2 = scopedStatePath.ToStateKey(); + + stateKey1.ShouldBe(targetKeyString); + stateKey2.ShouldBe(stateKey1); + } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/HashTests.cs b/test/AElf.Types.Tests/HashTests.cs index 721aede317..0a5d2980b2 100644 --- a/test/AElf.Types.Tests/HashTests.cs +++ b/test/AElf.Types.Tests/HashTests.cs @@ -1,96 +1,96 @@ +using System; using System.Collections.Generic; -using Xunit; using Shouldly; +using Xunit; -namespace AElf.Types.Tests +namespace AElf.Types.Tests; + +public class HashTests { - public class HashTests + [Fact] + public void Generate_Hash_Test() { - [Fact] - public void Generate_Hash_Test() - { - //Generate randomly - var hash1 = HashHelper.ComputeFrom("hash1"); - var hash2 = HashHelper.ComputeFrom("hash2"); - hash1.ShouldNotBe(hash2); - - //Generate from string - var hash3 = HashHelper.ComputeFrom("Test"); - hash3.ShouldNotBe(null); - - //Generate from byte - var bytes = new byte[]{00, 12, 14, 16}; - var hash4 = HashHelper.ComputeFrom(bytes); - hash4.ShouldNotBe(null); - - //Generate from teo hash - var hash5 = HashHelper.ConcatAndCompute(hash1, hash2); - hash5.ShouldNotBe(null); - - //Generate from xor - var hash6 = HashHelper.XorAndCompute(hash1, hash2); - hash6.ShouldNotBe(null); - - //Generate from long - long longtype = 1; - var hash7 = HashHelper.ComputeFrom(longtype); - hash7.ShouldNotBe(null); - - //Generate from Message - var message= new Transaction(); - var hash8 = HashHelper.ComputeFrom(message); - hash8.ShouldNotBe(null); - } - - [Fact] - public void Get_Hash_Info_Test() - { - var hash = HashHelper.ComputeFrom("hash"); - var byteArray = hash.ToByteArray(); - var hexString = hash.ToHex(); - byteArray.Length.ShouldBe(32); - hexString.ShouldNotBe(string.Empty); - } - - [Fact] - public void Equal_Test() - { - var hash1 = HashHelper.ComputeFrom(new byte[] {10, 14, 1, 15}); - var hash2 = HashHelper.ComputeFrom(new byte[] {10, 14, 1, 15}); - var hash3 = HashHelper.ComputeFrom(new byte[] {15, 1, 14, 10}); - hash1.ShouldBe(hash2); - hash1.ShouldNotBe(hash3); - } - - [Fact] - public void Compare_Test() - { - var hash1 = HashHelper.ComputeFrom(new byte[] {10, 14, 1, 15}); - var hash2 = HashHelper.ComputeFrom(new byte[] {15, 1, 14, 10}); - hash1.CompareTo(hash2).ShouldBe(-1); - Should.Throw(() => { hash1.CompareTo(null); }); - - (hash1 < null).ShouldBeFalse(); - (null < hash2).ShouldBeTrue(); - (hash1 > hash2).ShouldBe(hash1.CompareTo(hash2)>0); - - Hash hashA = null; - Hash hashB = null; - var value = hashA > hashB; - value.ShouldBeFalse(); - } - - [Fact] - public void Dictionary_Test() - { - var dict = new Dictionary(); - var hash = HashHelper.ComputeFrom(new byte[] {10, 14, 1, 15}); - dict[hash] = "test"; - - var anotherHash = HashHelper.ComputeFrom(new byte[] {10, 14, 1, 15}); - - Assert.True(dict.TryGetValue(anotherHash, out var test)); - test.ShouldBe("test"); - } + //Generate randomly + var hash1 = HashHelper.ComputeFrom("hash1"); + var hash2 = HashHelper.ComputeFrom("hash2"); + hash1.ShouldNotBe(hash2); + + //Generate from string + var hash3 = HashHelper.ComputeFrom("Test"); + hash3.ShouldNotBe(null); + + //Generate from byte + var bytes = new byte[] { 00, 12, 14, 16 }; + var hash4 = HashHelper.ComputeFrom(bytes); + hash4.ShouldNotBe(null); + + //Generate from teo hash + var hash5 = HashHelper.ConcatAndCompute(hash1, hash2); + hash5.ShouldNotBe(null); + + //Generate from xor + var hash6 = HashHelper.XorAndCompute(hash1, hash2); + hash6.ShouldNotBe(null); + + //Generate from long + long longtype = 1; + var hash7 = HashHelper.ComputeFrom(longtype); + hash7.ShouldNotBe(null); + + //Generate from Message + var message = new Transaction(); + var hash8 = HashHelper.ComputeFrom(message); + hash8.ShouldNotBe(null); + } + + [Fact] + public void Get_Hash_Info_Test() + { + var hash = HashHelper.ComputeFrom("hash"); + var byteArray = hash.ToByteArray(); + var hexString = hash.ToHex(); + byteArray.Length.ShouldBe(32); + hexString.ShouldNotBe(string.Empty); + } + + [Fact] + public void Equal_Test() + { + var hash1 = HashHelper.ComputeFrom(new byte[] { 10, 14, 1, 15 }); + var hash2 = HashHelper.ComputeFrom(new byte[] { 10, 14, 1, 15 }); + var hash3 = HashHelper.ComputeFrom(new byte[] { 15, 1, 14, 10 }); + hash1.ShouldBe(hash2); + hash1.ShouldNotBe(hash3); + } + + [Fact] + public void Compare_Test() + { + var hash1 = HashHelper.ComputeFrom(new byte[] { 10, 14, 1, 15 }); + var hash2 = HashHelper.ComputeFrom(new byte[] { 15, 1, 14, 10 }); + hash1.CompareTo(hash2).ShouldBe(-1); + Should.Throw(() => { hash1.CompareTo(null); }); + + (hash1 < null).ShouldBeFalse(); + (null < hash2).ShouldBeTrue(); + (hash1 > hash2).ShouldBe(hash1.CompareTo(hash2) > 0); + + Hash hashA = null; + Hash hashB = null; + var value = hashA > hashB; + value.ShouldBeFalse(); + } + + [Fact] + public void Dictionary_Test() + { + var dict = new Dictionary(); + var hash = HashHelper.ComputeFrom(new byte[] { 10, 14, 1, 15 }); + dict[hash] = "test"; + + var anotherHash = HashHelper.ComputeFrom(new byte[] { 10, 14, 1, 15 }); + + Assert.True(dict.TryGetValue(anotherHash, out var test)); + test.ShouldBe("test"); } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Helper/BlockHelperTest.cs b/test/AElf.Types.Tests/Helper/BlockHelperTest.cs index b6d1756248..1a7ba3fd8c 100644 --- a/test/AElf.Types.Tests/Helper/BlockHelperTest.cs +++ b/test/AElf.Types.Tests/Helper/BlockHelperTest.cs @@ -1,16 +1,15 @@ using Shouldly; using Xunit; -namespace AElf.Types.Tests.Helper +namespace AElf.Types.Tests.Helper; + +public class BlockHelperTest { - public class BlockHelperTest + [Fact] + public void GetRefBlockPrefix_Test() { - [Fact] - public void GetRefBlockPrefix_Test() - { - var blockHash = HashHelper.ComputeFrom("test"); - var get = BlockHelper.GetRefBlockPrefix(blockHash); - get.Length.ShouldBe(4); - } + var blockHash = HashHelper.ComputeFrom("test"); + var get = BlockHelper.GetRefBlockPrefix(blockHash); + get.Length.ShouldBe(4); } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Helper/ByteArrayHelperTests.cs b/test/AElf.Types.Tests/Helper/ByteArrayHelperTests.cs index c9722c2ded..74bcb2d3a5 100644 --- a/test/AElf.Types.Tests/Helper/ByteArrayHelperTests.cs +++ b/test/AElf.Types.Tests/Helper/ByteArrayHelperTests.cs @@ -1,115 +1,103 @@ using System; -using System.Linq; -using Xunit; using Shouldly; +using Xunit; -namespace AElf.Types.Tests.Helper +namespace AElf.Types.Tests.Helper; + +public class ByteArrayHelperTests { - public class ByteArrayHelperTests + private static readonly Random _rnd = new(); + + [Fact] + public void Convert_Byte_FromString_Test() { - [Fact] - public void Convert_Byte_FromString_Test() - { - var hexValue = HashHelper.ComputeFrom("hexvalue").ToHex(); - var hashArray = ByteArrayHelper.HexStringToByteArray(hexValue); - hashArray.Length.ShouldBe(32); + var hexValue = HashHelper.ComputeFrom("hexvalue").ToHex(); + var hashArray = ByteArrayHelper.HexStringToByteArray(hexValue); + hashArray.Length.ShouldBe(32); - var value = "0x00"; - var valueArrary = ByteArrayHelper.HexStringToByteArray(value); - valueArrary.Length.ShouldBe(1); - } + var value = "0x00"; + var valueArrary = ByteArrayHelper.HexStringToByteArray(value); + valueArrary.Length.ShouldBe(1); + } + private static byte[] RandomFill(int count) + { + var random = new byte[count]; - static Random _rnd = new Random(); + _rnd.NextBytes(random); - private static byte[] RandomFill(int count) - { - byte[] random = new byte[count]; + return random; + } - _rnd.NextBytes(random); + [Fact] + public void Bytes_Equal_Test() + { + var byteArray1 = RandomFill(10); + var byteArray2 = RandomFill(10); + var byteArray3 = RandomFill(11); + var result = byteArray1.BytesEqual(byteArray2); + result.ShouldBe(false); - return random; - } + var result1 = byteArray1.BytesEqual(byteArray1); + result1.ShouldBe(true); - [Fact] - public void Bytes_Equal_Test() - { - var byteArray1 = RandomFill(10); - var byteArray2 = RandomFill(10); - var byteArray3 = RandomFill(11); - var result = ByteArrayHelper.BytesEqual(byteArray1, byteArray2); - result.ShouldBe(false); - - var result1 = ByteArrayHelper.BytesEqual(byteArray1, byteArray1); - result1.ShouldBe(true); - - var result2 = ByteArrayHelper.BytesEqual(byteArray1, byteArray3); - result2.ShouldBe(false); - - byte[] byteArray4 = new byte[10]; - for (int i = 0; i < 10; i++) - { - byteArray4[i] = byteArray1[i]; - } - var result3= byteArray1.BytesEqual(byteArray4); - result3.ShouldBe(true); - - byte[] byteArray5 = null; - var result4 = byteArray5.BytesEqual(byteArray4); - result4.ShouldBe(false); - } + var result2 = byteArray1.BytesEqual(byteArray3); + result2.ShouldBe(false); - [Fact] - public void LeftPadBytes_Test() - { - var bytes = new byte[] {1, 2, 3, 4}; - var expectBytes = new byte[] {0, 0, 0, 0, 1, 2, 3, 4}; + var byteArray4 = new byte[10]; + for (var i = 0; i < 10; i++) byteArray4[i] = byteArray1[i]; + var result3 = byteArray1.BytesEqual(byteArray4); + result3.ShouldBe(true); - var result1 = bytes.LeftPad(8); - var result2 = bytes.LeftPad(2); + byte[] byteArray5 = null; + var result4 = byteArray5.BytesEqual(byteArray4); + result4.ShouldBe(false); + } - result1.ShouldBe(expectBytes); - result2.ShouldBe(bytes); - } + [Fact] + public void LeftPadBytes_Test() + { + var bytes = new byte[] { 1, 2, 3, 4 }; + var expectBytes = new byte[] { 0, 0, 0, 0, 1, 2, 3, 4 }; + + var result1 = bytes.LeftPad(8); + var result2 = bytes.LeftPad(2); - [Fact] - public void ConcatArrays_Test() + result1.ShouldBe(expectBytes); + result2.ShouldBe(bytes); + } + + [Fact] + public void ConcatArrays_Test() + { + var bytes1 = new byte[] { 1, 2, 3, 4 }; + var bytes2 = new byte[] { 5, 6, 7, 8 }; + var concatBytes = ByteArrayHelper.ConcatArrays(bytes1, bytes2); + concatBytes.Length.ShouldBe(8); + for (var i = 0; i < bytes1.Length; i++) + concatBytes[i].ShouldBe(bytes1[i]); + for (var i = bytes1.Length; i < concatBytes.Length; i++) + concatBytes[i].ShouldBe(bytes2[i - bytes1.Length]); + } + + [Theory] + [InlineData(new byte[] { 1, 2, 3 }, 1, 1)] + [InlineData(new byte[] { 1, 2, 3 }, 1, 2)] + [InlineData(new byte[] { 1, 2, 3 }, 1, 0)] + [InlineData(new byte[] { 1, 2, 3 }, 2, 0)] + public void SubArray_Test(byte[] array, int startIndex, int length) + { + if (length > 0) { - var bytes1 = new byte[] {1, 2, 3, 4}; - var bytes2 = new byte[] {5, 6, 7, 8}; - var concatBytes = ByteArrayHelper.ConcatArrays(bytes1, bytes2); - concatBytes.Length.ShouldBe(8); - for(var i =0; i < bytes1.Length; i ++) - concatBytes[i].ShouldBe(bytes1[i]); - for(var i = bytes1.Length; i < concatBytes.Length; i ++) - concatBytes[i].ShouldBe(bytes2[i - bytes1.Length]); + var subArray = ByteArrayHelper.SubArray(array, startIndex, length); + subArray.Length.ShouldBe(length); + for (var i = 0; i < length; i++) subArray[i].ShouldBe(array[startIndex + i]); } - - [Theory] - [InlineData( new byte[]{1,2,3}, 1 , 1)] - [InlineData( new byte[]{1,2,3}, 1 , 2)] - [InlineData( new byte[]{1,2,3}, 1 , 0)] - [InlineData( new byte[]{1,2,3}, 2 , 0)] - public void SubArray_Test(byte[] array, int startIndex, int length) + else { - if (length > 0) - { - var subArray = ByteArrayHelper.SubArray(array, startIndex, length); - subArray.Length.ShouldBe(length); - for (var i = 0; i < length; i++) - { - subArray[i].ShouldBe(array[startIndex + i]); - } - } - else - { - var subArray = ByteArrayHelper.SubArray(array, startIndex); - subArray.Length.ShouldBe(array.Length - startIndex); - for (var i = 0; i < length; i++) - { - subArray[i].ShouldBe(array[startIndex + i]); - } - } + var subArray = ByteArrayHelper.SubArray(array, startIndex); + subArray.Length.ShouldBe(array.Length - startIndex); + for (var i = 0; i < length; i++) subArray[i].ShouldBe(array[startIndex + i]); } } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Helper/ByteStringHelperTests.cs b/test/AElf.Types.Tests/Helper/ByteStringHelperTests.cs index cfd66af6a3..33f5df8b3d 100644 --- a/test/AElf.Types.Tests/Helper/ByteStringHelperTests.cs +++ b/test/AElf.Types.Tests/Helper/ByteStringHelperTests.cs @@ -1,35 +1,34 @@ -using Xunit; -using Google.Protobuf; +using Google.Protobuf; using Shouldly; +using Xunit; -namespace AElf.Types.Tests.Helper +namespace AElf.Types.Tests.Helper; + +public class ByteStringHelperTests { - public class ByteStringHelperTests + [Fact] + public void ByteString_Compare_Test() { - [Fact] - public void ByteString_Compare_Test() - { - var byteString1 = ByteString.CopyFrom(new byte[] { }); - var byteString2 = ByteString.CopyFrom(new byte[1] { 02 }); - var byteString3 = ByteString.CopyFrom(new byte[2] { 04, 10 }); - var byteString4 = ByteString.CopyFrom(new byte[3] { 10, 12, 14 }); - var byteString5 = ByteString.CopyFrom(new byte[3] { 00, 12, 14 }); - var byteString6 = ByteString.CopyFrom(new byte[3] { 00, 12, 14 }); - - ByteStringHelper.Compare(ByteString.Empty, ByteString.Empty).ShouldBe(0); - ByteStringHelper.Compare(byteString1, byteString2).ShouldBe(0); - ByteStringHelper.Compare(byteString2, byteString3).ShouldBe(-1); - ByteStringHelper.Compare(byteString3, byteString4).ShouldBe(-1); - ByteStringHelper.Compare(byteString4, byteString5).ShouldBe(1); - ByteStringHelper.Compare(byteString5, byteString6).ShouldBe(0); - } + var byteString1 = ByteString.CopyFrom(); + var byteString2 = ByteString.CopyFrom(02); + var byteString3 = ByteString.CopyFrom(04, 10); + var byteString4 = ByteString.CopyFrom(10, 12, 14); + var byteString5 = ByteString.CopyFrom(00, 12, 14); + var byteString6 = ByteString.CopyFrom(00, 12, 14); + + ByteStringHelper.Compare(ByteString.Empty, ByteString.Empty).ShouldBe(0); + ByteStringHelper.Compare(byteString1, byteString2).ShouldBe(0); + ByteStringHelper.Compare(byteString2, byteString3).ShouldBe(-1); + ByteStringHelper.Compare(byteString3, byteString4).ShouldBe(-1); + ByteStringHelper.Compare(byteString4, byteString5).ShouldBe(1); + ByteStringHelper.Compare(byteString5, byteString6).ShouldBe(0); + } - [Fact] - public void ByteString_FromHexString() - { - var hexString = HashHelper.ComputeFrom("hash").ToHex(); - var result = ByteStringHelper.FromHexString(hexString); - result.ShouldNotBe(null); - } + [Fact] + public void ByteString_FromHexString() + { + var hexString = HashHelper.ComputeFrom("hash").ToHex(); + var result = ByteStringHelper.FromHexString(hexString); + result.ShouldNotBe(null); } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Helper/ChainHelperTests.cs b/test/AElf.Types.Tests/Helper/ChainHelperTests.cs index eece4d49ab..5139cfe4a6 100644 --- a/test/AElf.Types.Tests/Helper/ChainHelperTests.cs +++ b/test/AElf.Types.Tests/Helper/ChainHelperTests.cs @@ -1,53 +1,52 @@ using Shouldly; using Xunit; -namespace AElf.Types.Tests.Helper +namespace AElf.Types.Tests.Helper; + +public class ChainHelperTests { - public class ChainHelperTests + [Fact] + public void TestChainIdGeneration() { - [Fact] - public void TestChainIdGeneration() { - { - var chainId = ChainHelper.GetChainId(0); - var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); - chainIdBased58.ShouldBe("2111"); - - var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58); - convertedChainId.ShouldBe(chainId); - } - - { - var chainId = ChainHelper.GetChainId(1); - var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); - chainIdBased58.ShouldBe("2112"); - - var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58); - convertedChainId.ShouldBe(chainId); - } - - { - var chainIdMaxValue = ChainHelper.GetChainId(long.MaxValue); - var chainIdBased58MaxValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue); - chainIdBased58MaxValue.ShouldBe("mR59"); - - var convertedChainIdMaxValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MaxValue); - convertedChainIdMaxValue.ShouldBe(chainIdMaxValue); - - var chainIdMinValue = ChainHelper.GetChainId(long.MinValue); - chainIdMinValue.ShouldBe(chainIdMaxValue); - var chainIdBased58MinValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue); - chainIdBased58MinValue.ShouldBe(chainIdBased58MaxValue); - var convertedChainIdMinValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MinValue); - convertedChainIdMinValue.ShouldBe(convertedChainIdMaxValue); - } - - { - var chainIdAElf = ChainHelper.ConvertBase58ToChainId("AELF"); - var chainId = ChainHelper.GetChainId(chainIdAElf + 1); - var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); - chainIdBased58.ShouldBe("tDVV"); - } + var chainId = ChainHelper.GetChainId(0); + var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); + chainIdBased58.ShouldBe("2111"); + + var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58); + convertedChainId.ShouldBe(chainId); + } + + { + var chainId = ChainHelper.GetChainId(1); + var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); + chainIdBased58.ShouldBe("2112"); + + var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58); + convertedChainId.ShouldBe(chainId); + } + + { + var chainIdMaxValue = ChainHelper.GetChainId(long.MaxValue); + var chainIdBased58MaxValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue); + chainIdBased58MaxValue.ShouldBe("mR59"); + + var convertedChainIdMaxValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MaxValue); + convertedChainIdMaxValue.ShouldBe(chainIdMaxValue); + + var chainIdMinValue = ChainHelper.GetChainId(long.MinValue); + chainIdMinValue.ShouldBe(chainIdMaxValue); + var chainIdBased58MinValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue); + chainIdBased58MinValue.ShouldBe(chainIdBased58MaxValue); + var convertedChainIdMinValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MinValue); + convertedChainIdMinValue.ShouldBe(convertedChainIdMaxValue); + } + + { + var chainIdAElf = ChainHelper.ConvertBase58ToChainId("AELF"); + var chainId = ChainHelper.GetChainId(chainIdAElf + 1); + var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId); + chainIdBased58.ShouldBe("tDVV"); } } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/Helper/SerializationHelperTest.cs b/test/AElf.Types.Tests/Helper/SerializationHelperTest.cs index 6e3f524b9f..e98e2b6861 100644 --- a/test/AElf.Types.Tests/Helper/SerializationHelperTest.cs +++ b/test/AElf.Types.Tests/Helper/SerializationHelperTest.cs @@ -3,102 +3,103 @@ using Shouldly; using Xunit; -namespace AElf.Types.Tests.Helper +namespace AElf.Types.Tests.Helper; + +public class SerializationHelperTest { - public class SerializationHelperTest + [Fact] + public void Serialize_And_Deserialize_Test() { - [Fact] - public void Serialize_And_Deserialize_Test() + //int { - //int - { - int originTarget = -1; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - //uint - { - uint originTarget = uint.MaxValue; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - //bool - { - var deserializeTarget = GetDeserializeValue(true); - deserializeTarget.ShouldBe(true); - } - - //long - { - long originTarget = -1; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - //ulong - { - ulong originTarget = 111_000_111_000; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - //enum - { - SerializeSupportType originTarget = SerializeSupportType.Long; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - //string - { - string originTarget = "test"; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - var iMessageObject = new LogEvent - { - Name = "Test" - }; - - //byte[] - { - var originTarget = iMessageObject.ToByteString().ToByteArray(); - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.Length.ShouldBe(originTarget.Length); - for(var i = 0; i < deserializeTarget.Length; i ++) - deserializeTarget[i].ShouldBe(originTarget[i]); - } - - //IMessage - { - var originTarget = iMessageObject; - var deserializeTarget = GetDeserializeValue(originTarget); - deserializeTarget.ShouldBe(originTarget); - } - - // other type - { - var originTarget = new SerializationHelperTest(); - Should.Throw(() => { SerializationHelper.Serialize(originTarget);}); - var dataByte = new byte[0]; - Should.Throw(() => { SerializationHelper.Deserialize(dataByte);}); - } - + var originTarget = -1; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); + } + + //uint + { + var originTarget = uint.MaxValue; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); + } + + //bool + { + var deserializeTarget = GetDeserializeValue(true); + deserializeTarget.ShouldBe(true); + } + + //long + { + long originTarget = -1; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); } - private T GetDeserializeValue(object ob) + //ulong { - var serializeTarget = SerializationHelper.Serialize(ob); - return SerializationHelper.Deserialize(serializeTarget); + ulong originTarget = 111_000_111_000; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); } - private enum SerializeSupportType + //enum { - Int, - Long + var originTarget = SerializeSupportType.Long; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); } + + //string + { + var originTarget = "test"; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); + } + + var iMessageObject = new LogEvent + { + Name = "Test" + }; + + //byte[] + { + var originTarget = iMessageObject.ToByteString().ToByteArray(); + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.Length.ShouldBe(originTarget.Length); + for (var i = 0; i < deserializeTarget.Length; i++) + deserializeTarget[i].ShouldBe(originTarget[i]); + } + + //IMessage + { + var originTarget = iMessageObject; + var deserializeTarget = GetDeserializeValue(originTarget); + deserializeTarget.ShouldBe(originTarget); + } + + // other type + { + var originTarget = new SerializationHelperTest(); + Should.Throw(() => { SerializationHelper.Serialize(originTarget); }); + var dataByte = new byte[0]; + Should.Throw(() => + { + SerializationHelper.Deserialize(dataByte); + }); + } + } + + private T GetDeserializeValue(object ob) + { + var serializeTarget = SerializationHelper.Serialize(ob); + return SerializationHelper.Deserialize(serializeTarget); + } + + private enum SerializeSupportType + { + Int, + Long } } \ No newline at end of file diff --git a/test/AElf.Types.Tests/ProtobufTests.cs b/test/AElf.Types.Tests/ProtobufTests.cs index 53d803a28a..a3805b0cb0 100644 --- a/test/AElf.Types.Tests/ProtobufTests.cs +++ b/test/AElf.Types.Tests/ProtobufTests.cs @@ -1,44 +1,41 @@ -using System; using Google.Protobuf; using Google.Protobuf.Reflection; -using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; using Xunit.Abstractions; -namespace AElf.Types.Tests +namespace AElf.Types.Tests; + +public class ProtobufTests { - public class ProtobufTests - { - private readonly ITestOutputHelper _testOutputHelper; + private readonly ITestOutputHelper _testOutputHelper; - public ProtobufTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } + public ProtobufTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } - [Fact] - public void TestDescriptor() - { - var descriptorBytes = Hash.Descriptor.File.SerializedData; + [Fact] + public void TestDescriptor() + { + var descriptorBytes = Hash.Descriptor.File.SerializedData; - var file = FileDescriptor.BuildFromByteStrings(new ByteString[] {descriptorBytes}); + var file = FileDescriptor.BuildFromByteStrings(new[] { descriptorBytes }); - var reg = TypeRegistry.FromFiles(file); + var reg = TypeRegistry.FromFiles(file); - var messageDescriptor = reg.Find("aelf.Hash"); + var messageDescriptor = reg.Find("aelf.Hash"); - messageDescriptor.Name.ShouldBe("Hash"); + messageDescriptor.Name.ShouldBe("Hash"); - var hash = HashHelper.ComputeFrom("hello"); + var hash = HashHelper.ComputeFrom("hello"); - var json = JsonFormatter.Default.Format(hash); + var json = JsonFormatter.Default.Format(hash); - //JsonParser.Default.Parse(json, messageDescriptor); - //it will not work, messageDescriptor clr type is null, the factory of parser is null + //JsonParser.Default.Parse(json, messageDescriptor); + //it will not work, messageDescriptor clr type is null, the factory of parser is null - var deserializedHash = (Hash) JsonParser.Default.Parse(json, Hash.Descriptor); - deserializedHash.ShouldBe(hash); - } + var deserializedHash = (Hash)JsonParser.Default.Parse(json, Hash.Descriptor); + deserializedHash.ShouldBe(hash); } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj index 2a0fa6839a..161e32c6a4 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj +++ b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj @@ -4,16 +4,16 @@ false - - - - - - + + + + + + - + - + diff --git a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs index a670de14c0..096c521b52 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs @@ -4,13 +4,11 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using AElf.Standards.ACS0; using AElf.ContractDeployer; using AElf.Contracts.Genesis; using AElf.Contracts.MultiToken; using AElf.Contracts.Vote; using AElf.Cryptography; -using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; @@ -20,1659 +18,1656 @@ using AElf.Kernel.TransactionPool.Infrastructure; using AElf.OS; using AElf.Runtime.CSharp; +using AElf.Standards.ACS0; using AElf.TestBase; using AElf.Types; using AElf.WebApp.Application.Chain.Application; using AElf.WebApp.Application.Chain.Dto; using AElf.WebApp.Application.Chain.Infrastructure; using Google.Protobuf; -using Microsoft.Extensions.Internal; using Microsoft.Extensions.Options; using Org.BouncyCastle.Utilities.Encoders; using Shouldly; using Xunit; using Xunit.Abstractions; -using SampleAddress = AElf.Kernel.SampleAddress; -using Volo.Abp.EventBus; -using Xunit.Sdk; -namespace AElf.WebApp.Application.Chain.Tests +namespace AElf.WebApp.Application.Chain.Tests; + +public sealed class BlockChainAppServiceTest : WebAppTestBase { - public sealed class BlockChainAppServiceTest : WebAppTestBase + private readonly IAccountService _accountService; + + private readonly IBlockchainService _blockchainService; + private readonly IBlockchainStateService _blockchainStateService; + private readonly IBlockStateSetManger _blockStateSetManger; + private readonly OSTestHelper _osTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; + private readonly TransactionValidationStatusChangedEventHandler _transactionValidationStatusChangedEventHandler; + private readonly ITxHub _txHub; + private IReadOnlyDictionary _codes; + + public BlockChainAppServiceTest(ITestOutputHelper outputHelper) : base(outputHelper) { - private IReadOnlyDictionary _codes; - - public IReadOnlyDictionary Codes => - _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - - private byte[] ConfigurationContractCode => Codes.Single(kv => kv.Key.Contains("Configuration")).Value; - private byte[] VoteContractCode => Codes.Single(kv => kv.Key.Contains("Vote")).Value; - - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly ITxHub _txHub; - private readonly IBlockchainStateService _blockchainStateService; - private readonly IBlockStateSetManger _blockStateSetManger; - private readonly OSTestHelper _osTestHelper; - private readonly IAccountService _accountService; - private readonly ITransactionResultStatusCacheProvider _transactionResultStatusCacheProvider; - private readonly TransactionValidationStatusChangedEventHandler _transactionValidationStatusChangedEventHandler; - public BlockChainAppServiceTest(ITestOutputHelper outputHelper) : base(outputHelper) - { - _transactionResultStatusCacheProvider = GetRequiredService();; - _blockchainService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _txHub = GetRequiredService(); - _blockchainStateService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - _accountService = GetRequiredService(); - _blockStateSetManger = GetRequiredService(); - _transactionValidationStatusChangedEventHandler = GetRequiredService(); - } + _transactionResultStatusCacheProvider = GetRequiredService(); + ; + _blockchainService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _txHub = GetRequiredService(); + _blockchainStateService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + _accountService = GetRequiredService(); + _blockStateSetManger = GetRequiredService(); + _transactionValidationStatusChangedEventHandler = + GetRequiredService(); + } - [Fact] - public async Task Deploy_Contract_Success_Test() - { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - var transaction = new Transaction - { - From = accountAddress, - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(BasicContractZero.DeploySmartContract), - Params = ByteString.CopyFrom(new ContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(VoteContractCode) - }.ToByteArray()), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash), - }; - transaction.Signature = - ByteString.CopyFrom(await _accountService.SignAsync(transaction.GetHash().ToByteArray())); - - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; + public IReadOnlyDictionary Codes => + _codes ?? (_codes = ContractsDeployer.GetContractCodes()); - var sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters); + private byte[] ConfigurationContractCode => Codes.Single(kv => kv.Key.Contains("Configuration")).Value; + private byte[] VoteContractCode => Codes.Single(kv => kv.Key.Contains("Vote")).Value; - sendTransactionResponse.TransactionId.ShouldBe(transaction.GetHash().ToHex()); - await _osTestHelper.MinedOneBlock(); - var transactionResult = await _osTestHelper.GetTransactionResultsAsync(transaction.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - [Fact] - public async Task Update_Contract_Success_Test() + [Fact] + public async Task Deploy_Contract_Success_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + var transaction = new Transaction { - var accountAddress = await _accountService.GetAccountAsync(); - var chain = await _blockchainService.GetChainAsync(); - var deployTransaction = new Transaction + From = accountAddress, + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(BasicContractZero.DeploySmartContract), + Params = ByteString.CopyFrom(new ContractDeploymentInput { - From = accountAddress, - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(BasicContractZero.DeploySmartContract), - Params = ByteString.CopyFrom(new ContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(VoteContractCode) - }.ToByteArray()), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash), - }; - deployTransaction.Signature = - ByteString.CopyFrom(await _accountService.SignAsync(deployTransaction.GetHash().ToByteArray())); - - var parameters = new Dictionary - { - {"rawTransaction", deployTransaction.ToByteArray().ToHex()} - }; - - var sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters); - - sendTransactionResponse.TransactionId.ShouldBe(deployTransaction.GetHash().ToHex()); - var deployBlock = await _osTestHelper.MinedOneBlock(); - var transactionResult = await _osTestHelper.GetTransactionResultsAsync(deployTransaction.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var address = Address.Parser.ParseFrom(transactionResult.ReturnValue); - var transaction = new Transaction - { - From = accountAddress, - To = address, - MethodName = nameof(VoteContractContainer.VoteContractStub.GetVotingResult), - Params = ByteString.CopyFrom(new GetVotingResultInput - { - SnapshotNumber = 1, - VotingItemId = Hash.Empty - }.ToByteArray()), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash), - }; - transaction.Signature = - ByteString.CopyFrom(await _accountService.SignAsync(transaction.GetHash().ToByteArray())); - - parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(VoteContractCode) + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + transaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(transaction.GetHash().ToByteArray())); + + var parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; - sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters); + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); - sendTransactionResponse.TransactionId.ShouldBe(transaction.GetHash().ToHex()); - await _osTestHelper.MinedOneBlock(); - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); - response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); - response.Transaction.Params.ShouldBe(GetVotingResultInput.Parser.ParseFrom(transaction.Params).ToString()); - - var updateTransaction = new Transaction + sendTransactionResponse.TransactionId.ShouldBe(transaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + var transactionResult = await _osTestHelper.GetTransactionResultsAsync(transaction.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact] + public async Task Update_Contract_Success_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + var deployTransaction = new Transaction + { + From = accountAddress, + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(BasicContractZero.DeploySmartContract), + Params = ByteString.CopyFrom(new ContractDeploymentInput { - From = accountAddress, - To = _smartContractAddressService.GetZeroSmartContractAddress(), - MethodName = nameof(BasicContractZero.UpdateSmartContract), - Params = ByteString.CopyFrom(new ContractUpdateInput - { - Address = address, - Code = ByteString.CopyFrom(ConfigurationContractCode) - }.ToByteArray()), - RefBlockNumber = chain.BestChainHeight, - RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash), - }; - updateTransaction.Signature = - ByteString.CopyFrom(await _accountService.SignAsync(updateTransaction.GetHash().ToByteArray())); - - parameters = new Dictionary + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(VoteContractCode) + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + deployTransaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(deployTransaction.GetHash().ToByteArray())); + + var parameters = new Dictionary + { + { "rawTransaction", deployTransaction.ToByteArray().ToHex() } + }; + + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(deployTransaction.GetHash().ToHex()); + var deployBlock = await _osTestHelper.MinedOneBlock(); + var transactionResult = await _osTestHelper.GetTransactionResultsAsync(deployTransaction.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var address = Address.Parser.ParseFrom(transactionResult.ReturnValue); + var transaction = new Transaction + { + From = accountAddress, + To = address, + MethodName = nameof(VoteContractContainer.VoteContractStub.GetVotingResult), + Params = ByteString.CopyFrom(new GetVotingResultInput { - {"rawTransaction", updateTransaction.ToByteArray().ToHex()} - }; - - sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters); - - sendTransactionResponse.TransactionId.ShouldBe(updateTransaction.GetHash().ToHex()); - await _osTestHelper.MinedOneBlock(); - transactionResult = await _osTestHelper.GetTransactionResultsAsync(updateTransaction.GetHash()); - transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); - response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); - response.Transaction.Params.ShouldBe(transaction.Params.ToBase64()); - response.Transaction.Params.ShouldNotBe( - GetVotingResultInput.Parser.ParseFrom(transaction.Params).ToString()); - } - - [Fact] - public async Task GetBlockHeight_Test() + SnapshotNumber = 1, + VotingItemId = Hash.Empty + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + transaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(transaction.GetHash().ToByteArray())); + + parameters = new Dictionary { - // Get current height - var response = await GetResponseAsStringAsync("/api/blockChain/blockHeight"); - var currentHeight = long.Parse(response); - - var chain = await _blockchainService.GetChainAsync(); - currentHeight.ShouldBe(chain.BestChainHeight); + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; - // Mined one block - var transaction = await _osTestHelper.GenerateTransferTransaction(); - await _osTestHelper.BroadcastTransactions(new List {transaction}); - await _osTestHelper.MinedOneBlock(); + sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); - // Get latest height - response = await GetResponseAsStringAsync("/api/blockChain/blockHeight"); - var height = long.Parse(response); - height.ShouldBe(currentHeight + 1); - } + sendTransactionResponse.TransactionId.ShouldBe(transaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); + response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); + response.Transaction.Params.ShouldBe(GetVotingResultInput.Parser.ParseFrom(transaction.Params).ToString()); - [Fact] - public async Task ExecuteTransaction_Success_Test() + var updateTransaction = new Transaction { - // Generate a transaction - var transaction = await GenerateViewTransaction( - nameof(TokenContractContainer.TokenContractStub.GetTokenInfo), - new GetTokenInfoInput - { - Symbol = "ELF" - }); + From = accountAddress, + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(BasicContractZero.UpdateSmartContract), + Params = ByteString.CopyFrom(new ContractUpdateInput + { + Address = address, + Code = ByteString.CopyFrom(ConfigurationContractCode) + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + updateTransaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(updateTransaction.GetHash().ToByteArray())); + + parameters = new Dictionary + { + { "rawTransaction", updateTransaction.ToByteArray().ToHex() } + }; + + sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(updateTransaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + transactionResult = await _osTestHelper.GetTransactionResultsAsync(updateTransaction.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); + response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); + response.Transaction.Params.ShouldBe(transaction.Params.ToBase64()); + response.Transaction.Params.ShouldNotBe( + GetVotingResultInput.Parser.ParseFrom(transaction.Params).ToString()); + } - var parameters = new Dictionary + [Fact] + public async Task GetBlockHeight_Test() + { + // Get current height + var response = await GetResponseAsStringAsync("/api/blockChain/blockHeight"); + var currentHeight = long.Parse(response); + + var chain = await _blockchainService.GetChainAsync(); + currentHeight.ShouldBe(chain.BestChainHeight); + + // Mined one block + var transaction = await _osTestHelper.GenerateTransferTransaction(); + await _osTestHelper.BroadcastTransactions(new List { transaction }); + await _osTestHelper.MinedOneBlock(); + + // Get latest height + response = await GetResponseAsStringAsync("/api/blockChain/blockHeight"); + var height = long.Parse(response); + height.ShouldBe(currentHeight + 1); + } + + [Fact] + public async Task ExecuteTransaction_Success_Test() + { + // Generate a transaction + var transaction = await GenerateViewTransaction( + nameof(TokenContractContainer.TokenContractStub.GetTokenInfo), + new GetTokenInfoInput { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; + Symbol = "ELF" + }); - var response = await PostResponseAsStringAsync("/api/blockChain/executeTransaction", parameters); - response.ShouldNotBeNullOrEmpty(); - } + var parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + + var response = await PostResponseAsStringAsync("/api/blockChain/executeTransaction", parameters); + response.ShouldNotBeNullOrEmpty(); + } - [Fact] - public async Task ExecuteTransaction_Failed_Test() + [Fact] + public async Task ExecuteTransaction_Failed_Test() + { + var parameters = new Dictionary { - var parameters = new Dictionary { - { - "rawTransaction", - "0a200a1e4604ccbdaa377fd7022b56436b99309e8b71cc5d78e909d271dbd1aeee6412200a1eaaa58b6cf58d4ef337f6dc55b701fd57d622015a3548a91a4e40892aa355180b220436957f93320c476574546f6b656e496e666f3a060a04454c46324a416246d781d80759d8ae6bb895b17203a3c9d4e89f083d7d89d9b6cbbf1c67ded52e134108fc8b3646f6549313868ce3e68a7117815cc0c2107ef1a986430a12ba002" - } - }; - var response = - await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, - expectedStatusCode: HttpStatusCode.Forbidden); - - response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - - //invalid signature - var transaction = await GenerateViewTransaction( - nameof(TokenContractContainer.TokenContractStub.GetTokenInfo), - new GetTokenInfoInput - { - Symbol = "ELF" - }); - transaction.Signature = ByteString.CopyFromUtf8("invalid"); + "rawTransaction", + "0a200a1e4604ccbdaa377fd7022b56436b99309e8b71cc5d78e909d271dbd1aeee6412200a1eaaa58b6cf58d4ef337f6dc55b701fd57d622015a3548a91a4e40892aa355180b220436957f93320c476574546f6b656e496e666f3a060a04454c46324a416246d781d80759d8ae6bb895b17203a3c9d4e89f083d7d89d9b6cbbf1c67ded52e134108fc8b3646f6549313868ce3e68a7117815cc0c2107ef1a986430a12ba002" + } + }; + var response = + await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, + expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - parameters = new Dictionary + //invalid signature + var transaction = await GenerateViewTransaction( + nameof(TokenContractContainer.TokenContractStub.GetTokenInfo), + new GetTokenInfoInput { - { - "rawTransaction", transaction.ToByteArray().ToHex() - } - }; - response = - await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); - } + Symbol = "ELF" + }); + transaction.Signature = ByteString.CopyFromUtf8("invalid"); - [Fact] - public async Task ExecuteRawTransaction_Success_Test() + parameters = new Dictionary { - const string methodName = "GetBalance"; - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var chain = await _blockchainService.GetChainAsync(); - var accountAddress = await _accountService.GetAccountAsync(); - var toAddress = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", chain.BestChainHeight.ToString()}, - {"RefBlockHash", chain.BestChainHash.ToHex()}, - {"MethodName", methodName}, - {"Params", "{\"owner\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\"}"} - }; - var createTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", - parameters); - var transactionId = - HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(createTransactionResponse.RawTransaction)); - - var signature = await _accountService.SignAsync(transactionId.ToByteArray()); - parameters = new Dictionary { - {"RawTransaction", createTransactionResponse.RawTransaction}, - {"Signature", signature.ToHex()} - }; - var sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", - parameters); - var output = new GetBalanceOutput - { - Owner = accountAddress, - Symbol = "ELF", - Balance = _osTestHelper.TokenTotalSupply - _osTestHelper.MockChainTokenAmount - }; - sendTransactionResponse.ShouldBe(output.ToString()); - } + "rawTransaction", transaction.ToByteArray().ToHex() + } + }; + response = + await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); + } - [Fact] - public async Task ExecuteRawTransaction_Failed_Test() + [Fact] + public async Task ExecuteRawTransaction_Success_Test() + { + const string methodName = "GetBalance"; + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var chain = await _blockchainService.GetChainAsync(); + var accountAddress = await _accountService.GetAccountAsync(); + var toAddress = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var parameters = new Dictionary { - var parameters = new Dictionary - { - {"RawTransaction", "wrongTransaction"} - }; - var wrongTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - wrongTransactionResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - wrongTransactionResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - - const string methodName = "GetBalance"; - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var chain = await _blockchainService.GetChainAsync(); - var accountAddress = await _accountService.GetAccountAsync(); - var toAddress = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", chain.BestChainHeight.ToString()}, - {"RefBlockHash", chain.BestChainHash.ToHex()}, - {"MethodName", methodName}, - {"Params", "{\"owner\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\"}"} - }; - var createTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", - parameters); - var wrongSignature = ByteString.CopyFromUtf8("wrongSignature").ToByteArray().ToHex(); - parameters = new Dictionary - { - {"RawTransaction", createTransactionResponse.RawTransaction}, - {"Signature", wrongSignature} - }; - var wrongSignatureResponse = - await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - wrongSignatureResponse.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); - wrongSignatureResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); - } + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", chain.BestChainHeight.ToString() }, + { "RefBlockHash", chain.BestChainHash.ToHex() }, + { "MethodName", methodName }, + { "Params", "{\"owner\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\"}" } + }; + var createTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", + parameters); + var transactionId = + HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(createTransactionResponse.RawTransaction)); + + var signature = await _accountService.SignAsync(transactionId.ToByteArray()); + parameters = new Dictionary + { + { "RawTransaction", createTransactionResponse.RawTransaction }, + { "Signature", signature.ToHex() } + }; + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", + parameters); + var output = new GetBalanceOutput + { + Owner = accountAddress, + Symbol = "ELF", + Balance = _osTestHelper.TokenTotalSupply - _osTestHelper.MockChainTokenAmount + }; + sendTransactionResponse.ShouldBe(output.ToString()); + } - [Fact] - public async Task Send_Transaction_Success_Test() + [Fact] + public async Task ExecuteRawTransaction_Failed_Test() + { + var parameters = new Dictionary { - // Generate a transaction - var transaction = await _osTestHelper.GenerateTransferTransaction(); - var transactionId = transaction.GetHash(); + { "RawTransaction", "wrongTransaction" } + }; + var wrongTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + wrongTransactionResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + wrongTransactionResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + + const string methodName = "GetBalance"; + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var chain = await _blockchainService.GetChainAsync(); + var accountAddress = await _accountService.GetAccountAsync(); + var toAddress = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + parameters = new Dictionary + { + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", chain.BestChainHeight.ToString() }, + { "RefBlockHash", chain.BestChainHash.ToHex() }, + { "MethodName", methodName }, + { "Params", "{\"owner\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\"}" } + }; + var createTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", + parameters); + var wrongSignature = ByteString.CopyFromUtf8("wrongSignature").ToByteArray().ToHex(); + parameters = new Dictionary + { + { "RawTransaction", createTransactionResponse.RawTransaction }, + { "Signature", wrongSignature } + }; + var wrongSignatureResponse = + await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + wrongSignatureResponse.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); + wrongSignatureResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); + } - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; + [Fact] + public async Task Send_Transaction_Success_Test() + { + // Generate a transaction + var transaction = await _osTestHelper.GenerateTransferTransaction(); + var transactionId = transaction.GetHash(); - var sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters); + var parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; - sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); - var chain = await _blockchainService.GetChainAsync(); - var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); - existTransaction.Transactions[0].GetHash().ShouldBe(transactionId); - } + sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); - [Fact] - public async Task Send_Transaction_ReturnInvalidTransaction_Test() - { - var fakeTransaction = "FakeTransaction"; - var parameters = new Dictionary - { - {"rawTransaction", fakeTransaction} - }; - var response = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - - response.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - - var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; - response = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - - response.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - } + var chain = await _blockchainService.GetChainAsync(); + var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); + existTransaction.Transactions[0].GetHash().ShouldBe(transactionId); + } - [Fact] - public async Task Send_Transaction_ReturnNoMatchMethodInContractAddress_Test() + [Fact] + public async Task Send_Transaction_ReturnInvalidTransaction_Test() + { + var fakeTransaction = "FakeTransaction"; + var parameters = new Dictionary { - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"InvalidMethod\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; - var response = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - - response.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); - } + { "rawTransaction", fakeTransaction } + }; + var response = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + + var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + response = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + } - [Fact] - public async Task Send_Transaction_ReturnInvalidParams_Test() + [Fact] + public async Task Send_Transaction_ReturnNoMatchMethodInContractAddress_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"InvalidMethod\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + var parameters = new Dictionary { - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var transactionParams = TransferInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); - - var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + - Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; - var response = - await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - - response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - } + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + var response = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); + } - [Fact] - public async Task Send_UnableVerify_Transaction_ReturnInvalidTransaction_Test() + [Fact] + public async Task Send_Transaction_ReturnInvalidParams_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var transactionParams = TransferInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); + + var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + + Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + var parameters = new Dictionary { - // Generate unsigned transaction - var transaction = await _osTestHelper.GenerateTransferTransaction(); - transaction.Signature = ByteString.CopyFrom(new byte[0]); + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + var response = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + } - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; - var response = await PostResponseAsObjectAsync( - "/api/blockChain/sendTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); + [Fact] + public async Task Send_UnableVerify_Transaction_ReturnInvalidTransaction_Test() + { + // Generate unsigned transaction + var transaction = await _osTestHelper.GenerateTransferTransaction(); + transaction.Signature = ByteString.CopyFrom(); - response.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); + var parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + var response = await PostResponseAsObjectAsync( + "/api/blockChain/sendTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - var existTransaction = await _txHub.GetQueuedTransactionAsync(transaction.GetHash()); - existTransaction.ShouldBeNull(); - } + response.Error.Code.ShouldBe(Error.InvalidSignature.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidSignature]); - [Fact] - public async Task Send_Transactions_Success_Test() - { - // Generate two transactions - var transaction1 = await _osTestHelper.GenerateTransferTransaction(); - var transaction2 = await _osTestHelper.GenerateTransferTransaction(); - var transactions = new List {transaction1, transaction2}; - var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); + var existTransaction = await _txHub.GetQueuedTransactionAsync(transaction.GetHash()); + existTransaction.ShouldBeNull(); + } - var parameters = new Dictionary - { - {"rawTransactions", rawTransactions} - }; - var sendTransactionsResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", parameters); - var responseTransactionIds = sendTransactionsResponse.ToList(); - - responseTransactionIds.Count.ShouldBe(2); - - var chain = await _blockchainService.GetChainAsync(); - var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); - existTransaction.Transactions.Select(x => x.GetHash().ToHex()).ShouldContain(responseTransactionIds[0]); - existTransaction.Transactions.Select(x => x.GetHash().ToHex()).ShouldContain(responseTransactionIds[1]); - - var getTransactionPoolStatusResponse = - await GetResponseAsObjectAsync("/api/blockChain/transactionPoolStatus"); - getTransactionPoolStatusResponse.Queued.ShouldBe(2); - } + [Fact] + public async Task Send_Transactions_Success_Test() + { + // Generate two transactions + var transaction1 = await _osTestHelper.GenerateTransferTransaction(); + var transaction2 = await _osTestHelper.GenerateTransferTransaction(); + var transactions = new List { transaction1, transaction2 }; + var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); - [Fact] - public async Task Send_Transactions_ReturnInvalidTransaction_Test() + var parameters = new Dictionary { - var transaction1 = await _osTestHelper.GenerateTransferTransaction(); - var transaction2 = await _osTestHelper.GenerateTransferTransaction(); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - - var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction3 = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); - transaction3.Signature = ByteString.CopyFrom(signature); - var transactions = new List {transaction1, transaction2, transaction3}; - var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); - - var parameters = new Dictionary - { - {"rawTransactions", rawTransactions} - }; - var sendTransactionsResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - sendTransactionsResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - } + { "rawTransactions", rawTransactions } + }; + var sendTransactionsResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", parameters); + var responseTransactionIds = sendTransactionsResponse.ToList(); + + responseTransactionIds.Count.ShouldBe(2); + + var chain = await _blockchainService.GetChainAsync(); + var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); + existTransaction.Transactions.Select(x => x.GetHash().ToHex()).ShouldContain(responseTransactionIds[0]); + existTransaction.Transactions.Select(x => x.GetHash().ToHex()).ShouldContain(responseTransactionIds[1]); + + var getTransactionPoolStatusResponse = + await GetResponseAsObjectAsync("/api/blockChain/transactionPoolStatus"); + getTransactionPoolStatusResponse.Queued.ShouldBe(2); + } - [Fact] - public async Task Send_Transactions_ReturnNoMatchMethodInContractAddress_Test() + [Fact] + public async Task Send_Transactions_ReturnInvalidTransaction_Test() + { + var transaction1 = await _osTestHelper.GenerateTransferTransaction(); + var transaction2 = await _osTestHelper.GenerateTransferTransaction(); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + + var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction3 = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); + transaction3.Signature = ByteString.CopyFrom(signature); + var transactions = new List { transaction1, transaction2, transaction3 }; + var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); + + var parameters = new Dictionary { - var transaction1 = await _osTestHelper.GenerateTransferTransaction(); - var transaction2 = await _osTestHelper.GenerateTransferTransaction(); - - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"InvalidMethod\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction3 = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); - transaction3.Signature = ByteString.CopyFrom(signature); - var transactions = new List {transaction1, transaction2, transaction3}; - var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); - - var parameters = new Dictionary - { - {"rawTransactions", rawTransactions} - }; - var sendTransactionsResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - sendTransactionsResponse.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); - sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); - } + { "rawTransactions", rawTransactions } + }; + var sendTransactionsResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + sendTransactionsResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + } - [Fact] - public async Task Send_Transactions_ReturnInvalidParams_Test() + [Fact] + public async Task Send_Transactions_ReturnNoMatchMethodInContractAddress_Test() + { + var transaction1 = await _osTestHelper.GenerateTransferTransaction(); + var transaction2 = await _osTestHelper.GenerateTransferTransaction(); + + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"InvalidMethod\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction3 = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); + transaction3.Signature = ByteString.CopyFrom(signature); + var transactions = new List { transaction1, transaction2, transaction3 }; + var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); + + var parameters = new Dictionary { - var transaction1 = await _osTestHelper.GenerateTransferTransaction(); - var transaction2 = await _osTestHelper.GenerateTransferTransaction(); - - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var transactionParams = TransferInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); - - var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + - Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; - var transaction3 = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); - transaction3.Signature = ByteString.CopyFrom(signature); - var transactions = new List {transaction1, transaction2, transaction3}; - var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); - - var parameters = new Dictionary - { - {"rawTransactions", rawTransactions} - }; - var sendTransactionsResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - sendTransactionsResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - } + { "rawTransactions", rawTransactions } + }; + var sendTransactionsResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + sendTransactionsResponse.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); + sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); + } - [Fact] - public async Task Get_TransactionResult_Success_Test() + [Fact] + public async Task Send_Transactions_ReturnInvalidParams_Test() + { + var transaction1 = await _osTestHelper.GenerateTransferTransaction(); + var transaction2 = await _osTestHelper.GenerateTransferTransaction(); + + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var transactionParams = TransferInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); + + var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + + Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; + var transaction3 = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction3.GetHash().ToByteArray()); + transaction3.Signature = ByteString.CopyFrom(signature); + var transactions = new List { transaction1, transaction2, transaction3 }; + var rawTransactions = string.Join(',', transactions.Select(t => t.ToByteArray().ToHex())); + + var parameters = new Dictionary { - // Generate a transaction and broadcast - var transaction = await _osTestHelper.GenerateTransferTransaction(); - var transactionHex = transaction.GetHash().ToHex(); - await _osTestHelper.BroadcastTransactions(new List {transaction}); + { "rawTransactions", rawTransactions } + }; + var sendTransactionsResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransactions", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + sendTransactionsResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + sendTransactionsResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + } - // Before mined - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionHex}"); + [Fact] + public async Task Get_TransactionResult_Success_Test() + { + // Generate a transaction and broadcast + var transaction = await _osTestHelper.GenerateTransferTransaction(); + var transactionHex = transaction.GetHash().ToHex(); + await _osTestHelper.BroadcastTransactions(new List { transaction }); - response.TransactionId.ShouldBe(transactionHex); - response.Status.ShouldBe(TransactionResultStatus.Pending.ToString().ToUpper()); + // Before mined + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - var block = await _osTestHelper.MinedOneBlock(); + response.TransactionId.ShouldBe(transactionHex); + response.Status.ShouldBe(TransactionResultStatus.Pending.ToString().ToUpper()); - // After mined - response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionHex}"); + var block = await _osTestHelper.MinedOneBlock(); - response.TransactionId.ShouldBe(transactionHex); - response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); - response.TransactionSize.ShouldBe(transaction.CalculateSize()); - response.BlockNumber.ShouldBe(block.Height); - response.BlockHash.ShouldBe(block.GetHash().ToHex()); - } + // After mined + response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - [Fact] - public async Task Get_Failed_TransactionResult_Success_Test() - { - // Generate a transaction and broadcast - var transactionList = await GenerateTwoInitializeTransaction(); - await _osTestHelper.BroadcastTransactions(transactionList); + response.TransactionId.ShouldBe(transactionHex); + response.Status.ShouldBe(TransactionResultStatus.Mined.ToString().ToUpper()); + response.TransactionSize.ShouldBe(transaction.CalculateSize()); + response.BlockNumber.ShouldBe(block.Height); + response.BlockHash.ShouldBe(block.GetHash().ToHex()); + } - var block = await _osTestHelper.MinedOneBlock(); - var txResult = await _osTestHelper.GetTransactionResultsAsync(transactionList[0].GetHash()); + [Fact] + public async Task Get_Failed_TransactionResult_Success_Test() + { + // Generate a transaction and broadcast + var transactionList = await GenerateTwoInitializeTransaction(); + await _osTestHelper.BroadcastTransactions(transactionList); - // After executed - var transactionHex = transactionList[1].GetHash().ToHex(); - { - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - - response.TransactionId.ShouldBe(transactionHex); - response.BlockNumber.ShouldBe(block.Height); - response.BlockHash.ShouldBe(block.Header.GetHash().ToHex()); - response.Status.ShouldBe(TransactionResultStatus.Failed.ToString().ToUpper()); - var errorInResponse = response.Error; - errorInResponse.ShouldBe(TransactionErrorResolver.TakeErrorMessage(txResult.Error, false)); - } + var block = await _osTestHelper.MinedOneBlock(); + var txResult = await _osTestHelper.GetTransactionResultsAsync(transactionList[0].GetHash()); - var optionMonitor = GetRequiredService>(); - optionMonitor.CurrentValue.IsDebugMode = true; - - { - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - - response.TransactionId.ShouldBe(transactionHex); - response.BlockNumber.ShouldBe(block.Height); - response.BlockHash.ShouldBe(block.Header.GetHash().ToHex()); - response.Status.ShouldBe(TransactionResultStatus.Failed.ToString().ToUpper()); - var errorInResponse = response.Error; - errorInResponse.ShouldBe(TransactionErrorResolver.TakeErrorMessage(txResult.Error, true)); - } - } - - [Fact] - public async Task Get_NotExisted_TransactionResult_Test() + // After executed + var transactionHex = transactionList[1].GetHash().ToHex(); { - // Generate a transaction - var transaction = await _osTestHelper.GenerateTransferTransaction(); - var transactionHex = transaction.GetHash().ToHex(); - var response = await GetResponseAsObjectAsync( $"/api/blockChain/transactionResult?transactionId={transactionHex}"); response.TransactionId.ShouldBe(transactionHex); - response.Status.ShouldBe(TransactionResultStatus.NotExisted.ToString().ToUpper()); - response.Bloom.ShouldBeNull(); - - _transactionResultStatusCacheProvider.AddTransactionResultStatus(transaction.GetHash()); - response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - response.TransactionId.ShouldBe(transactionHex); - response.Status.ShouldBe(TransactionResultStatus.NotExisted.ToString().ToUpper()); - response.Error.ShouldBeNull(); - response.Bloom.ShouldBeNull(); + response.BlockNumber.ShouldBe(block.Height); + response.BlockHash.ShouldBe(block.Header.GetHash().ToHex()); + response.Status.ShouldBe(TransactionResultStatus.Failed.ToString().ToUpper()); + var errorInResponse = response.Error; + errorInResponse.ShouldBe(TransactionErrorResolver.TakeErrorMessage(txResult.Error, false)); } - [Fact] - public async Task Get_TransactionResult_ReturnInvalidTransactionId_Test() + var optionMonitor = GetRequiredService>(); + optionMonitor.CurrentValue.IsDebugMode = true; + { - var fakeTransactionId = "FakeTransactionId"; - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={fakeTransactionId}", - expectedStatusCode: HttpStatusCode.Forbidden); + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionHex}"); - response.Error.Code.ShouldBe(Error.InvalidTransactionId.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransactionId]); + response.TransactionId.ShouldBe(transactionHex); + response.BlockNumber.ShouldBe(block.Height); + response.BlockHash.ShouldBe(block.Header.GetHash().ToHex()); + response.Status.ShouldBe(TransactionResultStatus.Failed.ToString().ToUpper()); + var errorInResponse = response.Error; + errorInResponse.ShouldBe(TransactionErrorResolver.TakeErrorMessage(txResult.Error, true)); } + } - [Fact] - public async Task Get_TransactionResults_Success_Test() - { - // Generate 20 transactions and mined - var transactions = new List(); - for (int i = 0; i < 20; i++) - { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - } - - await _osTestHelper.BroadcastTransactions(transactions); - var block = await _osTestHelper.MinedOneBlock(); + [Fact] + public async Task Get_NotExisted_TransactionResult_Test() + { + // Generate a transaction + var transaction = await _osTestHelper.GenerateTransferTransaction(); + var transactionHex = transaction.GetHash().ToHex(); + + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionHex}"); + + response.TransactionId.ShouldBe(transactionHex); + response.Status.ShouldBe(TransactionResultStatus.NotExisted.ToString().ToUpper()); + response.Bloom.ShouldBeNull(); + + _transactionResultStatusCacheProvider.AddTransactionResultStatus(transaction.GetHash()); + response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionHex}"); + response.TransactionId.ShouldBe(transactionHex); + response.Status.ShouldBe(TransactionResultStatus.NotExisted.ToString().ToUpper()); + response.Error.ShouldBeNull(); + response.Bloom.ShouldBeNull(); + } - var response = await GetResponseAsObjectAsync>( - $"/api/blockChain/transactionResults?blockHash={block.GetHash().ToHex()}&offset=0&limit=15"); + [Fact] + public async Task Get_TransactionResult_ReturnInvalidTransactionId_Test() + { + var fakeTransactionId = "FakeTransactionId"; + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={fakeTransactionId}", + expectedStatusCode: HttpStatusCode.Forbidden); - response.Count.ShouldBe(15); - foreach (var transactionResultDto in response) - { - transactionResultDto.TransactionSize.ShouldBe(transactions - .Single(t => t.GetHash() == Hash.LoadFromHex(transactionResultDto.TransactionId)).CalculateSize()); - } + response.Error.Code.ShouldBe(Error.InvalidTransactionId.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidTransactionId]); + } - response = await GetResponseAsObjectAsync>( - $"/api/blockChain/transactionResults?blockHash={block.GetHash().ToHex()}&offset=15&limit=15"); + [Fact] + public async Task Get_TransactionResults_Success_Test() + { + // Generate 20 transactions and mined + var transactions = new List(); + for (var i = 0; i < 20; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - response.Count.ShouldBe(5); - foreach (var transactionResultDto in response) - { - transactionResultDto.TransactionSize.ShouldBe(transactions - .Single(t => t.GetHash() == Hash.LoadFromHex(transactionResultDto.TransactionId)).CalculateSize()); - } - } + await _osTestHelper.BroadcastTransactions(transactions); + var block = await _osTestHelper.MinedOneBlock(); - [Fact] - public async Task Get_NotExisted_TransactionResults_Test() - { - var block = _osTestHelper.GenerateBlock(Hash.Empty, 10); - var blockHash = block.GetHash().ToHex(); - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=10", - expectedStatusCode: HttpStatusCode.Forbidden); + var response = await GetResponseAsObjectAsync>( + $"/api/blockChain/transactionResults?blockHash={block.GetHash().ToHex()}&offset=0&limit=15"); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); - } + response.Count.ShouldBe(15); + foreach (var transactionResultDto in response) + transactionResultDto.TransactionSize.ShouldBe(transactions + .Single(t => t.GetHash() == Hash.LoadFromHex(transactionResultDto.TransactionId)).CalculateSize()); - [Fact] - public async Task Get_TransactionResults_With_InvalidParameter_Test() - { - var block = _osTestHelper.GenerateBlock(Hash.Empty, 10); - var blockHash = block.GetHash().ToHex(); + response = await GetResponseAsObjectAsync>( + $"/api/blockChain/transactionResults?blockHash={block.GetHash().ToHex()}&offset=15&limit=15"); - var response1 = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=-3&limit=10", - expectedStatusCode: HttpStatusCode.Forbidden); + response.Count.ShouldBe(5); + foreach (var transactionResultDto in response) + transactionResultDto.TransactionSize.ShouldBe(transactions + .Single(t => t.GetHash() == Hash.LoadFromHex(transactionResultDto.TransactionId)).CalculateSize()); + } - response1.Error.Code.ShouldBe(Error.InvalidOffset.ToString()); - response1.Error.Message.Contains("Offset must greater than or equal to 0").ShouldBeTrue(); + [Fact] + public async Task Get_NotExisted_TransactionResults_Test() + { + var block = _osTestHelper.GenerateBlock(Hash.Empty, 10); + var blockHash = block.GetHash().ToHex(); + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=10", + expectedStatusCode: HttpStatusCode.Forbidden); + + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + } - var response2 = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=-5", - expectedStatusCode: HttpStatusCode.Forbidden); - response2.Error.Code.ShouldBe(Error.InvalidLimit.ToString()); - response2.Error.Message.Contains("Limit must between 0 and 100").ShouldBeTrue(); + [Fact] + public async Task Get_TransactionResults_With_InvalidParameter_Test() + { + var block = _osTestHelper.GenerateBlock(Hash.Empty, 10); + var blockHash = block.GetHash().ToHex(); + + var response1 = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=-3&limit=10", + expectedStatusCode: HttpStatusCode.Forbidden); + + response1.Error.Code.ShouldBe(Error.InvalidOffset.ToString()); + response1.Error.Message.Contains("Offset must greater than or equal to 0").ShouldBeTrue(); + + var response2 = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=-5", + expectedStatusCode: HttpStatusCode.Forbidden); + response2.Error.Code.ShouldBe(Error.InvalidLimit.ToString()); + response2.Error.Message.Contains("Limit must between 0 and 100").ShouldBeTrue(); + + var response3 = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=120", + expectedStatusCode: HttpStatusCode.Forbidden); + response3.Error.Code.ShouldBe(Error.InvalidLimit.ToString()); + response3.Error.Message.Contains("Limit must between 0 and 100").ShouldBeTrue(); + + var response4 = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResults?blockHash={blockHash.Substring(2)}&offset=0&limit=20", + expectedStatusCode: HttpStatusCode.Forbidden); + response4.Error.Code.ShouldBe(Error.InvalidBlockHash.ToString()); + } - var response3 = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResults?blockHash={blockHash}&offset=0&limit=120", - expectedStatusCode: HttpStatusCode.Forbidden); - response3.Error.Code.ShouldBe(Error.InvalidLimit.ToString()); - response3.Error.Message.Contains("Limit must between 0 and 100").ShouldBeTrue(); - - var response4 = await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResults?blockHash={blockHash.Substring(2)}&offset=0&limit=20", - expectedStatusCode: HttpStatusCode.Forbidden); - response4.Error.Code.ShouldBe(Error.InvalidBlockHash.ToString()); - } + [Fact] + public async Task Get_Block_By_BlockHeight_Success_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - [Fact] - public async Task Get_Block_By_BlockHeight_Success_Test() - { - var chain = await _blockchainService.GetChainAsync(); - var transactions = new List(); - for (int i = 0; i < 3; i++) - { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - } + await _osTestHelper.BroadcastTransactions(transactions); + var block = await _osTestHelper.MinedOneBlock(); - await _osTestHelper.BroadcastTransactions(transactions); - var block = await _osTestHelper.MinedOneBlock(); - - var response = - await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=true"); - - response.BlockHash.ShouldBe(block.GetHash().ToHex()); - response.Header.PreviousBlockHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); - response.Header.MerkleTreeRootOfTransactions.ShouldBe(block.Header.MerkleTreeRootOfTransactions.ToHex()); - response.Header.MerkleTreeRootOfWorldState.ShouldBe(block.Header.MerkleTreeRootOfWorldState.ToHex()); - response.Header.Height.ShouldBe(block.Height); - response.Header.Time.ShouldBe(block.Header.Time.ToDateTime()); - response.Header.ChainId.ShouldBe(ChainHelper.ConvertChainIdToBase58(chain.Id)); - response.Header.Bloom.ShouldBe(block.Header.Bloom.ToBase64()); - response.Header.Extra.ShouldBe(block.Header.ExtraData?.ToString()); - response.Header.MerkleTreeRootOfTransactionState.ShouldBe(block.Header.MerkleTreeRootOfTransactionStatus.ToHex()); - response.Header.SignerPubkey.ShouldBe(block.Header.SignerPubkey.ToHex()); - response.Body.TransactionsCount.ShouldBe(3); - response.BlockSize.ShouldBe(block.CalculateSize()); - - var responseTransactions = response.Body.Transactions; - responseTransactions.Count.ShouldBe(3); - - response = - await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=12"); - response.Body.TransactionsCount.ShouldBe(3); - response.Body.Transactions.Count.ShouldBe(0); - } + var response = + await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=true"); - [Fact] - public async Task Get_Block_By_BlockHash_Success_Test() - { - var chain = await _blockchainService.GetChainAsync(); - var transactions = new List(); - for (int i = 0; i < 3; i++) - { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - } + response.BlockHash.ShouldBe(block.GetHash().ToHex()); + response.Header.PreviousBlockHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); + response.Header.MerkleTreeRootOfTransactions.ShouldBe(block.Header.MerkleTreeRootOfTransactions.ToHex()); + response.Header.MerkleTreeRootOfWorldState.ShouldBe(block.Header.MerkleTreeRootOfWorldState.ToHex()); + response.Header.Height.ShouldBe(block.Height); + response.Header.Time.ShouldBe(block.Header.Time.ToDateTime()); + response.Header.ChainId.ShouldBe(ChainHelper.ConvertChainIdToBase58(chain.Id)); + response.Header.Bloom.ShouldBe(block.Header.Bloom.ToBase64()); + response.Header.Extra.ShouldBe(block.Header.ExtraData?.ToString()); + response.Header.MerkleTreeRootOfTransactionState.ShouldBe( + block.Header.MerkleTreeRootOfTransactionStatus.ToHex()); + response.Header.SignerPubkey.ShouldBe(block.Header.SignerPubkey.ToHex()); + response.Body.TransactionsCount.ShouldBe(3); + response.BlockSize.ShouldBe(block.CalculateSize()); + + var responseTransactions = response.Body.Transactions; + responseTransactions.Count.ShouldBe(3); + + response = + await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=12"); + response.Body.TransactionsCount.ShouldBe(3); + response.Body.Transactions.Count.ShouldBe(0); + } - await _osTestHelper.BroadcastTransactions(transactions); - var block = await _osTestHelper.MinedOneBlock(); - - var response = - await GetResponseAsObjectAsync( - $"/api/blockChain/block?blockHash={block.GetHash().ToHex()}&includeTransactions=true"); - - response.BlockHash.ShouldBe(block.GetHash().ToHex()); - response.Header.PreviousBlockHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); - response.Header.MerkleTreeRootOfTransactions.ShouldBe(block.Header.MerkleTreeRootOfTransactions.ToHex()); - response.Header.MerkleTreeRootOfWorldState.ShouldBe(block.Header.MerkleTreeRootOfWorldState.ToHex()); - response.Header.Height.ShouldBe(block.Height); - response.Header.Time.ShouldBe(block.Header.Time.ToDateTime()); - response.Header.ChainId.ShouldBe(ChainHelper.ConvertChainIdToBase58(chain.Id)); - response.Header.Bloom.ShouldBe(block.Header.Bloom.ToBase64()); - response.Header.SignerPubkey.ShouldBe(block.Header.SignerPubkey.ToByteArray().ToHex()); - response.Header.Extra.ShouldBe(block.Header.ExtraData?.ToString()); - response.Header.MerkleTreeRootOfTransactionState.ShouldBe(block.Header.MerkleTreeRootOfTransactionStatus.ToHex()); - response.Body.TransactionsCount.ShouldBe(3); - response.BlockSize.ShouldBe(block.CalculateSize()); - - var responseTransactions = response.Body.Transactions; - responseTransactions.Count.ShouldBe(3); - - response = - await GetResponseAsObjectAsync( - $"/api/blockChain/block?blockHash={block.GetHash().ToHex()}"); - response.Body.TransactionsCount.ShouldBe(3); - response.Body.Transactions.Count.ShouldBe(0); - } + [Fact] + public async Task Get_Block_By_BlockHash_Success_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); + + await _osTestHelper.BroadcastTransactions(transactions); + var block = await _osTestHelper.MinedOneBlock(); + + var response = + await GetResponseAsObjectAsync( + $"/api/blockChain/block?blockHash={block.GetHash().ToHex()}&includeTransactions=true"); + + response.BlockHash.ShouldBe(block.GetHash().ToHex()); + response.Header.PreviousBlockHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); + response.Header.MerkleTreeRootOfTransactions.ShouldBe(block.Header.MerkleTreeRootOfTransactions.ToHex()); + response.Header.MerkleTreeRootOfWorldState.ShouldBe(block.Header.MerkleTreeRootOfWorldState.ToHex()); + response.Header.Height.ShouldBe(block.Height); + response.Header.Time.ShouldBe(block.Header.Time.ToDateTime()); + response.Header.ChainId.ShouldBe(ChainHelper.ConvertChainIdToBase58(chain.Id)); + response.Header.Bloom.ShouldBe(block.Header.Bloom.ToBase64()); + response.Header.SignerPubkey.ShouldBe(block.Header.SignerPubkey.ToByteArray().ToHex()); + response.Header.Extra.ShouldBe(block.Header.ExtraData?.ToString()); + response.Header.MerkleTreeRootOfTransactionState.ShouldBe( + block.Header.MerkleTreeRootOfTransactionStatus.ToHex()); + response.Body.TransactionsCount.ShouldBe(3); + response.BlockSize.ShouldBe(block.CalculateSize()); + + var responseTransactions = response.Body.Transactions; + responseTransactions.Count.ShouldBe(3); + + response = + await GetResponseAsObjectAsync( + $"/api/blockChain/block?blockHash={block.GetHash().ToHex()}"); + response.Body.TransactionsCount.ShouldBe(3); + response.Body.Transactions.Count.ShouldBe(0); + } - [Fact] - public async Task Get_Block_ReturnNotFound_Test() - { - var response = await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=0", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + [Fact] + public async Task Get_Block_ReturnNotFound_Test() + { + var response = await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=0", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + + response = await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=100", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + + response = await GetResponseAsObjectAsync( + $"/api/blockChain/block?blockHash={Hash.Empty.ToHex()}", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + + response = await GetResponseAsObjectAsync( + "/api/blockChain/block?blockHash=7526008f73d931f48a9246648f3147aacf5bd9b2c79f93a708a86f77baaed865", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + + //invalid block hash parameter + const string blockHash = "invalid-hash"; + response = await GetResponseAsObjectAsync( + $"/api/blockChain/block?blockHash={blockHash}", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.InvalidBlockHash.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidBlockHash]); + } - response = await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=100", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + [Fact] + public async Task Get_Chain_Status_Success_Test() + { + var chain = await _blockchainService.GetChainAsync(); + var basicContractZero = _smartContractAddressService.GetZeroSmartContractAddress(); + + var response = await GetResponseAsObjectAsync("/api/blockChain/chainStatus"); + response.Branches.ShouldNotBeNull(); + var responseChainId = ChainHelper.ConvertBase58ToChainId(response.ChainId); + responseChainId.ShouldBe(chain.Id); + response.GenesisContractAddress.ShouldBe(basicContractZero.ToBase58()); + response.BestChainHeight.ShouldBe(11); + response.BestChainHash.ShouldBe(chain.BestChainHash?.ToHex()); + response.LongestChainHeight = chain.LongestChainHeight; + response.LongestChainHash = chain.LongestChainHash?.ToHex(); + response.GenesisBlockHash = chain.GenesisBlockHash.ToHex(); + response.LastIrreversibleBlockHash = chain.LastIrreversibleBlockHash?.ToHex(); + response.LastIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight; + } - response = await GetResponseAsObjectAsync( - $"/api/blockChain/block?blockHash={Hash.Empty.ToHex()}", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + [Fact] + public async Task Get_Block_State_Success_Test() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - response = await GetResponseAsObjectAsync( - "/api/blockChain/block?blockHash=7526008f73d931f48a9246648f3147aacf5bd9b2c79f93a708a86f77baaed865", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + await _osTestHelper.BroadcastTransactions(transactions); + await _osTestHelper.MinedOneBlock(); - //invalid block hash parameter - const string blockHash = "invalid-hash"; - response = await GetResponseAsObjectAsync( - $"/api/blockChain/block?blockHash={blockHash}", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.InvalidBlockHash.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidBlockHash]); - } + var block = await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=true"); - [Fact] - public async Task Get_Chain_Status_Success_Test() - { - var chain = await _blockchainService.GetChainAsync(); - var basicContractZero = _smartContractAddressService.GetZeroSmartContractAddress(); - - var response = await GetResponseAsObjectAsync("/api/blockChain/chainStatus"); - response.Branches.ShouldNotBeNull(); - var responseChainId = ChainHelper.ConvertBase58ToChainId(response.ChainId); - responseChainId.ShouldBe(chain.Id); - response.GenesisContractAddress.ShouldBe(basicContractZero.ToBase58()); - response.BestChainHeight.ShouldBe(11); - response.BestChainHash.ShouldBe(chain.BestChainHash?.ToHex()); - response.LongestChainHeight = chain.LongestChainHeight; - response.LongestChainHash = chain.LongestChainHash?.ToHex(); - response.GenesisBlockHash = chain.GenesisBlockHash.ToHex(); - response.LastIrreversibleBlockHash = chain.LastIrreversibleBlockHash?.ToHex(); - response.LastIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight; - } - [Fact] - public async Task Get_Block_State_Success_Test() - { - var transactions = new List(); - for (int i = 0; i < 3; i++) - { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - } + var blockState = await GetResponseAsObjectAsync( + $"/api/blockChain/blockState?blockHash={block.BlockHash}"); + blockState.ShouldNotBeNull(); + blockState.BlockHash.ShouldBe(block.BlockHash); + blockState.BlockHeight.ShouldBe(12); + blockState.PreviousHash.ShouldBe(block.Header.PreviousBlockHash); + blockState.Changes.ShouldNotBeNull(); + } - await _osTestHelper.BroadcastTransactions(transactions); - await _osTestHelper.MinedOneBlock(); + [Fact] + public async Task Get_Block_State_FewBlocks_Later_Test() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); + + await _osTestHelper.BroadcastTransactions(transactions); + var block = await _osTestHelper.MinedOneBlock(); + + //Continue generate block + for (var i = 0; i < 10; i++) await _osTestHelper.MinedOneBlock(); + + //Check Block State + var blockState = await GetResponseAsObjectAsync( + $"/api/blockChain/blockState?blockHash={block.GetHash().ToHex()}"); + blockState.ShouldNotBeNull(); + blockState.BlockHash.ShouldBe(block.GetHash().ToHex()); + blockState.BlockHeight.ShouldBe(12); + blockState.PreviousHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); + blockState.Changes.ShouldNotBeNull(); + + var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); + await _blockchainStateService.MergeBlockStateAsync(blockStateSet.BlockHeight, + blockStateSet.BlockHash); + + var errorResponse = await GetResponseAsObjectAsync( + $"/api/blockChain/blockState?blockHash={block.GetHash().ToHex()}", + expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + } - var block = await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=true"); + [Fact] + public async Task Query_NonExist_Api_Failed_Test() + { + var getResponse = await GetResponseAsObjectAsync("/api/blockChain/TestMethod", + expectedStatusCode: HttpStatusCode.NotFound); + getResponse.ShouldBeNull(); + var postResponse = await PostResponseAsObjectAsync("/api/blockChain/TestMethod", + new Dictionary(), + expectedStatusCode: HttpStatusCode.NotFound); + postResponse.ShouldBeNull(); + var deleteResponse = await DeleteResponseAsObjectAsync("/api/blockChain/TestMethod", + expectedStatusCode: HttpStatusCode.NotFound); + deleteResponse.ShouldBeNull(); + } + [Fact] + public async Task Get_ContractFileDescriptorSet_Success_Test() + { + // Generate a transaction and broadcast + var transaction = await _osTestHelper.GenerateTransferTransaction(); + await _osTestHelper.BroadcastTransactions(new List { transaction }); + + await _osTestHelper.MinedOneBlock(); + + var response = await GetResponseAsStringAsync( + $"/api/blockChain/contractFileDescriptorSet?address={transaction.To.ToBase58()}"); + response.ShouldNotBeEmpty(); + var set = FileDescriptorSet.Parser.ParseFrom( + ByteString.FromBase64(response.Substring(1, response.Length - 2))); + set.ShouldNotBeNull(); + set.File.Count.ShouldBeGreaterThanOrEqualTo(1); + } - var blockState = await GetResponseAsObjectAsync( - $"/api/blockChain/blockState?blockHash={block.BlockHash}"); - blockState.ShouldNotBeNull(); - blockState.BlockHash.ShouldBe(block.BlockHash); - blockState.BlockHeight.ShouldBe(12); - blockState.PreviousHash.ShouldBe(block.Header.PreviousBlockHash); - blockState.Changes.ShouldNotBeNull(); - } + [Fact] + public async Task Get_ContractFileDescriptorSet_Failed_Test() + { + var addressInfo = SampleAddress.AddressList[0].ToBase58(); + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/contractFileDescriptorSet?address={addressInfo}", + expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NotFound.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + + addressInfo = "invalid address"; + var errorResponse = await GetResponseAsObjectAsync( + $"/api/blockChain/contractFileDescriptorSet?address={addressInfo}", + expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + } - [Fact] - public async Task Get_Block_State_FewBlocks_Later_Test() + [Fact] + public async Task CreateRawTransaction_Failed_Test() + { + var newUserKeyPair = CryptoHelper.GenerateKeyPair(); + var toAddressValue = + Base64.ToBase64String(Address.FromPublicKey(newUserKeyPair.PublicKey).Value.ToByteArray()); + var parameters = new Dictionary { - var transactions = new List(); - for (int i = 0; i < 3; i++) + { "From", "6WZNJgU5MHWsvzZmPpC7cW6g3qciniQhDKRLCvbQcTCcVF1" }, + { "To", "4rkKQpsRFt1nU6weAHuJ6CfQDqo6dxruU3K3wNUFr6ZwZY1" }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a4182" }, + { "MethodName", "Transfer" }, { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); + "Params", + "{\"to\":{ \"Value\": \"" + toAddressValue + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" } - - await _osTestHelper.BroadcastTransactions(transactions); - var block = await _osTestHelper.MinedOneBlock(); - - //Continue generate block - for (int i = 0; i < 10; i++) + }; + var response = + await PostResponseAsObjectAsync( + "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.BadRequest); + response.Error.ValidationErrors.Any(v => v.Message == Error.Message[Error.InvalidAddress]).ShouldBeTrue(); + response.Error.ValidationErrors.Any(v => v.Message == Error.Message[Error.InvalidBlockHash]).ShouldBeTrue(); + response.Error.ValidationErrors.First(v => v.Message == Error.Message[Error.InvalidBlockHash]).Members + .ShouldContain("refBlockHash"); + response.Error.ValidationErrors.Any(v => v.Members.Contains("to")).ShouldBeTrue(); + response.Error.ValidationErrors.Any(v => v.Members.Contains("from")).ShouldBeTrue(); + + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var accountAddress = await _accountService.GetAccountAsync(); + parameters = new Dictionary + { + { "From", contractAddress.ToBase58() }, + { "To", accountAddress.ToBase58() }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418" }, + { "MethodName", "Transfer" }, { - await _osTestHelper.MinedOneBlock(); + "Params", + "{\"to\":{ \"Value\": \"" + toAddressValue + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" } - - //Check Block State - var blockState = await GetResponseAsObjectAsync( - $"/api/blockChain/blockState?blockHash={block.GetHash().ToHex()}"); - blockState.ShouldNotBeNull(); - blockState.BlockHash.ShouldBe(block.GetHash().ToHex()); - blockState.BlockHeight.ShouldBe(12); - blockState.PreviousHash.ShouldBe(block.Header.PreviousBlockHash.ToHex()); - blockState.Changes.ShouldNotBeNull(); - - var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash()); - await _blockchainStateService.MergeBlockStateAsync(blockStateSet.BlockHeight, - blockStateSet.BlockHash); - - var errorResponse = await GetResponseAsObjectAsync( - $"/api/blockChain/blockState?blockHash={block.GetHash().ToHex()}", - expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); - } - - [Fact] - public async Task Query_NonExist_Api_Failed_Test() + }; + response = + await PostResponseAsObjectAsync( + "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.InvalidContractAddress.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidContractAddress]); + + parameters = new Dictionary { - var getResponse = await GetResponseAsObjectAsync("/api/blockChain/TestMethod", - expectedStatusCode: HttpStatusCode.NotFound); - getResponse.ShouldBeNull(); - var postResponse = await PostResponseAsObjectAsync("/api/blockChain/TestMethod", - new Dictionary(), - expectedStatusCode: HttpStatusCode.NotFound); - postResponse.ShouldBeNull(); - var deleteResponse = await DeleteResponseAsObjectAsync("/api/blockChain/TestMethod", - expectedStatusCode: HttpStatusCode.NotFound); - deleteResponse.ShouldBeNull(); - } - - [Fact] - public async Task Get_ContractFileDescriptorSet_Success_Test() + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418" }, + { "MethodName", "NoMethod" }, + { + "Params", + "{\"to\":{ \"Value\": \"" + toAddressValue + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" + } + }; + response = + await PostResponseAsObjectAsync( + "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); + + parameters = new Dictionary { - // Generate a transaction and broadcast - var transaction = await _osTestHelper.GenerateTransferTransaction(); - await _osTestHelper.BroadcastTransactions(new List {transaction}); + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418" }, + { "MethodName", "Transfer" }, + { "Params", "NoParams" } + }; + response = + await PostResponseAsObjectAsync( + "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + + parameters = new Dictionary + { + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418" }, + { "MethodName", "Transfer" }, + { + "Params", + "{\"to\":{ \"Value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" + } + }; + response = + await PostResponseAsObjectAsync( + "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); + response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + } - await _osTestHelper.MinedOneBlock(); + [Fact] + public async Task CreateRawTransaction_InvalidParams_Test() + { + const string methodName = "GetBalance"; + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var chain = await _blockchainService.GetChainAsync(); + var accountAddress = await _accountService.GetAccountAsync(); - var response = await GetResponseAsStringAsync( - $"/api/blockChain/contractFileDescriptorSet?address={transaction.To.ToBase58()}"); - response.ShouldNotBeEmpty(); - var set = FileDescriptorSet.Parser.ParseFrom( - ByteString.FromBase64(response.Substring(1, response.Length - 2))); - set.ShouldNotBeNull(); - set.File.Count.ShouldBeGreaterThanOrEqualTo(1); - } - [Fact] - public async Task Get_ContractFileDescriptorSet_Failed_Test() + var parameters = new Dictionary { - var addressInfo = SampleAddress.AddressList[0].ToBase58(); - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/contractFileDescriptorSet?address={addressInfo}", - expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NotFound.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NotFound]); - - addressInfo = "invalid address"; - var errorResponse = await GetResponseAsObjectAsync( - $"/api/blockChain/contractFileDescriptorSet?address={addressInfo}", - expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); - } + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", chain.BestChainHeight.ToString() }, + { "RefBlockHash", chain.BestChainHash.ToHex() }, + { "MethodName", methodName }, + { "Params", "{\"owner\":{ \"value\": \"" + "\" },\"symbol\":\"ELF\"}" } + }; + var createTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + createTransactionResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + createTransactionResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + } - [Fact] - public async Task CreateRawTransaction_Failed_Test() + [Fact] + public async Task CreateRawTransaction_Success_Test() + { + var transferToAddress = + Address.FromBase58("21oXyCxvUd7YUUkgbZxkbmu4EWs65yos6iVC39rPwPknune6qZ"); + var toAddress = Base64.ToBase64String(transferToAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + OutputHelper.WriteLine(contractAddress.ToString()); //2J9wWhuyz7Drkmtu9DTegM9rLmamjekmRkCAWz5YYPjm7akfbH + var fromAddressInBase58 = "juYfvugva4PZSEz1w9J8VkAhgrbevEmqTLSATwc9i1XHZJvE1"; + var refHashInHex = "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"; + var parameters = new Dictionary { - var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - var toAddressValue = - Base64.ToBase64String(Address.FromPublicKey(newUserKeyPair.PublicKey).Value.ToByteArray()); - var parameters = new Dictionary + { "From", fromAddressInBase58 }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", "2788" }, + { "RefBlockHash", refHashInHex }, + { "MethodName", "Transfer" }, { - {"From", "6WZNJgU5MHWsvzZmPpC7cW6g3qciniQhDKRLCvbQcTCcVF1"}, - {"To", "4rkKQpsRFt1nU6weAHuJ6CfQDqo6dxruU3K3wNUFr6ZwZY1"}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a4182"}, - {"MethodName", "Transfer"}, - { - "Params", - "{\"to\":{ \"Value\": \"" + toAddressValue + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - var response = - await PostResponseAsObjectAsync( - "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.BadRequest); - response.Error.ValidationErrors.Any(v => v.Message == Error.Message[Error.InvalidAddress]).ShouldBeTrue(); - response.Error.ValidationErrors.Any(v => v.Message == Error.Message[Error.InvalidBlockHash]).ShouldBeTrue(); - response.Error.ValidationErrors.First(v => v.Message == Error.Message[Error.InvalidBlockHash]).Members - .ShouldContain("refBlockHash"); - response.Error.ValidationErrors.Any(v => v.Members.Contains("to")).ShouldBeTrue(); - response.Error.ValidationErrors.Any(v => v.Members.Contains("from")).ShouldBeTrue(); - - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var accountAddress = await _accountService.GetAccountAsync(); - parameters = new Dictionary - { - {"From", contractAddress.ToBase58()}, - {"To", accountAddress.ToBase58()}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"}, - {"MethodName", "Transfer"}, - { - "Params", - "{\"to\":{ \"Value\": \"" + toAddressValue + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - response = - await PostResponseAsObjectAsync( - "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.InvalidContractAddress.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidContractAddress]); - - parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"}, - {"MethodName", "NoMethod"}, - { - "Params", - "{\"to\":{ \"Value\": \"" + toAddressValue + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - response = - await PostResponseAsObjectAsync( - "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); - - parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"}, - {"MethodName", "Transfer"}, - {"Params", "NoParams"} - }; - response = - await PostResponseAsObjectAsync( - "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - - parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"}, - {"MethodName", "Transfer"}, - { - "Params", - "{\"to\":{ \"Value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - response = - await PostResponseAsObjectAsync( - "/api/blockChain/rawTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - response.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - } + "Params", + "{\"to\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" + } + }; + var response = + await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", + parameters); + var tx = Transaction.Parser.ParseFrom(ByteArrayHelper.HexStringToByteArray(response.RawTransaction)); + tx.From.ShouldBe(Address.FromBase58(fromAddressInBase58)); + tx.To.ShouldBe(contractAddress); + tx.RefBlockNumber.ShouldBe(2788); + tx.RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(Hash.LoadFromHex(refHashInHex))); + tx.MethodName.ShouldBe("Transfer"); + var transferInput = TransferInput.Parser.ParseFrom(tx.Params); + transferInput.Amount.ShouldBe(100); + transferInput.Memo.ShouldBe("test"); + transferInput.Symbol.ShouldBe("ELF"); + transferInput.To.ShouldBe(transferToAddress); + } - [Fact] - public async Task CreateRawTransaction_InvalidParams_Test() + [Fact] + public async Task SendRawTransaction_Success_Test() + { + const string methodName = "Transfer"; + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var chain = await _blockchainService.GetChainAsync(); + var newUserKeyPair = CryptoHelper.GenerateKeyPair(); + var accountAddress = await _accountService.GetAccountAsync(); + var toAddress = Base64.ToBase64String(Address.FromPublicKey(newUserKeyPair.PublicKey).Value.ToByteArray()); + var parameters = new Dictionary { - const string methodName = "GetBalance"; - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var chain = await _blockchainService.GetChainAsync(); - var accountAddress = await _accountService.GetAccountAsync(); - - - var parameters = new Dictionary + { "From", accountAddress.ToBase58() }, + { "To", contractAddress.ToBase58() }, + { "RefBlockNumber", chain.BestChainHeight.ToString() }, + { "RefBlockHash", chain.BestChainHash.ToHex() }, + { "MethodName", methodName }, { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", chain.BestChainHeight.ToString()}, - {"RefBlockHash", chain.BestChainHash.ToHex()}, - {"MethodName", methodName}, - {"Params", "{\"owner\":{ \"value\": \"" + "\" },\"symbol\":\"ELF\"}"} - }; - var createTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", - parameters,expectedStatusCode: HttpStatusCode.Forbidden); - createTransactionResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - createTransactionResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + "Params", + "{\"to\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" } - [Fact] - public async Task CreateRawTransaction_Success_Test() + }; + var createTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", + parameters); + var transactionId = + HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(createTransactionResponse.RawTransaction)); + + var signature = await _accountService.SignAsync(transactionId.ToByteArray()); + parameters = new Dictionary { - var transferToAddress = - Address.FromBase58("21oXyCxvUd7YUUkgbZxkbmu4EWs65yos6iVC39rPwPknune6qZ"); - var toAddress = Base64.ToBase64String(transferToAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - OutputHelper.WriteLine(contractAddress.ToString()); //2J9wWhuyz7Drkmtu9DTegM9rLmamjekmRkCAWz5YYPjm7akfbH - var fromAddressInBase58 = "juYfvugva4PZSEz1w9J8VkAhgrbevEmqTLSATwc9i1XHZJvE1"; - var refHashInHex = "190db8baaad13e40900a6a5970915a1402d18f2b685e2183efdd954ba890a418"; - var parameters = new Dictionary - { - {"From", fromAddressInBase58}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", "2788"}, - {"RefBlockHash", refHashInHex}, - {"MethodName", "Transfer"}, - { - "Params", - "{\"to\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - var response = - await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", - parameters); - var tx = Transaction.Parser.ParseFrom(ByteArrayHelper.HexStringToByteArray(response.RawTransaction)); - tx.From.ShouldBe(Address.FromBase58(fromAddressInBase58)); - tx.To.ShouldBe(contractAddress); - tx.RefBlockNumber.ShouldBe(2788); - tx.RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(Hash.LoadFromHex(refHashInHex))); - tx.MethodName.ShouldBe("Transfer"); - var transferInput = TransferInput.Parser.ParseFrom(tx.Params); - transferInput.Amount.ShouldBe(100); - transferInput.Memo.ShouldBe("test"); - transferInput.Symbol.ShouldBe("ELF"); - transferInput.To.ShouldBe(transferToAddress); - } - - [Fact] - public async Task SendRawTransaction_Success_Test() - { - const string methodName = "Transfer"; - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var chain = await _blockchainService.GetChainAsync(); - var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - var accountAddress = await _accountService.GetAccountAsync(); - var toAddress = Base64.ToBase64String(Address.FromPublicKey(newUserKeyPair.PublicKey).Value.ToByteArray()); - var parameters = new Dictionary - { - {"From", accountAddress.ToBase58()}, - {"To", contractAddress.ToBase58()}, - {"RefBlockNumber", chain.BestChainHeight.ToString()}, - {"RefBlockHash", chain.BestChainHash.ToHex()}, - {"MethodName", methodName}, - { - "Params", - "{\"to\":{ \"value\": \"" + toAddress + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}" - } - }; - var createTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/rawTransaction", - parameters); - var transactionId = - HashHelper.ComputeFrom(ByteArrayHelper.HexStringToByteArray(createTransactionResponse.RawTransaction)); - - var signature = await _accountService.SignAsync(transactionId.ToByteArray()); - parameters = new Dictionary - { - {"Transaction", createTransactionResponse.RawTransaction}, - {"Signature", signature.ToHex()} - }; - var sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters); - - sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); - sendTransactionResponse.Transaction.ShouldBeNull(); + { "Transaction", createTransactionResponse.RawTransaction }, + { "Signature", signature.ToHex() } + }; + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters); - var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); - existTransaction.Transactions[0].GetHash().ToHex().ShouldBe(sendTransactionResponse.TransactionId); + sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); + sendTransactionResponse.Transaction.ShouldBeNull(); - parameters = new Dictionary - { - {"Transaction", createTransactionResponse.RawTransaction}, - {"Signature", signature.ToHex()}, - {"returnTransaction", "true"} - }; - sendTransactionResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters); - - sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); - sendTransactionResponse.Transaction.ShouldNotBeNull(); - sendTransactionResponse.Transaction.To.ShouldBe(contractAddress.ToBase58()); - sendTransactionResponse.Transaction.From.ShouldBe(accountAddress.ToBase58()); - sendTransactionResponse.Transaction.MethodName.ShouldBe(methodName); - sendTransactionResponse.Transaction.Params.ShouldBe( - "{ \"to\": \"" + Address.FromPublicKey(newUserKeyPair.PublicKey).ToBase58() + - "\", \"symbol\": \"ELF\", \"amount\": \"100\", \"memo\": \"test\" }"); - sendTransactionResponse.Transaction.RefBlockNumber.ShouldBe(chain.BestChainHeight); - sendTransactionResponse.Transaction.RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(chain.BestChainHash).ToBase64()); - sendTransactionResponse.Transaction.Signature.ShouldBe(ByteString.CopyFrom(signature).ToBase64()); - - existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); - existTransaction.Transactions[0].GetHash().ToHex().ShouldBe(sendTransactionResponse.TransactionId); - } + var existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); + existTransaction.Transactions[0].GetHash().ToHex().ShouldBe(sendTransactionResponse.TransactionId); - [Fact] - public async Task SendRawTransaction_ReturnInvalidTransaction_Test() + parameters = new Dictionary { - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - - var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - var parameters = new Dictionary - { - {"Transaction", transaction.ToByteArray().ToHex()}, - {"Signature", signature.ToHex()} - }; - var errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - } + { "Transaction", createTransactionResponse.RawTransaction }, + { "Signature", signature.ToHex() }, + { "returnTransaction", "true" } + }; + sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(transactionId.ToHex()); + sendTransactionResponse.Transaction.ShouldNotBeNull(); + sendTransactionResponse.Transaction.To.ShouldBe(contractAddress.ToBase58()); + sendTransactionResponse.Transaction.From.ShouldBe(accountAddress.ToBase58()); + sendTransactionResponse.Transaction.MethodName.ShouldBe(methodName); + sendTransactionResponse.Transaction.Params.ShouldBe( + "{ \"to\": \"" + Address.FromPublicKey(newUserKeyPair.PublicKey).ToBase58() + + "\", \"symbol\": \"ELF\", \"amount\": \"100\", \"memo\": \"test\" }"); + sendTransactionResponse.Transaction.RefBlockNumber.ShouldBe(chain.BestChainHeight); + sendTransactionResponse.Transaction.RefBlockPrefix.ShouldBe(BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + .ToBase64()); + sendTransactionResponse.Transaction.Signature.ShouldBe(ByteString.CopyFrom(signature).ToBase64()); + + existTransaction = await _txHub.GetExecutableTransactionSetAsync(chain.BestChainHash, int.MaxValue); + existTransaction.Transactions[0].GetHash().ToHex().ShouldBe(sendTransactionResponse.TransactionId); + } - [Fact] - public async Task SendRawTransaction_ReturnNoMatchMethodInContractAddress_Test() + [Fact] + public async Task SendRawTransaction_ReturnInvalidTransaction_Test() + { + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + + var from = Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + var parameters = new Dictionary { - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var json = - "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"invalid_method\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - var parameters = new Dictionary - { - {"Transaction", transaction.ToByteArray().ToHex()}, - {"Signature", signature.ToHex()} - }; - var errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); - } + { "Transaction", transaction.ToByteArray().ToHex() }, + { "Signature", signature.ToHex() } + }; + var errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + } - [Fact] - public async Task SendRawTransaction_ReturnInvalidParams_Test() + [Fact] + public async Task SendRawTransaction_ReturnNoMatchMethodInContractAddress_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var json = + "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"invalid_method\", \"params\": \"CiIKIDAK0LTy1ZAHaf1nAnq/gkSqTCs4Kh6czxWpbNEX4EwaEgNFTEYYFA==\"}"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + var parameters = new Dictionary { - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var transactionParams = TransferInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); - - var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + - Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - var parameters = new Dictionary - { - {"Transaction", transaction.ToByteArray().ToHex()}, - {"Signature", signature.ToHex()} - }; - var errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - - var issueInput = IssueInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidHash")) + - "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); - - json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Issue\", \"params\": \"" + - Base64.ToBase64String(issueInput.ToByteArray()) + "\" }"; - transaction = Transaction.Parser.ParseJson(json); - - signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - parameters = new Dictionary - { - {"Transaction", transaction.ToByteArray().ToHex()}, - {"Signature", signature.ToHex()} - }; - errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", - parameters, expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); - } + { "Transaction", transaction.ToByteArray().ToHex() }, + { "Signature", signature.ToHex() } + }; + var errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.NoMatchMethodInContractAddress.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.NoMatchMethodInContractAddress]); + } - [Fact] - public async Task GetTaskQueueStateInfos_Test() + [Fact] + public async Task SendRawTransaction_ReturnInvalidParams_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var transactionParams = TransferInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidAddress")) + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); + + var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + + Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + var parameters = new Dictionary + { + { "Transaction", transaction.ToByteArray().ToHex() }, + { "Signature", signature.ToHex() } + }; + var errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + + var issueInput = IssueInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + Base64.ToBase64String(Encoding.UTF8.GetBytes("InvalidHash")) + + "\" },\"symbol\":\"ELF\",\"amount\":100,\"memo\":\"test\"}"); + + json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Issue\", \"params\": \"" + + Base64.ToBase64String(issueInput.ToByteArray()) + "\" }"; + transaction = Transaction.Parser.ParseJson(json); + + signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + parameters = new Dictionary { - var response = - await GetResponseAsObjectAsync>("/api/blockChain/taskQueueStatus"); + { "Transaction", transaction.ToByteArray().ToHex() }, + { "Signature", signature.ToHex() } + }; + errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendRawTransaction", + parameters, expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.InvalidParams.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); + } - var count = response.Count; - count.ShouldBeGreaterThan(0); - } + [Fact] + public async Task GetTaskQueueStateInfos_Test() + { + var response = + await GetResponseAsObjectAsync>("/api/blockChain/taskQueueStatus"); + + var count = response.Count; + count.ShouldBeGreaterThan(0); + } - [Fact] - public async Task GetMerklePathByTransactionId_Success_Test() + [Fact] + public async Task GetMerklePathByTransactionId_Success_Test() + { + var transactionList = new List(); + for (var i = 0; i < 3; i++) { - var transactionList = new List(); - for (var i = 0; i < 3; i++) + var transaction = await _osTestHelper.GenerateTransferTransaction(); + transactionList.Add(transaction); + } + + await _osTestHelper.BroadcastTransactions(transactionList); + var block = await _osTestHelper.MinedOneBlock(); + // After mined + var merkleTreeRoot = block.Header.MerkleTreeRootOfTransactionStatus; + var txHex = block.Body.TransactionIds[0].ToHex(); + + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/merklePathByTransactionId?transactionId={txHex}"); + var merklePath = new MerklePath(); + foreach (var res in response.MerklePathNodes) + merklePath.MerklePathNodes.Add(new MerklePathNode { - var transaction = await _osTestHelper.GenerateTransferTransaction(); - transactionList.Add(transaction); - } + Hash = Hash.LoadFromHex(res.Hash), IsLeftChildNode = res.IsLeftChildNode + }); - await _osTestHelper.BroadcastTransactions(transactionList); - var block = await _osTestHelper.MinedOneBlock(); - // After mined - var merkleTreeRoot = block.Header.MerkleTreeRootOfTransactionStatus; - var txHex = block.Body.TransactionIds[0].ToHex(); + var transactionResult = await _osTestHelper.GetTransactionResultsAsync(block.Body.TransactionIds[0]); + var calculatedRoot = merklePath.ComputeRootWithLeafNode( + GetHashCombiningTransactionAndStatus(transactionResult.TransactionId, transactionResult.Status)); - var response = await GetResponseAsObjectAsync( - $"/api/blockChain/merklePathByTransactionId?transactionId={txHex}"); - var merklePath = new MerklePath(); - foreach (var res in response.MerklePathNodes) - { - merklePath.MerklePathNodes.Add(new MerklePathNode - { - Hash = Hash.LoadFromHex(res.Hash), IsLeftChildNode = res.IsLeftChildNode - }); - } + var merklePathNodes = response.MerklePathNodes; + merklePathNodes.Count.ShouldBe(2); - var transactionResult = await _osTestHelper.GetTransactionResultsAsync(block.Body.TransactionIds[0]); - var calculatedRoot = merklePath.ComputeRootWithLeafNode( - GetHashCombiningTransactionAndStatus(transactionResult.TransactionId, transactionResult.Status)); + Assert.True(merklePathNodes[0].IsLeftChildNode == false); + Assert.True(merklePathNodes[1].IsLeftChildNode == false); + Assert.True(merkleTreeRoot == calculatedRoot); + } - var merklePathNodes = response.MerklePathNodes; - merklePathNodes.Count.ShouldBe(2); + [Fact] + public async Task GetMerklePathByTransactionId_Failed_Test() + { + var hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; - Assert.True(merklePathNodes[0].IsLeftChildNode == false); - Assert.True(merklePathNodes[1].IsLeftChildNode == false); - Assert.True(merkleTreeRoot == calculatedRoot); - } + var errorResponse = await GetResponseAsObjectAsync( + $"/api/blockChain/merklePathByTransactionId?transactionId={hex}", + expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); + } + + + [Fact] + public async Task GetMerklePathByTransactionId_InvalidTransactionId_Test() + { + var transactionId = "InvalidTransactionId"; + var errorResponse = await GetResponseAsObjectAsync( + $"/api/blockChain/merklePathByTransactionId?transactionId={transactionId}", + expectedStatusCode: HttpStatusCode.Forbidden); + + errorResponse.Error.Code.ShouldBe(Error.InvalidTransactionId.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransactionId]); + } - [Fact] - public async Task GetMerklePathByTransactionId_Failed_Test() + [Fact] + public async Task ExecuteTransaction_InvalidTransaction_Test() + { + // Generate a invalid transaction + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var transactionParams = TransferInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + from + + "\" },\"symbol\":\"ELF\",\"amount\":100000,\"memo\":\"test\"}"); + + var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + + Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + var parameters = new Dictionary { - string hex = "5a7d71da020cae179a0dfe82bd3c967e1573377578f4cc87bc21f74f2556c0ef"; + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; - var errorResponse = await GetResponseAsObjectAsync( - $"/api/blockChain/merklePathByTransactionId?transactionId={hex}", + var errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.NotFound.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.NotFound]); - } - - + errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + } - [Fact] - public async Task GetMerklePathByTransactionId_InvalidTransactionId_Test() - { - string transactionId = "InvalidTransactionId"; - var errorResponse = await GetResponseAsObjectAsync( - $"/api/blockChain/merklePathByTransactionId?transactionId={transactionId}",expectedStatusCode: HttpStatusCode.Forbidden); - - errorResponse.Error.Code.ShouldBe(Error.InvalidTransactionId.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransactionId]); - } - [Fact] - public async Task ExecuteTransaction_InvalidTransaction_Test() + [Fact] + public async Task ExecuteRawTransaction_InvalidTransaction_Test() + { + // Generate a invalid transaction + var accountAddress = await _accountService.GetAccountAsync(); + var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); + var contractAddress = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); + var transactionParams = TransferInput.Parser.ParseJson( + "{\"to\":{ \"value\": \"" + from + + "\" },\"symbol\":\"ELF\",\"amount\":100000,\"memo\":\"test\"}"); + + var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + + "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + + Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; + var transaction = Transaction.Parser.ParseJson(json); + + var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + var parameters = new Dictionary { - // Generate a invalid transaction - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var transactionParams = TransferInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + from + - "\" },\"symbol\":\"ELF\",\"amount\":100000,\"memo\":\"test\"}"); - - var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + - Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - var parameters = new Dictionary - { - {"rawTransaction", transaction.ToByteArray().ToHex()} - }; - - var errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/executeTransaction", parameters, - expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - } + { "RawTransaction", transaction.ToByteArray().ToHex() }, + { "Signature", signature.ToHex() } + }; + var errorResponse = + await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", parameters, + expectedStatusCode: HttpStatusCode.Forbidden); + errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); + errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); + } - [Fact] - public async Task ExecuteRawTransaction_InvalidTransaction_Test() - { - // Generate a invalid transaction - var accountAddress = await _accountService.GetAccountAsync(); - var from = Base64.ToBase64String(accountAddress.Value.ToByteArray()); - var contractAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var to = Base64.ToBase64String(contractAddress.Value.ToByteArray()); - var transactionParams = TransferInput.Parser.ParseJson( - "{\"to\":{ \"value\": \"" + from + - "\" },\"symbol\":\"ELF\",\"amount\":100000,\"memo\":\"test\"}"); - - var json = "{ \"from\": { \"value\": \"" + from + "\" }, \"to\": { \"value\": \"" + to + - "\" }, \"ref_block_number\": \"11\", \"ref_block_prefix\": \"H9f1zQ==\", \"method_name\": \"Transfer\", \"params\": \"" + - Base64.ToBase64String(transactionParams.ToByteArray()) + "\" }"; - var transaction = Transaction.Parser.ParseJson(json); - - var signature = await _accountService.SignAsync(transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - var parameters = new Dictionary - { - {"RawTransaction", transaction.ToByteArray().ToHex()}, - {"Signature", signature.ToHex()} - }; - var errorResponse = - await PostResponseAsObjectAsync("/api/blockChain/executeRawTransaction", parameters, - expectedStatusCode: HttpStatusCode.Forbidden); - errorResponse.Error.Code.ShouldBe(Error.InvalidTransaction.ToString()); - errorResponse.Error.Message.ShouldBe(Error.Message[Error.InvalidTransaction]); - - } - [Fact] - public async Task GetBlock_ExcludeTransaction_Test() - { - var transactions = new List(); - for (int i = 0; i < 3; i++) - { - transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - } + [Fact] + public async Task GetBlock_ExcludeTransaction_Test() + { + var transactions = new List(); + for (var i = 0; i < 3; i++) transactions.Add(await _osTestHelper.GenerateTransferTransaction()); - await _osTestHelper.BroadcastTransactions(transactions); - await _osTestHelper.MinedOneBlock(); + await _osTestHelper.BroadcastTransactions(transactions); + await _osTestHelper.MinedOneBlock(); - var block = await GetResponseAsObjectAsync( - "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=false"); - block.Body.Transactions.ShouldBeEmpty(); - } + var block = await GetResponseAsObjectAsync( + "/api/blockChain/blockByHeight?blockHeight=12&includeTransactions=false"); + block.Body.Transactions.ShouldBeEmpty(); + } - [Fact] - public async Task TransactionValidationStatusChangedEventHandler_Test() + [Fact] + public async Task TransactionValidationStatusChangedEventHandler_Test() + { + var transactionId = HashHelper.ComputeFrom("Test"); + _transactionResultStatusCacheProvider.AddTransactionResultStatus(transactionId); { - var transactionId = HashHelper.ComputeFrom("Test"); - _transactionResultStatusCacheProvider.AddTransactionResultStatus(transactionId); - { - var originalStatus = _transactionResultStatusCacheProvider.GetTransactionResultStatus(transactionId); - originalStatus.TransactionResultStatus.ShouldBe(TransactionResultStatus.NotExisted); - } - await _transactionValidationStatusChangedEventHandler.HandleEventAsync(new TransactionValidationStatusChangedEvent + var originalStatus = _transactionResultStatusCacheProvider.GetTransactionResultStatus(transactionId); + originalStatus.TransactionResultStatus.ShouldBe(TransactionResultStatus.NotExisted); + } + await _transactionValidationStatusChangedEventHandler.HandleEventAsync( + new TransactionValidationStatusChangedEvent { TransactionId = transactionId, TransactionResultStatus = TransactionResultStatus.PendingValidation, Error = "error" }); - var result= _transactionResultStatusCacheProvider.GetTransactionResultStatus(transactionId); - result.TransactionResultStatus.ShouldBe(TransactionResultStatus.PendingValidation); - result.Error.ShouldBe("error"); - } + var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(transactionId); + result.TransactionResultStatus.ShouldBe(TransactionResultStatus.PendingValidation); + result.Error.ShouldBe("error"); + } + + private async Task> GenerateTwoInitializeTransaction() + { + var transactionList = new List(); + var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - private async Task> GenerateTwoInitializeTransaction() + for (var i = 0; i < 2; i++) { - var transactionList = new List(); - var newUserKeyPair = CryptoHelper.GenerateKeyPair(); + var transaction = _osTestHelper.GenerateTransaction(Address.FromPublicKey(newUserKeyPair.PublicKey), + await _smartContractAddressService.GetAddressByContractNameAsync( + await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), + nameof(TokenContractContainer.TokenContractStub.CrossChainReceiveToken), new CrossChainReceiveTokenInput + { + FromChainId = ChainHelper.ConvertBase58ToChainId("AELF"), + ParentChainHeight = i + }); - for (int i = 0; i < 2; i++) - { - var transaction = _osTestHelper.GenerateTransaction(Address.FromPublicKey(newUserKeyPair.PublicKey), - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - nameof(TokenContractContainer.TokenContractStub.CrossChainReceiveToken), new CrossChainReceiveTokenInput - { - FromChainId = ChainHelper.ConvertBase58ToChainId("AELF"), - ParentChainHeight = i - }); - - var signature = - CryptoHelper.SignWithPrivateKey(newUserKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); - - transactionList.Add(transaction); - } + var signature = + CryptoHelper.SignWithPrivateKey(newUserKeyPair.PrivateKey, transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); - return transactionList; + transactionList.Add(transaction); } - private async Task GenerateViewTransaction(string method, IMessage input) - { - var newUserKeyPair = CryptoHelper.GenerateKeyPair(); + return transactionList; + } - var transaction = _osTestHelper.GenerateTransaction(Address.FromPublicKey(newUserKeyPair.PublicKey), - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName), - method, input); + private async Task GenerateViewTransaction(string method, IMessage input) + { + var newUserKeyPair = CryptoHelper.GenerateKeyPair(); - var signature = CryptoHelper.SignWithPrivateKey(newUserKeyPair.PrivateKey, - transaction.GetHash().ToByteArray()); - transaction.Signature = ByteString.CopyFrom(signature); + var transaction = _osTestHelper.GenerateTransaction(Address.FromPublicKey(newUserKeyPair.PublicKey), + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName), + method, input); + + var signature = CryptoHelper.SignWithPrivateKey(newUserKeyPair.PrivateKey, + transaction.GetHash().ToByteArray()); + transaction.Signature = ByteString.CopyFrom(signature); + + return transaction; + } + + private Hash GetHashCombiningTransactionAndStatus(Hash txId, + TransactionResultStatus executionReturnStatus) + { + // combine tx result status + var rawBytes = txId.ToByteArray().Concat(Encoding.UTF8.GetBytes(executionReturnStatus.ToString())) + .ToArray(); + return HashHelper.ComputeFrom(rawBytes); + } + + [IgnoreOnCIFact] + public async Task TransactionResultStatusCacheProviderTest() + { + var txId = HashHelper.ComputeFrom("Test"); + _transactionResultStatusCacheProvider.AddTransactionResultStatus(txId); - return transaction; - } - - private Hash GetHashCombiningTransactionAndStatus(Hash txId, - TransactionResultStatus executionReturnStatus) { - // combine tx result status - var rawBytes = txId.ToByteArray().Concat(Encoding.UTF8.GetBytes(executionReturnStatus.ToString())) - .ToArray(); - return HashHelper.ComputeFrom(rawBytes); + var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); + result.ShouldNotBeNull(); } - [IgnoreOnCIFact] - public async Task TransactionResultStatusCacheProviderTest() - { - var txId = HashHelper.ComputeFrom("Test"); - _transactionResultStatusCacheProvider.AddTransactionResultStatus(txId); - - { - var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); - result.ShouldNotBeNull(); - } - - _transactionResultStatusCacheProvider.ChangeTransactionResultStatus(txId, - new TransactionValidateStatus - { - TransactionResultStatus = TransactionResultStatus.PendingValidation - }); - - Thread.Sleep(1500); - + _transactionResultStatusCacheProvider.ChangeTransactionResultStatus(txId, + new TransactionValidateStatus { - var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); - result.TransactionResultStatus.ShouldBe(TransactionResultStatus.PendingValidation); - } + TransactionResultStatus = TransactionResultStatus.PendingValidation + }); - Thread.Sleep(700); - - { - var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); - result.ShouldBeNull(); - } + Thread.Sleep(1500); + + { + var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); + result.TransactionResultStatus.ShouldBe(TransactionResultStatus.PendingValidation); + } + + Thread.Sleep(700); + + { + var result = _transactionResultStatusCacheProvider.GetTransactionResultStatus(txId); + result.ShouldBeNull(); } } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Chain.Tests/FormatterAndConverterTests.cs b/test/AElf.WebApp.Application.Chain.Tests/FormatterAndConverterTests.cs index 8f7ffb6af9..e28b73e7e4 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/FormatterAndConverterTests.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/FormatterAndConverterTests.cs @@ -14,162 +14,160 @@ using Newtonsoft.Json; using Shouldly; using Xunit; -using Type = System.Type; -namespace AElf.WebApp.Application.Chain.Tests +namespace AElf.WebApp.Application.Chain.Tests; + +public class FormatterAndConverterTests { - public class FormatterAndConverterTests + private readonly InputFormatter _inputFormatter; + private readonly JsonConverter _jsonConverter; + private readonly OutputFormatter _outputFormatter; + + public FormatterAndConverterTests() + { + _inputFormatter = new ProtobufInputFormatter(); + _outputFormatter = new ProtobufOutputFormatter(); + _jsonConverter = new ProtoMessageConverter(); + } + + [Fact] + public async Task InputFormatter_Context_With_Message_Test() + { + var hashValue = HashHelper.ComputeFrom("test").ToByteArray(); + var content = hashValue.ToString(); + var context = GenerateInputFormatterContext(content, typeof(Hash), "application/x-protobuf"); + + var canRead = _inputFormatter.CanRead(context); + canRead.ShouldBeTrue(); + + await _inputFormatter.ReadRequestBodyAsync(context); + } + + [Fact] + public async Task InputFormatter_Context_With_NoneIMessage_Test() + { + const string content = "{\"Name\":\"GetBlock\",\"Size\": 100}"; + var context = GenerateInputFormatterContext(content, typeof(TaskQueueInfoDto), null); + + var canRead = _inputFormatter.CanRead(context); + canRead.ShouldBeFalse(); + + var result = await _inputFormatter.ReadRequestBodyAsync(context); + result.HasError.ShouldBeTrue(); + } + + [Fact] + public void OutputFormatter_Context_CanWrite_Test() + { + var context = GenerateOutputFormatterWriteContext(typeof(Address), null); + var result = _outputFormatter.CanWriteResult(context); + result.ShouldBeFalse(); + + var address = GenerateAddress(); + context = GenerateOutputFormatterWriteContext(typeof(Address), address, "application/x-protobuf"); + var result2 = _outputFormatter.CanWriteResult(context); + result2.ShouldBeTrue(); + } + + [Fact] + public async Task OutputFormatter_WriteResponse_Test() + { + var address = GenerateAddress(); + var stream = new MemoryStream(); + var context = + GenerateOutputFormatterWriteContext(typeof(Address), address, "application/x-protobuf", stream); + + await _outputFormatter.WriteResponseBodyAsync(context); + } + + [Fact] + public void JsonConverter_CanConvert_Test() { - private readonly InputFormatter _inputFormatter; - private readonly OutputFormatter _outputFormatter; - private readonly JsonConverter _jsonConverter; - - public FormatterAndConverterTests() - { - _inputFormatter = new ProtobufInputFormatter(); - _outputFormatter = new ProtobufOutputFormatter(); - _jsonConverter = new ProtoMessageConverter(); - } - - [Fact] - public async Task InputFormatter_Context_With_Message_Test() - { - var hashValue = HashHelper.ComputeFrom("test").ToByteArray(); - var content = hashValue.ToString(); - var context = GenerateInputFormatterContext(content, typeof(Hash), "application/x-protobuf"); - - var canRead = _inputFormatter.CanRead(context); - canRead.ShouldBeTrue(); - - await _inputFormatter.ReadRequestBodyAsync(context); - } - - [Fact] - public async Task InputFormatter_Context_With_NoneIMessage_Test() - { - const string content = "{\"Name\":\"GetBlock\",\"Size\": 100}"; - var context = GenerateInputFormatterContext(content, typeof(TaskQueueInfoDto), null); - - var canRead = _inputFormatter.CanRead(context); - canRead.ShouldBeFalse(); - - var result = await _inputFormatter.ReadRequestBodyAsync(context); - result.HasError.ShouldBeTrue(); - } - - [Fact] - public void OutputFormatter_Context_CanWrite_Test() - { - var context = GenerateOutputFormatterWriteContext(typeof(Address), null); - var result = _outputFormatter.CanWriteResult(context); - result.ShouldBeFalse(); - - var address = GenerateAddress(); - context = GenerateOutputFormatterWriteContext(typeof(Address), address, "application/x-protobuf"); - var result2 = _outputFormatter.CanWriteResult(context); - result2.ShouldBeTrue(); - } - - [Fact] - public async Task OutputFormatter_WriteResponse_Test() - { - var address = GenerateAddress(); - var stream = new MemoryStream(); - var context = - GenerateOutputFormatterWriteContext(typeof(Address), address, "application/x-protobuf", stream); - - await _outputFormatter.WriteResponseBodyAsync(context); - } - - [Fact] - public void JsonConverter_CanConvert_Test() - { - var result = _jsonConverter.CanConvert(typeof(TaskQueueInfoDto)); - result.ShouldBeFalse(); - - var result1 = _jsonConverter.CanConvert(typeof(Address)); - result1.ShouldBeTrue(); - } - - [Fact] - public void JsonConverter_ReadJson_Test() - { - const string content = "{\"value\":\"EvU6Z9HnVFwt4f7fKlsu5qK4RoEraDxCUJuUM6HO6ic=\"}"; - var serializer = new JsonSerializer(); - var reader = new JsonTextReader(new StringReader(content)); - - var result = _jsonConverter.ReadJson(reader, typeof(Address), null, serializer); - result.ShouldNotBeNull(); - result.GetType().ShouldBe(typeof(Address)); - } - - [Fact] - public void JsonConverter_WriteJson_Test() - { - var address = GenerateAddress(); - - var serializer = new JsonSerializer(); - var sb = new StringBuilder(); - var writer = new JsonTextWriter(new StringWriter(sb)); - - _jsonConverter.WriteJson(writer, address, serializer); - sb.Length.ShouldBeGreaterThan(0); - sb.ToString().Contains("value").ShouldBeTrue(); - } - - private InputFormatterContext GenerateInputFormatterContext(string content, Type type, - string contentType = "application/json") - { - var contentBytes = Encoding.UTF8.GetBytes(content); - var stream = new MemoryStream(contentBytes); - var httpContext = new DefaultHttpContext(); - httpContext.Request.ContentType = contentType; - httpContext.Request.Body = stream; - - var modelState = new ModelStateDictionary(); - var provider = new EmptyModelMetadataProvider(); - var metadata = provider.GetMetadataForType(type); - var context = new InputFormatterContext( - httpContext, - string.Empty, - modelState, - metadata, - new TestHttpRequestStreamReaderFactory().CreateReader); - return context; - } - - private OutputFormatterWriteContext GenerateOutputFormatterWriteContext(Type type, object objInfo, - string contentType = "application/json", MemoryStream stream = null) - { - var httpContext = new DefaultHttpContext(); - httpContext.Request.ContentType = contentType; - httpContext.Response.Body = stream ?? new MemoryStream(); - - var context = new OutputFormatterWriteContext( - httpContext, - Mock.Of>(), - type, - objInfo - ); - context.ContentType = contentType; - - return context; - } - - private static Address GenerateAddress() - { - var byteArray = new byte[32]; - new Random().NextBytes(byteArray); - - return Address.FromBytes(byteArray); - } + var result = _jsonConverter.CanConvert(typeof(TaskQueueInfoDto)); + result.ShouldBeFalse(); + + var result1 = _jsonConverter.CanConvert(typeof(Address)); + result1.ShouldBeTrue(); + } + + [Fact] + public void JsonConverter_ReadJson_Test() + { + const string content = "{\"value\":\"EvU6Z9HnVFwt4f7fKlsu5qK4RoEraDxCUJuUM6HO6ic=\"}"; + var serializer = new JsonSerializer(); + var reader = new JsonTextReader(new StringReader(content)); + + var result = _jsonConverter.ReadJson(reader, typeof(Address), null, serializer); + result.ShouldNotBeNull(); + result.GetType().ShouldBe(typeof(Address)); + } + + [Fact] + public void JsonConverter_WriteJson_Test() + { + var address = GenerateAddress(); + + var serializer = new JsonSerializer(); + var sb = new StringBuilder(); + var writer = new JsonTextWriter(new StringWriter(sb)); + + _jsonConverter.WriteJson(writer, address, serializer); + sb.Length.ShouldBeGreaterThan(0); + sb.ToString().Contains("value").ShouldBeTrue(); + } + + private InputFormatterContext GenerateInputFormatterContext(string content, Type type, + string contentType = "application/json") + { + var contentBytes = Encoding.UTF8.GetBytes(content); + var stream = new MemoryStream(contentBytes); + var httpContext = new DefaultHttpContext(); + httpContext.Request.ContentType = contentType; + httpContext.Request.Body = stream; + + var modelState = new ModelStateDictionary(); + var provider = new EmptyModelMetadataProvider(); + var metadata = provider.GetMetadataForType(type); + var context = new InputFormatterContext( + httpContext, + string.Empty, + modelState, + metadata, + new TestHttpRequestStreamReaderFactory().CreateReader); + return context; + } + + private OutputFormatterWriteContext GenerateOutputFormatterWriteContext(Type type, object objInfo, + string contentType = "application/json", MemoryStream stream = null) + { + var httpContext = new DefaultHttpContext(); + httpContext.Request.ContentType = contentType; + httpContext.Response.Body = stream ?? new MemoryStream(); + + var context = new OutputFormatterWriteContext( + httpContext, + Mock.Of>(), + type, + objInfo + ); + context.ContentType = contentType; + + return context; } - - public class TestHttpRequestStreamReaderFactory : IHttpRequestStreamReaderFactory + + private static Address GenerateAddress() + { + var byteArray = new byte[32]; + new Random().NextBytes(byteArray); + + return Address.FromBytes(byteArray); + } +} + +public class TestHttpRequestStreamReaderFactory : IHttpRequestStreamReaderFactory +{ + public TextReader CreateReader(Stream stream, Encoding encoding) { - public TextReader CreateReader(Stream stream, Encoding encoding) - { - return new HttpRequestStreamReader(stream, encoding); - } + return new HttpRequestStreamReader(stream, encoding); } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Chain.Tests/TransactionToHubTests.cs b/test/AElf.WebApp.Application.Chain.Tests/TransactionToHubTests.cs index 531005bf63..e5cd052fe4 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/TransactionToHubTests.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/TransactionToHubTests.cs @@ -1,18 +1,13 @@ using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Cryptography; using AElf.Cryptography.ECDSA; -using AElf.Kernel; -using AElf.Kernel.Account.Application; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus; using AElf.Kernel.SmartContract.Application; -using AElf.Kernel.SmartContract.Domain; using AElf.Kernel.Token; -using AElf.Kernel.TransactionPool.Infrastructure; using AElf.OS; using AElf.Types; using AElf.WebApp.Application.Chain.Dto; @@ -23,65 +18,40 @@ using Xunit.Abstractions; using Enum = System.Enum; -namespace AElf.WebApp.Application.Chain.Tests +namespace AElf.WebApp.Application.Chain.Tests; + +public class TransactionToHubTests : WebAppTestBase { - public class TransactionToHubTests : WebAppTestBase + private readonly IBlockchainService _blockchainService; + private readonly OSTestHelper _osTestHelper; + private readonly ISmartContractAddressService _smartContractAddressService; + + public TransactionToHubTests(ITestOutputHelper outputHelper) : base(outputHelper) { - private readonly IBlockchainService _blockchainService; - private readonly ISmartContractAddressService _smartContractAddressService; - private readonly OSTestHelper _osTestHelper; - - public TransactionToHubTests(ITestOutputHelper outputHelper) : base(outputHelper) - { - _blockchainService = GetRequiredService(); - _smartContractAddressService = GetRequiredService(); - _osTestHelper = GetRequiredService(); - } + _blockchainService = GetRequiredService(); + _smartContractAddressService = GetRequiredService(); + _osTestHelper = GetRequiredService(); + } - [Fact] - public async Task SentTransaction_Token_Check_Test() + [Fact] + public async Task SentTransaction_Token_Check_Test() + { + //user without token - NotExisted { - //user without token - NotExisted - { - var keyPair = CryptoHelper.GenerateKeyPair(); - var tokenAddress = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), - TokenSmartContractAddressNameProvider.StringName); - - //approve transaction - var transaction = await GenerateTransaction(keyPair, tokenAddress, "Approve", new ApproveInput - { - Amount = 100, - Spender = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey), - // TODO: valid symbol needed for a test case not related to token symbol - Symbol = "Check user without token whether can sent transaction" - }); - - var transactionId = await SendTransactionAsync(transaction); - var transactionResult = await QueryTransactionResultAsync(transactionId); - Enum.TryParse(transactionResult.Status, true, out var status); - status.ShouldBe(TransactionResultStatus.Failed); - } - - //bp user with token - Mined + var keyPair = CryptoHelper.GenerateKeyPair(); + var tokenAddress = + await _smartContractAddressService.GetAddressByContractNameAsync( + await _osTestHelper.GetChainContextAsync(), + TokenSmartContractAddressNameProvider.StringName); + + //approve transaction + var transaction = await GenerateTransaction(keyPair, tokenAddress, "Approve", new ApproveInput { - var transaction = await _osTestHelper.GenerateTransferTransaction(); - var transactionId = await SendTransactionAsync(transaction); - var transactionResult = await QueryTransactionResultAsync(transactionId); - Enum.TryParse(transactionResult.Status, true, out var status); - status.ShouldBe(TransactionResultStatus.Mined); - } - } - - [Fact] - public async Task SentTransaction_ContractAddress_Check_Test() - { - //prepare token - var (transactions, keyPairs) = await _osTestHelper.PrepareTokenForParallel(2, 100); - await SendTransactionAsync(transactions[0]); - - var fakeContract = Address.FromPublicKey(keyPairs[1].PublicKey); - var transaction = await GenerateTransaction(keyPairs[0], fakeContract, "ContractTest", new Empty()); + Amount = 100, + Spender = Address.FromPublicKey(CryptoHelper.GenerateKeyPair().PublicKey), + // TODO: valid symbol needed for a test case not related to token symbol + Symbol = "Check user without token whether can sent transaction" + }); var transactionId = await SendTransactionAsync(transaction); var transactionResult = await QueryTransactionResultAsync(transactionId); @@ -89,63 +59,88 @@ public async Task SentTransaction_ContractAddress_Check_Test() status.ShouldBe(TransactionResultStatus.Failed); } - [Fact] - public async Task SentTransaction_SystemContract_Check_Test() + //bp user with token - Mined { - //prepare token - var (transactions, keyPairs) = await _osTestHelper.PrepareTokenForParallel(1, 100); - await SendTransactionAsync(transactions[0]); - - //send consensus transaction - var consensusContract = - await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), - ConsensusSmartContractAddressNameProvider.StringName); - var transaction = await GenerateTransaction(keyPairs[0], consensusContract, "FirstRound", new Round()); - + var transaction = await _osTestHelper.GenerateTransferTransaction(); var transactionId = await SendTransactionAsync(transaction); var transactionResult = await QueryTransactionResultAsync(transactionId); Enum.TryParse(transactionResult.Status, true, out var status); - status.ShouldBe(TransactionResultStatus.Failed); + status.ShouldBe(TransactionResultStatus.Mined); } + } - private async Task SendTransactionAsync(Transaction transaction) - { - await _osTestHelper.BroadcastTransactions(new List {transaction}); - await _osTestHelper.MinedOneBlock(); + [Fact] + public async Task SentTransaction_ContractAddress_Check_Test() + { + //prepare token + var (transactions, keyPairs) = await _osTestHelper.PrepareTokenForParallel(2, 100); + await SendTransactionAsync(transactions[0]); - return transaction.GetHash().ToHex(); - } + var fakeContract = Address.FromPublicKey(keyPairs[1].PublicKey); + var transaction = await GenerateTransaction(keyPairs[0], fakeContract, "ContractTest", new Empty()); - private async Task QueryTransactionResultAsync(string transactionId) - { - return await GetResponseAsObjectAsync( - $"/api/blockChain/transactionResult?transactionId={transactionId}"); - } + var transactionId = await SendTransactionAsync(transaction); + var transactionResult = await QueryTransactionResultAsync(transactionId); + Enum.TryParse(transactionResult.Status, true, out var status); + status.ShouldBe(TransactionResultStatus.Failed); + } - private async Task GenerateTransaction(ECKeyPair keyPair, Address contract, string method, - IMessage input) - { - var transaction = new Transaction - { - From = Address.FromPublicKey(keyPair.PublicKey), - To = contract, - MethodName = method, - Params = input.ToByteString() - }; - return await AddReferenceAndSignAsync(keyPair, transaction); - } + [Fact] + public async Task SentTransaction_SystemContract_Check_Test() + { + //prepare token + var (transactions, keyPairs) = await _osTestHelper.PrepareTokenForParallel(1, 100); + await SendTransactionAsync(transactions[0]); + + //send consensus transaction + var consensusContract = + await _smartContractAddressService.GetAddressByContractNameAsync(await _osTestHelper.GetChainContextAsync(), + ConsensusSmartContractAddressNameProvider.StringName); + var transaction = await GenerateTransaction(keyPairs[0], consensusContract, "FirstRound", new Round()); + + var transactionId = await SendTransactionAsync(transaction); + var transactionResult = await QueryTransactionResultAsync(transactionId); + Enum.TryParse(transactionResult.Status, true, out var status); + status.ShouldBe(TransactionResultStatus.Failed); + } - private async Task AddReferenceAndSignAsync(ECKeyPair keyPair, Transaction transaction) + private async Task SendTransactionAsync(Transaction transaction) + { + await _osTestHelper.BroadcastTransactions(new List { transaction }); + await _osTestHelper.MinedOneBlock(); + + return transaction.GetHash().ToHex(); + } + + private async Task QueryTransactionResultAsync(string transactionId) + { + return await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transactionId}"); + } + + private async Task GenerateTransaction(ECKeyPair keyPair, Address contract, string method, + IMessage input) + { + var transaction = new Transaction { - var chain = await _blockchainService.GetChainAsync(); - transaction.RefBlockNumber = chain.BestChainHeight; - transaction.RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash); + From = Address.FromPublicKey(keyPair.PublicKey), + To = contract, + MethodName = method, + Params = input.ToByteString() + }; + return await AddReferenceAndSignAsync(keyPair, transaction); + } + + private async Task AddReferenceAndSignAsync(ECKeyPair keyPair, Transaction transaction) + { + var chain = await _blockchainService.GetChainAsync(); + transaction.RefBlockNumber = chain.BestChainHeight; + transaction.RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash); - transaction.Signature = - ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, - transaction.GetHash().ToByteArray())); + transaction.Signature = + ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(keyPair.PrivateKey, + transaction.GetHash().ToByteArray())); - return transaction; - } + return transaction; } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Net.Tests/AElf.WebApp.Application.Net.Tests.csproj b/test/AElf.WebApp.Application.Net.Tests/AElf.WebApp.Application.Net.Tests.csproj index c987966b63..4233a50e11 100644 --- a/test/AElf.WebApp.Application.Net.Tests/AElf.WebApp.Application.Net.Tests.csproj +++ b/test/AElf.WebApp.Application.Net.Tests/AElf.WebApp.Application.Net.Tests.csproj @@ -4,16 +4,16 @@ false - - - - - - - + + + + + + + - + - + diff --git a/test/AElf.WebApp.Application.Net.Tests/NetAppServiceTest.cs b/test/AElf.WebApp.Application.Net.Tests/NetAppServiceTest.cs index d9cd0f7f59..ae94651be8 100644 --- a/test/AElf.WebApp.Application.Net.Tests/NetAppServiceTest.cs +++ b/test/AElf.WebApp.Application.Net.Tests/NetAppServiceTest.cs @@ -17,200 +17,208 @@ using Xunit; using Xunit.Abstractions; -namespace AElf.WebApp.Application.Net.Tests +namespace AElf.WebApp.Application.Net.Tests; + +public sealed class NetAppServiceTest : WebAppTestBase { - public sealed class NetAppServiceTest: WebAppTestBase + private readonly BasicAuthOptions _basicAuthOptions; + private readonly IPeerPool _peerPool; + private readonly IReconnectionService _reconnectionService; + + public NetAppServiceTest(ITestOutputHelper outputHelper) : base(outputHelper) { - private readonly IPeerPool _peerPool; - private readonly IReconnectionService _reconnectionService; - private readonly BasicAuthOptions _basicAuthOptions; + _peerPool = GetRequiredService(); + _reconnectionService = GetRequiredService(); + _basicAuthOptions = GetRequiredService>().CurrentValue; + } - public NetAppServiceTest(ITestOutputHelper outputHelper) : base(outputHelper) + private IPeer BuildPeer(string ipAddress, string pubkey, Timestamp connectionTime, bool isInbound) + { + var connectionInfo = new PeerConnectionInfo { - _peerPool = GetRequiredService(); - _reconnectionService = GetRequiredService(); - _basicAuthOptions = GetRequiredService>().CurrentValue; - } - - private IPeer BuildPeer(string ipAddress, string pubkey, Timestamp connectionTime, bool isInbound) + Pubkey = pubkey, + ProtocolVersion = KernelConstants.ProtocolVersion, + ConnectionTime = connectionTime, + IsInbound = isInbound + }; + + var peerMock = new Mock(); + peerMock.SetupGet(p => p.Info).Returns(connectionInfo); + + AElfPeerEndpointHelper.TryParse(ipAddress, out var ip); + + peerMock.SetupGet(p => p.RemoteEndpoint).Returns(ip); + peerMock.Setup(p => p.GetRequestMetrics()).Returns(new Dictionary> + { { "test", new List { new() } } }); + + return peerMock.Object; + } + + [Fact] + public async Task AddPeer_Test() + { + var parameters = new Dictionary { - var connectionInfo = new PeerConnectionInfo - { - Pubkey = pubkey, - ProtocolVersion = KernelConstants.ProtocolVersion, - ConnectionTime = connectionTime, - IsInbound = isInbound - }; - - var peerMock = new Mock(); - peerMock.SetupGet(p => p.Info).Returns(connectionInfo); - - AElfPeerEndpointHelper.TryParse(ipAddress, out var ip); - - peerMock.SetupGet(p => p.RemoteEndpoint).Returns(ip); - peerMock.Setup(p => p.GetRequestMetrics()).Returns(new Dictionary> - {{"test", new List {new RequestMetric()}}}); - - return peerMock.Object; - } - - [Fact] - public async Task AddPeer_Test() - { - var parameters = new Dictionary - { - { "address","127.0.0.1:1680"} - }; - - //failed - await PostResponseAsStringAsync("/api/net/peer", parameters, basicAuth: new BasicAuth - { - UserName = BasicAuth.DefaultUserName, - Password = "123" - }, expectedStatusCode: HttpStatusCode.Unauthorized); + { "address", "127.0.0.1:1680" } + }; - _basicAuthOptions.Password = string.Empty; - _basicAuthOptions.UserName = string.Empty; - - await PostResponseAsync("/api/net/peer", parameters, basicAuth: new BasicAuth - { - Password = _basicAuthOptions.Password, - UserName = _basicAuthOptions.UserName - },expectedStatusCode: HttpStatusCode.Unauthorized, reason: "User name and password for basic auth should be set"); - - _basicAuthOptions.Password = BasicAuth.Default.Password; - _basicAuthOptions.UserName = BasicAuth.Default.UserName; - - //success - var response = - await PostResponseAsObjectAsync("/api/net/peer", parameters, basicAuth: BasicAuth.Default); - response.ShouldBeFalse(); - - - } - - [Fact] - public async Task RemovePeer_CancelsReconnection_EvenIfPeerNotInPool() + //failed + await PostResponseAsStringAsync("/api/net/peer", parameters, basicAuth: new BasicAuth { - _reconnectionService.SchedulePeerForReconnection("127.0.0.1:3000"); - await DeleteResponseAsStringAsync($"/api/net/peer?address=127.0.0.1:3000", basicAuth: new BasicAuth + UserName = BasicAuth.DefaultUserName, + Password = "123" + }, expectedStatusCode: HttpStatusCode.Unauthorized); + + _basicAuthOptions.Password = string.Empty; + _basicAuthOptions.UserName = string.Empty; + + await PostResponseAsync("/api/net/peer", parameters, basicAuth: new BasicAuth { - UserName = BasicAuth.DefaultUserName, - Password = "123" - }, expectedStatusCode: HttpStatusCode.Unauthorized); - - _basicAuthOptions.Password = string.Empty; - _basicAuthOptions.UserName = string.Empty; - - await DeleteResponseAsync($"/api/net/peer?address=127.0.0.1:3000", basicAuth: new BasicAuth + Password = _basicAuthOptions.Password, + UserName = _basicAuthOptions.UserName + }, expectedStatusCode: HttpStatusCode.Unauthorized, + reason: "User name and password for basic auth should be set"); + + _basicAuthOptions.Password = BasicAuth.Default.Password; + _basicAuthOptions.UserName = BasicAuth.Default.UserName; + + //success + var response = + await PostResponseAsObjectAsync("/api/net/peer", parameters, basicAuth: BasicAuth.Default); + response.ShouldBeFalse(); + } + + [Fact] + public async Task RemovePeer_CancelsReconnection_EvenIfPeerNotInPool() + { + _reconnectionService.SchedulePeerForReconnection("127.0.0.1:3000"); + await DeleteResponseAsStringAsync("/api/net/peer?address=127.0.0.1:3000", basicAuth: new BasicAuth + { + UserName = BasicAuth.DefaultUserName, + Password = "123" + }, expectedStatusCode: HttpStatusCode.Unauthorized); + + _basicAuthOptions.Password = string.Empty; + _basicAuthOptions.UserName = string.Empty; + + await DeleteResponseAsync("/api/net/peer?address=127.0.0.1:3000", basicAuth: new BasicAuth { UserName = BasicAuth.DefaultUserName, Password = "123" - }, expectedStatusCode: HttpStatusCode.Unauthorized, reason: "User name and password for basic auth should be set"); - - _basicAuthOptions.Password = BasicAuth.Default.Password; - _basicAuthOptions.UserName = BasicAuth.Default.UserName; - - await DeleteResponseAsObjectAsync($"/api/net/peer?address=127.0.0.1:3000", + }, expectedStatusCode: HttpStatusCode.Unauthorized, + reason: "User name and password for basic auth should be set"); + + _basicAuthOptions.Password = BasicAuth.Default.Password; + _basicAuthOptions.UserName = BasicAuth.Default.UserName; + + await DeleteResponseAsObjectAsync("/api/net/peer?address=127.0.0.1:3000", + basicAuth: BasicAuth.Default); + _reconnectionService.GetPeersReadyForReconnection(null).ShouldBeEmpty(); + } + + [Fact] + public async Task GetPeers_Test() + { + var connectionTime = TimestampHelper.GetUtcNow(); + var ipAddressOne = "192.168.1.1:1680"; + var onePubkey = + "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; + + var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); + _peerPool.TryAddPeer(peerOne); + + var ipAddressTwo = "192.168.1.2:1680"; + var twoPubkey = + "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; + + var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); + _peerPool.TryAddPeer(peerTwo); + + var peers = await GetResponseAsObjectAsync>("api/net/peers"); + + peers.Count.ShouldBe(2); + + peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressOne, ipAddressTwo)); + peers.ShouldContain(peer => peer.ProtocolVersion == KernelConstants.ProtocolVersion); + peers.ShouldContain(peer => peer.ConnectionTime == connectionTime.Seconds); + peers.ShouldContain(peer => peer.Inbound); + peers.ShouldContain(peer => peer.Inbound == false); + peers.ShouldAllBe(peer => peer.RequestMetrics.Count == 0); + } + + [Fact] + public async Task GetPeers_WithMetrics_Test() + { + var connectionTime = TimestampHelper.GetUtcNow(); + var ipAddressOne = "192.168.1.1:1680"; + var onePubkey = + "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; + + var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); + _peerPool.TryAddPeer(peerOne); + + var peers = await GetResponseAsObjectAsync>("api/net/peers?withMetrics=true"); + + peers.Count.ShouldBe(1); + + peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressOne)); + peers.ShouldContain(peer => peer.ProtocolVersion == KernelConstants.ProtocolVersion); + peers.ShouldContain(peer => peer.ConnectionTime == connectionTime.Seconds); + peers.ShouldContain(peer => peer.Inbound); + peers.ShouldAllBe(peer => peer.RequestMetrics.Count == 1); + } + + [Fact] + public async Task RemovePeer_Test() + { + var connectionTime = TimestampHelper.GetUtcNow(); + var ipAddressOne = "192.168.1.1:1680"; + var onePubkey = + "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; + + var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); + _peerPool.TryAddPeer(peerOne); + + var ipAddressTwo = "192.168.1.2:1680"; + var twoPubkey = + "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; + + var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); + _peerPool.TryAddPeer(peerTwo); + + var response = + await DeleteResponseAsObjectAsync($"/api/net/peer?address={ipAddressOne}", basicAuth: BasicAuth.Default); - _reconnectionService.GetPeersReadyForReconnection(null).ShouldBeEmpty(); - } + response.ShouldBeTrue(); - [Fact] - public async Task GetPeers_Test() - { - var connectionTime = TimestampHelper.GetUtcNow(); - var ipAddressOne = "192.168.1.1:1680"; - var onePubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; - - var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); - _peerPool.TryAddPeer(peerOne); - - var ipAddressTwo = "192.168.1.2:1680"; - var twoPubkey = "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; - - var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); - _peerPool.TryAddPeer(peerTwo); - - var peers = await GetResponseAsObjectAsync>("api/net/peers"); - - peers.Count.ShouldBe(2); - - peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressOne, ipAddressTwo)); - peers.ShouldContain(peer => peer.ProtocolVersion == KernelConstants.ProtocolVersion); - peers.ShouldContain(peer => peer.ConnectionTime == connectionTime.Seconds); - peers.ShouldContain(peer => peer.Inbound); - peers.ShouldContain(peer => peer.Inbound == false); - peers.ShouldAllBe(peer => peer.RequestMetrics.Count == 0); - } - - [Fact] - public async Task GetPeers_WithMetrics_Test() - { - var connectionTime = TimestampHelper.GetUtcNow(); - var ipAddressOne = "192.168.1.1:1680"; - var onePubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; - - var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); - _peerPool.TryAddPeer(peerOne); - - var peers = await GetResponseAsObjectAsync>("api/net/peers?withMetrics=true"); - - peers.Count.ShouldBe(1); - - peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressOne)); - peers.ShouldContain(peer => peer.ProtocolVersion == KernelConstants.ProtocolVersion); - peers.ShouldContain(peer => peer.ConnectionTime == connectionTime.Seconds); - peers.ShouldContain(peer => peer.Inbound); - peers.ShouldAllBe(peer => peer.RequestMetrics.Count == 1); - } - - [Fact] - public async Task RemovePeer_Test() - { - var connectionTime = TimestampHelper.GetUtcNow(); - var ipAddressOne = "192.168.1.1:1680"; - var onePubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; - - var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); - _peerPool.TryAddPeer(peerOne); - - var ipAddressTwo = "192.168.1.2:1680"; - var twoPubkey = "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; - - var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); - _peerPool.TryAddPeer(peerTwo); - - var response = await DeleteResponseAsObjectAsync($"/api/net/peer?address={ipAddressOne}", basicAuth:BasicAuth.Default); - response.ShouldBeTrue(); - - var peers = await GetResponseAsObjectAsync>("/api/net/peers"); - peers.Count.ShouldBe(1); - peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressTwo)); - } - - [Fact] - public async Task GetNetWorkInfo_Test() - { - var connectionTime = TimestampHelper.GetUtcNow(); - var ipAddressOne = "192.168.1.1:1680"; - var onePubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; - - var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); - _peerPool.TryAddPeer(peerOne); - - var ipAddressTwo = "192.168.1.2:1680"; - var twoPubkey = "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; - - var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); - _peerPool.TryAddPeer(peerTwo); - - var peers = await GetResponseAsObjectAsync>("api/net/peers"); - - var networkInfo = await GetResponseAsObjectAsync("/api/net/networkInfo"); - networkInfo.Version.ShouldBe(typeof(NetApplicationWebAppAElfModule).Assembly.GetName().Version.ToString()); - networkInfo.ProtocolVersion.ShouldBe(KernelConstants.ProtocolVersion); - networkInfo.Connections.ShouldBe(peers.Count); - } + var peers = await GetResponseAsObjectAsync>("/api/net/peers"); + peers.Count.ShouldBe(1); + peers.ShouldContain(peer => peer.IpAddress.IsIn(ipAddressTwo)); + } + + [Fact] + public async Task GetNetWorkInfo_Test() + { + var connectionTime = TimestampHelper.GetUtcNow(); + var ipAddressOne = "192.168.1.1:1680"; + var onePubkey = + "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; + + var peerOne = BuildPeer(ipAddressOne, onePubkey, connectionTime, true); + _peerPool.TryAddPeer(peerOne); + + var ipAddressTwo = "192.168.1.2:1680"; + var twoPubkey = + "040a7bf44d2c79fe5e270943773783a24eed5cda3e71fa49470cdba394a23832d5c831e233cddebea2720c194dffadd656d4dedf84643818ca77edeee17ad4307a"; + + var peerTwo = BuildPeer(ipAddressTwo, twoPubkey, connectionTime, false); + _peerPool.TryAddPeer(peerTwo); + + var peers = await GetResponseAsObjectAsync>("api/net/peers"); + + var networkInfo = await GetResponseAsObjectAsync("/api/net/networkInfo"); + networkInfo.Version.ShouldBe(typeof(NetApplicationWebAppAElfModule).Assembly.GetName().Version.ToString()); + networkInfo.ProtocolVersion.ShouldBe(KernelConstants.ProtocolVersion); + networkInfo.Connections.ShouldBe(peers.Count); } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.TestBase/AElf.WebApp.Application.TestBase.csproj b/test/AElf.WebApp.Application.TestBase/AElf.WebApp.Application.TestBase.csproj index ac1eca388b..3a94a7fe32 100644 --- a/test/AElf.WebApp.Application.TestBase/AElf.WebApp.Application.TestBase.csproj +++ b/test/AElf.WebApp.Application.TestBase/AElf.WebApp.Application.TestBase.csproj @@ -5,16 +5,16 @@ false - - - - - - + + + + + + - - + + diff --git a/test/AElf.WebApp.Application.TestBase/WebAppErrorResponse.cs b/test/AElf.WebApp.Application.TestBase/WebAppErrorResponse.cs index 5dc1d7a658..bbee1524c0 100644 --- a/test/AElf.WebApp.Application.TestBase/WebAppErrorResponse.cs +++ b/test/AElf.WebApp.Application.TestBase/WebAppErrorResponse.cs @@ -1,27 +1,26 @@ using System.Collections.Generic; -namespace AElf.WebApp.Application +namespace AElf.WebApp.Application; + +public class WebAppErrorResponse +{ + public WebAppResponseError Error { get; set; } +} + +public class WebAppResponseError { - public class WebAppErrorResponse - { - public WebAppResponseError Error { get; set; } - } - - public class WebAppResponseError - { - public string Code { get; set; } - - public string Message { get; set; } - - public string Details { get; set; } - - public List ValidationErrors { get; set; } - } - - public class ValidationError - { - public string Message { get; set; } - - public List Members { get; set; } - } + public string Code { get; set; } + + public string Message { get; set; } + + public string Details { get; set; } + + public List ValidationErrors { get; set; } +} + +public class ValidationError +{ + public string Message { get; set; } + + public List Members { get; set; } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.TestBase/WebAppTestAElfModule.cs b/test/AElf.WebApp.Application.TestBase/WebAppTestAElfModule.cs index 5084eea5d5..c2d6783b8f 100644 --- a/test/AElf.WebApp.Application.TestBase/WebAppTestAElfModule.cs +++ b/test/AElf.WebApp.Application.TestBase/WebAppTestAElfModule.cs @@ -4,16 +4,12 @@ using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.FeeCalculation; -using AElf.Kernel.FeeCalculation.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.ExecutionPluginForMethodFee; -using AElf.Kernel.TransactionPool.Application; -using AElf.Kernel.Txn.Application; using AElf.Modularity; using AElf.OS; using AElf.OS.Network.Application; using AElf.OS.Network.Infrastructure; -using AElf.Sdk.CSharp; using AElf.WebApp.Web; using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; @@ -23,75 +19,74 @@ using Volo.Abp.Autofac; using Volo.Abp.Modularity; -namespace AElf.WebApp.Application +namespace AElf.WebApp.Application; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpAspNetCoreTestBaseModule), + typeof(WebWebAppAElfModule), + typeof(OSCoreWithChainTestAElfModule), + typeof(FeeCalculationModule) +)] +public class WebAppTestAElfModule : AElfModule { - [DependsOn( - typeof(AbpAutofacModule), - typeof(AbpAspNetCoreTestBaseModule), - typeof(WebWebAppAElfModule), - typeof(OSCoreWithChainTestAElfModule), - typeof(FeeCalculationModule) - )] - public class WebAppTestAElfModule : AElfModule + public override void ConfigureServices(ServiceConfigurationContext context) { - public override void ConfigureServices(ServiceConfigurationContext context) + context.Services.Replace(ServiceDescriptor.Singleton()); + + context.Services.Replace(ServiceDescriptor.Singleton(o => { - context.Services.Replace(ServiceDescriptor.Singleton()); - - context.Services.Replace(ServiceDescriptor.Singleton(o => - { - var pool = o.GetService(); - var serverMock = new Mock(); - - serverMock.Setup(p => p.DisconnectAsync(It.IsAny(), It.IsAny())) - .Returns(Task.CompletedTask) - .Callback((peer, disc) => pool.RemovePeer(peer.Info.Pubkey)); - - return serverMock.Object; - })); + var pool = o.GetService(); + var serverMock = new Mock(); + + serverMock.Setup(p => p.DisconnectAsync(It.IsAny(), It.IsAny())) + .Returns(Task.CompletedTask) + .Callback((peer, disc) => pool.RemovePeer(peer.Info.Pubkey)); + + return serverMock.Object; + })); - context.Services.AddSingleton(provider => - { - var mockService = new Mock(); - mockService.Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny(), It.IsAny())) - .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation + context.Services.AddSingleton(provider => + { + var mockService = new Mock(); + mockService.Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny(), It.IsAny())) + .Returns(ByteString.CopyFrom(new AElfConsensusHeaderInformation + { + Behaviour = AElfConsensusBehaviour.NextRound, + Round = new Round { - Behaviour = AElfConsensusBehaviour.NextRound, - Round = new Round + RoundNumber = 12, + TermNumber = 1, + BlockchainAge = 3, + ExtraBlockProducerOfPreviousRound = "bp2-pubkey", + MainChainMinersRoundNumber = 3, + RealTimeMinersInformation = { - RoundNumber = 12, - TermNumber = 1, - BlockchainAge = 3, - ExtraBlockProducerOfPreviousRound = "bp2-pubkey", - MainChainMinersRoundNumber = 3, - RealTimeMinersInformation = { + "bp1-pubkey", new MinerInRound { - "bp1-pubkey", new MinerInRound - { - Order = 2, - ProducedBlocks = 3, - ExpectedMiningTime = TimestampHelper.GetUtcNow().AddSeconds(3), - ActualMiningTimes = { }, - MissedTimeSlots = 1 - } + Order = 2, + ProducedBlocks = 3, + ExpectedMiningTime = TimestampHelper.GetUtcNow().AddSeconds(3), + MissedTimeSlots = 1 } } - }, - SenderPubkey = ByteString.CopyFromUtf8("pubkey") - }.ToByteArray())); + } + }, + SenderPubkey = ByteString.CopyFromUtf8("pubkey") + }.ToByteArray())); + + return mockService.Object; + }); - return mockService.Object; - }); - - context.Services.AddSingleton(); - context.Services.AddTransient(); - context.Services.Replace(ServiceDescriptor.Singleton()); - Configure(options => - { - options.UserName = BasicAuth.DefaultUserName; - options.Password = BasicAuth.DefaultPassword; - }); - } + context.Services.AddSingleton(); + context.Services.AddTransient(); + context.Services.Replace(ServiceDescriptor + .Singleton()); + Configure(options => + { + options.UserName = BasicAuth.DefaultUserName; + options.Password = BasicAuth.DefaultPassword; + }); } } \ No newline at end of file diff --git a/test/AElf.WebApp.Application.TestBase/WebAppTestBase.cs b/test/AElf.WebApp.Application.TestBase/WebAppTestBase.cs index 183048ce50..89fb471ec6 100644 --- a/test/AElf.WebApp.Application.TestBase/WebAppTestBase.cs +++ b/test/AElf.WebApp.Application.TestBase/WebAppTestBase.cs @@ -18,13 +18,13 @@ namespace AElf.WebApp.Application; public class WebAppTestBase : AbpAspNetCoreIntegratedTestBase, ITestOutputHelperAccessor { - public ITestOutputHelper OutputHelper { get; set; } - public WebAppTestBase(ITestOutputHelper outputHelper) { OutputHelper = outputHelper; } + public ITestOutputHelper OutputHelper { get; set; } + protected override IHostBuilder CreateHostBuilder() { return base.CreateHostBuilder() @@ -150,7 +150,7 @@ public class BasicAuth public static string DefaultPassword = "password"; - public static readonly BasicAuth Default = new BasicAuth + public static readonly BasicAuth Default = new() { UserName = DefaultUserName, Password = DefaultPassword diff --git a/test/AElf.WebApp.Application.TestBase/WebAppTestStartup.cs b/test/AElf.WebApp.Application.TestBase/WebAppTestStartup.cs index a42d6c68a0..9b9a2f4e15 100644 --- a/test/AElf.WebApp.Application.TestBase/WebAppTestStartup.cs +++ b/test/AElf.WebApp.Application.TestBase/WebAppTestStartup.cs @@ -1,31 +1,27 @@ -using AElf.Kernel.SmartContract; -using Microsoft.AspNetCore.Builder; using AElf.Kernel.TransactionPool.Infrastructure; using AElf.OS; using AElf.WebApp.Application.Chain; -using AElf.WebApp.Web; -using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; -namespace AElf.WebApp.Application +namespace AElf.WebApp.Application; + +public class WebAppTestStartup { - public class WebAppTestStartup + public void ConfigureServices(IServiceCollection services) { - public void ConfigureServices(IServiceCollection services) - { - services.AddSingleton(); - services.AddApplication(); - services.Configure(options => { options.TransactionResultStatusCacheSeconds = 2; }); - } + services.AddSingleton(); + services.AddApplication(); + services.Configure(options => { options.TransactionResultStatusCacheSeconds = 2; }); + } - public void Configure(IApplicationBuilder app) - { - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - app.InitializeApplication(); - app.UseCors(builder => - builder.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod()); - } + public void Configure(IApplicationBuilder app) + { + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.InitializeApplication(); + app.UseCors(builder => + builder.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod()); } } \ No newline at end of file